Posts Tagged ‘peg’

common treetop pattern for parsing lists of things

rule expression_list
  expression tail:(SPACE expression)* {
    def eval(env = {})
      expressions.inject([]) do |exprs, expr|
        exprs << expr.eval(env)
      end
    end

    def expressions
      [ expression ] + tail.elements.map { |e| e.expression }
    end
  }
end

comment and keyword handling in treetop

# whitespace
rule white
[ \r\t\n]+
end

# mandatory space
rule SPACE
(white / comment)+
end

# optional space
rule space
SPACE?
end

# anything but not white
rule non_white_char
!white .
end

# typical keyword rule
rule var_keyword
'var' !non_white_char
end

rule comment
comment_to_eol / multiline_comment
end

rule multiline_comment
'/*' (!'*/' . )* '*/'
end

rule comment_to_eol
# TODO find out why this doesn't work in specs
#'#' (!"\n" .)+ "\n"

'#' (!"\n" .)*
end

(ab)using ruby within treetop(?)

rule case_expression

case_keyword SPACE case_exp:expression SPACE
when_expression_list SPACE
else_keyword SPACE else_exp:statement_list SPACE
end_keyword

{
def eval(env = {})
case_val = case_exp.eval(env)
else_val = else_exp.eval(env)
Kernel.eval <<-CASE_STMT
lambda do
case #{case_val.is_a?(String) ? "'#{case_val}'" : case_val}
#{ruby_when_expressions(env)}
else #{else_val.is_a?(String) ? "'#{else_val}'" : else_val}
end
end [] # call this lambda immediately
CASE_STMT
end

def ruby_when_expressions(env = {})
when_expression_list.eval(env).inject('') do |ruby, e|
# possible string values have been wrapped in '' already
ruby << "when #{e[:condition]} then #{e[:expression]} "
end
end
}

end

interactive treetop

# All credits go to Clifford Heath
# --------------------------------

require 'rubygems'
require 'treetop'
require 'my_grammar'
require 'readline'

parser = MyGrammarParser.new
while line = Readline::readline("? ", [])
  begin
    p parser.parse(line)
    rescue => e
    puts e
  end
end
puts