Question

Je construis un analyseur syntaxique pour un langage de programmation imaginaire appelé C-- (et non le langage C--). J'ai atteint le stade où j'ai besoin de traduire la grammaire de la langue en quelque chose que Pyparsing peut accepter. Malheureusement, lorsque je viens d'analyser ma chaîne d'entrée (ce qui est correct et ne devrait pas causer d'erreur à Pyparsing), l'analyse n'est pas correcte. Je crains que cela ne soit dû à des erreurs de grammaire, mais lorsque je commence Pyparsing pour la première fois, je ne peux pas sembler comprendre où je me trompe.

J'ai téléchargé la grammaire que je traduis de ici pour permettre aux personnes de disposer d'un lire à travers.

MODIFIER: mis à jour avec les conseils de Paul.

C’est le grammeur que j’ai actuellement (les deux lignes principales de la définition de la syntaxe sont terriblement mauvaises pour moi, je le sais):

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

J'aimerais savoir si j'ai commis des erreurs dans la traduction de la grammaire et quelles améliorations je pourrais apporter pour la simplifier tout en respectant la grammaire qui m'a été donnée.

EDIT 2: mis à jour pour inclure la nouvelle erreur.

Voici la chaîne d'entrée que j'analyse:

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

Et voici le message d'erreur que je reçois lors de l'exécution de mon programme depuis Terminal:

/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
Était-ce utile?

La solution

1) Modifiez Literal("if") en Keyword("if") (et ainsi de suite jusqu'à Literal("void")) pour éviter de faire correspondre le & "si &"; d'une variable nommée "ifactor".

2) nums, alphas et alphanums ne sont pas des expressions, mais des chaînes, qui peuvent être utilisées avec la classe Word pour définir des jeux de caractères typiques lors de la définition de & "mots quot; comme & "; un nombre est un mot composé de" & "ou &"; un identifiant est un mot qui commence par un alpha, suivi de zéro ou plusieurs alphanums. & "; Donc au lieu de:

number = nums
identifier = alphas + OneOrMore(alphanums)

vous voulez

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

3) Au lieu de Combine, je pense que vous voulez Group. Utilisez "3.14" lorsque vous souhaitez que les jetons correspondants soient contigus, sans espaces blancs intermédiaires, puis concaténez les jetons et les renvoient sous la forme d'une chaîne unique. ['3', '.', '14'] est souvent utilisé dans les cas suivants:

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

Sans '3.14', l'analyse 3.14 renvoie la liste des chaînes 'The answer is 3. 10 is too much.', nous ajoutons donc "3. 10" de sorte que le résultat analysé pour realnum soit "int x;" (que vous pouvez ensuite transmettre à une action d'analyse à convertir en valeur flottante réelle "int x ;"). Word L’application de non espaces blancs nous empêche également d’analyser accidentellement Literal et de penser que '' représente un nombre réel.

4) Cela ne devrait pas provoquer votre erreur, mais votre chaîne d'entrée contient beaucoup d'espaces supplémentaires. Si votre grammaire fonctionne, vous devriez pouvoir analyser << aussi bien que ().

J'espère que certains de ces conseils vous permettront de continuer. Avez-vous lu des articles ou des tutoriels en ligne? Et s'il vous plaît regardez à travers les exemples en ligne. Vous devez bien comprendre comment <=>, <=>, <=>, etc. effectuer leurs tâches d'analyse individuelles.

5) Vous avez mal implémenté les définitions récursives des termes et instructions. Au lieu de leur attribuer <=>, écrivez:

term = Forward()
statement = Forward()

Ensuite, lorsque vous allez les définir avec leurs définitions récursives, utilisez l'opérateur <=> (et assurez-vous de placer le RHS entre <=>.).

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

Vous pouvez trouver un exemple d'analyseur récursif ici , et une présentation de l’utilisation de base des pyparses ici - voir la section intitulé " Analyser les listes " pour plus de détails sur la gestion de la récursivité.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top