/* * Analyseur ascendant en ProLog * --------- */ :-module(parser, [ parse/2 ] ). pause:-get_single_char(0'x),break. pause. /* * Définition des règles : * tete := corps * * Actions sémantiques : * { ... } * * Token lexicaux : * appel à une règle descendante récursive (-->) * */ :-op(1200,xfx,:=). :-module_transparent parse/2, parse/3, shift/3. parse(AXIOM,SOURCE):- shift(AXIOM,SOURCE,[]). aff([A|SUITE]):- aff(SUITE), % A=..[F|_], writef(" %t |",[A]). aff([]). parse(_,_,SYMBOLS):- writef("Pile courante : "), aff(SYMBOLS), nl, pause, fail. % parse/3 : parse(AXIOM,FLOT_D_ENTREE,LISTE_DES_SYMBOLES_RECONNUS) % La liste des symboles est renversée : dernier symbole lu en tete parse(AXIOM,[],[AXIOM]).% L'axiome est reconstruit et plus rien à lire % Reduce parse(AXIOM,SOURCE,SYMBOLS):- (HEAD := BODY), % On prend une règle apply_rule_globally((HEAD := BODY),SYMBOLS,NEW_SYMBOLS), parse(AXIOM,SOURCE,NEW_SYMBOLS). % Shift parse(AXIOM,SOURCE,SYMBOLS):- shift(AXIOM,SOURCE,SYMBOLS). shift(AXIOM,SOURCE,SYMBOLS):- lex(TOKEN,SOURCE,REST), TOKEN=..[F|_], writef("Token : %t\n",[F]), ( /* On n'applique les règles qu'à la queue */ (HEAD := BODY), apply_rule((HEAD := BODY),[TOKEN|SYMBOLS],NEW_SYMBOLS), parse(AXIOM,REST,NEW_SYMBOLS) ; /* Si pas de règle applicable en queue : on continue à décaler */ shift(AXIOM,REST,[TOKEN|SYMBOLS]) ). /* OPTIMISATION : shift Après un shift, il suffit de n'appliquer les règles qu'à la fin de la liste puisqu'elles ont échouées pendant reduce Après un reduce, ce n'est pas le cas */ apply_rule_globally(RULE, SYMBOLS, NEW_SYMBOLS):- apply_rule(RULE, SYMBOLS, NEW_SYMBOLS). apply_rule_globally(RULE, [SYMBOL|SYMBOLS], [SYMBOL|NEW_SYMBOLS]):- apply_rule_globally(RULE, SYMBOLS, NEW_SYMBOLS). apply_rule((HEAD := BODY), SYMBOLS, NEW_SYMBOLS):- remove_symbols(BODY, SYMBOLS, REST), append_symbols(HEAD, REST, NEW_SYMBOLS), apply_semantics(HEAD := BODY). % writef("Regle appliquee : %t\n",[HEAD:=BODY]),pause. remove_symbols((SYMBOL,SYMBOLS), LIST, REST):- !, remove_symbols(SYMBOLS, LIST, REST1), remove_symbols(SYMBOL, REST1, REST). remove_symbols({_},LIST,LIST):-!. % actions sémantiques remove_symbols(SYMBOL, [SYMBOL|SYMBOLS], SYMBOLS). % pour enlever le dernier append_symbols([],LIST,LIST):- !. append_symbols((SYMBOL,SYMBOLS), LIST, REST):- !, append_symbols(SYMBOLS,[SYMBOL|LIST],REST). append_symbols(SYMBOL, LIST, [SYMBOL|LIST]). apply_semantics(HEAD := (ITEM, BODY)):- !, apply_semantics(HEAD := ITEM), apply_semantics(HEAD := BODY). apply_semantics(HEAD := {SEMANTIC,SEMANTICS}):- !, SEMANTIC, apply_semantics(HEAD := {SEMANTICS}). apply_semantics(_ := {SEMANTIC}):- !, SEMANTIC. apply_semantics(_ := _).