Skip to content

Instruções

Gabriel B. Sant'Anna edited this page Sep 20, 2021 · 20 revisions

Acesso à aplicação

O trabalho pode ser testado online, em navegadores desktop ou mobile, basta acessar o site www.formallysharp.codes

Lexer Parser
poly calc

Caso o site esteja indisponível, ou por outro motivo você queira rodá-lo localmente, basta seguir os seguintes passos:

  1. Baixar um pacote do código fonte ou clonar o repositório do GitHub:

git clone https://github.com/baioc/FormallySharp.git

  1. Instalar as seguintes dependências:
  1. Na pasta raiz do projeto rodar os seguintes comandos:
dotnet tool restore
dotnet run
  1. Pronto! O app estará rodando no endereço localhost:8080

Definições Regulares

Sintaxe de expressões regulares

  • A palavra vazia (epsilon), é representada pelo padrão

&

  • A concatenação é dada pela justaposição de padrões:

ab

  • Para a inclusão da operação |, é necessário que o regex esteja dentro de parênteses e com exatamente dois operandos, por exemplo:

((a|b)|c)

  • O operador * (fecho de Kleene) também necessita de parênteses, aos quais deve vir logo em seguida, por exemplo:

(a)*

  • O uso de [colchetes] é reservado para sequências de caracteres, por exemplo:

([a-zA-Z]|_)

  • Outros operadores regex (? e +, por exemplo) não são diretamente suportados mas podem ser emulados com as regras anteriores.

Classes de definições (token, separador e fragmento)

  • O lexicon é definido pelos tokens e separadores, que se diferenciam pelo fato dos separadores não gerarem entradas na tabela de símbolos.
  • Geralmente, separadores identificam padrões a serem ignorados na linguagem. Por exemplo, espaços ou quebras de linha:

( |\n)

  • Fragmentos podem ser inseridos dentro de outras regras, bastando referenciar seu nome entre colchetes. Supondo A e B fragmentos, temos o exemplo:

({A}|{B})

  • As regras de sintaxe da definição de fragmentos é igual à dos tokens e separadores, com a exceção de que fragmentos não podem incluir fragmentos.
  • Para alterar uma definição adicionada anteriormente, basta digitar o nome atribuído a ele e alterar a sua regex (o botão de adicionar passará a ser de edição):
    editar
  • Para que os Fragmentos, Tokens e Separadores tenham efeito no Lexer é necessário clicar no botão "Gerar Analisador Léxico".
  • OBS: Quando um fragmento é inserido/referenciado dentro de outro padrão, edições (ou mesmo remoção) do fragmento não serão propagadas aos padrões nos quais ele foi incluído. Será necessário re-inserir o token em questão para atualizá-lo.

Execução do Lexer

  • Para executar a análise léxica sobre uma string, basta gerar o lexer e inserir a string de teste no campo de entrada: lexer
  • O analisador léxico vai automaticamente gerar a tabela de símbolos, indicando Token, Lexema e a Posição do mesmo.
  • O lexer para de processar a entrada ao encontrar um erro léxico, que ele indica junto à tabela.
  • Quando mais de um padrão se encaixa com um lexema, a prioridade é dada aos tokens (sobre os separadores).
  • Se múltiplos tokens reconhecerem a mesma parte da entrada, a preferência é dada àquele que mais consome a entrada.

Seja uma string de entrada aab, o token aab tem preferência sobre tokens aa e b.

  • Para alterar o comportamento anterior, as setas para cima e para baixo na interface alteram a prioridade dos tokens (mais para cima implica maior prioridade).

Com isso, é possível fazer com que um padrão de palavra reservada if tenha preferência sobre um padrão genérico ([a-z])*, por exemplo.

Gramática e Parser LL(1)

Quando o analisador léxico não encontra erros na entrada, a caixa de texto fica amarela enquanto não houver um analisador sintático, este podendo ser gerado a partir de uma gramática LL(1) definida na aba Sintaxe:

tabs

Regras de produção da gramática devem ser adicionadas uma a uma, sempre com um <NaoTerminal> na cabeça da produção e um corpo contendo uma sequência (separada por espaços), de <NaoTerminais> e Terminais, onde cada símbolo não-terminal deve se referir a um não-terminal já existente e cada símbolo terminal deve ser o nome de um token criado na etapa de análise léxica.

O não terminal especial que indica a palavra vazia (ε) é representado pelo corpo de produção &

Além do botão de remover uma regra, a interface de projeto de sintaxe inclui indicadores do símbolo inicial da gramática.

first_first

No exemplo acima, vemos um exemplo de não-terminal inicial com múltiplas produções, em BNF: <S> ::= <E> | <E> a

Depois de gerar o analisador sintático, a caixa de texto será marcada em vermelho ou verde, respectivamente se a entrada for rejeitada ou aceita pela linguagem formal definida.

OBS: O sistema só aceita gramáticas LL(1) sem recursão à esquerda e já fatoradas. Se as produções não respeitarem essa restrição, a tabela de análise gerada vai destacar os conflitos LL(1) detectados.

Persistência

  • É possível salvar e carregar projetos de linguagem formal, através dos botões "abrir" e "salvar" na parte superior direita da aplicação.

Utilizando o seu navegador, você poderá ver projetos exemplo com os identificadores "poly" ou "calc", como na imagem a seguir: persistencia
OBS: Por favor não sobrescrevam os exemplos! 😄

  • Atenção! Não nos responsabilizamos por quaisquer informações armazenadas na forma de projetos de linguagem. Nunca insira dados confidenciais.
  • Qualquer um pode acessar e sobrescrever projetos, basta conhecer o seu identificador. Portanto, não nos responsabilizamos por perdas de informações.