Gerador de First/Follow
Gerador automático de First/Follow.
Importação
Considere importar a biblioteca da vivi-lang, aqui demos o nome de @fantastic/compiler
import { generateLL1ParsingTable, GrammarProps } from "@fantastic/compiler";
O compilador expõe uma função chamada generateLL1ParsingTable
que recebe um objeto com as especificações de uma gramática LL(1) e retorna para a mesma os conjuntos First/Follow e a Tabela Sintática.
Grámatica LL(1) exemplo
Considere a seguinte grámatica para realizar um bloco de instruções if e else:
S -> if ( CONDITION ) BLOCK S'
S' -> else BLOCK | &
CONDITION -> condition
BLOCK -> { COMMANDS }
COMMANDS -> command COMMANDS'
COMMANDS' -> command COMMANDS' | &
Para o compilador vivi-lang devemos passar a gramática no seguinte formato:
const input: GrammarProps = {
startSymbol: "S",
terminals: new Set([
"if",
"(",
")",
"{",
"}",
"else",
"condition",
"command",
"ε",
]),
nonTerminals: new Set([
"S",
"SL",
"CONDITION",
"BLOCK",
"COMMANDS",
"COMMANDSL",
]),
productionRules: [
{
nonTerminal: "S",
production: ["if", "(", "CONDITION", ")", "BLOCK", "SL"],
},
{ nonTerminal: "SL", production: ["else", "BLOCK"] },
{ nonTerminal: "SL", production: ["ε"] },
{ nonTerminal: "CONDITION", production: ["condition"] },
{ nonTerminal: "BLOCK", production: ["{", "COMMANDS", "}"] },
{ nonTerminal: "COMMANDS", production: ["command", "COMMANDSL"] },
{ nonTerminal: "COMMANDSL", production: ["command", "COMMANDSL"] },
{ nonTerminal: "COMMANDSL", production: ["ε"] },
],
};
Gerando os conjuntos First/Follow e a Tabela Sintática:
import { generateLL1ParsingTable } from "@fantastic/compiler";
const { first, follow, parsingTable } = generateLL1ParsingTable(input);
console.log(first);
console.log(follow);
console.log(parsingTable);
Estrutura first
// First:
new Map([
[
"S",
{
key: "S",
value: new Set(["if"]),
},
],
[
"SL",
{
key: "SL",
value: new Set(["else", "ε"]),
},
],
[
"CONDITION",
{
key: "CONDITION",
value: new Set(["condition"]),
},
],
[
"BLOCK",
{
key: "BLOCK",
value: new Set(["{"]),
},
],
[
"COMMANDS",
{
key: "COMMANDS",
value: new Set(["command"]),
},
],
[
"COMMANDSL",
{
key: "COMMANDSL",
value: new Set(["command", "ε"]),
},
],
]);
Estrutura follow
// Follow:
new Map([
[
"S",
{
key: "S",
value: new Set(["$"]),
},
],
[
"SL",
{
key: "SL",
value: new Set(["$"]),
},
],
[
"CONDITION",
{
key: "CONDITION",
value: new Set([")"]),
},
],
[
"BLOCK",
{
key: "BLOCK",
value: new Set(["else", "$"]),
},
],
[
"COMMANDS",
{
key: "COMMANDS",
value: new Set(["}"]),
},
],
[
"COMMANDSL",
{
key: "COMMANDSL",
value: new Set(["}"]),
},
],
]);
Estrutura tabela sintática
// Tabela sintática:
new Map([
[
"S",
{
key: "S",
value: new Map([
["if", ["if", "(", "CONDITION", ")", "BLOCK", "SL"]],
["(", "error"],
[")", "error"],
["{", "error"],
["}", "error"],
["else", "error"],
["condition", "error"],
["command", "error"],
["$", "sync"],
]),
},
],
[
"SL",
{
key: "SL",
value: new Map([
["else", ["else", "BLOCK"]],
["$", ["ε"]],
["if", "error"],
["(", "error"],
[")", "error"],
["{", "error"],
["}", "error"],
["condition", "error"],
["command", "error"],
]),
},
],
[
"CONDITION",
{
key: "CONDITION",
value: new Map([
["condition", ["condition"]],
["if", "error"],
["(", "error"],
[")", "sync"],
["{", "error"],
["}", "error"],
["else", "error"],
["command", "error"],
["$", "error"],
]),
},
],
[
"BLOCK",
{
key: "BLOCK",
value: new Map([
["{", ["{", "COMMANDS", "}"]],
["if", "error"],
["(", "error"],
[")", "error"],
["}", "error"],
["else", "sync"],
["condition", "error"],
["command", "error"],
["$", "sync"],
]),
},
],
[
"COMMANDS",
{
key: "COMMANDS",
value: new Map([
["command", ["command", "COMMANDSL"]],
["if", "error"],
["(", "error"],
[")", "error"],
["{", "error"],
["}", "sync"],
["else", "error"],
["condition", "error"],
["$", "error"],
]),
},
],
[
"COMMANDSL",
{
key: "COMMANDSL",
value: new Map([
["command", ["command", "COMMANDSL"]],
["}", ["ε"]],
["if", "error"],
["(", "error"],
[")", "error"],
["{", "error"],
["else", "error"],
["condition", "error"],
["$", "error"],
]),
},
],
]);
First Follow e Tabela Sintática
Os dados abaixo foram gerados automaticamente a partir da gramática LL(1) fornecida.
Não terminal | First | Follow |
---|---|---|
S | if | $ |
SL | else, ε | $ |
CONDITION | condition | ) |
BLOCK | { | else, $ |
COMMANDS | command | } |
COMMANDSL | command, ε | } |
- First(S): { if }
- First(SL): { else, ε }
- First(CONDITION): { condition }
- First(BLOCK): { { }
- First(COMMANDS): { command }
- First(COMMANDSL): { command, ε }
- Follow(S): { $ }
- Follow(SL): { $ }
- Follow(CONDITION): { ) }
- Follow(BLOCK): { else, $ }
- Follow(COMMANDS): { } }
- Follow(COMMANDSL): { } }
Não Terminal | if | ( | ) | { | } | else | condition | command | $ |
---|---|---|---|---|---|---|---|---|---|
S | if ( CONDITION ) BLOCK SL | error | error | error | error | error | error | error | sync |
SL | error | error | error | error | error | else BLOCK | error | error | ε |
CONDITION | error | error | sync | error | error | error | condition | error | error |
BLOCK | error | error | error | { COMMANDS } | error | sync | error | error | sync |
COMMANDS | error | error | error | error | sync | error | error | command COMMANDSL | error |
COMMANDSL | error | error | error | error | ε | error | error | command COMMANDSL | error |