12

pyparsing次の形式で関数呼び出しを解析するために使用しようとしています。

f(x, y)

簡単だ。ただし、再帰下降パーサーであるため、解析も簡単です。

f(g(x), y)

それは私が得ることができないものです。要約した例を次に示します。

from pyparsing import Forward, Word, alphas, alphanums, nums, ZeroOrMore, Literal

lparen = Literal("(")
rparen = Literal(")")

identifier = Word(alphas, alphanums + "_")
integer  = Word( nums )

functor = identifier

# allow expression to be used recursively
expression = Forward()

arg = identifier | integer | expression
args = arg + ZeroOrMore("," + arg)

expression << functor + lparen + args + rparen

print expression.parseString("f(x, y)")
print expression.parseString("f(g(x), y)")

そして、これが出力です:

['f', '(', 'x', ',', 'y', ')']
Traceback (most recent call last):
  File "tmp.py", line 14, in <module>
    print expression.parseString("f(g(x), y)")
  File "/usr/local/lib/python2.6/dist-packages/pyparsing-1.5.6-py2.6.egg/pyparsing.py", line 1032, in parseString
    raise exc
pyparsing.ParseException: Expected ")" (at char 3), (line:1, col:4)

パーサーが内部式のファンクターをスタンドアロンの識別子として解釈するのはなぜですか?

4

3 に答える 3

14

の定義でそれがマスキングされていたことidentifierがわかりました。パーサーに関するその他のヒントは次のとおりです。expressionarg

x + ZeroOrMore(',' + x)はpyparsingパーサーで非常に一般的なパターンであるため、pyparsingには、delimitedListその式を。に置き換えることができるヘルパーメソッドが含まれていますdelimitedList(x)。実際にdelimitedListは、もう1つのことを行います。区切り文字は解析時に役立つという概念に基づいて、区切りコンマ(またはオプションの引数を使用して指定されている場合は他の区切り文字delim)を抑制しますが、解析されたデータをふるいにかけるときは単なる雑然としたトークンです。その後。したがって、argsをとして書き直すことができargs = delimitedList(arg)、リスト内のargsのみを取得し、「ステップオーバー」する必要のあるコンマはありません。

このGroupクラスを使用して、解析されたトークンに実際の構造を作成できます。これにより、このリストをたどって'('および')'を探してネスト階層を構築し、関数のネストでレベルが下がったことを通知します。

 arg = Group(expression) | identifier | integer
 expression << functor + Group(lparen + args + rparen)

argsがGroup編集されているので、parensをさらに抑制することができます。これは、区切りコンマのように、構文解析中にそれらの役割を果たしますが、トークンをグループ化することで、それらは不要になります。

lparen = Literal("(").suppress()
rparen = Literal(")").suppress()

'h()'は有効な関数呼び出しであり、引数はないと思います。Optional:を使用して、引数をオプションにすることができます。

expression << functor + Group(lparen + Optional(args) + rparen)

これで、「f(g(x)、y、h())」を解析できます。

pyparsingへようこそ!

于 2012-04-17T09:19:46.323 に答える
4

の定義はarg、左側の別の項目で始まる項目に配置する必要があるため、優先的に一致します。

arg = expression | identifier | integer
于 2012-04-16T05:28:11.097 に答える
1

ポールの答えは大いに役立ちました。後世のために、同じものを使用して、次のように定義できfor loopsます(ここでは、構造を示すために簡略化された疑似パーサー)。

from pyparsing import (
    Forward, Group, Keyword, Literal, OneOrMore)

sep = Literal(';')
if_ = Keyword('if')
then_ = Keyword('then')
elif_ = Keyword('elif')
end_ = Keyword('end')

if_block = Forward()
do_block = Forward()

stmt = other | if_block
stmts = OneOrMore(stmt + sep)

case = Group(guard + then_ + stmts)
cases = case + OneOrMore(elif_ + case)

if_block << if_ + cases + end_
于 2013-07-24T22:06:32.597 に答える