2017-03-25 2 views
1

J'écris actuellement l'analyseur pour un compilateur d'un langage de jouets en utilisant Happy & Alex. Depuis une certaine forme de mise en page en option est nécessaire, je dois changer l'état d'Alex avant de correspondre à la block non-terminal. Malheureusement il semble que le jeton lookahead requis par Happy est lu avant J'ai la chance de changer l'état d'Alex.Happy & Alex - Empêcher le lookahead d'affecter communication parser-lexer

Voici un petit extrait montrant le problème:

funcDef : header localDefs block 
         ^I have to change alex's state 
          before the underlying lexer 
          starts reading the block tokens. 

Y at-il une approche commune à ce problème?

+0

Comment savez-vous où commence un bloc? Je suppose que 'localDefs' n'est pas auto-terminé, donc il doit y avoir une fonctionnalité lexicale que vous pouvez utiliser pour savoir où le bloc commence. Pourriez-vous peut-être élucider un peu? – rici

+0

@rici Le bloc est entouré de mots-clés begin/end ou est basé sur l'indentation. Il est fondamentalement défini comme begin stmts + end ou stmts autoend. Le lexeur doit être averti qu'un begin est manquant afin de produire un autoend lorsqu'il détecte un changement d'identité. Toute l'approche semble très hacky il doit y avoir un meilleur moyen. –

+0

Je viens de résoudre ce problème _exact_ il y a deux semaines. Je ne pensais pas que quelqu'un d'autre allait le traverser. – Alec

Répondre

0

Je suppose que vous utilisez une lexeur à thread (si Happy et Alex fonctionnent dans la même monade). Le truc que j'ai utilisé face à un problème similaire est de faire une règle de production vide que vous glissez dans votre règle.

changeAlexState :: {() } 
    : {- empty -} {%% \tok -> changeAlexState *> pushTok tok } 

funcDef : header localDefs changeAlexState block 

Ensuite, vous devez ajouter à votre monade un état pour soutenir pushTok :: Token -> P() (où P est votre monade lexing/analyse syntaxique) et assurez-vous toujours pop quand ce jeton lorsque vous êtes lexing. Qu'est-ce que %% est documented here.

n : t_1 ... t_n {%% <expr> }

... Le type de <expr> est le même [encore Token -> P a], mais dans ce cas, le jeton est en fait préanalyse mis au rebut et un nouveau jeton est lu à partir de l'entrée. Cela peut être utile lorsque vous voulez changer le jeton suivant et continuer l'analyse.

J'ai mentionné que j'ai fait quelque chose de similaire il n'y a pas longtemps. Here is my "empty" rule, here is an example use of it, here is where my pushing function is defined et here is where I "pop" tokens. Faites-moi savoir comment ça se passe!