{"id":50730229,"url":"https://github.com/grazen0/the-ultimate-parser","last_synced_at":"2026-06-10T08:01:40.037Z","repository":{"id":358743619,"uuid":"1236231909","full_name":"Grazen0/the-ultimate-parser","owner":"Grazen0","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-18T23:12:04.000Z","size":500,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-18T23:49:55.418Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://parser.grazen.xyz","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Grazen0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-12T04:12:51.000Z","updated_at":"2026-05-18T23:12:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Grazen0/the-ultimate-parser","commit_stats":null,"previous_names":["grazen0/the-ultimate-parser"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Grazen0/the-ultimate-parser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grazen0%2Fthe-ultimate-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grazen0%2Fthe-ultimate-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grazen0%2Fthe-ultimate-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grazen0%2Fthe-ultimate-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Grazen0","download_url":"https://codeload.github.com/Grazen0/the-ultimate-parser/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grazen0%2Fthe-ultimate-parser/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34142643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-10T08:01:38.842Z","updated_at":"2026-06-10T08:01:40.030Z","avatar_url":"https://github.com/Grazen0.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The Ultimate Parser\n\nAplicación web para visualizar métodos de análisis sintáctico usados en el curso CS3402 Compiladores. Permite cargar gramáticas, probar cadenas de entrada y comparar parsers Top-Down y Bottom-Up con tablas, trazas y diagnósticos.\n\n## Funcionalidades\n\n- Parsers implementados:\n  - Descenso recursivo.\n  - Predictivo LL(1).\n  - LR(0).\n  - SLR(1).\n  - LALR(1).\n  - LR(1).\n- Construcción de FIRST y FOLLOW.\n- Construcción de tablas LL(1), ACTION y GOTO.\n- Simulación paso a paso con pila, entrada restante y acción aplicada.\n- Visualización de árbol de derivación.\n- Diagnósticos locales para conflictos, prefijos comunes y recursión izquierda directa.\n- Teclado formal con símbolos como `ϵ`, `→`, `|` y `$`.\n- Ejemplos precargados.\n- Exportación básica mediante impresión del navegador.\n- PWA básica con manifest e icono.\n\n## Stack\n\n- Next.js 16\n- React 19\n- TypeScript\n- Tailwind CSS 4\n- Vitest\n- `next/font/google` con JetBrains Mono\n\n## Formato de Gramáticas\n\nUna producción por línea:\n\n```txt\nE -\u003e T E'\nE' -\u003e + T E' | ϵ\nT -\u003e F T'\nT' -\u003e * F T' | ϵ\nF -\u003e ( E ) | id\n```\n\nReglas aceptadas:\n\n- Flechas: `-\u003e`, o `::=`.\n- Alternativas con `|`.\n- Epsilon como `ϵ`, `ε`, `eps` o `epsilon`.\n- Los símbolos deben estar separados por espacios.\n- La primera producción define el símbolo inicial.\n- Los comentarios de línea empiezan con `#`.\n\nEjemplo de cadena:\n\n```txt\nid + id * id\n```\n\n## Arquitectura\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                    Next.js 16 App Router                   │\n│  src/app/ (pages, layout, styles, manifest)               │\n└─────────────────────────────────────────────────────────────┘\n                              │\n                              ▼\n┌─────────────────────────────────────────────────────────────┐\n│              src/features/parser-lab/                       │\n│  - use-parser-lab.ts (React hooks + estado)               │\n│  - components/ (componentes UI)                           │\n└─────────────────────────────────────────────────────────────┘\n                              │\n                              ▼\n┌─────────────────────────────────────────────────────────────┐\n│                  src/lib/parser/                           │\n│  (Motor puro de parsing - sin dependencias de React)      │\n├─────────────────────────────────────────────────────────────┤\n│  grammar.ts   - Parsing de gramáticas                      │\n│  sets.ts      - Cálculo de conjuntos FIRST/FOLLOW         │\n│  diagnostics.ts - Sugerencias y advertencias de gramática │\n│  ll1.ts       - Tabla y simulación LL(1)                  │\n│  lr.ts        - Autómata LR, tabla y simulación            │\n│  analyze.ts   - Punto de entrada principal                │\n│  types.ts     - Definiciones de tipos TypeScript           │\n│  examples.ts  - Gramáticas de ejemplo                      │\n└─────────────────────────────────────────────────────────────┘\n```\n\nLa lógica de parsing vive en `src/lib/parser` y no depende de React. La interfaz vive en `src/features/parser-lab`, separando el estado del feature de sus componentes visuales.\n\n### Principios de Diseño\n\n- **Motor puro**: Todas las funciones de parsing están en `src/lib/parser/` y no importan ningún componente de React. Esto permite que el código sea testeable y reutilizable.\n- **Interfaz reactiva**: Los componentes de UI en `src/features/parser-lab/` consumen el motor de parsing y manejan el estado de la aplicación.\n- **Separación de responsabilidades**: La capa de análisis (`analyze.ts`) orquesta el flujo completo: parsing → conjuntos → tabla → simulación.\n\n## Tipos Principales\n\n### Grammar (types.ts)\n\n```typescript\ntype Grammar = {\n  start: string; // Símbolo inicial de la gramática\n  augmentedStart: string; // Símbolo inicial aumentado (S')\n  nonterminals: string[]; // Lista de no terminales\n  terminals: string[]; // Lista de terminales\n  productions: Production[]; // Lista de producciones\n  byLhs: Record\u003cstring, Production[]\u003e; // Producciones agrupadas por LHS\n};\n```\n\n### Production (types.ts)\n\n```typescript\ntype Production = {\n  id: number; // Identificador único de producción\n  lhs: string; // Lado izquierdo (no terminal)\n  rhs: string[]; // Lado derecho (secuencia de símbolos)\n  label: string; // Representación formateada \"A -\u003e α\"\n};\n```\n\n### LRItem (types.ts)\n\n```typescript\ntype LRItem = {\n  productionId: number; // ID de la producción\n  dot: number; // Posición del punto (0 = inicio)\n  lookahead?: string; // Lookahead (para LR(1)/LALR)\n};\n```\n\n### LRState (types.ts)\n\n```typescript\ntype LRState = {\n  id: number; // ID del estado\n  items: LRItem[]; // Items LR en el estado\n  transitions: Record\u003cstring, number\u003e; // Transiciones: símbolo → estado\n};\n```\n\n### AnalysisResult (types.ts)\n\n```typescript\ntype AnalysisResult = {\n  kind: AnalysisKind; // Tipo de parser (recursive, ll1, lr0, etc.)\n  name: string; // Nombre legible del parser\n  accepted: boolean; // Si la cadena fue aceptada\n  diagnostics: Diagnostic[]; // Diagnósticos y errores\n  steps: ParserStep[]; // Pasos de la simulación\n  tree?: TreeNode; // Árbol de derivación\n  ll1Table?: LL1Table; // Tabla predictiva LL(1)\n  lrStates?: LRState[]; // Estados del autómata LR\n  lrTable?: LRTable; // Tablas ACTION y GOTO\n  first: Record\u003cstring, string[]\u003e; // Conjuntos FIRST (solo no terminales)\n  follow: Record\u003cstring, string[]\u003e; // Conjuntos FOLLOW (solo no terminales)\n};\n```\n\n## API del Motor de Parsing\n\n### grammar.ts\n\n#### tokenizeInput(input: string): string[]\n\nConvierte una cadena de entrada en una lista de símbolos normalizados.\n\n- **Parámetros**: `input` - Cadena de texto con tokens separados por espacios\n- **Retorna**: Array de símbolos normalizados\n\n#### normalizeSymbol(symbol: string): string\n\nNormaliza un símbolo individuales, convirtiendo aliases de epsilon a `ϵ`.\n\n- **Parámetros**: `symbol` - Símbolo a normalizar\n- **Retorna**: Símbolo normalizado o cadena vacía si es whitespace\n\n#### parseGrammar(source: string): ParseResult\u003cGrammar\u003e\n\nParsea texto de gramática y construye un objeto Grammar.\n\n- **Parámetros**: `source` - Texto con producciones (una por línea)\n- **Retorna**: `ParseResult\u003cGrammar\u003e` con `ok`, `value` (Grammar) y `diagnostics`\n\n#### formatProduction(production: Production): string\n\nFormatea una producción como string legible.\n\n- **Parámetros**: `production` - Objeto Production\n- **Retorna**: String formateado \"A -\u003e α\" (usa ϵ si RHS es vacío)\n\n---\n\n### sets.ts\n\n#### firstSets(grammar: Grammar): Record\u003cstring, Set\u003cstring\u003e\u003e\n\nCalcula los conjuntos FIRST para todos los símbolos de la gramática.\n\n- **Parámetros**: `grammar` - Objeto Grammar\n- **Retorna**: Objeto mapeando símbolo → Set de terminales en FIRST\n\n#### firstOfSequence(sequence: string[], first: Record\u003cstring, Set\u003cstring\u003e\u003e): Set\u003cstring\u003e\n\nCalcula FIRST(α) para una secuencia de símbolos.\n\n- **Parámetros**:\n  - `sequence` - Array de símbolos\n  - `first` - Mapa de conjuntos FIRST precalculados\n- **Retorna**: Set con los FIRST de la secuencia (incluye ϵ si toda la secuencia es nullable)\n\n#### followSets(grammar: Grammar, first = firstSets(grammar)): Record\u003cstring, Set\u003cstring\u003e\u003e\n\nCalcula los conjuntos FOLLOW para todos los no terminales.\n\n- **Parámetros**:\n  - `grammar` - Objeto Grammar\n  - `first` - (opcional) Conjuntos FIRST precalculados\n- **Retorna**: Objeto mapeando no terminal → Set de símbolos en FOLLOW\n\n#### printableSets(sets: Record\u003cstring, Set\u003cstring\u003e\u003e): Record\u003cstring, string[]\u003e\n\nConvierte conjuntos de Sets a arrays de strings ordenados para display.\n\n- **Parámetros**: `sets` - Mapa de símbolo → Set\n- **Retorna**: Mapa de símbolo → array de strings ordenados alfabeticamente\n\n---\n\n### diagnostics.ts\n\n#### grammarHints(grammar: Grammar, conflicts: Diagnostic[] = []): Diagnostic[]\n\nGenera sugerencias y advertencias sobre la gramática.\n\n- **Parámetros**:\n  - `grammar` - Objeto Grammar\n  - `conflicts` - (opcional) Array de conflictos detectados\n- **Retorna**: Array de Diagnostic con advertencias sobre recursión izquierda, prefijos comunes, y conflictos\n\n---\n\n### ll1.ts\n\n#### buildLL1Table(grammar: Grammar, first: Record\u003cstring, Set\u003cstring\u003e\u003e, follow: Record\u003cstring, Set\u003cstring\u003e\u003e): LL1Table\n\nConstruye la tabla predictiva LL(1).\n\n- **Parámetros**:\n  - `grammar` - Objeto Grammar\n  - `first` - Conjuntos FIRST\n  - `follow` - Conjuntos FOLLOW\n- **Retorna**: Tabla LL(1) como `Record\u003cnoTerminal, Record\u003cterminal, TableCell\u003e\u003e`\n\n#### simulateLL1(grammar: Grammar, table: LL1Table, tokens: string[]): { accepted: boolean; steps: ParserStep[]; tree?: TreeNode }\n\nSimula el parsing LL(1) sobre una cadena de entrada.\n\n- **Parámetros**:\n  - `grammar` - Objeto Grammar\n  - `table` - Tabla predictiva LL(1)\n  - `tokens` - Array de tokens de entrada\n- **Retorna**: Objeto con `accepted`, `steps` (traza de ejecución), y `tree` (árbol de derivación)\n\n#### simulateRecursiveDescent(grammar: Grammar, table: LL1Table, tokens: string[])\n\nIgual que simulateLL1 pero formatea las acciones con notación de funciones (para \"Descenso recursivo\").\n\n- **Parámetros**: Mismos que simulateLL1\n- **Retorna**: Mismo formato que simulateLL1 pero con acciones como \"Función E(): Aplicar ...\"\n\n---\n\n### lr.ts\n\n#### buildLRMachine(grammar: Grammar, mode: LRMode, first: Record\u003cstring, Set\u003cstring\u003e\u003e): { states: LRState[]; augmented: Production[] }\n\nConstruye el autómata LR (conjunto de estados y transiciones).\n\n- **Parámetros**:\n  - `grammar` - Objeto Grammar\n  - `mode` - Modo LR: \"lr0\" | \"slr1\" | \"lalr1\" | \"lr1\"\n  - `first` - Conjuntos FIRST\n- **Retorna**: Objeto con `states` (array de LRState) y `augmented` (producciones aumentadas)\n\n#### buildLRTable(grammar: Grammar, states: LRState[], augmented: Production[], mode: LRMode, follow: Record\u003cstring, Set\u003cstring\u003e\u003e): LRTable\n\nConstruye las tablas ACTION y GOTO para parsing LR.\n\n- **Parámetros**:\n  - `grammar` - Objeto Grammar\n  - `states` - Estados del autómata\n  - `augmented` - Producciones aumentadas\n  - `mode` - Modo LR\n  - `follow` - Conjuntos FOLLOW\n- **Retorna**: LRTable con `action`, `goto`, y `conflicts`\n\n#### simulateLR(grammar: Grammar, table: LRTable, tokens: string[]): { accepted: boolean; steps: ParserStep[]; tree?: TreeNode }\n\nSimula el parsing LR sobre una cadena de entrada.\n\n- **Parámetros**:\n  - `grammar` - Objeto Grammar\n  - `table` - Tabla LR (ACTION/GOTO)\n  - `tokens` - Array de tokens de entrada\n- **Retorna**: Objeto con `accepted`, `steps` (traza de ejecución), y `tree` (árbol de derivación)\n\n#### formatItem(grammar: Grammar, item: LRItem, augmented: Production[]): string\n\nFormatea un item LR con el punto (•) en la posición correcta.\n\n- **Parámetros**:\n  - `grammar` - Objeto Grammar\n  - `item` - Item LR\n  - `augmented` - Producciones aumentadas\n- **Retorna**: String formateado \"A -\u003e •α\" o \"A -\u003e •α, a\" (con lookahead)\n\n---\n\n### analyze.ts\n\n#### analyze(grammarSource: string, inputSource: string, kind: AnalysisKind): AnalysisResult\n\nPunto de entrada principal. Orquesta todo el proceso de análisis.\n\n1. Parsea la gramática\n2. Calcula FIRST y FOLLOW\n3. Construye la tabla (LL1 o LR según `kind`)\n4. Simula el parsing\n5. Genera diagnósticos\n\n- **Parámetros**:\n  - `grammarSource` - Texto con la gramática\n  - `inputSource` - Cadena de entrada a analizar\n  - `kind` - Tipo de parser: \"recursive\" | \"ll1\" | \"lr0\" | \"slr1\" | \"lalr1\" | \"lr1\"\n- **Retorna**: AnalysisResult completo con tabla, pasos, árbol y diagnósticos\n\n---\n\n## Tests\n\nLos tests están en `scripts/` y utilizan Vitest. La suite cubre:\n\n### Estructura de Tests\n\n```\nscripts/\n└── parser-engine.test.ts\n    ├── describe(\"grammar parsing\")\n    │   ├── it(\"parsea flechas, alternativas, comentarios, epsilon y terminales\")\n    │   ├── it(\"reporta producciones malformadas y gramáticas vacías\")\n    │   └── it(\"normaliza whitespace y tokens epsilon\")\n    ├── describe(\"FIRST y FOLLOW\")\n    │   └── it(\"calcula FIRST y FOLLOW para gramática expression\")\n    ├── describe(\"LL(1) parser\")\n    │   ├── it(\"acepta expresión LL(1) válida\")\n    │   ├── it(\"rechaza expresión incompleta\")\n    │   ├── it(\"acepta expresiones parentizadas\")\n    │   ├── it(\"reporta conflictos LL(1)\")\n    │   └── it(\"maneja prefijos comunes en gramática\")\n    ├── describe(\"LR parsers\", { each: [\"lr0\", \"slr1\", \"lalr1\", \"lr1\"] })\n    │   ├── it(\"acepta gramática bottom-up canónica\")\n    │   ├── it(\"rechaza orden de tokens inválido\")\n    │   └── (otros tests específicos por modo)\n    ├── describe(\"LALR(1) parser specifics\")\n    │   └── it(\"acepta producciones nullables\")\n    ├── describe(\"ambiguous grammars\")\n    │   ├── it(\"detecta ambigüedad en gramática if-else\")\n    │   ├── it(\"detecta recursión izquierda\")\n    │   └── it(\"detecta conflictos shift-reduce\")\n    └── describe(\"LR(1) specifics\")\n        ├── it(\"detecta conflicto dangling else\")\n        └── (otros tests específicos)\n```\n\n### Categorías de Tests\n\n1. **Parsing de gramáticas**: Validación de formato, normalización de símbolos, detección de errores.\n2. **Conjuntos**: Cálculo correcto de FIRST y FOLLOW.\n3. **LL(1)**: Aceptación/rechazo, construcción de tabla, conflictos.\n4. **LR(0), SLR(1), LALR(1), LR(1)**: Aceptación/rechazo, construcción de autómata, conflictos.\n5. **Gramáticas ambiguas**: Detección de conflictos shift-reduce y reduce-reduce.\n6. **Casos edge**: Producciones nullables, recursión izquierda, prefijos comunes.\n\n### Ejecutar Tests\n\n```bash\npnpm test\n```\n\n## Comandos\n\nInstalar dependencias:\n\n```bash\npnpm install\n```\n\nDesarrollo:\n\n```bash\npnpm dev\n```\n\nAbrir:\n\n```txt\nhttp://localhost:3000\n```\n\nTests:\n\n```bash\npnpm test\n```\n\nLint:\n\n```bash\npnpm lint\n```\n\nBuild de producción:\n\n```bash\npnpm build\n```\n\n## Despliegue\n\nEl proyecto es una app Next.js sin backend externo. Puede desplegarse en Vercel o cualquier plataforma compatible con Next.js.\n\n```bash\npnpm build\npnpm start\n```\n\n## Notas\n\n- Los diagnósticos inteligentes son heurísticas locales; no requieren API keys.\n- Las gramáticas muy grandes pueden generar muchas tablas y estados; el objetivo principal es uso didáctico para ejemplos de clase.\n- El motor de parsing es puro y no tiene dependencias de React, lo que permite su uso independiente en otros contextos.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrazen0%2Fthe-ultimate-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrazen0%2Fthe-ultimate-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrazen0%2Fthe-ultimate-parser/lists"}