web-dev-qa-db-fra.com

Quelle est la différence entre l'analyse syntaxique LL et LR?

Quelqu'un peut-il me donner un exemple simple d'analyse syntaxique LL par rapport à l'analyse syntaxique LR?

209
Creativity2345

À un niveau élevé, la différence entre l'analyse syntaxique LL et l'analyse syntaxique LR est que les analyseurs syntaxiques LL commencent au symbole de début et tentent d'appliquer des productions pour atteindre la chaîne cible, tandis que les analyseurs syntaxiques LR commencent à la chaîne cible et tentent de revenir au début. symbole.

Une analyse LL est une dérivation de gauche à droite. C'est-à-dire que nous considérons les symboles d'entrée de gauche à droite et essayons de construire une dérivation la plus à gauche. Ceci est fait en commençant par le symbole de début et en développant de manière répétée le non-terminal le plus à gauche jusqu'à ce que nous arrivions à la chaîne cible. Une analyse LR est une dérivation de gauche à droite, la plus à droite, ce qui signifie que nous balayons de gauche à droite et essayons de construire une dérivation la plus à droite. L'analyseur sélectionne en permanence une sous-chaîne de l'entrée et tente de l'inverser en non-terminal.

Lors d'une analyse LL, l'analyseur choisit en permanence entre deux actions:

  1. Prédire : sur la base du non-terminal le plus à gauche et d'un certain nombre de jetons lookahead, choisissez la production à appliquer pour se rapprocher de la chaîne d'entrée.
  2. Correspondance : faites correspondre le symbole de terminal deviné le plus à gauche avec le symbole d'entrée non consommé le plus à gauche.

A titre d'exemple, étant donné cette grammaire:

  • S → E
  • E → T + E
  • E → T
  • T → int

Puis, étant donné la chaîne int + int + int _, un analyseur LL (2) (qui utilise deux jetons de lookahead) analysera la chaîne comme suit:

Production       Input              Action
---------------------------------------------------------
S                int + int + int    Predict S -> E
E                int + int + int    Predict E -> T + E
T + E            int + int + int    Predict T -> int
int + E          int + int + int    Match int
+ E              + int + int        Match +
E                int + int          Predict E -> T + E
T + E            int + int          Predict T -> int
int + E          int + int          Match int
+ E              + int              Match +
E                int                Predict E -> T
T                int                Predict T -> int
int              int                Match int
                                    Accept

Notez qu'à chaque étape, nous examinons le symbole le plus à gauche de notre production. Si c'est un terminal, nous l'assortissons, et s'il s'agit d'un terminal, nous prédisons ce que cela va devenir en choisissant l'une des règles.

Dans un analyseur syntaxique LR, il existe deux actions:

  1. Shift : ajoute le prochain jeton d'entrée dans un tampon pour examen.
  2. Réduire : Réduit un ensemble de terminaux et de non-terminaux dans ce tampon pour revenir à un non-terminal en inversant une production.

Par exemple, un analyseur syntaxique LR (1) (avec un jeton de lookahead) peut analyser la même chaîne de la manière suivante:

Workspace        Input              Action
---------------------------------------------------------
                 int + int + int    Shift
int              + int + int        Reduce T -> int
T                + int + int        Shift
T +              int + int          Shift
T + int          + int              Reduce T -> int
T + T            + int              Shift
T + T +          int                Shift
T + T + int                         Reduce T -> int
T + T + T                           Reduce E -> T
T + T + E                           Reduce E -> T + E
T + E                               Reduce E -> T + E
E                                   Reduce S -> E
S                                   Accept

Les deux algorithmes d'analyse que vous avez mentionnés (LL et LR) sont connus pour avoir des caractéristiques différentes. Les analyseurs syntaxiques LL ont tendance à être plus faciles à écrire à la main, mais ils sont moins puissants que les analyseurs syntaxiques LR et acceptent un ensemble de grammaires beaucoup plus petit que celui utilisé par les analyseurs syntaxiques LR. Les analyseurs syntaxiques LR sont proposés dans de nombreuses versions (LR (0), SLR (1), LALR (1), LR (1), IELR (1), GLR (0), etc.) et sont beaucoup plus puissants. Ils ont également tendance à être beaucoup plus complexes et sont presque toujours générés par des outils tels que yacc ou bison. Les analyseurs syntaxiques LL sont également proposés dans de nombreuses versions (y compris LL (*), qui est utilisé par l’outil ANTLR ), bien que, dans la pratique, LL (1) soit le plus largement utilisé.

Si vous souhaitez en savoir plus sur l’analyse syntaxique de LL et de LR, je viens tout juste de terminer l’enseignement d’un cours de compilation et j’ai des fiches et des diapositives sur l’analyse syntaxique sur le site Web du cours. Je serais ravi de vous en dire plus si vous pensez que cela serait utile.

445
templatetypedef

Josh Haberman dans son article LL et LR Parsing Demystified affirme que l'analyse de LL correspond directement à notation polonaise , alors que LR correspond à notation polonaise inversée . La différence entre PN et RPN est l’ordre de traverser l’arbre binaire de l’équation:

binary tree of an equation

+ 1 * 2 3  // Polish (prefix) expression; pre-order traversal.
1 2 3 * +  // Reverse Polish (postfix) expression; post-order traversal.

Selon Haberman, cela illustre la principale différence entre les analyseurs syntaxiques LL et LR:

La différence principale entre le fonctionnement des analyseurs syntaxiques LL et LR réside dans le fait qu’un analyseur syntaxique LL génère une traversée de pré-ordre de l’arbre d’analyse syntaxique et qu’un analyseur LR délivre une traversée de post-ordre.

Pour des explications détaillées, des exemples et des conclusions, consultez Haberman article .

52
msiemens

La LR utilise une approche descendante, tandis que la LR utilise une approche ascendante.

Si vous analysez une langue de programmation:

  • Le LL voit un code source, qui contient des fonctions, qui contient une expression.
  • Le LR voit l'expression, qui appartient aux fonctions, ce qui donne la source complète.
8
betontalpfa

L'analyse de LL est handicapée par rapport à la LR. Voici une grammaire cauchemardesque pour un générateur d'analyseur syntaxique LL:

Goal           -> (FunctionDef | FunctionDecl)* <eof>                  

FunctionDef    -> TypeSpec FuncName '(' [Arg/','+] ')' '{' '}'       

FunctionDecl   -> TypeSpec FuncName '(' [Arg/','+] ')' ';'            

TypeSpec       -> int        
               -> char '*' '*'                
               -> long                 
               -> short                   

FuncName       -> IDENTIFIER                

Arg            -> TypeSpec ArgName         

ArgName        -> IDENTIFIER 

Un FunctionDef ressemble exactement à un FunctionDecl jusqu'à ce que le ';' ou '{' est rencontré.

Un analyseur LL ne peut pas gérer deux règles en même temps, il doit donc choisir FunctionDef ou FunctionDecl. Mais pour savoir ce qui est correct, il faut rechercher un ';' ou '{'. Au moment de l’analyse grammaticale, le lookahead (k) apparaît infini. Au moment de l'analyse, il est fini, mais peut être volumineux.

Un analyseur syntaxique LR n'a pas besoin de regarder en avance, car il peut gérer deux règles en même temps. Ainsi, les générateurs d’analyseurs LALR (1) peuvent gérer cette grammaire avec facilité.

Étant donné le code d'entrée:

int main (int na, char** arg); 

int main (int na, char** arg) 
{

}

Un analyseur syntaxique LR peut analyser le

int main (int na, char** arg)

sans se soucier de savoir quelle règle est reconnue jusqu'à ce qu'elle rencontre un ';' ou un '{'.

Un analyseur syntaxique LL se bloque au niveau de 'int' car il doit savoir quelle règle est reconnue. Par conséquent, il doit rechercher un ';' ou '{'.

L'autre cauchemar pour les analyseurs syntaxiques LL est la récursion dans une grammaire. La récursion gauche est une chose normale dans les grammaires, pas de problème pour un générateur d'analyseur syntaxique LR, mais LL ne peut pas la gérer.

Vous devez donc écrire vos grammaires de manière non naturelle avec LL.

1
Paul B Mann

Exemple de dérivation la plus à gauche: Une grammaire G sans contexte a les productions

z → xXY (règle: 1) X → Ybx (règle: 2) Y → bY (règle: 3) Y → c (règle: 4)

Calculez la chaîne w = 'xcbxbc' avec la dérivation la plus à gauche.

z ⇒ xXY (règle: 1) ⇒ xYbxY (règle: 2) ⇒ xcbxY (règle: 4) ⇒ xcbxbY (règle: 3) ⇒ xcbxbc (règle: 4)


Exemple de dérivation la plus à droite: K → aKK (règle: 1) A → b (règle: 2)

Calculez la chaîne w = ‘aababbb’ avec la dérivation la plus à droite.

K ⇒ aKK (règle: 1) ⇒ aKb (règle: 2) ⇒ aaKKb (règle: 1) ⇒ aaKaKKb (règle: 1) ⇒ aaKaKbb (règle: 2) ⇒ aaKabbb (règle: 2) ⇒ aababbb (règle: 2)

0
Anupama Thathsarani