parser generator書いてみた

現状こんな感じで書ける.

lexer = Lexer.new("x + 4 * 5", /[ \t\n\r\v]+/) {
  token(:operator, /[+]/) {|ma| ma[0].to_sym }
  token(:operator2, /[*]/) {|ma| ma[0].to_sym }
  token(:integer, /[0-9]+/) {|ma| ma[0].to_i }
  token(:identifier, /[a-z]+/) {|ma| ma[0].to_sym }
}

parser = Parser.new(:expr, lexer) {
  rule(:expr, seq(:term, repeat(:operator, :term))) {|(term, ary)|
    ary.inject(term) {|r, (op, x)| r.__send__(op.content, x) }
  }

  rule(:term, seq(:factor, repeat(:operator2, :factor))) {|(factor, ary)|
    ary.inject(factor) {|r, (op, x)| r.__send__(op.content, x) }
  }

  rule(:factor, select(:integer, :identifier)) {|token|
    case token.type
    when :integer
      token.content
    when :identifier
      10
    end
  }
}

p parser.parse # => 30

COOL!!
解析木はこんな感じ.

[[#<Token x>, []], [[#<Token +>, [#<Token 4>, [[#<Token *>, #<Token 5>]]]]]]

(2009-10-12 17:30 追記)ちょっとした修正