# egg-parser

# Objetivos

Usando el generador de analizadores Nearley.js escriba un parser para el lenguaje Egg que genere los árboles según la especificación que se describe en la sección ASTs: Árboles de Análisis Abstracto. Utilice el generador de analizadores léxicos moo-ignore para la fase de análisis léxico.

Construya un paquete npm y publíquelo en GitHub Registry con ámbito @ull-esit-pl-2223 y nombre el nombre del repo asignado.

El módulo exportará un objeto con al menos la propiedad { parseFromfile }.

  • parseFromFile(inputFile) es una función que devuelve el AST construído a partir de los contenidos del programa en lenguaje Egg contenido en el fichero con nombre inputFile

La gramática del lenguaje Egg se describe en la sección Gramáticas Independientes del Contexto. This is the equivalent syntax diagram:

expression

STRING NUMBER WORD applies

applies

ε "(" expression "," expression ")" applies

Se deberá proveer un ejecutable eggc con una interfaz como esta:

➜  prefix-lang git:(master) ✗ bin/eggc.js -h
Usage: eggc [options] <origin>

Compile a Egg lang file

Arguments:
  origin                   The path of the file to compile

Options:
  -V, --version            output the version number
  -o, --out <destination>  Path for output file. If it isn't specified the path of the origin file will be
                           used,changing the extension to .json
  -h, --help               display help for command
1
2
3
4
5
6
7
8
9
10
11
12
13

Puede usar el ejecutable evm (las siglas corresponden a Egg virtual Machine) del paquete "@crguezl/eloquentjsegg" (opens new window) para comprobar que los ASTs generados funcionan.

Sigue un ejemplo (compatible "@crguezl/eloquentjsegg" (opens new window) versión 1.2.6) de como debería funcionar nuestro parser eggc:

➜  prefix-lang git:(master) ✗ cat test/examples/array.egg 
do(
  def(x, arr(arr(1,4),5,7)),
  print([](x,0)), # [1,4]
  print([](x,1))  # 5
)
1
2
3
4
5
6

Nuestro parser deberà por tanto producir un AST conforme a la especificación dada en la sección Anatomía de los AST para Egg. Esto es, deberá estar conforme a esta gramática árbol:

ast: VALUE
   | WORD 
   | APPLY( operator:WORD args:[ ast * ]))
1
2
3

Los nodos APPLY tienen dos atributos operator y args. El atributo args es un ARRAY conteniendo los ASTs que se corresponden con los argumentos de operator. Los nodos WORD son nodos hoja y tienen al menos el atributo name. Los nodos VALUE tienen al menos el atributo value.

Por ejemplo, el AST para +(a,*(4,5)) se podría describir mediante este término:

APPLY(
  operator: WORD{name: +},
  args: [
    WORD{name: a}, 
    APPLY(
      operator: WORD{name:*}, 
      args: [VALUE{value:4}, VALUE{value:5}]
    )
   ]
)
1
2
3
4
5
6
7
8
9
10

A la derecha del tipo de nodo y entre llaves escribimos las parejasatributo: valor que nos interesa resaltar.

El ejecutable bin/eggc.js deberá producir un fichero JSON con el ast:

✗ bin/eggc.js test/examples/array.egg -o test/ast/array.json
1

Puede ver los contenidos del ast para el ejemplo test/examples/array.egg (opens new window) haciendo click sobre este enlace:

➜ prefix-lang git:(master) ✗ cat test/ast/array.json

A continuación podemos usar el ejecutable evm para interpretar el árbol:

➜  prefix-lang git:(master) ✗ npx evm test/ast/array.json
[ 1, 4 ]
5
1
2
3

Observe que puesto que el paquete "@crguezl/eloquentjsegg" (opens new window) ha sido instalado localmente, necesitamos hacer uso de npx (opens new window) para ejecutar el intérprete evm.

npx

npx <command>[@version] [command-arg]... executes <command> either from a local node_modules/.bin, or from a central cache, usually in ~/.npm/cacache

  npm config get cache
  /Users/casianorodriguezleon/.npm
  ✗ ls /Users/casianorodriguezleon/.npm/_cacache 
content-v2 index-v5   tmp
1
2
3
4

installing any packages needed in order for <command> to run. By default, npx will check whether <command> exists in $PATH, or in the local project binaries, and execute that. If <command> is not found, it will be installed prior to execution.

En el directorio node_modules/@crguezl/eloquentjsegg/examples tiene algunos ejemplos de programas egg que puede usar para comprobar el buen funcionamiento de su parser:

➜  prefix-lang git:(master) ✗ ls  node_modules/@crguezl/eloquentjsegg/examples 
array.egg       greater-x-5.egg main2.js        one.egg         sum.egg         unbalanced.egg
expcomma.egg    if.egg          one-err-2.egg   scope.egg       sum.egg.evm
fun.egg         main.js         one-err.egg     string.egg      two.egg
1
2
3
4

Nota de Advertencia

En algunos de los ejemplos, vídeos, repos, etc. que acompañan esta práctica puede notar algunas inconsistencias en el lenguaje Egg debidas a que casi en cada curso hemos ido haciendo alias de algunos de los nombres de los constructos. Por ejemplo, a veces en un vídeo en vez de fun usamos -> y en algún ejemplo en los apuntes en vez de element se usa <-, etc. También en algún ejemplo aparecen llavitas { y } en vez de paréntesis (de nuevo una llave aquí es un alias del correspondiente paréntesis). Son cambios triviales que no deberían afectar a la comprensión del texto.

# Publicación del módulo

Una parte de los conceptos y habilidades a adquirir con esta práctica se explican en la sección Creating and publishing a node.js module en GitHub y en NPM. Léala con detenimiento antes de hacer esta práctica.

# Pruebas

Deberá añadir pruebas usando Mocha y Chai o Jest. Repase las secciones Testing with Mocha and Chai y Jest.

Añada un estudio de covering. See the notes in covering.

Añada CI con GitHub Actions.

# Informe y Documentación

Documente el módulo incorporando un README.md: Como se instala, como se usa el ejecutable, como se carga la librería, etc.

Use GitHub Pages en el directorio docs.

No haga el informe de la práctica en el README.md sino que utilice el generador estático Vuepress (opens new window) para hacer el informe.

Para el despliegue (opens new window) del informe puede

  • mover los ficheros generados por VuePress del directorio src/.vuepress/dist/ al directorio docs/).

  • Recuerde poner base en su Vuepress config.js con el nombre de su repo. Algo así:

    module.exports = {
      title: 'Lab egg-parser Report',
      base: '/egg-parser-casiano-rodriguez-leon-alumno5/',
      ...
    }
    
    1
    2
    3
    4
    5
  • Añada un fichero con nombre .nojekyll (opens new window) en su directorio docs/.

La documentación de la API de la función exportada usando JsDoc la puede dejar accesible en el despliegue (directorio docs/api) o puede tratar de integrarla con Vuepress JsDoc Plugin (opens new window).

Añada el informe de Covering también (directorio docs/covering o similar).

# Challenge

  • Asegúrese de producir mensajes de error significativos informando de los números de línea y columna correctos

# References

# Nearley.js

# moo

# Testing

# Documentation

# Semantic versioning and npm

Grading Rubric#

Comments#

Last Updated: 2 months ago