next up previous contents
Next: Application : Grammaires catégorielles Up: Analyseur ascendant dépendant du Previous: Analyse

Sources de l'analyseur

/*
 * 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(_ := _).



Christophe Delord
1998-09-02