Skip to content

Latest commit

 

History

History
231 lines (206 loc) · 4.97 KB

README.md

File metadata and controls

231 lines (206 loc) · 4.97 KB

Build Status npm version

Code from Eloquent JS. Chapter 11. Project: A Programming Language

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 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:

$ 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
    }
  ]
}

Examples

Instalation

$ npm i -g @crguezl/eloquentjsegg
...

Executables

  • egg
    • Runs an egg program: egg examples/two.egg 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
  • eggc
    • Compiles the input program to produce a JSON containing the tree: eggc examples/two.egg produces the JSON file examples/two.egg.evm
  • evm
    • Egg Virtual Machine. Runs the tree: evm examples/two.egg.evm
$ 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"
        }
      ]
    }
  ]
}

Using it as a library

> 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 } ] }