Code from Eloquent JS. Chapter 11. Project: A Programming Language
- Eloquent JS. Chapter 11. Project: A Programming Language
- As an npm module
- gist to check the npm module
Grammar
expression: STRING
| NUMBER
| WORD apply
apply: /* vacio */
| '(' (expression ',')* expression? ')' apply
WHITES = /^(\s|[#;].*|\/\*(.|\n)*?\*\/)*/;
STRING = /^"((?:[^"\\]|\\.)*)"/;
NUMBER = /^([-+]?\d*\.?\d+([eE][-+]?\d+)?)/;
WORD = /^([^\s(),"]+)/;
AST
-
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. -
Finally, "APPLY" expressions represent applications. They have an
operator
property that refers to the expression that is being applied, and anargs
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:
$ cat greater-x-5.horace
>(x,5)
$ ./horacec.js greater-x-5.horace
$ cat greater-x-5.horace.evm
{
"type": "apply",
"operator": {
"type": "word",
"name": ">"
},
"args": [
{
"type": "word",
"name": "x"
},
{
"type": "value",
"value": 5
}
]
}
Examples
Instalation
$ npm i -g @crguezl/eloquentjshorace
...
Executables
-
horace
- Runs an horace program:
horace examples/two.horace
compiles the source onto the AST and interprets the AST
- Runs an horace program:
$ cat one.horace
do(
define(x, 4),
define(setx, fun(val,
set(x, val)
)
),
setx(50),
print(x)
)
$ horace one.horace
50
-
horacec
- Compiles the input program to produce a JSON containing the tree:
horacec examples/two.horace
produces the JSON fileexamples/two.horace.evm
- Compiles the input program to produce a JSON containing the tree:
-
evm
- horace Virtual Machine. Runs the tree:
evm examples/two.horace.evm
- horace Virtual Machine. Runs the tree:
$ horacec one.horace
$ ls -ltr | tail -1
-rw-r--r-- 1 casiano wheel 1656 19 mar 08:05 one.horace.evm
$ evm one.horace.evm
50
Here is the tree in JSON format for the former one.horace
program:
$ cat one.horace.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"
}
]
}
]
}
Using it as a library
> horace = require('@crguezl/eloquentjshorace')
{ 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 = horace.parser
> parser.parse('def(x,4)')
{ type: 'apply',
operator: { type: 'word', name: 'def' },
args: [ { type: 'word', name: 'x' }, { type: 'value', value: 4 } ] }