Esclarecimento sobre gramáticas, Lexers e Parsers

8

Informações de plano de fundo ( maio de Skip ): Estou trabalhando em uma tarefa que definimos na uni na qual precisamos criar uma gramática para uma DSL que nos foi fornecida. A gramática deve estar em BNF ou EBNF. Além de outras coisas, estamos sendo avaliados sobre as regras lexicais na gramática e nas regras de análise - como se as regras são adequadas ao subconjunto de idiomas, quão abrangentes são essas regras, quão claras são as regras.

O que não entendo é se essas regras são abordadas em uma gramática definida no BNF (é um novo tópico para nós).

A pergunta : uma gramática para um determinado idioma que foi definido no BNF ou no EBNF contém / fornece regras para análise e / ou análise lexical ? ( ou eles precisam ser especificados em outro lugar? )

Além disso, o que seria considerado uma regra lexical? E o que seria considerado uma regra de análise?

The_Neo
fonte
1
BNF é apenas uma sintaxe descrever totalmente a gramática como regex descreve completamente uma linguagem regular
aberração catraca
4
Sim, você pode definir lexing e parsing em uma única descrição semelhante a BNF - consulte PEGs, por exemplo. A distinção entre lexing e análise é bastante arbitrária e desatualizada.
SK-logic

Respostas:

8

Sim, uma gramática BNF contém todas as regras necessárias para análise e análise lexical. A diferença entre os dois é um pouco confusa. Um bom exemplo de uma regra lexical no EBNF seria:

number = [ "-" ], digit, { digit } ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;

Normalmente, os lexers podem ser implementados usando um código relativamente simples. Você pode pesquisar uma sequência para o próximo espaço e, em seguida, ver se o resultado começa com um "-" opcional, contém pelo menos um dígito depois disso e contém apenas dígitos depois disso. Os Lexers costumavam ser quase sempre uma etapa separada, mas geralmente são agrupados com o analisador atualmente. Daí a imprecisão.

Uma regra do analisador usaria o numbernão terminal para aumentar algo, como a seguinte expressão de adição.

add = number, "+", number

Mesmo que eles estejam misturados no mesmo arquivo, seu professor ainda desejará ver uma distinção clara entre regras de "lexer" e regras de "analisador". Por exemplo, não faça isso:

add = {"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" }, "+",
      {"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" }

Não apenas esse erro é propenso, é difícil de ler e difícil de implementar.

Karl Bielefeldt
fonte
Obrigado, a seção sobre fazer uma distinção clara entre regras "lexer" e regras "parser" realmente me ajudou a entender para que estamos sendo avaliados!
The_Neo
4

A gramática para análise lexical é normalmente especificada por meio de expressões regulares (especialmente para projetos do tipo universidade). Aceita um idioma regular.

Um analisador geralmente aceita uma linguagem livre de contexto, que pode ser especificada via BNF.

A distinção entre um analisador e um scanner (ou analisador lexical) é um tanto artificial, mas facilita a escrita dos analisadores.

Veja http://en.wikipedia.org/wiki/Chomsky_hierarchy

Mike Harris
fonte
Você levanta um bom argumento sobre os projetos universitários serem frequentemente diferentes. Cabe a ele esclarecer os requisitos exatos com seu professor.
Karl Bielefeldt
2

A resposta para sua pergunta é certamente Sim, ambas as regras de análise e lexing podem ser e são especificadas usando um EBNF (que é realmente apenas uma forma mais compacta de um BNF). No entanto, nos compiladores de qualidade de produção, a próxima parte da resposta é diferente.

A maioria dos idiomas possui uma gramática livre de contexto e está em conformidade com um conjunto de regras relacionadas ao lookahead e ao backtracking. As gramáticas mais comuns são LL (1) e LR (1). As gramáticas LL (1) permitem uma gramática simples descendente recursiva, geralmente codificada manualmente, enquanto LR (1) geralmente significa um gerador de analisador como o YACC. Esta parte da gramática vai para tokens (terminais), mas não para baixo.

Os símbolos são geralmente definidos separadamente usando uma gramática ainda mais simples, como uma gramática de operador. [Você pode procurar esses termos para obter melhores definições do que posso fornecer aqui.] O lexer que lê esses símbolos é geralmente responsável pela maior parte do desempenho do compilador, portanto, na minha experiência, ele sempre é codificado à mão. LEX é desajeitado (e somente C) e o regex é muito lento.

O ponto é entender que as regras de análise conduzem a tecnologia necessária para o seu analisador, e as regras de lexing são para o lexer. A distinção clara entre eles é se eles se aplicam ao uso de tokens (terminais) ou à construção deles.

Isso pode não ajudar no seu progresso acadêmico, mas importa se você for além dos projetos de brinquedos.

david.pfx
fonte