Frage

Ich baue einen Parser für eine imaginäre Programmiersprache C-- (nicht die tatsächliche C-- Sprache) genannt. Ich habe auf die Bühne gekommen, wo ich die Sprache der Grammatik in etwas Pyparsing akzeptieren zu übersetzen. Leider, wenn ich komme meinen Eingabestring zu analysieren (was richtig ist, und soll nicht dazu führen, Pyparsing Fehler und Irrtum), es ist nicht richtig Parsen. Ich fürchte, dies zu Fehlern in meiner Grammatik zurückzuführen ist, aber wie ich Pyparsing zum ersten Mal fange, kann ich nicht scheinen, um zu sehen, wo ich falsch gehe.

Ich habe die Grammatik hochgeladen, die ich von hier bin übersetzen für die Menschen ein haben lesen durch.

EDIT:. aktualisiert mit den Ratschlägen von Paul

Dies ist der grammer ich zur Zeit habe (die beiden oberen Zeilen der Syntax-Definition sind furchtbar schlecht von mir, ich weiß):

# 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)

Ich würde gerne wissen, ob es irgendwelche Fehler, die ich in der Übersetzung der Grammatik gemacht habe über und welche Verbesserungen ich tun könnte, um es an die Grammatik zu machen vereinfacht, während die Einhaltung ich gegeben habe.

EDIT 2:. aktualisiert, um die neuen Fehler enthalten

Hier ist die Eingabezeichenfolge Ich bin Parsen:

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 ) ; 
} 

Und das ist die Fehlermeldung erhalte ich, wenn mein Programm vom Terminal ausgeführt wird:

/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
War es hilfreich?

Lösung

1) Veränderung Literal("if") Keyword("if") (und so weiter, bis hin zu Literal("void")), zu verhindern, dass die führenden "wenn" einer Variablen mit dem Namen "ifactor" entspricht.

2) nums, alphas und alphanums nicht Ausdrücke sind, sie sind Strings, die mit der Wortklasse verwendet werden können, einige typische Sätze von Zeichen zu definieren, bei der Definition von „Wörtern“ wie „eine Zahl ist ein Wort aus nums gemacht “oder‚ein Identifikator ist ein Wort, das mit einem alpha beginnt, gefolgt von null oder mehr alphanums.‘ Anstatt also:

number = nums
identifier = alphas + OneOrMore(alphanums)

Sie

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

3) Statt Combine, ich glaube, Sie Group wollen. Verwenden Sie Combine, wenn Sie die angepassten Token wollen ohne dazwischen Leerzeichen zusammenhängend zu sein, und die Token verketten und sie als einzelne Zeichenfolge zurück. Combine wird häufig in Fällen wie diesem verwendet:

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

Ohne Combine, "3.14" Parsen würde die Liste von Strings ['3', '.', '14'] zurückkehren, also fügen wir Combine, so dass das analysierte Ergebnis für realnum ist '3.14' (die Sie dann zu einer Parse-Aktion passieren könnten auf den tatsächlichen Floating Wert 3.14 zu konvertieren). Combines Durchsetzung ohne dazwischen Leerzeichen hält uns auch versehentlich 'The answer is 3. 10 is too much.' Parsen und die "3. 10" Denken eine reelle Zahl.

4) Dies sollte Ihren Fehler nicht verursachen, aber Ihre Eingabezeichenfolge hat viel von zusätzlichen Leerzeichen. Wenn Sie Ihre Grammatik Arbeits erhalten, sollten Sie in der Lage sein "int x;" zu analysieren ebenso wie "int x ;".

Hoffnung einige dieser Hinweise erhalten Sie gehen. Haben Sie irgendwelche Online pyparsing Artikel oder Tutorials lesen? Und bitte die Online-Beispiele schauen. Sie werden ein gutes Verständnis davon bekommen, müssen, wie Word, Literal, Combine usw. führen ihre einzelnen Parsing-Aufgaben.

5) Sie haben die rekursive Definitionen für Ausdruck und Aussage-mis umgesetzt. Stattdessen '' ihnen zuzuweisen, schreiben Sie:

term = Forward()
statement = Forward()

Dann, wenn Sie gehen, um tatsächlich sie mit ihren rekursiven Definitionen zu definieren, verwenden Sie den << Operator (und sicher sein, die RHS in () den einzuschließen).

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

Sie können ein Beispiel für eine rekursive Parser finden Sie hier und eine Präsentation zu dem grundlegenden pyparsing Nutzung hier - siehe Abschnitt der Titel „Parsing-Liste“ nach Schritt-für-Schritt, wie die Rekursion behandelt wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top