2015-11-16 6 views
0

Я изучаю грамматику PEGjs и я запрашиваю помощь или направлять по следующим вопросам:PEGjs: Запрос Помощь/руководство в определении арифметических функций

У меня есть такие функции, как, PRODUCT(), SUM(), DIVIDE()

ПРОДУКТ может занять несколько /PRODUCT()/SUM()/DIVIDE() в качестве параметров (любое количество, но разделенные запятой)

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

таким же образом, сумма может принимать любое число параметров, разделенных запятой.

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

РАЗДЕЛИТЬ будет принимать два параметра (2 необходимо), число или другая функция

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

Может кто-нибудь помочь или направить меня, как я могу достичь?

Правила, у меня до сих пор

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] 

Указанное правило поддерживают только продукт/сумму два числа. Как я могу достичь вышеуказанного?

Заранее спасибо Manjunath Reddy

ответ

1

Хорошее начало, но вам необходимо выяснить, как разобрать списки аргументов и делать больше рекурсию.

Я нашел лучший способ узнать по примерам (https://github.com/pegjs/pegjs/tree/master/examples).

Попробуйте это в 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]+ 

Примеры:

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 
+0

Большое спасибо за помощь. – user3130446

1

Вообще, если вы хотите, чтобы разобрать неограниченный список таких как

1, 2, 3, 4 

вы можете создать рекурсивный правило:

args = head:Integer rest:(_ "," _ r:args{ return r; })? { 
    return rest != null ? [head].concat(rest) : [head]; 
} 

Integer = [0-9]+ { return parseInt(text(), 10); } 

_ = [ \t\n\r]* 

 Смежные вопросы

  • Нет связанных вопросов^_^