| 1 | = Formal Grammar for UCUM = |
| 2 | |
| 3 | This grammar was created from a parser project employing ANTLR as a LL(*) parser generator. Note that this is only one of many ways to express a formal Grammar for UCUM. Alternatively the grammar could be written for LR-parser generators (e.g. yacc). Lexer rules have been omitted for clarity. The objective is to create UCUM-parsers from a declarative definition of the grammar. |
| 4 | |
| 5 | {{{ |
| 6 | ucumExpr : DIVIDE expr |
| 7 | | expr |
| 8 | ; |
| 9 | multiply : TIMES term |
| 10 | | DIVIDE term |
| 11 | ; |
| 12 | expr : term (multiply)* |
| 13 | ; |
| 14 | term : element (exponent)? (ANN)* |
| 15 | ; |
| 16 | element : simpleUnit |
| 17 | | LPAREN expr RPAREN |
| 18 | | ANN |
| 19 | ; |
| 20 | exponent : (SIGN)? DIGITS // allow zero exponent? |
| 21 | ; |
| 22 | simpleUnit : prefix metricAtom // prefix is token from lexer |
| 23 | | metricAtom |
| 24 | | nonMetricAtom // token from lexer |
| 25 | | DIGITS // allow zero? |
| 26 | ; |
| 27 | metricAtom : baseUnit // token from lexer |
| 28 | | derivedMetricAtom // token from lexer |
| 29 | ; |
| 30 | }}} |
| 31 | |
| 32 | The following is an original code snippet from a working project using the ANTLR parser generator: |
| 33 | |
| 34 | {{{ |
| 35 | //... |
| 36 | startRule returns [UnitExpr u=null] |
| 37 | : u=ucumExpr EOF // or EOL |
| 38 | ; |
| 39 | |
| 40 | ucumExpr returns [UnitExpr u=null] |
| 41 | : DIVIDE u=expr { u.invert(); } |
| 42 | | u=expr |
| 43 | ; |
| 44 | |
| 45 | multiply[UnitExpr a] returns [UnitExpr u=null] |
| 46 | : TIMES u=term { u=a.multiply(u); } |
| 47 | | DIVIDE u=term { u.invert(); u=a.multiply(u); } |
| 48 | ; |
| 49 | |
| 50 | expr returns [UnitExpr u=null] |
| 51 | : u=term (u=multiply[u])* |
| 52 | ; |
| 53 | |
| 54 | term returns [UnitExpr u=null] |
| 55 | { int exp = 1; } |
| 56 | : u=element (exp=exponent)? (ANN)* { u.setExponent(exp); } |
| 57 | ; |
| 58 | |
| 59 | element returns [UnitExpr u=null] |
| 60 | : u=simpleUnit |
| 61 | | LPAREN u=expr RPAREN |
| 62 | | ANN { u = new UnitExpr();} |
| 63 | ; |
| 64 | |
| 65 | exponent returns [int exp=1] |
| 66 | : (s:SIGN)? e:DIGITS // allow zero? |
| 67 | { |
| 68 | exp = Integer.parseInt(e.getText()); |
| 69 | if(s != null && s.getText().equals("-") ) exp *= -1; |
| 70 | } |
| 71 | ; |
| 72 | |
| 73 | simpleUnit returns [UnitExpr u=null] |
| 74 | { double p=0; } |
| 75 | : p=prefix u=metricAtom { u.setPrefix(p); } |
| 76 | | u=metricAtom |
| 77 | | u=nonMetricAtom |
| 78 | | d:DIGITS { u = new UnitExpr(Integer.parseInt(d.getText())); } // allow zero? |
| 79 | ; |
| 80 | |
| 81 | metricAtom returns [UnitExpr u=null] |
| 82 | : u=baseUnit |
| 83 | | u=derivedMetricAtom |
| 84 | ; |
| 85 | //... lexer definitions follow |
| 86 | }}} |