Created
January 26, 2017 21:56
-
-
Save raisch/da4a4121f183beff2af8b966c9d7e9a6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
/* | |
Filename: grammar.pegjs | |
Author: [email protected] | |
*/ | |
const util = require('util') | |
const _ = require('lodash') | |
/** | |
* Storage of Declared Variables | |
* @type {Object} | |
*/ | |
const vars = {} | |
/** | |
* If true, debugging messages will be emitted via debug | |
* @type {Boolean} | |
*/ | |
const DEBUGGING = false | |
/** | |
* Emit debugging message via debug if DEBUGGING is true. | |
* @param {Array} args - arguments supplied to util.format | |
*/ | |
const debug = (...args) => { | |
if (DEBUGGING) { | |
console.log('DEBUG: ' + util.format.apply(null, args)) | |
} | |
} | |
} | |
start = result:statement { | |
debug(`found statement "${text()}" = ${JSON.stringify(result)}`) | |
return result | |
} | |
// ==== STATEMENTS ==== | |
statement = expr:expression { | |
debug(`found expression_statement:"${text()}" = ${JSON.stringify(expr)}`) | |
return expr | |
} | |
/ primary:primary { | |
debug(`found primary_statement:"${text()}"`) | |
return primary | |
} | |
// ==== EXPRESSION ==== | |
expression = head:term tail:( SP* addsub_op SP* term )* { | |
debug(`found expression:"${text()}"`) | |
return tail.reduce((res, elt) => { | |
const op = elt[1] | |
debug(`found ${op} operator`) | |
if(op === '+') { | |
return res + elt[3] | |
} | |
else if(op === '-') { | |
return res - elt[3] | |
} | |
}, head) | |
} | |
term = SP* head:factor tail:( SP* multdiv_op SP* factor)* { | |
debug(`found term:"${text()}"`) | |
return tail.reduce((res, elt) => { | |
const op = elt[1] | |
debug(`found ${op} operator`) | |
if(op === '*') { | |
return res * elt[3] | |
} | |
else if (op === '/') { | |
return res / elt[3] | |
} | |
}, head) | |
} | |
factor = OPENPAREN expr:expression CLOSEPAREN { | |
debug(`found paren factor:"${text()}"`) | |
return expr | |
} | |
/ primary:primary { | |
debug(`found primary factor:"${text()}"`) | |
return primary | |
} | |
primary | |
= float { | |
debug(`found float primary:"${text()}"`) | |
return parseFloat(text()) | |
} | |
/ integer { | |
debug(`found integer primary:"${text()}"`) | |
return parseInt(text(), 10) | |
} | |
/ cond:path QUESTION result:path { | |
debug(`found condition primary:"${text()}"`) | |
return _.get(options, cond, null) ? _.get(options, result) : 0 | |
} | |
/ path:path { | |
debug(`found path primary:"${text()}"`) | |
return _.get(options, path) | |
} | |
path = $( symbol ( POINT ( integer / symbol ) )* ) | |
integer = SIGN? intdigits { | |
debug(`found integer:"${text()}"`) | |
return text() | |
} | |
float = SIGN? intdigits float_frac? { | |
debug(`found float:"${text()}"`) | |
return text() | |
} | |
float_frac = POINT digits { | |
return text() | |
} | |
addsub_op = op:( ADD / SUB ) { | |
debug(`found addsub op:"${op}"`) | |
return op | |
} | |
multdiv_op = op:( MULT / DIV ) { | |
debug(`found multdiv op:"${op}"`) | |
return op | |
} | |
symbol = LETTER ( LETTER / DIGIT )* { | |
debug(`found symbol:"${text()}"`) | |
return text() | |
} | |
digits = DIGIT DIGIT* { | |
debug(`found digits:"${text()}"`) | |
return text() | |
} | |
intdigits = INTDIGIT DIGIT* { | |
debug(`found intdigits:"${text()}"`) | |
return text() | |
} | |
// ==== LEXICALS ==== | |
OPENCURLY = '{' | |
CLOSECURLY = '}' | |
OPENPAREN = '(' | |
CLOSEPAREN = ')' | |
LETTER = [a-z] | |
DIGIT = [0-9] | |
INTDIGIT = [1-9] | |
ASSIGN = '=' | |
SEMI = ';' | |
SIGN = '+' / '-' | |
POINT = '.' | |
ADD = '+' | |
SUB = '-' | |
MULT = '*' | |
DIV = '/' | |
QUESTION = '?' | |
SP = [ \t] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Filename: testParser.js | |
Author: [email protected] | |
Tester for parser created from grammar.pegjs | |
*/ | |
const assert = require('assert') | |
const parser = require('./parser') | |
const target = '500 + depth+material.include?edge.face+material.thickness' | |
const expected = 624.5 | |
const context = { | |
depth: 100, | |
material: { | |
thickness: 20, | |
include: true | |
}, | |
edge: { | |
face: 4.5 | |
} | |
} | |
let result | |
try { | |
result = parser.parse(target, context) | |
} catch (err) { | |
console.log(JSON.stringify(err, null, 2)) | |
} | |
assert(expected === result, `found unexpected result: ${result}`) | |
console.log('The result is %s', result) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment