-
Notifications
You must be signed in to change notification settings - Fork 0
Instruções
O trabalho pode ser testado online, em navegadores desktop ou mobile, basta acessar o site www.formallysharp.codes
Lexer | Parser |
---|---|
![]() |
![]() |
Caso o site esteja indisponível, ou por outro motivo você queira rodá-lo localmente, basta seguir os seguintes passos:
- Baixar um pacote do código fonte ou clonar o repositório do GitHub:
git clone https://github.com/baioc/FormallySharp.git
- Instalar as seguintes dependências:
- .NET Core SDK 5.0 ou superior
- ASP.NET Core Runtime
- Node LTS, incluindo o NPM
- Na pasta raiz do projeto rodar os seguintes comandos:
dotnet tool restore dotnet run
- Pronto! O app estará rodando no endereço localhost:8080
- 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.
- 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):
- 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.
- Para executar a análise léxica sobre uma string, basta gerar o lexer e inserir a string de teste no campo de entrada:
- 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 tokenaab
tem preferência sobre tokensaa
eb
.
- 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.
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:
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.
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.
- É 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:
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.