grammar LengthGrammar
rule term additive | factor end rule additive (factor operator:('+' | '-') space* term) { capture(:factor).value.send(capture(:operator).to_s, capture(:term).value) } end rule factor multiplicative | prefix end rule multiplicative (prefix operator:('*' | '/' | '%') space* factor) { capture(:prefix).value.send(capture(:operator).to_s, capture(:factor).value) } end rule prefix prefixed | number_group end rule prefixed (operator:('-' | '+' | '~') space* prefix) { s = capture(:operator).to_s s += '@' unless s == '~' # Unary + and - require an @. capture(:prefix).value.send(s) } end rule number_group number_set | exponent end rule number_set (primary space* number_group){ capture(:primary).value + capture(:number_group).value } end rule exponent exponential | primary end rule exponential (primary operator:'**' space* prefix) { capture(:primary).value.send(capture(:operator).to_s, capture(:prefix).value) } end rule primary group | mixed_number end rule group (lparen term rparen) { capture(:term).value } end ## Lexical syntax rule mixed_number digits_with_unit | number end rule digits_with_unit (number unit space*){ RubyUnits::Unit.new capture(:number).value, capture(:unit).to_str } end rule number irrational | integer end rule irrational rational | float end rule float decimal | integer end rule decimal (integer '.' integer) { Rational(capture(:decimal).to_str) } end rule integer (digits space*) { capture(:digits).to_str.to_i } end rule rational leading_with_minus_whole | leading_whole | fraction end rule leading_with_minus_whole (integer operator:('-') fraction){ capture(:integer).value + capture(:fraction).value } end rule leading_whole (integer fraction){ capture(:integer).value + capture(:fraction).value } end rule fraction (float '/' float) { Rational(*captures(:float).map(&:to_str).map(&:to_f)) } end rule unit ([A-z]+ | '"' | '\'' | '˚' )* end rule digits [0-9]+ ('_' [0-9]+)* # mixed_numbers may contain underscores. end rule lparen '(' space* end rule rparen ')' space* end rule space [\s] end
end