42 votes

Devrais-je utiliser un lexer lors de l'utilisation d'une bibliothèque de combinateur d'analyseurs telle que Parsec?

Lors de l'écriture d'un parser un analyseur de combinateur de la bibliothèque comme Haskell Parsec, généralement, vous avez 2 choix:

  • Écrire un analyseur lexical pour diviser votre String entrée en jetons, puis effectuer l'analyse sur [Token]
  • Écrire directement l'analyseur combinators sur String

La première méthode semble souvent donner un sens étant donné que beaucoup de l'analyse entrées peuvent être compris comme des jetons séparés par des espaces.

En d'autres lieux, j'ai vu des gens de recommander à l'encontre de la segmentation (ou balayage ou lexing, comment certains l'appellent), avec la simplicité d'être cité comme la raison principale.

Ce sont en général des trade-offs entre lexing et de ne pas le faire?

55voto

nh2 Points 4421

La différence la plus importante est que lexing va traduire votre domaine d'entrée.

Un beau résultat de ceci est que

  • Vous n'avez pas à penser à des espaces plus. Dans une directe (non-lexing) de l'analyseur, vous devez saupoudrer space des analyseurs dans tous les lieux où les espaces sont autorisés à être, qui est facile d'oublier et cela encombre votre code si l'espace doit séparer toutes vos jetons de toute façon.

  • Vous pouvez penser au sujet de votre entrée dans un morceau par morceau, ce qui est facile pour l'homme.

Toutefois, si vous effectuez lexing, vous obtenez les problèmes que

  • Vous ne pouvez pas utiliser le bon analyseurs sur String plus - par exemple, pour l'analyse d'un nombre avec une Fonction de la bibliothèque parseFloat :: Parsec String s Float (qui fonctionne sur une Chaîne de flux d'entrée), vous avez à faire quelque chose comme takeNextToken :: TokenParser String et execute le parseFloat de l'analyseur sur elle, l'inspection de l'analyser résultat (habituellement Either ErrorMessage a). C'est pénible à écrire et les limites de la composabilité.

  • Vous devez régler tous les messages d'erreur. Si votre analyseur sur les pions d'échec lors de la 20e jeton, où dans la chaîne d'entrée est qui? Vous devrez manuellement erreur sur la carte des emplacements de retour à la chaîne d'entrée, ce qui est fastidieux (en Parsec cela signifie pour régler tous SourcePos des valeurs).

  • Rapport d'erreur est généralement pire. L'exécution string "hello" *> space *> float sur de fausses entrée comme "hello4" vais vous dire précisément qu'il est prévu des espaces manquants après l' hello, tandis qu'un analyseur lexical sera juste affirment avoir trouvé un "invalid token".

  • Beaucoup de choses que l'on pourrait s'attendre à des unités atomiques et d'être séparés par un analyseur lexical sont en fait assez "trop dur" pour un lexer à identifier. Prenez par exemple les littéraux de Chaîne - soudain "hello world" ne sont pas deux jetons "hello et world" (mais seulement, bien sûr, si les guillemets ne sont pas échappé, comme \") - alors que c'est très naturel pour un analyseur syntaxique, cela signifie que les règles complexes et pour des cas particuliers d'un analyseur lexical.

  • Vous ne pouvez pas ré-utiliser les analyseurs sur les jetons en tant que bien. Si vous définissez comment analyser un double d'un String, l'exportation et le reste du monde peut l'utiliser; ils ne peuvent pas exécuter votre (spécialisée) de générateur de jetons d'abord.

  • Vous êtes coincé avec elle. Lors du développement de la langue à l'analyse, à l'aide d'un analyseur lexical pourrait vous conduire dans la prise de décisions rapides, fixer les choses que vous souhaiterez peut-être modifier par la suite. Par exemple, imaginez que vous avez défini une langue qui contient quelques - Float jeton. À un certain point, vous voulez introduire les littéraux négatifs (-3.4 et - 3.4) - cela pourrait ne pas être possible en raison de l'analyseur lexical de l'interprétation d'espaces comme jeton de séparateur. À l'aide d'un analyseur seule approche, vous pouvez rester plus souple, de faire des changements dans votre langue plus facile. Ce n'est pas vraiment surprenant, car un parser est un outil plus complexe qui, naturellement, encode les règles.

Pour résumer, je vous recommande d'écrire lexer-gratuit analyseurs pour la plupart des cas.

En fin de compte, un analyseur lexical est juste un "simplifiés"* l'analyseur, si vous avez besoin d'un analyseur de toute façon, de les combiner en un seul.


* À partir d'informatique de la théorie, nous savons que tous les langages réguliers sont également libre de tout contexte langues; lexers sont généralement réguliers, les analyseurs libre de tout contexte ou même contexte sensible (monadique analyseurs comme Parsec pouvez exprimer au contexte de la sensibilité).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X