gobstones 0.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +3 -0
  4. data/.ruby-version +1 -0
  5. data/.simplecov +3 -0
  6. data/.travis.yml +4 -0
  7. data/CHANGELOG +4 -0
  8. data/Gemfile +12 -0
  9. data/Gemfile.lock +47 -0
  10. data/LICENSE +675 -0
  11. data/README.md +17 -0
  12. data/Rakefile +4 -0
  13. data/bin/gobstones +12 -0
  14. data/gobstones.gemspec +24 -0
  15. data/lib/gobstones/cli/board_template +39 -0
  16. data/lib/gobstones/cli/printer.rb +106 -0
  17. data/lib/gobstones/cli/runner.rb +52 -0
  18. data/lib/gobstones/extensions/all.rb +2 -0
  19. data/lib/gobstones/extensions/boolean.rb +17 -0
  20. data/lib/gobstones/extensions/fixnum.rb +9 -0
  21. data/lib/gobstones/lang/all.rb +5 -0
  22. data/lib/gobstones/lang/commands/all.rb +13 -0
  23. data/lib/gobstones/lang/commands/assignments.rb +29 -0
  24. data/lib/gobstones/lang/commands/boom_cmd.rb +28 -0
  25. data/lib/gobstones/lang/commands/command_block.rb +37 -0
  26. data/lib/gobstones/lang/commands/conditional_cmd.rb +27 -0
  27. data/lib/gobstones/lang/commands/if_cmd.rb +38 -0
  28. data/lib/gobstones/lang/commands/ir_al_origen_cmd.rb +19 -0
  29. data/lib/gobstones/lang/commands/mover_cmd.rb +25 -0
  30. data/lib/gobstones/lang/commands/poner_cmd.rb +31 -0
  31. data/lib/gobstones/lang/commands/procedure_call.rb +23 -0
  32. data/lib/gobstones/lang/commands/repeat_with_cmd.rb +73 -0
  33. data/lib/gobstones/lang/commands/sacar_cmd.rb +31 -0
  34. data/lib/gobstones/lang/commands/skip_cmd.rb +19 -0
  35. data/lib/gobstones/lang/commands/vaciar_tablero_cmd.rb +19 -0
  36. data/lib/gobstones/lang/commands/while_cmd.rb +25 -0
  37. data/lib/gobstones/lang/definitions/all.rb +4 -0
  38. data/lib/gobstones/lang/definitions/definition.rb +32 -0
  39. data/lib/gobstones/lang/definitions/definition_call.rb +24 -0
  40. data/lib/gobstones/lang/definitions/function.rb +14 -0
  41. data/lib/gobstones/lang/definitions/main.rb +26 -0
  42. data/lib/gobstones/lang/definitions/no_return_statement.rb +15 -0
  43. data/lib/gobstones/lang/definitions/procedure.rb +44 -0
  44. data/lib/gobstones/lang/definitions/return_from_function.rb +22 -0
  45. data/lib/gobstones/lang/definitions/return_from_main.rb +22 -0
  46. data/lib/gobstones/lang/definitions/var_tuple.rb +26 -0
  47. data/lib/gobstones/lang/expressions/all.rb +8 -0
  48. data/lib/gobstones/lang/expressions/arithmetic_expressions.rb +52 -0
  49. data/lib/gobstones/lang/expressions/boolean_expressions.rb +29 -0
  50. data/lib/gobstones/lang/expressions/comparison_expressions.rb +45 -0
  51. data/lib/gobstones/lang/expressions/function_call.rb +15 -0
  52. data/lib/gobstones/lang/expressions/one_arg_expression.rb +21 -0
  53. data/lib/gobstones/lang/expressions/parentheses_expression.rb +13 -0
  54. data/lib/gobstones/lang/expressions/primitive_functions.rb +68 -0
  55. data/lib/gobstones/lang/expressions/two_arg_expression.rb +34 -0
  56. data/lib/gobstones/lang/expressions/type_bound_functions.rb +66 -0
  57. data/lib/gobstones/lang/expressions/var_name.rb +31 -0
  58. data/lib/gobstones/lang/literals/all.rb +4 -0
  59. data/lib/gobstones/lang/literals/booleans.rb +109 -0
  60. data/lib/gobstones/lang/literals/colors.rb +94 -0
  61. data/lib/gobstones/lang/literals/directions.rb +137 -0
  62. data/lib/gobstones/lang/literals/literal.rb +63 -0
  63. data/lib/gobstones/lang/literals/number.rb +49 -0
  64. data/lib/gobstones/lang/program.rb +32 -0
  65. data/lib/gobstones/modules/equal_by_class.rb +13 -0
  66. data/lib/gobstones/parser/ast/ast.rb +210 -0
  67. data/lib/gobstones/parser/grammar/gobstones.treetop +316 -0
  68. data/lib/gobstones/parser/parse_error.rb +17 -0
  69. data/lib/gobstones/parser/treetop_parser.rb +73 -0
  70. data/lib/gobstones/runner/all.rb +6 -0
  71. data/lib/gobstones/runner/board.rb +57 -0
  72. data/lib/gobstones/runner/cell.rb +60 -0
  73. data/lib/gobstones/runner/errors/all.rb +8 -0
  74. data/lib/gobstones/runner/errors/boom_error.rb +11 -0
  75. data/lib/gobstones/runner/errors/definition_not_found_error.rb +19 -0
  76. data/lib/gobstones/runner/errors/empty_cell_error.rb +11 -0
  77. data/lib/gobstones/runner/errors/gobstones_runtime_error.rb +11 -0
  78. data/lib/gobstones/runner/errors/gobstones_type_error.rb +11 -0
  79. data/lib/gobstones/runner/errors/out_of_board_error.rb +11 -0
  80. data/lib/gobstones/runner/errors/undefined_variable_error.rb +11 -0
  81. data/lib/gobstones/runner/errors/wrong_arguments_error.rb +11 -0
  82. data/lib/gobstones/runner/execution_context.rb +89 -0
  83. data/lib/gobstones/runner/head.rb +101 -0
  84. data/lib/gobstones/type_check_result.rb +16 -0
  85. data/spec/lang/commands/assignments_spec.rb +13 -0
  86. data/spec/lang/commands/boom_cmd_spec.rb +8 -0
  87. data/spec/lang/commands/cmd_block_spec.rb +21 -0
  88. data/spec/lang/commands/if_cmd_spec.rb +49 -0
  89. data/spec/lang/commands/ir_al_origen_cmd_spec.rb +16 -0
  90. data/spec/lang/commands/mover_cmd_spec.rb +38 -0
  91. data/spec/lang/commands/poner_cmd_spec.rb +29 -0
  92. data/spec/lang/commands/procedure_call_spec.rb +44 -0
  93. data/spec/lang/commands/procedure_spec.rb +67 -0
  94. data/spec/lang/commands/repeat_with_cmd_spec.rb +41 -0
  95. data/spec/lang/commands/sacar_cmd_spec.rb +34 -0
  96. data/spec/lang/commands/skip_cmd_spec.rb +12 -0
  97. data/spec/lang/commands/vaciar_tablero_cmd_spec.rb +13 -0
  98. data/spec/lang/commands/while_cmd_spec.rb +37 -0
  99. data/spec/lang/expressions/arithmetic_expressions_spec.rb +108 -0
  100. data/spec/lang/expressions/boolean_expressions_spec.rb +56 -0
  101. data/spec/lang/expressions/comparison_expressions_spec.rb +285 -0
  102. data/spec/lang/expressions/primitive_functions_spec.rb +126 -0
  103. data/spec/lang/expressions/type_bound_functions_spec.rb +39 -0
  104. data/spec/lang/expressions/var_name_spec.rb +16 -0
  105. data/spec/lang/literals/booleans_spec.rb +13 -0
  106. data/spec/lang/literals/colors_spec.rb +13 -0
  107. data/spec/lang/literals/directions_spec.rb +45 -0
  108. data/spec/lang/literals/numbers_spec.rb +8 -0
  109. data/spec/matchers/parse_matcher.rb +84 -0
  110. data/spec/parser/arithmetic_expressions_spec.rb +129 -0
  111. data/spec/parser/assignments_spec.rb +39 -0
  112. data/spec/parser/boolean_expressions_spec.rb +111 -0
  113. data/spec/parser/command_block_spec.rb +50 -0
  114. data/spec/parser/data_types_spec.rb +67 -0
  115. data/spec/parser/function_calls_spec.rb +37 -0
  116. data/spec/parser/function_definitions_spec.rb +50 -0
  117. data/spec/parser/gobstones_program_spec.rb +55 -0
  118. data/spec/parser/if_command_spec.rb +46 -0
  119. data/spec/parser/main_definition_spec.rb +42 -0
  120. data/spec/parser/nested_expressions_spec.rb +39 -0
  121. data/spec/parser/primitive_expressions_spec.rb +105 -0
  122. data/spec/parser/procedure_calls_spec.rb +36 -0
  123. data/spec/parser/procedure_definitions_spec.rb +39 -0
  124. data/spec/parser/repeat_with_command_spec.rb +23 -0
  125. data/spec/parser/simple_commands_spec.rb +62 -0
  126. data/spec/parser/treetop_parser_spec.rb +109 -0
  127. data/spec/parser/var_tuple_spec.rb +30 -0
  128. data/spec/parser/while_command_spec.rb +30 -0
  129. data/spec/runner/board_spec.rb +85 -0
  130. data/spec/runner/cell_spec.rb +72 -0
  131. data/spec/runner/execution_context_spec.rb +64 -0
  132. data/spec/runner/head_spec.rb +139 -0
  133. data/spec/spec_helper.rb +15 -0
  134. data/spec/type_checker_spec.rb +37 -0
  135. metadata +242 -0
@@ -0,0 +1,32 @@
1
+ require 'gobstones/runner/execution_context'
2
+
3
+ module Gobstones
4
+
5
+ module Lang
6
+
7
+ class Program
8
+
9
+ attr_reader :definitions, :main_definition
10
+
11
+ def initialize(definitions, main_definition)
12
+ @definitions = definitions
13
+ @main_definition = main_definition
14
+ end
15
+
16
+ def ==(other)
17
+ self.class == other.class &&
18
+ self.definitions == other.definitions &&
19
+ self.main_definition == other.main_definition
20
+ end
21
+
22
+ def evaluate
23
+ context = Gobstones::Runner::ProgramExecutionContext.for self
24
+ main_definition.evaluate context
25
+ context
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,13 @@
1
+ module Gobstones
2
+
3
+ module EqualByClass
4
+
5
+ def ==(other)
6
+ self.class == other.class
7
+ end
8
+
9
+ alias_method :eql?, :==
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,210 @@
1
+ require 'gobstones/lang/all'
2
+
3
+ module Gobstones
4
+
5
+ # TODO divide into smaller modules
6
+ module Parser
7
+
8
+ include Gobstones::Lang
9
+
10
+ RESERVED_IDS = %w(
11
+ if else not True False case of while Skip repeatWith in procedure function
12
+ return Mover Sacar Poner BOOM IrAlOrigen VaciarTablero div mod hayBolitas
13
+ nroBolitas puedeMover Norte Sur Este Oeste minBool maxBool minDir maxDir
14
+ minColor maxColor siguiente previo opuesto Verde Rojo Azul Negro Main
15
+ )
16
+
17
+ def self.ast_node(name, &value_block)
18
+ # TODO check if it is better to have classes
19
+ mod = Module.new do
20
+ define_method :value do
21
+ instance_eval(&value_block)
22
+ end
23
+ end
24
+ const_set name, mod
25
+ end
26
+
27
+ ast_node(:IntegerLiteral) { Number.new text_value.to_i }
28
+ ast_node(:BooleanLiteral) { Kernel.const_get(text_value).new }
29
+ ast_node(:ColorLiteral) { Kernel.const_get(text_value).new }
30
+ ast_node(:DirectionLiteral) { Kernel.const_get(text_value).new }
31
+
32
+ ast_node(:MinBoolFuncNode) { MinBool.new }
33
+ ast_node(:MaxBoolFuncNode) { MaxBool.new }
34
+ ast_node(:MinColorFuncNode) { MinColor.new }
35
+ ast_node(:MaxColorFuncNode) { MaxColor.new }
36
+ ast_node(:MinDirFuncNode) { MinDir.new }
37
+ ast_node(:MaxDirFuncNode) { MaxDir.new }
38
+
39
+ ast_node(:VarNameNode) { VarName.new text_value }
40
+
41
+ ast_node(:NroBolitasFuncNode) { NroBolitas.new gexp.value }
42
+ ast_node(:HayBolitasFuncNode) { HayBolitas.new gexp.value }
43
+ ast_node(:PuedeMoverFuncNode) { PuedeMover.new gexp.value }
44
+ ast_node(:SiguienteFuncNode) { Siguiente.new gexp.value }
45
+ ast_node(:PrevioFuncNode) { Previo.new gexp.value }
46
+ ast_node(:OpuestoFuncNode) { Opuesto.new gexp.value }
47
+
48
+ ast_node :NopExprNode do
49
+ if sub_exps.empty?
50
+ left.value
51
+ else
52
+ # it is a nested exp
53
+ sub_exps.elements.inject(left.value) do |memo, node|
54
+ case node.op.text_value
55
+ when '+'
56
+ memo = Add.new memo, node.right.value
57
+ when '-'
58
+ memo = Sub.new memo, node.right.value
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ ast_node :MulExprNode do
65
+ if sub_exps.empty?
66
+ left.value
67
+ else
68
+ # it is a nested exp
69
+ sub_exps.elements.inject(left.value) do |memo, node|
70
+ memo = Mul.new memo, node.right.value
71
+ end
72
+ end
73
+ end
74
+
75
+ ast_node :DivModExprNode do
76
+ case op.text_value
77
+ when 'div'
78
+ Div.new left.value, right.value
79
+ when 'mod'
80
+ Mod.new left.value, right.value
81
+ end
82
+ end
83
+
84
+ ast_node :PowExprNode do
85
+ if sub_exps.empty?
86
+ left.value
87
+ else
88
+ # it is a nested exp
89
+ sub_exps.elements.inject(left.value) do |memo, node|
90
+ memo = Pow.new memo, node.right.value
91
+ end
92
+ end
93
+ end
94
+
95
+ ast_node :RopExprNode do
96
+ classes = {
97
+ '==' => Equal, '/=' => NotEqual,
98
+ '<' => LessThan, '>' => GreaterThan,
99
+ '<=' => LessEqual, '>=' => GreaterEqual
100
+ }
101
+ classes[rop.text_value].new left.value, right.value
102
+ end
103
+
104
+ ast_node(:NotExprNode) { Not.new exp.value }
105
+ ast_node(:AndExprNode) { And.new left.value, right.value }
106
+ ast_node(:OrExprNode) { Or.new left.value, right.value }
107
+
108
+ ast_node(:ParenthesesExprNode) { ParenthesesExpr.new gexp.value }
109
+ ast_node(:FuncCallNode) do
110
+ FunctionCall.new func_name.text_value, gexp_tuple.value
111
+ end
112
+ ast_node(:TupleExprNode) { exps.empty? ? [] : exps.value }
113
+
114
+ ast_node :GexpsNode do
115
+ if elements.length == 2
116
+ [elements[0].value]
117
+ else
118
+ [exp.value] + exps.value
119
+ end
120
+ end
121
+
122
+ ast_node(:SkipCmdNode) { Skip.new }
123
+ ast_node(:BoomCmdNode) { Boom.new string.text_value[1..-2] }
124
+
125
+ ast_node(:PonerCmdNode) { Poner.new gexp.value }
126
+ ast_node(:SacarCmdNode) { Sacar.new gexp.value }
127
+ ast_node(:MoverCmdNode) { Mover.new gexp.value }
128
+
129
+ ast_node(:IrAlOrigenCmdNode) { IrAlOrigen.new }
130
+ ast_node(:VaciarTableroCmdNode) { VaciarTablero.new }
131
+
132
+ ast_node :ProcCallNode do
133
+ ProcedureCall.new proc_name.text_value, gexp_tuple.value
134
+ end
135
+
136
+ ast_node :SingleAssignmentNode do
137
+ SingleAssignment.new var_name.value, gexp.value
138
+ end
139
+
140
+ ast_node :CmdBlockNode do
141
+ CmdBlock.new create_commands(commands)
142
+ end
143
+
144
+ ast_node :IfCmdNode do
145
+ if else_clause.empty?
146
+ IfCmd.new gexp.value, then_block.value
147
+ else
148
+ IfElseCmd.new gexp.value, then_block.value, else_clause.else_block.value
149
+ end
150
+ end
151
+
152
+ ast_node(:WhileCmdNode) { WhileCmd.new gexp.value, cmd_block.value }
153
+
154
+ ast_node :RepeatWithCmdNode do
155
+ RepeatWithCmd.new var_name.value, range_min.value,
156
+ range_max.value, cmd_block.value
157
+ end
158
+
159
+ # TODO abstract duplication, very similar to GexpsNode
160
+ ast_node(:VarNamesNode) do
161
+ if elements.length == 2
162
+ # TODO check why it is needed to create a VarName
163
+ # instead of having already a VarName in elements[0]
164
+ [VarName.new(elements[0].text_value)]
165
+ else
166
+ [vn.value] + vns.value
167
+ end
168
+ end
169
+
170
+ ast_node(:VarTupleNode) do
171
+ variables = vns.empty? ? [] : vns.value
172
+ VarTuple.new variables
173
+ end
174
+
175
+ ast_node(:ProcedureNode) do
176
+ Procedure.new proc_name.text_value, var_tuple.value, cmd_block.value
177
+ end
178
+
179
+ ast_node(:FunctionNode) do
180
+ cmd_block = CmdBlock.new create_commands(commands)
181
+ Function.new func_name.text_value, var_tuple.value,
182
+ cmd_block, func_return.value
183
+ end
184
+
185
+ ast_node(:FuncReturnNode) do
186
+ ReturnFromFunction.new gexp_tuple_1.value
187
+ end
188
+
189
+ ast_node(:MainReturnNode) do
190
+ ReturnFromMain.new var_tuple.value
191
+ end
192
+
193
+ ast_node(:MainDefNode) do
194
+ cmd_block = CmdBlock.new create_commands(commands)
195
+ return_st = ret.empty? ? NoReturnStatement.new : ret.value
196
+ Main.new cmd_block, return_st
197
+ end
198
+
199
+ ast_node(:ProgramNode) do
200
+ defs = definitions.elements.map { |node| node.definition.value }
201
+ Program.new defs, main_def.value
202
+ end
203
+
204
+ def create_commands(commands)
205
+ commands.elements.map { |node| node.command.value }
206
+ end
207
+
208
+ end
209
+
210
+ end
@@ -0,0 +1,316 @@
1
+ # TODO modularize when possible
2
+ grammar Gobstones
3
+
4
+ # TOP RULE: program
5
+
6
+ rule program
7
+ definitions main_def space* <ProgramNode>
8
+ end
9
+
10
+ # DEFINITIONS: main, procedures, functions
11
+
12
+ rule definitions
13
+ (space* definition space*)*
14
+ end
15
+
16
+ rule definition
17
+ procedure_def / function_def
18
+ end
19
+
20
+ rule main_def
21
+ 'procedure' space+ 'Main' space* '(' space* ')' space*
22
+ '{' space* commands ret:main_return? space* '}' <MainDefNode>
23
+ end
24
+
25
+ rule main_return
26
+ 'return' space* var_tuple space* ';'? <MainReturnNode>
27
+ end
28
+
29
+ rule procedure_def
30
+ 'procedure' space+ proc_name space*
31
+ var_tuple space* cmd_block <ProcedureNode>
32
+ end
33
+
34
+ rule function_def
35
+ 'function' space+ func_name space* var_tuple space*
36
+ '{' space* commands func_return space* '}' <FunctionNode>
37
+ end
38
+
39
+ rule func_return
40
+ 'return' space* gexp_tuple_1 space* ';'? <FuncReturnNode>
41
+ end
42
+
43
+ # COMMANDS
44
+
45
+ rule commands
46
+ (command space* ';'? space*)*
47
+ end
48
+
49
+ rule command
50
+ simple_cmd / complex_cmd
51
+ end
52
+
53
+ rule simple_cmd
54
+ skip_cmd / boom_cmd / poner_cmd / sacar_cmd / mover_cmd /
55
+ ir_al_origen_cmd / vaciar_tablero_cmd / proc_call /
56
+ cmd_block / single_assignment # / multiple_assignment
57
+ end
58
+
59
+ rule skip_cmd
60
+ 'Skip' <SkipCmdNode>
61
+ end
62
+
63
+ rule boom_cmd
64
+ 'BOOM' space* '(' space* string space* ')' <BoomCmdNode>
65
+ end
66
+
67
+ rule poner_cmd
68
+ 'Poner' space* '(' space* gexp space* ')' <PonerCmdNode>
69
+ end
70
+
71
+ rule sacar_cmd
72
+ 'Sacar' space* '(' space* gexp space* ')' <SacarCmdNode>
73
+ end
74
+
75
+ rule mover_cmd
76
+ 'Mover' space* '(' space* gexp space* ')' <MoverCmdNode>
77
+ end
78
+
79
+ rule ir_al_origen_cmd
80
+ 'IrAlOrigen' space* '(' space* ')' <IrAlOrigenCmdNode>
81
+ end
82
+
83
+ rule vaciar_tablero_cmd
84
+ 'VaciarTablero' space* '(' space* ')' <VaciarTableroCmdNode>
85
+ end
86
+
87
+ rule proc_call
88
+ proc_name space* gexp_tuple <ProcCallNode>
89
+ end
90
+
91
+ rule cmd_block
92
+ '{' space* commands space* '}' <CmdBlockNode>
93
+ end
94
+
95
+ rule single_assignment
96
+ var_name space* ':=' space* gexp <SingleAssignmentNode>
97
+ end
98
+
99
+ # TODO implement
100
+ # rule multiple_assignment
101
+ # end
102
+
103
+ rule complex_cmd
104
+ if_cmd / while_cmd / repeat_with_cmd # / case_cmd
105
+ end
106
+
107
+ rule if_cmd
108
+ 'if' space* '(' space* gexp space* ')'
109
+ space* then_block:cmd_block
110
+ else_clause:(space* 'else' space* else_block:cmd_block)?
111
+ <IfCmdNode>
112
+ end
113
+
114
+ rule while_cmd
115
+ 'while' space* '(' space* gexp space* ')' space* cmd_block <WhileCmdNode>
116
+ end
117
+
118
+ rule repeat_with_cmd
119
+ 'repeatWith' space+ var_name space+ 'in' space+
120
+ range_min:gexp space* '..' space* range_max:gexp space*
121
+ cmd_block <RepeatWithCmdNode>
122
+ end
123
+
124
+ # TODO implement
125
+ # rule case_cmd
126
+ # end
127
+
128
+ # EXPRESSIONS
129
+
130
+ rule gexp
131
+ bexp
132
+ end
133
+
134
+ rule bexp
135
+ left:bterm space* '||' space* right:bexp <OrExprNode> / bterm
136
+ end
137
+
138
+ rule bterm
139
+ left:bfact space* '&&' space* right:bterm <AndExprNode> / bfact
140
+ end
141
+
142
+ rule bfact
143
+ 'not' space+ exp:batom <NotExprNode> / batom
144
+ end
145
+
146
+ rule batom
147
+ left:nexp space* rop space* right:nexp <RopExprNode> / nexp
148
+ end
149
+
150
+ rule rop
151
+ '==' / '/=' / '<=' / '>=' / '<' / '>'
152
+ end
153
+
154
+ rule nexp
155
+ left:nterm sub_exps:(space* op:[+-] space* right:nterm)* <NopExprNode>
156
+ end
157
+
158
+ rule nterm
159
+ left:nfactH sub_exps:(space* '*' space* right:nfactH)* <MulExprNode>
160
+ end
161
+
162
+ rule nfactH
163
+ left:nfactL space+ op:mop space+ right:nfactL <DivModExprNode> / nfactL
164
+ end
165
+
166
+ rule mop
167
+ 'div' / 'mod'
168
+ end
169
+
170
+ rule nfactL
171
+ left:natom sub_exps:(space* '^' space* right:natom)* <PowExprNode>
172
+ end
173
+
174
+ rule natom
175
+ literal / type_bound_func / primitive_func /
176
+ paren_expr / func_call / var_name
177
+ end
178
+
179
+ rule type_bound_func
180
+ bool_type_bound_func / color_type_bound_func / direction_type_bound_func
181
+ end
182
+
183
+ rule bool_type_bound_func
184
+ 'minBool()' <MinBoolFuncNode> / 'maxBool()' <MaxBoolFuncNode>
185
+ end
186
+
187
+ rule color_type_bound_func
188
+ 'minColor()' <MinColorFuncNode> / 'maxColor()' <MaxColorFuncNode>
189
+ end
190
+
191
+ rule direction_type_bound_func
192
+ 'minDir()' <MinDirFuncNode> / 'maxDir()' <MaxDirFuncNode>
193
+ end
194
+
195
+ rule primitive_func
196
+ nro_bolitas_func / hay_bolitas_func / puede_mover_func /
197
+ siguiente_func / previo_func / opuesto_func
198
+ end
199
+
200
+ rule nro_bolitas_func
201
+ 'nroBolitas' space* '(' space* gexp space* ')' <NroBolitasFuncNode>
202
+ end
203
+
204
+ rule hay_bolitas_func
205
+ 'hayBolitas' space* '(' space* gexp space* ')' <HayBolitasFuncNode>
206
+ end
207
+
208
+ rule puede_mover_func
209
+ 'puedeMover' space* '(' space* gexp space* ')' <PuedeMoverFuncNode>
210
+ end
211
+
212
+ rule siguiente_func
213
+ 'siguiente' space* '(' space* gexp space* ')' <SiguienteFuncNode>
214
+ end
215
+
216
+ rule previo_func
217
+ 'previo' space* '(' space* gexp space* ')' <PrevioFuncNode>
218
+ end
219
+
220
+ rule opuesto_func
221
+ 'opuesto' space* '(' space* gexp space* ')' <OpuestoFuncNode>
222
+ end
223
+
224
+ rule paren_expr
225
+ '(' space* gexp space* ')' <ParenthesesExprNode>
226
+ end
227
+
228
+ rule func_call
229
+ func_name space* gexp_tuple <FuncCallNode>
230
+ end
231
+
232
+ rule var_name
233
+ lower_id &{ |id| id[0].is_not_reserved } <VarNameNode>
234
+ end
235
+
236
+ # LITERALS
237
+
238
+ rule literal
239
+ number / boolean / color / direction
240
+ end
241
+
242
+ rule number
243
+ '-'? [0-9] [0-9]* <IntegerLiteral>
244
+ end
245
+
246
+ rule boolean
247
+ ('True' / 'False') <BooleanLiteral>
248
+ end
249
+
250
+ rule color
251
+ ('Azul' / 'Negro' / 'Rojo' / 'Verde') <ColorLiteral>
252
+ end
253
+
254
+ rule direction
255
+ ('Norte' / 'Este' / 'Sur' / 'Oeste') <DirectionLiteral>
256
+ end
257
+
258
+ # AUX DEFINITIONS: identifiers, tuples
259
+
260
+ rule proc_name
261
+ upper_id &{ |id| id[0].is_not_reserved }
262
+ end
263
+
264
+ rule func_name
265
+ lower_id &{ |id| id[0].is_not_reserved }
266
+ end
267
+
268
+ rule var_tuple
269
+ '(' space* vns:var_names? space* ')' <VarTupleNode>
270
+ end
271
+
272
+ rule var_names
273
+ ((vn:var_name space* ',' space* vns:var_names) / var_name) <VarNamesNode>
274
+ end
275
+
276
+ rule gexp_tuple
277
+ '(' space* exps:gexps? space* ')' <TupleExprNode>
278
+ end
279
+
280
+ rule gexp_tuple_1
281
+ '(' space* exps:gexps space* ')' <TupleExprNode>
282
+ end
283
+
284
+ rule gexps
285
+ ((exp:gexp space* ',' space* exps:gexps) / gexp) <GexpsNode>
286
+ end
287
+
288
+ rule lower_id
289
+ [a-z] char* {
290
+ def is_not_reserved
291
+ !Gobstones::Parser::RESERVED_IDS.include? text_value
292
+ end
293
+ }
294
+ end
295
+
296
+ rule upper_id
297
+ [A-Z] char* {
298
+ def is_not_reserved
299
+ !Gobstones::Parser::RESERVED_IDS.include? text_value
300
+ end
301
+ }
302
+ end
303
+
304
+ rule char
305
+ [a-zA-Z0-9'_]
306
+ end
307
+
308
+ rule string
309
+ '"' ('\"' / !'"' .)* '"'
310
+ end
311
+
312
+ rule space
313
+ [\s]
314
+ end
315
+
316
+ end