Quand j'ai commencé à utiliser des combinateurs d'analyseurs, ma première réaction a été un sentiment de libération de ce qui semblait être une distinction artificielle entre l'analyse et lexing. Tout d'un coup, tout n'était que de l'analyse!
Cependant, j'ai récemment rencontré cette publication sur codereview.stackexchange illustrant quelqu'un rétablissant cette distinction. Au début, je pensais que c'était très stupide de leur part, mais ensuite le fait que des fonctions existent dans Parsec pour soutenir ce comportement me conduit à me remettre en question.
Quels sont les avantages / inconvénients de l'analyse sur un flux déjà lexé dans les combinateurs d'analyseurs?
parsing
lexer
parser-combinator
Eli Frey
la source
la source
Réponses:
Sous l'analyse, nous comprenons le plus souvent l'analyse des langages sans contexte. Un langage sans contexte est plus puissant qu'un langage ordinaire, donc l'analyseur peut (le plus souvent) faire le travail de l'analyseur lexical tout de suite.
Mais, c'est a) assez peu naturel b) souvent inefficace.
Pour a), si je pense à quoi
if
ressemble par exemple une expression, je pense que SI expr ALORS expr ELSE expr et pas 'i' 'f', peut-être quelques espaces, alors tout caractère avec lequel une expression peut commencer, etc. vous obtenez le idée.Pour b), il existe des outils puissants qui font un excellent travail pour reconnaître les entités lexicales, comme les identifiants, les littéraux, les crochets de toutes sortes, etc. Ils feront leur travail en un rien de temps et vous donneront une interface agréable: une liste de jetons. Plus besoin de sauter des espaces dans l'analyseur, votre analyseur sera beaucoup plus abstrait lorsqu'il traitera de jetons et non de personnages.
Après tout, si vous pensez qu'un analyseur devrait être occupé avec des trucs de bas niveau, pourquoi alors traiter les personnages? On pourrait aussi l'écrire au niveau des bits! Vous voyez, un tel analyseur qui fonctionne au niveau du bit serait presque incompréhensible. C'est la même chose avec les personnages et les jetons.
Juste mes 2 cents.
la source
if = string "if" >> expr >> string "then" >> expr >> string "else" >> expr
.Tout le monde suggérant que séparer lexing et analyse est une "bonne pratique" - je ne suis pas d'accord - dans de nombreux cas, effectuer lexing et l'analyse en une seule passe donne beaucoup plus de pouvoir, et les implications en termes de performances ne sont pas aussi mauvaises qu'elles sont présentées dans le autres réponses (voir Packrat ).
Cette approche brille quand on doit mélanger un certain nombre de langues différentes dans un seul flux d'entrée. Cela n'est pas seulement nécessaire pour les langages étranges orientés métaprogrammation comme Katahdin et similaires , mais aussi pour des applications beaucoup plus courantes, comme la programmation alphabétisée (mélange de latex et, par exemple, C ++), l'utilisation de HTML dans les commentaires, le bourrage de Javascript dans HTML, et bientôt.
la source
Un analyseur lexical reconnaît un langage normal et un analyseur reconnaît un langage sans contexte. Étant donné que chaque langue régulière est également sans contexte (elle peut être définie par une grammaire dite linéaire à droite ), un analyseur peut également reconnaître un langage régulier et la distinction entre analyseur et analyseur lexical semble ajouter une complexité inutile: un contexte unique -la grammaire libre (analyseur) pourrait faire le travail d'un analyseur et d'un analyseur lexical.
D'un autre côté, il peut être utile de capturer certains éléments d'un langage sans contexte à travers un langage normal (et donc un analyseur lexical) car
Ainsi, séparer l'analyse syntaxique de l'analyse lexicale présente l'avantage de pouvoir travailler avec une grammaire sans contexte plus simple et d'encapsuler certaines tâches de base (souvent routinières) dans l'analyseur lexical (divide et impera).
ÉDITER
Je ne suis pas familier avec les combinateurs d'analyseurs, donc je ne sais pas comment les considérations ci-dessus s'appliquent dans ce contexte. Mon impression est que même si avec les combinateurs d'analyseurs, on n'a qu'une seule grammaire sans contexte, la distinction entre deux niveaux (analyse lexicale / analyse syntaxique) pourrait aider à rendre cette grammaire plus modulaire. Comme indiqué, la couche d'analyse lexicale inférieure peut contenir des analyseurs de base réutilisables pour les identificateurs, les littéraux, etc.
la source
\alpha'_1 (K_0, \vec{T})
, où \ alpha'_1, K_0 et \ vec {T} sont des identifiants.Simplement, lexing et l'analyse doivent être séparés car ce sont des complexités différentes. Lexing est un DFA (automate fini déterministe) et un analyseur est un PDA (automate push-down). Cela signifie que l'analyse syntaxique consomme intrinsèquement plus de ressources que lexing, et il existe des techniques d'optimisation spécifiques disponibles uniquement pour les DFA. De plus, l'écriture d'une machine à états finis est beaucoup moins complexe et plus facile à automatiser.
Vous gaspillez en utilisant un algorithme d'analyse syntaxique pour lex.
la source
L'un des principaux avantages de l'analyse séparée / lex est la représentation intermédiaire - le flux de jetons. Cela peut être traité de différentes manières qui ne seraient pas possibles autrement avec une combinaison lex / parse.
Cela dit, j'ai trouvé qu'un bon décent récursif peut être moins compliqué et plus facile à travailler qu'avec l'apprentissage d'un générateur d'analyseur, et avoir à trouver comment exprimer la faiblesse du grammeur dans les règles du générateur d'analyseur.
la source