add the test code from crystal

This commit is contained in:
Torsten Ruger 2014-06-04 19:56:50 +03:00
parent ea19554b44
commit 7ab293cb62
17 changed files with 1051 additions and 0 deletions

38
test/README.markdown Normal file
View File

@ -0,0 +1,38 @@
Parsing
-------
Some sanity is emerging in the testing of parsers
(Parsers are fiddly in respect to space and order, small changes may and do have unexpected effects)
Parsing is a two step process with parslet:
- parse takes an input and outputs hashes/arrays with basic types
- tramsform takes the output of parse and generates an ast (as specified by the transformation)
A test tests both phases seperately and again together.
Each test must thus specify (as instance variables):
- the string input
- the parse output
- the transform output
Magic
-----
Test are grouped by functionality into cases (classes) and define methods test_*
Test cases must include ParserHelper, which includes the magic to write the 3 test methods for each
test method. See test_basic for easy example.
Example:
def test_number
@string_input = '42 '
@test_output = {:integer => '42'}
@transform_output = Parser::IntegerExpression.new(42)
@parser = @parser.integer
end
The first three lines define the data as described above.
The last line tells the parser what to parse. This is off couse only needed when a non-root rule is tested
and should be left out if possible.
As can be seen, there are no asserts. All asserting is done by the created methods, which call
the check_* methods in helper.

65
test/parse_helper.rb Normal file
View File

@ -0,0 +1,65 @@
require_relative "../helper"
require "parslet/convenience"
# remove the line numbers on assert fails, so it's easy to copy paste the result as the expected result
Parslet::Slice.class_eval do
def inspect
'"' + to_s + '"'
end
end
# Included in parser test will create tests methods
module ParserHelper
def self.included(base)
base.send :include, InstanceMethods #provides helpers and setup
base.send :extend, ClassMethods #gets the method creation going
end
module InstanceMethods
def setup
@parser = Parser::Crystal.new
@transform = Parser::Transform.new
end
# check that @string_input parses correctly to @parse_output
def check_parse
is = @parser.parse_with_debug(@string_input)
assert_equal @parse_output , is
end
#check that @parse_output transforms to @transform_output
def check_transform
is = @transform.apply @parse_output
#puts is.transform
assert_equal @transform_output , is
end
# check that @string_input parses and transforms to @transform_output
def check_ast
syntax = @parser.parse(@string_input)
is = @transform.apply(syntax)
#puts is.inspect
assert_equal @transform_output , is
end
end
module ClassMethods
# this creates test methods dynamically. For each test_* method we create
# three test_*[ast/parse/transf] methods that in turn check the three phases.
# runnable_methods is called by minitest to determine which tests to run
def runnable_methods
tests = []
public_instance_methods(true).grep(/^test_/).map(&:to_s).each do |test|
["ast" , "transform" , "parse"].each do |what|
name = "#{test}_#{what}"
tests << name
self.send(:define_method, name ) do
send(test)
send("check_#{what}")
end
end
end
tests
end
end
end

14
test/test_all.rb Normal file
View File

@ -0,0 +1,14 @@
require_relative "test_arguments"
require_relative "test_basic"
require_relative "test_call_site"
require_relative "test_class"
require_relative "test_compound"
require_relative "test_conditional"
require_relative "test_expressions"
require_relative "test_function_definition"
require_relative "test_module"
require_relative "test_operators"
require_relative "test_return"
require_relative "test_root"
require_relative "test_while"

37
test/test_arguments.rb Normal file
View File

@ -0,0 +1,37 @@
require_relative "helper"
class TestArguments < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_one_argument
@string_input = '(42)'
@parse_output = {:argument_list => [{:argument => {:integer => '42'}}] }
@transform_output = [Ast::IntegerExpression.new(42) ]
@parser = @parser.argument_list
end
def test_argument_list
@string_input = '(42, foo)'
@parse_output = {:argument_list => [{:argument => {:integer => '42'}},
{:argument => {:name => 'foo'}}]}
@transform_output = [Ast::IntegerExpression.new(42), Ast::NameExpression.new('foo')]
@parser = @parser.argument_list
end
def test_parmeter
@string_input = "(foo)"
@parse_output = {:parmeter_list => [{:parmeter => { :name => "foo"}} ]}
@transform_output = [Ast::NameExpression.new('foo')]
@parser = @parser.parmeter_list
end
def test_parmeter_list
@string_input = "( foo , bar)"
@parse_output = {:parmeter_list => [{:parmeter => { :name => "foo"}},
{:parmeter => { :name => "bar"}} ]}
@transform_output = [Ast::NameExpression.new('foo') , Ast::NameExpression.new('bar')]
@parser = @parser.parmeter_list
end
end

73
test/test_basic.rb Normal file
View File

@ -0,0 +1,73 @@
require_relative "helper"
class TestBasic < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_number
@string_input = '42 '
@parse_output = {:integer => '42'}
@transform_output = Ast::IntegerExpression.new(42)
@parser = @parser.integer
end
def test_name
@string_input = 'foo '
@parse_output = {:name => 'foo'}
@transform_output = Ast::NameExpression.new('foo')
@parser = @parser.name
end
def test_name_underscode_start
@string_input = '_bar '
@parse_output = {:name => '_bar'}
@transform_output = Ast::NameExpression.new('_bar')
@parser = @parser.name
end
def test_name_underscode_middle
@string_input = 'foo_bar '
@parse_output = {:name => 'foo_bar'}
@transform_output = Ast::NameExpression.new('foo_bar')
@parser = @parser.name
end
def test_instance_variable
@string_input = '@foo_bar '
@parse_output = {:instance_variable=>{:name=>"foo_bar"}}
@transform_output = Ast::VariableExpression.new(:foo_bar)
@parser = @parser.instance_variable
end
def test_module_name
@string_input = 'FooBar '
@parse_output = {:module_name=>"FooBar"}
@transform_output = Ast::ModuleName.new("FooBar")
@parser = @parser.module_name
end
def test_comment
out = "# i am a comment \n"
@string_input = out.dup #NEEDS the return, which is what delimits the comment
@parse_output = out
@transform_output = @parse_output #dont transform
@parser = @parser.comment
end
def test_string
@string_input = "\"hello\""
@parse_output = {:string=>[{:char=>"h"}, {:char=>"e"}, {:char=>"l"}, {:char=>"l"}, {:char=>"o"}]}
@transform_output = Ast::StringExpression.new('hello')
@parser = @parser.string
end
def test_string_escapes
out = 'hello \nyou'
@string_input = '"' + out + '"'
@parse_output = {:string=>[{:char=>"h"}, {:char=>"e"}, {:char=>"l"}, {:char=>"l"}, {:char=>"o"},
{:char=>" "}, {:char=>" "}, {:esc=>"n"}, {:char=>"y"}, {:char=>"o"}, {:char=>"u"}]}
@transform_output = Ast::StringExpression.new(out)
@parser = @parser.string
end
end

103
test/test_call_site.rb Normal file
View File

@ -0,0 +1,103 @@
require_relative "helper"
class TestCallSite < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_single_argument
@string_input = 'foo(42)'
@parse_output = {:call_site => {:name => 'foo'},
:argument_list => [{:argument => {:integer => '42'} }] }
@transform_output = Ast::CallSiteExpression.new :foo, [Ast::IntegerExpression.new(42)]
@parser = @parser.call_site
end
def test_single_self
@string_input = 'self.foo(42)'
@parse_output = {:receiver=>{:name=>"self"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
@transform_output = Ast::CallSiteExpression.new :foo, [Ast::IntegerExpression.new(42)]
@parser = @parser.call_site
end
def test_single_instance
@string_input = '@var.foo(42)'
@parse_output = {:receiver=>{:instance_variable=>{:name=>"var"}}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
@transform_output = Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(42)] ,Ast::VariableExpression.new(:var))
@parser = @parser.call_site
end
def test_single_name
@string_input = 'my_my.foo(42)'
@parse_output = {:receiver=>{:name=>"my_my"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
@transform_output = Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(42)] ,Ast::NameExpression.new("my_my"))
@parser = @parser.call_site
end
def test_single_class
@string_input = 'Object.foo(42)'
@parse_output = {:receiver=>{:module_name=>"Object"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
@transform_output = Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(42)] ,Ast::ModuleName.new("Object"))
@parser = @parser.call_site
end
def test_call_site_multi
@string_input = 'baz(42, foo)'
@parse_output = {:call_site => {:name => 'baz' },
:argument_list => [{:argument => {:integer => '42'}},
{:argument => {:name => 'foo'}}]}
@transform_output = Ast::CallSiteExpression.new :baz,
[Ast::IntegerExpression.new(42), Ast::NameExpression.new("foo") ]
@parser = @parser.call_site
end
def test_call_site_string
@string_input = 'puts( "hello")'
@parse_output = {:call_site => {:name => 'puts' },
:argument_list => [{:argument =>
{:string=>[{:char=>"h"}, {:char=>"e"}, {:char=>"l"}, {:char=>"l"}, {:char=>"o"}]}}]}
@transform_output = Ast::CallSiteExpression.new "puts", [Ast::StringExpression.new("hello")]
@parser = @parser.call_site
end
def test_call_operator
@string_input = 'puts( 3 + 5)'
@parse_output = {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:l=>{:integer=>"3"}, :o=>"+ ", :r=>{:integer=>"5"}}}]}
@transform_output = Ast::CallSiteExpression.new(:puts, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(5))] )
@parser = @parser.call_site
end
def test_call_two_operators
@string_input = 'puts(3 + 5 , a - 3)'
@parse_output = {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:l=>{:integer=>"3"}, :o=>"+ ", :r=>{:integer=>"5"}}}, {:argument=>{:l=>{:name=>"a"}, :o=>"- ", :r=>{:integer=>"3"}}}]}
@transform_output = Ast::CallSiteExpression.new(:puts, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(5)),Ast::OperatorExpression.new("-", Ast::NameExpression.new("a"),Ast::IntegerExpression.new(3))] )
@parser = @parser.call_site
end
def test_call_chaining
@string_input = 'puts(putint(3 + 5 ), a - 3)'
@parse_output = {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:call_site=>{:name=>"putint"}, :argument_list=>[{:argument=>{:l=>{:integer=>"3"}, :o=>"+ ", :r=>{:integer=>"5"}}}]}}, {:argument=>{:l=>{:name=>"a"}, :o=>"- ", :r=>{:integer=>"3"}}}]}
@transform_output = Ast::CallSiteExpression.new(:puts, [Ast::CallSiteExpression.new(:putint, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(5))] ),Ast::OperatorExpression.new("-", Ast::NameExpression.new("a"),Ast::IntegerExpression.new(3))] )
@parser = @parser.call_site
end
def test_call_chaining_name
@string_input = 'puts(name.putint(4), a)'
@parse_output = {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:receiver=>{:name=>"name"}, :call_site=>{:name=>"putint"}, :argument_list=>[{:argument=>{:integer=>"4"}}]}}, {:argument=>{:name=>"a"}}]}
@transform_output = Ast::CallSiteExpression.new(:puts, [Ast::CallSiteExpression.new(:putint, [Ast::IntegerExpression.new(4)] ,Ast::NameExpression.new("name")),Ast::NameExpression.new("a")] ,Ast::NameExpression.new("self"))
@parser = @parser.call_site
end
def test_call_chaining_class
@string_input = 'Class.new(self.get(4))'
@parse_output = {:receiver=>{:module_name=>"Class"}, :call_site=>{:name=>"new"}, :argument_list=>[{:argument=>{:receiver=>{:name=>"self"}, :call_site=>{:name=>"get"}, :argument_list=>[{:argument=>{:integer=>"4"}}]}}]}
@transform_output = Ast::CallSiteExpression.new(:new, [Ast::CallSiteExpression.new(:get, [Ast::IntegerExpression.new(4)] ,Ast::NameExpression.new("self"))] ,Ast::ModuleName.new("Class"))
@parser = @parser.call_site
end
def test_call_chaining_instance
@string_input = '@class.new(self.get(4))'
@parse_output = {:receiver=>{:instance_variable=>{:name=>"class"}}, :call_site=>{:name=>"new"}, :argument_list=>[{:argument=>{:receiver=>{:name=>"self"}, :call_site=>{:name=>"get"}, :argument_list=>[{:argument=>{:integer=>"4"}}]}}]}
@transform_output = Ast::CallSiteExpression.new(:new, [Ast::CallSiteExpression.new(:get, [Ast::IntegerExpression.new(4)] ,Ast::NameExpression.new("self"))] ,Ast::VariableExpression.new(:class))
@parser = @parser.call_site
end
end

74
test/test_class.rb Normal file
View File

@ -0,0 +1,74 @@
require_relative "helper"
class TestClassDef < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_simplest_class
@string_input = <<HERE
class Foo
5
end
HERE
@parse_output = {:module_name=>"Foo", :class_expressions=>[{:integer=>"5"}], :end=>"end"}
@transform_output = Ast::ClassExpression.new(:Foo ,[Ast::IntegerExpression.new(5)] )
@parser = @parser.class_definition
end
def test_class_ops
@string_input = <<HERE
class Opers
def foo(x)
@abba = 5
2 + 5
end
end
HERE
@parse_output = {:module_name=>"Opers", :class_expressions=>[{:function_name=>{:name=>"foo"}, :parmeter_list=>[{:parmeter=>{:name=>"x"}}], :expressions=>[{:l=>{:instance_variable=>{:name=>"abba"}}, :o=>"= ", :r=>{:integer=>"5"}}, {:l=>{:integer=>"2"}, :o=>"+ ", :r=>{:integer=>"5"}}], :end=>"end"}], :end=>"end"}
@transform_output = Ast::ClassExpression.new(:Opers ,[Ast::FunctionExpression.new(:foo, [Ast::NameExpression.new("x")] , [Ast::OperatorExpression.new("=", Ast::VariableExpression.new(:abba),Ast::IntegerExpression.new(5)),Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(2),Ast::IntegerExpression.new(5))] )] )
@parser = @parser.class_definition
end
def test_class_if
@string_input = <<HERE
class Ifi
def ofthen(n)
if(0)
isit = 42
else
maybenot = 667
end
end
end
HERE
@parse_output = {:module_name=>"Ifi", :class_expressions=>[{:function_name=>{:name=>"ofthen"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:if=>"if", :conditional=>{:integer=>"0"}, :if_true=>{:expressions=>[{:l=>{:name=>"isit"}, :o=>"= ", :r=>{:integer=>"42"}}], :else=>"else"}, :if_false=>{:expressions=>[{:l=>{:name=>"maybenot"}, :o=>"= ", :r=>{:integer=>"667"}}], :end=>"end"}}], :end=>"end"}], :end=>"end"}
@transform_output = Ast::ClassExpression.new(:Ifi ,[Ast::FunctionExpression.new(:ofthen, [Ast::NameExpression.new("n")] , [Ast::IfExpression.new(Ast::IntegerExpression.new(0), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("isit"),Ast::IntegerExpression.new(42))],[Ast::OperatorExpression.new("=", Ast::NameExpression.new("maybenot"),Ast::IntegerExpression.new(667))] )] )] )
@parser = @parser.class_definition
end
def test_class_function
@string_input = <<HERE
class Pifi
ofthen(3+4 , var)
def ofthen(n,m)
44
end
end
HERE
@parse_output = {:module_name=>"Pifi", :class_expressions=>[{:call_site=>{:name=>"ofthen"}, :argument_list=>[{:argument=>{:l=>{:integer=>"3"}, :o=>"+", :r=>{:integer=>"4"}}}, {:argument=>{:name=>"var"}}]}, {:function_name=>{:name=>"ofthen"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}, {:parmeter=>{:name=>"m"}}], :expressions=>[{:integer=>"44"}], :end=>"end"}], :end=>"end"}
@transform_output =Ast::ClassExpression.new(:Pifi ,[Ast::CallSiteExpression.new(:ofthen, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)),Ast::NameExpression.new(:var)] ), Ast::FunctionExpression.new(:ofthen, [Ast::NameExpression.new("n"),Ast::NameExpression.new("m")] , [Ast::IntegerExpression.new(44)] )] )
@parser = @parser.class_definition
end
def test_class_module
@string_input = <<HERE
class Foo
module Boo
funcall(3+4 , var)
end
end
HERE
@parse_output = {:module_name=>"Foo", :class_expressions=>[{:module_name=>"Boo", :module_expressions=>[{:call_site=>{:name=>"funcall"}, :argument_list=>[{:argument=>{:l=>{:integer=>"3"}, :o=>"+", :r=>{:integer=>"4"}}}, {:argument=>{:name=>"var"}}]}], :end=>"end"}], :end=>"end"}
@transform_output = Ast::ClassExpression.new(:Foo ,[Ast::ModuleExpression.new(:Boo ,[Ast::CallSiteExpression.new(:funcall, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)),Ast::NameExpression.new(:var)] )] )] )
@parser = @parser.class_definition
end
end

44
test/test_compound.rb Normal file
View File

@ -0,0 +1,44 @@
require_relative "helper"
class TestCompound < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_one_array
@string_input = '[42]'
@parse_output = {:array_constant=>[{:array_element=>{:integer=>"42"}}]}
@transform_output = Ast::ArrayExpression.new([Ast::IntegerExpression.new(42)])
@parser = @parser.array_constant
end
def test_array_list
@string_input = '[42, foo]'
@parse_output = {:array_constant=>[{:array_element=>{:integer=>"42"}}, {:array_element=>{:name=>"foo"}}]}
@transform_output = Ast::ArrayExpression.new([Ast::IntegerExpression.new(42), Ast::NameExpression.new("foo")])
@parser = @parser.array_constant
end
def test_array_ops
@string_input = '[ 3 + 4 , foo(22) ]'
@parse_output = {:array_constant=>[{:array_element=>{:l=>{:integer=>"3"}, :o=>"+ ", :r=>{:integer=>"4"}}}, {:array_element=>{:call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"22"}}]}}]}
@transform_output = Ast::ArrayExpression.new(
[Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)),
Ast::CallSiteExpression.new("foo", [Ast::IntegerExpression.new(22)] )])
@parser = @parser.array_constant
end
def test_hash
@string_input = '{ foo => 33 }'
@parse_output = {:hash_constant=>[{:hash_pair=>{:hash_key=>{:name=>"foo"}, :hash_value=>{:integer=>"33"}}}]}
@transform_output = Ast::HashExpression.new([Ast::AssociationExpression.new(Ast::NameExpression.new("foo") , Ast::IntegerExpression.new(33))])
@parser = @parser.hash_constant
end
def test_hash_list
@string_input = "{foo => 33 , bar => 42}"
@parse_output = {:hash_constant=>[{:hash_pair=>{:hash_key=>{:name=>"foo"}, :hash_value=>{:integer=>"33"}}}, {:hash_pair=>{:hash_key=>{:name=>"bar"}, :hash_value=>{:integer=>"42"}}}]}
@transform_output = Ast::HashExpression.new([Ast::AssociationExpression.new(Ast::NameExpression.new("foo") , Ast::IntegerExpression.new(33)),Ast::AssociationExpression.new(Ast::NameExpression.new("bar") , Ast::IntegerExpression.new(42))])
@parser = @parser.hash_constant
end
end

41
test/test_conditional.rb Normal file
View File

@ -0,0 +1,41 @@
require_relative "helper"
class TestConditional < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_conditional_brackets
check("(0)")
end
def test_conditional_no_brackets
check("0")
end
def check cond
input = <<HERE
42
else
667
end
HERE
@string_input = "if #{cond} " + input.chop!
@parse_output = {:if=>"if", :conditional=>{:integer=>"0"}, :if_true=>{:expressions=>[{:integer=>"42"}], :else=>"else"}, :if_false=>{:expressions=>[{:integer=>"667"}], :end=>"end"}}
@transform_output = Ast::IfExpression.new(Ast::IntegerExpression.new(0), [Ast::IntegerExpression.new(42)],[Ast::IntegerExpression.new(667)] )
@parser = @parser.conditional
end
def test_conditional_with_calls
@string_input = <<HERE
if(3 > var)
Object.initialize(3)
else
var.new(33)
end
HERE
@string_input.chop!
@parse_output = {:if=>"if", :conditional=>{:l=>{:integer=>"3"}, :o=>"> ", :r=>{:name=>"var"}}, :if_true=>{:expressions=>[{:receiver=>{:module_name=>"Object"}, :call_site=>{:name=>"initialize"}, :argument_list=>[{:argument=>{:integer=>"3"}}]}], :else=>"else"}, :if_false=>{:expressions=>[{:receiver=>{:name=>"var"}, :call_site=>{:name=>"new"}, :argument_list=>[{:argument=>{:integer=>"33"}}]}], :end=>"end"}}
@transform_output = Ast::IfExpression.new(Ast::OperatorExpression.new(">", Ast::IntegerExpression.new(3),Ast::NameExpression.new("var")), [Ast::CallSiteExpression.new(:initialize, [Ast::IntegerExpression.new(3)] ,Ast::ModuleName.new("Object"))],[Ast::CallSiteExpression.new(:new, [Ast::IntegerExpression.new(33)] ,Ast::NameExpression.new("var"))] )
@parser = @parser.conditional
end
end

40
test/test_expressions.rb Normal file
View File

@ -0,0 +1,40 @@
require_relative "helper"
class TestExpressions < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_expression_else
@string_input = <<HERE
dud
fuu(3)
else
HERE
@string_input.chop!
@parse_output = {:expressions=>[{:name=>"dud"},
{:call_site=>{:name=>"fuu"}, :argument_list=>[{:argument=>{:integer=>"3"}}]}],
:else=>"else"}
@transform_output ={:expressions=>[Ast::NameExpression.new("dud"),
Ast::CallSiteExpression.new("fuu", [Ast::IntegerExpression.new(3)] )], :else=>"else"}
@parser = @parser.expressions_else
end
def test_expression_end
@string_input = <<HERE
name
call(4,6)
end
HERE
@string_input.chop!
@parse_output = {:expressions=>[{:name=>"name"},
{:call_site=>{:name=>"call"}, :argument_list=>[{:argument=>{:integer=>"4"}}, {:argument=>{:integer=>"6"}}]}],
:end=>"end"}
@transform_output = {:expressions=>[Ast::NameExpression.new("name"),
Ast::CallSiteExpression.new("call", [Ast::IntegerExpression.new(4),Ast::IntegerExpression.new(6)] )],
:end=>"end"}
@parser = @parser.expressions_end
end
end

26
test/test_fails.rb Normal file
View File

@ -0,0 +1,26 @@
require_relative "helper"
# some cases that fail, and fail badly.
# These make the parse "hang", ie there is some looping going on in the parser, but not straight down, as theey don't
# throw even StackError
# Annoyingly, the user error is quite small, a missing bracket or things
class TestFails < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_fail_function
@string_input = <<HERE
class Foo
def bar
4
end
end
HERE
@parse_output = nil
@transform_output = nil
@parser = @parser.root
end
end

View File

@ -0,0 +1,130 @@
require_relative "helper"
class TestFunctionDefinition < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_simplest_function
@string_input = <<HERE
def foo(x)
5
end
HERE
@parse_output = {:function_name=>{:name=>"foo"}, :parmeter_list=>[{:parmeter=>{:name=>"x"}}], :expressions=>[{:integer=>"5"}], :end=>"end"}
@transform_output = Ast::FunctionExpression.new(:foo, [Ast::NameExpression.new("x")] , [Ast::IntegerExpression.new(5)] )
@parser = @parser.function_definition
end
def test_class_function
@string_input = <<HERE
def String.length(x)
@length
end
HERE
@parse_output = {:receiver=>{:module_name=>"String"}, :function_name=>{:name=>"length"}, :parmeter_list=>[{:parmeter=>{:name=>"x"}}], :expressions=>[{:instance_variable=>{:name=>"length"}}], :end=>"end"}
@transform_output = Ast::FunctionExpression.new(:length, [Ast::NameExpression.new("x")] , [Ast::VariableExpression.new(:length)] ,Ast::ModuleName.new("String") )
@parser = @parser.function_definition
end
def test_function_ops
@string_input = <<HERE
def foo(x)
abba = 5
2 + 5
end
HERE
@parse_output = {:function_name=>{:name=>"foo"}, :parmeter_list=>[{:parmeter=>{:name=>"x"}}], :expressions=>[{:l=>{:name=>"abba"}, :o=>"= ", :r=>{:integer=>"5"}}, {:l=>{:integer=>"2"}, :o=>"+ ", :r=>{:integer=>"5"}}], :end=>"end"}
@transform_output = Ast::FunctionExpression.new(:foo, [Ast::NameExpression.new("x")] , [Ast::OperatorExpression.new("=", Ast::NameExpression.new("abba"),Ast::IntegerExpression.new(5)),Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(2),Ast::IntegerExpression.new(5))] ,nil )
@parser = @parser.function_definition
end
def test_function_if
@string_input = <<HERE
def ofthen(n)
if(0)
isit = 42
else
maybenot = 667
end
end
HERE
@parse_output = {:function_name=>{:name=>"ofthen"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:if=>"if", :conditional=>{:integer=>"0"}, :if_true=>{:expressions=>[{:l=>{:name=>"isit"}, :o=>"= ", :r=>{:integer=>"42"}}], :else=>"else"}, :if_false=>{:expressions=>[{:l=>{:name=>"maybenot"}, :o=>"= ", :r=>{:integer=>"667"}}], :end=>"end"}}], :end=>"end"}
@transform_output = Ast::FunctionExpression.new(:ofthen, [Ast::NameExpression.new("n")] , [Ast::IfExpression.new(Ast::IntegerExpression.new(0), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("isit"),Ast::IntegerExpression.new(42))],[Ast::OperatorExpression.new("=", Ast::NameExpression.new("maybenot"),Ast::IntegerExpression.new(667))] )] ,nil )
@parser = @parser.function_definition
end
def test_function_return
@string_input = <<HERE
def retvar(n)
i = 5
return i
end
HERE
@parse_output = {:function_name=>{:name=>"retvar"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:l=>{:name=>"i"}, :o=>"= ", :r=>{:integer=>"5"}}, {:return=>"return", :return_expression=>{:name=>"i"}}], :end=>"end"}
@transform_output = Ast::FunctionExpression.new(:retvar, [Ast::NameExpression.new("n")] , [Ast::OperatorExpression.new("=", Ast::NameExpression.new("i"),Ast::IntegerExpression.new(5)),Ast::ReturnExpression.new(Ast::NameExpression.new("i") )] )
@parser = @parser.function_definition
end
def test_function_return_if
@string_input = <<HERE
def retvar(n)
if( n > 5)
return 10
else
return 20
end
end
HERE
@parse_output = {:function_name=>{:name=>"retvar"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:if=>"if", :conditional=>{:l=>{:name=>"n"}, :o=>"> ", :r=>{:integer=>"5"}}, :if_true=>{:expressions=>[{:return=>"return", :return_expression=>{:integer=>"10"}}], :else=>"else"}, :if_false=>{:expressions=>[{:return=>"return", :return_expression=>{:integer=>"20"}}], :end=>"end"}}], :end=>"end"}
@transform_output = Ast::FunctionExpression.new(:retvar, [Ast::NameExpression.new("n")] , [Ast::IfExpression.new(Ast::OperatorExpression.new(">", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(5)), [Ast::ReturnExpression.new(Ast::IntegerExpression.new(10) )],[Ast::ReturnExpression.new(Ast::IntegerExpression.new(20) )] )] )
@parser = @parser.function_definition
end
def test_function_return_while
@string_input = <<HERE
def retvar(n)
while( n > 5) do
n = n + 1
return n
end
end
HERE
@parse_output = {:function_name=>{:name=>"retvar"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:while=>"while", :while_cond=>{:l=>{:name=>"n"}, :o=>"> ", :r=>{:integer=>"5"}}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"n"}, :o=>"= ", :r=>{:l=>{:name=>"n"}, :o=>"+ ", :r=>{:integer=>"1"}}}, {:return=>"return", :return_expression=>{:name=>"n"}}], :end=>"end"}}], :end=>"end"}
@transform_output = Ast::FunctionExpression.new(:retvar, [Ast::NameExpression.new("n")] , [Ast::WhileExpression.new(Ast::OperatorExpression.new(">", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(5)), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("n"),Ast::OperatorExpression.new("+", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1))), Ast::ReturnExpression.new(Ast::NameExpression.new("n") )] )] )
@parser = @parser.function_definition
end
def test_function_while
@string_input = <<HERE
def fibonaccit(n)
a = 0
while (n) do
some = 43
other = some * 4
end
end
HERE
@parse_output = {:function_name=>{:name=>"fibonaccit"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:l=>{:name=>"a"}, :o=>"= ", :r=>{:integer=>"0"}}, {:while=>"while", :while_cond=>{:name=>"n"}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"some"}, :o=>"= ", :r=>{:integer=>"43"}}, {:l=>{:name=>"other"}, :o=>"= ", :r=>{:l=>{:name=>"some"}, :o=>"* ", :r=>{:integer=>"4"}}}], :end=>"end"}}], :end=>"end"}
@transform_output = Ast::FunctionExpression.new(:fibonaccit, [Ast::NameExpression.new("n")] , [Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::IntegerExpression.new(0)),Ast::WhileExpression.new(Ast::NameExpression.new("n"), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("some"),Ast::IntegerExpression.new(43)), Ast::OperatorExpression.new("=", Ast::NameExpression.new("other"),Ast::OperatorExpression.new("*", Ast::NameExpression.new("some"),Ast::IntegerExpression.new(4)))] )] ,nil )
@parser = @parser.function_definition
end
def test_function_big_while
@string_input = <<HERE
def fibonaccit(n)
a = 0
b = 1
while( n > 1 ) do
tmp = a
a = b
b = tmp + b
puts(b)
n = n - 1
end
end
HERE
@parse_output = {:function_name=>{:name=>"fibonaccit"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:l=>{:name=>"a"}, :o=>"= ", :r=>{:integer=>"0"}}, {:l=>{:name=>"b"}, :o=>"= ", :r=>{:integer=>"1"}}, {:while=>"while", :while_cond=>{:l=>{:name=>"n"}, :o=>"> ", :r=>{:integer=>"1"}}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, {:l=>{:name=>"a"}, :o=>"= ", :r=>{:name=>"b"}}, {:l=>{:name=>"b"}, :o=>"= ", :r=>{:l=>{:name=>"tmp"}, :o=>"+ ", :r=>{:name=>"b"}}}, {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"b"}}]}, {:l=>{:name=>"n"}, :o=>"= ", :r=>{:l=>{:name=>"n"}, :o=>"- ", :r=>{:integer=>"1"}}}], :end=>"end"}}], :end=>"end"}
@transform_output = Ast::FunctionExpression.new(:fibonaccit, [Ast::NameExpression.new("n")] , [Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::IntegerExpression.new(0)),Ast::OperatorExpression.new("=", Ast::NameExpression.new("b"),Ast::IntegerExpression.new(1)),Ast::WhileExpression.new(Ast::OperatorExpression.new(">", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::NameExpression.new("b")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("b"),Ast::OperatorExpression.new("+", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("b"))), Ast::CallSiteExpression.new("puts", [Ast::NameExpression.new("b")] ), Ast::OperatorExpression.new("=", Ast::NameExpression.new("n"),Ast::OperatorExpression.new("-", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)))] )] )
@parser = @parser.function_definition
end
end

86
test/test_module.rb Normal file
View File

@ -0,0 +1,86 @@
require_relative "helper"
class TestModuleDef < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_simplest_module
@string_input = <<HERE
module Simple
5
end
HERE
@parse_output = {:module_name=>"Simple", :module_expressions=>[{:integer=>"5"}], :end=>"end"}
@transform_output = Ast::ModuleExpression.new(:Simple ,[Ast::IntegerExpression.new(5)] )
@parser = @parser.module_definition
end
def test_module_ops
@string_input = <<HERE
module Opers
def foo(x)
abba = 5
2 + 5
end
end
HERE
@parse_output = {:module_name=>"Opers", :module_expressions=>[{:function_name=>{:name=>"foo"}, :parmeter_list=>[{:parmeter=>{:name=>"x"}}], :expressions=>[{:l=>{:name=>"abba"}, :o=>"= ", :r=>{:integer=>"5"}}, {:l=>{:integer=>"2"}, :o=>"+ ", :r=>{:integer=>"5"}}], :end=>"end"}], :end=>"end"}
@transform_output = Ast::ModuleExpression.new(:Opers ,[Ast::FunctionExpression.new(:foo, [Ast::NameExpression.new("x")] , [Ast::OperatorExpression.new("=", Ast::NameExpression.new("abba"),Ast::IntegerExpression.new(5)),Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(2),Ast::IntegerExpression.new(5))] )] )
@parser = @parser.module_definition
end
def test_module_assign_instance
@string_input = <<HERE
module Opers
@abba = 5
end
HERE
@parse_output = {:module_name=>"Opers", :module_expressions=>[{:l=>{:instance_variable=>{:name=>"abba"}}, :o=>"= ", :r=>{:integer=>"5"}}], :end=>"end"}
@transform_output = Ast::ModuleExpression.new(:Opers ,[Ast::OperatorExpression.new("=", Ast::VariableExpression.new(:abba),Ast::IntegerExpression.new(5))] )
@parser = @parser.module_definition
end
def test_module_if
@string_input = <<HERE
module Foo
def ofthen(n)
if(0)
isit = 42
else
maybenot = 667
end
end
end
HERE
@parse_output = {:module_name=>"Foo", :module_expressions=>[{:function_name=>{:name=>"ofthen"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:if=>"if", :conditional=>{:integer=>"0"}, :if_true=>{:expressions=>[{:l=>{:name=>"isit"}, :o=>"= ", :r=>{:integer=>"42"}}], :else=>"else"}, :if_false=>{:expressions=>[{:l=>{:name=>"maybenot"}, :o=>"= ", :r=>{:integer=>"667"}}], :end=>"end"}}], :end=>"end"}], :end=>"end"}
@transform_output = Ast::ModuleExpression.new(:Foo ,[Ast::FunctionExpression.new(:ofthen, [Ast::NameExpression.new("n")] , [Ast::IfExpression.new(Ast::IntegerExpression.new(0), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("isit"),Ast::IntegerExpression.new(42))],[Ast::OperatorExpression.new("=", Ast::NameExpression.new("maybenot"),Ast::IntegerExpression.new(667))] )] )] )
@parser = @parser.module_definition
end
def test_module_function
@string_input = <<HERE
module Soho
ofthen(3+4 , var)
def ofthen(n,m)
44
end
end
HERE
@parse_output = {:module_name=>"Soho", :module_expressions=>[{:call_site=>{:name=>"ofthen"}, :argument_list=>[{:argument=>{:l=>{:integer=>"3"}, :o=>"+", :r=>{:integer=>"4"}}}, {:argument=>{:name=>"var"}}]}, {:function_name=>{:name=>"ofthen"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}, {:parmeter=>{:name=>"m"}}], :expressions=>[{:integer=>"44"}], :end=>"end"}], :end=>"end"}
@transform_output = Ast::ModuleExpression.new(:Soho ,[Ast::CallSiteExpression.new(:ofthen, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)),Ast::NameExpression.new("var")] ), Ast::FunctionExpression.new(:ofthen, [Ast::NameExpression.new("n"),Ast::NameExpression.new("m")] , [Ast::IntegerExpression.new(44)] )] )
@parser = @parser.module_definition
end
def test_module_class
@string_input = <<HERE
module Foo
class Bar
funcall(3+4 , var)
end
end
HERE
@parse_output = {:module_name=>"Foo", :module_expressions=>[{:module_name=>"Bar", :class_expressions=>[{:call_site=>{:name=>"funcall"}, :argument_list=>[{:argument=>{:l=>{:integer=>"3"}, :o=>"+", :r=>{:integer=>"4"}}}, {:argument=>{:name=>"var"}}]}], :end=>"end"}], :end=>"end"}
@transform_output = Ast::ModuleExpression.new(:Foo ,[Ast::ClassExpression.new(:Bar ,[Ast::CallSiteExpression.new(:funcall, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)),Ast::NameExpression.new("var")] )] )] )
@parser = @parser.module_definition
end
end

86
test/test_operators.rb Normal file
View File

@ -0,0 +1,86 @@
require_relative "helper"
class TestExpressions < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def simple_op op
@string_input = "5 #{op} 3"
@parse_output = {:l=>{:integer=>"5"}, :o=>"#{op} ", :r=>{:integer=>"3"}}
@transform_output = Ast::OperatorExpression.new(op, Ast::IntegerExpression.new(5),Ast::IntegerExpression.new(3))
@parser = @parser.operator_expression
end
def test_simple_multiply
simple_op "*"
end
def test_simple_devide
simple_op "/"
end
def test_simple_plus
simple_op "+"
end
def test_simple_minus
simple_op "-"
end
def test_simple_greater
simple_op ">"
end
def test_simple_smaller
simple_op "<"
end
def test_op_variable
@string_input = "a + 35"
@parse_output = {:l=>{:name=>"a"}, :o=>"+ ", :r=>{:integer=>"35"}}
@transform_output = Ast::OperatorExpression.new("+", Ast::NameExpression.new(:a),Ast::IntegerExpression.new(35))
@parser = @parser.operator_expression
end
def test_op_two_variable
@string_input = "a - b"
@parse_output = {:l=>{:name=>"a"}, :o=>"- ", :r=>{:name=>"b"}}
@transform_output = Ast::OperatorExpression.new("-", Ast::NameExpression.new(:a),Ast::NameExpression.new("b"))
@parser = @parser.operator_expression
end
def test_op_instance_variable
@string_input = "@a - 5"
@parse_output = {:l=>{:instance_variable=>{:name=>"a"}}, :o=>"- ", :r=>{:integer=>"5"}}
@transform_output = Ast::OperatorExpression.new("-", Ast::VariableExpression.new(:a),Ast::IntegerExpression.new(5))
@parser = @parser.operator_expression
end
def test_op_variable_string
@string_input = 'a - "st"'
@parse_output = {:l=>{:name=>"a"}, :o=>"- ", :r=>{:string=>[{:char=>"s"}, {:char=>"t"}]}}
@transform_output = Ast::OperatorExpression.new("-", Ast::NameExpression.new(:a),Ast::StringExpression.new("st"))
@parser = @parser.operator_expression
end
def test_two_same_ops
@string_input = '2 + 3 + 4'
@parse_output = {:l=>{:l=>{:integer=>"2"}, :o=>"+ ", :r=>{:integer=>"3"}}, :o=>"+ ", :r=>{:integer=>"4"}}
@transform_output = Ast::OperatorExpression.new("+", Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(2),Ast::IntegerExpression.new(3)),Ast::IntegerExpression.new(4))
@parser = @parser.operator_expression
end
def test_two_different_ops
@string_input = '2 + 3 * 4'
@parse_output = {:l=>{:integer=>"2"}, :o=>"+ ", :r=>{:l=>{:integer=>"3"}, :o=>"* ", :r=>{:integer=>"4"}}}
@transform_output = Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(2),Ast::OperatorExpression.new("*", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)))
@parser = @parser.operator_expression
end
def test_two_different_ops_order
@string_input = '2 * 3 + 4'
@parse_output = {:l=>{:l=>{:integer=>"2"}, :o=>"* ", :r=>{:integer=>"3"}}, :o=>"+ ", :r=>{:integer=>"4"}}
@transform_output = Ast::OperatorExpression.new("+", Ast::OperatorExpression.new("*", Ast::IntegerExpression.new(2),Ast::IntegerExpression.new(3)),Ast::IntegerExpression.new(4))
@parser = @parser.operator_expression
end
def test_assignment
@string_input = "a = 5"
@parse_output = {:l=>{:name=>"a"}, :o=>"= ", :r=>{:integer=>"5"}}
@transform_output = Ast::OperatorExpression.new("=", Ast::NameExpression.new(:a),Ast::IntegerExpression.new(5))
@parser = @parser.operator_expression
end
def test_assignment_instance
@string_input = "@a = 5"
@parse_output = {:l=>{:instance_variable=>{:name=>"a"}}, :o=>"= ", :r=>{:integer=>"5"}}
@transform_output = Ast::OperatorExpression.new("=", Ast::VariableExpression.new(:a),Ast::IntegerExpression.new(5))
@parser = @parser.operator_expression
end
end

28
test/test_return.rb Normal file
View File

@ -0,0 +1,28 @@
require_relative "helper"
class TestReturn < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_return_int
@string_input = 'return 42'
@parse_output = {:return=>"return", :return_expression=>{:integer=>"42"}}
@transform_output = Ast::ReturnExpression.new(Ast::IntegerExpression.new(42) )
@parser = @parser.simple_return
end
def test_return_variable
@string_input = 'return foo'
@parse_output = {:return=>"return", :return_expression=>{:name=>"foo"}}
@transform_output = Ast::ReturnExpression.new(Ast::NameExpression.new("foo") )
@parser = @parser.simple_return
end
def test_return_string
@string_input = 'return "hello"'
@parse_output = {:return=>"return", :return_expression=>{:string=>[{:char=>"h"}, {:char=>"e"}, {:char=>"l"}, {:char=>"l"}, {:char=>"o"}]}}
@transform_output = Ast::ReturnExpression.new(Ast::StringExpression.new("hello") )
@parser = @parser.simple_return
end
end

118
test/test_root.rb Normal file
View File

@ -0,0 +1,118 @@
require_relative "helper"
class TestRoot < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_double_root
@string_input = <<HERE
def foo(x)
a = 5
end
foo( 3 )
HERE
@parse_output = [{:function_name=>{:name=>"foo"},
:parmeter_list=>[{:parmeter=>{:name=>"x"}}],
:expressions=>[{:l=>{:name=>"a"}, :o=>"= ", :r=>{:integer=>"5"}}], :end=>"end"},
{:call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"3"}}]}]
@transform_output = [Ast::FunctionExpression.new(:foo,
[Ast::NameExpression.new("x")] ,
[Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::IntegerExpression.new(5))] ),
Ast::CallSiteExpression.new("foo", [Ast::IntegerExpression.new(3)] )]
end
def test_comments
@string_input = <<HERE
def foo(x) #here
a = 0 # a == r1
b = 1 # b = r2
while(n<1) do #comment
tmp = a # r3 <- r1
a = b # r1 <- r2
b = tmp + b # r4 = r2 + r3 (r4 transient) r2 <- r4
putstring(b)
n = n - 1 #me
end #no
end #anywhere
foo( 3 ) #and more
HERE
@parse_output = [{:function_name=>{:name=>"foo"}, :parmeter_list=>[{:parmeter=>{:name=>"x"}}], :expressions=>[{:l=>{:name=>"a"}, :o=>"= ", :r=>{:integer=>"0"}}, {:l=>{:name=>"b"}, :o=>"= ", :r=>{:integer=>"1"}}, {:while=>"while", :while_cond=>{:l=>{:name=>"n"}, :o=>"<", :r=>{:integer=>"1"}}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, {:l=>{:name=>"a"}, :o=>"= ", :r=>{:name=>"b"}}, {:l=>{:name=>"b"}, :o=>"= ", :r=>{:l=>{:name=>"tmp"}, :o=>"+ ", :r=>{:name=>"b"}}}, {:call_site=>{:name=>"putstring"}, :argument_list=>[{:argument=>{:name=>"b"}}]}, {:l=>{:name=>"n"}, :o=>"= ", :r=>{:l=>{:name=>"n"}, :o=>"- ", :r=>{:integer=>"1"}}}], :end=>"end"}}], :end=>"end"}, {:call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"3"}}]}]
@transform_output = [Ast::FunctionExpression.new(:foo, [Ast::NameExpression.new("x")] , [Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::IntegerExpression.new(0)),Ast::OperatorExpression.new("=", Ast::NameExpression.new("b"),Ast::IntegerExpression.new(1)),Ast::WhileExpression.new(Ast::OperatorExpression.new("<", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::NameExpression.new("b")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("b"),Ast::OperatorExpression.new("+", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("b"))), Ast::CallSiteExpression.new(:putstring, [Ast::NameExpression.new("b")] ), Ast::OperatorExpression.new("=", Ast::NameExpression.new("n"),Ast::OperatorExpression.new("-", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)))] )] ), Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(3)] )]
end
def test_fibo1
@string_input = <<HERE
def fibonaccit(n)
a = 0
b = 1
while( n > 1 ) do
tmp = a
a = b
b = tmp + b
puts(b)
n = n - 1
end
end
fibonaccit( 10 )
HERE
@parse_output = [{:function_name=>{:name=>"fibonaccit"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:l=>{:name=>"a"}, :o=>"= ", :r=>{:integer=>"0"}}, {:l=>{:name=>"b"}, :o=>"= ", :r=>{:integer=>"1"}}, {:while=>"while", :while_cond=>{:l=>{:name=>"n"}, :o=>"> ", :r=>{:integer=>"1"}}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, {:l=>{:name=>"a"}, :o=>"= ", :r=>{:name=>"b"}}, {:l=>{:name=>"b"}, :o=>"= ", :r=>{:l=>{:name=>"tmp"}, :o=>"+ ", :r=>{:name=>"b"}}}, {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"b"}}]}, {:l=>{:name=>"n"}, :o=>"= ", :r=>{:l=>{:name=>"n"}, :o=>"- ", :r=>{:integer=>"1"}}}], :end=>"end"}}], :end=>"end"}, {:call_site=>{:name=>"fibonaccit"}, :argument_list=>[{:argument=>{:integer=>"10"}}]}]
@transform_output = [Ast::FunctionExpression.new(:fibonaccit, [Ast::NameExpression.new("n")] , [Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::IntegerExpression.new(0)),Ast::OperatorExpression.new("=", Ast::NameExpression.new("b"),Ast::IntegerExpression.new(1)),Ast::WhileExpression.new(Ast::OperatorExpression.new(">", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::NameExpression.new("b")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("b"),Ast::OperatorExpression.new("+", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("b"))), Ast::CallSiteExpression.new("puts", [Ast::NameExpression.new("b")] ), Ast::OperatorExpression.new("=", Ast::NameExpression.new("n"),Ast::OperatorExpression.new("-", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)))] )] ), Ast::CallSiteExpression.new("fibonaccit", [Ast::IntegerExpression.new(10)] )]
end
def test_module_method
@string_input = <<HERE
module Fibo
def fibonaccit(n)
a = 0
end
fibonaccit( 10 )
end
HERE
@parse_output = [{:module_name=>"Fibo", :module_expressions=>[{:function_name=>{:name=>"fibonaccit"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:l=>{:name=>"a"}, :o=>"= ", :r=>{:integer=>"0"}}], :end=>"end"}, {:call_site=>{:name=>"fibonaccit"}, :argument_list=>[{:argument=>{:integer=>"10"}}]}], :end=>"end"}]
@transform_output = [Ast::ModuleExpression.new(:Fibo ,[Ast::FunctionExpression.new(:fibonaccit, [Ast::NameExpression.new("n")] , [Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::IntegerExpression.new(0))] ), Ast::CallSiteExpression.new(:fibonaccit, [Ast::IntegerExpression.new(10)] )] )]
end
def test_module_assignment
@string_input = <<HERE
module Fibo
a = 5 + foo
bar( b , a , r)
end
HERE
@parse_output = [{:module_name=>"Fibo", :module_expressions=>[{:l=>{:name=>"a"}, :o=>"= ", :r=>{:l=>{:integer=>"5"}, :o=>"+ ", :r=>{:name=>"foo"}}}, {:call_site=>{:name=>"bar"}, :argument_list=>[{:argument=>{:name=>"b"}}, {:argument=>{:name=>"a"}}, {:argument=>{:name=>"r"}}]}], :end=>"end"}]
@transform_output = [Ast::ModuleExpression.new(:Fibo ,[Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(5),Ast::NameExpression.new("foo"))), Ast::CallSiteExpression.new(:bar, [Ast::NameExpression.new("b"),Ast::NameExpression.new("a"),Ast::NameExpression.new("r")] )] )]
end
def test_module_class
@string_input = <<HERE
module FooBo
class Bar
a = 5 + foo
end
end
HERE
@parse_output = [{:module_name=>"FooBo", :module_expressions=>[{:module_name=>"Bar", :class_expressions=>[{:l=>{:name=>"a"}, :o=>"= ", :r=>{:l=>{:integer=>"5"}, :o=>"+ ", :r=>{:name=>"foo"}}}], :end=>"end"}], :end=>"end"}]
@transform_output = [Ast::ModuleExpression.new(:FooBo ,[Ast::ClassExpression.new(:Bar ,[Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(5),Ast::NameExpression.new("foo")))] )] )]
end
def test_class_method
@string_input = <<HERE
class FooBo
Bar.call(35)
end
HERE
@parse_output = [{:module_name=>"FooBo", :class_expressions=>[{:receiver=>{:module_name=>"Bar"}, :call_site=>{:name=>"call"}, :argument_list=>[{:argument=>{:integer=>"35"}}]}], :end=>"end"}]
@transform_output = [Ast::ClassExpression.new(:FooBo ,[Ast::CallSiteExpression.new(:call, [Ast::IntegerExpression.new(35)] ,Ast::ModuleName.new("Bar"))] )]
end
end

48
test/test_while.rb Normal file
View File

@ -0,0 +1,48 @@
require_relative "helper"
class TestWhile < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_while
@string_input = <<HERE
while(1) do
tmp = a
puts(b)
end
HERE
@string_input.chop!
@parse_output = {:while=>"while", :while_cond=>{:integer=>"1"}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"b"}}]}], :end=>"end"}}
@transform_output = Ast::WhileExpression.new(Ast::IntegerExpression.new(1), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), Ast::CallSiteExpression.new(:puts, [Ast::NameExpression.new("b")] ,Ast::NameExpression.new("self"))] )
@parser = @parser.while_do
end
def test_while_method
@string_input = <<HERE
while(1) do
tmp = String.new()
tmp.puts(i)
end
HERE
@string_input.chop!
@parse_output = {:while=>"while", :while_cond=>{:integer=>"1"}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:receiver=>{:module_name=>"String"}, :call_site=>{:name=>"new"}, :argument_list=>[]}}, {:receiver=>{:name=>"tmp"}, :call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"i"}}]}], :end=>"end"}}
@transform_output = Ast::WhileExpression.new(Ast::IntegerExpression.new(1), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::CallSiteExpression.new(:new, [] ,Ast::ModuleName.new("String"))), Ast::CallSiteExpression.new(:puts, [Ast::NameExpression.new("i")] ,Ast::NameExpression.new("tmp"))] )
@parser = @parser.while_do
end
def test_big_while
@string_input = <<HERE
while( n > 1) do
tmp = a
a = b
b = tmp + b
puts(b)
n = n - 1
end
HERE
@string_input.chop!
@parse_output = {:while=>"while", :while_cond=>{:l=>{:name=>"n"}, :o=>"> ", :r=>{:integer=>"1"}}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, {:l=>{:name=>"a"}, :o=>"= ", :r=>{:name=>"b"}}, {:l=>{:name=>"b"}, :o=>"= ", :r=>{:l=>{:name=>"tmp"}, :o=>"+ ", :r=>{:name=>"b"}}}, {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"b"}}]}, {:l=>{:name=>"n"}, :o=>"= ", :r=>{:l=>{:name=>"n"}, :o=>"- ", :r=>{:integer=>"1"}}}], :end=>"end"}}
@transform_output = Ast::WhileExpression.new(Ast::OperatorExpression.new(">", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::NameExpression.new("b")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("b"),Ast::OperatorExpression.new("+", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("b"))), Ast::CallSiteExpression.new(:puts, [Ast::NameExpression.new("b")] ,Ast::NameExpression.new("self")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("n"),Ast::OperatorExpression.new("-", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)))] )
@parser = @parser.while_do
end
end