Distinguishing integer and decimal arithmetic with ohm.js

17 Views Asked by At

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.

0

There are 0 best solutions below