module LambdaCalculus
include Treetop::Runtime
def root
@root || :program
end
include Arithmetic
module Program0
def space
elements[1]
end
def expression
elements[2]
end
end
module Program1
def expression
elements[0]
end
def more_expressions
elements[1]
end
end
module Program2
def eval(env={})
env = env.clone
last_eval = nil
expressions.each do |exp|
last_eval = exp.eval(env)
end
last_eval
end
def expressions
[expression] + more_expressions.elements.map {|elt| elt.expression}
end
end
def _nt_program
start_index = index
cached = node_cache[:program][index]
if cached
@index = cached.interval.end
return cached
end
i0, s0 = index, []
r1 = _nt_expression
s0 << r1
if r1.success?
s2, i2 = [], index
loop do
i3, s3 = index, []
r4 = parse_terminal(';', SyntaxNode)
s3 << r4
if r4.success?
r5 = _nt_space
s3 << r5
if r5.success?
r6 = _nt_expression
s3 << r6
end
end
if s3.last.success?
r3 = (SyntaxNode).new(input, i3...index, s3)
r3.extend(Program0)
else
self.index = i3
r3 = ParseFailure.new(input, i3)
end
if r3.success?
s2 << r3
else
break
end
end
r2 = SyntaxNode.new(input, i2...index, s2)
s0 << r2
end
if s0.last.success?
r0 = (SyntaxNode).new(input, i0...index, s0)
r0.extend(Program1)
r0.extend(Program2)
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
node_cache[:program][start_index] = r0
return r0
end
def _nt_expression
start_index = index
cached = node_cache[:expression][index]
if cached
@index = cached.interval.end
return cached
end
i0 = index
r1 = _nt_definition
if r1.success?
r0 = r1
else
r2 = _nt_conditional
if r2.success?
r0 = r2
else
r3 = _nt_application
if r3.success?
r0 = r3
else
r4 = _nt_function
if r4.success?
r0 = r4
else
r5 = super
if r5.success?
r0 = r5
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
end
end
end
end
node_cache[:expression][start_index] = r0
return r0
end
module Definition0
def space
elements[1]
end
def variable
elements[2]
end
def space
elements[3]
end
def expression
elements[4]
end
end
module Definition1
def eval(env)
env[variable.name] = expression.eval(env)
end
end
def _nt_definition
start_index = index
cached = node_cache[:definition][index]
if cached
@index = cached.interval.end
return cached
end
i0, s0 = index, []
r1 = parse_terminal('def', SyntaxNode)
s0 << r1
if r1.success?
r2 = _nt_space
s0 << r2
if r2.success?
r3 = _nt_variable
s0 << r3
if r3.success?
r4 = _nt_space
s0 << r4
if r4.success?
r5 = _nt_expression
s0 << r5
end
end
end
end
if s0.last.success?
r0 = (SyntaxNode).new(input, i0...index, s0)
r0.extend(Definition0)
r0.extend(Definition1)
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
node_cache[:definition][start_index] = r0
return r0
end
module Conditional0
def space
elements[1]
end
def space
elements[3]
end
def condition
elements[4]
end
def space
elements[5]
end
def space
elements[7]
end
def true_case
elements[8]
end
def space
elements[9]
end
def space
elements[11]
end
def false_case
elements[12]
end
end
module Conditional1
def eval(env)
if condition.eval(env)
true_case.eval(env)
else
false_case.eval(env)
end
end
end
def _nt_conditional
start_index = index
cached = node_cache[:conditional][index]
if cached
@index = cached.interval.end
return cached
end
i0, s0 = index, []
r1 = parse_terminal('if', SyntaxNode)
s0 << r1
if r1.success?
r2 = _nt_space
s0 << r2
if r2.success?
r3 = parse_terminal('(', SyntaxNode)
s0 << r3
if r3.success?
r4 = _nt_space
s0 << r4
if r4.success?
r5 = _nt_expression
s0 << r5
if r5.success?
r6 = _nt_space
s0 << r6
if r6.success?
r7 = parse_terminal(')', SyntaxNode)
s0 << r7
if r7.success?
r8 = _nt_space
s0 << r8
if r8.success?
r9 = _nt_expression
s0 << r9
if r9.success?
r10 = _nt_space
s0 << r10
if r10.success?
r11 = parse_terminal('else', SyntaxNode)
s0 << r11
if r11.success?
r12 = _nt_space
s0 << r12
if r12.success?
r13 = _nt_expression
s0 << r13
end
end
end
end
end
end
end
end
end
end
end
end
if s0.last.success?
r0 = (SyntaxNode).new(input, i0...index, s0)
r0.extend(Conditional0)
r0.extend(Conditional1)
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
node_cache[:conditional][start_index] = r0
return r0
end
def _nt_primary
start_index = index
cached = node_cache[:primary][index]
if cached
@index = cached.interval.end
return cached
end
i0 = index
r1 = _nt_application
if r1.success?
r0 = r1
else
r2 = super
if r2.success?
r0 = r2
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
end
node_cache[:primary][start_index] = r0
return r0
end
module Application0
def operator
elements[0]
end
def space
elements[1]
end
def expression
elements[2]
end
end
module Application1
def eval(env={})
left_associative_apply(operator.eval(env), env)
end
def left_associative_apply(operator, env)
if expression.instance_of?(Application)
expression.left_associative_apply(operator.apply(expression.operator.eval(env)), env)
else
operator.apply(expression.eval(env))
end
end
def to_s(env={})
operator.to_s(env) + ' ' + expression.to_s(env)
end
end
def _nt_application
start_index = index
cached = node_cache[:application][index]
if cached
@index = cached.interval.end
return cached
end
i0, s0 = index, []
r1 = _nt_operator
s0 << r1
if r1.success?
r2 = _nt_space
s0 << r2
if r2.success?
r3 = _nt_expression
s0 << r3
end
end
if s0.last.success?
r0 = (Application).new(input, i0...index, s0)
r0.extend(Application0)
r0.extend(Application1)
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
node_cache[:application][start_index] = r0
return r0
end
def _nt_operator
start_index = index
cached = node_cache[:operator][index]
if cached
@index = cached.interval.end
return cached
end
i0 = index
r1 = _nt_function
if r1.success?
r0 = r1
else
r2 = _nt_variable
if r2.success?
r0 = r2
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
end
node_cache[:operator][start_index] = r0
return r0
end
def _nt_non_application
start_index = index
cached = node_cache[:non_application][index]
if cached
@index = cached.interval.end
return cached
end
i0 = index
r1 = _nt_function
if r1.success?
r0 = r1
else
r2 = _nt_variable
if r2.success?
r0 = r2
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
end
node_cache[:non_application][start_index] = r0
return r0
end
module Function0
def param
elements[1]
end
def body
elements[3]
end
end
module Function1
class Closure
attr_reader :env, :function
def initialize(function, env)
@function = function
@env = env
end
def apply(arg)
function.body.eval(function.param.bind(arg, env))
end
def to_s(other_env={})
"\\#{function.param.to_s}(#{function.body.to_s(other_env.merge(env))})"
end
end
def eval(env={})
Closure.new(self, env)
end
def to_s(env={})
eval(env).to_s
end
end
def _nt_function
start_index = index
cached = node_cache[:function][index]
if cached
@index = cached.interval.end
return cached
end
i0, s0 = index, []
r1 = parse_terminal('\\', SyntaxNode)
s0 << r1
if r1.success?
r2 = _nt_variable
s0 << r2
if r2.success?
r3 = parse_terminal('(', SyntaxNode)
s0 << r3
if r3.success?
r4 = _nt_expression
s0 << r4
if r4.success?
r5 = parse_terminal(')', SyntaxNode)
s0 << r5
end
end
end
end
if s0.last.success?
r0 = (SyntaxNode).new(input, i0...index, s0)
r0.extend(Function0)
r0.extend(Function1)
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
node_cache[:function][start_index] = r0
return r0
end
module Variable0
def bind(value, env)
env.merge(name => value)
end
def to_s(env={})
env.has_key?(name) ? env[name].to_s : name
end
end
module Variable1
end
def _nt_variable
start_index = index
cached = node_cache[:variable][index]
if cached
@index = cached.interval.end
return cached
end
i0, s0 = index, []
i1 = index
r2 = _nt_keyword
if r2.success?
r1 = ParseFailure.new(input, i1)
else
self.index = i1
r1 = SyntaxNode.new(input, index...index)
end
s0 << r1
if r1.success?
r3 = super
r3.extend(Variable0)
s0 << r3
end
if s0.last.success?
r0 = (SyntaxNode).new(input, i0...index, s0)
r0.extend(Variable1)
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
node_cache[:variable][start_index] = r0
return r0
end
module Keyword0
end
def _nt_keyword
start_index = index
cached = node_cache[:keyword][index]
if cached
@index = cached.interval.end
return cached
end
i0, s0 = index, []
i1 = index
r2 = parse_terminal('if', SyntaxNode)
if r2.success?
r1 = r2
else
r3 = parse_terminal('else', SyntaxNode)
if r3.success?
r1 = r3
else
self.index = i1
r1 = ParseFailure.new(input, i1)
end
end
s0 << r1
if r1.success?
i4 = index
r5 = _nt_non_space_char
if r5.success?
r4 = ParseFailure.new(input, i4)
else
self.index = i4
r4 = SyntaxNode.new(input, index...index)
end
s0 << r4
end
if s0.last.success?
r0 = (SyntaxNode).new(input, i0...index, s0)
r0.extend(Keyword0)
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
node_cache[:keyword][start_index] = r0
return r0
end
module NonSpaceChar0
end
def _nt_non_space_char
start_index = index
cached = node_cache[:non_space_char][index]
if cached
@index = cached.interval.end
return cached
end
i0, s0 = index, []
i1 = index
r2 = parse_char_class(/[ \n]/, ' \n', SyntaxNode)
if r2.success?
r1 = ParseFailure.new(input, i1)
else
self.index = i1
r1 = SyntaxNode.new(input, index...index)
end
s0 << r1
if r1.success?
r3 = parse_anything(SyntaxNode)
s0 << r3
end
if s0.last.success?
r0 = (SyntaxNode).new(input, i0...index, s0)
r0.extend(NonSpaceChar0)
else
self.index = i0
r0 = ParseFailure.new(input, i0)
end
node_cache[:non_space_char][start_index] = r0
return r0
end
def _nt_space
start_index = index
cached = node_cache[:space][index]
if cached
@index = cached.interval.end
return cached
end
s0, i0 = [], index
loop do
r1 = parse_char_class(/[ \n]/, ' \n', SyntaxNode)
if r1.success?
s0 << r1
else
break
end
end
r0 = SyntaxNode.new(input, i0...index, s0)
node_cache[:space][start_index] = r0
return r0
end
end
class LambdaCalculusParser < Treetop::Runtime::CompiledParser
include LambdaCalculus
end