class Lex def initialize(rule) @rule = rule @buf = "" end attr_accessor :buf def get @rule.each do |rule, token, action| if @buf =~ rule @buf = $' return token, action.call($&) end end return nil,nil end end class Parse def initialize(rule) @rule = rule @tokens = "" @values = [] end attr_accessor :tokens, :values def set(token, value) @tokens += token @values.push(value) end def parse @rule.each do |rule, to, action| if ind = (rule =~ @tokens) @tokens.sub!(rule, to) action.call(ind, @values) return true end end return false end def clear @tokens = "" @values = [] end end lex_rule = [[/exit/, 'e', Proc.new{|val| exit}], [/^\(/, 'l', Proc.new{|val| val}], [/^\)/, 'r', Proc.new{|val| val}], [/^\d+/, 'N', Proc.new{|val| val.to_i}], [/^\+/, 'o', Proc.new{|val| '+'}], [/^\-/, 'o', Proc.new{|val| '-'}], [/^\*/, 'O', Proc.new{|val| '*'}], [/^\//, 'O', Proc.new{|val| '/'}], [/^\s+/, 's', Proc.new{|val| val}]] lex = Lex.new(lex_rule) parse_rule = [[/s/, '', Proc.new{|ind, values| values.delete_at(ind)}], [/NON/, 'N', Proc.new{|ind, values| operator(ind, values)}], [/([ol])NoN([or])/, '\1N\2', Proc.new{|ind, values| operator(ind+1, values)}], [/^NoN$/, 'N', Proc.new{|ind, values| operator(ind, values)}], [/^NoNo/, 'No', Proc.new{|ind, values| operator(ind, values)}], [/lNr/, 'N', Proc.new{|ind, values| values.delete_at(ind); values.delete_at(ind+1)}]] def operator(ind, values) val_1 = values[ind] op = values[ind+1] val_2 = values[ind+2] values.delete_at(ind) values.delete_at(ind) case op when '+' values[ind] = val_1 + val_2 when '-' values[ind] = val_1 - val_2 when '*' values[ind] = val_1 * val_2 when '/' values[ind] = val_1 / val_2 end end parser = Parse.new(parse_rule) while true print '> ' lex.buf = gets.chomp t, v = lex.get while (t) parser.set(t, v) t, v = lex.get end while(parser.parse) p parser.tokens p parser.values end puts parser.values.pop parser.clear end