2015-11-01 1 views
2

Lorsque vous écrivez une bonne description, vous devez définir tous les types de jetons possibles qui peuvent apparaître. Mais vous ne pouvez match contre jeton types, non jeton valeurs individuelles ...Heureux: ce n'est pas un mot-clé

C'est un peu problématique. Considérons, par exemple, le mot-clé data. Selon le rapport Haskell, ce jeton est un "reservedid". Donc mon tokeniser le reconnaît et le marque comme tel. Cependant, considérez le mot-clé as. Maintenant il s'avère que c'est pas un reservedid; c'est une varid ordinaire. Ce n'est spécial que dans un contexte. Vous pouvez déclarer totalement une variable normale nommée as, et ça va.

Donc, voici une question: Comment analyser as spécifiquement? Au début, je n'y pensais pas vraiment. Je viens de définir un nouveau type de jeton qui représente tout jeton varid dont le texte est as.

... et puis j'ai passé environ 2 heures à essayer de travailler pourquoi diable ma grammaire ne fonctionne pas réellement. Oui, il s'avère que puisque ce type de jeton chevauche un type de jeton existant, l'ordre de déclaration est significatif. (!!!) Littéralement, changer l'ordre des déclarations fait parfaitement analyser la grammaire.

Mais maintenant je suis inquiet. Je crains que as ne soit jamais apparié comme varid et ne correspondra jamais comme lui-même. Donc, toutes les règles de grammaire qui disent varid vont rejeter le as jeton — ce qui est complètement faux!

Quelle est la correcte comment résoudre ce problème?

Répondre

5

Qu'est-ce GHC fait dans son Parser.y est de définir un type de jeton non terminal special_id qui répertorie un grand nombre des non-mots-clés spéciaux comme as, puis définir les jetons tyvarid et varid (non terminal) d'inclure cela comme une option en plus du terminal VARID (et d'autres, bien que la plupart d'entre eux me ressemblent aurait été mis en special_id aussi).

Un extrait:

varid :: { Located RdrName } 
     : VARID   { sL1 $1 $! mkUnqual varName (getVARID $1) } 
     | special_id  { sL1 $1 $! mkUnqual varName (unLoc $1) } 
     | 'unsafe'   { sL1 $1 $! mkUnqual varName (fsLit "unsafe") } 
     ... 

special_id :: { Located FastString } 
special_id 
     : 'as'     { sL1 $1 (fsLit "as") } 
     | 'qualified'   { sL1 $1 (fsLit "qualified") } 
     | 'hiding'    { sL1 $1 (fsLit "hiding") } 
     | 'export'    { sL1 $1 (fsLit "export") } 
     ...