Domanda

Sto costruendo un parser per un linguaggio di programmazione immaginario chiamato C-- (non l'attuale linguaggio C--). Sono arrivato al punto in cui ho bisogno di tradurre la grammatica della lingua in qualcosa che Pyparsing può accettare. Sfortunatamente quando vengo ad analizzare la mia stringa di input (che è corretta e non dovrebbe causare errori in Pyparsing) non sta analizzando correttamente. Temo che ciò sia dovuto a errori nella mia grammatica, ma dato che sto iniziando Pyparsing per la prima volta, non riesco a vedere dove sto sbagliando.

Ho caricato la grammatica che sto traducendo da qui affinché le persone abbiano un leggere.

MODIFICA: aggiornato con i consigli di Paul.

Questa è la grammatica che ho attualmente (le due linee principali della definizione della sintassi sono terribilmente cattive da parte mia, lo so):

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

Vorrei sapere se ci sono errori che ho commesso nel tradurre la grammatica e quali miglioramenti potrei fare per renderla semplificata aderendo alla grammatica che mi è stata data.

MODIFICA 2: aggiornato per includere il nuovo errore.

Ecco la stringa di input che sto analizzando:

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

E questo è il messaggio di errore che ricevo quando eseguo il mio programma dal Terminale:

/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
È stato utile?

Soluzione

1) Cambia Literal("if") in Keyword("if") (e così via, fino a Literal("void")), per evitare la corrispondenza delle quotazioni & iniziali; se " di una variabile denominata "ifactor".

2) nums, alphas e alphanums non sono espressioni, sono stringhe, che possono essere utilizzate con la classe Word per definire alcuni insiemi di caratteri tipici durante la definizione di " parole quot; come " un numero è una parola formata da nums " oppure " un identificatore è una parola che inizia con un alfa, seguita da zero o più alfani. " Quindi invece di:

number = nums
identifier = alphas + OneOrMore(alphanums)

vuoi

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

3) Invece di Combine, penso che tu voglia Group. Utilizzare "3.14" quando si desidera che i token abbinati siano contigui senza spazi bianchi intermedi e si concateneranno i token e li restituiranno come una singola stringa. ['3', '.', '14'] viene spesso utilizzato in casi come questo:

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

Senza '3.14', l'analisi 3.14 restituisce l'elenco di stringhe 'The answer is 3. 10 is too much.', quindi aggiungeremo "3. 10" in modo che il risultato analizzato per realnum sia "int x;" (che è quindi possibile passare a un'azione di analisi in converti nel valore variabile reale "int x ;"). L'applicazione di Word nessuno spazio bianco intermedio ci impedisce anche di analizzare accidentalmente Literal e pensare che '' rappresenti un numero reale.

4) Questo non dovrebbe causare il tuo errore, ma la tua stringa di input ha molti di spazi extra. Se la grammatica funziona, dovresti essere in grado di analizzare << e ().

Spero che alcuni di questi suggerimenti ti facciano partire. Hai letto articoli o tutorial di pyparsing online? E guarda negli esempi online. Dovrai avere una buona conoscenza di come <=>, <=>, <=>, ecc. Eseguono le loro singole attività di analisi.

5) Hai implementato male le definizioni ricorsive per termine e dichiarazione. Invece di assegnare loro <=>, scrivi:

term = Forward()
statement = Forward()

Quindi quando vai a definirli effettivamente con le loro definizioni ricorsive, usa l'operatore <=> (e assicurati di racchiudere l'RHS tra <=>).

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

Puoi trovare un esempio di un parser ricorsivo qui e una presentazione sull'utilizzo pyparsing di base qui - consultare la sezione intitolato " Liste di analisi " per ulteriori informazioni dettagliate sulla gestione della ricorsione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top