Dans quel processus une erreur de syntaxe se produit-elle? (tokenisation ou analyse)

23

J'essaie de comprendre la compilation et l'interprétation, étape par étape pour trouver une image totale. J'ai donc posé une question en lisant http://www.cs.man.ac.uk/~pjj/farrell/comp3.html cet article

Ça dit :

La prochaine étape du compilateur est appelée l'analyseur. Cette partie du compilateur a une compréhension de la grammaire du langage. Il est chargé d'identifier les erreurs de syntaxe et de traduire un programme sans erreur en structures de données internes pouvant être interprétées ou écrites dans une autre langue.

Mais je n'ai pas pu comprendre comment le tokenizer peut correctement tokenize le flux donné qui a l'erreur de syntaxe.

Il doit y être collé ou donner des informations erronées à l'analyseur. Je veux dire, la tokenisation n'est-elle pas aussi une sorte de traducteur?

Alors, comment cela a-t-il surmonté les lignes de code lexicales corrompues lors de la tokenisation?

Il y a un exemple de jeton à l'intérieur du lien ci-dessus à l'en- tête The Tokenizer .

Si je comprends bien, la forme du jeton semble, s'il y a quelque chose de mal dans le jeton de code, il serait également corrompu.

Pourriez-vous clarifier mon malentendu?

FZE
la source

Réponses:

32

Un tokenizer n'est qu'une optimisation de l'analyseur. Il est parfaitement possible d'implémenter un analyseur sans tokenizer.

Un tokenizer (ou lexer ou scanner) coupe l'entrée dans une liste de jetons. Certaines parties de la chaîne (commentaires, espaces blancs) sont généralement ignorées. Chaque jeton a un type (la signification de cette chaîne dans la langue) et une valeur (la chaîne qui compose le jeton). Par exemple, l'extrait de code source PHP

$a + $b

pourrait être représenté par les jetons

Variable('$a'),
Plus('+'),
Variable('$b')

Le tokenizer ne considère pas si un token est possible dans ce contexte. Par exemple, l'entrée

$a $b + +

serait heureux de produire le flux de jetons

Variable('$a'),
Variable('$b'),
Plus('+'),
Plus('+')

Lorsque l'analyseur consomme ensuite ces jetons, il remarquera que deux variables ne peuvent pas se suivre, pas plus que deux opérateurs d'infixe. (Notez que d'autres langages ont des syntaxes différentes où un tel flux de jetons peut être légal, mais pas en PHP).

Un analyseur peut toujours échouer au stade du tokenizer. Par exemple, il pourrait y avoir un caractère illégal:

$a × ½ — 3

Un tokenizer PHP ne pourrait pas faire correspondre cette entrée à ses règles et produirait une erreur avant le début de l'analyse principale.

Plus formellement, les tokenizers sont utilisés lorsque chaque token peut être décrit comme un langage normal . Les jetons peuvent ensuite être mis en correspondance de manière extrêmement efficace, éventuellement implémentés en tant que DFA. En revanche, la grammaire principale est généralement sans contexte et nécessite un algorithme d'analyse plus compliqué et moins performant tel que LALR.

amon
la source
Ainsi, nous pourrions penser que le tokenizer fait partie de l'analyseur et l'erreur de syntaxe peut se produire soit une étape de tokenisation soit une étape d'analyse selon la forme d'erreur de syntaxe. Merci pour la clarification.
FZE
4
@FZE: Vous pourriez penser de cette façon, mais c'est trompeur. Lexing n'est pas "juste une optimisation de l'analyseur". Au contraire, lexing mappe une représentation physique (une séquence de caractères) en une représentation logique (les jetons représentés par ces caractères). Cela isole l'analyseur des minuties comme la façon dont la fin d'une ligne est représentée, ou si vous décidez de représenter une logique et comme andou &&ou autre chose. C'est (principalement) séparé et différent de l'analyse. L'optimisation (le cas échéant) est un effet secondaire presque accidentel.
Jerry Coffin
@JerryCoffin merci pour l'explication supplémentaire que cela a plus de sens maintenant.
FZE
2
@JerryCoffin, amon a raison, c'est que la différence n'est pas fondamentale. Vous pouvez créer une grammaire BNF cohérente qui couvre à la fois les parties "lexer" et "parser". Nous classons généralement les règles en bas niveau (par exemple, nombre, opérateur d'addition) et haut niveau (sommation), mais la grammaire elle-même ne fait pas une telle distinction.
Paul Draper
1
@PaulDraper Je ne sais pas si séparer une langue régulière comme première phase est le bon choix. Par exemple, des paires appariées (non régulières) peuvent être nécessaires pour décrire les littéraux de chaîne dans certaines langues, mais il est toujours logique de les gérer dans la première phase. Éviter / minimiser le back-tracking semble être une meilleure ligne directrice.
CodesInChaos
16

Vous vous attendez généralement à ce que la plupart des erreurs de syntaxe proviennent de l'analyseur, pas du lexeur.

Le lexer générerait une erreur si (et surtout seulement si) il y a quelque chose dans l'entrée qui ne peut pas être symbolisé. Dans de nombreuses langues, cependant, presque toutes les séquences de caractères peuvent être transformées en jetons, les erreurs sont donc assez inhabituelles.

L'analyseur générera une erreur si l'entrée contient des jetons valides, mais ces jetons ne sont pas organisés de sorte qu'ils forment des instructions / expressions valides dans la langue cible. C'est beaucoup plus courant en règle générale.

Jerry Coffin
la source
11

Tokenizer divise simplement le flux de caractères en jetons. Du tokenizer POV, cela est complètement valide:

1 * * 1

et se traduit par quelque chose comme: ["1", MULTIPLY, MULTIPLY, "1"] Seul l'analyseur peut rejeter de telles expressions - il sait que l'opérateur multiplier ne peut pas suivre un autre opérateur multiplier. Par exemple, en JavaScript, cela produit:

Uncaught SyntaxError: Unexpected token *(…)

Il y a des erreurs qui peuvent être détectées par le tokenizer. Par exemple littéraux de chaîne inachevées: "abcou des numéros invalides: 0x0abcdefg. Ils peuvent néanmoins être signalés comme des erreurs de syntaxe:

Uncaught SyntaxError: Unexpected token ILLEGAL

Notez cependant que le jeton n'a pas été reconnu et est signalé comme ILLEGAL.

Banthar
la source