編集:私は最初のバージョンを作成しましたが、Eike はそれをかなり進めるのに役立ちました。私は今、より具体的な問題に固執しています。これについては、以下で説明します。履歴で元の質問を見ることができます
データベースから特定のデータを要求するために使用される小さな言語を解析するために pyparsing を使用しています。多数のキーワード、演算子、データ型、およびブール論理を備えています。
現在のメッセージはあまり役に立たないため、構文エラーが発生したときにユーザーに送信されるエラー メッセージを改善しようとしています。前述の言語で行っていることと似ていますが、はるかに小さい小さな例を設計しました。
#!/usr/bin/env python
from pyparsing import *
def validate_number(s, loc, tokens):
if int(tokens[0]) != 0:
raise ParseFatalException(s, loc, "number musth be 0")
def fail(s, loc, tokens):
raise ParseFatalException(s, loc, "Unknown token %s" % tokens[0])
def fail_value(s, loc, expr, err):
raise ParseFatalException(s, loc, "Wrong value")
number = Word(nums).setParseAction(validate_number).setFailAction(fail_value)
operator = Literal("=")
error = Word(alphas).setParseAction(fail)
rules = MatchFirst([
Literal('x') + operator + number,
])
rules = operatorPrecedence(rules | error , [
(Literal("and"), 2, opAssoc.RIGHT),
])
def try_parse(expression):
try:
rules.parseString(expression, parseAll=True)
except Exception as e:
msg = str(e)
print("%s: %s" % (msg, expression))
print(" " * (len("%s: " % msg) + (e.loc)) + "^^^")
基本的に、この言語でできることは、一連の を書くことだけx = 0
ですand
。
現在、and
と 括弧が使用されている場合、エラー報告があまり良くない場合があります。次の例を検討してください。
>>> try_parse("x = a and x = 0") # This one is actually good!
Wrong value (at char 4), (line:1, col:5): x = a and x = 0
^^^
>>> try_parse("x = 0 and x = a")
Expected end of text (at char 6), (line:1, col:1): x = 0 and x = a
^^^
>>> try_parse("x = 0 and (x = 0 and (x = 0 and (x = a)))")
Expected end of text (at char 6), (line:1, col:1): x = 0 and (x = 0 and (x = 0 and (x = a)))
^^^
>>> try_parse("x = 0 and (x = 0 and (x = 0 and (x = 0)))")
Expected end of text (at char 6), (line:1, col:1): x = 0 and (x = 0 and (x = 0 and (xxxxxxxx = 0)))
^^^
実際、パーサーが a の後の何かを解析できない場合(ここで解析することが重要です) and
、適切なエラー メッセージが生成されないようです :(
つまり、 parseを意味します。5 を解析できても、「検証」が parse アクションで失敗した場合でも、適切なエラー メッセージが生成されるからです。a
ただし、有効な数値 ( など) または有効なキーワード ( など)を解析できない場合xxxxxx
、正しいエラー メッセージの生成が停止します。
何か案が?