Class: Pikuri::Tool::Calculator::Parser
- Inherits:
-
Object
- Object
- Pikuri::Tool::Calculator::Parser
- Defined in:
- lib/pikuri/tool/calculator.rb
Overview
Recursive-descent parser-evaluator for Python's arithmetic grammar:
additive := multiplicative (('+' | '-') multiplicative)*
multiplicative := unary (('*' | '/' | '//' | '%') unary)*
unary := ('+' | '-') unary | power
power := atom ('**' unary)?
atom := NUMBER | '(' additive ')'
The +power+→+unary+ recursion on the right operand makes **
right-associative (+232+ is 512) and lets a sign follow it
(+2**-3+); unary above power on the left makes -2**2 evaluate to
-4 — both as Python parses them.
Semantics follow Python 3 where Ruby differs: / is always true (float)
division, // floors, 2**-1 is Float 0.5 (not a Rational), and a
negative base under a fractional exponent is rejected (not a Complex).
Constant Summary collapse
- TOKEN_RE =
One number or operator. +**+/+//+ listed before their single-char prefixes so the two-char operators win; number literals cover
42,4.2,5.,.5, and e-notation.\Ganchors each match at the scan position so nothing between tokens is missed. %r{\G\s*(\*\*|//|\d+(?:\.\d*)?(?:[eE][+-]?\d+)?|\.\d+(?:[eE][+-]?\d+)?|[-+*/%()])}
Instance Method Summary collapse
-
#initialize(expression) ⇒ Parser
constructor
A new instance of Parser.
-
#parse ⇒ Integer, Float
Parse and evaluate the whole token stream.
Constructor Details
#initialize(expression) ⇒ Parser
Returns a new instance of Parser.
77 78 79 80 |
# File 'lib/pikuri/tool/calculator.rb', line 77 def initialize(expression) @tokens = tokenize(expression) @pos = 0 end |
Instance Method Details
#parse ⇒ Integer, Float
Parse and evaluate the whole token stream.
86 87 88 89 90 91 |
# File 'lib/pikuri/tool/calculator.rb', line 86 def parse value = additive raise Error, "unexpected #{peek.inspect} after expression" if peek value end |