LRLA(1)パーサジェネーレータのDSLのアイディア

ふと思いついたので。
自分で実装する気はさらさらないけどね!

lhsとかrhsとかが邪魔だ。

Raccでこう書くところを、

program :
        {
          result = create_statement_list()
        }
        | stmt_list

stmt_list : stmt
          {
            result = create_statement_list()
            result.add(val[0])
          }
          | stmt_list stmt
          {
            result.add(val[1])
          }

stmt : expr
     | while_stmt
     | break_stmt
     | continue_stmt

while_stmt : WHILE '(' expr ')' block
           {
             result = create_while_statement(val[2], val[4])
           }

break_stmt : BREAK
           {
             result = create_break_statement()
           }

continue_stmt : CONTINUE
              {
                result = create_continue_statement()
              }

block : '{' stmt_list '}'
      {
        result = val[1]
      }

expr : '(' expr ')'
     {
       result = val[1]
     }
     | primary

primary : INTEGER
        | STRING

こんな感じで…

rule{
  lhs :program do
    rhs do
      create_statement_list()
    end
    rhs :stmt_list
  end
  lhs :stmt_list do
    rhs :stmt do |statement|
      list = create_statement_list()
      list.add(statement)
      list
    end
    rhs :stmt_list, :stmt do |list, statement|
      list.add(statement)
      list
    end
  end
  lhs :stmt do
    rhs :expr
    rhs :while_stmt
    rhs :break_stmt
    rhs :continue_stmt
  end
  lhs :while_stmt do
    rhs :WHILE, '(', :expr, ')', :block do |*val|
      cond, body = val[2], val[4]
      create_while_statement(cond, body)
    end
  end
  lhs :break_stmt do
    rhs :BREAK do
      create_break_statement()
    end
  end
  lhs :continue_stmt do
    rhs :CONTINUE do
      create_continue_statement()
    end
  end
  lhs :block do
    rhs '{', :stmt_list, '}' do |lb, body, rb|
      body
    end
  end
  lhs :expr do
    rhs '(', :expr, ')' do |lp, expr, rp|
      expr
    end
    rhs :primary
  end
  lhs :primary do
    rhs :INTEGER
    rhs :STRING
  end
}