ExprParser is a simple command line calculator written in Ruby.
Command Line Usage
$ ruby ExprParser.rb >> a = 6 => 6.0 >> a + 12 * (5 + 3) => 102.0 >> a ^ 2 => 36.0 >> $ ruby ExprParser.rb 'a = 6' 'a ^ 2' 36.0 $ ruby ExprParser.rb --tokens --tree 'a = 6' 'a ^ 2' >> a = 6 Tokens: [[:IDENT, "a"], [:EQUAL, "="], [:NUMBER, "6"]] Syntax Tree: [:ASSIGN, "a", "6"] >> a ^ 2 Tokens: [[:IDENT, "a"], [:UP, "^"], [:NUMBER, "2"]] Syntax Tree: [:POWER, "a", "2"] 36.0
Command Line Arguments
ruby ExprParser.rb [--help] [--tokens] [--tree] [EXPR ...] * --help: show the help message. * --tokens: show the tokens parsed. * --tree: show the syntax tree. * EXPR ...: expression(s) to be evaluated.
Code Usage
e = ExprParser.new { :x => 10 }
e.evaluate "x ^ 2" # => 100
e.prepare "1 + sqrt(12 * 5) * (5 * 8)"
e.tokens # => [[:NUMBER, "1"], [:PLUS, "+"], [:IDENT, "sqrt"],
[:LEFT_PAREN, "("], [:NUMBER, "12"], [:MULTIPLY, "*"],
[:NUMBER, "5"], [:RIGHT_PAREN, ")"], [:MULTIPLY, "*"],
[:LEFT_PAREN, "("], [:NUMBER, "5"], [:MULTIPLY, "*"],
[:NUMBER, "8"], [:RIGHT_PAREN, ")"]]
e.tree # => [:ADD, "1", [:MULTIPLY, [:CALL, "sqrt", [:MULTIPLY, "12", "5"]],
[:MULTIPLY, "5", "8"]]]
e.evaluate # => 310.838667696593
Syntax
BNF
Expression ::= AssignmentExpression
| MainExpression
AssignmentExpression ::= <IDENT> "=" MainExpression
MainExpression ::= Term
[ ( "+" | "-" ) Term ]
Term ::= "-" Term
| ( Exponent
[ ( "*" | "/" )
Exponent ] )
Exponent ::= Primary "^" [ Exponent ]
Primary ::= "(" MainExpression ")"
| ( <IDENT> "("
( MainExpression "," )*
[ MainExpression ]
")" )
| <IDENT>
| <NUMBER>
Tokens
Numbers
A number consists of sequence of digits, an optional decimal part and optional e-notation. For example:
12581.2581.258e101.258e+101.258e-10
A number matches the regexp /([1-9][0-9]*|[0-9])(\.[0-9]+)?(e[+-]?[1-9][0-9]*)?/.
Identifiers
An identifier consists of sequence of chararacters capital A-Z, lowercase a-z, underscore ("_") or numbers 0-9. An identifier cannot
start with a number. The regexp used for identifiers is /[A-Za-z_][A-Za-z0-9_]*/. abc, x1, theNumber are
valid while 4chan is not a valid identifier.
Operator Precedence
a = B(bin, n-assoc)A + B,A - B(bin, l-assoc)A * B,A / B(bin, l-assoc),-A(unary)A ^ B(bin, r-assoc)(A),f(A)
Functions
sqrt exp log log10 cos sin tan cosh sinh tanh acos asin atan atan2 acosh asinh atanh
They are mapped from Ruby Math module.
Version History
0.1
Changed the operator associativity of +-*/ to left-associative. 5 - 3 - 3 now equals -1.
0.0
Initial release.