gobstones 0.0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.simplecov +3 -0
- data/.travis.yml +4 -0
- data/CHANGELOG +4 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +47 -0
- data/LICENSE +675 -0
- data/README.md +17 -0
- data/Rakefile +4 -0
- data/bin/gobstones +12 -0
- data/gobstones.gemspec +24 -0
- data/lib/gobstones/cli/board_template +39 -0
- data/lib/gobstones/cli/printer.rb +106 -0
- data/lib/gobstones/cli/runner.rb +52 -0
- data/lib/gobstones/extensions/all.rb +2 -0
- data/lib/gobstones/extensions/boolean.rb +17 -0
- data/lib/gobstones/extensions/fixnum.rb +9 -0
- data/lib/gobstones/lang/all.rb +5 -0
- data/lib/gobstones/lang/commands/all.rb +13 -0
- data/lib/gobstones/lang/commands/assignments.rb +29 -0
- data/lib/gobstones/lang/commands/boom_cmd.rb +28 -0
- data/lib/gobstones/lang/commands/command_block.rb +37 -0
- data/lib/gobstones/lang/commands/conditional_cmd.rb +27 -0
- data/lib/gobstones/lang/commands/if_cmd.rb +38 -0
- data/lib/gobstones/lang/commands/ir_al_origen_cmd.rb +19 -0
- data/lib/gobstones/lang/commands/mover_cmd.rb +25 -0
- data/lib/gobstones/lang/commands/poner_cmd.rb +31 -0
- data/lib/gobstones/lang/commands/procedure_call.rb +23 -0
- data/lib/gobstones/lang/commands/repeat_with_cmd.rb +73 -0
- data/lib/gobstones/lang/commands/sacar_cmd.rb +31 -0
- data/lib/gobstones/lang/commands/skip_cmd.rb +19 -0
- data/lib/gobstones/lang/commands/vaciar_tablero_cmd.rb +19 -0
- data/lib/gobstones/lang/commands/while_cmd.rb +25 -0
- data/lib/gobstones/lang/definitions/all.rb +4 -0
- data/lib/gobstones/lang/definitions/definition.rb +32 -0
- data/lib/gobstones/lang/definitions/definition_call.rb +24 -0
- data/lib/gobstones/lang/definitions/function.rb +14 -0
- data/lib/gobstones/lang/definitions/main.rb +26 -0
- data/lib/gobstones/lang/definitions/no_return_statement.rb +15 -0
- data/lib/gobstones/lang/definitions/procedure.rb +44 -0
- data/lib/gobstones/lang/definitions/return_from_function.rb +22 -0
- data/lib/gobstones/lang/definitions/return_from_main.rb +22 -0
- data/lib/gobstones/lang/definitions/var_tuple.rb +26 -0
- data/lib/gobstones/lang/expressions/all.rb +8 -0
- data/lib/gobstones/lang/expressions/arithmetic_expressions.rb +52 -0
- data/lib/gobstones/lang/expressions/boolean_expressions.rb +29 -0
- data/lib/gobstones/lang/expressions/comparison_expressions.rb +45 -0
- data/lib/gobstones/lang/expressions/function_call.rb +15 -0
- data/lib/gobstones/lang/expressions/one_arg_expression.rb +21 -0
- data/lib/gobstones/lang/expressions/parentheses_expression.rb +13 -0
- data/lib/gobstones/lang/expressions/primitive_functions.rb +68 -0
- data/lib/gobstones/lang/expressions/two_arg_expression.rb +34 -0
- data/lib/gobstones/lang/expressions/type_bound_functions.rb +66 -0
- data/lib/gobstones/lang/expressions/var_name.rb +31 -0
- data/lib/gobstones/lang/literals/all.rb +4 -0
- data/lib/gobstones/lang/literals/booleans.rb +109 -0
- data/lib/gobstones/lang/literals/colors.rb +94 -0
- data/lib/gobstones/lang/literals/directions.rb +137 -0
- data/lib/gobstones/lang/literals/literal.rb +63 -0
- data/lib/gobstones/lang/literals/number.rb +49 -0
- data/lib/gobstones/lang/program.rb +32 -0
- data/lib/gobstones/modules/equal_by_class.rb +13 -0
- data/lib/gobstones/parser/ast/ast.rb +210 -0
- data/lib/gobstones/parser/grammar/gobstones.treetop +316 -0
- data/lib/gobstones/parser/parse_error.rb +17 -0
- data/lib/gobstones/parser/treetop_parser.rb +73 -0
- data/lib/gobstones/runner/all.rb +6 -0
- data/lib/gobstones/runner/board.rb +57 -0
- data/lib/gobstones/runner/cell.rb +60 -0
- data/lib/gobstones/runner/errors/all.rb +8 -0
- data/lib/gobstones/runner/errors/boom_error.rb +11 -0
- data/lib/gobstones/runner/errors/definition_not_found_error.rb +19 -0
- data/lib/gobstones/runner/errors/empty_cell_error.rb +11 -0
- data/lib/gobstones/runner/errors/gobstones_runtime_error.rb +11 -0
- data/lib/gobstones/runner/errors/gobstones_type_error.rb +11 -0
- data/lib/gobstones/runner/errors/out_of_board_error.rb +11 -0
- data/lib/gobstones/runner/errors/undefined_variable_error.rb +11 -0
- data/lib/gobstones/runner/errors/wrong_arguments_error.rb +11 -0
- data/lib/gobstones/runner/execution_context.rb +89 -0
- data/lib/gobstones/runner/head.rb +101 -0
- data/lib/gobstones/type_check_result.rb +16 -0
- data/spec/lang/commands/assignments_spec.rb +13 -0
- data/spec/lang/commands/boom_cmd_spec.rb +8 -0
- data/spec/lang/commands/cmd_block_spec.rb +21 -0
- data/spec/lang/commands/if_cmd_spec.rb +49 -0
- data/spec/lang/commands/ir_al_origen_cmd_spec.rb +16 -0
- data/spec/lang/commands/mover_cmd_spec.rb +38 -0
- data/spec/lang/commands/poner_cmd_spec.rb +29 -0
- data/spec/lang/commands/procedure_call_spec.rb +44 -0
- data/spec/lang/commands/procedure_spec.rb +67 -0
- data/spec/lang/commands/repeat_with_cmd_spec.rb +41 -0
- data/spec/lang/commands/sacar_cmd_spec.rb +34 -0
- data/spec/lang/commands/skip_cmd_spec.rb +12 -0
- data/spec/lang/commands/vaciar_tablero_cmd_spec.rb +13 -0
- data/spec/lang/commands/while_cmd_spec.rb +37 -0
- data/spec/lang/expressions/arithmetic_expressions_spec.rb +108 -0
- data/spec/lang/expressions/boolean_expressions_spec.rb +56 -0
- data/spec/lang/expressions/comparison_expressions_spec.rb +285 -0
- data/spec/lang/expressions/primitive_functions_spec.rb +126 -0
- data/spec/lang/expressions/type_bound_functions_spec.rb +39 -0
- data/spec/lang/expressions/var_name_spec.rb +16 -0
- data/spec/lang/literals/booleans_spec.rb +13 -0
- data/spec/lang/literals/colors_spec.rb +13 -0
- data/spec/lang/literals/directions_spec.rb +45 -0
- data/spec/lang/literals/numbers_spec.rb +8 -0
- data/spec/matchers/parse_matcher.rb +84 -0
- data/spec/parser/arithmetic_expressions_spec.rb +129 -0
- data/spec/parser/assignments_spec.rb +39 -0
- data/spec/parser/boolean_expressions_spec.rb +111 -0
- data/spec/parser/command_block_spec.rb +50 -0
- data/spec/parser/data_types_spec.rb +67 -0
- data/spec/parser/function_calls_spec.rb +37 -0
- data/spec/parser/function_definitions_spec.rb +50 -0
- data/spec/parser/gobstones_program_spec.rb +55 -0
- data/spec/parser/if_command_spec.rb +46 -0
- data/spec/parser/main_definition_spec.rb +42 -0
- data/spec/parser/nested_expressions_spec.rb +39 -0
- data/spec/parser/primitive_expressions_spec.rb +105 -0
- data/spec/parser/procedure_calls_spec.rb +36 -0
- data/spec/parser/procedure_definitions_spec.rb +39 -0
- data/spec/parser/repeat_with_command_spec.rb +23 -0
- data/spec/parser/simple_commands_spec.rb +62 -0
- data/spec/parser/treetop_parser_spec.rb +109 -0
- data/spec/parser/var_tuple_spec.rb +30 -0
- data/spec/parser/while_command_spec.rb +30 -0
- data/spec/runner/board_spec.rb +85 -0
- data/spec/runner/cell_spec.rb +72 -0
- data/spec/runner/execution_context_spec.rb +64 -0
- data/spec/runner/head_spec.rb +139 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/type_checker_spec.rb +37 -0
- metadata +242 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
describe Gobstones::Parser, "assignments" do
|
2
|
+
|
3
|
+
describe "single" do
|
4
|
+
|
5
|
+
it "should parse a valid assignment with a simple expression" do
|
6
|
+
assignment = SingleAssignment.new VarName.new('myDir'), Norte.new
|
7
|
+
|
8
|
+
expect('myDir:=Norte').
|
9
|
+
to be_parsed_as(:command).and_return(assignment)
|
10
|
+
expect('myDir := Norte').
|
11
|
+
to be_parsed_as(:command).and_return(assignment)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should parse a valid assignment with a complex expression" do
|
15
|
+
a, b = VarName.new('a'), VarName.new('b')
|
16
|
+
exp = Or.new False.new, ParenthesesExpr.new(And.new(a, b))
|
17
|
+
assignment = SingleAssignment.new VarName.new('myVar'), exp
|
18
|
+
|
19
|
+
expect('myVar := False || (a && b)').
|
20
|
+
to be_parsed_as(:command).and_return(assignment)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not parse with an invalid var name" do
|
24
|
+
expect('MyWrongVar := a').to be_parsed_as(:command).and_fail
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not parse with a command on the right side" do
|
28
|
+
expect('myVar := Skip').to be_parsed_as(:command).and_fail
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "multiple" do
|
34
|
+
|
35
|
+
# TODO implement
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
describe Gobstones::Parser, "boolean expressions" do
|
2
|
+
|
3
|
+
let(:a) { VarName.new 'a' }
|
4
|
+
let(:b) { VarName.new 'b' }
|
5
|
+
let(:c) { VarName.new 'c' }
|
6
|
+
let(:d) { VarName.new 'd' }
|
7
|
+
|
8
|
+
describe "relational operators" do
|
9
|
+
|
10
|
+
it "should parse an expression with ==" do
|
11
|
+
eq = Equal.new a, b
|
12
|
+
|
13
|
+
expect('a==b').to be_parsed_as(:expression).and_return(eq)
|
14
|
+
expect('a == b').to be_parsed_as(:expression).and_return(eq)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should parse an expression with /=" do
|
18
|
+
not_eq = NotEqual.new a, b
|
19
|
+
|
20
|
+
expect('a/=b').to be_parsed_as(:expression).and_return(not_eq)
|
21
|
+
expect('a /= b').to be_parsed_as(:expression).and_return(not_eq)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should parse an expression with <" do
|
25
|
+
lt = LessThan.new a, b
|
26
|
+
|
27
|
+
expect('a<b').to be_parsed_as(:expression).and_return(lt)
|
28
|
+
expect('a < b').to be_parsed_as(:expression).and_return(lt)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should parse an expression with <=" do
|
32
|
+
le = LessEqual.new a, b
|
33
|
+
|
34
|
+
expect('a<=b').to be_parsed_as(:expression).and_return(le)
|
35
|
+
expect('a <= b').to be_parsed_as(:expression).and_return(le)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should parse an expression with >=" do
|
39
|
+
ge = GreaterEqual.new a, b
|
40
|
+
|
41
|
+
expect('a>=b').to be_parsed_as(:expression).and_return(ge)
|
42
|
+
expect('a >= b').to be_parsed_as(:expression).and_return(ge)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should parse an expression with >" do
|
46
|
+
gt = GreaterThan.new a, b
|
47
|
+
|
48
|
+
expect('a>b').to be_parsed_as(:expression).and_return(gt)
|
49
|
+
expect('a > b').to be_parsed_as(:expression).and_return(gt)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "not, and, or" do
|
55
|
+
|
56
|
+
it "should parse a not expression" do
|
57
|
+
exp = Equal.new a, b
|
58
|
+
not_exp = Not.new exp
|
59
|
+
|
60
|
+
expect('not a == b').to be_parsed_as(:expression).and_return(not_exp)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should parse an And expression" do
|
64
|
+
exp = And.new a, b
|
65
|
+
|
66
|
+
expect('a&&b').to be_parsed_as(:expression).and_return(exp)
|
67
|
+
expect('a && b').to be_parsed_as(:expression).and_return(exp)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should parse an Or expression" do
|
71
|
+
exp = Or.new a, b
|
72
|
+
|
73
|
+
expect('a||b').to be_parsed_as(:expression).and_return(exp)
|
74
|
+
expect('a || b').to be_parsed_as(:expression).and_return(exp)
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "nested" do
|
78
|
+
|
79
|
+
it "should parse a nested || expression, associating right" do
|
80
|
+
inner_or = Or.new b, c
|
81
|
+
outer_or = Or.new a, inner_or
|
82
|
+
|
83
|
+
expect('a || b || c').to be_parsed_as(:expression).and_return(outer_or)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should parse a nested && expression, associating right" do
|
87
|
+
inner_and = And.new b, c
|
88
|
+
outer_and = And.new a, inner_and
|
89
|
+
|
90
|
+
expect('a && b && c').to be_parsed_as(:expression).and_return(outer_and)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "|| should take precedence over &&, left" do
|
94
|
+
bc_and = And.new b, c
|
95
|
+
abc_or = Or.new a, bc_and
|
96
|
+
|
97
|
+
expect('a || b && c').to be_parsed_as(:expression).and_return(abc_or)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "|| should take precedence over &&, right" do
|
101
|
+
ab_and = And.new a, b
|
102
|
+
abc_or = Or.new ab_and, c
|
103
|
+
|
104
|
+
expect('a && b || c').to be_parsed_as(:expression).and_return(abc_or)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
describe Gobstones::Parser, "command blocks" do
|
2
|
+
|
3
|
+
it "should parse an empty block" do
|
4
|
+
cmd_block = CmdBlock.empty
|
5
|
+
|
6
|
+
expect('{}').to be_parsed_as(:command).and_return(cmd_block)
|
7
|
+
expect('{ }').to be_parsed_as(:command).and_return(cmd_block)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should parse a block with one simple cmd" do
|
11
|
+
cmd_block = CmdBlock.new [Skip.new]
|
12
|
+
expect('{ Skip }').to be_parsed_as(:command).and_return(cmd_block)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should parse a block with many simple commands" do
|
16
|
+
first = Poner.new Verde.new
|
17
|
+
second = Boom.new "error"
|
18
|
+
third = Mover.new Oeste.new
|
19
|
+
cmd_block = CmdBlock.new [first, second, third]
|
20
|
+
|
21
|
+
expect('{
|
22
|
+
Poner(Verde)
|
23
|
+
BOOM("error")
|
24
|
+
Mover(Oeste)
|
25
|
+
}').to be_parsed_as(:command).and_return(cmd_block)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should allow ; between commands" do
|
29
|
+
first = Poner.new Verde.new
|
30
|
+
second = Boom.new "error"
|
31
|
+
third = Mover.new Oeste.new
|
32
|
+
cmd_block = CmdBlock.new [first, second, third]
|
33
|
+
|
34
|
+
expect('{Poner(Verde); BOOM("error");
|
35
|
+
Mover(Oeste);
|
36
|
+
}').to be_parsed_as(:command).and_return(cmd_block)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should parse a block with simple and complex commands" do
|
40
|
+
first = ProcedureCall.new 'Proc', []
|
41
|
+
second = IfCmd.new True.new, CmdBlock.empty
|
42
|
+
cmd_block = CmdBlock.new [first, second]
|
43
|
+
|
44
|
+
expect('{
|
45
|
+
Proc()
|
46
|
+
if (True) {}
|
47
|
+
}').to be_parsed_as(:command).and_return(cmd_block)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
describe Gobstones::Parser, "data types" do
|
2
|
+
|
3
|
+
describe "numbers" do
|
4
|
+
|
5
|
+
it "should parse a positive number" do
|
6
|
+
expect('42').to be_parsed_as(:expression).and_return(42.to_gbs_num)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should parse a negative number" do
|
10
|
+
expect('-42').to be_parsed_as(:expression).and_return(-42.to_gbs_num)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "booleans" do
|
16
|
+
|
17
|
+
it "should parse a true boolean" do
|
18
|
+
expect('True').to be_parsed_as(:expression).and_return(True.new)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should parse a false boolean" do
|
22
|
+
expect('False').to be_parsed_as(:expression).and_return(False.new)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "colors" do
|
28
|
+
|
29
|
+
it "should parse the 'Azul' color" do
|
30
|
+
expect('Azul').to be_parsed_as(:expression).and_return(Azul.new)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should parse the 'Negro' color" do
|
34
|
+
expect('Negro').to be_parsed_as(:expression).and_return(Negro.new)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should parse the 'Rojo' color" do
|
38
|
+
expect('Rojo').to be_parsed_as(:expression).and_return(Rojo.new)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should parse the 'Verde' color" do
|
42
|
+
expect('Verde').to be_parsed_as(:expression).and_return(Verde.new)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "directions" do
|
48
|
+
|
49
|
+
it "should parse the 'Norte' direction" do
|
50
|
+
expect('Norte').to be_parsed_as(:expression).and_return(Norte.new)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should parse the 'Este' direction" do
|
54
|
+
expect('Este').to be_parsed_as(:expression).and_return(Este.new)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should parse the 'Sur' direction" do
|
58
|
+
expect('Sur').to be_parsed_as(:expression).and_return(Sur.new)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should parse the 'Oeste' direction" do
|
62
|
+
expect('Oeste').to be_parsed_as(:expression).and_return(Oeste.new)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
describe Gobstones::Parser, "function calls" do
|
2
|
+
|
3
|
+
it "should parse a function call without args" do
|
4
|
+
expected = FunctionCall.new 'f1'
|
5
|
+
expect('f1()').to be_parsed_as(:expression).and_return(expected)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should not parse a function call without a valid identifier" do
|
9
|
+
expect('F1()').to be_parsed_as(:expression).and_fail
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should parse a function call with one arg" do
|
13
|
+
expected = FunctionCall.new 'func1', [Verde.new]
|
14
|
+
expect('func1(Verde)').to be_parsed_as(:expression).and_return(expected)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should parse a function with many args" do
|
18
|
+
first_arg = 42.to_gbs_num
|
19
|
+
second_arg = NroBolitas.new Verde.new
|
20
|
+
third_arg = Norte.new
|
21
|
+
expected = FunctionCall.new 'func1', [first_arg, second_arg, third_arg]
|
22
|
+
|
23
|
+
expect('func1(42, nroBolitas(Verde), Norte)').
|
24
|
+
to be_parsed_as(:expression).and_return(expected)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse a complex function call" do
|
28
|
+
or_expr = Or.new VarName.new('a'), VarName.new('b')
|
29
|
+
paren_expr = ParenthesesExpr.new Div.new(10.to_gbs_num, VarName.new('c'))
|
30
|
+
num_expr = Mul.new 5.to_gbs_num, paren_expr
|
31
|
+
func2_call = FunctionCall.new 'func2', [Verde.new, Opuesto.new(Norte.new)]
|
32
|
+
func1_call = FunctionCall.new 'func1', [or_expr, num_expr, func2_call]
|
33
|
+
expect('func1(a || b, 5*(10 div c), func2(Verde, opuesto(Norte)))').
|
34
|
+
to be_parsed_as(:expression).and_return(func1_call)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
describe Gobstones::Parser, "function definitions" do
|
2
|
+
|
3
|
+
it "should parse a function without args and a single return" do
|
4
|
+
args = VarTuple.new []
|
5
|
+
func_return = ReturnFromFunction.new [42.to_gbs_num]
|
6
|
+
|
7
|
+
func_def = Function.new 'just42', args, CmdBlock.new([]), func_return
|
8
|
+
|
9
|
+
expect('function just42() { return (42) }').
|
10
|
+
to be_parsed_as(:definition).and_return(func_def)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should parse a function with some args" do
|
14
|
+
first_arg = VarName.new 'firstArg'
|
15
|
+
second_arg = VarName.new 'secondArg'
|
16
|
+
third_arg = VarName.new 'thirdArg'
|
17
|
+
args = VarTuple.new [first_arg, second_arg, third_arg]
|
18
|
+
body =
|
19
|
+
return_st = ReturnFromFunction.new [Verde.new, PuedeMover.new(Norte.new)]
|
20
|
+
func_def = Function.new 'myCoolFunction', args, CmdBlock.new([]), return_st
|
21
|
+
|
22
|
+
expect('function myCoolFunction (firstArg, secondArg, thirdArg) {
|
23
|
+
return (Verde, puedeMover(Norte))
|
24
|
+
}').to be_parsed_as(:definition).and_return(func_def)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse a function with some statements" do
|
28
|
+
args = VarTuple.new [VarName.new('arg')]
|
29
|
+
body = CmdBlock.new [Poner.new(Verde.new)]
|
30
|
+
return_st = ReturnFromFunction.new [True.new]
|
31
|
+
func_def = Function.new 'myFunc', args, body, return_st
|
32
|
+
|
33
|
+
expect('function myFunc(arg)
|
34
|
+
{
|
35
|
+
Poner(Verde)
|
36
|
+
return (True)
|
37
|
+
}').to be_parsed_as(:definition).and_return(func_def)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should not parse a function without a valid identifier" do
|
41
|
+
expect('function MyWrongFunc() { return(True) }').
|
42
|
+
to be_parsed_as(:definition).and_fail
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should not parse a function without a return statement" do
|
46
|
+
expect('function myFuncWithoutReturn() { }').
|
47
|
+
to be_parsed_as(:definition).and_fail
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
describe Gobstones::Parser, "program definitions" do
|
2
|
+
|
3
|
+
it "should parse a simple program with a single main" do
|
4
|
+
main_def = Main.new CmdBlock.new([]), NoReturnStatement.new
|
5
|
+
program = Program.new [], main_def
|
6
|
+
|
7
|
+
expect('procedure Main(){}').to be_parsed_as(:program).and_return(program)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should parse a program with Main and procedures" do
|
11
|
+
main_def = Main.new CmdBlock.new([]), NoReturnStatement.new
|
12
|
+
proc_1 = Procedure.new 'Procedure1', VarTuple.new([]), CmdBlock.new([])
|
13
|
+
proc_2 = Procedure.new 'Procedure2', VarTuple.new([]), CmdBlock.new([])
|
14
|
+
program = Program.new [proc_1, proc_2], main_def
|
15
|
+
|
16
|
+
gbs_code = <<GBS
|
17
|
+
procedure Procedure1(){ }
|
18
|
+
|
19
|
+
procedure Procedure2 () {}
|
20
|
+
|
21
|
+
procedure Main() {}
|
22
|
+
GBS
|
23
|
+
expect(gbs_code).to be_parsed_as(:program).and_return(program)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should parse a program with Main, procedures and functions" do
|
27
|
+
main_def = Main.new CmdBlock.new([]), NoReturnStatement.new
|
28
|
+
proc_1 = Procedure.new 'Procedure1', VarTuple.new([]), CmdBlock.new([])
|
29
|
+
func_1 = Function.new 'function1', VarTuple.new([]), CmdBlock.new([]), ReturnFromFunction.new([42.to_gbs_num])
|
30
|
+
proc_2 = Procedure.new 'Procedure2', VarTuple.new([]), CmdBlock.new([])
|
31
|
+
program = Program.new [proc_1, func_1, proc_2], main_def
|
32
|
+
gbs_code = <<GBS
|
33
|
+
procedure Procedure1(){ }
|
34
|
+
|
35
|
+
function function1() { return (42) }
|
36
|
+
|
37
|
+
procedure Procedure2 () {}
|
38
|
+
|
39
|
+
procedure Main() {}
|
40
|
+
GBS
|
41
|
+
expect(gbs_code).to be_parsed_as(:program).and_return(program)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not parse a program without a Main definition" do
|
45
|
+
expect('procedure Procedure1(){}
|
46
|
+
procedure Procedure2() {}').to be_parsed_as(:program).and_fail
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not parse a program if Main is not the last definition" do
|
50
|
+
expect('procedure Procedure1() {}
|
51
|
+
procedure Main() {}
|
52
|
+
procedure Procedure2() {}').to be_parsed_as(:program).and_fail
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
describe Gobstones::Parser, "if statements" do
|
2
|
+
|
3
|
+
describe "if" do
|
4
|
+
|
5
|
+
it "should parse a statement with a simple boolean and an empty block" do
|
6
|
+
if_cmd = IfCmd.new True.new, CmdBlock.empty
|
7
|
+
|
8
|
+
expect('if (True) {}').to be_parsed_as(:command).and_return(if_cmd)
|
9
|
+
expect('if (True) {
|
10
|
+
}').to be_parsed_as(:command).and_return(if_cmd)
|
11
|
+
expect('if (True)
|
12
|
+
{}').to be_parsed_as(:command).and_return(if_cmd)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should parse a statement with a simple boolean and a block with commands" do
|
16
|
+
cmd_block = CmdBlock.new [Poner.new(Verde.new), Skip.new]
|
17
|
+
if_cmd = IfCmd.new False.new, cmd_block
|
18
|
+
|
19
|
+
expect('if(False){Poner(Verde); Skip}').
|
20
|
+
to be_parsed_as(:command).and_return(if_cmd)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should parse a statement with a complex boolean expression" do
|
24
|
+
and_expr = And.new VarName.new('a'), False.new
|
25
|
+
exp = Or.new PuedeMover.new(Norte.new), ParenthesesExpr.new(and_expr)
|
26
|
+
if_cmd = IfCmd.new exp, CmdBlock.empty
|
27
|
+
|
28
|
+
expect('if (puedeMover(Norte) || (a && False)) {}').
|
29
|
+
to be_parsed_as(:command).and_return(if_cmd)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "if-else" do
|
35
|
+
|
36
|
+
it "should parse a statement with an else block" do
|
37
|
+
else_block = CmdBlock.new [Mover.new(Norte.new)]
|
38
|
+
if_else_cmd = IfElseCmd.new False.new, CmdBlock.empty, else_block
|
39
|
+
|
40
|
+
expect('if (False) { } else { Mover(Norte) }').
|
41
|
+
to be_parsed_as(:command).and_return(if_else_cmd)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|