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 |