I want to write a grammar using ohm.js. The grammar should parse basic arithmetic operations and a few number functions. Not to pass a decimal to the factorial function, I need to distinguish integers and decimals.
I tried a few variations but none of them worked for all the test cases listed below. Simplified version is as follows:
Arithmetic {
Exp = Number1
Number1 = Decimal1
| Integer1
Decimal1 = Decimal1 ("+"|"-") Decimal2 -- v1
| Decimal1 ("+"|"-") Integer1 -- v2
| Integer1 ("+"|"-") Decimal2 -- v3
| Decimal2
Integer1 = Integer1 ("+"|"-") Integer2 -- v1
| Integer2
Decimal2 = Decimal2 ("*"|"/") Decimal3 -- v1
| Decimal2 ("*"|"/") Integer2 -- v2
| Integer2 ("*"|"/") Decimal3 -- v3
| Integer2 "/" Integer2 -- v4
| Decimal3
Integer2 = Integer2 ("*") Integer3 -- v1
| Integer3
Decimal3 = ("exp"|"sqrt"|"log"|"ln") "(" Number1 ")" -- v1
| "(" Decimal1 ")" -- v2
| decimalLiteral
Integer3 = "fact" "(" Integer1 ")" -- v1
| "(" Integer1 ")" -- v2
| integerLiteral (~("."))
decimalLiteral = integerLiteral? "." decimalDigit*
integerLiteral = nonZeroDigit decimalDigit* -- v1
| "0" -- v2
decimalDigit = "0".."9"
nonZeroDigit = "1".."9"
}
Test cases:
1. + 2 * 3
1 + 2. * 3
1 + 2 * 3.
1 + 1 + 2 * 3.
1 + 1 + 1 + 2 * 3.
1. - 2 + 3
https://ohmjs.org/editor/ can be used for online testing.