Quando comecei a usar combinadores de analisadores, minha primeira reação foi uma sensação de libertação do que parecia uma distinção artificial entre análise e lexing. De repente, tudo estava apenas analisando!
No entanto, recentemente deparei com esta postagem no codereview.stackexchange ilustrando alguém que restabelece essa distinção. A princípio, achei que isso era muito bobo, mas o fato de existirem funções no Parsec para apoiar esse comportamento me leva a me questionar.
Quais são as vantagens / desvantagens de analisar em um fluxo já flexível nos combinadores de analisadores?
parsing
lexer
parser-combinator
Eli Frey
fonte
fonte
Respostas:
Na análise, entendemos com mais frequência a análise de linguagens livres de contexto. Uma linguagem livre de contexto é mais poderosa que a linguagem comum; portanto, o analisador pode (na maioria das vezes) executar o trabalho do analisador lexical imediatamente.
Mas isso é a) bastante antinatural b) muitas vezes ineficiente.
Para a), se eu pensar em como, por exemplo, uma
if
expressão, acho que, se expr THEN expr ELSE expr e não 'i' 'f', talvez alguns espaços, qualquer caractere com o qual uma expressão possa começar etc. idéia.Para b) existem ferramentas poderosas que fazem um excelente trabalho ao reconhecer entidades lexicais, como identificadores, literais, colchetes de todos os tipos, etc. Eles farão seu trabalho praticamente em pouco tempo e fornecerão uma ótima interface: uma lista de tokens. Não se preocupe em ignorar mais espaços no analisador, seu analisador será muito mais abstrato quando lidar com tokens e não com caracteres.
Afinal, se você acha que um analisador deve estar ocupado com coisas de baixo nível, por que então processar caracteres? Pode-se escrever também no nível de bits! Veja bem, esse analisador que funciona no nível de bits seria quase incompreensível. É o mesmo com personagens e tokens.
Apenas meus 2 centavos.
fonte
if = string "if" >> expr >> string "then" >> expr >> string "else" >> expr
.Todo mundo sugerindo que separar lexing e análise é uma "boa prática" - eu tenho que discordar - em muitos casos, executar lexing e analisar em uma única passagem dá muito mais poder, e as implicações de desempenho não são tão ruins quanto são apresentadas no outras respostas (consulte Packrat ).
Essa abordagem brilha quando é preciso misturar vários idiomas diferentes em um único fluxo de entrada. Isso não é apenas necessário por linguagens estranhas orientadas à metaprogramação, como Katahdin e similares , mas também para aplicativos muito mais populares, como programação alfabetizada (misturando latex e, digamos, C ++), usando HTML em comentários, colocando Javascript em HTML e em breve.
fonte
Um analisador lexical reconhece uma linguagem regular e um analisador reconhece uma linguagem livre de contexto. Como cada linguagem regular também é livre de contexto (pode ser definida por uma gramática linear-direita ), um analisador também pode reconhecer uma linguagem regular e a distinção entre analisador e analisador lexical parece adicionar alguma complexidade desnecessária: um único contexto A gramática livre (analisador) poderia fazer o trabalho de um analisador e de um analisador lexical.
Por outro lado, pode ser útil capturar alguns elementos de uma linguagem livre de contexto por meio de uma linguagem regular (e, portanto, um analisador lexical) porque
Portanto, separar a análise da análise lexical tem a vantagem de poder trabalhar com uma gramática livre de contexto mais simples e encapsular algumas tarefas básicas (geralmente rotineiras) no analisador lexical (divide et impera).
EDITAR
Eu não estou familiarizado com os combinadores de analisadores, portanto, não tenho certeza de como as considerações acima se aplicam nesse contexto. Minha impressão é que, mesmo com os combinadores de analisadores, apenas um tenha uma gramática livre de contexto, a distinção entre dois níveis (análise / análise lexical) poderia ajudar a tornar essa gramática mais modular. Como dito, a camada de análise lexical inferior pode conter analisadores básicos reutilizáveis para identificadores, literais e assim por diante.
fonte
\alpha'_1 (K_0, \vec{T})
, onde \ alpha'_1, K_0 e \ vec {T} são identificadores.Simplesmente, lexing e análise devem ser separados porque são complexidades diferentes. Lexing é um DFA (autômato finito determinístico) e um analisador é um PDA (autômato push-down). Isso significa que a análise consome inerentemente mais recursos do que a lexing, e existem técnicas de otimização específicas disponíveis apenas para os DFAs. Além disso, escrever uma máquina de estados finitos é muito menos complexo e é mais fácil de automatizar.
Você está sendo um desperdício usando um algoritmo de análise para lex.
fonte
Uma das principais vantagens da análise / análise separada é a representação intermediária - o fluxo de token. Isso pode ser processado de várias maneiras que, de outra forma, não seriam possíveis com uma combinação lex / análise.
Dito isso, descobri que um bom e decente recursivo pode ser menos complicado e mais fácil de trabalhar do que aprender um gerador de analisador, e ter que descobrir como expressar a fraqueza da gramática dentro das regras do gerador de analisador.
fonte