mikldk
mikldk

Reputation: 194

PEG.js extension with predefined functions and variables

I have had a look at the PEG.js parser generator for JavaScript. It looks pretty nice!

I don't have much experience with specifying grammars. I am searching for help to extend the example grammar at 1 a bit to allow for

  1. Decimal numbers
  2. Operator ^
  3. Predefined functions (not function declarations, only to call some functions that I specify beforehand), where arguments themselves are first order expressions, e.g. f(g(2+4) + 3)
  4. Variables A-Z (not declarations, only usage definitions -- these are meant to point to a input box that also contains a program, letters A to Z are sufficient)

Can you help me with where to find help to do that?

Upvotes: 5

Views: 819

Answers (2)

Bart Kiers
Bart Kiers

Reputation: 170308

Here's quick demo:

{
  variables = { 
    PI : Math.PI, 
    E  : Math.E 
  };
  functions = {
    squared : function(n) { return n * n; },
    incr    : function(n) { return n + 1; }
  }
}

start
 = additive

additive
 = left:multiplicative "+" right:additive { return left + right; }
 / multiplicative

multiplicative
 = left:power "*" right:additive { return left * right; }
 / power

// evaluated left to right!
power
 = left:primary "^" right:additive { return Math.pow(left, right); }
 / primary

primary
 = integer
 / "(" e:additive ")"      { return e; }
 / i:id "(" e:additive ")" { return functions[i.join("")](e); }
 / i:id                    { return variables[i.join("")]; }

integer
  = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

id
 = [a-zA-Z]+

If you now test the parser (online) with the input:

PI+incr(squared(3))^2

you will see it being evaluated as:

103.1415926535898

Upvotes: 5

mikldk
mikldk

Reputation: 194

{
  variables = { 
    PI : Math.PI, 
    E  : Math.E 
  };
  functions = {
    squared : function(n) { return n * n; },
    incr    : function(n) { return n + 1; }
  }
}

start
 = additive

additive
 = left:multiplicative "+" right:additive { return left + right; }
 / multiplicative

multiplicative
 = left:power "*" right:power { return left * right; }
 / power

// evaluated left to right!
power
 = left:primary "^" right:primary { return Math.pow(left, right); }
 / primary

primary
 = number
 / integer
 / "(" e:additive ")"      { return e; }
 / i:id "(" e:additive ")" { return functions[i.join("")](e); }
 / i:id                    { return variables[i.join("")]; }

number_frac
    = "." chars:[0-9]* { return "." + chars.join(''); }

number
    = chars:[0-9]+ frac:number_frac? { return parseFloat(chars.join('') + frac); }

integer
  = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

id
 = [a-zA-Z]+

Upvotes: -1

Related Questions