19

私は C-- (実際の C-- 言語ではありません) と呼ばれる架空のプログラミング言語用のパーサーを構築しています。私は、言語の文法を Pyparsing が受け入れられるものに翻訳する必要がある段階に達しました。残念ながら、入力文字列を解析しようとすると (これは正しく、Pyparsing でエラーが発生することはありません)、正しく解析されません。これは私の文法の誤りによるのではないかと心配していますが、初めて Pyparsing を始めたので、どこが間違っているのかわかりません。

ここから翻訳している文法をアップロードして、人々が読んでもらうようにしました.

編集:ポールからのアドバイスで更新されました。

これは私が現在持っている文法です (Syntax 定義の上部の 2 行は、私が知っている私にはひどく悪いです):

# Lexical structure definition
ifS = Keyword('if')
elseS = Keyword('else')
whileS = Keyword('while')
returnS = Keyword('return')
intVar = Keyword('int')
voidKeyword = Keyword('void')
sumdiff = Literal('+') | Literal('-')
prodquot = Literal('*') | Literal('/')
relation = Literal('<=') | Literal('<') | Literal('==') | \
           Literal('!=') | Literal('>') | Literal('=>')
lbrace = Literal('{')
rbrace = Literal('}')
lparn = Literal('(')
rparn = Literal(')')
semi = Literal(';')
comma = Literal(',')
number = Word(nums)
identifier = Word(alphas, alphanums)

# Syntax definition
term = ''
statement = ''
variable    =   intVar + identifier + semi
locals      =   ZeroOrMore(variable)
expr        =   term | OneOrMore(Group(sumdiff + term))
args        =   ZeroOrMore(OneOrMore(Group(expr + comma)) | expr)
funccall    =   Group(identifier + lparn + args + rparn)
factor      =   Group(lparn + expr + rparn) | identifier | funccall | number
term        =   factor | OneOrMore(prodquot + factor)
cond        =   Group(lparn + expr + relation + expr + rparn)
returnState =   Group(returnS + semi) | Combine(returnS + expr + semi)
assignment  =   Group(identifier + '=' + expr + semi)
proccall    =   Group(identifier + lparn + args + rparn + semi)
block       =   Group(lbrace + locals + statement + rbrace)
iteration   =   Group(whileS + cond + block)
selection   =   Group(ifS + cond + block) | Group(ifS + cond + block + elseS + block)
statement   =   OneOrMore(proccall | assignment | selection | iteration | returnState)
param       =   Group(intVar + identifier)
paramlist   =   OneOrMore(Combine(param + comma)) | param
params      =   paramlist | voidKeyword
procedure   =   Group(voidKeyword + identifier + lparn + params + rparn + block)
function    =   Group(intVar + identifier + lparn + params + rparn + block)
declaration =   variable | function | procedure
program     =   OneOrMore(declaration)

文法を翻訳する際に間違いを犯したかどうか、および与えられた文法に準拠しながら単純化するために何ができるかを知りたい.

編集 2:新しいエラーを含めるように更新されました。

解析している入力文字列は次のとおりです。

int larger ( int first , int second ) { 
if ( first > second ) { 
return first ; 
} else { 
return second ; 
} 
} 

void main ( void ) { 
int count ; 
int sum ; 
int max ; 
int x ; 

x = input ( ) ; 
max = x ; 
sum = 0 ; 
count = 0 ; 

while ( x != 0 ) { 
count = count + 1 ; 
sum = sum + x ; 
max = larger ( max , x ) ; 
x = input ( ) ; 
} 

output ( count ) ; 
output ( sum ) ; 
output ( max ) ; 
} 

これは、ターミナルからプログラムを実行したときに表示されるエラー メッセージです。

/Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1156: SyntaxWarning: null string passed to Literal; use Empty() instead
other = Literal( other )
/Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1258: SyntaxWarning: null string passed to Literal; use Empty() instead
other = Literal( other )
Expected ")" (at char 30), (line:6, col:26)
None
4

1 に答える 1

33

1)に(以下同様に) を変更Literal("if")して、 という名前の変数の先頭の「if」が一致しないようにします。Keyword("if")Literal("void")"ifactor"

2) numsalphas、およびalphanumsは式ではなく、文字列であり、Word クラスで使用して、「数値は数値で構成される単語である」、または「識別子」などの「単語」を定義するときに、いくつかの典型的な文字セットを定義できます。は英字で始まり、その後に 0 個以上の英数字が続く単語です。」したがって、代わりに:

number = nums
identifier = alphas + OneOrMore(alphanums)

あなたが欲しい

number = Word(nums)
identifier = Word(alphas, alphanums)

3) の代わりにCombine、あなたが欲しいと思いますGroupCombine一致したトークンを間に空白を入れずに連続させたい場合に 使用し、トークンを連結して単一の文字列として返します。Combine次のような場合によく使用されます。

realnum = Combine(Word(nums) + "." + Word(nums))

がないCombineと、解析"3.14"によって文字列のリストが返されるため、 realnum の解析結果が になる['3', '.', '14']ように追加します (これを解析アクションに渡して、実際の浮動小数点値に変換できます)。 介在する空白がないという s の強制により、誤って解析して が実数を表していると考えることがなくなります。Combine'3.14'3.14Combine'The answer is 3. 10 is too much.'"3. 10"

4) これでエラーが発生することはありませんが、入力文字列に余分なスペースがたくさんあります。"int x;"文法が機能するようになれば、と同様に解析できるはずです"int x ;"

これらのヒントのいくつかがあなたを前進させることを願っています. オンラインの pyparsing の記事やチュートリアルを読んだことがありますか? そして、オンラインの例を見てください。WordLiteralCombineなどが個々の解析タスクをどのように実行するかをよく理解する必要があります。

5) term と statement の再帰的な定義を誤って実装しました。それらに割り当てる代わりに、次の''ように記述します。

term = Forward()
statement = Forward()

次に、再帰的な定義でそれらを実際に定義するときは、演算子を使用します (RHS を's<<で囲むようにしてください)。()

term << (... term definition ...)
statement << (... statement definition ...)

再帰パーサーの例はここにあり、基本的な pyparsing の使用法に関するプレゼンテーションはここにあります。再帰の処理方法の詳細については、「リストの解析」というタイトルのセクションを参照してください。

于 2009-12-01T01:55:18.137 に答える