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,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,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
|