http://eloquentjavascript.net/11_language.html and https://ULL-ESIT-PL-1617.github.io/egg
npm install @crguezl/eloquentjsegg


```
$ npm i -g @crguezl/eloquentjsegg
...
* egg egg examples/two.egg
- Runs an egg program: compiles the source onto the AST and interprets the AST
``
$ cat one.egg
do(
define(x, 4),
define(setx, fun(val,
set(x, val)
)
),
setx(50),
print(x)
)
$ egg one.egg
50
* eggceggc examples/two.egg
- Compiles the input program to produce a JSON containing the tree: produces the JSON file examples/two.egg.evmevm
* evm examples/two.egg.evm
- Egg Virtual Machine. Runs the tree: ``
$ eggc one.egg
$ ls -ltr | tail -1
-rw-r--r-- 1 casiano wheel 1656 19 mar 08:05 one.egg.evm
$ evm one.egg.evm
50
Here is the tree in JSON format for the former one.egg program:
``
$ cat one.egg.evm
{
"type": "apply",
"operator": {
"type": "word",
"name": "do"
},
"args": [
{
"type": "apply",
"operator": {
"type": "word",
"name": "define"
},
"args": [
{
"type": "word",
"name": "x"
},
{
"type": "value",
"value": 4
}
]
},
{
"type": "apply",
"operator": {
"type": "word",
"name": "define"
},
"args": [
{
"type": "word",
"name": "setx"
},
{
"type": "apply",
"operator": {
"type": "word",
"name": "fun"
},
"args": [
{
"type": "word",
"name": "val"
},
{
"type": "apply",
"operator": {
"type": "word",
"name": "set"
},
"args": [
{
"type": "word",
"name": "x"
},
{
"type": "word",
"name": "val"
}
]
}
]
}
]
},
{
"type": "apply",
"operator": {
"type": "word",
"name": "setx"
},
"args": [
{
"type": "value",
"value": 50
}
]
},
{
"type": "apply",
"operator": {
"type": "word",
"name": "print"
},
"args": [
{
"type": "word",
"name": "x"
}
]
}
]
}$3
`js`
> egg = require('@crguezl/eloquentjsegg')
{ run: [Function: run],
runFromFile: [Function: runFromFile],
runFromEVM: [Function: runFromEVM],
parser:
{ getProgram: [Function: getProgram],
lex: [Function: lex],
parse: [Function: parse],
parseApply: [Function: parseApply],
parseExpression: [Function: parseExpression],
parseFromFile: [Function: parseFromFile],
setProgram: [Function: setProgram] } }
> parser = egg.parser
> parser.parse('def(x,4)')
{ type: 'apply',
operator: { type: 'word', name: 'def' },
args: [ { type: 'word', name: 'x' }, { type: 'value', value: 4 } ] }
`Yacc
expression: STRING
| NUMBER
| WORD apply
apply: / vacio /
| '(' (expression ',')* expression? ')' apply
WHITES = /^(\s|[#;].|\/\(.|\n)?\\/)*/;
STRING = /^"((?:[^"\\]|\\.)*)"/;
NUMBER = /^([-+]?\d*\.?\d+([eE][-+]?\d+)?)/;
WORD = /^([^\s(),"]+)/;
`
* Expressions of type "VALUE" represent literal strings or numbers.
Their value property contains the string or number value that they represent.
* Expressions of type "WORD" are used for identifiers (names). Such objects have a name property that holds the identifier’s name as a string. operator
* Finally, "APPLY" expressions represent applications. They have an property that refers to the expression that is being applied, and an args property that holds an array of argument expressions.
``
ast: VALUE{value: String | Number}
| WORD{name: String}
| APPLY{operator: ast, args: [ ast ...]}
The >(x, 5) would be represented like this:
`bash``
$ cat greater-x-5.egg
>(x,5)
$ ./eggc.js greater-x-5.egg
$ cat greater-x-5.egg.evm
{
"type": "apply",
"operator": {
"type": "word",
"name": ">"
},
"args": [
{
"type": "word",
"name": "x"
},
{
"type": "value",
"value": 5
}
]
}
* Eloquent JS. Chapter 11. Project: A Programming Language
* As an npm module
* gist to check the npm module