require 'polyglot' require 'treetop' require 'awesome_print' require 'rest_client' require File.join(File.dirname(__FILE__), 'scope') require File.join(File.dirname(__FILE__), 'extended_value') require File.join(File.dirname(__FILE__), 'webhook') 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 def self.all_symbols %w(+ - * / = set sum post >= > < <= and or if date get put lookup $lookup $head $tail $reverse round $round $days_ago $hours_ago $minutes_ago $append $id) end module Boolean def eval(scope = nil) 'true' == text_value end end module IntegerValue def eval(scope = nil) text_value.to_i end end module FloatValue def eval(scope = nil) text_value.to_f end end module StringValue def eval(scope = nil) text_value.gsub('"', '') 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) first_elem = statements.first.eval(scope) if first_elem.is_a? Function first_elem.call(scope, statements[1..-1]) else statements.map {|stat| stat.eval(scope) } end end end class Statement < Treetop::Runtime::SyntaxNode def data elements[1] end def eval(scope) data.eval(scope) 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 end