require 'polyglot' require 'treetop' require 'awesome_print' require File.join(File.dirname(__FILE__), 'scope') Treetop.load File.join(File.dirname(__FILE__), 'expressive_grammar.treetop') module Expressive def self.run(source_code, scope = TopLevel.new ) program = parse(source_code) program.eval(scope) end def self.parse(expressions) @parser ||= ::ExpressiveParser.new @parser.parse(expressions) end end module Boolean def eval(scope) 'true' == text_value end end module IntegerValue def eval(scope) text_value.to_i end end module FloatValue def eval(scope) text_value.to_f end end class Program < Treetop::Runtime::SyntaxNode def eval(scope) elements.map {|e| e.eval(scope) }.last end end class List < Treetop::Runtime::SyntaxNode def statements elements[1].elements.map {|e| e.data } end def eval(scope) function = statements.first.eval(scope) function.call(scope, statements[1..-1]) end end class Statement < Treetop::Runtime::SyntaxNode def data elements[1] end def eval(scope) data.eval(scope) end end # class SetNode < Treetop::Runtime::SyntaxNode # def pieces # [ :set, fieldname.text_value, value.text_value ] # end # end class Identifier < Treetop::Runtime::SyntaxNode def eval(scope) scope[text_value] end end class Function def initialize(&block) @block = block end def call(scope, statements) parameters = statements.map {|c| c.eval(scope)} @block.call(*parameters) end end class Syntax < Function def call(scope, statements) @block.call(scope, statements) end end