javascriptcontext-free-grammarpegjs

PEGjs: Request Help/guide in defining Arithmetic functions


I'm learning the PEGjs grammar and I request help or guide on the following:

I have functions like, PRODUCT(), SUM(), DIVIDE()

PRODUCT can take number/PRODUCT()/SUM()/DIVIDE() as parameters (any number but comma separated)

ex: PRODUCT(2, 5, SUM(5, 6, 7), DIVIDE(5, 2), PRODUCT(4, 6, 20, 12))

Same way the SUM can take any number of parameters separated by comma.

Ex: SUM(4, 5, 10, DIVIDE(SUM(2, 5, 6), 3))

DIVIDE will take two parameters (2 must), number's or another function

Ex: DIVIDE(3, PRODUCT(3, 4, SUM(2, 3)))

Could some one help or guide me how I can achieve?

The rules I have so far

start = sum
  /multiply

multiply = "PRODUCT("a:digit "," __ b:digit ")" {return a * b}

sum = "SUM("a:digit "," b:digit ")"  {return a + b}

digit = [0-9]

__ = WhiteSpace*

WhiteSpace "whitespace"
  = [ \t\r\n]

The above rule only support product/sum of two number's. How can I achieve the above?

Thanks in Advance Manjunath Reddy


Solution

  • Good start but you needed to figure out how to parse lists of arguments and do more recursion.

    I found the best way to learn is by examples (https://github.com/pegjs/pegjs/tree/master/examples).

    Try this in the online editor:

    start
      = sum
      / multiply
      / divide
    
    multiply
      = "PRODUCT(" _ args:arguments _ ")" { return args.reduce(function(a,b) {return a*b;}); }
    
    sum
      = "SUM(" _ args:arguments _ ")"  { return args.reduce(function(a,b) {return a+b;}); }
    
    divide
      = "DIVIDE(" _ dividend:argument _ "," _ divisor:argument _ ")" { return dividend / divisor; }
    
    arguments
      = first:argument rest:(_ ',' _ arg:argument { return arg; })* { return [first].concat(rest); }
    
    argument
      = multiply
      / sum
      / divide
      / number
    
    number
      = digits:(digit)+ { return parseInt(digits.join(''), 10); }
    
    digit = [0-9]
    
    _ "optionalWhitespace"
      = whitespace *
    
    whitespace
      = [ \t\n\r]+
    

    Examples:

    PRODUCT(2, 5, SUM(5, 6, 7), DIVIDE(5, 2), PRODUCT(4, 6, 20, 12))
    2592000
    SUM(4, 5, 10, DIVIDE(SUM(2, 5, 6), 3))
    23.333333333333332
    DIVIDE(3, PRODUCT(3, 4, SUM(2, 3)))
    0.05