ruby--ruby/lib/date/delta/parser.ry

85 lines
1.6 KiB
Plaintext
Raw Normal View History

# parser.ry: Written by Tadayoshi Funaba 2006,2008,2009 -*- ruby -*-
class Date::Delta::Parser
prechigh
nonassoc UNARY
left '^'
left '*' '/'
left '+' ',' AND '-'
preclow
rule
stmt : expr
;
expr : time
| iso
| expr '+' expr {result += val[2]}
| expr ',' expr {result += val[2]}
| expr AND expr {result += val[2]}
| expr '-' expr {result -= val[2]}
| expr '*' DIGITS {result *= val[2]}
| expr '/' DIGITS {result /= val[2]}
| expr '^' DIGITS {result **= val[2]}
| '-' expr =UNARY {result = -val[1]}
| '+' expr =UNARY {result = +val[1]}
| '(' expr ')' {result = val[1]}
;
time : DIGITS unit {result = val[0] * val[1]}
;
unit : {result = 1} | UNIT
;
iso : DURATION
;
---- header ----
---- inner ----
def lookup(str)
t = str.downcase
k = UNITS4KEY[t]
return [:UNIT, k] if k
return [:AND, nil] if t == 'and'
return [:UNKNOWNWORD, nil]
end
def parse(str)
@q = []
until str.empty?
case str
when /\A\s+/
when /\AP(\d+y)?(\d+m)?(\d+d)?t?(\d+h)?(\d+m)?(\d+s)?(\d+w)?/i
y, m, d, h, min, s, w =
[$1, $2, $3, $4, $5, $6, $7].collect{|x| x.to_i}
y *= UNITS4KEY['years']
m *= UNITS4KEY['months']
d *= UNITS4KEY['days']
h *= UNITS4KEY['hours']
min *= UNITS4KEY['minutes']
s *= UNITS4KEY['seconds']
w *= UNITS4KEY['weeks']
@q.push [:DURATION, y + m + d + h + min + s + w]
when /\A\d+/
@q.push [:DIGITS, $&.to_i]
when /\A[a-z]+/i
@q.push lookup($&)
when /\A.|\n/
@q.push [$&, $&]
end
str = $'
end
@q.push [false, false]
do_parse
end
def next_token
@q.shift
end
---- footer ----