Clarkoer commited on
Commit
53f237e
·
1 Parent(s): c960c5f

Update trash files ehe

Browse files
Files changed (38) hide show
  1. Backend/GALinterpreter.py +282 -44
  2. Backend/GALsemantic.py +149 -23
  3. Backend/Gal_Parser.py +75 -2
  4. Backend/cfg.py +39 -8
  5. Backend/icg.py +23 -2
  6. Backend/lexer.py +126 -118
  7. Backend/main.js +0 -569
  8. Backend/server.py +144 -28
  9. Backend/test_array_param.py +0 -45
  10. Backend/test_curly_init.py +0 -41
  11. Backend/test_mp16.py +0 -77
  12. Backend/test_mp16_full.py +0 -113
  13. Docus & mps/CFG_FIRST_FOLLOW_PREDICT.txt +0 -0
  14. Docus & mps/CFG_Latest_1_extracted.txt +214 -0
  15. Docus & mps/CFG_Latest_First_Follow_Predict_Set_extracted.txt +1441 -0
  16. Docus & mps/CFG_Latest_extracted.txt +225 -0
  17. Docus & mps/CFG_live_from_code.txt +199 -0
  18. DEFENSE_01_server.md → Docus & mps/DEFENSE_01_server.md +0 -0
  19. DEFENSE_01_server.pdf → Docus & mps/DEFENSE_01_server.pdf +0 -0
  20. DEFENSE_02_tokens_errors.md → Docus & mps/DEFENSE_02_tokens_errors.md +0 -0
  21. DEFENSE_02_tokens_errors.pdf → Docus & mps/DEFENSE_02_tokens_errors.pdf +0 -0
  22. Docus & mps/DEFENSE_03_lexer.md +791 -0
  23. Docus & mps/DEFENSE_03_lexer.pdf +448 -0
  24. Docus & mps/DEFENSE_04_parser_ast_semantic_icg_interpreter.md +2290 -0
  25. Docus & mps/DEFENSE_FULL_PIPELINE.md +0 -0
  26. Docus & mps/DEFENSE_FULL_PIPELINE.pdf +0 -0
  27. GAL_COMPILER_KNOWLEDGE_BASE.md → Docus & mps/GAL_COMPILER_KNOWLEDGE_BASE.md +0 -0
  28. GAL_PROGRAMS_EXPLANATION.pdf.md → Docus & mps/GAL_PROGRAMS_EXPLANATION.pdf.md +0 -0
  29. GAL_RESERVED_WORDS_EXPLANATION.md → Docus & mps/GAL_RESERVED_WORDS_EXPLANATION.md +0 -0
  30. GAL_RESERVED_WORDS_EXPLANATION.pdf → Docus & mps/GAL_RESERVED_WORDS_EXPLANATION.pdf +0 -0
  31. GAL_SYSTEM_DOCUMENTATION.md → Docus & mps/GAL_SYSTEM_DOCUMENTATION.md +0 -0
  32. Docus & mps/cfg_to_pred_extracted.txt +943 -0
  33. convert_defense_to_pdf.py → Docus & mps/convert_defense_to_pdf.py +0 -0
  34. convert_to_pdf.py → Docus & mps/convert_to_pdf.py +0 -0
  35. Docus & mps/gal_server_codex.err.log +10 -0
  36. Docus & mps/gal_server_codex.log +0 -0
  37. payslip.gal → Docus & mps/payslip.gal +0 -0
  38. Docus & mps/system_cfg_first_follow_predict_current.txt +559 -0
Backend/GALinterpreter.py CHANGED
@@ -1,22 +1,58 @@
1
- from GALsemantic import (ProgramNode, VariableDeclarationNode, AssignmentNode, BinaryOpNode, FunctionDeclarationNode,
2
- FunctionCallNode, IfStatementNode, ForLoopNode, WhileLoopNode, PrintNode, UnaryOpNode,
3
- FertileDeclarationNode, ReturnNode, SwitchNode, ContinueNode, BreakNode, ListNode, TaperNode,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  TSNode, SoilNode, BloomNode, AppendNode, InsertNode, RemoveNode, CastNode, ListAccessNode, DoWhileLoopNode,
5
  MemberAccessNode, BundleDefinitionNode, ArrayMemberAccessNode)
6
 
7
  import threading
8
  import sys
9
 
 
 
10
  sys.setrecursionlimit(10000)
11
 
12
  # Prefer eventlet's cooperative Event so wait_for_input yields to the
13
  # eventlet hub instead of blocking the entire event loop.
 
14
  try:
15
  import eventlet.event as _ev
16
  _USE_EVENTLET = True
17
  except ImportError:
18
  _USE_EVENTLET = False
19
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  class SemanticError(Exception):
21
  def __init__(self, message, line):
22
  super().__init__(message)
@@ -26,6 +62,7 @@ class SemanticError(Exception):
26
  return self.message
27
 
28
  class ReturnValue(Exception):
 
29
  def __init__(self, value):
30
  self.value = value
31
 
@@ -34,6 +71,7 @@ class _CancelledError(Exception):
34
  pass
35
 
36
  class InterpreterError(Exception):
 
37
  def __init__(self, message, line):
38
  super().__init__(message)
39
  if line is not None:
@@ -41,38 +79,67 @@ class InterpreterError(Exception):
41
 
42
  else:
43
  self.message = message
44
-
45
  def __str__(self):
46
  return self.message
47
 
48
  class InterpreterInputRequest(Exception):
 
49
  def __init__(self, prompt, line):
50
  self.prompt = prompt
51
  self.line = line
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  class Interpreter:
54
  def __init__(self, socketio=None):
55
- self.output = []
56
- self.loop_stack = []
57
- self.break_flag = False
58
- self.continue_flag = False
59
- self.input_required = False
60
- self.socketio = socketio
61
- self.input_events = {}
62
- self.input_values = {}
63
- self.current_node = None
 
 
 
 
 
 
 
64
  self.current_parent = None
65
 
66
- self.variables = {}
67
- self.global_variables = {}
68
- self.functions = {}
69
- self.scopes = [{}]
70
- self.current_func_name = None
71
- self.function_variables = {}
72
- self.bundle_types = {} # Stores bundle (struct) type definitions
73
-
74
-
75
- ###### VARIABLE ######
 
 
 
 
 
76
  def declare_variable(self, name, type_, value=None, is_list=False, is_fertile=False):
77
  scope = self.scopes[-1]
78
  current_func = self.current_func_name
@@ -119,9 +186,14 @@ class Interpreter:
119
  return f"Semantic Error: Variable '{name}' not declared in any scope."
120
 
121
 
122
- ###### FUNCTION ######
 
 
 
 
123
  def declare_function(self, name, return_type, params, node=None):
124
  if name in self.functions:
 
125
  return f"Semantic Error: Function '{name}' already declared."
126
  self.functions[name] = {"return_type": return_type, "params": params, "node": node}
127
 
@@ -129,17 +201,24 @@ class Interpreter:
129
  if name in self.functions:
130
  return self.functions[name]
131
  return f"Semantic Error: Function '{name}' is not defined."
132
-
133
 
134
- ###### SCOPE ######
 
 
 
 
 
 
135
  def enter_scope(self):
136
  self.scopes.append({})
137
-
138
 
139
  def exit_scope(self):
 
140
  if len(self.scopes) > 1:
141
  self.scopes.pop()
142
-
 
143
  if self.current_func_name:
144
  current_func = self.current_func_name
145
 
@@ -147,8 +226,11 @@ class Interpreter:
147
  self.function_variables[current_func].clear()
148
 
149
 
150
-
151
- #INTERPRETER
 
 
 
152
  def interpret(self, node):
153
  if isinstance(node, ProgramNode):
154
  return self.eval_program(node)
@@ -242,13 +324,24 @@ class Interpreter:
242
  else:
243
  raise Exception(f"Unknown AST node type: {node.node_type}")
244
 
 
 
 
 
 
245
  def eval_program(self, node):
 
246
  for child in node.children:
247
  self.interpret(child)
248
 
 
249
  main_call = FunctionCallNode("root", [], node.line)
250
  return self.interpret(main_call)
251
 
 
 
 
 
252
  def eval_variable_declaration(self, node):
253
  var_type = node.children[0].value
254
  var_name = node.children[1].value
@@ -386,6 +479,16 @@ class Interpreter:
386
  value = self.interpret(value_node)
387
  self.declare_variable(var_name, var_type, value, is_list=False, is_fertile=True)
388
 
 
 
 
 
 
 
 
 
 
 
389
  def eval_assignment(self, node):
390
  target_node = node.children[0]
391
  value_node = node.children[1]
@@ -565,6 +668,14 @@ class Interpreter:
565
  #print(f"\nUpdating variable '{var_name}' of type '{var_type}' with value: {value}")
566
 
567
 
 
 
 
 
 
 
 
 
568
  def eval_binary_op(self, node):
569
  left = self.interpret(node.children[0])
570
  right = self.interpret(node.children[1])
@@ -619,6 +730,17 @@ class Interpreter:
619
  elif isinstance(right, str):
620
  right = 1 if right != "" else 0
621
  return left * right
 
 
 
 
 
 
 
 
 
 
 
622
  elif operator == '/':
623
  if not isinstance(left, (int, float)) and not isinstance(right, (int, float)):
624
  if isinstance(left, bool):
@@ -724,6 +846,12 @@ class Interpreter:
724
  except ZeroDivisionError:
725
  raise InterpreterError("Runtime Error: Division by zero", "")
726
 
 
 
 
 
 
 
727
  def _parse_literal(self, value):
728
 
729
  if isinstance(value, str):
@@ -763,8 +891,13 @@ class Interpreter:
763
  return value
764
 
765
 
 
 
 
 
 
766
  def eval_function_declaration(self, node):
767
- return_type = node.children[0].value
768
  parameters_node = node.children[1]
769
  func_name = node.value
770
 
@@ -782,24 +915,41 @@ class Interpreter:
782
 
783
  return None
784
 
 
 
 
 
785
  def eval_block(self, block_node):
786
  for statement in block_node.children:
787
- self.interpret(statement)
 
788
  if self.break_triggered():
789
  return
 
790
  if self.continue_flag:
791
  return
792
-
793
-
 
 
 
 
794
  def plant(self, value):
795
  """GAL output primitive."""
796
  self.socketio.emit('output', {'output': str(value)})
797
 
798
- # Backward-compatible alias
799
  def plant_out(self, num):
800
  self.socketio.emit('output', {'output': str(num)})
801
  self.output.append(str(num))
802
 
 
 
 
 
 
 
 
803
  def eval_print(self, node):
804
  if not node.children:
805
  return
@@ -849,11 +999,16 @@ class Interpreter:
849
 
850
  self.plant(str(evaluated_first))
851
 
 
 
 
 
 
852
  def eval_formatted_string(self, node):
853
  value = node.value
854
  if value.startswith('"') and value.endswith('"'):
855
  value = value[1:-1]
856
-
857
  # Escape sequences
858
  value = value.replace(r'\\', '\\')
859
  value = value.replace(r'\n', '\n')
@@ -864,7 +1019,12 @@ class Interpreter:
864
  value = value.replace(r'\/', '/')
865
  return value
866
 
867
-
 
 
 
 
 
868
  def eval_list_access(self, node):
869
  # children[0] is ASTNode("ListName", list_name) where list_name is a string or ListAccessNode
870
  name_or_node = node.children[0].value
@@ -892,11 +1052,22 @@ class Interpreter:
892
  return list_value[index]
893
 
894
 
 
 
 
 
 
 
895
  def eval_return(self, node):
896
  value = self.interpret(node.children[0]) if node.children else None
897
  raise ReturnValue(value)
898
-
899
 
 
 
 
 
 
 
900
  def eval_function_call(self, node):
901
  function_name = node.value
902
  args = [self.interpret(arg.children[0]) for arg in node.children]
@@ -938,6 +1109,11 @@ class Interpreter:
938
  self.current_func_name = None
939
 
940
 
 
 
 
 
 
941
  def eval_append(self, node):
942
  list_name = node.parent.children[0].value
943
  list_info = self.lookup_variable(list_name)
@@ -986,6 +1162,12 @@ class Interpreter:
986
  removed = list_info["value"].pop(index)
987
  #print(f"Removed value {removed} from list '{list_name}': {list_info['value']}")
988
 
 
 
 
 
 
 
989
  def eval_unaryop(self, node):
990
  if not isinstance(node.children[0], ListAccessNode):
991
  operand_node = node.children[0]
@@ -1062,6 +1244,10 @@ class Interpreter:
1062
 
1063
  raise InterpreterError(f"Unknown unary operator {node.value}", node.line)
1064
 
 
 
 
 
1065
  def eval_cast(self, node):
1066
  value = self.interpret(node.children[1])
1067
  cast_type = node.children[0].value
@@ -1072,7 +1258,7 @@ class Interpreter:
1072
  return float(value)
1073
  elif cast_type == "leaf":
1074
  if isinstance(value, int):
1075
- return chr(value)
1076
  return str(value)[0] if value else '\0'
1077
  elif cast_type == "branch":
1078
  return bool(value)
@@ -1081,6 +1267,15 @@ class Interpreter:
1081
  else:
1082
  raise InterpreterError(f"Unknown cast type: {cast_type}", node.line)
1083
 
 
 
 
 
 
 
 
 
 
1084
  def eval_taper(self, node):
1085
  var_name = node.children[0].value
1086
  var_info = self.lookup_variable(var_name)
@@ -1113,6 +1308,12 @@ class Interpreter:
1113
  var_info = self.lookup_variable(var_name)
1114
  return var_info["value"].upper()
1115
 
 
 
 
 
 
 
1116
  def eval_if_statement(self, node):
1117
  condition_result = self.interpret(node.children[0].children[0])
1118
  self.enter_scope()
@@ -1159,10 +1360,16 @@ class Interpreter:
1159
 
1160
  return None
1161
 
 
 
 
 
 
 
1162
  def eval_for_loop(self, node):
1163
  self.enter_loop('for')
1164
  self.enter_scope()
1165
- MAX_LOOP_ITERATIONS = 10000
1166
  LOOP_COUNTER = 0
1167
 
1168
  try:
@@ -1274,12 +1481,18 @@ class Interpreter:
1274
  self.exit_loop()
1275
 
1276
 
 
 
 
 
 
 
1277
  def eval_break(self, node):
1278
  if self.loop_stack:
1279
  self.trigger_break()
1280
  else:
1281
  raise InterpreterError("Runtime Error: Break statement used outside of a loop", node.line)
1282
-
1283
  def trigger_break(self):
1284
  self.break_flag = True
1285
 
@@ -1287,6 +1500,7 @@ class Interpreter:
1287
  return self.break_flag
1288
 
1289
  def enter_loop(self, loop_type):
 
1290
  self.loop_stack.append(loop_type)
1291
  self.break_flag = False
1292
  self.continue_flag = False
@@ -1302,13 +1516,19 @@ class Interpreter:
1302
  self.trigger_continue()
1303
  else:
1304
  raise InterpreterError("Runtime Error: Continue statement used outside of a loop", node.line)
1305
-
1306
  def continue_triggered(self):
1307
  return self.continue_flag
1308
-
1309
  def trigger_continue(self):
1310
  self.continue_flag = True
1311
 
 
 
 
 
 
 
1312
  def eval_switch(self, node):
1313
  self.enter_loop('switch')
1314
  self.enter_scope()
@@ -1353,7 +1573,18 @@ class Interpreter:
1353
  self.exit_scope()
1354
 
1355
 
 
 
 
 
 
 
 
 
 
 
1356
  def emit_input_request(self, var_name, prompt):
 
1357
  self.socketio.emit('input_required', {'prompt': prompt, 'variable': var_name})
1358
 
1359
  # Method to capture input from the client
@@ -1394,7 +1625,14 @@ class Interpreter:
1394
  self.input_events.pop(var_name, None)
1395
  return value
1396
 
1397
- # Modify the eval_input method to use the new input handling
 
 
 
 
 
 
 
1398
  def eval_input(self, node):
1399
  parent_node = node.parent
1400
  if isinstance(parent_node, VariableDeclarationNode):
 
1
+ # ============================================================================
2
+ # GAL INTERPRETER - Tree-walking executor for the semantic AST
3
+ # ============================================================================
4
+ # This is the runtime engine of the GAL compiler. It walks the AST produced
5
+ # by GALsemantic and executes each node directly. The interpreter does NOT
6
+ # consume the ICG output — TAC is a parallel display layer; execution happens
7
+ # here on the AST.
8
+ #
9
+ # Pipeline position:
10
+ # lex -> parse -> AST -> semantic -> ICG (display) -> THIS FILE (execute)
11
+ #
12
+ # Output is sent via self.socketio.emit('output', ...) which can be either
13
+ # a real Socket.IO instance (live mode) or an OutputCollector (synchronous).
14
+ # Input is collected via self.socketio.emit('input_required', ...) which
15
+ # parks the interpreter until provide_input() is called.
16
+ # ============================================================================
17
+
18
+ # ============================================================================
19
+ # IMPORTS - AST node classes from the semantic analyzer + concurrency
20
+ # primitives for cooperative input-waiting.
21
+ # ============================================================================
22
+ from GALsemantic import (ProgramNode, VariableDeclarationNode, AssignmentNode, BinaryOpNode, FunctionDeclarationNode,
23
+ FunctionCallNode, IfStatementNode, ForLoopNode, WhileLoopNode, PrintNode, UnaryOpNode,
24
+ FertileDeclarationNode, ReturnNode, SwitchNode, ContinueNode, BreakNode, ListNode, TaperNode,
25
  TSNode, SoilNode, BloomNode, AppendNode, InsertNode, RemoveNode, CastNode, ListAccessNode, DoWhileLoopNode,
26
  MemberAccessNode, BundleDefinitionNode, ArrayMemberAccessNode)
27
 
28
  import threading
29
  import sys
30
 
31
+ # Allow deeply recursive GAL programs (e.g. recursive pollinate functions)
32
+ # without hitting Python's default recursion limit (1000)
33
  sys.setrecursionlimit(10000)
34
 
35
  # Prefer eventlet's cooperative Event so wait_for_input yields to the
36
  # eventlet hub instead of blocking the entire event loop.
37
+ # Falls back to threading.Event if eventlet isn't installed (e.g. in tests).
38
  try:
39
  import eventlet.event as _ev
40
  _USE_EVENTLET = True
41
  except ImportError:
42
  _USE_EVENTLET = False
43
 
44
+
45
+ # ============================================================================
46
+ # EXCEPTION CLASSES - Used to short-circuit AST traversal for special cases:
47
+ # - SemanticError : A semantic-level error that escaped to runtime
48
+ # - ReturnValue : reclaim <value> uses exception unwinding to bubble
49
+ # a return value up through nested function calls
50
+ # - _CancelledError : raised when the user starts a new run while an
51
+ # old interpreter is still executing
52
+ # - InterpreterError : standard runtime error (division by zero, etc.)
53
+ # - InterpreterInputRequest : raised when the program calls water() to
54
+ # request input from the client
55
+ # ============================================================================
56
  class SemanticError(Exception):
57
  def __init__(self, message, line):
58
  super().__init__(message)
 
62
  return self.message
63
 
64
  class ReturnValue(Exception):
65
+ """Raised by 'reclaim <expr>;' to unwind out of a function with a value."""
66
  def __init__(self, value):
67
  self.value = value
68
 
 
71
  pass
72
 
73
  class InterpreterError(Exception):
74
+ """All runtime errors raised by the interpreter inherit from this."""
75
  def __init__(self, message, line):
76
  super().__init__(message)
77
  if line is not None:
 
79
 
80
  else:
81
  self.message = message
82
+
83
  def __str__(self):
84
  return self.message
85
 
86
  class InterpreterInputRequest(Exception):
87
+ """Carries a prompt up the call stack when water() needs input."""
88
  def __init__(self, prompt, line):
89
  self.prompt = prompt
90
  self.line = line
91
 
92
+ # ============================================================================
93
+ # INTERPRETER CLASS - Tree-walks the AST and executes each node
94
+ # ============================================================================
95
+ # State organization:
96
+ # - self.scopes : stack of scope dicts (innermost on top); enter_scope
97
+ # pushes a fresh dict, exit_scope pops it
98
+ # - self.variables : globals (visible from every scope)
99
+ # - self.functions : pollinate definitions, keyed by function name
100
+ # - self.bundle_types: bundle (struct) layouts
101
+ # - self.loop_stack : current loop nesting, used by prune/skip
102
+ # - self.break_flag : 'prune' was hit, propagate up to nearest loop/switch
103
+ # - self.continue_flag: 'skip' was hit, propagate up to nearest loop
104
+ # - self.input_* : channels for water() input arriving from the client
105
+ # - self.socketio : adapter for output/input I/O (SessionEmitter or
106
+ # OutputCollector — both expose .emit())
107
+ # ============================================================================
108
  class Interpreter:
109
  def __init__(self, socketio=None):
110
+ # ---- Output state ----
111
+ self.output = [] # legacy collector, kept for compat
112
+ self.socketio = socketio # plant() uses this to emit 'output'
113
+
114
+ # ---- Control-flow flags (set by break/continue, cleared by loops) ----
115
+ self.loop_stack = [] # nested loop-type strings
116
+ self.break_flag = False # set by 'prune'
117
+ self.continue_flag = False # set by 'skip'
118
+
119
+ # ---- Input plumbing for water() ----
120
+ self.input_required = False # True while waiting for the client
121
+ self.input_events = {} # var_name -> Event (eventlet/threading)
122
+ self.input_values = {} # var_name -> string typed by client
123
+
124
+ # ---- Diagnostics ----
125
+ self.current_node = None # node being interpreted (for error msgs)
126
  self.current_parent = None
127
 
128
+ # ---- Symbol tables ----
129
+ self.variables = {} # global variables (visible everywhere)
130
+ self.global_variables = {} # mirror used by declare_variable for dup-check
131
+ self.functions = {} # pollinate definitions (name -> info)
132
+ self.scopes = [{}] # scope stack; [0] is the global scope
133
+ self.current_func_name = None # name of the function currently executing
134
+ self.function_variables = {} # per-function locals (legacy, partially unused)
135
+ self.bundle_types = {} # bundle (struct) layouts
136
+
137
+
138
+ # ========================================================================
139
+ # VARIABLE MANAGEMENT - declare / lookup / set
140
+ # Lookup walks the scope stack from innermost outward, then falls back to
141
+ # globals. This implements lexical scoping for the AST walker.
142
+ # ========================================================================
143
  def declare_variable(self, name, type_, value=None, is_list=False, is_fertile=False):
144
  scope = self.scopes[-1]
145
  current_func = self.current_func_name
 
186
  return f"Semantic Error: Variable '{name}' not declared in any scope."
187
 
188
 
189
+ # ========================================================================
190
+ # FUNCTION MANAGEMENT - declare / lookup
191
+ # GAL functions are first registered (when the parser walks pollinate
192
+ # declarations) and then invoked by name from eval_function_call.
193
+ # ========================================================================
194
  def declare_function(self, name, return_type, params, node=None):
195
  if name in self.functions:
196
+ # Returns an error string — caller decides whether to raise
197
  return f"Semantic Error: Function '{name}' already declared."
198
  self.functions[name] = {"return_type": return_type, "params": params, "node": node}
199
 
 
201
  if name in self.functions:
202
  return self.functions[name]
203
  return f"Semantic Error: Function '{name}' is not defined."
 
204
 
205
+
206
+ # ========================================================================
207
+ # SCOPE MANAGEMENT - enter / exit
208
+ # Each function call, block, and loop body pushes a fresh scope onto
209
+ # self.scopes. Variables declared inside go in the top dict and vanish
210
+ # when the scope is popped.
211
+ # ========================================================================
212
  def enter_scope(self):
213
  self.scopes.append({})
214
+
215
 
216
  def exit_scope(self):
217
+ # Never pop the global scope (scopes[0])
218
  if len(self.scopes) > 1:
219
  self.scopes.pop()
220
+
221
+ # Clear function-local cache if we're leaving a function call
222
  if self.current_func_name:
223
  current_func = self.current_func_name
224
 
 
226
  self.function_variables[current_func].clear()
227
 
228
 
229
+ # ========================================================================
230
+ # MAIN AST DISPATCH - The 'switch' that maps each AST-node class to its
231
+ # eval_* handler. This is the entry point of execution; server.py calls
232
+ # interp.interpret(ast) where ast is a ProgramNode.
233
+ # ========================================================================
234
  def interpret(self, node):
235
  if isinstance(node, ProgramNode):
236
  return self.eval_program(node)
 
324
  else:
325
  raise Exception(f"Unknown AST node type: {node.node_type}")
326
 
327
+ # ========================================================================
328
+ # PROGRAM ENTRY - Walks every top-level declaration (globals, fertile,
329
+ # bundle, pollinate functions) and then synthesizes a call to root().
330
+ # This implements GAL's rule that root() is always the entry point.
331
+ # ========================================================================
332
  def eval_program(self, node):
333
+ # 1. Process every top-level node (registers globals + functions)
334
  for child in node.children:
335
  self.interpret(child)
336
 
337
+ # 2. Now invoke root() — the program's entry point
338
  main_call = FunctionCallNode("root", [], node.line)
339
  return self.interpret(main_call)
340
 
341
+
342
+ # ========================================================================
343
+ # DECLARATIONS - variables, bundles, members, fertile (constants)
344
+ # ========================================================================
345
  def eval_variable_declaration(self, node):
346
  var_type = node.children[0].value
347
  var_name = node.children[1].value
 
479
  value = self.interpret(value_node)
480
  self.declare_variable(var_name, var_type, value, is_list=False, is_fertile=True)
481
 
482
+
483
+ # ========================================================================
484
+ # ASSIGNMENT - The biggest dispatch in this file. Handles every shape:
485
+ # x = expr; (simple variable)
486
+ # arr[i] = expr; (single-dim list element)
487
+ # arr[i][j] = expr; (multi-dim list element)
488
+ # bundle.member = expr;(struct member)
489
+ # x += expr; etc. (compound assignment operators)
490
+ # Type-checking against the variable's declared type happens here too.
491
+ # ========================================================================
492
  def eval_assignment(self, node):
493
  target_node = node.children[0]
494
  value_node = node.children[1]
 
668
  #print(f"\nUpdating variable '{var_name}' of type '{var_type}' with value: {value}")
669
 
670
 
671
+ # ========================================================================
672
+ # BINARY OPERATIONS - + - * / % ** == != < <= > >= && || `
673
+ # The biggest expression evaluator. Each operator branch coerces non-
674
+ # numeric operands (bool, str) into numeric form before computing, so
675
+ # mixed-type expressions don't crash. The `(backtick) operator handles
676
+ # vine concatenation specially (BEFORE _parse_literal) to preserve
677
+ # whitespace-only strings like " ".
678
+ # ========================================================================
679
  def eval_binary_op(self, node):
680
  left = self.interpret(node.children[0])
681
  right = self.interpret(node.children[1])
 
730
  elif isinstance(right, str):
731
  right = 1 if right != "" else 0
732
  return left * right
733
+ elif operator == '**':
734
+ if not isinstance(left, (int, float)) and not isinstance(right, (int, float)):
735
+ if isinstance(left, bool):
736
+ left = 1 if left == True else 0
737
+ elif isinstance(left, str):
738
+ left = 1 if left != "" else 0
739
+ if isinstance(right, bool):
740
+ right = 1 if right == True else 0
741
+ elif isinstance(right, str):
742
+ right = 1 if right != "" else 0
743
+ return left ** right
744
  elif operator == '/':
745
  if not isinstance(left, (int, float)) and not isinstance(right, (int, float)):
746
  if isinstance(left, bool):
 
846
  except ZeroDivisionError:
847
  raise InterpreterError("Runtime Error: Division by zero", "")
848
 
849
+ # ========================================================================
850
+ # _PARSE_LITERAL - Converts a token's string value into the right Python
851
+ # type. Handles GAL's negative-number prefix '~' (e.g. '~5' -> -5), the
852
+ # boolean keywords sunshine/frost, and ints / floats / strings / chars.
853
+ # Called from inside eval_binary_op before doing arithmetic.
854
+ # ========================================================================
855
  def _parse_literal(self, value):
856
 
857
  if isinstance(value, str):
 
891
  return value
892
 
893
 
894
+ # ========================================================================
895
+ # FUNCTION DECLARATION - Registers a 'pollinate' function so it can be
896
+ # called later. This walks the parameter list and saves the function
897
+ # body node for the actual call to interpret.
898
+ # ========================================================================
899
  def eval_function_declaration(self, node):
900
+ return_type = node.children[0].value
901
  parameters_node = node.children[1]
902
  func_name = node.value
903
 
 
915
 
916
  return None
917
 
918
+ # ========================================================================
919
+ # BLOCK EXECUTION - Walks the children of a block { ... } in order,
920
+ # short-circuiting if a break (prune) or continue (skip) was triggered.
921
+ # ========================================================================
922
  def eval_block(self, block_node):
923
  for statement in block_node.children:
924
+ self.interpret(statement)
925
+ # 'prune' was hit somewhere inside — stop executing this block
926
  if self.break_triggered():
927
  return
928
+ # 'skip' was hit — also stop; the surrounding loop handles re-entry
929
  if self.continue_flag:
930
  return
931
+
932
+
933
+ # ========================================================================
934
+ # OUTPUT - 'plant' primitive. Routes to socketio.emit so output is
935
+ # delivered to the right client (live mode) or collected (sync mode).
936
+ # ========================================================================
937
  def plant(self, value):
938
  """GAL output primitive."""
939
  self.socketio.emit('output', {'output': str(value)})
940
 
941
+ # Backward-compatible alias kept for older internal callers
942
  def plant_out(self, num):
943
  self.socketio.emit('output', {'output': str(num)})
944
  self.output.append(str(num))
945
 
946
+
947
+ # ========================================================================
948
+ # PRINT STATEMENT - Implements plant("template", arg1, arg2, ...).
949
+ # If the first argument is a string with {} placeholders, it formats
950
+ # the rest into the template (Python str.format style). Otherwise
951
+ # arguments are joined with spaces (C printf style).
952
+ # ========================================================================
953
  def eval_print(self, node):
954
  if not node.children:
955
  return
 
999
 
1000
  self.plant(str(evaluated_first))
1001
 
1002
+ # ========================================================================
1003
+ # FORMATTED STRING - Strips outer quotes and converts escape sequences
1004
+ # (\n, \t, \", \{, \}, \/, \\) into their real characters before the
1005
+ # string is used as a plant() template.
1006
+ # ========================================================================
1007
  def eval_formatted_string(self, node):
1008
  value = node.value
1009
  if value.startswith('"') and value.endswith('"'):
1010
  value = value[1:-1]
1011
+
1012
  # Escape sequences
1013
  value = value.replace(r'\\', '\\')
1014
  value = value.replace(r'\n', '\n')
 
1019
  value = value.replace(r'\/', '/')
1020
  return value
1021
 
1022
+
1023
+ # ========================================================================
1024
+ # LIST ACCESS - arr[index] reads. Validates bounds and that the index
1025
+ # is an integer. NOTE: indexing is 0-based in the implementation, even
1026
+ # though the GAL spec describes 1-based arrays.
1027
+ # ========================================================================
1028
  def eval_list_access(self, node):
1029
  # children[0] is ASTNode("ListName", list_name) where list_name is a string or ListAccessNode
1030
  name_or_node = node.children[0].value
 
1052
  return list_value[index]
1053
 
1054
 
1055
+ # ========================================================================
1056
+ # RETURN ('reclaim') - Uses exception unwinding so the return value
1057
+ # bubbles up cleanly through any number of nested blocks/loops/ifs.
1058
+ # eval_function_call catches ReturnValue and uses its .value as the
1059
+ # call's result.
1060
+ # ========================================================================
1061
  def eval_return(self, node):
1062
  value = self.interpret(node.children[0]) if node.children else None
1063
  raise ReturnValue(value)
 
1064
 
1065
+
1066
+ # ========================================================================
1067
+ # FUNCTION CALL - Looks up the function, validates arg count, binds
1068
+ # parameters into a fresh scope, and runs the body. ReturnValue is
1069
+ # caught to extract 'reclaim'-returned values.
1070
+ # ========================================================================
1071
  def eval_function_call(self, node):
1072
  function_name = node.value
1073
  args = [self.interpret(arg.children[0]) for arg in node.children]
 
1109
  self.current_func_name = None
1110
 
1111
 
1112
+ # ========================================================================
1113
+ # LIST OPERATIONS - append, insert, remove
1114
+ # These mutate the underlying Python list stored in the variable's value.
1115
+ # Index validation matches eval_list_access (0-based bounds).
1116
+ # ========================================================================
1117
  def eval_append(self, node):
1118
  list_name = node.parent.children[0].value
1119
  list_info = self.lookup_variable(list_name)
 
1162
  removed = list_info["value"].pop(index)
1163
  #print(f"Removed value {removed} from list '{list_name}': {list_info['value']}")
1164
 
1165
+ # ========================================================================
1166
+ # UNARY OPERATIONS - x++, x--, ~x (negate), !x (logical not)
1167
+ # Increment/decrement mutate the variable in place; ~ and ! return a
1168
+ # new value without mutation. Works on both simple variables and
1169
+ # list elements (arr[i]++).
1170
+ # ========================================================================
1171
  def eval_unaryop(self, node):
1172
  if not isinstance(node.children[0], ListAccessNode):
1173
  operand_node = node.children[0]
 
1244
 
1245
  raise InterpreterError(f"Unknown unary operator {node.value}", node.line)
1246
 
1247
+ # ========================================================================
1248
+ # TYPE CAST - Converts a value to the named GAL type. Supports the five
1249
+ # data types: seed, tree, leaf, branch, vine.
1250
+ # ========================================================================
1251
  def eval_cast(self, node):
1252
  value = self.interpret(node.children[1])
1253
  cast_type = node.children[0].value
 
1258
  return float(value)
1259
  elif cast_type == "leaf":
1260
  if isinstance(value, int):
1261
+ return chr(value) # int -> ASCII character
1262
  return str(value)[0] if value else '\0'
1263
  elif cast_type == "branch":
1264
  return bool(value)
 
1267
  else:
1268
  raise InterpreterError(f"Unknown cast type: {cast_type}", node.line)
1269
 
1270
+
1271
+ # ========================================================================
1272
+ # STRING / LIST UTILITY HELPERS - taper, ts, soil, bloom
1273
+ # taper : split a vine into a list of leaves (characters)
1274
+ # ts : length of a list, vine, or leaf-array
1275
+ # soil : lowercase a string
1276
+ # bloom : uppercase a string
1277
+ # These are GAL's built-in string/collection primitives.
1278
+ # ========================================================================
1279
  def eval_taper(self, node):
1280
  var_name = node.children[0].value
1281
  var_info = self.lookup_variable(var_name)
 
1308
  var_info = self.lookup_variable(var_name)
1309
  return var_info["value"].upper()
1310
 
1311
+ # ========================================================================
1312
+ # CONDITIONAL: spring / bud / wither (if / else-if / else)
1313
+ # GAL chains: spring (cond) {} bud (cond) {} bud (cond) {} wither {}
1314
+ # We evaluate the spring condition, then bud chain, then wither default.
1315
+ # The condition must be a boolean (branch type).
1316
+ # ========================================================================
1317
  def eval_if_statement(self, node):
1318
  condition_result = self.interpret(node.children[0].children[0])
1319
  self.enter_scope()
 
1360
 
1361
  return None
1362
 
1363
+ # ========================================================================
1364
+ # LOOPS: cultivate (for), grow (while), tend (do-while)
1365
+ # All three use the same MAX_LOOP_ITERATIONS guard (10000) to catch
1366
+ # runaway loops during a demo. Each tracks break/continue flags so
1367
+ # 'prune' exits the loop and 'skip' jumps to the next iteration.
1368
+ # ========================================================================
1369
  def eval_for_loop(self, node):
1370
  self.enter_loop('for')
1371
  self.enter_scope()
1372
+ MAX_LOOP_ITERATIONS = 10000 # Runaway-loop safety net
1373
  LOOP_COUNTER = 0
1374
 
1375
  try:
 
1481
  self.exit_loop()
1482
 
1483
 
1484
+ # ========================================================================
1485
+ # BREAK / CONTINUE - 'prune' and 'skip'
1486
+ # These set flags that the surrounding block / loop checks each
1487
+ # iteration. The loop_stack ensures break/continue can only be used
1488
+ # inside a loop or switch.
1489
+ # ========================================================================
1490
  def eval_break(self, node):
1491
  if self.loop_stack:
1492
  self.trigger_break()
1493
  else:
1494
  raise InterpreterError("Runtime Error: Break statement used outside of a loop", node.line)
1495
+
1496
  def trigger_break(self):
1497
  self.break_flag = True
1498
 
 
1500
  return self.break_flag
1501
 
1502
  def enter_loop(self, loop_type):
1503
+ # Push a new loop frame; reset break/continue so they don't carry over
1504
  self.loop_stack.append(loop_type)
1505
  self.break_flag = False
1506
  self.continue_flag = False
 
1516
  self.trigger_continue()
1517
  else:
1518
  raise InterpreterError("Runtime Error: Continue statement used outside of a loop", node.line)
1519
+
1520
  def continue_triggered(self):
1521
  return self.continue_flag
1522
+
1523
  def trigger_continue(self):
1524
  self.continue_flag = True
1525
 
1526
+
1527
+ # ========================================================================
1528
+ # SWITCH: harvest / variety / soil (switch / case / default)
1529
+ # Cases match the switch value. 'prune' inside a case exits the switch.
1530
+ # 'soil' is the default case (executes if no variety matched).
1531
+ # ========================================================================
1532
  def eval_switch(self, node):
1533
  self.enter_loop('switch')
1534
  self.enter_scope()
 
1573
  self.exit_scope()
1574
 
1575
 
1576
+ # ========================================================================
1577
+ # INPUT SYSTEM ('water')
1578
+ # When water() runs, the interpreter:
1579
+ # 1. emit_input_request -> tells the client to show an input box
1580
+ # 2. wait_for_input -> parks on an Event (eventlet or threading)
1581
+ # 3. (client emits 'capture_input' -> server calls provide_input)
1582
+ # 4. provide_input -> .send() / .set() unblocks the waiter
1583
+ # 5. wait_for_input returns the typed string
1584
+ # 6. eval_input parses and type-checks it (e.g. ~5 -> -5 for seed)
1585
+ # ========================================================================
1586
  def emit_input_request(self, var_name, prompt):
1587
+ # Tell the client a water() prompt is needed
1588
  self.socketio.emit('input_required', {'prompt': prompt, 'variable': var_name})
1589
 
1590
  # Method to capture input from the client
 
1625
  self.input_events.pop(var_name, None)
1626
  return value
1627
 
1628
+ # ========================================================================
1629
+ # EVAL_INPUT - Implements 'water(...)'. Determines what type of value
1630
+ # the receiving variable expects, prompts the user, then validates and
1631
+ # converts the typed input to that type. Enforces strict GAL syntax:
1632
+ # - Negative numbers must use '~' (not '-')
1633
+ # - Booleans must be 'sunshine' or 'frost' (not 'true'/'false')
1634
+ # Errors include a "did you mean" suggestion to guide the user.
1635
+ # ========================================================================
1636
  def eval_input(self, node):
1637
  parent_node = node.parent
1638
  if isinstance(parent_node, VariableDeclarationNode):
Backend/GALsemantic.py CHANGED
@@ -1,6 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import re
2
 
3
- ##### ERROR ######
 
 
 
 
4
  class SemanticError(Exception):
5
  def __init__(self, message, line):
6
  super().__init__(message)
@@ -10,14 +36,28 @@ class SemanticError(Exception):
10
  return self.message
11
 
12
 
13
- ##### SEMANTIC ANALYZER #####
 
 
 
 
 
14
  class SemanticAnalyzer:
15
  def __init__(self, symbol_table):
16
  self.symbol_table = symbol_table
17
  self.visited_nodes = set()
18
 
19
 
20
- ##### AST NODES #####
 
 
 
 
 
 
 
 
 
21
  class ASTNode:
22
  def __init__(self, node_type, value=None, line=None):
23
  self.node_type = node_type # Type of node (e.g., 'VariableDeclaration', 'BinaryOp')
@@ -236,7 +276,13 @@ class BundleDefinitionNode(ASTNode):
236
  self.members = members # dict: {member_name: member_type}
237
 
238
 
239
- ###### SYMBOL TABLE ######
 
 
 
 
 
 
240
 
241
  class SymbolTable:
242
  def __init__(self):
@@ -347,9 +393,17 @@ symbol_table = SymbolTable()
347
  semantic_analyzer = SemanticAnalyzer(symbol_table)
348
  context_stack = []
349
 
350
- #######################
351
- ###### BUILD AST ######
352
- #######################
 
 
 
 
 
 
 
 
353
 
354
  def build_ast(tokens):
355
  """Constructs an AST from the token list after LL(1) parsing."""
@@ -423,7 +477,7 @@ def build_ast(tokens):
423
  root.add_child(node)
424
 
425
  else:
426
- raise SemanticError(f"Syntax Error: Expected data type for function declaration after 'pollinate'.", tokens[index].line)
427
 
428
  elif token.value == "fertile":
429
  node, index = parse_fertile(tokens, index)
@@ -523,7 +577,7 @@ def parse_functionOrVariable(tokens, index):
523
  node, index = parse_variable(tokens, index, id_name, id_type)
524
 
525
  else:
526
- error = f"Syntax Error: Invalid function or variable declaration."
527
  raise SemanticError(error, line)
528
 
529
  node.line = line
@@ -590,6 +644,12 @@ def _all_paths_return(node):
590
 
591
  return False
592
 
 
 
 
 
 
 
593
  def parse_function(tokens, index, func_name, func_type):
594
  line = tokens[index].line
595
 
@@ -612,17 +672,17 @@ def parse_function(tokens, index, func_name, func_type):
612
  if tokens[index].type == "(":
613
  index += 1
614
  if tokens[index].type != ")":
615
- raise SemanticError(f"Syntax Error: {func_name}() should not have parameters.", line)
616
  index += 1
617
  elif func_name == "root":
618
- raise SemanticError("Syntax Error: Missing () for root function declaration.", line)
619
 
620
  params_node = ASTNode("Parameters")
621
  func_node = FunctionDeclarationNode(func_type, func_name, params_node)
622
 
623
  else:
624
  if tokens[index].type != "(":
625
- error = f"Syntax Error: Missing () for function declaration."
626
  raise SemanticError(error, line)
627
 
628
  params_node = ASTNode("Parameters")
@@ -645,7 +705,7 @@ def parse_function(tokens, index, func_name, func_type):
645
  if tokens[index].type == "[":
646
  index += 1 # skip '['
647
  if tokens[index].type != "]":
648
- raise SemanticError(f"Syntax Error: Expected ']' after '[' in array parameter.", line)
649
  index += 1 # skip ']'
650
  is_list = True
651
  param_node.add_child(ASTNode("ArrayParam", "true"))
@@ -659,7 +719,7 @@ def parse_function(tokens, index, func_name, func_type):
659
  index += 1
660
 
661
  else:
662
- error = f"Syntax Error: Invalid parameter declaration."
663
  raise SemanticError(error, line)
664
 
665
  elif tokens[index].type == "id" and tokens[index].value in symbol_table.bundle_types:
@@ -680,7 +740,7 @@ def parse_function(tokens, index, func_name, func_type):
680
  if tokens[index].type == ",":
681
  index += 1
682
  else:
683
- error = f"Syntax Error: Invalid parameter declaration."
684
  raise SemanticError(error, line)
685
 
686
  else:
@@ -710,16 +770,16 @@ def parse_function(tokens, index, func_name, func_type):
710
  # All functions (including root) must end with reclaim;
711
  if not has_any_return:
712
  if func_name == "root":
713
- raise SemanticError(f"Syntax Error: root() must end with 'reclaim;'.", line)
714
  elif func_type == "empty":
715
- raise SemanticError(f"Syntax Error: Function '{func_name}' must end with 'reclaim;'.", line)
716
 
717
  index += 1
718
  func_node.add_child(block_node)
719
  symbol_table.exit_scope()
720
  symbol_table.current_func_name = None
721
  else:
722
- error = f"Syntax Error: Function body must be enclosed in curly braces."
723
  raise SemanticError(error, line)
724
 
725
  return func_node, index
@@ -769,7 +829,7 @@ def parse_variable(tokens, index, var_name, var_type):
769
  water_line = tokens[index].line
770
  index += 1 # skip 'water'
771
  if tokens[index].type != "(":
772
- raise SemanticError(f"Syntax Error: Expected '(' after water.", water_line)
773
  index += 1 # skip '('
774
  water_type = None
775
  if tokens[index].value in {"seed", "tree", "leaf", "branch", "vine"}:
@@ -874,6 +934,13 @@ def _skip_semicolons(tokens, index):
874
  return index
875
 
876
 
 
 
 
 
 
 
 
877
  def parse_statement(tokens, index, func_type = None):
878
  token = tokens[index]
879
 
@@ -1630,6 +1697,18 @@ def parse_expression_leaf(tokens, index):
1630
  return left_node, index
1631
 
1632
 
 
 
 
 
 
 
 
 
 
 
 
 
1633
  def parse_expression(tokens, index):
1634
  """Parses an expression with +, -, and ` (string concat).
1635
  Returns (node, index, type_str)."""
@@ -1679,7 +1758,7 @@ def parse_expression(tokens, index):
1679
  def parse_term(tokens, index):
1680
  """Parses multiplication, division, and modulus with type checking.
1681
  Returns (node, index, type_str)."""
1682
- left_node, index, left_type = parse_unary(tokens, index)
1683
 
1684
  while tokens[index].type in {"*", "/", "%"}:
1685
  op = tokens[index].value
@@ -1702,7 +1781,7 @@ def parse_term(tokens, index):
1702
  )
1703
 
1704
  index += 1
1705
- right_node, index, right_type = parse_unary(tokens, index)
1706
 
1707
  # Validate right operand is numeric
1708
  if right_type not in {"seed", "tree"}:
@@ -1732,6 +1811,36 @@ def parse_term(tokens, index):
1732
 
1733
  return left_node, index, left_type
1734
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1735
  def parse_unary(tokens, index):
1736
  """Returns (node, index, type_str)."""
1737
 
@@ -2228,7 +2337,7 @@ def parse_operand(tokens, index):
2228
 
2229
  if is_list and tokens[index + 1].type != "[":
2230
  # Check if this is an array <op> array case (e.g., x = a + b)
2231
- if tokens[index + 1].type in {"+", "-", "*", "/", "%", "==", "!=", ">", "<", ">=", "<="}:
2232
  op_token = tokens[index + 1]
2233
  if index + 2 < len(tokens) and tokens[index + 2].type == "id":
2234
  rhs_info = symbol_table.lookup_variable(tokens[index + 2].value)
@@ -2818,6 +2927,12 @@ def parse_fertile(tokens, index):
2818
 
2819
  return FertileDeclarationNode(var_type, var_name, value_node, line=line), index
2820
 
 
 
 
 
 
 
2821
  def parse_if(tokens, index, func_type):
2822
  line = tokens[index].line
2823
  index += 1 # Move past "spring"
@@ -3591,6 +3706,12 @@ def is_inside_loop_or_switch_stack():
3591
  return any(ctx in {"WhileNode", "DoWhileNode", "SwitchNode", "ForNode"} for ctx in context_stack)
3592
 
3593
 
 
 
 
 
 
 
3594
  def analyze_semantics(tokens):
3595
  """
3596
  Legacy API — builds AST from tokens and validates in one pass.
@@ -3870,6 +3991,11 @@ class ASTValidator:
3870
  self._walk(child)
3871
 
3872
 
 
 
 
 
 
3873
  def validate_ast(ast, symbol_table_data):
3874
  """Public API: validate an already-built AST.
3875
 
@@ -3886,4 +4012,4 @@ def validate_ast(ast, symbol_table_data):
3886
  dict with keys: success, errors, warnings, symbol_table, ast
3887
  """
3888
  validator = ASTValidator()
3889
- return validator.validate(ast, symbol_table_data)
 
1
+ # ============================================================================
2
+ # GAL SEMANTIC ANALYZER + AST BUILDER
3
+ # ============================================================================
4
+ # This file does THREE jobs:
5
+ # 1. Defines all AST node classes (ProgramNode, FunctionDeclarationNode,
6
+ # etc.) that the rest of the compiler consumes.
7
+ # 2. Provides the SymbolTable used to track declarations across scopes.
8
+ # 3. Provides build_ast(tokens) which walks the token stream and
9
+ # constructs the AST — and ALSO performs many semantic checks during
10
+ # construction (undeclared variables, duplicate functions, type
11
+ # mismatches in expressions). A separate ASTValidator does an extra
12
+ # tree-walking pass for checks that need the full AST visible.
13
+ #
14
+ # Pipeline position:
15
+ # lex -> parse -> THIS FILE (build AST + check semantics) -> ICG -> run
16
+ #
17
+ # Two entry points:
18
+ # build_ast(tokens) : called by Gal_Parser.parse_and_build
19
+ # validate_ast(ast, st) : called by server.py for the final tree pass
20
+ # analyze_semantics(toks): legacy one-shot entry (lex+parse already done)
21
+ # ============================================================================
22
+
23
  import re
24
 
25
+
26
+ # ============================================================================
27
+ # ERROR CLASS - Raised whenever the analyzer detects a semantic problem.
28
+ # Includes the source line so the IDE can highlight the right location.
29
+ # ============================================================================
30
  class SemanticError(Exception):
31
  def __init__(self, message, line):
32
  super().__init__(message)
 
36
  return self.message
37
 
38
 
39
+ # ============================================================================
40
+ # SEMANTIC ANALYZER (legacy placeholder)
41
+ # This class is a vestige of an earlier design. The actual semantic checks
42
+ # happen inside the parse_* functions below and inside ASTValidator at the
43
+ # bottom of this file. Kept for backward compatibility.
44
+ # ============================================================================
45
  class SemanticAnalyzer:
46
  def __init__(self, symbol_table):
47
  self.symbol_table = symbol_table
48
  self.visited_nodes = set()
49
 
50
 
51
+ # ============================================================================
52
+ # AST NODE CLASSES
53
+ # Each node has:
54
+ # - node_type : a string label (e.g. "Program", "VariableDeclaration")
55
+ # - value : the node's primary data (function name, operator, etc.)
56
+ # - children : list of child ASTNodes
57
+ # - line : source line for error reporting
58
+ # - parent : back-pointer for traversals (set by add_child)
59
+ # Subclasses below define convenient constructors for each AST shape.
60
+ # ============================================================================
61
  class ASTNode:
62
  def __init__(self, node_type, value=None, line=None):
63
  self.node_type = node_type # Type of node (e.g., 'VariableDeclaration', 'BinaryOp')
 
276
  self.members = members # dict: {member_name: member_type}
277
 
278
 
279
+ # ============================================================================
280
+ # SYMBOL TABLE - Tracks declarations during AST construction
281
+ # Stores variables, functions, and bundle (struct) types. Maintains a
282
+ # scope stack so the parser can detect 'undeclared' / 'redeclared' errors
283
+ # during build_ast. After AST construction the table is passed to
284
+ # ASTValidator for the second-pass checks (function arity, return types).
285
+ # ============================================================================
286
 
287
  class SymbolTable:
288
  def __init__(self):
 
393
  semantic_analyzer = SemanticAnalyzer(symbol_table)
394
  context_stack = []
395
 
396
+ # ============================================================================
397
+ # BUILD AST - Main entry point for AST construction
398
+ # ============================================================================
399
+ # Walks the token stream produced by the lexer (after parser validation)
400
+ # and constructs a tree of ASTNode objects. While walking it also performs
401
+ # many semantic checks via the parse_* helpers below (undeclared variables,
402
+ # duplicate functions, type mismatches in expressions, etc.).
403
+ #
404
+ # Called by Gal_Parser.parse_and_build right after LL(1) syntax validation.
405
+ # Returns the root ProgramNode. Errors are raised as SemanticError.
406
+ # ============================================================================
407
 
408
  def build_ast(tokens):
409
  """Constructs an AST from the token list after LL(1) parsing."""
 
477
  root.add_child(node)
478
 
479
  else:
480
+ raise SemanticError(f"Semantic Error: Expected data type for function declaration after 'pollinate'.", tokens[index].line)
481
 
482
  elif token.value == "fertile":
483
  node, index = parse_fertile(tokens, index)
 
577
  node, index = parse_variable(tokens, index, id_name, id_type)
578
 
579
  else:
580
+ error = f"Semantic Error: Invalid function or variable declaration."
581
  raise SemanticError(error, line)
582
 
583
  node.line = line
 
644
 
645
  return False
646
 
647
+ # ============================================================================
648
+ # DECLARATION PARSERS - parse_function, parse_variable
649
+ # These build the AST nodes for top-level declarations and register them
650
+ # in the symbol table. parse_function handles both root() and pollinate
651
+ # functions; parse_variable handles seed/tree/leaf/branch/vine declarations.
652
+ # ============================================================================
653
  def parse_function(tokens, index, func_name, func_type):
654
  line = tokens[index].line
655
 
 
672
  if tokens[index].type == "(":
673
  index += 1
674
  if tokens[index].type != ")":
675
+ raise SemanticError(f"Semantic Error: {func_name}() should not have parameters.", line)
676
  index += 1
677
  elif func_name == "root":
678
+ raise SemanticError("Semantic Error: Missing () for root function declaration.", line)
679
 
680
  params_node = ASTNode("Parameters")
681
  func_node = FunctionDeclarationNode(func_type, func_name, params_node)
682
 
683
  else:
684
  if tokens[index].type != "(":
685
+ error = f"Semantic Error: Missing () for function declaration."
686
  raise SemanticError(error, line)
687
 
688
  params_node = ASTNode("Parameters")
 
705
  if tokens[index].type == "[":
706
  index += 1 # skip '['
707
  if tokens[index].type != "]":
708
+ raise SemanticError(f"Semantic Error: Expected ']' after '[' in array parameter.", line)
709
  index += 1 # skip ']'
710
  is_list = True
711
  param_node.add_child(ASTNode("ArrayParam", "true"))
 
719
  index += 1
720
 
721
  else:
722
+ error = f"Semantic Error: Invalid parameter declaration."
723
  raise SemanticError(error, line)
724
 
725
  elif tokens[index].type == "id" and tokens[index].value in symbol_table.bundle_types:
 
740
  if tokens[index].type == ",":
741
  index += 1
742
  else:
743
+ error = f"Semantic Error: Invalid parameter declaration."
744
  raise SemanticError(error, line)
745
 
746
  else:
 
770
  # All functions (including root) must end with reclaim;
771
  if not has_any_return:
772
  if func_name == "root":
773
+ raise SemanticError(f"Semantic Error: root() must end with 'reclaim;'.", line)
774
  elif func_type == "empty":
775
+ raise SemanticError(f"Semantic Error: Function '{func_name}' must end with 'reclaim;'.", line)
776
 
777
  index += 1
778
  func_node.add_child(block_node)
779
  symbol_table.exit_scope()
780
  symbol_table.current_func_name = None
781
  else:
782
+ error = f"Semantic Error: Function body must be enclosed in curly braces."
783
  raise SemanticError(error, line)
784
 
785
  return func_node, index
 
829
  water_line = tokens[index].line
830
  index += 1 # skip 'water'
831
  if tokens[index].type != "(":
832
+ raise SemanticError(f"Semantic Error: Expected '(' after water.", water_line)
833
  index += 1 # skip '('
834
  water_type = None
835
  if tokens[index].value in {"seed", "tree", "leaf", "branch", "vine"}:
 
934
  return index
935
 
936
 
937
+ # ============================================================================
938
+ # STATEMENT PARSER - The big dispatch
939
+ # Walks one statement at a time inside a function body. Recognizes every
940
+ # statement form: variable declaration, assignment, function call,
941
+ # spring/bud/wither, grow/cultivate/tend, harvest, plant, water,
942
+ # reclaim, prune, skip. Returns (ast_node, new_index).
943
+ # ============================================================================
944
  def parse_statement(tokens, index, func_type = None):
945
  token = tokens[index]
946
 
 
1697
  return left_node, index
1698
 
1699
 
1700
+ # ============================================================================
1701
+ # EXPRESSION PARSER - Operator-precedence climbing
1702
+ # Standard precedence ladder built from these layered functions:
1703
+ # parse_expression : + - ` (lowest precedence)
1704
+ # parse_term : * / %
1705
+ # parse_power : ** (right-associative)
1706
+ # parse_unary : ~ ! ++ --
1707
+ # parse_factor : literals, identifiers, function calls,
1708
+ # parenthesized expressions (highest)
1709
+ # Each layer calls the next-higher-precedence layer for its operands.
1710
+ # All return (ast_node, new_index, inferred_type).
1711
+ # ============================================================================
1712
  def parse_expression(tokens, index):
1713
  """Parses an expression with +, -, and ` (string concat).
1714
  Returns (node, index, type_str)."""
 
1758
  def parse_term(tokens, index):
1759
  """Parses multiplication, division, and modulus with type checking.
1760
  Returns (node, index, type_str)."""
1761
+ left_node, index, left_type = parse_power(tokens, index)
1762
 
1763
  while tokens[index].type in {"*", "/", "%"}:
1764
  op = tokens[index].value
 
1781
  )
1782
 
1783
  index += 1
1784
+ right_node, index, right_type = parse_power(tokens, index)
1785
 
1786
  # Validate right operand is numeric
1787
  if right_type not in {"seed", "tree"}:
 
1811
 
1812
  return left_node, index, left_type
1813
 
1814
+ def parse_power(tokens, index):
1815
+ """Parses right-associative exponentiation (**).
1816
+ Returns (node, index, type_str)."""
1817
+ left_node, index, left_type = parse_unary(tokens, index)
1818
+
1819
+ if tokens[index].type == "**":
1820
+ op = tokens[index].value
1821
+ token = tokens[index]
1822
+
1823
+ if left_type not in {"seed", "tree"}:
1824
+ raise SemanticError(
1825
+ f"Semantic Error: Cannot use '{op}' on type '{left_type}'. Expected 'seed' or 'tree'.",
1826
+ token.line,
1827
+ )
1828
+
1829
+ index += 1
1830
+ right_node, index, right_type = parse_power(tokens, index)
1831
+
1832
+ if right_type not in {"seed", "tree"}:
1833
+ raise SemanticError(
1834
+ f"Semantic Error: Cannot use '{op}' on type '{right_type}'. Expected 'seed' or 'tree'.",
1835
+ token.line,
1836
+ )
1837
+
1838
+ left_node = BinaryOpNode(left_node, op, right_node, line=token.line)
1839
+ if left_type == "tree" or right_type == "tree":
1840
+ left_type = "tree"
1841
+
1842
+ return left_node, index, left_type
1843
+
1844
  def parse_unary(tokens, index):
1845
  """Returns (node, index, type_str)."""
1846
 
 
2337
 
2338
  if is_list and tokens[index + 1].type != "[":
2339
  # Check if this is an array <op> array case (e.g., x = a + b)
2340
+ if tokens[index + 1].type in {"+", "-", "*", "/", "%", "**", "==", "!=", ">", "<", ">=", "<="}:
2341
  op_token = tokens[index + 1]
2342
  if index + 2 < len(tokens) and tokens[index + 2].type == "id":
2343
  rhs_info = symbol_table.lookup_variable(tokens[index + 2].value)
 
2927
 
2928
  return FertileDeclarationNode(var_type, var_name, value_node, line=line), index
2929
 
2930
+ # ============================================================================
2931
+ # CONTROL-FLOW PARSERS - parse_if / parse_for / parse_while / parse_do /
2932
+ # parse_switch. Each builds the matching AST node (IfStatementNode,
2933
+ # ForLoopNode, etc.) and recursively parses the body via parse_statement.
2934
+ # Conditions must evaluate to a branch (boolean) — checked here.
2935
+ # ============================================================================
2936
  def parse_if(tokens, index, func_type):
2937
  line = tokens[index].line
2938
  index += 1 # Move past "spring"
 
3706
  return any(ctx in {"WhileNode", "DoWhileNode", "SwitchNode", "ForNode"} for ctx in context_stack)
3707
 
3708
 
3709
+ # ============================================================================
3710
+ # analyze_semantics() - LEGACY ONE-SHOT ENTRY POINT
3711
+ # Older API that does build_ast in one call. The current pipeline uses
3712
+ # the two-step parse_and_build + validate_ast instead so the IDE can
3713
+ # distinguish 'syntax' from 'semantic' error stages.
3714
+ # ============================================================================
3715
  def analyze_semantics(tokens):
3716
  """
3717
  Legacy API — builds AST from tokens and validates in one pass.
 
3991
  self._walk(child)
3992
 
3993
 
3994
+ # ============================================================================
3995
+ # validate_ast() - PUBLIC SEMANTIC-ANALYSIS ENTRY POINT
3996
+ # Used by server.py after parse_and_build succeeds. Wraps ASTValidator.
3997
+ # Returns a dict with success/errors/warnings/symbol_table/ast.
3998
+ # ============================================================================
3999
  def validate_ast(ast, symbol_table_data):
4000
  """Public API: validate an already-built AST.
4001
 
 
4012
  dict with keys: success, errors, warnings, symbol_table, ast
4013
  """
4014
  validator = ASTValidator()
4015
+ return validator.validate(ast, symbol_table_data)
Backend/Gal_Parser.py CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
 
2
  from __future__ import annotations
3
 
@@ -12,6 +29,11 @@ from GALsemantic import (
12
  )
13
 
14
 
 
 
 
 
 
15
  @dataclass(frozen=True)
16
  class _TokView:
17
  """Lightweight view to normalize token access."""
@@ -24,12 +46,14 @@ class _TokView:
24
  def _as_tok(token: Any) -> _TokView:
25
  """Normalize token objects/dicts to a common view."""
26
  if isinstance(token, Mapping):
 
27
  return _TokView(
28
  type=str(token.get("type", "")),
29
  value=str(token.get("value", "")),
30
  line=int(token.get("line", 0) or 0),
31
  col=int(token.get("col", 0) or 0),
32
  )
 
33
  return _TokView(
34
  type=str(getattr(token, "type", "")),
35
  value=str(getattr(token, "value", "")),
@@ -38,6 +62,9 @@ def _as_tok(token: Any) -> _TokView:
38
  )
39
 
40
 
 
 
 
41
  class LL1Parser:
42
  def __init__(
43
  self,
@@ -72,6 +99,13 @@ class LL1Parser:
72
 
73
  self.parsing_table: Dict[str, Dict[str, List[str]]] = self.construct_parsing_table()
74
 
 
 
 
 
 
 
 
75
  def construct_parsing_table(self) -> Dict[str, Dict[str, List[str]]]:
76
  """Build LL(1) parsing table using provided PREDICT sets."""
77
  table: Dict[str, Dict[str, List[str]]] = {}
@@ -82,6 +116,8 @@ class LL1Parser:
82
  key = (non_terminal, tuple(production))
83
  terms = self.predict_sets.get(key, set())
84
  for terminal in terms:
 
 
85
  if terminal in row and row[terminal] != production:
86
  raise ValueError(
87
  f"LL(1) conflict at {non_terminal} with lookahead {terminal}: "
@@ -91,6 +127,13 @@ class LL1Parser:
91
  table[non_terminal] = row
92
  return table
93
 
 
 
 
 
 
 
 
94
  def _normalize_token_type(self, token_type: str) -> str:
95
  """Map lexer token types into the terminal names used by the CFG."""
96
  return self.token_type_alias.get(token_type, token_type)
@@ -129,6 +172,13 @@ class LL1Parser:
129
  'EOF': 'end of file',
130
  }
131
 
 
 
 
 
 
 
 
132
  def _format_expected(self, expected: Set[str], non_terminal: Optional[str] = None) -> str:
133
  """Return a human-readable string listing the expected terminals.
134
 
@@ -157,6 +207,13 @@ class LL1Parser:
157
  return 'nothing'
158
  return f"Expected: {', '.join(parts)}"
159
 
 
 
 
 
 
 
 
160
  def _generate_helpful_error(
161
  self,
162
  non_terminal: str,
@@ -728,6 +785,15 @@ class LL1Parser:
728
  # Default message with helpful context
729
  return f"SYNTAX error line {line} col {col} Unexpected token '{token_value}'. {self._format_expected(expected, non_terminal)}"
730
 
 
 
 
 
 
 
 
 
 
731
  def parse(self, tokens: Sequence[Any]) -> Tuple[bool, List[str]]:
732
  """Parse tokens according to the supplied CFG/PREDICT sets.
733
 
@@ -1394,8 +1460,15 @@ class LL1Parser:
1394
 
1395
  return True, []
1396
 
1397
- # ── AST Construction ─────────────────────────────────────────────
1398
-
 
 
 
 
 
 
 
1399
  def parse_and_build(self, tokens: Sequence[Any]):
1400
  """Validate syntax with LL(1) grammar, then build AST.
1401
 
 
1
+ # ============================================================================
2
+ # GAL LL(1) PARSER - Table-driven syntax analysis + AST construction
3
+ # ============================================================================
4
+ # This is the syntax-analysis stage of the compiler. It consumes the token
5
+ # stream from the lexer and validates it against the GAL grammar (defined
6
+ # in cfg.py). The parser is LL(1) — it picks a production using one token
7
+ # of lookahead via the precomputed PREDICT sets.
8
+ #
9
+ # Pipeline position:
10
+ # lex -> THIS FILE (parse + build AST) -> semantic -> ICG -> interpret
11
+ #
12
+ # The parser exposes two entry points:
13
+ # parse(tokens) : syntax-only check, returns (success, errors)
14
+ # parse_and_build(tokens) : syntax + AST construction (delegates to
15
+ # GALsemantic.build_ast), returns dict with
16
+ # ast/errors/symbol_table/error_stage
17
+ # ============================================================================
18
 
19
  from __future__ import annotations
20
 
 
29
  )
30
 
31
 
32
+ # ============================================================================
33
+ # TOKEN VIEW HELPERS - The parser accepts tokens as either Token objects
34
+ # or dicts (e.g. when reloaded from JSON). _TokView gives a uniform shape
35
+ # so the parsing loop doesn't have to handle both cases.
36
+ # ============================================================================
37
  @dataclass(frozen=True)
38
  class _TokView:
39
  """Lightweight view to normalize token access."""
 
46
  def _as_tok(token: Any) -> _TokView:
47
  """Normalize token objects/dicts to a common view."""
48
  if isinstance(token, Mapping):
49
+ # Dict-shaped token (came from a JSON request body)
50
  return _TokView(
51
  type=str(token.get("type", "")),
52
  value=str(token.get("value", "")),
53
  line=int(token.get("line", 0) or 0),
54
  col=int(token.get("col", 0) or 0),
55
  )
56
+ # Token object (the lexer's normal output)
57
  return _TokView(
58
  type=str(getattr(token, "type", "")),
59
  value=str(getattr(token, "value", "")),
 
62
  )
63
 
64
 
65
+ # ============================================================================
66
+ # LL1Parser - The table-driven LL(1) parser
67
+ # ============================================================================
68
  class LL1Parser:
69
  def __init__(
70
  self,
 
99
 
100
  self.parsing_table: Dict[str, Dict[str, List[str]]] = self.construct_parsing_table()
101
 
102
+ # ========================================================================
103
+ # PARSING TABLE CONSTRUCTION
104
+ # Builds the LL(1) parsing table from the CFG + PREDICT sets.
105
+ # Layout: table[non_terminal][lookahead_token] = production_to_apply.
106
+ # Raises ValueError if the grammar isn't LL(1) (two productions claim
107
+ # the same lookahead) — this is the compile-time correctness check.
108
+ # ========================================================================
109
  def construct_parsing_table(self) -> Dict[str, Dict[str, List[str]]]:
110
  """Build LL(1) parsing table using provided PREDICT sets."""
111
  table: Dict[str, Dict[str, List[str]]] = {}
 
116
  key = (non_terminal, tuple(production))
117
  terms = self.predict_sets.get(key, set())
118
  for terminal in terms:
119
+ # An LL(1) conflict means the grammar can't be parsed
120
+ # with one token of lookahead — fix the grammar first.
121
  if terminal in row and row[terminal] != production:
122
  raise ValueError(
123
  f"LL(1) conflict at {non_terminal} with lookahead {terminal}: "
 
127
  table[non_terminal] = row
128
  return table
129
 
130
+
131
+ # ========================================================================
132
+ # TOKEN NORMALIZATION HELPERS - Bridge between lexer and grammar
133
+ # The lexer emits some token types that don't match the CFG terminal
134
+ # names (e.g. 'dbllit' from lexer vs 'dblit' in cfg.py). The alias map
135
+ # papers over those differences in one place.
136
+ # ========================================================================
137
  def _normalize_token_type(self, token_type: str) -> str:
138
  """Map lexer token types into the terminal names used by the CFG."""
139
  return self.token_type_alias.get(token_type, token_type)
 
172
  'EOF': 'end of file',
173
  }
174
 
175
+ # ========================================================================
176
+ # ERROR-MESSAGE HELPERS
177
+ # When the parser hits a token that doesn't match any production, we
178
+ # build a friendly "Expected: X, Y, Z" string from the parsing-table
179
+ # row. _generate_helpful_error adds context-aware hints (e.g. "did you
180
+ # mean '==' instead of '='?").
181
+ # ========================================================================
182
  def _format_expected(self, expected: Set[str], non_terminal: Optional[str] = None) -> str:
183
  """Return a human-readable string listing the expected terminals.
184
 
 
207
  return 'nothing'
208
  return f"Expected: {', '.join(parts)}"
209
 
210
+ # ========================================================================
211
+ # _GENERATE_HELPFUL_ERROR - The big one
212
+ # When a token doesn't match, this method inspects context (previous
213
+ # tokens, the non-terminal we're inside, common typos like '==='/' &&&')
214
+ # and produces a SPECIFIC error rather than a generic "Expected: ..."
215
+ # message. This is what makes GAL's error messages friendly.
216
+ # ========================================================================
217
  def _generate_helpful_error(
218
  self,
219
  non_terminal: str,
 
785
  # Default message with helpful context
786
  return f"SYNTAX error line {line} col {col} Unexpected token '{token_value}'. {self._format_expected(expected, non_terminal)}"
787
 
788
+ # ========================================================================
789
+ # parse() - LL(1) SYNTAX VALIDATION (no AST built)
790
+ # The classic table-driven LL(1) algorithm: maintain a parse stack
791
+ # initialized with the start symbol, then for each input token either
792
+ # 'match' a terminal (pop stack + advance input) or 'expand' a
793
+ # non-terminal (look up table[NT][lookahead], push the production
794
+ # backwards onto the stack). Returns (success, error_messages_list).
795
+ # Used by /api/parse for syntax-only checking.
796
+ # ========================================================================
797
  def parse(self, tokens: Sequence[Any]) -> Tuple[bool, List[str]]:
798
  """Parse tokens according to the supplied CFG/PREDICT sets.
799
 
 
1460
 
1461
  return True, []
1462
 
1463
+ # ========================================================================
1464
+ # parse_and_build() - SYNTAX + AST CONSTRUCTION (full parser entry)
1465
+ # First runs the LL(1) check; if it passes, delegates to
1466
+ # GALsemantic.build_ast which walks the same token stream and
1467
+ # constructs the AST. Some semantic errors (undeclared variables,
1468
+ # duplicate functions) are caught during AST construction and reported
1469
+ # with error_stage='semantic' so the IDE can label them correctly.
1470
+ # Used by /api/semantic, /api/icg, /api/run, and Socket.IO 'run_code'.
1471
+ # ========================================================================
1472
  def parse_and_build(self, tokens: Sequence[Any]):
1473
  """Validate syntax with LL(1) grammar, then build AST.
1474
 
Backend/cfg.py CHANGED
@@ -1,7 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import sys
2
  from collections import defaultdict
3
 
4
- # Set UTF-8 encoding for Windows console
5
  if sys.platform == 'win32':
6
  try:
7
  sys.stdout.reconfigure(encoding='utf-8')
@@ -168,7 +187,7 @@ def compute_predict(cfg, first, follow):
168
  predict[key] = first_set
169
  # If production can derive epsilon, add FOLLOW(lhs)
170
  if epsilon in first_set:
171
- predict[key] |= follow[lhs]
172
 
173
  return predict
174
 
@@ -703,7 +722,8 @@ cfg = {
703
  # 3. Relational (>, <, >=, <=, ==, !=)
704
  # 4. Arithmetic (+, -)
705
  # 5. Term (*, /, %)
706
- # 6. Factor (literals, variables, function calls, parentheses)
 
707
 
708
  # Level 1: Logical OR (lowest precedence)
709
  # Example: a || b || c
@@ -769,17 +789,28 @@ cfg = {
769
  # Level 5: Term (multiplication/division/modulo)
770
  # Example: a * b / c % d
771
  "<term>": [
772
- ["<factor>", "<term_next>"],
773
  ],
774
 
775
  "<term_next>": [
776
- ["*", "<factor>", "<term_next>"], # Multiplication
777
- ["/", "<factor>", "<term_next>"], # Division
778
- ["%", "<factor>", "<term_next>"], # Modulo
779
  [EPSILON], # End
780
  ],
781
 
782
- # Level 6: Factor (highest precedence - literals, variables, etc.)
 
 
 
 
 
 
 
 
 
 
 
783
  "<factor>": [
784
  ["(", "<paren_expr>"], # Cast or parenthesized expression
785
  ["<unary_op>", "<factor>"], # Unary operation (e.g., ~x, !flag)
 
1
+ # ============================================================================
2
+ # GAL CONTEXT-FREE GRAMMAR + PARSE TABLE
3
+ # ============================================================================
4
+ # This file contains the grammar that defines GAL syntax and the helpers
5
+ # that build the LL(1) parse table from it. Three artifacts are exported:
6
+ #
7
+ # cfg : Dict[non_terminal -> List[List[symbol]]] productions
8
+ # first_sets : Dict[non_terminal -> Set[terminal]] FIRST sets
9
+ # predict_sets : Dict[(non_terminal, production) -> Set[terminal]]
10
+ #
11
+ # The parser (Gal_Parser.LL1Parser) consumes these to drive its table-
12
+ # driven LL(1) algorithm. λ (lambda) denotes the empty production.
13
+ #
14
+ # To add or change grammar rules:
15
+ # 1. Edit the cfg dict at the bottom of this file
16
+ # 2. Run this module — FIRST/FOLLOW/PREDICT are recomputed automatically
17
+ # 3. The parser will detect any LL(1) conflict at startup
18
+ # ============================================================================
19
+
20
  import sys
21
  from collections import defaultdict
22
 
23
+ # Set UTF-8 encoding for Windows console (so λ prints correctly during dev)
24
  if sys.platform == 'win32':
25
  try:
26
  sys.stdout.reconfigure(encoding='utf-8')
 
187
  predict[key] = first_set
188
  # If production can derive epsilon, add FOLLOW(lhs)
189
  if epsilon in first_set:
190
+ predict[key] |= follow[lhs]
191
 
192
  return predict
193
 
 
722
  # 3. Relational (>, <, >=, <=, ==, !=)
723
  # 4. Arithmetic (+, -)
724
  # 5. Term (*, /, %)
725
+ # 6. Power (**)
726
+ # 7. Factor (literals, variables, function calls, parentheses)
727
 
728
  # Level 1: Logical OR (lowest precedence)
729
  # Example: a || b || c
 
789
  # Level 5: Term (multiplication/division/modulo)
790
  # Example: a * b / c % d
791
  "<term>": [
792
+ ["<power>", "<term_next>"],
793
  ],
794
 
795
  "<term_next>": [
796
+ ["*", "<power>", "<term_next>"], # Multiplication
797
+ ["/", "<power>", "<term_next>"], # Division
798
+ ["%", "<power>", "<term_next>"], # Modulo
799
  [EPSILON], # End
800
  ],
801
 
802
+ # Level 6: Power (right-associative exponentiation)
803
+ # Example: a ** b ** c
804
+ "<power>": [
805
+ ["<factor>", "<power_next>"],
806
+ ],
807
+
808
+ "<power_next>": [
809
+ ["**", "<power>"], # Exponentiation
810
+ [EPSILON], # End
811
+ ],
812
+
813
+ # Level 7: Factor (highest precedence - literals, variables, etc.)
814
  "<factor>": [
815
  ["(", "<paren_expr>"], # Cast or parenthesized expression
816
  ["<unary_op>", "<factor>"], # Unary operation (e.g., ~x, !flag)
Backend/icg.py CHANGED
@@ -3,6 +3,17 @@
3
  # ============================================================================
4
  # Generates three-address code (TAC) from a GAL token stream.
5
  #
 
 
 
 
 
 
 
 
 
 
 
6
  # The output is a list of TAC instructions (quad-like) that can be further
7
  # optimised or translated to target code.
8
  #
@@ -987,15 +998,25 @@ class ICGenerator:
987
 
988
  def _term(self) -> str:
989
  """<term> → <factor> <term_next>"""
990
- left = self._factor()
991
  while self._peek().type in ("*", "/", "%"):
992
  op = self._advance().type
993
- right = self._factor()
994
  tmp = self._new_temp()
995
  self._emit(op, left, right, tmp)
996
  left = tmp
997
  return left
998
 
 
 
 
 
 
 
 
 
 
 
999
  def _factor(self) -> str:
1000
  """<factor> → ( <expr> ) | <unary_op> <factor> | id ... | literal"""
1001
  tok = self._peek()
 
3
  # ============================================================================
4
  # Generates three-address code (TAC) from a GAL token stream.
5
  #
6
+ # IMPORTANT: ICG output is DISPLAY-ONLY. The interpreter (GALinterpreter.py)
7
+ # does NOT consume this output — it walks the AST directly. This module
8
+ # exists so the IDE can show students what intermediate code their GAL
9
+ # program would compile to. Pipeline position:
10
+ #
11
+ # lex -> parse -> AST -> semantic -> THIS FILE (display) -> interpret(AST)
12
+ # \________________/
13
+ # parallel pass; not on runtime path
14
+ #
15
+ # Called from server.py /api/icg endpoint.
16
+ #
17
  # The output is a list of TAC instructions (quad-like) that can be further
18
  # optimised or translated to target code.
19
  #
 
998
 
999
  def _term(self) -> str:
1000
  """<term> → <factor> <term_next>"""
1001
+ left = self._power()
1002
  while self._peek().type in ("*", "/", "%"):
1003
  op = self._advance().type
1004
+ right = self._power()
1005
  tmp = self._new_temp()
1006
  self._emit(op, left, right, tmp)
1007
  left = tmp
1008
  return left
1009
 
1010
+ def _power(self) -> str:
1011
+ left = self._factor()
1012
+ if self._peek().type == "**":
1013
+ op = self._advance().type
1014
+ right = self._power()
1015
+ tmp = self._new_temp()
1016
+ self._emit(op, left, right, tmp)
1017
+ return tmp
1018
+ return left
1019
+
1020
  def _factor(self) -> str:
1021
  """<factor> → ( <expr> ) | <unary_op> <factor> | id ... | literal"""
1022
  tok = self._peek()
Backend/lexer.py CHANGED
@@ -323,140 +323,148 @@ class Lexer:
323
  - tokens: list of Token objects
324
  - errors: list of LexicalError objects
325
  """
326
- tokens = [] # List to store all tokens found
327
- line = 1 # Current line number (for token tracking)
328
- errors = [] # List to store all lexical errors found
329
- pos = self.pos.copy() # Initialize pos for EOF handling (avoids crash on empty source)
330
-
331
- # Main loop: process each character until end of file
332
- while self.current_char != None:
333
-
334
  # =====================================================================
335
  # KEYWORD & IDENTIFIER RECOGNITION
336
- # Check if current character starts a keyword or identifier (letter)
 
 
337
  # =====================================================================
338
- if self.current_char in ALPHA:
339
- ident_str = '' # String to build the identifier/keyword
340
- pos = self.pos.copy() # Save position for error reporting
341
-
342
  # --- Letter B: 'branch', 'bud', 'bundle' ---
343
- if self.current_char == "b":
344
- ident_str += self.current_char
345
- self.advance()
346
- if self.current_char == "r": # branch
347
- ident_str += self.current_char
348
- self.advance()
349
- if self.current_char == "a":
350
- ident_str += self.current_char
351
- self.advance()
352
- if self.current_char == "n":
353
- ident_str += self.current_char
354
- self.advance()
355
- if self.current_char == "c":
356
- ident_str += self.current_char
357
- self.advance()
358
- if self.current_char == "h":
359
- ident_str += self.current_char
360
- self.advance()
361
- # Branch keyword recognized - emit token
 
362
  if self.current_char is None or self.current_char in space_delim or self.current_char == ';':
363
- tokens.append(Token(TT_RW_BRANCH, ident_str, line, pos.col))
364
- continue
365
- elif self.current_char not in ALPHANUM:
366
- tokens.append(Token(TT_RW_BRANCH, ident_str, line, pos.col))
367
- continue
368
- elif self.current_char == "u":
369
- ident_str += self.current_char
370
- self.advance()
371
- if self.current_char == "d": # bud
372
- ident_str += self.current_char
373
- self.advance()
 
374
  if self.current_char is None or (self.current_char is not None and self.current_char.isspace()) or self.current_char in delim4:
375
- tokens.append(Token(TT_RW_BUD, ident_str, line, pos.col))
376
- continue
377
  elif self.current_char is not None and not self.current_char.isspace() and self.current_char not in delim4 and self.current_char not in ALPHANUM:
 
378
  errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'"))
379
- self.advance()
380
- continue
381
- elif self.current_char == "n": # bundle
382
- ident_str += self.current_char
383
- self.advance()
384
- if self.current_char == "d":
385
- ident_str += self.current_char
386
- self.advance()
387
- if self.current_char == "l":
388
- ident_str += self.current_char
389
- self.advance()
390
- if self.current_char == "e":
391
- ident_str += self.current_char
392
- self.advance()
393
- if self.current_char is not None and self.current_char in space_delim: # struct delimiter (was hawk_dlm)
394
- tokens.append(Token(TT_RW_BUNDLE, ident_str, line, pos.col))
395
- continue
396
  elif self.current_char is not None and self.current_char not in space_delim and self.current_char not in ALPHANUM:
 
397
  errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'"))
398
- self.advance()
399
- continue
400
-
401
  #Letter C
402
- elif self.current_char == "c":
403
- ident_str += self.current_char
404
- self.advance()
405
- if self.current_char == "u": # cultivate
406
- ident_str += self.current_char
407
- self.advance()
408
- if self.current_char == "l":
409
- ident_str += self.current_char
410
- self.advance()
411
- if self.current_char == "t":
412
- ident_str += self.current_char
413
- self.advance()
414
- if self.current_char == "i":
415
- ident_str += self.current_char
416
- self.advance()
417
- if self.current_char == "v":
418
- ident_str += self.current_char
419
- self.advance()
420
- if self.current_char == "a":
421
- ident_str += self.current_char
422
- self.advance()
423
- if self.current_char == "t":
424
- ident_str += self.current_char
425
- self.advance()
426
- if self.current_char == "e":
427
- ident_str += self.current_char
428
- self.advance()
 
429
  if self.current_char is None or (self.current_char is not None and self.current_char.isspace()) or self.current_char in delim4:
430
- tokens.append(Token(TT_RW_CULTIVATE, ident_str, line, pos.col))
431
- continue
432
  elif self.current_char is not None and not self.current_char.isspace() and self.current_char not in delim4 and self.current_char not in ALPHANUM:
433
- errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'"))
434
- self.advance()
435
- continue
436
-
437
  # Letter E
438
- elif self.current_char == "e":
439
- ident_str += self.current_char
440
- self.advance()
441
- if self.current_char == "m": # empty
442
- ident_str += self.current_char
443
- self.advance()
444
- if self.current_char == "p":
445
- ident_str += self.current_char
446
- self.advance()
447
- if self.current_char == "t":
448
- ident_str += self.current_char
449
- self.advance()
450
- if self.current_char == "y":
451
- ident_str += self.current_char
452
- self.advance()
 
453
  if self.current_char is None or (self.current_char is not None and self.current_char.isspace()) or self.current_char in space_delim:
454
- tokens.append(Token(TT_RW_EMPTY, ident_str, line, pos.col))
455
- continue
456
  elif self.current_char is not None and not self.current_char.isspace() and self.current_char not in space_delim and self.current_char not in ALPHANUM:
457
- errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'"))
458
- self.advance()
459
- continue
460
 
461
  # Letter F
462
  elif self.current_char == "f":
 
323
  - tokens: list of Token objects
324
  - errors: list of LexicalError objects
325
  """
326
+ tokens = [] # accumulator: every recognized Token is appended here
327
+ line = 1 # running line number (1-indexed for user-facing errors)
328
+ errors = [] # accumulator: every LexicalError encountered is appended here
329
+ pos = self.pos.copy() # snapshot of current pos; reused as fallback for EOF token at end
330
+
331
+ # Main loop: drive the FSM one character at a time until source is exhausted (current_char becomes None).
332
+ while self.current_char != None: # None sentinel = end of source_code reached
333
+
334
  # =====================================================================
335
  # KEYWORD & IDENTIFIER RECOGNITION
336
+ # Hand-written transition diagram: each branch matches one keyword.
337
+ # If no keyword path completes, the trailing "else" falls through to
338
+ # generic identifier scanning at the bottom of this if-block.
339
  # =====================================================================
340
+ if self.current_char in ALPHA: # only letters can start a keyword/identifier (digits cannot)
341
+ ident_str = '' # buffer that will hold the lexeme as we walk it character-by-character
342
+ pos = self.pos.copy() # capture starting position so error/Token carries the *first* char's line/col
343
+
344
  # --- Letter B: 'branch', 'bud', 'bundle' ---
345
+ if self.current_char == "b": # FSM root for words starting with 'b'
346
+ ident_str += self.current_char # buffer the 'b'
347
+ self.advance() # consume it; current_char now points to the 2nd letter
348
+ if self.current_char == "r": # 'b'+'r' → potentially "branch"
349
+ ident_str += self.current_char # buffer the 'r'
350
+ self.advance() # consume 'r'; look at 3rd letter
351
+ if self.current_char == "a": # 'br'+'a' → still on track for "branch"
352
+ ident_str += self.current_char # buffer the 'a'
353
+ self.advance() # consume 'a'
354
+ if self.current_char == "n": # 'bra'+'n'
355
+ ident_str += self.current_char # buffer the 'n'
356
+ self.advance() # consume 'n'
357
+ if self.current_char == "c": # 'bran'+'c'
358
+ ident_str += self.current_char # buffer the 'c'
359
+ self.advance() # consume 'c'
360
+ if self.current_char == "h": # 'branc'+'h' → full keyword spelled out
361
+ ident_str += self.current_char # buffer the trailing 'h'
362
+ self.advance() # consume 'h'; current_char is now whatever comes AFTER "branch"
363
+ # Maximal-munch check: only emit BRANCH token if the next char is a legal delimiter.
364
+ # Otherwise "branchx" must become an identifier, not keyword+identifier.
365
  if self.current_char is None or self.current_char in space_delim or self.current_char == ';':
366
+ tokens.append(Token(TT_RW_BRANCH, ident_str, line, pos.col)) # emit reserved-word token
367
+ continue # restart the outer while loop — do NOT fall through to identifier scan
368
+ elif self.current_char not in ALPHANUM: # any non-alphanumeric (e.g. '(', '{') also closes the keyword
369
+ tokens.append(Token(TT_RW_BRANCH, ident_str, line, pos.col)) # emit reserved-word token
370
+ continue # restart the outer while loop
371
+ elif self.current_char == "u": # 'b'+'u' → either "bud" or "bundle"
372
+ ident_str += self.current_char # buffer the 'u'
373
+ self.advance() # consume 'u'
374
+ if self.current_char == "d": # 'bu'+'d' → potentially "bud"
375
+ ident_str += self.current_char # buffer the 'd'
376
+ self.advance() # consume 'd'; check what follows
377
+ # Maximal-munch: "bud" needs whitespace or delim4 ({':', '('}) to terminate.
378
  if self.current_char is None or (self.current_char is not None and self.current_char.isspace()) or self.current_char in delim4:
379
+ tokens.append(Token(TT_RW_BUD, ident_str, line, pos.col)) # emit BUD reserved-word token
380
+ continue # restart outer loop on next char
381
  elif self.current_char is not None and not self.current_char.isspace() and self.current_char not in delim4 and self.current_char not in ALPHANUM:
382
+ # Strict rule: an illegal delimiter after the keyword is a lexical error (not a fallback to identifier).
383
  errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'"))
384
+ self.advance() # skip the bad char so we don't loop forever
385
+ continue # back to outer scan
386
+ elif self.current_char == "n": # 'bu'+'n' → potentially "bundle"
387
+ ident_str += self.current_char # buffer 'n'
388
+ self.advance() # consume 'n'
389
+ if self.current_char == "d": # 'bun'+'d'
390
+ ident_str += self.current_char # buffer 'd'
391
+ self.advance() # consume 'd'
392
+ if self.current_char == "l": # 'bund'+'l'
393
+ ident_str += self.current_char # buffer 'l'
394
+ self.advance() # consume 'l'
395
+ if self.current_char == "e": # 'bundl'+'e' → "bundle" complete
396
+ ident_str += self.current_char # buffer trailing 'e'
397
+ self.advance() # consume 'e'
398
+ if self.current_char is not None and self.current_char in space_delim: # bundle requires whitespace next
399
+ tokens.append(Token(TT_RW_BUNDLE, ident_str, line, pos.col)) # emit BUNDLE token
400
+ continue # next iteration
401
  elif self.current_char is not None and self.current_char not in space_delim and self.current_char not in ALPHANUM:
402
+ # Anything else (and not a letter that would extend it to an identifier) → illegal delimiter error.
403
  errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'"))
404
+ self.advance() # skip bad char
405
+ continue # restart outer scan
406
+
407
  #Letter C
408
+ elif self.current_char == "c": # FSM root for words starting with 'c' (only "cultivate")
409
+ ident_str += self.current_char # buffer 'c'
410
+ self.advance() # consume 'c'
411
+ if self.current_char == "u": # 'c'+'u' → on track for "cultivate"
412
+ ident_str += self.current_char # buffer 'u'
413
+ self.advance() # consume 'u'
414
+ if self.current_char == "l": # 'cu'+'l'
415
+ ident_str += self.current_char # buffer 'l'
416
+ self.advance() # consume 'l'
417
+ if self.current_char == "t": # 'cul'+'t'
418
+ ident_str += self.current_char # buffer 't'
419
+ self.advance() # consume 't'
420
+ if self.current_char == "i": # 'cult'+'i'
421
+ ident_str += self.current_char # buffer 'i'
422
+ self.advance() # consume 'i'
423
+ if self.current_char == "v": # 'culti'+'v'
424
+ ident_str += self.current_char # buffer 'v'
425
+ self.advance() # consume 'v'
426
+ if self.current_char == "a": # 'cultiv'+'a'
427
+ ident_str += self.current_char # buffer 'a'
428
+ self.advance() # consume 'a'
429
+ if self.current_char == "t": # 'cultiva'+'t'
430
+ ident_str += self.current_char # buffer 't'
431
+ self.advance() # consume 't'
432
+ if self.current_char == "e": # 'cultivat'+'e' → "cultivate" complete
433
+ ident_str += self.current_char # buffer trailing 'e'
434
+ self.advance() # consume 'e'
435
+ # cultivate (for-loop) requires whitespace or delim4 ({':', '('}) next.
436
  if self.current_char is None or (self.current_char is not None and self.current_char.isspace()) or self.current_char in delim4:
437
+ tokens.append(Token(TT_RW_CULTIVATE, ident_str, line, pos.col)) # emit CULTIVATE token
438
+ continue # next iteration
439
  elif self.current_char is not None and not self.current_char.isspace() and self.current_char not in delim4 and self.current_char not in ALPHANUM:
440
+ errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'")) # illegal trailer
441
+ self.advance() # skip bad char
442
+ continue # restart outer scan
443
+
444
  # Letter E
445
+ elif self.current_char == "e": # FSM root for 'e' (only "empty")
446
+ ident_str += self.current_char # buffer 'e'
447
+ self.advance() # consume 'e'
448
+ if self.current_char == "m": # 'e'+'m' → potentially "empty"
449
+ ident_str += self.current_char # buffer 'm'
450
+ self.advance() # consume 'm'
451
+ if self.current_char == "p": # 'em'+'p'
452
+ ident_str += self.current_char # buffer 'p'
453
+ self.advance() # consume 'p'
454
+ if self.current_char == "t": # 'emp'+'t'
455
+ ident_str += self.current_char # buffer 't'
456
+ self.advance() # consume 't'
457
+ if self.current_char == "y": # 'empt'+'y' → "empty" complete
458
+ ident_str += self.current_char # buffer trailing 'y'
459
+ self.advance() # consume 'y'
460
+ # empty is the void return type; whitespace is a valid delimiter.
461
  if self.current_char is None or (self.current_char is not None and self.current_char.isspace()) or self.current_char in space_delim:
462
+ tokens.append(Token(TT_RW_EMPTY, ident_str, line, pos.col)) # emit EMPTY token
463
+ continue # next iteration
464
  elif self.current_char is not None and not self.current_char.isspace() and self.current_char not in space_delim and self.current_char not in ALPHANUM:
465
+ errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'")) # illegal trailer
466
+ self.advance() # skip bad char
467
+ continue # restart outer scan
468
 
469
  # Letter F
470
  elif self.current_char == "f":
Backend/main.js DELETED
@@ -1,569 +0,0 @@
1
-
2
- let fitAddon;
3
- document.addEventListener('DOMContentLoaded', async () => {
4
-
5
- // Auto-target Flask backend when running from a different origin (e.g., VS Code Live Server on 5500)
6
- const API_BASE = (location.port && location.port !== '5000') ? 'http://localhost:5000' : '';
7
-
8
- // Use same-origin Socket.IO connection for portability (works in Docker and cloud)
9
- const socketBase = (location.port && location.port !== '5000') ? 'http://localhost:5000' : undefined;
10
- const socket = socketBase ? io(socketBase) : io();
11
- let waitingForInput = false;
12
- let userInput = '';
13
- let inputCallback = null;
14
- let variable = ''; // Store the variable name for which we need input
15
- let termDataListener = null;
16
-
17
- socket.on('connect', () => {
18
- console.log('Socket.IO connected');
19
- });
20
-
21
- socket.on('disconnect', () => {
22
- console.log('Socket.IO disconnected');
23
- });
24
- //
25
-
26
-
27
-
28
- require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.43.0/min/vs',
29
- 'xterm': 'https://cdn.jsdelivr.net/npm/xterm/lib',
30
- 'xterm-addon-fit': 'https://cdn.jsdelivr.net/npm/xterm-addon-fit/lib/xterm-addon-fit',
31
-
32
- } });
33
-
34
- require(['vs/editor/editor.main'], function () {
35
-
36
- monaco.languages.register({ id: "gal" });
37
-
38
- monaco.languages.setMonarchTokensProvider("gal", {
39
- tokenizer: {
40
-
41
- root: [
42
- // GAL basic data types
43
- [/\b(tree|seed|leaf|branch|string)\b/, "type"],
44
- // GAL advanced data types
45
- [/\b(variety|fertile|soil|bundle)\b/, "advancedType"],
46
- // GAL control flow
47
- [/\b(plant|harvest|grow|prune|graft|water|sow|root|sprout|bud|cultivate|tend|skip|reclaim|pollinate)\b/, "control"],
48
- // GAL boolean values
49
- [/\b(sunshine|frost|tr|fs|empty)\b/, "boolean"],
50
- // GAL I/O functions
51
- [/\b(bloom|wither|spring)\b/, "io"],
52
- // Comments
53
- [/\/\/.*/, "comment"],
54
- [/#.*/, "comment"],
55
- [/\/\*/, 'comment', '@comment'],
56
- // Numbers (integers and decimals)
57
- [/\d+\.\d+/, "number"],
58
- [/\d+/, "number"],
59
- // Strings
60
- [/"[^"]*"/, "string"],
61
- // Characters
62
- [/'.'/, "character"],
63
- // Operators
64
- [/[+\-*/%<>=!&|~]+/, "operator"],
65
- // Function calls
66
- [/\b[a-zA-Z_]\w*(?=\()/, "functionIdentifier"],
67
- // Identifiers
68
- [/\b[a-zA-Z_]\w*\b/, "identifier"],
69
- // Brackets and braces
70
- [/[\{\}]/, "braces"],
71
- [/[\[\]]/, "bracket"],
72
- [/[\(\)]/, "parenthesis"],
73
- ],
74
-
75
- comment: [
76
- [/[^*]+/, 'comment'],
77
- [/\*\//, 'comment', '@pop'],
78
- [/\*/, 'comment'],
79
- ],
80
- },
81
- });
82
-
83
- monaco.languages.setLanguageConfiguration("gal", {
84
- comments: {
85
- blockComment: ["/*", "*/"],
86
- lineComment: "//"
87
- },
88
- autoClosingPairs: [
89
- { open: '{', close: '}' },
90
- { open: '[', close: ']' },
91
- { open: '(', close: ')' },
92
- { open: '"', close: '"'},
93
- { open: "'", close: "'"},
94
- { open: '/*', close: '*/'},
95
- ],
96
- });
97
-
98
- monaco.editor.defineTheme("galTheme", {
99
- base: "vs-dark",
100
- inherit: true,
101
- rules: [
102
- { token: "type", foreground: "#89CFF0", fontStyle: "bold"},
103
- { token: "advancedType", foreground: "#D4A5FF", fontStyle: "bold"},
104
- { token: "control", foreground: "#FFD36E", fontStyle: "bold"},
105
- { token: "io", foreground: "#FF8A5B"},
106
- { token: "boolean", foreground: "#B6FF85"},
107
- { token: "number", foreground: "#FFE7AF"},
108
- { token: "string", foreground: "#A6E3A1"},
109
- { token: "character", foreground: "#A6E3A1"},
110
- { token: "operator", foreground: "#F2FFEF"},
111
- { token: "identifier", foreground: "#E0FFD9"},
112
- { token: "functionIdentifier", foreground: "#FF8A5B", fontStyle: "bold"},
113
- { token: "braces", foreground: "#7CD26F"},
114
- { token: "bracket", foreground: "#7CD26F"},
115
- { token: "parenthesis", foreground: "#F2FFEF"},
116
- { token: "comment", foreground: "#6D8F74", fontStyle: "italic" },
117
- ],
118
- colors: {
119
- "editor.foreground": "#F2FFEF",
120
- "editor.background": "#18361D",
121
- "editorCursor.foreground": "#F2FFEF",
122
- "editor.lineHighlightBackground": "#204B27",
123
- "editorLineNumber.foreground": "#A6C3A9",
124
- "editorindentGuide.background": "#2A5A35",
125
- "editorindentGuide.activebackground": "#3A7D4A",
126
- "scrollbarSlider.background": "#0F2014",
127
- "scrollbarSlider.hoverBackground": "#15301E",
128
- "scrollbarSlider.activeBackground": "#224B2B"
129
- }
130
- });
131
-
132
- window.editor = monaco.editor.create(document.getElementById('editor'), {
133
- value: `root(){\n\t// your code here\n\t\n}`,
134
- language: 'gal',
135
- theme: 'galTheme',
136
- minimap: { enabled: false },
137
- overviewRulerLanes: 0,
138
- automaticLayout: true,
139
- newLineCharacter: "\n",
140
- suggest: {
141
- filterGraceful: false,
142
- showWords: false,
143
- enabled: false,
144
- },
145
- scrollbar: {
146
- vertical: "auto",
147
- horizontal: "auto",
148
- alwaysConsumeMouseWheel: false,
149
- verticalScrollbarSize: 10,
150
- horizontalScrollbarSize: 10,
151
- },
152
- // Mobile optimizations
153
- quickSuggestions: false,
154
- parameterHints: { enabled: false },
155
- codeLens: false,
156
- folding: false,
157
- lineDecorationsWidth: 0,
158
- lineNumbersMinChars: 3,
159
- renderLineHighlight: 'line',
160
- occurrencesHighlight: false,
161
- selectionHighlight: false,
162
- renderValidationDecorations: 'off',
163
- });
164
-
165
- // Add line highlighting on click
166
- let currentLineDecorations = [];
167
- editor.onDidChangeCursorPosition((e) => {
168
- const lineNumber = e.position.lineNumber;
169
- // Highlight the current line
170
- currentLineDecorations = editor.deltaDecorations(currentLineDecorations, [
171
- {
172
- range: new monaco.Range(lineNumber, 1, lineNumber, 1),
173
- options: {
174
- isWholeLine: true,
175
- className: 'current-line-highlight',
176
- glyphMarginClassName: 'current-line-glyph'
177
- }
178
- }
179
- ]);
180
- });
181
-
182
- // (reverted) no status bar cursor updates
183
- });
184
-
185
- require(['vs/editor/editor.main', 'xterm/xterm', 'xterm-addon-fit'], function (_, Xterm, FitAddon) {
186
-
187
- const term = new Xterm.Terminal({
188
- cursorBlink: true,
189
- cursorStyle: 'bar',
190
- scrollback: 5000,
191
- rows: 20,
192
-
193
- theme: {
194
- background: '#102417',
195
- foreground: '#f2ffef',
196
- cursor: '#f2ffef',
197
- FontFace: 'monospace',
198
- fontStyle: 'bold',
199
- },
200
- });
201
-
202
- fitAddon = new FitAddon.FitAddon();
203
- term.loadAddon(fitAddon);
204
-
205
- term.open(document.getElementById('terminal'));
206
-
207
- setTimeout(() => term.focus(), 100);
208
- term.write('Terminal Ready\r\n');
209
-
210
- fitAddon.fit();
211
-
212
- window.addEventListener('resize', () => {
213
- fitAddon.fit();
214
- });
215
-
216
- // HUD removed: no coins/energy UI
217
-
218
- // Toolbar buttons
219
- const btnRun = document.getElementById('btn-run');
220
- const btnLex = document.getElementById('btn-lex');
221
- const btnClear = document.getElementById('btn-clear');
222
- // Removed Run/Lexical toolbar bindings per UI update
223
- btnClear && btnClear.addEventListener('click', () => {
224
- term.clear();
225
- const tbody = document.getElementById('tokenBody');
226
- if (tbody) tbody.innerHTML = '';
227
- const tbodySide = document.getElementById('tokenBodySide');
228
- if (tbodySide) tbodySide.innerHTML = '';
229
- ['status-lex','status-syn','status-sem','status-exe'].forEach(id => {
230
- const el = document.getElementById(id);
231
- if (el){ el.classList.remove('ok','err'); el.textContent = el.textContent.replace(/:.*/, ': —'); }
232
- });
233
- });
234
-
235
- // Terminal header actions
236
- let autoScroll = true;
237
- const autoBtn = document.getElementById('term-autoscroll');
238
- const copyBtn = document.getElementById('term-copy');
239
- const clearBtn = document.getElementById('term-clear');
240
- const toggleMobileLexBtn = document.getElementById('toggle-mobile-lexemes-nav');
241
-
242
- if (autoBtn) {
243
- autoBtn.setAttribute('aria-pressed', 'true');
244
- autoBtn.addEventListener('click', () => {
245
- autoScroll = !autoScroll;
246
- autoBtn.setAttribute('aria-pressed', String(autoScroll));
247
- });
248
- }
249
-
250
- if (copyBtn) {
251
- copyBtn.addEventListener('click', async () => {
252
- try {
253
- const buffer = term.buffer.active;
254
- let text = '';
255
- for (let i = 0; i < buffer.length; i++) {
256
- const line = buffer.getLine(i);
257
- if (line) text += line.translateToString() + '\n';
258
- }
259
- await navigator.clipboard.writeText(text);
260
- } catch (e) {
261
- console.warn('Copy failed:', e);
262
- }
263
- });
264
- }
265
-
266
- if (clearBtn) {
267
- clearBtn.addEventListener('click', () => term.clear());
268
- }
269
-
270
- // Mobile lexeme table toggle (navbar button)
271
- if (toggleMobileLexBtn) {
272
- const mobileTokensSection = document.querySelector('.mobile-tokens');
273
- const backdrop = document.getElementById('mobile-tokens-backdrop');
274
- const toggleIcon = document.getElementById('lexeme-toggle-icon');
275
- const closeBtn = document.getElementById('mobile-tokens-close');
276
-
277
- const closeLexemeTable = () => {
278
- if (mobileTokensSection) mobileTokensSection.classList.remove('show');
279
- if (backdrop) backdrop.classList.remove('show');
280
- if (toggleMobileLexBtn) toggleMobileLexBtn.setAttribute('aria-expanded', 'false');
281
- if (toggleIcon) toggleIcon.textContent = '▼';
282
- };
283
-
284
- toggleMobileLexBtn.addEventListener('click', () => {
285
- if (!mobileTokensSection) return;
286
-
287
- const isShowing = mobileTokensSection.classList.toggle('show');
288
- if (backdrop) backdrop.classList.toggle('show', isShowing);
289
-
290
- toggleMobileLexBtn.setAttribute('aria-expanded', String(isShowing));
291
- if (toggleIcon) {
292
- toggleIcon.textContent = isShowing ? '▲' : '▼';
293
- }
294
- });
295
-
296
- // Close when clicking close button
297
- if (closeBtn) {
298
- closeBtn.addEventListener('click', closeLexemeTable);
299
- }
300
-
301
- // Close when clicking backdrop
302
- if (backdrop) {
303
- backdrop.addEventListener('click', closeLexemeTable);
304
- }
305
- }
306
-
307
-
308
- window.runLexer = async function (options = {}) {
309
- const silent = options.silent === true;
310
- const sourceCode = editor.getValue();
311
- console.log("Running lexer with source code:", sourceCode);
312
- if (!silent) {
313
- // Separate runs with a blank line
314
- term.write('\r\n');
315
- }
316
-
317
- try {
318
- const response = await fetch(`${API_BASE}/api/lex`, {
319
- method: 'POST',
320
- headers: { 'Content-Type': 'application/json' },
321
- body: JSON.stringify({ source_code: sourceCode })
322
- });
323
-
324
- if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
325
-
326
- const data = await response.json();
327
- console.log("Lexer response:", data);
328
-
329
- const tokensTableBody = document.getElementById('tokenBody');
330
- tokensTableBody.innerHTML = '';
331
- const tokensTableBodySide = document.getElementById('tokenBodySide');
332
- if (tokensTableBodySide) tokensTableBodySide.innerHTML = '';
333
- const tokensTableBodyMobile = document.getElementById('tokenBodyMobile');
334
- if (tokensTableBodyMobile) tokensTableBodyMobile.innerHTML = '';
335
-
336
- // Map backend token types to display names (Token column)
337
- const displayType = (tok) => {
338
- // For identifiers, show the actual identifier name
339
- if (tok.type === 'idf' || tok.type === 'id' || tok.type === 'TT_IDENTIFIER') {
340
- return tok.value || 'id';
341
- }
342
-
343
- // For literals, show the actual literal value
344
- const literalTypes = new Set(['intlit','dbllit','strnglit','chrlit','TT_INTEGERLIT','TT_DOUBLELIT','TT_STRINGLIT','TT_CHARLIT','seedlit','treelit','leaflit']);
345
- if (literalTypes.has(tok.type)) return tok.value != null ? String(tok.value) : '';
346
-
347
- // Boolean literals: sunshine and frost show their keyword as token
348
- if (tok.type === 'sunshine') return 'sunshine';
349
- if (tok.type === 'frost') return 'frost';
350
-
351
- // Reserved words are their type directly
352
- const kwSet = new Set(['water','plant','seed','leaf','branch','tree','spring','wither','bud','harvest','grow','cultivate','tend','empty','prune','skip','reclaim','root','pollinate','variety','fertile','soil','bundle','string']);
353
- if (kwSet.has(tok.type)) return tok.type;
354
-
355
- // Show symbols in the Token column as the actual symbol
356
- const SYMBOLS = new Set(['+','-','*','/','%','=','==','===','+=','-=','*=','/=','%=','<','>','<=','>=','!=','&&','&','||','|','!','++','--','~','`','(',')','{','}','[',']',',',';',';',':','.']);
357
- if (tok && typeof tok.value === 'string' && SYMBOLS.has(tok.value)) return tok.value;
358
- if (tok && typeof tok.type === 'string' && SYMBOLS.has(tok.type)) return tok.type;
359
-
360
- // Fallback for any other token types from old or new lexer
361
- if (tok.type && tok.type.startsWith('TT_')) {
362
- // If value looks like a symbol, prefer it
363
- if (typeof tok.value === 'string' && SYMBOLS.has(tok.value)) return tok.value;
364
- return tok.type.substring(3).toLowerCase();
365
- }
366
- return tok.type || '';
367
- };
368
-
369
- // Determine token classification (Type column)
370
- const RESERVED = new Set([
371
- 'water','plant','seed','leaf','branch','tree','spring','wither','bud','harvest','grow','cultivate','tend','empty','prune','skip','reclaim','root','pollinate','variety','fertile','soil','bundle','string'
372
- ]);
373
- const SYMBOLS = new Set(['+','-','*','/','%','=','==','===','+=','-=','*=','/=','%=','<','>','<=','>=','!=','&&','&','||','|','!','++','--','~','`','(',')','{','}','[',']',',',';',';',':','.']);
374
- const symbolTypeName = (sym) => {
375
- if (sym === '{') return 'R_Curly';
376
- if (sym === '}') return 'L_Curly';
377
- if (sym === '(') return 'L_Paren';
378
- if (sym === ')') return 'R_Paren';
379
- if (sym === '[') return 'L_Brkt';
380
- if (sym === ']') return 'R_Brkt';
381
- if (sym === ',') return 'Comma';
382
- if (sym === ';') return 'Semi_c';
383
- if (sym === ':') return 'Colon';
384
- if (sym === '.') return 'Dot';
385
- return '';
386
- };
387
- const classifyType = (tok) => {
388
- const t = tok.type || '';
389
- // Keep only these categories in Type column
390
- if (RESERVED.has(t)) return 'RW';
391
- if (t === 'idf' || t === 'id' || t === 'TT_IDENTIFIER') return 'ID';
392
- if (t === 'intlit' || t === 'TT_INTEGERLIT') return 'integer';
393
- if (t === 'dbllit' || t === 'TT_DOUBLELIT' || t === 'treelit') return 'double';
394
- if (t === 'strnglit' || t === 'TT_STRINGLIT') return 'string';
395
- if (t === 'chrlit' || t === 'TT_CHARLIT') return 'character';
396
- // Boolean literals
397
- if (t === 'sunshine' || t === 'frost') return 'false';
398
- // Operators are labeled 'operator'
399
- const OPS = new Set(['+','-','*','/','%','=','==','===','+=','-=','*=','/=','%=','<','>','<=','>=','!=','&&','&','||','|','!','++','--','~','`']);
400
- const lex = (tok.value == null ? '' : String(tok.value));
401
- if (OPS.has(lex) || OPS.has(t)) return 'operator';
402
- // Symbols like braces/parens get specific names
403
- if (SYMBOLS.has(lex)) return symbolTypeName(lex);
404
- if (SYMBOLS.has(t)) return symbolTypeName(t);
405
- // Everything else (operators etc.) blank
406
- return '';
407
- };
408
-
409
- // Filter out tokens we don't want displayed in the lexeme tables
410
- const visibleTokens = (data.tokens || []).filter(t => t && t.type !== 'TT_NL' && t.type !== 'TT_EOF' && t.type !== 'EOF');
411
- visibleTokens.forEach(token => {
412
- const tDisp = displayType(token); // Token column
413
- const vDisp = token.value == null ? '' : String(token.value); // Lexeme column
414
- const cDisp = classifyType(token); // Token Type column
415
-
416
- const row = tokensTableBody.insertRow();
417
- row.insertCell(0).textContent = vDisp;
418
- row.insertCell(1).textContent = tDisp;
419
- row.insertCell(2).textContent = cDisp;
420
-
421
- if (tokensTableBodySide){
422
- const r = tokensTableBodySide.insertRow();
423
- r.insertCell(0).textContent = vDisp;
424
- r.insertCell(1).textContent = tDisp;
425
- r.insertCell(2).textContent = cDisp;
426
- }
427
-
428
- if (tokensTableBodyMobile){
429
- const m = tokensTableBodyMobile.insertRow();
430
- m.insertCell(0).textContent = vDisp;
431
- m.insertCell(1).textContent = tDisp;
432
- m.insertCell(2).textContent = cDisp;
433
- }
434
- });
435
-
436
- // No table content mirrored to terminal output
437
-
438
- if (data.errors.length > 0) {
439
- if (!silent) {
440
- data.errors.forEach(err => {
441
- term.write(`${err}\r\n`);
442
- });
443
- }
444
- const sl = document.getElementById('status-lex');
445
- if (sl){ sl.classList.remove('ok'); sl.classList.add('err'); sl.textContent = 'Lexical: Error'; }
446
- } else {
447
- if (!silent) term.write('Lexical analysis successful!\r\n');
448
- const sl = document.getElementById('status-lex');
449
- if (sl){ sl.classList.remove('err'); sl.classList.add('ok'); sl.textContent = 'Lexical: OK'; }
450
- return true;
451
- }
452
-
453
- } catch (error) {
454
- console.error("Error running lexical analysis:", error);
455
- if (!silent) term.write('Error running lexical analysis.\r\n');
456
- return false;
457
- }
458
- };
459
-
460
- // Syntax analysis removed; only lexical phase retained.
461
-
462
-
463
- socket.on('output', function (data) {
464
- const lines = data.output.split('\n');
465
- lines.forEach((line, index) => {
466
- term.write(line);
467
- // Only add newline if not the last line or if the original ended with newline
468
- if (index < lines.length - 1 || data.output.endsWith('\n')) {
469
- term.write('\r\n');
470
- }
471
- });
472
- if (autoScroll) term.scrollToBottom();
473
- term.focus();
474
- });
475
-
476
- socket.on('input_required', function (data) {
477
- const prompt = data.prompt;
478
- variable = data.variable;
479
-
480
-
481
- waitingForInput = true;
482
- userInput = '';
483
-
484
- if (termDataListener) {
485
- term.offData(termDataListener);
486
- }
487
-
488
- const inputStartPosition = term.cols;
489
-
490
- termDataListener = function (e) {
491
- if (!waitingForInput) return;
492
-
493
- if (e === '\x1b[A' || e === '\x1b[B' || e === '\x1b[C' || e === '\x1b[D') {
494
- return;
495
- }
496
-
497
- if (e === '\r') {
498
- term.write('\r\n');
499
- waitingForInput = false;
500
- socket.emit('capture_input', { var_name: variable, input: userInput });
501
- userInput = '';
502
- } else if (e === '\u007f') {
503
- if (userInput.length > 0) {
504
- userInput = userInput.slice(0, -1);
505
- term.write('\b \b');
506
- }
507
- } else {
508
- userInput += e;
509
- term.write(e);
510
- }
511
-
512
-
513
- };
514
-
515
- term.onData(termDataListener);
516
- });
517
-
518
-
519
- window.runCode = async function () {
520
- // Run lexical analysis (same as Lexical button)
521
- await runLexer({ silent: false });
522
- };
523
- });
524
-
525
- });
526
-
527
-
528
- document.querySelector(".widthResizer").addEventListener("mousedown", (e) => {
529
- e.preventDefault();
530
- document.addEventListener("mousemove", widthResize);
531
- document.addEventListener("mouseup", () => {
532
- document.removeEventListener("mousemove", widthResize);
533
- }, { once: true });
534
- });
535
-
536
- function widthResize(e) {
537
- let newWidth = e.clientX - document.querySelector(".textFieldCont").getBoundingClientRect().left;
538
- document.querySelector(".textFieldCont").style.width = `${newWidth}px`;
539
- }
540
-
541
- function toggleDropdown() {
542
- const menu = document.getElementById("dropdown-menu");
543
- menu.classList.toggle("hidden");
544
- }
545
-
546
-
547
-
548
- // Hide dropdown if clicked outside
549
- document.addEventListener("click", function (e) {
550
- const dropdown = document.querySelector(".dropdown");
551
- const menu = document.getElementById("dropdown-menu");
552
-
553
- if (!dropdown.contains(e.target)) {
554
- menu.classList.add("hidden");
555
- }
556
- });
557
-
558
- // Auto-lex on typing (debounced) to keep sidebar tokens in sync with GALalexer rules
559
- function debounce(fn, wait){
560
- let t; return function(...args){ clearTimeout(t); t = setTimeout(() => fn.apply(this, args), wait); };
561
- }
562
- const debouncedLex = debounce(() => window.runLexer({ silent: true }), 400);
563
- if (window.editor && editor.onDidChangeModelContent){
564
- editor.onDidChangeModelContent(() => {
565
- debouncedLex();
566
- });
567
- }
568
-
569
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Backend/server.py CHANGED
@@ -1,22 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import warnings
2
  warnings.filterwarnings("ignore", message=".*RLock.*were not greened.*")
3
 
4
  import eventlet
5
  eventlet.monkey_patch()
6
 
 
 
 
7
  from flask import Flask, request, jsonify, send_from_directory
8
  from flask_cors import CORS
9
  from flask_socketio import SocketIO, emit
10
  import os
11
- from google import genai
12
- from lexer import lex, get_token_description
13
- from Gal_Parser import LL1Parser
14
- from cfg import cfg, first_sets, predict_sets
15
- from GALsemantic import analyze_semantics, validate_ast
16
- from icg import generate_icg
17
- from GALinterpreter import Interpreter, InterpreterError, _CancelledError
18
- from gal_fallback import fallback_reply
19
-
 
 
 
 
 
20
  def _display_value(val):
21
  """Escape special chars in token values for safe display (like C's repr)."""
22
  if val is None:
@@ -27,33 +54,52 @@ def _display_value(val):
27
  s = s.replace('\r', '\\r')
28
  return s
29
 
 
 
 
 
30
  app = Flask(__name__, static_folder='../UI', static_url_path='')
31
- CORS(app)
32
- socketio = SocketIO(app, cors_allowed_origins="*")
33
 
34
- # Store interpreter instances per session for input handling
 
35
  interpreters = {}
36
 
37
 
 
 
 
 
38
  class SessionEmitter:
39
  """Wrapper around SocketIO that always emits to a specific client session."""
40
  def __init__(self, sio, sid):
41
- self._sio = sio
42
- self._sid = sid
43
 
44
  def emit(self, event, data=None, **kwargs):
 
45
  self._sio.emit(event, data, to=self._sid, **kwargs)
46
 
47
- # Initialize the parser once at startup
 
 
 
 
48
  parser = LL1Parser(
49
- cfg=cfg,
50
- predict_sets=predict_sets,
51
- first_sets=first_sets,
52
- start_symbol="<program>",
53
- end_marker="EOF",
54
- skip_token_types={'\n'} # Skip newline tokens
55
  )
56
 
 
 
 
 
 
57
  @app.after_request
58
  def add_no_cache(response):
59
  """Prevent browser from caching static files during development."""
@@ -77,6 +123,12 @@ def serve_static(path):
77
  """Serve static files (CSS, JS, etc.) from UI folder"""
78
  return send_from_directory('../UI', path)
79
 
 
 
 
 
 
 
80
  @app.route('/api/lex', methods=['POST'])
81
  def lexer_endpoint():
82
  """
@@ -118,6 +170,12 @@ def lexer_endpoint():
118
  'error': f'Server error: {str(e)}'
119
  }), 500
120
 
 
 
 
 
 
 
121
  @app.route('/api/parse', methods=['POST'])
122
  def parser_endpoint():
123
  """
@@ -181,6 +239,9 @@ def parser_endpoint():
181
  'error': f'Server error: {str(e)}'
182
  }), 500
183
 
 
 
 
184
  @app.route('/api/health', methods=['GET'])
185
  def health_check():
186
  """Health check endpoint"""
@@ -189,6 +250,13 @@ def health_check():
189
  'message': 'GAL Compiler Server is running'
190
  })
191
 
 
 
 
 
 
 
 
192
  @app.route('/api/semantic', methods=['POST'])
193
  def semantic_endpoint():
194
  """
@@ -262,6 +330,12 @@ def semantic_endpoint():
262
  'error': f'Server error: {str(e)}'
263
  }), 500
264
 
 
 
 
 
 
 
265
  @app.route('/api/icg', methods=['POST'])
266
  def icg_endpoint():
267
  """
@@ -342,26 +416,41 @@ def icg_endpoint():
342
  }), 500
343
 
344
 
345
- # ─── REST endpoint for program execution (no Socket.IO needed) ────
 
 
 
 
 
 
346
 
347
  class OutputCollector:
348
  """Drop-in replacement for SessionEmitter that collects output in a list."""
349
  def __init__(self):
350
- self.outputs = []
351
- self.needs_input = False
352
 
353
  def emit(self, event, data=None, **kwargs):
354
  if event == 'output' and data:
 
355
  self.outputs.append(data.get('output', ''))
356
  elif event == 'input_required':
 
 
357
  self.needs_input = True
358
- raise _InputNeeded() # Abort interpreter when input is needed
359
 
360
 
361
  class _InputNeeded(Exception):
362
  """Raised by OutputCollector to abort REST execution when water() is called."""
363
  pass
364
 
 
 
 
 
 
 
365
  @app.route('/api/run', methods=['POST'])
366
  def run_endpoint():
367
  """Run a GAL program synchronously and return all output."""
@@ -446,14 +535,22 @@ def run_endpoint():
446
  return jsonify({'error': f'Server error: {str(e)}'}), 500
447
 
448
 
449
- # ─── Socket.IO events for program execution ───────────────────────
 
 
 
 
 
 
450
 
451
  @socketio.on('connect')
452
  def handle_connect():
 
453
  pass
454
 
455
  @socketio.on('disconnect')
456
  def handle_disconnect():
 
457
  sid = request.sid
458
  interpreters.pop(sid, None)
459
 
@@ -543,6 +640,11 @@ def handle_run_code(data):
543
 
544
  socketio.start_background_task(run_interpreter)
545
 
 
 
 
 
 
546
  @socketio.on('capture_input')
547
  def handle_capture_input(data):
548
  """Receive input from the client and forward to the waiting interpreter."""
@@ -551,11 +653,18 @@ def handle_capture_input(data):
551
  if interp:
552
  var_name = data.get('var_name', '')
553
  input_value = data.get('input', '')
 
554
  interp.provide_input(var_name, input_value)
555
 
556
 
557
- # ─── AI Chat Helper (Google Gemini) ─────────────────────────────
 
 
 
 
 
558
 
 
559
  _prompt_path = os.path.join(os.path.dirname(__file__), 'gal_prompt.txt')
560
  with open(_prompt_path, 'r', encoding='utf-8') as _f:
561
  GAL_SYSTEM_PROMPT = _f.read()
@@ -659,10 +768,16 @@ def chat_clear_endpoint():
659
  return jsonify({'success': True})
660
 
661
 
 
 
 
 
 
 
662
  if __name__ == '__main__':
663
  port = int(os.environ.get('PORT', 5000))
664
  debug = os.environ.get('DEBUG', 'False') != 'True'
665
-
666
  print("Starting GAL Compiler Server...")
667
  print(f"Server running at http://0.0.0.0:{port}")
668
  print("API endpoints:")
@@ -672,4 +787,5 @@ if __name__ == '__main__':
672
  print(f" - POST http://localhost:{port}/api/icg (Intermediate Code Generation)")
673
  print(f" - POST http://localhost:{port}/api/chat (AI Chat Helper)")
674
  print(f" - Socket.IO: run_code (Execute Program)")
 
675
  socketio.run(app, host='0.0.0.0', port=port, debug=debug, allow_unsafe_werkzeug=True)
 
1
+ # ============================================================================
2
+ # GAL COMPILER SERVER - HTTP + WebSocket entry point
3
+ # ============================================================================
4
+ # This is the orchestrator of the entire compiler. It exposes Flask routes
5
+ # for each compiler stage (lex / parse / semantic / icg / run) and Socket.IO
6
+ # events for interactive program execution. Every request flows through:
7
+ #
8
+ # source code -> lexer -> parser+AST -> semantic -> ICG -> interpreter
9
+ #
10
+ # Each stage short-circuits on failure so the user sees the FIRST stage that
11
+ # rejected their code, not a flood of cascading errors.
12
+ # ============================================================================
13
+
14
+ # ============================================================================
15
+ # WARNING SUPPRESSION + EVENTLET BOOTSTRAP
16
+ # Eventlet provides cooperative concurrency so Socket.IO can park a request
17
+ # (e.g. waiting on water() input) without blocking the whole server.
18
+ # monkey_patch() must run BEFORE flask/socketio are imported.
19
+ # ============================================================================
20
  import warnings
21
  warnings.filterwarnings("ignore", message=".*RLock.*were not greened.*")
22
 
23
  import eventlet
24
  eventlet.monkey_patch()
25
 
26
+ # ============================================================================
27
+ # IMPORTS - Flask web framework + every layer of the GAL compiler
28
+ # ============================================================================
29
  from flask import Flask, request, jsonify, send_from_directory
30
  from flask_cors import CORS
31
  from flask_socketio import SocketIO, emit
32
  import os
33
+ from google import genai # AI chat helper (optional)
34
+ from lexer import lex, get_token_description # Stage 1: Lexical
35
+ from Gal_Parser import LL1Parser # Stage 2: Syntax (LL(1))
36
+ from cfg import cfg, first_sets, predict_sets # Grammar + parse table
37
+ from GALsemantic import analyze_semantics, validate_ast # Stage 3: Semantic
38
+ from icg import generate_icg # Stage 4: ICG (display)
39
+ from GALinterpreter import Interpreter, InterpreterError, _CancelledError # Stage 5: Run
40
+ from gal_fallback import fallback_reply # Rule-based AI fallback
41
+
42
+
43
+ # ============================================================================
44
+ # DISPLAY HELPER - Escapes control characters so token values are safe
45
+ # to embed in JSON responses for the IDE's lexeme table.
46
+ # ============================================================================
47
  def _display_value(val):
48
  """Escape special chars in token values for safe display (like C's repr)."""
49
  if val is None:
 
54
  s = s.replace('\r', '\\r')
55
  return s
56
 
57
+
58
+ # ============================================================================
59
+ # FLASK APP INITIALIZATION
60
+ # ============================================================================
61
  app = Flask(__name__, static_folder='../UI', static_url_path='')
62
+ CORS(app) # Allow browser frontend on any origin (dev)
63
+ socketio = SocketIO(app, cors_allowed_origins="*") # WebSocket layer for live program execution
64
 
65
+ # Per-session interpreter registry (sid -> Interpreter instance).
66
+ # One user can only have one program running at a time; new runs cancel the old.
67
  interpreters = {}
68
 
69
 
70
+ # ============================================================================
71
+ # SESSION EMITTER - Routes interpreter output to the originating browser
72
+ # session instead of broadcasting to every connected client.
73
+ # ============================================================================
74
  class SessionEmitter:
75
  """Wrapper around SocketIO that always emits to a specific client session."""
76
  def __init__(self, sio, sid):
77
+ self._sio = sio # the global SocketIO instance
78
+ self._sid = sid # this client's session ID
79
 
80
  def emit(self, event, data=None, **kwargs):
81
+ # Always 'to=sid' so output goes to one user, never broadcast
82
  self._sio.emit(event, data, to=self._sid, **kwargs)
83
 
84
+
85
+ # ============================================================================
86
+ # PARSER SINGLETON - Built once at startup; the LL(1) parser is stateless
87
+ # across calls so this instance is shared by every request.
88
+ # ============================================================================
89
  parser = LL1Parser(
90
+ cfg=cfg, # Grammar productions
91
+ predict_sets=predict_sets, # Pre-computed parse table
92
+ first_sets=first_sets, # FIRST sets (for error recovery hints)
93
+ start_symbol="<program>", # Top of the GAL grammar
94
+ end_marker="EOF", # Matches the synthetic EOF token from the lexer
95
+ skip_token_types={'\n'} # Newlines are filtered before the parser sees them
96
  )
97
 
98
+ # ============================================================================
99
+ # STATIC FILE SERVING - Serves the IDE's HTML/CSS/JS/images so the whole app
100
+ # works as a single deployable. The no-cache header prevents stale UI during
101
+ # development.
102
+ # ============================================================================
103
  @app.after_request
104
  def add_no_cache(response):
105
  """Prevent browser from caching static files during development."""
 
123
  """Serve static files (CSS, JS, etc.) from UI folder"""
124
  return send_from_directory('../UI', path)
125
 
126
+
127
+ # ============================================================================
128
+ # API ENDPOINT: /api/lex - LEXICAL ANALYSIS (stage 1 only)
129
+ # Returns the token stream and any lexical errors. Used by the IDE's
130
+ # "Lexemes" tab to display the token table.
131
+ # ============================================================================
132
  @app.route('/api/lex', methods=['POST'])
133
  def lexer_endpoint():
134
  """
 
170
  'error': f'Server error: {str(e)}'
171
  }), 500
172
 
173
+ # ============================================================================
174
+ # API ENDPOINT: /api/parse - LEX + SYNTAX ANALYSIS
175
+ # Runs the lexer and (only if no lex errors) the LL(1) parser.
176
+ # Short-circuits at the first failing stage and labels the response with
177
+ # the failing stage so the IDE can highlight the right phase indicator.
178
+ # ============================================================================
179
  @app.route('/api/parse', methods=['POST'])
180
  def parser_endpoint():
181
  """
 
239
  'error': f'Server error: {str(e)}'
240
  }), 500
241
 
242
+ # ============================================================================
243
+ # API ENDPOINT: /api/health - liveness check (used by deployment tools)
244
+ # ============================================================================
245
  @app.route('/api/health', methods=['GET'])
246
  def health_check():
247
  """Health check endpoint"""
 
250
  'message': 'GAL Compiler Server is running'
251
  })
252
 
253
+
254
+ # ============================================================================
255
+ # API ENDPOINT: /api/semantic - LEX + PARSE + AST + SEMANTIC ANALYSIS
256
+ # Uses the parser's two-step API: parse_and_build (syntax + AST construction)
257
+ # then validate_ast (tree-walking semantic checks). Distinguishes between
258
+ # 'syntax' and 'semantic' error stages even though both come from the parser.
259
+ # ============================================================================
260
  @app.route('/api/semantic', methods=['POST'])
261
  def semantic_endpoint():
262
  """
 
330
  'error': f'Server error: {str(e)}'
331
  }), 500
332
 
333
+ # ============================================================================
334
+ # API ENDPOINT: /api/icg - LEX + PARSE + SEMANTIC + ICG (display only)
335
+ # ICG produces three-address code (TAC) for the IDE's "Intermediate Code"
336
+ # tab. The interpreter does NOT consume this output; it walks the AST directly.
337
+ # So ICG is a teaching/visualization layer, not a runtime layer.
338
+ # ============================================================================
339
  @app.route('/api/icg', methods=['POST'])
340
  def icg_endpoint():
341
  """
 
416
  }), 500
417
 
418
 
419
+ # ============================================================================
420
+ # SYNCHRONOUS EXECUTION (no Socket.IO required)
421
+ #
422
+ # OutputCollector is an adapter — same .emit() interface as SessionEmitter,
423
+ # but instead of streaming output via WebSocket it captures it in a list.
424
+ # This is the adapter pattern: one Interpreter class, two delivery modes.
425
+ # ============================================================================
426
 
427
  class OutputCollector:
428
  """Drop-in replacement for SessionEmitter that collects output in a list."""
429
  def __init__(self):
430
+ self.outputs = [] # Accumulated plant() output strings
431
+ self.needs_input = False # Flips to True if program calls water()
432
 
433
  def emit(self, event, data=None, **kwargs):
434
  if event == 'output' and data:
435
+ # Accumulate normal plant() output
436
  self.outputs.append(data.get('output', ''))
437
  elif event == 'input_required':
438
+ # No interactive channel here -> abort the interpreter so the
439
+ # client can switch to the Socket.IO flow that supports input.
440
  self.needs_input = True
441
+ raise _InputNeeded()
442
 
443
 
444
  class _InputNeeded(Exception):
445
  """Raised by OutputCollector to abort REST execution when water() is called."""
446
  pass
447
 
448
+
449
+ # ============================================================================
450
+ # API ENDPOINT: /api/run - One-shot execution returning all output at once.
451
+ # Used for non-interactive programs (no water() calls). For interactive runs,
452
+ # the client uses the Socket.IO 'run_code' event below.
453
+ # ============================================================================
454
  @app.route('/api/run', methods=['POST'])
455
  def run_endpoint():
456
  """Run a GAL program synchronously and return all output."""
 
535
  return jsonify({'error': f'Server error: {str(e)}'}), 500
536
 
537
 
538
+ # ============================================================================
539
+ # SOCKET.IO INTERACTIVE EXECUTION
540
+ #
541
+ # This path supports water() input. The interpreter runs in a green thread
542
+ # (eventlet) so it can park while waiting for input without blocking the
543
+ # server. Output is streamed back via 'output' events as plant() fires.
544
+ # ============================================================================
545
 
546
  @socketio.on('connect')
547
  def handle_connect():
548
+ # No setup needed — interpreter is created lazily on first 'run_code'.
549
  pass
550
 
551
  @socketio.on('disconnect')
552
  def handle_disconnect():
553
+ # Drop the user's interpreter so memory doesn't leak across reconnects.
554
  sid = request.sid
555
  interpreters.pop(sid, None)
556
 
 
640
 
641
  socketio.start_background_task(run_interpreter)
642
 
643
+ # ============================================================================
644
+ # SOCKET.IO INPUT CHANNEL - When a running program calls water(), the
645
+ # interpreter parks on an event. The frontend prompts the user, sends back
646
+ # 'capture_input', and this handler routes the value to the right interpreter.
647
+ # ============================================================================
648
  @socketio.on('capture_input')
649
  def handle_capture_input(data):
650
  """Receive input from the client and forward to the waiting interpreter."""
 
653
  if interp:
654
  var_name = data.get('var_name', '')
655
  input_value = data.get('input', '')
656
+ # Unblock the parked interpreter so execution resumes
657
  interp.provide_input(var_name, input_value)
658
 
659
 
660
+ # ============================================================================
661
+ # AI CHAT HELPER (Google Gemini)
662
+ # Optional learning aid — answers user questions about GAL syntax. Falls
663
+ # back to a rule-based reply if no GEMINI_API_KEY is set or the API fails.
664
+ # This is NOT part of the compiler pipeline.
665
+ # ============================================================================
666
 
667
+ # Load the system prompt that teaches Gemini how to talk about GAL
668
  _prompt_path = os.path.join(os.path.dirname(__file__), 'gal_prompt.txt')
669
  with open(_prompt_path, 'r', encoding='utf-8') as _f:
670
  GAL_SYSTEM_PROMPT = _f.read()
 
768
  return jsonify({'success': True})
769
 
770
 
771
+ # ============================================================================
772
+ # SERVER STARTUP - Reads PORT/DEBUG env vars, prints a banner listing every
773
+ # endpoint, then hands the app to eventlet's WSGI server.
774
+ # host='0.0.0.0' makes the server reachable from any network interface,
775
+ # not just localhost.
776
+ # ============================================================================
777
  if __name__ == '__main__':
778
  port = int(os.environ.get('PORT', 5000))
779
  debug = os.environ.get('DEBUG', 'False') != 'True'
780
+
781
  print("Starting GAL Compiler Server...")
782
  print(f"Server running at http://0.0.0.0:{port}")
783
  print("API endpoints:")
 
787
  print(f" - POST http://localhost:{port}/api/icg (Intermediate Code Generation)")
788
  print(f" - POST http://localhost:{port}/api/chat (AI Chat Helper)")
789
  print(f" - Socket.IO: run_code (Execute Program)")
790
+ # allow_unsafe_werkzeug=True is needed when running inside eventlet during dev
791
  socketio.run(app, host='0.0.0.0', port=port, debug=debug, allow_unsafe_werkzeug=True)
Backend/test_array_param.py DELETED
@@ -1,45 +0,0 @@
1
- """Quick test for array parameter passing feature."""
2
- from lexer import Lexer
3
- from Gal_Parser import LL1Parser
4
- from GALsemantic import build_ast
5
- from GALinterpreter import Interpreter
6
- from cfg import cfg, first_sets, predict_sets
7
-
8
- code = '''
9
- pollinate empty printEl(seed arr[], seed i) {
10
- plant("{} ", arr[i]) ;
11
- reclaim ;
12
- }
13
-
14
- root() {
15
- seed nums[3] ;
16
- nums[0] = 10 ;
17
- nums[1] = 20 ;
18
- nums[2] = 30 ;
19
- printEl(nums, 0) ;
20
- printEl(nums, 1) ;
21
- printEl(nums, 2) ;
22
- reclaim ;
23
- }
24
- '''
25
-
26
- # Lexer
27
- lexer = Lexer(code)
28
- tokens, lex_errors = lexer.make_tokens()
29
- print("Lex OK:", len(tokens), "tokens, errors:", lex_errors)
30
-
31
- # Parser
32
- parser = LL1Parser(cfg=cfg, predict_sets=predict_sets, first_sets=first_sets)
33
- errors = parser.parse(tokens)
34
- print("Parse errors:", errors)
35
-
36
- # Semantic + AST
37
- filtered = [t for t in tokens if t.type != '\n']
38
- ast = build_ast(filtered)
39
- print("Semantic + AST OK")
40
-
41
- # Interpreter — patch plant() since no Socket.IO in test
42
- interp = Interpreter()
43
- interp.plant = lambda value: print(value, end="")
44
- interp.interpret(ast)
45
- print("\nDone")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Backend/test_curly_init.py DELETED
@@ -1,41 +0,0 @@
1
- """Test array initialization with curly brace syntax: seed nums[3] = {10, 20, 30}"""
2
- from lexer import Lexer
3
- from Gal_Parser import LL1Parser
4
- from GALsemantic import build_ast
5
- from GALinterpreter import Interpreter
6
- from cfg import cfg, first_sets, predict_sets
7
-
8
- code = '''
9
- pollinate empty printArr(seed arr[], seed n, seed i) {
10
- spring(i >= n) {
11
- reclaim ;
12
- }
13
- plant("{} ", arr[i]) ;
14
- printArr(arr, n, i + 1) ;
15
- reclaim ;
16
- }
17
-
18
- root() {
19
- seed nums[3] = {10, 20, 30} ;
20
- printArr(nums, 3, 0) ;
21
- reclaim ;
22
- }
23
- '''
24
-
25
- lexer = Lexer(code)
26
- tokens, lex_errors = lexer.make_tokens()
27
- print("Lex:", len(tokens), "tokens, errors:", lex_errors)
28
-
29
- parser = LL1Parser(cfg=cfg, predict_sets=predict_sets, first_sets=first_sets)
30
- errors = parser.parse(tokens)
31
- print("Parse:", errors)
32
-
33
- filtered = [t for t in tokens if t.type != '\n']
34
- ast = build_ast(filtered)
35
- print("Semantic OK")
36
-
37
- interp = Interpreter()
38
- interp.plant = lambda value: print(value, end="")
39
- interp.interpret(ast)
40
- print()
41
- print("Done")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Backend/test_mp16.py DELETED
@@ -1,77 +0,0 @@
1
- """Test MP16: Array print + sort with recursion using array parameter passing."""
2
- from lexer import Lexer
3
- from Gal_Parser import LL1Parser
4
- from GALsemantic import build_ast
5
- from GALinterpreter import Interpreter
6
- from cfg import cfg, first_sets, predict_sets
7
-
8
- code = '''
9
- pollinate empty printArr(seed arr[], seed n, seed i) {
10
- spring(i >= n) {
11
- reclaim ;
12
- }
13
- plant("{} ", arr[i]) ;
14
- printArr(arr, n, i + 1) ;
15
- reclaim ;
16
- }
17
-
18
- pollinate empty bubblePass(seed arr[], seed n, seed i) {
19
- spring(i >= n - 1) {
20
- reclaim ;
21
- }
22
- spring(arr[i] > arr[i + 1]) {
23
- seed temp = arr[i] ;
24
- arr[i] = arr[i + 1] ;
25
- arr[i + 1] = temp ;
26
- }
27
- bubblePass(arr, n, i + 1) ;
28
- reclaim ;
29
- }
30
-
31
- pollinate empty bubbleSort(seed arr[], seed n) {
32
- spring(n <= 1) {
33
- reclaim ;
34
- }
35
- bubblePass(arr, n, 0) ;
36
- bubbleSort(arr, n - 1) ;
37
- reclaim ;
38
- }
39
-
40
- root() {
41
- seed nums[5] ;
42
- nums[0] = 64 ;
43
- nums[1] = 34 ;
44
- nums[2] = 25 ;
45
- nums[3] = 12 ;
46
- nums[4] = 22 ;
47
-
48
- plant("Before sorting:") ;
49
- printArr(nums, 5, 0) ;
50
- plant("") ;
51
-
52
- bubbleSort(nums, 5) ;
53
-
54
- plant("After sorting:") ;
55
- printArr(nums, 5, 0) ;
56
- plant("") ;
57
- reclaim ;
58
- }
59
- '''
60
-
61
- lexer = Lexer(code)
62
- tokens, lex_errors = lexer.make_tokens()
63
- print("Lex:", len(tokens), "tokens, errors:", lex_errors)
64
-
65
- parser = LL1Parser(cfg=cfg, predict_sets=predict_sets, first_sets=first_sets)
66
- errors = parser.parse(tokens)
67
- print("Parse:", errors)
68
-
69
- filtered = [t for t in tokens if t.type != '\n']
70
- ast = build_ast(filtered)
71
- print("Semantic OK")
72
-
73
- interp = Interpreter()
74
- interp.plant = lambda value: print(value, end="")
75
- interp.interpret(ast)
76
- print()
77
- print("Done")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Backend/test_mp16_full.py DELETED
@@ -1,113 +0,0 @@
1
- """Test MP16: Array Elements Print & Sort with Recursion (lex+parse+semantic only)."""
2
- from lexer import Lexer
3
- from Gal_Parser import LL1Parser
4
- from GALsemantic import build_ast
5
- from cfg import cfg, first_sets, predict_sets
6
-
7
- code = '''
8
- pollinate empty printArr(seed arr[], seed n, seed i) {
9
- spring(i >= n) {
10
- reclaim ;
11
- }
12
- plant("{} ", arr[i]) ;
13
- printArr(arr, n, i + 1) ;
14
- reclaim ;
15
- }
16
-
17
- pollinate empty bblPass(seed arr[], seed n, seed i) {
18
- spring(i >= n - 1) {
19
- reclaim ;
20
- }
21
- spring(arr[i] > arr[i + 1]) {
22
- seed temp = arr[i] ;
23
- arr[i] = arr[i + 1] ;
24
- arr[i + 1] = temp ;
25
- }
26
- bblPass(arr, n, i + 1) ;
27
- reclaim ;
28
- }
29
-
30
- pollinate empty sortAsc(seed arr[], seed n) {
31
- spring(n <= 1) {
32
- reclaim ;
33
- }
34
- bblPass(arr, n, 0) ;
35
- sortAsc(arr, n - 1) ;
36
- reclaim ;
37
- }
38
-
39
- pollinate empty bblPassDsc(seed arr[], seed n, seed i) {
40
- spring(i >= n - 1) {
41
- reclaim ;
42
- }
43
- spring(arr[i] < arr[i + 1]) {
44
- seed dTemp = arr[i] ;
45
- arr[i] = arr[i + 1] ;
46
- arr[i + 1] = dTemp ;
47
- }
48
- bblPassDsc(arr, n, i + 1) ;
49
- reclaim ;
50
- }
51
-
52
- pollinate empty sortDsc(seed arr[], seed n) {
53
- spring(n <= 1) {
54
- reclaim ;
55
- }
56
- bblPassDsc(arr, n, 0) ;
57
- sortDsc(arr, n - 1) ;
58
- reclaim ;
59
- }
60
-
61
- root() {
62
- plant("Input the number of elements to be stored in the array :") ;
63
- seed n = water(seed) ;
64
- seed arr[20] ;
65
-
66
- plant("Input {} elements in the array :", n) ;
67
- cultivate(seed i = 0 ; i < n ; i++) {
68
- plant("element - {} : ", i) ;
69
- arr[i] = water(seed) ;
70
- }
71
-
72
- plant("The elements in the array are : ") ;
73
- printArr(arr, n, 0) ;
74
-
75
- plant("Sort Out:") ;
76
- plant("1. Ascending") ;
77
- plant("2. Descending") ;
78
- plant("Enter choice (1 or 2): ") ;
79
- seed choice = water(seed) ;
80
-
81
- spring(choice == 1) {
82
- sortAsc(arr, n) ;
83
- plant("Ascending order : ") ;
84
- printArr(arr, n, 0) ;
85
- }
86
- bud(choice == 2) {
87
- sortDsc(arr, n) ;
88
- plant("Descending order : ") ;
89
- printArr(arr, n, 0) ;
90
- }
91
- wither {
92
- plant("Invalid choice!") ;
93
- }
94
-
95
- reclaim ;
96
- }
97
- '''
98
-
99
- # Lexer
100
- lexer = Lexer(code)
101
- tokens, lex_errors = lexer.make_tokens()
102
- print("Lex OK:", len(tokens), "tokens, errors:", lex_errors)
103
-
104
- # Parser
105
- parser = LL1Parser(cfg=cfg, predict_sets=predict_sets, first_sets=first_sets)
106
- errors = parser.parse(tokens)
107
- print("Parse:", errors)
108
-
109
- # Semantic + AST
110
- filtered = [t for t in tokens if t.type != '\n']
111
- ast = build_ast(filtered)
112
- print("Semantic + AST OK")
113
- print("All stages passed!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Docus & mps/CFG_FIRST_FOLLOW_PREDICT.txt ADDED
Binary file (48.2 kB). View file
 
Docus & mps/CFG_Latest_1_extracted.txt ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Production Production Set
2
+ 1 <program> -> <global_declaration> <function_definition> root ( ) { <statement> }
3
+ 2 <global_declaration>
4
+ -> bundle id <bundle_or_var> <global_declaration>
5
+ 3 <global_declaration>
6
+ -> <data_type> id <array_dec> <var_value> ; <global_declaration>
7
+ 4 <global_declaration>
8
+ -> fertile <data_type> id = <init_val> <const_next> ; <global_declaration>
9
+ 5 <global_declaration>
10
+ -> λ
11
+ 6 <bundle_or_var> -> { <bundle_members> } ;
12
+ 7 <bundle_or_var> -> <bundle_mem_dec> ;
13
+ 8 <declaration> -> <var_dec> ; <declaration>
14
+ 9 <declaration> -> <const_dec> ; <declaration>
15
+ 10 <declaration> -> λ
16
+ 11 <data_type> -> seed
17
+ 12 <data_type> -> tree
18
+ 13 <data_type> -> leaf
19
+ 14 <data_type> -> branch
20
+ 15 <data_type> -> vine
21
+ 16 <const_dec> -> fertile <data_type> id = <init_val> <const_next>
22
+ 17 <const_next> -> , id = <init_val> <const_next>
23
+ 18 <const_next> -> λ
24
+ 19 <var_dec> -> <data_type> id <array_dec> <var_value>
25
+ 20 <var_dec> -> bundle id <bundle_mem_dec>
26
+ 21 <bundle_mem_dec> -> id <array_dec> <var_value_next>
27
+ 22 <bundle_mem_dec> -> , id <var_value_next>
28
+ 23 <bundle_mem_dec> -> λ
29
+ 24 <var_value> -> = <init_val> <var_value_next>
30
+ 25 <var_value> -> <var_value_next>
31
+ 26 <var_value_next> -> , id <array_dec> <var_value>
32
+ 27 <var_value_next> -> λ
33
+ 28 <init_val> -> <array_init_opt>
34
+ 29 <init_val> -> water ( <water_arg> )
35
+ 30 <init_val> -> <expression>
36
+ 31 <array_dec> -> [ <array_dim_opt> ] <array_dec>
37
+ 32 <array_dec> -> λ
38
+ 33 <array_dim_opt> -> intlit
39
+ 34 <array_dim_opt> -> dblit
40
+ 35 <array_dim_opt> -> λ
41
+ 36 <array_init_opt> -> { <init_vals> }
42
+ 37 <array_init_opt> -> λ
43
+ 38 <init_vals> -> <init_val_item> <init_vals_next>
44
+ 39 <init_vals> -> λ
45
+ 40 <init_vals_next> -> , <init_val_item> <init_vals_next>
46
+ 41 <init_vals_next> -> λ
47
+ 42 <init_val_item> -> { <init_vals> }
48
+ 43 <init_val_item> -> <expression>
49
+ 44 <bundle_declaration>
50
+ -> bundle id { <bundle_members> }
51
+ 45 <bundle_members> -> <data_type> id ; <bundle_members>
52
+ 46 <bundle_members> -> id id ; <bundle_members>
53
+ 47 <bundle_members> -> λ
54
+ 48 <function_definition>
55
+ -> pollinate <return_type> id ( <parameters> ) { <statement> } <function_definition>
56
+ 49 <function_definition>
57
+ -> λ
58
+ 50 <return_type> -> <data_type>
59
+ 51 <return_type> -> empty
60
+ 52 <return_type> -> id
61
+ 53 <parameters> -> λ
62
+ 54 <parameters> -> <param> <param_next>
63
+ 55 <param> -> <data_type> id <param_array>
64
+ 56 <param> -> id id
65
+ 57 <param_array> -> λ
66
+ 58 <param_array> -> [ ]
67
+ 59 <param_next> -> λ
68
+ 60 <param_next> -> , <param> <param_next>
69
+ 61 <reclaim_opt> -> reclaim <reclaim_value>
70
+ 62 <reclaim_opt> -> λ
71
+ 63 <reclaim_value> -> <expression> ;
72
+ 64 <reclaim_value> -> ;
73
+ 65 <statement> -> <simple_stmt> <statement>
74
+ 66 <statement> -> λ
75
+ 67 <simple_stmt> -> id <id_stmt>
76
+ 68 <simple_stmt> -> <inc_dec_op> id ;
77
+ 69 <simple_stmt> -> <io_stmt>
78
+ 70 <simple_stmt> -> <conditional_stmt>
79
+ 71 <simple_stmt> -> <loop_stmt>
80
+ 72 <simple_stmt> -> <switch_stmt>
81
+ 73 <simple_stmt> -> <control_stmt>
82
+ 74 <simple_stmt> -> reclaim <reclaim_value>
83
+ 75 <simple_stmt> -> <var_dec> ;
84
+ 76 <simple_stmt> -> <const_dec> ;
85
+ 77 <id_stmt> -> <id_next> <assign_op> <assign_rhs> ;
86
+ 78 <id_stmt> -> <inc_dec_op> ;
87
+ 79 <id_stmt> -> ( <arguments> ) ;
88
+ 80 <assignment_stmt> -> <value> <assign_op> <assign_rhs> ;
89
+ 81 <assign_rhs> -> water ( <water_arg> )
90
+ 82 <assign_rhs> -> <expression>
91
+ 83 <assign_op> -> =
92
+ 84 <assign_op> -> +=
93
+ 85 <assign_op> -> -=
94
+ 86 <assign_op> -> *=
95
+ 87 <assign_op> -> /=
96
+ 88 <assign_op> -> %=
97
+ 89 <value> -> id <id_next>
98
+ 90 <id_next> -> <array_access> <post_array_access>
99
+ 91 <id_next> -> <struct_access>
100
+ 92 <id_next> -> λ
101
+ 93 <array_access> -> [ <expression> ] <array_access_more>
102
+ 94 <array_access_more>
103
+ -> [ <expression> ] <array_access_more>
104
+ 95 <array_access_more>
105
+ -> λ
106
+ 96 <struct_access> -> . id <struct_access_more>
107
+ 97 <struct_access_more>
108
+ -> . id <struct_access_more>
109
+ 98 <struct_access_more>
110
+ -> λ
111
+ 99 <post_array_access>
112
+ -> . id <post_array_access>
113
+ 100 <post_array_access>
114
+ -> λ
115
+ 101 <io_stmt> -> plant ( <arguments> ) ;
116
+ 102 <io_stmt> -> water ( <water_arg> ) ;
117
+ 103 <water_arg> -> <data_type>
118
+ 104 <water_arg> -> id <water_id_tail>
119
+ 105 <water_arg> -> λ
120
+ 106 <water_id_tail> -> [ <expression> ] <water_id_tail>
121
+ 107 <water_id_tail> -> λ
122
+ 108 <arguments> -> <expression> <arg_next>
123
+ 109 <arguments> -> λ
124
+ 110 <arg_next> -> , <expression> <arg_next>
125
+ 111 <arg_next> -> λ
126
+ 112 <conditional_stmt>
127
+ -> spring ( <expression> ) { <statement> } <elseif_chain> <else_opt>
128
+ 113 <elseif_chain> -> bud ( <expression> ) { <statement> } <elseif_chain>
129
+ 114 <elseif_chain> -> λ
130
+ 115 <else_opt> -> wither { <statement> }
131
+ 116 <else_opt> -> λ
132
+ 117 <loop_stmt> -> grow ( <expression> ) { <statement> }
133
+ 118 <loop_stmt> -> cultivate ( <for_init> ; <expression> ; <for_update> ) { <statement> }
134
+ 119 <loop_stmt> -> tend { <statement> } grow ( <expression> ) ;
135
+ 120 <for_init> -> <data_type> id <array_dec> <var_value>
136
+ 121 <for_init> -> id <id_next> <assign_op> <expression>
137
+ 122 <for_init> -> λ
138
+ 123 <for_update> -> id <for_update_type>
139
+ 124 <for_update> -> λ
140
+ 125 <for_update_type> -> <inc_dec_op>
141
+ 126 <for_update_type> -> <id_next> <assign_op> <expression>
142
+ 127 <unary_stmt> -> id <inc_dec_op> ;
143
+ 128 <inc_dec_op> -> ++
144
+ 129 <inc_dec_op> -> --
145
+ 130 <switch_stmt> -> harvest ( <expression> ) { <case_list> <default_opt> }
146
+ 131 <case_list> -> variety <case_literal> : <case_statements> <case_list>
147
+ 132 <case_list> -> λ
148
+ 133 <case_literal> -> intlit
149
+ 134 <case_literal> -> dblit
150
+ 135 <case_literal> -> chrlit
151
+ 136 <case_literal> -> stringlit
152
+ 137 <case_literal> -> sunshine
153
+ 138 <case_literal> -> frost
154
+ 139 <case_statements> -> <case_statement> <case_statements>
155
+ 140 <case_statements> -> λ
156
+ 141 <case_statement> -> id <id_stmt>
157
+ 142 <case_statement> -> <inc_dec_op> id ;
158
+ 143 <case_statement> -> <var_dec> ;
159
+ 144 <case_statement> -> <io_stmt>
160
+ 145 <case_statement> -> <conditional_stmt>
161
+ 146 <case_statement> -> <loop_stmt>
162
+ 147 <case_statement> -> <switch_stmt>
163
+ 148 <case_statement> -> { <case_statements> }
164
+ 149 <case_statement> -> prune ;
165
+ 150 <case_statement> -> skip ;
166
+ 151 <case_statement> -> reclaim <reclaim_value>
167
+ 152 <default_opt> -> soil : <case_statements>
168
+ 153 <default_opt> -> λ
169
+ 154 <control_stmt> -> prune ;
170
+ 155 <control_stmt> -> skip ;
171
+ 156 <function_call> -> id ( <arguments> ) ;
172
+ 157 <expression> -> <logic_or>
173
+ 158 <logic_or> -> <logic_and> <logic_or_next>
174
+ 159 <logic_or_next> -> || <logic_and> <logic_or_next>
175
+ 160 <logic_or_next> -> λ
176
+ 161 <logic_and> -> <relational> <logic_and_next>
177
+ 162 <logic_and_next> -> && <relational> <logic_and_next>
178
+ 163 <logic_and_next> -> λ
179
+ 164 <relational> -> <arithmetic> <relational_next>
180
+ 165 <relational_next> -> <relational_op> <arithmetic>
181
+ 166 <relational_next> -> λ
182
+ 167 <relational_op> -> >
183
+ 168 <relational_op> -> <
184
+ 169 <relational_op> -> >=
185
+ 170 <relational_op> -> <=
186
+ 171 <relational_op> -> ==
187
+ 172 <relational_op> -> !=
188
+ 173 <arithmetic> -> <term> <arithmetic_next>
189
+ 174 <arithmetic_next> -> + <term> <arithmetic_next>
190
+ 175 <arithmetic_next> -> - <term> <arithmetic_next>
191
+ 176 <arithmetic_next> -> ` <term> <arithmetic_next>
192
+ 177 <arithmetic_next> -> λ
193
+ 178 <term> -> <factor> <term_next>
194
+ 179 <term_next> -> * <factor> <term_next>
195
+ 180 <term_next> -> / <factor> <term_next>
196
+ 181 <term_next> -> % <factor> <term_next>
197
+ 182 <term_next> -> λ
198
+ 183 <factor> -> ( <paren_expr>
199
+ 184 <factor> -> <unary_op> <factor>
200
+ 185 <factor> -> id <factor_id_next>
201
+ 186 <factor> -> intlit
202
+ 187 <factor> -> dblit
203
+ 188 <factor> -> chrlit
204
+ 189 <factor> -> stringlit
205
+ 190 <factor> -> sunshine
206
+ 191 <factor> -> frost
207
+ 192 <paren_expr> -> <data_type> ) <factor>
208
+ 193 <paren_expr> -> <expression> )
209
+ 194 <unary_op> -> ~
210
+ 195 <unary_op> -> !
211
+ 196 <factor_id_next> -> <array_access> <post_array_access>
212
+ 197 <factor_id_next> -> <struct_access>
213
+ 198 <factor_id_next> -> ( <arguments> )
214
+ 199 <factor_id_next> -> λ
Docus & mps/CFG_Latest_First_Follow_Predict_Set_extracted.txt ADDED
@@ -0,0 +1,1441 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ XI. FIRST SET
2
+ #
3
+ Nonterminal
4
+ First Set
5
+ 1
6
+ <program>
7
+ ->
8
+ { branch, bundle, fertile, leaf, pollinate, root, seed, tree, vine }
9
+ 2
10
+ <global_declaration>
11
+ ->
12
+ { branch, bundle, fertile, leaf, seed, tree, vine, λ }
13
+ 3
14
+ <bundle_or_var>
15
+ ->
16
+ { {, ,, ;, id }
17
+ 4
18
+ <declaration>
19
+ ->
20
+ { branch, bundle, fertile, leaf, seed, tree, vine, λ }
21
+ 5
22
+ <data_type>
23
+ ->
24
+ { branch, leaf, seed, tree, vine }
25
+ 6
26
+ <const_dec>
27
+ ->
28
+ { fertile }
29
+ 7
30
+ <const_next>
31
+ ->
32
+ { ,, λ }
33
+ 8
34
+ <var_dec>
35
+ ->
36
+ { branch, bundle, leaf, seed, tree, vine }
37
+ 9
38
+ <bundle_mem_dec>
39
+ ->
40
+ { ,, id, λ }
41
+ 10
42
+ <var_value>
43
+ ->
44
+ { ,, =, λ }
45
+ 11
46
+ <var_value_next>
47
+ ->
48
+ { ,, λ }
49
+ 12
50
+ <init_val>
51
+ ->
52
+ { !, ~, (, {, id, water, intlit, dblit, chrlit, stringlit, sunshine, frost, λ }
53
+ 13
54
+ <array_dec>
55
+ ->
56
+ { [, λ }
57
+ 14
58
+ <array_dim_opt>
59
+ ->
60
+ { intlit, dblit, λ }
61
+ 15
62
+ <array_init_opt>
63
+ ->
64
+ { {, λ }
65
+ 16
66
+ <init_vals>
67
+ ->
68
+ { !, ~, (, {, id, intlit, dblit, chrlit, stringlit, sunshine, frost, λ }
69
+ 17
70
+ <init_vals_next>
71
+ ->
72
+ { ,, λ }
73
+ 18
74
+ <init_val_item>
75
+ ->
76
+ { !, ~, (, {, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
77
+ 19
78
+ <bundle_declaration>
79
+ ->
80
+ { bundle }
81
+ 20
82
+ <bundle_members>
83
+ ->
84
+ { branch, id, leaf, seed, tree, vine, λ }
85
+ 21
86
+ <function_definition>
87
+ ->
88
+ { pollinate, λ }
89
+ 22
90
+ <return_type>
91
+ ->
92
+ { branch, empty, id, leaf, seed, tree, vine }
93
+ 23
94
+ <parameters>
95
+ ->
96
+ { branch, id, leaf, seed, tree, vine, λ }
97
+ 24
98
+ <param>
99
+ ->
100
+ { branch, id, leaf, seed, tree, vine }
101
+ 25
102
+ <param_array>
103
+ ->
104
+ { [, λ }
105
+ 26
106
+ <param_next>
107
+ ->
108
+ { ,, λ }
109
+ 27
110
+ <reclaim_opt>
111
+ ->
112
+ { reclaim, λ }
113
+ 28
114
+ <reclaim_value>
115
+ ->
116
+ { !, ~, (, ;, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
117
+ 29
118
+ <statement>
119
+ ->
120
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water, λ }
121
+ 30
122
+ <simple_stmt>
123
+ ->
124
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water }
125
+ 31
126
+ <id_stmt>
127
+ ->
128
+ { ++, --, (, [, ., =, +=, -=, *=, /=, %= }
129
+ 32
130
+ <assignment_stmt>
131
+ ->
132
+ { id }
133
+ 33
134
+ <assign_rhs>
135
+ ->
136
+ { !, ~, (, id, water, intlit, dblit, chrlit, stringlit, sunshine, frost }
137
+ 34
138
+ <assign_op>
139
+ ->
140
+ { =, +=, -=, *=, /=, %= }
141
+ 35
142
+ <value>
143
+ ->
144
+ { id }
145
+ 36
146
+ <id_next>
147
+ ->
148
+ { [, ., λ }
149
+ 37
150
+ <array_access>
151
+ ->
152
+ { [ }
153
+ 38
154
+ <array_access_more>
155
+ ->
156
+ { [, λ }
157
+ 39
158
+ <struct_access>
159
+ ->
160
+ { . }
161
+ 40
162
+ <struct_access_more>
163
+ ->
164
+ { ., λ }
165
+ 41
166
+ <post_array_access>
167
+ ->
168
+ { ., λ }
169
+ 42
170
+ <io_stmt>
171
+ ->
172
+ { plant, water }
173
+ 43
174
+ <water_arg>
175
+ ->
176
+ { branch, id, leaf, seed, tree, vine, λ }
177
+ 44
178
+ <water_id_tail>
179
+ ->
180
+ { [, λ }
181
+ 45
182
+ <arguments>
183
+ ->
184
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost, λ }
185
+ 46
186
+ <arg_next>
187
+ ->
188
+ { ,, λ }
189
+ 47
190
+ <conditional_stmt>
191
+ ->
192
+ { spring }
193
+ 48
194
+ <elseif_chain>
195
+ ->
196
+ { bud, λ }
197
+ 49
198
+ <else_opt>
199
+ ->
200
+ { wither, λ }
201
+ 50
202
+ <loop_stmt>
203
+ ->
204
+ { cultivate, grow, tend }
205
+ 51
206
+ <for_init>
207
+ ->
208
+ { branch, id, leaf, seed, tree, vine, λ }
209
+ 52
210
+ <for_update>
211
+ ->
212
+ { id, λ }
213
+ 53
214
+ <for_update_type>
215
+ ->
216
+ { ++, --, [, ., =, +=, -=, *=, /=, %= }
217
+ 54
218
+ <unary_stmt>
219
+ ->
220
+ { id }
221
+ 55
222
+ <inc_dec_op>
223
+ ->
224
+ { ++, -- }
225
+ 56
226
+ <switch_stmt>
227
+ ->
228
+ { harvest }
229
+ 57
230
+ <case_list>
231
+ ->
232
+ { variety, λ }
233
+ 58
234
+ <case_literal>
235
+ ->
236
+ { intlit, dblit, chrlit, stringlit, sunshine, frost }
237
+ 59
238
+ <case_statements>
239
+ ->
240
+ { ++, --, {, branch, bundle, cultivate, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water, λ }
241
+ 60
242
+ <case_statement>
243
+ ->
244
+ { ++, --, {, branch, bundle, cultivate, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water }
245
+ 61
246
+ <default_opt>
247
+ ->
248
+ { soil, λ }
249
+ 62
250
+ <control_stmt>
251
+ ->
252
+ { prune, skip }
253
+ 63
254
+ <function_call>
255
+ ->
256
+ { id }
257
+ 64
258
+ <expression>
259
+ ->
260
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
261
+ 65
262
+ <logic_or>
263
+ ->
264
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
265
+ 66
266
+ <logic_or_next>
267
+ ->
268
+ { ||, λ }
269
+ 67
270
+ <logic_and>
271
+ ->
272
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
273
+ 68
274
+ <logic_and_next>
275
+ ->
276
+ { &&, λ }
277
+ 69
278
+ <relational>
279
+ ->
280
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
281
+ 70
282
+ <relational_next>
283
+ ->
284
+ { >, <, >=, <=, ==, !=, λ }
285
+ 71
286
+ <relational_op>
287
+ ->
288
+ { >, <, >=, <=, ==, != }
289
+ 72
290
+ <arithmetic>
291
+ ->
292
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
293
+ 73
294
+ <arithmetic_next>
295
+ ->
296
+ { +, -, `, λ }
297
+ 74
298
+ <term>
299
+ ->
300
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
301
+ 75
302
+ <term_next>
303
+ ->
304
+ { *, /, %, λ }
305
+ 76
306
+ <factor>
307
+ ->
308
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
309
+ 77
310
+ <paren_expr>
311
+ ->
312
+ { !, ~, (, branch, id, leaf, seed, tree, vine, intlit, dblit, chrlit, stringlit, sunshine, frost }
313
+ 78
314
+ <unary_op>
315
+ ->
316
+ { !, ~ }
317
+ 79
318
+ <factor_id_next>
319
+ ->
320
+ { (, [, ., λ }
321
+ XII. FOLLOW SET
322
+ #
323
+ Nonterminal
324
+ Follow Set
325
+ 1
326
+ <program>
327
+ ->
328
+ { EOF }
329
+ 2
330
+ <global_declaration>
331
+ ->
332
+ { pollinate, root }
333
+ 3
334
+ <bundle_or_var>
335
+ ->
336
+ { branch, bundle, fertile, leaf, pollinate, root, seed, tree, vine }
337
+ 4
338
+ <declaration>
339
+ ->
340
+ { }
341
+ 5
342
+ <data_type>
343
+ ->
344
+ { ), id }
345
+ 6
346
+ <const_dec>
347
+ ->
348
+ { ; }
349
+ 7
350
+ <const_next>
351
+ ->
352
+ { ; }
353
+ 8
354
+ <var_dec>
355
+ ->
356
+ { ; }
357
+ 9
358
+ <bundle_mem_dec>
359
+ ->
360
+ { ; }
361
+ 10
362
+ <var_value>
363
+ ->
364
+ { ; }
365
+ 11
366
+ <var_value_next>
367
+ ->
368
+ { ; }
369
+ 12
370
+ <init_val>
371
+ ->
372
+ { ,, ; }
373
+ 13
374
+ <array_dec>
375
+ ->
376
+ { ,, ;, = }
377
+ 14
378
+ <array_dim_opt>
379
+ ->
380
+ { ] }
381
+ 15
382
+ <array_init_opt>
383
+ ->
384
+ { ,, ; }
385
+ 16
386
+ <init_vals>
387
+ ->
388
+ { } }
389
+ 17
390
+ <init_vals_next>
391
+ ->
392
+ { } }
393
+ 18
394
+ <init_val_item>
395
+ ->
396
+ { }, , }
397
+ 19
398
+ <bundle_declaration>
399
+ ->
400
+ { }
401
+ 20
402
+ <bundle_members>
403
+ ->
404
+ { } }
405
+ 21
406
+ <function_definition>
407
+ ->
408
+ { root }
409
+ 22
410
+ <return_type>
411
+ ->
412
+ { id }
413
+ 23
414
+ <parameters>
415
+ ->
416
+ { ) }
417
+ 24
418
+ <param>
419
+ ->
420
+ { ), , }
421
+ 25
422
+ <param_array>
423
+ ->
424
+ { ), , }
425
+ 26
426
+ <param_next>
427
+ ->
428
+ { ) }
429
+ 27
430
+ <reclaim_opt>
431
+ ->
432
+ { }
433
+ 28
434
+ <reclaim_value>
435
+ ->
436
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water }
437
+ 29
438
+ <statement>
439
+ ->
440
+ { } }
441
+ 30
442
+ <simple_stmt>
443
+ ->
444
+ { ++, --, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water }
445
+ 31
446
+ <id_stmt>
447
+ ->
448
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water }
449
+ 32
450
+ <assignment_stmt>
451
+ ->
452
+ { }
453
+ 33
454
+ <assign_rhs>
455
+ ->
456
+ { ; }
457
+ 34
458
+ <assign_op>
459
+ ->
460
+ { !, ~, (, id, water, intlit, dblit, chrlit, stringlit, sunshine, frost }
461
+ 35
462
+ <value>
463
+ ->
464
+ { =, +=, -=, *=, /=, %= }
465
+ 36
466
+ <id_next>
467
+ ->
468
+ { =, +=, -=, *=, /=, %= }
469
+ 37
470
+ <array_access>
471
+ ->
472
+ { ), ], }, ,, ;, ., =, +=, -=, *=, /=, %=, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
473
+ 38
474
+ <array_access_more>
475
+ ->
476
+ { ), ], }, ,, ;, ., =, +=, -=, *=, /=, %=, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
477
+ 39
478
+ <struct_access>
479
+ ->
480
+ { ), ], }, ,, ;, =, +=, -=, *=, /=, %=, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
481
+ 40
482
+ <struct_access_more>
483
+ ->
484
+ { ), ], }, ,, ;, =, +=, -=, *=, /=, %=, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
485
+ 41
486
+ <post_array_access>
487
+ ->
488
+ { ), ], }, ,, ;, =, +=, -=, *=, /=, %=, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
489
+ 42
490
+ <io_stmt>
491
+ ->
492
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water }
493
+ 43
494
+ <water_arg>
495
+ ->
496
+ { ) }
497
+ 44
498
+ <water_id_tail>
499
+ ->
500
+ { ) }
501
+ 45
502
+ <arguments>
503
+ ->
504
+ { ) }
505
+ 46
506
+ <arg_next>
507
+ ->
508
+ { ) }
509
+ 47
510
+ <conditional_stmt>
511
+ ->
512
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water }
513
+ 48
514
+ <elseif_chain>
515
+ ->
516
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, wither }
517
+ 49
518
+ <else_opt>
519
+ ->
520
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water }
521
+ 50
522
+ <loop_stmt>
523
+ ->
524
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water }
525
+ 51
526
+ <for_init>
527
+ ->
528
+ { ; }
529
+ 52
530
+ <for_update>
531
+ ->
532
+ { ) }
533
+ 53
534
+ <for_update_type>
535
+ ->
536
+ { ) }
537
+ 54
538
+ <unary_stmt>
539
+ ->
540
+ { }
541
+ 55
542
+ <inc_dec_op>
543
+ ->
544
+ { ), ;, id }
545
+ 56
546
+ <switch_stmt>
547
+ ->
548
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water }
549
+ 57
550
+ <case_list>
551
+ ->
552
+ { }, soil }
553
+ 58
554
+ <case_literal>
555
+ ->
556
+ { : }
557
+ 59
558
+ <case_statements>
559
+ ->
560
+ { }, soil, variety }
561
+ 60
562
+ <case_statement>
563
+ ->
564
+ { ++, --, {, }, branch, bundle, cultivate, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water }
565
+ 61
566
+ <default_opt>
567
+ ->
568
+ { } }
569
+ 62
570
+ <control_stmt>
571
+ ->
572
+ { ++, --, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water }
573
+ 63
574
+ <function_call>
575
+ ->
576
+ { }
577
+ 64
578
+ <expression>
579
+ ->
580
+ { ), ], }, ,, ; }
581
+ 65
582
+ <logic_or>
583
+ ->
584
+ { ), ], }, ,, ; }
585
+ 66
586
+ <logic_or_next>
587
+ ->
588
+ { ), ], }, ,, ; }
589
+ 67
590
+ <logic_and>
591
+ ->
592
+ { ), ], }, ,, ;, || }
593
+ 68
594
+ <logic_and_next>
595
+ ->
596
+ { ), ], }, ,, ;, || }
597
+ 69
598
+ <relational>
599
+ ->
600
+ { ), ], }, ,, ;, &&, || }
601
+ 70
602
+ <relational_next>
603
+ ->
604
+ { ), ], }, ,, ;, &&, || }
605
+ 71
606
+ <relational_op>
607
+ ->
608
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
609
+ 72
610
+ <arithmetic>
611
+ ->
612
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, || }
613
+ 73
614
+ <arithmetic_next>
615
+ ->
616
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, || }
617
+ 74
618
+ <term>
619
+ ->
620
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, ||, +, -, ` }
621
+ 75
622
+ <term_next>
623
+ ->
624
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, ||, +, -, ` }
625
+ 76
626
+ <factor>
627
+ ->
628
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
629
+ 77
630
+ <paren_expr>
631
+ ->
632
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
633
+ 78
634
+ <unary_op>
635
+ ->
636
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
637
+ 79
638
+ <factor_id_next>
639
+ ->
640
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
641
+ XIII. PREDICT SET
642
+ No
643
+ FIRST / Expression Form
644
+ Basis
645
+ Predict Set
646
+ 1
647
+ first(<global_declaration> <function_definition> root ( ) { <statement> })
648
+ first(<global_declaration> <function_definition> root ( ) { <statement> })
649
+ { branch, bundle, fertile, leaf, pollinate, root, seed, tree, vine }
650
+ 2
651
+ first(bundle id <bundle_or_var> <global_declaration>)
652
+ first(bundle id <bundle_or_var> <global_declaration>)
653
+ { bundle }
654
+ 3
655
+ first(<data_type> id <array_dec> <var_value> ; <global_declaration>)
656
+ first(<data_type> id <array_dec> <var_value> ; <global_declaration>)
657
+ { branch, leaf, seed, tree, vine }
658
+ 4
659
+ first(fertile <data_type> id = <init_val> <const_next> ; <global_declaration>)
660
+ first(fertile <data_type> id = <init_val> <const_next> ; <global_declaration>)
661
+ { fertile }
662
+ 5
663
+ first(λ)
664
+ follow(<global_declaration>)
665
+ { pollinate, root }
666
+ 6
667
+ first({ <bundle_members> } ;)
668
+ first({ <bundle_members> } ;)
669
+ { { }
670
+ 7
671
+ first(<bundle_mem_dec> ;)
672
+ first(<bundle_mem_dec> ;)
673
+ { ,, ;, id }
674
+ 8
675
+ first(<var_dec> ; <declaration>)
676
+ first(<var_dec> ; <declaration>)
677
+ { branch, bundle, leaf, seed, tree, vine }
678
+ 9
679
+ first(<const_dec> ; <declaration>)
680
+ first(<const_dec> ; <declaration>)
681
+ { fertile }
682
+ 10
683
+ first(λ)
684
+ follow(<declaration>)
685
+ { }
686
+ 11
687
+ first(seed)
688
+ first(seed)
689
+ { seed }
690
+ 12
691
+ first(tree)
692
+ first(tree)
693
+ { tree }
694
+ 13
695
+ first(leaf)
696
+ first(leaf)
697
+ { leaf }
698
+ 14
699
+ first(branch)
700
+ first(branch)
701
+ { branch }
702
+ 15
703
+ first(vine)
704
+ first(vine)
705
+ { vine }
706
+ 16
707
+ first(fertile <data_type> id = <init_val> <const_next>)
708
+ first(fertile <data_type> id = <init_val> <const_next>)
709
+ { fertile }
710
+ 17
711
+ first(, id = <init_val> <const_next>)
712
+ first(, id = <init_val> <const_next>)
713
+ { , }
714
+ 18
715
+ first(λ)
716
+ follow(<const_next>)
717
+ { ; }
718
+ 19
719
+ first(<data_type> id <array_dec> <var_value>)
720
+ first(<data_type> id <array_dec> <var_value>)
721
+ { branch, leaf, seed, tree, vine }
722
+ 20
723
+ first(bundle id <bundle_mem_dec>)
724
+ first(bundle id <bundle_mem_dec>)
725
+ { bundle }
726
+ 21
727
+ first(id <array_dec> <var_value_next>)
728
+ first(id <array_dec> <var_value_next>)
729
+ { id }
730
+ 22
731
+ first(, id <var_value_next>)
732
+ first(, id <var_value_next>)
733
+ { , }
734
+ 23
735
+ first(λ)
736
+ follow(<bundle_mem_dec>)
737
+ { ; }
738
+ 24
739
+ first(= <init_val> <var_value_next>)
740
+ first(= <init_val> <var_value_next>)
741
+ { = }
742
+ 25
743
+ first(<var_value_next>)
744
+ first(<var_value_next>) ∪ follow(<var_value>)
745
+ { ,, ; }
746
+ 26
747
+ first(, id <array_dec> <var_value>)
748
+ first(, id <array_dec> <var_value>)
749
+ { , }
750
+ 27
751
+ first(λ)
752
+ follow(<var_value_next>)
753
+ { ; }
754
+ 28
755
+ first(<array_init_opt>)
756
+ first(<array_init_opt>) ∪ follow(<init_val>)
757
+ { {, ,, ; }
758
+ 29
759
+ first(water ( <water_arg> ))
760
+ first(water ( <water_arg> ))
761
+ { water }
762
+ 30
763
+ first(<expression>)
764
+ first(<expression>)
765
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
766
+ 31
767
+ first([ <array_dim_opt> ] <array_dec>)
768
+ first([ <array_dim_opt> ] <array_dec>)
769
+ { [ }
770
+ 32
771
+ first(λ)
772
+ follow(<array_dec>)
773
+ { ,, ;, = }
774
+ 33
775
+ first(intlit)
776
+ first(intlit)
777
+ { intlit }
778
+ 34
779
+ first(dblit)
780
+ first(dblit)
781
+ { dblit }
782
+ 35
783
+ first(λ)
784
+ follow(<array_dim_opt>)
785
+ { ] }
786
+ 36
787
+ first({ <init_vals> })
788
+ first({ <init_vals> })
789
+ { { }
790
+ 37
791
+ first(λ)
792
+ follow(<array_init_opt>)
793
+ { ,, ; }
794
+ 38
795
+ first(<init_val_item> <init_vals_next>)
796
+ first(<init_val_item> <init_vals_next>)
797
+ { !, ~, (, {, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
798
+ 39
799
+ first(λ)
800
+ follow(<init_vals>)
801
+ { } }
802
+ 40
803
+ first(, <init_val_item> <init_vals_next>)
804
+ first(, <init_val_item> <init_vals_next>)
805
+ { , }
806
+ 41
807
+ first(λ)
808
+ follow(<init_vals_next>)
809
+ { } }
810
+ 42
811
+ first({ <init_vals> })
812
+ first({ <init_vals> })
813
+ { { }
814
+ 43
815
+ first(<expression>)
816
+ first(<expression>)
817
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
818
+ 44
819
+ first(bundle id { <bundle_members> })
820
+ first(bundle id { <bundle_members> })
821
+ { bundle }
822
+ 45
823
+ first(<data_type> id ; <bundle_members>)
824
+ first(<data_type> id ; <bundle_members>)
825
+ { branch, leaf, seed, tree, vine }
826
+ 46
827
+ first(id id ; <bundle_members>)
828
+ first(id id ; <bundle_members>)
829
+ { id }
830
+ 47
831
+ first(λ)
832
+ follow(<bundle_members>)
833
+ { } }
834
+ 48
835
+ first(pollinate <return_type> id ( <parameters> ) { <statement> } <function_definition>)
836
+ first(pollinate <return_type> id ( <parameters> ) { <statement> } <function_definition>)
837
+ { pollinate }
838
+ 49
839
+ first(λ)
840
+ follow(<function_definition>)
841
+ { root }
842
+ 50
843
+ first(<data_type>)
844
+ first(<data_type>)
845
+ { branch, leaf, seed, tree, vine }
846
+ 51
847
+ first(empty)
848
+ first(empty)
849
+ { empty }
850
+ 52
851
+ first(id)
852
+ first(id)
853
+ { id }
854
+ 53
855
+ first(λ)
856
+ follow(<parameters>)
857
+ { ) }
858
+ 54
859
+ first(<param> <param_next>)
860
+ first(<param> <param_next>)
861
+ { branch, id, leaf, seed, tree, vine }
862
+ 55
863
+ first(<data_type> id <param_array>)
864
+ first(<data_type> id <param_array>)
865
+ { branch, leaf, seed, tree, vine }
866
+ 56
867
+ first(id id)
868
+ first(id id)
869
+ { id }
870
+ 57
871
+ first(λ)
872
+ follow(<param_array>)
873
+ { ), , }
874
+ 58
875
+ first([ ])
876
+ first([ ])
877
+ { [ }
878
+ 59
879
+ first(λ)
880
+ follow(<param_next>)
881
+ { ) }
882
+ 60
883
+ first(, <param> <param_next>)
884
+ first(, <param> <param_next>)
885
+ { , }
886
+ 61
887
+ first(reclaim <reclaim_value>)
888
+ first(reclaim <reclaim_value>)
889
+ { reclaim }
890
+ 62
891
+ first(λ)
892
+ follow(<reclaim_opt>)
893
+ { }
894
+ 63
895
+ first(<expression> ;)
896
+ first(<expression> ;)
897
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
898
+ 64
899
+ first(;)
900
+ first(;)
901
+ { ; }
902
+ 65
903
+ first(<simple_stmt> <statement>)
904
+ first(<simple_stmt> <statement>)
905
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water }
906
+ 66
907
+ first(λ)
908
+ follow(<statement>)
909
+ { } }
910
+ 67
911
+ first(id <id_stmt>)
912
+ first(id <id_stmt>)
913
+ { id }
914
+ 68
915
+ first(<inc_dec_op> id ;)
916
+ first(<inc_dec_op> id ;)
917
+ { ++, -- }
918
+ 69
919
+ first(<io_stmt>)
920
+ first(<io_stmt>)
921
+ { plant, water }
922
+ 70
923
+ first(<conditional_stmt>)
924
+ first(<conditional_stmt>)
925
+ { spring }
926
+ 71
927
+ first(<loop_stmt>)
928
+ first(<loop_stmt>)
929
+ { cultivate, grow, tend }
930
+ 72
931
+ first(<switch_stmt>)
932
+ first(<switch_stmt>)
933
+ { harvest }
934
+ 73
935
+ first(<control_stmt>)
936
+ first(<control_stmt>)
937
+ { prune, skip }
938
+ 74
939
+ first(reclaim <reclaim_value>)
940
+ first(reclaim <reclaim_value>)
941
+ { reclaim }
942
+ 75
943
+ first(<var_dec> ;)
944
+ first(<var_dec> ;)
945
+ { branch, bundle, leaf, seed, tree, vine }
946
+ 76
947
+ first(<const_dec> ;)
948
+ first(<const_dec> ;)
949
+ { fertile }
950
+ 77
951
+ first(<id_next> <assign_op> <assign_rhs> ;)
952
+ first(<id_next> <assign_op> <assign_rhs> ;)
953
+ { [, ., =, +=, -=, *=, /=, %= }
954
+ 78
955
+ first(<inc_dec_op> ;)
956
+ first(<inc_dec_op> ;)
957
+ { ++, -- }
958
+ 79
959
+ first(( <arguments> ) ;)
960
+ first(( <arguments> ) ;)
961
+ { ( }
962
+ 80
963
+ first(<value> <assign_op> <assign_rhs> ;)
964
+ first(<value> <assign_op> <assign_rhs> ;)
965
+ { id }
966
+ 81
967
+ first(water ( <water_arg> ))
968
+ first(water ( <water_arg> ))
969
+ { water }
970
+ 82
971
+ first(<expression>)
972
+ first(<expression>)
973
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
974
+ 83
975
+ first(=)
976
+ first(=)
977
+ { = }
978
+ 84
979
+ first(+=)
980
+ first(+=)
981
+ { += }
982
+ 85
983
+ first(-=)
984
+ first(-=)
985
+ { -= }
986
+ 86
987
+ first(*=)
988
+ first(*=)
989
+ { *= }
990
+ 87
991
+ first(/=)
992
+ first(/=)
993
+ { /= }
994
+ 88
995
+ first(%=)
996
+ first(%=)
997
+ { %= }
998
+ 89
999
+ first(id <id_next>)
1000
+ first(id <id_next>)
1001
+ { id }
1002
+ 90
1003
+ first(<array_access> <post_array_access>)
1004
+ first(<array_access> <post_array_access>)
1005
+ { [ }
1006
+ 91
1007
+ first(<struct_access>)
1008
+ first(<struct_access>)
1009
+ { . }
1010
+ 92
1011
+ first(λ)
1012
+ follow(<id_next>)
1013
+ { =, +=, -=, *=, /=, %= }
1014
+ 93
1015
+ first([ <expression> ] <array_access_more>)
1016
+ first([ <expression> ] <array_access_more>)
1017
+ { [ }
1018
+ 94
1019
+ first([ <expression> ] <array_access_more>)
1020
+ first([ <expression> ] <array_access_more>)
1021
+ { [ }
1022
+ 95
1023
+ first(λ)
1024
+ follow(<array_access_more>)
1025
+ { ), ], }, ,, ;, ., =, +=, -=, *=, /=, %=, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
1026
+ 96
1027
+ first(. id <struct_access_more>)
1028
+ first(. id <struct_access_more>)
1029
+ { . }
1030
+ 97
1031
+ first(. id <struct_access_more>)
1032
+ first(. id <struct_access_more>)
1033
+ { . }
1034
+ 98
1035
+ first(λ)
1036
+ follow(<struct_access_more>)
1037
+ { ), ], }, ,, ;, =, +=, -=, *=, /=, %=, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
1038
+ 99
1039
+ first(. id <post_array_access>)
1040
+ first(. id <post_array_access>)
1041
+ { . }
1042
+ 100
1043
+ first(λ)
1044
+ follow(<post_array_access>)
1045
+ { ), ], }, ,, ;, =, +=, -=, *=, /=, %=, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
1046
+ 101
1047
+ first(plant ( <arguments> ) ;)
1048
+ first(plant ( <arguments> ) ;)
1049
+ { plant }
1050
+ 102
1051
+ first(water ( <water_arg> ) ;)
1052
+ first(water ( <water_arg> ) ;)
1053
+ { water }
1054
+ 103
1055
+ first(<data_type>)
1056
+ first(<data_type>)
1057
+ { branch, leaf, seed, tree, vine }
1058
+ 104
1059
+ first(id <water_id_tail>)
1060
+ first(id <water_id_tail>)
1061
+ { id }
1062
+ 105
1063
+ first(λ)
1064
+ follow(<water_arg>)
1065
+ { ) }
1066
+ 106
1067
+ first([ <expression> ] <water_id_tail>)
1068
+ first([ <expression> ] <water_id_tail>)
1069
+ { [ }
1070
+ 107
1071
+ first(λ)
1072
+ follow(<water_id_tail>)
1073
+ { ) }
1074
+ 108
1075
+ first(<expression> <arg_next>)
1076
+ first(<expression> <arg_next>)
1077
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
1078
+ 109
1079
+ first(λ)
1080
+ follow(<arguments>)
1081
+ { ) }
1082
+ 110
1083
+ first(, <expression> <arg_next>)
1084
+ first(, <expression> <arg_next>)
1085
+ { , }
1086
+ 111
1087
+ first(λ)
1088
+ follow(<arg_next>)
1089
+ { ) }
1090
+ 112
1091
+ first(spring ( <expression> ) { <statement> } <elseif_chain> <else_opt>)
1092
+ first(spring ( <expression> ) { <statement> } <elseif_chain> <else_opt>)
1093
+ { spring }
1094
+ 113
1095
+ first(bud ( <expression> ) { <statement> } <elseif_chain>)
1096
+ first(bud ( <expression> ) { <statement> } <elseif_chain>)
1097
+ { bud }
1098
+ 114
1099
+ first(λ)
1100
+ follow(<elseif_chain>)
1101
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, wither }
1102
+ 115
1103
+ first(wither { <statement> })
1104
+ first(wither { <statement> })
1105
+ { wither }
1106
+ 116
1107
+ first(λ)
1108
+ follow(<else_opt>)
1109
+ { ++, --, {, }, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water }
1110
+ 117
1111
+ first(grow ( <expression> ) { <statement> })
1112
+ first(grow ( <expression> ) { <statement> })
1113
+ { grow }
1114
+ 118
1115
+ first(cultivate ( <for_init> ; <expression> ; <for_update> ) { <statement> })
1116
+ first(cultivate ( <for_init> ; <expression> ; <for_update> ) { <statement> })
1117
+ { cultivate }
1118
+ 119
1119
+ first(tend { <statement> } grow ( <expression> ) ;)
1120
+ first(tend { <statement> } grow ( <expression> ) ;)
1121
+ { tend }
1122
+ 120
1123
+ first(<data_type> id <array_dec> <var_value>)
1124
+ first(<data_type> id <array_dec> <var_value>)
1125
+ { branch, leaf, seed, tree, vine }
1126
+ 121
1127
+ first(id <id_next> <assign_op> <expression>)
1128
+ first(id <id_next> <assign_op> <expression>)
1129
+ { id }
1130
+ 122
1131
+ first(λ)
1132
+ follow(<for_init>)
1133
+ { ; }
1134
+ 123
1135
+ first(id <for_update_type>)
1136
+ first(id <for_update_type>)
1137
+ { id }
1138
+ 124
1139
+ first(λ)
1140
+ follow(<for_update>)
1141
+ { ) }
1142
+ 125
1143
+ first(<inc_dec_op>)
1144
+ first(<inc_dec_op>)
1145
+ { ++, -- }
1146
+ 126
1147
+ first(<id_next> <assign_op> <expression>)
1148
+ first(<id_next> <assign_op> <expression>)
1149
+ { [, ., =, +=, -=, *=, /=, %= }
1150
+ 127
1151
+ first(id <inc_dec_op> ;)
1152
+ first(id <inc_dec_op> ;)
1153
+ { id }
1154
+ 128
1155
+ first(++)
1156
+ first(++)
1157
+ { ++ }
1158
+ 129
1159
+ first(--)
1160
+ first(--)
1161
+ { -- }
1162
+ 130
1163
+ first(harvest ( <expression> ) { <case_list> <default_opt> })
1164
+ first(harvest ( <expression> ) { <case_list> <default_opt> })
1165
+ { harvest }
1166
+ 131
1167
+ first(variety <case_literal> : <case_statements> <case_list>)
1168
+ first(variety <case_literal> : <case_statements> <case_list>)
1169
+ { variety }
1170
+ 132
1171
+ first(λ)
1172
+ follow(<case_list>)
1173
+ { }, soil }
1174
+ 133
1175
+ first(intlit)
1176
+ first(intlit)
1177
+ { intlit }
1178
+ 134
1179
+ first(dblit)
1180
+ first(dblit)
1181
+ { dblit }
1182
+ 135
1183
+ first(chrlit)
1184
+ first(chrlit)
1185
+ { chrlit }
1186
+ 136
1187
+ first(stringlit)
1188
+ first(stringlit)
1189
+ { stringlit }
1190
+ 137
1191
+ first(sunshine)
1192
+ first(sunshine)
1193
+ { sunshine }
1194
+ 138
1195
+ first(frost)
1196
+ first(frost)
1197
+ { frost }
1198
+ 139
1199
+ first(<case_statement> <case_statements>)
1200
+ first(<case_statement> <case_statements>)
1201
+ { ++, --, {, branch, bundle, cultivate, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water }
1202
+ 140
1203
+ first(λ)
1204
+ follow(<case_statements>)
1205
+ { }, soil, variety }
1206
+ 141
1207
+ first(id <id_stmt>)
1208
+ first(id <id_stmt>)
1209
+ { id }
1210
+ 142
1211
+ first(<inc_dec_op> id ;)
1212
+ first(<inc_dec_op> id ;)
1213
+ { ++, -- }
1214
+ 143
1215
+ first(<var_dec> ;)
1216
+ first(<var_dec> ;)
1217
+ { branch, bundle, leaf, seed, tree, vine }
1218
+ 144
1219
+ first(<io_stmt>)
1220
+ first(<io_stmt>)
1221
+ { plant, water }
1222
+ 145
1223
+ first(<conditional_stmt>)
1224
+ first(<conditional_stmt>)
1225
+ { spring }
1226
+ 146
1227
+ first(<loop_stmt>)
1228
+ first(<loop_stmt>)
1229
+ { cultivate, grow, tend }
1230
+ 147
1231
+ first(<switch_stmt>)
1232
+ first(<switch_stmt>)
1233
+ { harvest }
1234
+ 148
1235
+ first({ <case_statements> })
1236
+ first({ <case_statements> })
1237
+ { { }
1238
+ 149
1239
+ first(prune ;)
1240
+ first(prune ;)
1241
+ { prune }
1242
+ 150
1243
+ first(skip ;)
1244
+ first(skip ;)
1245
+ { skip }
1246
+ 151
1247
+ first(reclaim <reclaim_value>)
1248
+ first(reclaim <reclaim_value>)
1249
+ { reclaim }
1250
+ 152
1251
+ first(soil : <case_statements>)
1252
+ first(soil : <case_statements>)
1253
+ { soil }
1254
+ 153
1255
+ first(λ)
1256
+ follow(<default_opt>)
1257
+ { } }
1258
+ 154
1259
+ first(prune ;)
1260
+ first(prune ;)
1261
+ { prune }
1262
+ 155
1263
+ first(skip ;)
1264
+ first(skip ;)
1265
+ { skip }
1266
+ 156
1267
+ first(id ( <arguments> ) ;)
1268
+ first(id ( <arguments> ) ;)
1269
+ { id }
1270
+ 157
1271
+ first(<logic_or>)
1272
+ first(<logic_or>)
1273
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
1274
+ 158
1275
+ first(<logic_and> <logic_or_next>)
1276
+ first(<logic_and> <logic_or_next>)
1277
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
1278
+ 159
1279
+ first(|| <logic_and> <logic_or_next>)
1280
+ first(|| <logic_and> <logic_or_next>)
1281
+ { || }
1282
+ 160
1283
+ first(λ)
1284
+ follow(<logic_or_next>)
1285
+ { ), ], }, ,, ; }
1286
+ 161
1287
+ first(<relational> <logic_and_next>)
1288
+ first(<relational> <logic_and_next>)
1289
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
1290
+ 162
1291
+ first(&& <relational> <logic_and_next>)
1292
+ first(&& <relational> <logic_and_next>)
1293
+ { && }
1294
+ 163
1295
+ first(λ)
1296
+ follow(<logic_and_next>)
1297
+ { ), ], }, ,, ;, || }
1298
+ 164
1299
+ first(<arithmetic> <relational_next>)
1300
+ first(<arithmetic> <relational_next>)
1301
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
1302
+ 165
1303
+ first(<relational_op> <arithmetic>)
1304
+ first(<relational_op> <arithmetic>)
1305
+ { >, <, >=, <=, ==, != }
1306
+ 166
1307
+ first(λ)
1308
+ follow(<relational_next>)
1309
+ { ), ], }, ,, ;, &&, || }
1310
+ 167
1311
+ first(>)
1312
+ first(>)
1313
+ { > }
1314
+ 168
1315
+ first(<)
1316
+ first(<)
1317
+ { < }
1318
+ 169
1319
+ first(>=)
1320
+ first(>=)
1321
+ { >= }
1322
+ 170
1323
+ first(<=)
1324
+ first(<=)
1325
+ { <= }
1326
+ 171
1327
+ first(==)
1328
+ first(==)
1329
+ { == }
1330
+ 172
1331
+ first(!=)
1332
+ first(!=)
1333
+ { != }
1334
+ 173
1335
+ first(<term> <arithmetic_next>)
1336
+ first(<term> <arithmetic_next>)
1337
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
1338
+ 174
1339
+ first(+ <term> <arithmetic_next>)
1340
+ first(+ <term> <arithmetic_next>)
1341
+ { + }
1342
+ 175
1343
+ first(- <term> <arithmetic_next>)
1344
+ first(- <term> <arithmetic_next>)
1345
+ { - }
1346
+ 176
1347
+ first(` <term> <arithmetic_next>)
1348
+ first(` <term> <arithmetic_next>)
1349
+ { ` }
1350
+ 177
1351
+ first(λ)
1352
+ follow(<arithmetic_next>)
1353
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, || }
1354
+ 178
1355
+ first(<factor> <term_next>)
1356
+ first(<factor> <term_next>)
1357
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
1358
+ 179
1359
+ first(* <factor> <term_next>)
1360
+ first(* <factor> <term_next>)
1361
+ { * }
1362
+ 180
1363
+ first(/ <factor> <term_next>)
1364
+ first(/ <factor> <term_next>)
1365
+ { / }
1366
+ 181
1367
+ first(% <factor> <term_next>)
1368
+ first(% <factor> <term_next>)
1369
+ { % }
1370
+ 182
1371
+ first(λ)
1372
+ follow(<term_next>)
1373
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, ||, +, -, ` }
1374
+ 183
1375
+ first(( <paren_expr>)
1376
+ first(( <paren_expr>)
1377
+ { ( }
1378
+ 184
1379
+ first(<unary_op> <factor>)
1380
+ first(<unary_op> <factor>)
1381
+ { !, ~ }
1382
+ 185
1383
+ first(id <factor_id_next>)
1384
+ first(id <factor_id_next>)
1385
+ { id }
1386
+ 186
1387
+ first(intlit)
1388
+ first(intlit)
1389
+ { intlit }
1390
+ 187
1391
+ first(dblit)
1392
+ first(dblit)
1393
+ { dblit }
1394
+ 188
1395
+ first(chrlit)
1396
+ first(chrlit)
1397
+ { chrlit }
1398
+ 189
1399
+ first(stringlit)
1400
+ first(stringlit)
1401
+ { stringlit }
1402
+ 190
1403
+ first(sunshine)
1404
+ first(sunshine)
1405
+ { sunshine }
1406
+ 191
1407
+ first(frost)
1408
+ first(frost)
1409
+ { frost }
1410
+ 192
1411
+ first(<data_type> ) <factor>)
1412
+ first(<data_type> ) <factor>)
1413
+ { branch, leaf, seed, tree, vine }
1414
+ 193
1415
+ first(<expression> ))
1416
+ first(<expression> ))
1417
+ { !, ~, (, id, intlit, dblit, chrlit, stringlit, sunshine, frost }
1418
+ 194
1419
+ first(~)
1420
+ first(~)
1421
+ { ~ }
1422
+ 195
1423
+ first(!)
1424
+ first(!)
1425
+ { ! }
1426
+ 196
1427
+ first(<array_access> <post_array_access>)
1428
+ first(<array_access> <post_array_access>)
1429
+ { [ }
1430
+ 197
1431
+ first(<struct_access>)
1432
+ first(<struct_access>)
1433
+ { . }
1434
+ 198
1435
+ first(( <arguments> ))
1436
+ first(( <arguments> ))
1437
+ { ( }
1438
+ 199
1439
+ first(λ)
1440
+ follow(<factor_id_next>)
1441
+ { ), ], }, ,, ;, >, <, >=, <=, ==, !=, &&, ||, +, -, `, *, /, % }
Docus & mps/CFG_Latest_extracted.txt ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Production Production Set
2
+ 1 <program> -> <global_declaration> <function_definition> root ( ) { <statement> }
3
+ 2 <global_declaration>
4
+ -> bundle id <bundle_or_var> <global_declaration>
5
+ 3 <global_declaration>
6
+ -> <data_type> id <array_dec> <var_value> ; <global_declaration>
7
+ 4 <global_declaration>
8
+ -> fertile <data_type> id = <init_val> <const_next> ; <global_declaration>
9
+ 5 <global_declaration>
10
+ -> λ
11
+ 6 <bundle_or_var> -> { <bundle_members> } ;
12
+ 7 <bundle_or_var> -> <bundle_mem_dec> ;
13
+ 8 <declaration> -> <var_dec> ; <declaration>
14
+ 9 <declaration> -> <const_dec> ; <declaration>
15
+ 10 <declaration> -> λ
16
+ 11 <data_type> -> seed
17
+ 12 <data_type> -> tree
18
+ 13 <data_type> -> leaf
19
+ 14 <data_type> -> branch
20
+ 15 <data_type> -> vine
21
+ 16 <const_dec> -> fertile <data_type> id = <init_val> <const_next>
22
+ 17 <const_next> -> , id = <init_val> <const_next>
23
+ 18 <const_next> -> λ
24
+ 19 <var_dec> -> <data_type> id <array_dec> <var_value>
25
+ 20 <var_dec> -> bundle id <bundle_mem_dec>
26
+ 21 <bundle_mem_dec> -> id <array_dec> <var_value_next>
27
+ 22 <bundle_mem_dec> -> , id <var_value_next>
28
+ 23 <bundle_mem_dec> -> λ
29
+ 24 <var_value> -> = <init_val> <var_value_next>
30
+ 25 <var_value> -> <var_value_next>
31
+ 26 <var_value_next> -> , id <array_dec> <var_value>
32
+ 27 <var_value_next> -> λ
33
+ 28 <init_val> -> <array_init_opt>
34
+ 29 <init_val> -> water ( <water_arg> )
35
+ 30 <init_val> -> <expression>
36
+ 31 <array_dec> -> [ <array_dim_opt> ] <array_dec>
37
+ 32 <array_dec> -> λ
38
+ 33 <array_dim_opt> -> intlit
39
+ 34 <array_dim_opt> -> dblit
40
+ 35 <array_dim_opt> -> λ
41
+ 36 <array_init_opt> -> { <init_vals> }
42
+ 37 <array_init_opt> -> λ
43
+ 38 <init_vals> -> <init_val_item> <init_vals_next>
44
+ 39 <init_vals> -> λ
45
+ 40 <init_vals_next> -> , <init_val_item> <init_vals_next>
46
+ 41 <init_vals_next> -> λ
47
+ 42 <init_val_item> -> { <init_vals> }
48
+ 43 <init_val_item> -> <expression>
49
+ 44 <bundle_declaration>
50
+ -> bundle id { <bundle_members> }
51
+ 45 <bundle_members> -> <data_type> id ; <bundle_members>
52
+ 46 <bundle_members> -> id id ; <bundle_members>
53
+ 47 <bundle_members> -> λ
54
+ 48 <function_definition>
55
+ -> pollinate <return_type> id ( <parameters> ) { <statement> } <function_definition>
56
+ 49 <function_definition>
57
+ -> λ
58
+ 50 <return_type> -> <data_type>
59
+ 51 <return_type> -> empty
60
+ 52 <return_type> -> id
61
+ 53 <parameters> -> λ
62
+ 54 <parameters> -> <param> <param_next>
63
+ 55 <param> -> <data_type> id <param_array>
64
+ 56 <param> -> id id
65
+ 57 <param_array> -> λ
66
+ 58 <param_array> -> [ ]
67
+ 59 <param_next> -> λ
68
+ 60 <param_next> -> , <param> <param_next>
69
+ 61 <reclaim_opt> -> reclaim <reclaim_value>
70
+ 62 <reclaim_opt> -> λ
71
+ 63 <reclaim_value> -> <expression> ;
72
+ 64 <reclaim_value> -> ;
73
+ 65 <statement> -> <simple_stmt> <statement>
74
+ 66 <statement> -> λ
75
+ 67 <simple_stmt> -> id <id_stmt>
76
+ 68 <simple_stmt> -> <inc_dec_op> id ;
77
+ 69 <simple_stmt> -> <io_stmt>
78
+ 70 <simple_stmt> -> <conditional_stmt>
79
+ 71 <simple_stmt> -> <loop_stmt>
80
+ 72 <simple_stmt> -> <switch_stmt>
81
+ 73 <simple_stmt> -> <control_stmt>
82
+ 74 <simple_stmt> -> reclaim <reclaim_value>
83
+ 75 <simple_stmt> -> <var_dec> ;
84
+ 76 <simple_stmt> -> <const_dec> ;
85
+ 77 <id_stmt> -> <id_next> <assign_op> <assign_rhs> ;
86
+ 78 <id_stmt> -> <inc_dec_op> ;
87
+ 79 <id_stmt> -> ( <arguments> ) ;
88
+ 80 <assignment_stmt>
89
+ -> <value> <assign_op> <assign_rhs> ;
90
+ 81 <assign_rhs> -> water ( <water_arg> )
91
+ 82 <assign_rhs> -> <expression>
92
+ 83 <assign_op> -> =
93
+ 84 <assign_op> -> +=
94
+ 85 <assign_op> -> -=
95
+ 86 <assign_op> -> *=
96
+ 87 <assign_op> -> /=
97
+ 88 <assign_op> -> %=
98
+ 89 <value> -> id <id_next>
99
+ 90 <id_next> -> <array_access> <post_array_access>
100
+ 91 <id_next> -> <struct_access>
101
+ 92 <id_next> -> λ
102
+ 93 <array_access> -> [ <expression> ] <array_access_more>
103
+ 94 <array_access_more>
104
+ -> [ <expression> ] <array_access_more>
105
+ 95 <array_access_more>
106
+ -> λ
107
+ 96 <struct_access> -> . id <struct_access_more>
108
+ 97 <struct_access_more>
109
+ -> . id <struct_access_more>
110
+ 98 <struct_access_more>
111
+ -> λ
112
+ 99 <post_array_access>
113
+ -> . id <post_array_access>
114
+ 100 <post_array_access>
115
+ -> λ
116
+ 101 <io_stmt> -> plant ( <arguments> ) ;
117
+ 102 <io_stmt> -> water ( <water_arg> ) ;
118
+ 103 <water_arg> -> <data_type>
119
+ 104 <water_arg> -> id <water_id_tail>
120
+ 105 <water_arg> -> λ
121
+ 106 <water_id_tail> -> [ <expression> ] <water_id_tail>
122
+ 107 <water_id_tail> -> λ
123
+ 108 <arguments> -> <expression> <arg_next>
124
+ 109 <arguments> -> λ
125
+ 110 <arg_next> -> , <expression> <arg_next>
126
+ 111 <arg_next> -> λ
127
+ 112 <conditional_stmt>
128
+ -> spring ( <expression> ) { <statement> } <elseif_chain> <else_opt>
129
+ 113 <elseif_chain> -> bud ( <expression> ) { <statement> } <elseif_chain>
130
+ 114 <elseif_chain> -> λ
131
+ 115 <else_opt> -> wither { <statement> }
132
+ 116 <else_opt> -> λ
133
+ 117 <loop_stmt> -> grow ( <expression> ) { <statement> }
134
+ 118 <loop_stmt> -> cultivate ( <for_init> ; <expression> ; <for_update> ) { <statement> }
135
+ 119 <loop_stmt> -> tend { <statement> } grow ( <expression> ) ;
136
+ 120 <for_init> -> <data_type> id <array_dec> <var_value>
137
+ 121 <for_init> -> id <id_next> <assign_op> <expression>
138
+ 122 <for_init> -> λ
139
+ 123 <for_update> -> id <for_update_type>
140
+ 124 <for_update> -> λ
141
+ 125 <for_update_type>
142
+ -> <inc_dec_op>
143
+ 126 <for_update_type>
144
+ -> <id_next> <assign_op> <expression>
145
+ 127 <unary_stmt> -> id <inc_dec_op> ;
146
+ 128 <inc_dec_op> -> ++
147
+ 129 <inc_dec_op> -> --
148
+ 130 <switch_stmt> -> harvest ( <expression> ) { <case_list> <default_opt> }
149
+ 131 <case_list> -> variety <case_literal> : <case_statements> <case_list>
150
+ 132 <case_list> -> λ
151
+ 133 <case_literal> -> intlit
152
+ 134 <case_literal> -> dblit
153
+ 135 <case_literal> -> chrlit
154
+ 136 <case_literal> -> stringlit
155
+ 137 <case_literal> -> sunshine
156
+ 138 <case_literal> -> frost
157
+ 139 <case_statements>
158
+ -> <case_statement> <case_statements>
159
+ 140 <case_statements>
160
+ -> λ
161
+ 141 <case_statement> -> id <id_stmt>
162
+ 142 <case_statement> -> <inc_dec_op> id ;
163
+ 143 <case_statement> -> <var_dec> ;
164
+ 144 <case_statement> -> <io_stmt>
165
+ 145 <case_statement> -> <conditional_stmt>
166
+ 146 <case_statement> -> <loop_stmt>
167
+ 147 <case_statement> -> <switch_stmt>
168
+ 148 <case_statement> -> { <case_statements> }
169
+ 149 <case_statement> -> prune ;
170
+ 150 <case_statement> -> skip ;
171
+ 151 <case_statement> -> reclaim <reclaim_value>
172
+ 152 <default_opt> -> soil : <case_statements>
173
+ 153 <default_opt> -> λ
174
+ 154 <control_stmt> -> prune ;
175
+ 155 <control_stmt> -> skip ;
176
+ 156 <function_call> -> id ( <arguments> ) ;
177
+ 157 <expression> -> <logic_or>
178
+ 158 <logic_or> -> <logic_and> <logic_or_next>
179
+ 159 <logic_or_next> -> || <logic_and> <logic_or_next>
180
+ 160 <logic_or_next> -> λ
181
+ 161 <logic_and> -> <relational> <logic_and_next>
182
+ 162 <logic_and_next> -> && <relational> <logic_and_next>
183
+ 163 <logic_and_next> -> λ
184
+ 164 <relational> -> <arithmetic> <relational_next>
185
+ 165 <relational_next>
186
+ -> <relational_op> <arithmetic>
187
+ 166 <relational_next>
188
+ -> λ
189
+ 167 <relational_op> -> >
190
+ 168 <relational_op> -> <
191
+ 169 <relational_op> -> >=
192
+ 170 <relational_op> -> <=
193
+ 171 <relational_op> -> ==
194
+ 172 <relational_op> -> !=
195
+ 173 <arithmetic> -> <term> <arithmetic_next>
196
+ 174 <arithmetic_next>
197
+ -> + <term> <arithmetic_next>
198
+ 175 <arithmetic_next>
199
+ -> - <term> <arithmetic_next>
200
+ 176 <arithmetic_next>
201
+ -> \ <arithmetic_next>`
202
+ 177 <arithmetic_next>
203
+ -> λ
204
+ 178 <term> -> <factor> <term_next>
205
+ 179 <term_next> -> * <factor> <term_next>
206
+ 180 <term_next> -> / <factor> <term_next>
207
+ 181 <term_next> -> % <factor> <term_next>
208
+ 182 <term_next> -> λ
209
+ 183 <factor> -> ( <paren_expr>
210
+ 184 <factor> -> <unary_op> <factor>
211
+ 185 <factor> -> id <factor_id_next>
212
+ 186 <factor> -> intlit
213
+ 187 <factor> -> dblit
214
+ 188 <factor> -> chrlit
215
+ 189 <factor> -> stringlit
216
+ 190 <factor> -> sunshine
217
+ 191 <factor> -> frost
218
+ 192 <paren_expr> -> <data_type> ) <factor>
219
+ 193 <paren_expr> -> <expression> )
220
+ 194 <unary_op> -> ~
221
+ 195 <unary_op> -> !
222
+ 196 <factor_id_next> -> <array_access> <post_array_access>
223
+ 197 <factor_id_next> -> <struct_access>
224
+ 198 <factor_id_next> -> ( <arguments> )
225
+ 199 <factor_id_next> -> λ
Docus & mps/CFG_live_from_code.txt ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <program> -> <global_declaration> <function_definition> root ( ) { <statement> }
2
+ <global_declaration> -> bundle id <bundle_or_var> <global_declaration>
3
+ <global_declaration> -> <data_type> id <array_dec> <var_value> ; <global_declaration>
4
+ <global_declaration> -> fertile <data_type> id = <init_val> <const_next> ; <global_declaration>
5
+ <global_declaration> -> λ
6
+ <bundle_or_var> -> { <bundle_members> } ;
7
+ <bundle_or_var> -> <bundle_mem_dec> ;
8
+ <declaration> -> <var_dec> ; <declaration>
9
+ <declaration> -> <const_dec> ; <declaration>
10
+ <declaration> -> λ
11
+ <data_type> -> seed
12
+ <data_type> -> tree
13
+ <data_type> -> leaf
14
+ <data_type> -> branch
15
+ <data_type> -> vine
16
+ <const_dec> -> fertile <data_type> id = <init_val> <const_next>
17
+ <const_next> -> , id = <init_val> <const_next>
18
+ <const_next> -> λ
19
+ <var_dec> -> <data_type> id <array_dec> <var_value>
20
+ <var_dec> -> bundle id <bundle_mem_dec>
21
+ <bundle_mem_dec> -> id <array_dec> <var_value_next>
22
+ <bundle_mem_dec> -> , id <var_value_next>
23
+ <bundle_mem_dec> -> λ
24
+ <var_value> -> = <init_val> <var_value_next>
25
+ <var_value> -> <var_value_next>
26
+ <var_value_next> -> , id <array_dec> <var_value>
27
+ <var_value_next> -> λ
28
+ <init_val> -> <array_init_opt>
29
+ <init_val> -> water ( <water_arg> )
30
+ <init_val> -> <expression>
31
+ <array_dec> -> [ <array_dim_opt> ] <array_dec>
32
+ <array_dec> -> λ
33
+ <array_dim_opt> -> intlit
34
+ <array_dim_opt> -> dblit
35
+ <array_dim_opt> -> λ
36
+ <array_init_opt> -> { <init_vals> }
37
+ <array_init_opt> -> λ
38
+ <init_vals> -> <init_val_item> <init_vals_next>
39
+ <init_vals> -> λ
40
+ <init_vals_next> -> , <init_val_item> <init_vals_next>
41
+ <init_vals_next> -> λ
42
+ <init_val_item> -> { <init_vals> }
43
+ <init_val_item> -> <expression>
44
+ <bundle_declaration> -> bundle id { <bundle_members> }
45
+ <bundle_members> -> <data_type> id ; <bundle_members>
46
+ <bundle_members> -> id id ; <bundle_members>
47
+ <bundle_members> -> λ
48
+ <function_definition> -> pollinate <return_type> id ( <parameters> ) { <statement> } <function_definition>
49
+ <function_definition> -> λ
50
+ <return_type> -> <data_type>
51
+ <return_type> -> empty
52
+ <return_type> -> id
53
+ <parameters> -> λ
54
+ <parameters> -> <param> <param_next>
55
+ <param> -> <data_type> id <param_array>
56
+ <param> -> id id
57
+ <param_array> -> λ
58
+ <param_array> -> [ ]
59
+ <param_next> -> λ
60
+ <param_next> -> , <param> <param_next>
61
+ <reclaim_opt> -> reclaim <reclaim_value>
62
+ <reclaim_opt> -> λ
63
+ <reclaim_value> -> <expression> ;
64
+ <reclaim_value> -> ;
65
+ <statement> -> <simple_stmt> <statement>
66
+ <statement> -> λ
67
+ <simple_stmt> -> id <id_stmt>
68
+ <simple_stmt> -> <inc_dec_op> id ;
69
+ <simple_stmt> -> <io_stmt>
70
+ <simple_stmt> -> <conditional_stmt>
71
+ <simple_stmt> -> <loop_stmt>
72
+ <simple_stmt> -> <switch_stmt>
73
+ <simple_stmt> -> <control_stmt>
74
+ <simple_stmt> -> reclaim <reclaim_value>
75
+ <simple_stmt> -> <var_dec> ;
76
+ <simple_stmt> -> <const_dec> ;
77
+ <id_stmt> -> <id_next> <assign_op> <assign_rhs> ;
78
+ <id_stmt> -> <inc_dec_op> ;
79
+ <id_stmt> -> ( <arguments> ) ;
80
+ <assignment_stmt> -> <value> <assign_op> <assign_rhs> ;
81
+ <assign_rhs> -> water ( <water_arg> )
82
+ <assign_rhs> -> <expression>
83
+ <assign_op> -> =
84
+ <assign_op> -> +=
85
+ <assign_op> -> -=
86
+ <assign_op> -> *=
87
+ <assign_op> -> /=
88
+ <assign_op> -> %=
89
+ <value> -> id <id_next>
90
+ <id_next> -> <array_access> <post_array_access>
91
+ <id_next> -> <struct_access>
92
+ <id_next> -> λ
93
+ <array_access> -> [ <expression> ] <array_access_more>
94
+ <array_access_more> -> [ <expression> ] <array_access_more>
95
+ <array_access_more> -> λ
96
+ <struct_access> -> . id <struct_access_more>
97
+ <struct_access_more> -> . id <struct_access_more>
98
+ <struct_access_more> -> λ
99
+ <post_array_access> -> . id <post_array_access>
100
+ <post_array_access> -> λ
101
+ <io_stmt> -> plant ( <arguments> ) ;
102
+ <io_stmt> -> water ( <water_arg> ) ;
103
+ <water_arg> -> <data_type>
104
+ <water_arg> -> id <water_id_tail>
105
+ <water_arg> -> λ
106
+ <water_id_tail> -> [ <expression> ] <water_id_tail>
107
+ <water_id_tail> -> λ
108
+ <arguments> -> <expression> <arg_next>
109
+ <arguments> -> λ
110
+ <arg_next> -> , <expression> <arg_next>
111
+ <arg_next> -> λ
112
+ <conditional_stmt> -> spring ( <expression> ) { <statement> } <elseif_chain> <else_opt>
113
+ <elseif_chain> -> bud ( <expression> ) { <statement> } <elseif_chain>
114
+ <elseif_chain> -> λ
115
+ <else_opt> -> wither { <statement> }
116
+ <else_opt> -> λ
117
+ <loop_stmt> -> grow ( <expression> ) { <statement> }
118
+ <loop_stmt> -> cultivate ( <for_init> ; <expression> ; <for_update> ) { <statement> }
119
+ <loop_stmt> -> tend { <statement> } grow ( <expression> ) ;
120
+ <for_init> -> <data_type> id <array_dec> <var_value>
121
+ <for_init> -> id <id_next> <assign_op> <expression>
122
+ <for_init> -> λ
123
+ <for_update> -> id <for_update_type>
124
+ <for_update> -> λ
125
+ <for_update_type> -> <inc_dec_op>
126
+ <for_update_type> -> <id_next> <assign_op> <expression>
127
+ <unary_stmt> -> id <inc_dec_op> ;
128
+ <inc_dec_op> -> ++
129
+ <inc_dec_op> -> --
130
+ <switch_stmt> -> harvest ( <expression> ) { <case_list> <default_opt> }
131
+ <case_list> -> variety <case_literal> : <case_statements> <case_list>
132
+ <case_list> -> λ
133
+ <case_literal> -> intlit
134
+ <case_literal> -> dblit
135
+ <case_literal> -> chrlit
136
+ <case_literal> -> stringlit
137
+ <case_literal> -> sunshine
138
+ <case_literal> -> frost
139
+ <case_statements> -> <case_statement> <case_statements>
140
+ <case_statements> -> λ
141
+ <case_statement> -> id <id_stmt>
142
+ <case_statement> -> <inc_dec_op> id ;
143
+ <case_statement> -> <var_dec> ;
144
+ <case_statement> -> <io_stmt>
145
+ <case_statement> -> <conditional_stmt>
146
+ <case_statement> -> <loop_stmt>
147
+ <case_statement> -> <switch_stmt>
148
+ <case_statement> -> { <case_statements> }
149
+ <case_statement> -> prune ;
150
+ <case_statement> -> skip ;
151
+ <case_statement> -> reclaim <reclaim_value>
152
+ <default_opt> -> soil : <case_statements>
153
+ <default_opt> -> λ
154
+ <control_stmt> -> prune ;
155
+ <control_stmt> -> skip ;
156
+ <function_call> -> id ( <arguments> ) ;
157
+ <expression> -> <logic_or>
158
+ <logic_or> -> <logic_and> <logic_or_next>
159
+ <logic_or_next> -> || <logic_and> <logic_or_next>
160
+ <logic_or_next> -> λ
161
+ <logic_and> -> <relational> <logic_and_next>
162
+ <logic_and_next> -> && <relational> <logic_and_next>
163
+ <logic_and_next> -> λ
164
+ <relational> -> <arithmetic> <relational_next>
165
+ <relational_next> -> <relational_op> <arithmetic>
166
+ <relational_next> -> λ
167
+ <relational_op> -> >
168
+ <relational_op> -> <
169
+ <relational_op> -> >=
170
+ <relational_op> -> <=
171
+ <relational_op> -> ==
172
+ <relational_op> -> !=
173
+ <arithmetic> -> <term> <arithmetic_next>
174
+ <arithmetic_next> -> + <term> <arithmetic_next>
175
+ <arithmetic_next> -> - <term> <arithmetic_next>
176
+ <arithmetic_next> -> ` <term> <arithmetic_next>
177
+ <arithmetic_next> -> λ
178
+ <term> -> <factor> <term_next>
179
+ <term_next> -> * <factor> <term_next>
180
+ <term_next> -> / <factor> <term_next>
181
+ <term_next> -> % <factor> <term_next>
182
+ <term_next> -> λ
183
+ <factor> -> ( <paren_expr>
184
+ <factor> -> <unary_op> <factor>
185
+ <factor> -> id <factor_id_next>
186
+ <factor> -> intlit
187
+ <factor> -> dblit
188
+ <factor> -> chrlit
189
+ <factor> -> stringlit
190
+ <factor> -> sunshine
191
+ <factor> -> frost
192
+ <paren_expr> -> <data_type> ) <factor>
193
+ <paren_expr> -> <expression> )
194
+ <unary_op> -> ~
195
+ <unary_op> -> !
196
+ <factor_id_next> -> <array_access> <post_array_access>
197
+ <factor_id_next> -> <struct_access>
198
+ <factor_id_next> -> ( <arguments> )
199
+ <factor_id_next> -> λ
DEFENSE_01_server.md → Docus & mps/DEFENSE_01_server.md RENAMED
File without changes
DEFENSE_01_server.pdf → Docus & mps/DEFENSE_01_server.pdf RENAMED
File without changes
DEFENSE_02_tokens_errors.md → Docus & mps/DEFENSE_02_tokens_errors.md RENAMED
File without changes
DEFENSE_02_tokens_errors.pdf → Docus & mps/DEFENSE_02_tokens_errors.pdf RENAMED
File without changes
Docus & mps/DEFENSE_03_lexer.md ADDED
@@ -0,0 +1,791 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # GAL Compiler — Defense-Prep Walkthrough
2
+
3
+ ## File 3 of 9: `lexer.py` — the `Lexer` class itself
4
+
5
+ This is the **scanner** (lexical analyzer) of GAL. It is where raw character text becomes a stream of tokens. The file is large (~1900 lines) because GAL has 26 reserved words, 5 data types, ~20 operators, 5 literal kinds, two comment styles, and strict per-keyword delimiter rules. The entire file is built around **one big function**: `Lexer.make_tokens()`.
6
+
7
+ ---
8
+
9
+ ## 1. FILE PURPOSE
10
+
11
+ `lexer.py` performs **lexical analysis** — phase 1 of compilation. Its responsibilities:
12
+
13
+ 1. Read the GAL source code character by character.
14
+ 2. Group characters into **lexemes** and tag each with a **token type** (a `Token` object).
15
+ 3. **Track line and column** so every token knows where it came from in the source.
16
+ 4. **Detect lexical errors** (illegal characters, malformed numbers, unclosed strings/comments, bad delimiters) and produce `LexicalError` objects — without crashing.
17
+ 5. **Skip whitespace and comments** entirely (they never become tokens).
18
+ 6. **Recognize keywords vs identifiers** with a transition-diagram-style hand-written FSM, one branch per starting letter.
19
+ 7. Emit a final `EOF` token so the parser knows when input ends.
20
+
21
+ Where it sits in the pipeline:
22
+
23
+ ```
24
+ Source code (Python string)
25
+
26
+
27
+ ┌──────────────────┐
28
+ │ Lexer (this file)│
29
+ └──────────────────┘
30
+
31
+ ─ tokens, errors ─→ server.py / parser
32
+ ```
33
+
34
+ What depends on it:
35
+
36
+ | File | What it imports | When used |
37
+ |---|---|---|
38
+ | `server.py` | `lex`, `get_token_description` | Every API endpoint runs `lex(source_code)` first |
39
+ | `Gal_Parser.py` | (consumes tokens, doesn't import the lexer module) | Receives tokens to drive the LL(1) parser |
40
+ | `GALsemantic.py` | `Lexer` (for some tests) | Uses `analyze_semantics(tokens)` legacy path |
41
+ | `icg.py` | (consumes tokens) | Reads the same token stream to emit display TAC |
42
+
43
+ The lexer **does not** depend on anything other than the token/Position/error classes that live at the top of the same file. That makes it easy to test in isolation.
44
+
45
+ ---
46
+
47
+ ## 2. IMPORTS / DEPENDENCIES
48
+
49
+ **The lexer file has zero `import` statements.** Everything it needs — the character classes, the token-type constants, the `Position`, `LexicalError`, and `Token` classes — is defined in the same file (the part covered in defense file #2 of this series).
50
+
51
+ This is intentional. The lexer must be a pure data-processing function with no side effects beyond producing tokens. By avoiding imports, we guarantee:
52
+
53
+ - It can be unit-tested without setting up Flask, Socket.IO, or eventlet.
54
+ - It has no hidden global state from other modules.
55
+ - Removing or renaming any import in `server.py` cannot break tokenization.
56
+
57
+ **Defense answer:** *"The lexer is self-contained. The only data structures it uses are defined in the same file. This isolates the most-tested, most-critical phase of the compiler from runtime concerns."*
58
+
59
+ ---
60
+
61
+ ## 3. GLOBAL CONSTANTS / VARIABLES
62
+
63
+ The lexer relies on the constants defined at the top of `lexer.py` (these were covered in defense file #2). Briefly:
64
+
65
+ - **Character classes** — `ZERO`, `DIGIT`, `ZERODIGIT`, `LOW_ALPHA`, `UPPER_ALPHA`, `ALPHA`, `ALPHANUM` — used to test `if self.current_char in ALPHA:` etc.
66
+ - **Delimiter sets** — `space_delim`, `delim2` … `delim24`, `idf_delim`, `whlnum_delim`, `decim_delim` — each one is the set of characters that may legally follow a particular kind of token. The actively-used ones (`space_delim`, `delim4`, `delim6`, `delim7`, `delim8`, `delim23`, `idf_delim`, `whlnum_delim`, `decim_delim`) drive lookahead checks in the scanner. The numbered ones are kept as 1-to-1 documentation mapping back to the GAL proposal's regular-definition table.
67
+ - **Token-type constants** (`TT_*`) — what each emitted `Token` is tagged with.
68
+
69
+ The `Lexer` instance itself owns three pieces of state:
70
+
71
+ ```python
72
+ self.source_code # the raw input string
73
+ self.pos # a Position(index, line, col) — current scan location
74
+ self.current_char # the character at self.pos.index, or None at EOF
75
+ ```
76
+
77
+ That's it. No caches, no counters outside the loop. Everything else lives in local variables of `make_tokens()`.
78
+
79
+ ---
80
+
81
+ ## 4. CLASSES AND FUNCTIONS
82
+
83
+ This file exposes one class (`Lexer`) and two module-level functions (`run` and `lex`). The `Lexer` class has three methods.
84
+
85
+ ### 4.1 `Lexer.__init__(source_code)` (lines 307-311)
86
+
87
+ ```python
88
+ def __init__(self, source_code):
89
+ self.source_code = source_code.replace('\r', '')
90
+ self.pos = Position(-1, 1, -1)
91
+ self.current_char = None
92
+ self.advance()
93
+ ```
94
+
95
+ **Receives:** the full GAL source code as a Python string.
96
+
97
+ **Returns / modifies:** populates the three instance fields and primes `current_char` to the first character of the source.
98
+
99
+ **Why it exists:** sets up scanner state. The `\r` strip handles Windows line endings (`\r\n`) so the rest of the lexer only ever has to consider `\n`.
100
+
101
+ **Why `Position(-1, 1, -1)`:** the position starts *before* the first character. The very first call to `self.advance()` will move it to index 0, line 1, column 0 — the actual start of the source.
102
+
103
+ **Compiler stage:** Lexical (setup).
104
+
105
+ ### 4.2 `Lexer.advance()` (lines 313-317)
106
+
107
+ ```python
108
+ def advance(self):
109
+ self.pos.advance(self.current_char)
110
+ self.current_char = (
111
+ self.source_code[self.pos.index]
112
+ if self.pos.index < len(self.source_code) else None
113
+ )
114
+ ```
115
+
116
+ **Receives:** nothing.
117
+
118
+ **Returns / modifies:** `self.pos` is incremented (line/column updated based on the *previous* `current_char`); `self.current_char` is set to the next source character or `None` if past the end.
119
+
120
+ **Why it exists:** every scanner branch in `make_tokens` calls `self.advance()` to move forward by one character. Centralizing it ensures consistent line/column tracking.
121
+
122
+ **Edge case:** when EOF is reached, `self.current_char` becomes `None`. Every scanner branch checks `is not None` before reading.
123
+
124
+ ### 4.3 `Lexer.make_tokens()` (lines 319-1832 — the heart of the lexer)
125
+
126
+ ```python
127
+ def make_tokens(self):
128
+ tokens = []
129
+ line = 1
130
+ errors = []
131
+ pos = self.pos.copy()
132
+ while self.current_char != None:
133
+ # ... one big if-elif-else over current_char ...
134
+ if self.current_char is None:
135
+ tokens.append(Token(TT_EOF, "", line, pos.col))
136
+ return tokens, errors
137
+ ```
138
+
139
+ **Receives:** nothing (operates on `self.source_code`).
140
+
141
+ **Returns:** the tuple `(tokens, errors)` — a list of `Token` objects and a list of `LexicalError` objects.
142
+
143
+ **Why it exists:** this is the scanner. Every character of the source goes through this loop exactly once. Each iteration recognizes one lexeme and emits at most one token (whitespace and comments emit nothing).
144
+
145
+ **Edge cases:**
146
+ - Empty source: the `while` loop never runs, EOF is appended, `(([EOF], [])` is returned.
147
+ - Source with only comments: tokens list contains only EOF.
148
+ - Source with only errors: tokens list may still contain valid tokens before/after each error.
149
+
150
+ **Defense framing:** *"Make_tokens is one big dispatch. The first character of each lexeme decides which branch to take. Inside each branch we keep reading characters as long as they belong to the current token, then emit it. Errors are collected — never raised — so we can report multiple problems in one pass."*
151
+
152
+ ### 4.4 `run(source_code)` and `lex(source_code)` module-level helpers (lines 1838-1880)
153
+
154
+ ```python
155
+ def run(source_code):
156
+ """Legacy function - runs lexer and returns tokens and errors."""
157
+ lexer = Lexer(source_code)
158
+ return lexer.make_tokens()
159
+
160
+ def lex(source_code):
161
+ """Main entry point for lexical analysis (used by server.py)."""
162
+ lexer = Lexer(source_code)
163
+ tokens, errors = lexer.make_tokens()
164
+ str_errors = [e.as_string() if hasattr(e, 'as_string') else str(e)
165
+ for e in errors]
166
+ return tokens, str_errors
167
+ ```
168
+
169
+ **Why two:**
170
+
171
+ - `run()` is the **legacy** entry point (kept for older grading/test scripts that imported it). Returns raw `LexicalError` objects.
172
+ - `lex()` is the **production** entry point used by `server.py`. It additionally converts each error into its formatted string via `as_string()`, because the HTTP/JSON layer needs strings, not Python objects.
173
+
174
+ **Stage:** Lexical (public interface).
175
+
176
+ **Defense answer for "why two?":** *"`run` is kept for backwards compatibility with grading scripts. `lex` is what the server uses — it adds error-to-string conversion so the JSON response is ready to serialize."*
177
+
178
+ ---
179
+
180
+ ## 5. LINE-BY-LINE / BLOCK-BY-BLOCK EXPLANATION
181
+
182
+ The body of `make_tokens` is a huge `if … elif … elif … else` chain. I'll walk the most important branches in the order they appear. Every branch follows the same pattern: detect the start character → consume the lexeme → emit a token (or an error) → `continue` the loop.
183
+
184
+ ### 5.1 The keyword/identifier scanner — letter-by-letter FSM (lines 338-940)
185
+
186
+ ```python
187
+ if self.current_char in ALPHA:
188
+ ident_str = ''
189
+ pos = self.pos.copy()
190
+
191
+ if self.current_char == "b":
192
+ ident_str += self.current_char
193
+ self.advance()
194
+ if self.current_char == "r": # branch
195
+ ident_str += self.current_char
196
+ self.advance()
197
+ if self.current_char == "a":
198
+ ...
199
+ # eventually:
200
+ if self.current_char is None or self.current_char in space_delim:
201
+ tokens.append(Token(TT_RW_BRANCH, ident_str, line, pos.col))
202
+ continue
203
+ elif self.current_char == "u":
204
+ ... # bud / bundle
205
+ elif self.current_char == "c":
206
+ ... # cultivate
207
+ elif self.current_char == "e":
208
+ ... # empty
209
+ elif self.current_char == "f":
210
+ ... # frost / fertile
211
+ elif self.current_char == "g":
212
+ ... # grow
213
+ # ... and so on for h, l, p, r, s, t, v, w
214
+ ```
215
+
216
+ **What this block does:** Hand-written transition diagram. For each letter the source could start with that begins a GAL keyword, there is an explicit nested `if` chain that walks character-by-character down the keyword's spelling. If the chain completes AND the next character is a valid delimiter (space, `;`, `{`, etc.), a keyword `Token` is emitted.
217
+
218
+ **Why hand-written and not regex/dictionary?**
219
+
220
+ - **Visibility for the panel**: this is the implementation of the **transition diagrams** in the GAL compiler proposal. Each `if` chain corresponds to one DFA path in the spec. A panelist can point at any `if "h"` branch and it maps directly to the proposal's "harvest" transition diagram.
221
+ - **Per-keyword delimiter rules**: GAL is strict about what may come after each keyword. `bud` requires `:` or `(` to follow (delim4); `fertile` requires `;` (delim8); `plant` allows `;`, `(`, `,`, etc. (delim6). With a regex-based approach, this would all be a separate validation step. With the hand-written FSM, the delimiter check is in-line right where the keyword is recognized.
222
+ - **Identifier fallback**: if the chain breaks (e.g., `b` is followed by `e`, not `r` or `u`), control falls through to a generic "scan an identifier" loop that runs at the end of the block (lines 802-940 in the file). The result is `Token('id', ident_str, ...)`.
223
+
224
+ **Why the spec-derived scanner uses delimiter sets:**
225
+
226
+ ```python
227
+ if self.current_char is None or (self.current_char is not None and self.current_char.isspace()) or self.current_char in delim4:
228
+ tokens.append(Token(TT_RW_CULTIVATE, ident_str, line, pos.col))
229
+ continue
230
+ elif self.current_char is not None and not self.current_char.isspace() and self.current_char not in delim4 and self.current_char not in ALPHANUM:
231
+ errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'"))
232
+ self.advance()
233
+ continue
234
+ ```
235
+
236
+ This pattern repeats for every keyword. The two cases are:
237
+
238
+ 1. **Valid delimiter** (`delim4` for `cultivate`) — emit the keyword token, continue.
239
+ 2. **Invalid non-alphanumeric delimiter** (e.g., `cultivate$`) — report a delimiter error.
240
+
241
+ The third implicit case — character is alphanumeric — means the keyword spelling matched a *prefix* but the user actually typed a longer identifier (e.g., `cultivate1`). Control falls out of the keyword branch and into the generic identifier loop, which builds `Token('id', 'cultivate1')`.
242
+
243
+ **Defense answer:** *"The keyword scanner is a hand-written transition diagram, one branch per starting letter. This mirrors the FSMs documented in our compiler proposal. After spelling out each keyword, we check that the next character is a valid delimiter for that specific keyword — for example, `cultivate` may only be followed by `:`, `(`, or whitespace because it's a control-flow header. If the next character is alphanumeric instead, we treat the prefix as part of an identifier."*
244
+
245
+ ### 5.2 The negative-literal scanner — `~` (lines 991-1049)
246
+
247
+ This is the most distinctive part of GAL — `~` is the negative sign.
248
+
249
+ ```python
250
+ elif self.current_char == "~": # Added for negative prefix
251
+ ident_str = self.current_char
252
+ pos = self.pos.copy()
253
+ self.advance()
254
+
255
+ # If ~ is directly followed by a digit, consume the number as a negative literal
256
+ if self.current_char is not None and self.current_char in ZERODIGIT:
257
+ # Read integer digits
258
+ num_str = ""
259
+ integer_digit_count = 0
260
+ while self.current_char is not None and self.current_char in ZERODIGIT:
261
+ integer_digit_count += 1
262
+ num_str += self.current_char
263
+ self.advance()
264
+
265
+ # Check for decimal point (negative double)
266
+ if self.current_char == ".":
267
+ ...
268
+ tokens.append(Token(TT_DOUBLELIT, ident_str, line, pos.col))
269
+ continue
270
+ else:
271
+ # Negative integer
272
+ if integer_digit_count > 8:
273
+ errors.append(LexicalError(pos, f"Integer exceeds maximum of 8 digits"))
274
+ continue
275
+ num_str = num_str.lstrip("0") or "0"
276
+ ident_str = "~" + num_str
277
+ tokens.append(Token(TT_INTEGERLIT, ident_str, line, pos.col))
278
+ continue
279
+
280
+ # ~ not followed by a digit: emit as negate operator
281
+ elif self.current_char is None or self.current_char in ALPHANUM + ' \t\n':
282
+ tokens.append(Token(TT_NEGATIVE, ident_str, line, pos.col))
283
+ continue
284
+ else:
285
+ errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'."))
286
+ self.advance()
287
+ continue
288
+ ```
289
+
290
+ **What this block does:** The lexer treats `~` two different ways depending on what comes next:
291
+
292
+ 1. **`~` followed by a digit** (e.g., `~5`, `~3.14`) — fold the sign into a literal token. The result is a single `Token('intlit', '~5', …)` or `Token('dbllit', '~3.14', …)`. The `~` stays in the value string so the interpreter can recognize it later and emit a real negative number.
293
+ 2. **`~` followed by an identifier or a paren** (e.g., `~x`, `~(a + b)`) — emit a separate `Token('~', '~', …)` (the `TT_NEGATIVE` operator). The parser's grammar treats this as a unary minus prefix on an expression.
294
+
295
+ **Why both behaviors:** for literals, folding the sign at lex time means the parser never needs a "unary minus" production in front of every integer or double — the literal already carries the sign. For variables, we *can't* fold because the value isn't known yet, so we keep the operator as a separate token.
296
+
297
+ **Defense answer:** *"GAL uses `~` for negation. The lexer pre-folds `~5` into a single negative integer literal at scan time, but emits `~` as a separate operator token when it precedes an identifier. This avoids a unary-minus production in the grammar for the literal case."*
298
+
299
+ ### 5.3 Maximal-munch operator scanners (lines 1051-1283)
300
+
301
+ ```python
302
+ elif self.current_char == "!":
303
+ ident_str = self.current_char
304
+ pos = self.pos.copy()
305
+ self.advance()
306
+ if self.current_char == "=":
307
+ ident_str += self.current_char
308
+ self.advance()
309
+ tokens.append(Token(TT_NOTEQ, ident_str, line, pos.col))
310
+ continue
311
+ else:
312
+ tokens.append(Token(TT_NOT, ident_str, line, pos.col))
313
+ continue
314
+ ```
315
+
316
+ **Pattern:** when the current character could start either a 1-char or a 2-char operator (e.g., `!` could be NOT or `!=`), we read the first char, **peek** at the next, and decide:
317
+
318
+ - If the next char extends the operator → emit the longer token.
319
+ - Otherwise → emit the shorter token.
320
+
321
+ This is **maximal munch** — the classic lexer rule "always grab the longest valid token."
322
+
323
+ **Operators handled this way:**
324
+
325
+ | Single | Double | Triple-extended |
326
+ |---|---|---|
327
+ | `!` | `!=` | — |
328
+ | `=` | `==` | `===` is detected by the parser as `==` followed by `=` (we deliberately don't make a `TT_TRIPLEEQ` token; the parser issues a friendlier error) |
329
+ | `<` | `<=` | — |
330
+ | `>` | `>=` | — |
331
+ | `+` | `++`, `+=` | — |
332
+ | `-` | `--`, `-=` | — |
333
+ | `*` | `**`, `*=` | — |
334
+ | `/` | `/=`, also `//` (single-line comment), `/*` (multi-line comment) | — |
335
+ | `%` | `%=` | — |
336
+ | `&` | `&&` | — (single `&` is captured as `TT_SINGLE_AND` so the parser can flag it as invalid) |
337
+ | `\|` | `\|\|` | — (single `\|` is captured as `TT_SINGLE_OR`) |
338
+
339
+ **Why we emit `TT_SINGLE_AND` and `TT_SINGLE_OR`:** if the user writes `a & b`, the lexer doesn't crash — it produces a token with type `&`. The parser's grammar has no rule that accepts `&` alone, so it produces the error *"Invalid operator '&'. Did you mean '&&'?"*. By passing it through as a token, error reporting happens at the layer that knows the most context.
340
+
341
+ **Defense answer for maximal munch:** *"For multi-character operators we use the maximal-munch rule. We read one character, peek the next, and if together they form a longer operator we emit the longer token. This is what a textbook lexer does and resolves all ambiguity between e.g. `=` (assignment) and `==` (equality)."*
342
+
343
+ **Defense answer for `&` and `|`:** *"We tokenize single ampersand and single pipe as `TT_SINGLE_AND` and `TT_SINGLE_OR` — token types that the parser explicitly does not accept. This means the user gets a syntax error at the parser layer with the full grammar context, instead of a misleading lexical error."*
344
+
345
+ ### 5.4 Newline, tab, space — whitespace handling (lines 1286-1313)
346
+
347
+ ```python
348
+ elif self.current_char == '\n':
349
+ pos = self.pos.copy()
350
+ if tokens and tokens[-1].type != TT_NL:
351
+ tokens.append(Token(TT_NL, "\\n", line, pos.col))
352
+ while self.current_char == '\t' or self.current_char == ' ' or self.current_char == '\n':
353
+ if self.current_char == '\t' or self.current_char == ' ':
354
+ self.advance()
355
+ else:
356
+ line += 1
357
+ self.advance()
358
+ continue
359
+
360
+ elif self.current_char == '\t':
361
+ ident_str = self.current_char
362
+ pos = self.pos.copy()
363
+ while self.current_char == '\t':
364
+ self.advance()
365
+ continue
366
+
367
+ elif self.current_char == ' ':
368
+ ident_str = self.current_char
369
+ pos = self.pos.copy()
370
+ self.advance()
371
+ while self.current_char == ' ':
372
+ self.advance()
373
+ continue
374
+ ```
375
+
376
+ **What this block does:**
377
+
378
+ - A single `\n` token is emitted to mark the end of a logical line, but **only if** the last token wasn't already a `\n` — this collapses multiple consecutive blank lines into one newline token.
379
+ - The inner `while` loop advances past *all* contiguous whitespace (spaces, tabs, newlines), so the next iteration of the outer loop starts at a real character.
380
+ - For tabs and spaces alone, the consumed whitespace is discarded entirely (no token emitted).
381
+
382
+ **Why emit `TT_NL` tokens at all when the parser is configured to skip them?** Because the lexer's *line counter* depends on counting newlines. The token is also useful for error recovery and for the IDE's lexeme view. The parser is configured with `skip_token_types={'\n'}` so it transparently ignores them during parsing.
383
+
384
+ **Why the `if tokens and tokens[-1].type != TT_NL` guard:** Prevents a sequence like `\n\n\n\n` from emitting four `TT_NL` tokens — only one is needed.
385
+
386
+ **Defense answer:** *"Whitespace is consumed but not emitted as tokens, except newlines. Newlines are emitted exactly once per logical line break so the parser's line tracking and the IDE's lexeme view stay accurate. The parser is configured to skip newline tokens during shift operations."*
387
+
388
+ ### 5.5 Forward slash — division, comments, and divide-assign (lines 1318-1370)
389
+
390
+ ```python
391
+ elif self.current_char == "/":
392
+ ident_str = self.current_char
393
+ pos = self.pos.copy()
394
+ self.advance()
395
+
396
+ if self.current_char == "/": # Single-line comment: // comment text
397
+ ident_str += self.current_char
398
+ self.advance()
399
+ while self.current_char is not None and self.current_char != "\n":
400
+ ident_str += self.current_char
401
+ self.advance()
402
+ continue
403
+
404
+ elif self.current_char == "*": # Multi-line comment: /* ... */
405
+ ident_str += self.current_char
406
+ self.advance()
407
+ found_close = False
408
+ while self.current_char is not None:
409
+ if self.current_char == "*" and self.pos.index + 1 < len(self.source_code) and self.source_code[self.pos.index + 1] == "/":
410
+ ident_str += "*/"
411
+ self.advance()
412
+ self.advance()
413
+ found_close = True
414
+ break
415
+ else:
416
+ ident_str += self.current_char
417
+ if self.current_char == "\n":
418
+ line += 1
419
+ self.advance()
420
+ if not found_close:
421
+ errors.append(LexicalError(pos, f"Missing closing '*/' after '{ident_str}'"))
422
+ continue
423
+ continue
424
+
425
+ elif self.current_char == "=":
426
+ ident_str += self.current_char
427
+ self.advance()
428
+ tokens.append(Token(TT_DIVEQ, ident_str, line, pos.col))
429
+ continue
430
+
431
+ else:
432
+ ...
433
+ tokens.append(Token(TT_DIV, ident_str, line, pos.col))
434
+ continue
435
+ ```
436
+
437
+ **What this block does:** the `/` character is a four-way fork:
438
+
439
+ 1. `//` — single-line comment. Consume everything up to (but not including) the next newline. **Comments are NOT emitted as tokens** — they vanish from the token stream entirely.
440
+ 2. `/*` — multi-line comment. Consume characters until `*/` is found, tracking line numbers internally. If EOF is reached before `*/`, report *"Missing closing '*/'"*.
441
+ 3. `/=` — divide-assign operator.
442
+ 4. Plain `/` — division operator.
443
+
444
+ **Why comments don't become tokens:** they have zero meaning to the parser or any later stage. Suppressing them at the lexer level keeps every later layer simpler.
445
+
446
+ **Multi-line comment edge case — line counting:** because a `/* ... */` block can span many lines, we explicitly increment `line` whenever we consume a newline inside the comment. Otherwise error messages after a multi-line comment would point at the wrong line.
447
+
448
+ **Defense answer:** *"The forward slash has four meanings — comment, multi-line comment, divide-assign, division. We resolve them by peeking at the next character. Comments are consumed but never emitted; they don't reach the parser. Unclosed multi-line comments produce a lexical error with the position of the opening `/*`."*
449
+
450
+ ### 5.6 Number scanner — integers and doubles (lines 1418-1625)
451
+
452
+ ```python
453
+ elif self.current_char in ZERODIGIT:
454
+ dot_count = 0
455
+ ident_str = ""
456
+ pos = self.pos.copy()
457
+ integer_digit_count = 0
458
+ fractional_digit_count = 0
459
+
460
+ # Read all digits before decimal point
461
+ while self.current_char is not None and self.current_char in ZERODIGIT:
462
+ integer_digit_count += 1
463
+ ident_str += self.current_char
464
+ self.advance()
465
+
466
+ # Check for decimal point (converts to double/float)
467
+ if self.current_char == ".":
468
+ # ... read fractional part ...
469
+ # ... validate digit limits ...
470
+ tokens.append(Token(TT_DOUBLELIT, ident_str, line, pos.col))
471
+ continue
472
+
473
+ # No decimal point — emit as integer
474
+ if integer_digit_count > 8:
475
+ # Process integer part in chunks of 8: each chunk beyond the valid last ≤8 digits is an error
476
+ ...
477
+ tokens.append(Token(TT_INTEGERLIT, remaining, line, pos.col))
478
+ continue
479
+ ```
480
+
481
+ **What this block does:** When the current char is a digit (0-9):
482
+
483
+ 1. Read all consecutive digits — the integer part.
484
+ 2. If the next character is `.`, this is a double — read the fractional part too.
485
+ 3. Validate against GAL's digit limits:
486
+ - **Integer (`seed`)**: max 8 digits.
487
+ - **Double (`tree`)**: max 15 digits before decimal, max 8 digits after.
488
+ 4. Format the value (strip leading zeros from integer part, drop trailing zeros from fractional part, ensure at least one fractional digit).
489
+ 5. Emit `TT_INTEGERLIT` or `TT_DOUBLELIT`.
490
+
491
+ **Edge case — leading zero stripping:**
492
+
493
+ ```python
494
+ remaining = remaining.lstrip("0") or "0"
495
+ ```
496
+
497
+ The `or "0"` is a Python idiom: if `lstrip("0")` returns the empty string (i.e., the input was all zeros like `"0000"`), keep one zero so the number isn't lost.
498
+
499
+ **Edge case — trailing zero handling on doubles:**
500
+
501
+ ```python
502
+ fractional_part = (parts[1] if len(parts) > 1 else "").rstrip("0") or "0"
503
+ if fractional_part == "0":
504
+ num_str = f"{integer_part}.0"
505
+ else:
506
+ num_str = f"{integer_part}.{fractional_part}"
507
+ ```
508
+
509
+ `3.140` becomes `3.14`; `3.000` becomes `3.0` (we always keep at least one zero after the decimal so it's still recognizable as a double). This keeps display consistent.
510
+
511
+ **Defense answer:** *"The number scanner reads all consecutive digits, then checks for a decimal point. We enforce the digit limits documented in the GAL specification — 8 digits for integers, 15 left and 8 right for doubles. We also normalize the displayed value: strip leading zeros, drop trailing zeros after the decimal but keep at least one."*
512
+
513
+ ### 5.7 String literal scanner — `"..."` (lines 1631-1692)
514
+
515
+ ```python
516
+ elif self.current_char == '"':
517
+ string = ''
518
+ pos = self.pos.copy()
519
+ escape_character = False
520
+ string += self.current_char # opening quote
521
+ self.advance()
522
+
523
+ escape_characters = {
524
+ 'n': '\n', 't': '\t',
525
+ '{': '\\{', '}': '\\}',
526
+ '"': '"', '\\': '\\',
527
+ }
528
+
529
+ has_string_error = False
530
+ while self.current_char is not None and (self.current_char != '"' or escape_character):
531
+ if escape_character:
532
+ if self.current_char in escape_characters:
533
+ string += escape_characters[self.current_char]
534
+ else:
535
+ errors.append(LexicalError(pos, f"Invalid escape sequence '\\{self.current_char}'..."))
536
+ has_string_error = True
537
+ escape_character = False
538
+ else:
539
+ if self.current_char == '\\':
540
+ escape_character = True
541
+ elif self.current_char == '\n':
542
+ break # newline ends the string (unclosed)
543
+ else:
544
+ string += self.current_char
545
+ self.advance()
546
+
547
+ if self.current_char == '"':
548
+ string += self.current_char
549
+ self.advance()
550
+ else:
551
+ errors.append(LexicalError(pos, f"Missing closing '\"' for string literal"))
552
+ continue
553
+
554
+ tokens.append(Token(TT_STRINGLIT, string, line, pos.col))
555
+ continue
556
+ ```
557
+
558
+ **What this block does:**
559
+
560
+ 1. Consume the opening `"`.
561
+ 2. Read characters until the closing `"`. The `escape_character` flag tracks whether the next character is an escape continuation.
562
+ 3. Recognized escapes: `\n`, `\t`, `\{`, `\}`, `\"`, `\\`. Anything else triggers an *"Invalid escape sequence"* error.
563
+ 4. A literal newline (not preceded by `\`) inside a string ends the string scan; if the next char is not `"`, the string is unclosed.
564
+ 5. Emit `TT_STRINGLIT` whose `value` is the **fully-parsed text** including the quotes (the parser/interpreter peel the quotes off later).
565
+
566
+ **Why escape sequences are processed at the lexer:** the value stored in the token is the **real** string (with `\n` already converted to a newline char). This matches how C compilers do it — the lexer is the single point that handles escapes, so every later stage sees the actual text the user intended.
567
+
568
+ **Defense answer:** *"String literals are scanned with a small state machine that tracks whether the next character is part of an escape sequence. Recognized escapes are `\\n`, `\\t`, `\\{`, `\\}`, `\\\"`, `\\\\`. Unclosed strings produce a lexical error with the position of the opening quote so the IDE can highlight the right place."*
569
+
570
+ ### 5.8 Character literal scanner — `'a'` (lines 1698-1777)
571
+
572
+ ```python
573
+ elif self.current_char == "'":
574
+ string = ''
575
+ char = ''
576
+ pos = self.pos.copy()
577
+ string += self.current_char
578
+ self.advance()
579
+ has_error = False
580
+
581
+ while self.current_char is not None and self.current_char != "'":
582
+ if self.current_char == '\n':
583
+ break
584
+ elif self.current_char == '\\':
585
+ string += self.current_char
586
+ self.advance()
587
+ if self.current_char in "'\\nt":
588
+ char += f"\\{self.current_char}"
589
+ string += self.current_char
590
+ else:
591
+ errors.append(LexicalError(pos, f"Invalid escape sequence..."))
592
+ has_error = True
593
+ break
594
+ else:
595
+ string += self.current_char
596
+ char += self.current_char
597
+ self.advance()
598
+
599
+ if self.current_char == "'":
600
+ string += self.current_char
601
+ self.advance()
602
+ else:
603
+ errors.append(LexicalError(pos, f"Missing closing quote..."))
604
+ continue
605
+
606
+ inner = char.strip()
607
+ if len(inner) == 0:
608
+ # Empty char literal '' defaults to a space character
609
+ ...
610
+ elif len(inner) > 1:
611
+ errors.append(LexicalError(pos, f"Character literal must contain exactly one character..."))
612
+ continue
613
+
614
+ tokens.append(Token(TT_CHARLIT, string, line, pos.col))
615
+ continue
616
+ ```
617
+
618
+ **What this block does:** Like strings, but enforces **exactly one character** between the quotes. Multi-char content like `'AB'` is rejected with *"Character literal must contain exactly one character"*.
619
+
620
+ **Special cases:**
621
+ - Empty `''` is treated as a space character (defensive default).
622
+ - Escape sequences `\n`, `\t`, `\\`, `\'` are accepted and treated as one character.
623
+ - Newline inside the literal ends scanning; reported as unclosed.
624
+
625
+ **Defense answer:** *"A character literal is exactly one character (or one escape sequence) inside single quotes. We share the escape logic with strings but require length 1. Empty `''` defaults to space because some legacy programs rely on this."*
626
+
627
+ ### 5.9 Backtick — concatenation operator (lines 1779-1789)
628
+
629
+ ```python
630
+ elif self.current_char == '`':
631
+ pos = self.pos.copy()
632
+ ident_str = self.current_char
633
+ self.advance()
634
+ if self.current_char is not None and self.current_char not in set(ALPHANUM + '(~!"\' ' + '\t' + '\n'):
635
+ errors.append(LexicalError(pos, f"Invalid delimiter '{self.current_char}' after '{ident_str}'"))
636
+ self.advance()
637
+ continue
638
+ tokens.append(Token(TT_CONCAT, ident_str, line, pos.col))
639
+ continue
640
+ ```
641
+
642
+ **What this block does:** GAL uses backtick `` ` `` as the **string-concatenation** operator (where most languages would use `+` or `..`). It's a single-character token. The delimiter check ensures the next character is something that could legally start an operand (an identifier, a literal, a paren, etc.).
643
+
644
+ **Defense answer:** *"GAL uses backtick as the concatenation operator. We chose it because the `+` symbol is reserved for arithmetic and using a distinct character makes string-vs-number context obvious to the reader."*
645
+
646
+ ### 5.10 The catch-all `else` — illegal characters (lines 1791-1826)
647
+
648
+ ```python
649
+ else:
650
+ pos = self.pos.copy()
651
+ char = self.current_char
652
+
653
+ if char == '_':
654
+ # Underscore at start of identifier — special error
655
+ ...
656
+ if temp_str in reserved_words:
657
+ errors.append(LexicalError(pos, f"Reserved word cannot start with a symbol: '_{temp_str}'"))
658
+ else:
659
+ errors.append(LexicalError(pos, f"Identifiers cannot start with a symbol: '_...'"))
660
+ ...
661
+ continue
662
+ else:
663
+ self.advance()
664
+ errors.append(LexicalError(pos, f"Illegal Character '{char}'"))
665
+ continue
666
+ ```
667
+
668
+ **What this block does:** if no branch above matched, the character is illegal. We emit a lexical error and skip past the bad character so scanning can continue.
669
+
670
+ **Special case for `_`:** GAL identifiers must start with a letter, not an underscore. If the user wrote `_water`, we want to give a more helpful error than "illegal character" — we peek ahead, check if the rest of the word is a reserved word, and emit a clearer message: *"Reserved word cannot start with a symbol: '_water'"*.
671
+
672
+ **Defense answer:** *"The default branch reports any character we don't recognize as an illegal-character lexical error. We have a special path for leading underscore because that's a common typo where the user expected an identifier; we tell them specifically that identifiers must start with a letter."*
673
+
674
+ ### 5.11 EOF handling and return (lines 1828-1832)
675
+
676
+ ```python
677
+ if self.current_char is None:
678
+ tokens.append(Token(TT_EOF, "", line, pos.col))
679
+
680
+ return tokens, errors
681
+ ```
682
+
683
+ **What this block does:** after the main `while` loop ends (EOF reached), append a synthetic `TT_EOF` token. This is critical — the parser's LL(1) table uses `EOF` as the end-marker terminal. Without this token, the parser would not know when to stop.
684
+
685
+ **Defense answer:** *"The lexer always appends an EOF token at the end of input. The parser is configured with `end_marker='EOF'` and uses this synthetic token to know when valid input has ended."*
686
+
687
+ ---
688
+
689
+ ## 6. DEFENSE QUESTION PREPARATION
690
+
691
+ **Q: Why is the keyword scanner hand-written instead of using regex or a dictionary?**
692
+
693
+ > "Three reasons. First, it directly mirrors the transition diagrams in our compiler proposal — each `if` chain is one DFA path, so a panel can trace the implementation back to the spec. Second, GAL has per-keyword delimiter rules (e.g., `cultivate` requires `:` or `(` to follow) — a regex approach would need a separate validator. Third, the hand-written FSM cleanly falls through to the generic identifier loop when a keyword prefix doesn't complete — `seedling` is recognized as one identifier, not as `seed` + `ling`."
694
+
695
+ **Q: How does the lexer distinguish `seed` (keyword) from `seedy` (identifier)?**
696
+
697
+ > "After spelling out the keyword `seed`, the next character must be a valid delimiter — whitespace, `;`, `(`, etc. If the next character is alphanumeric (`y` in `seedy`), the FSM exits and control falls through to the generic identifier loop, which builds an `id` token whose value is `seedy`. So `seedy` is one identifier token, not two."
698
+
699
+ **Q: Why does `~` produce two different kinds of tokens?**
700
+
701
+ > "When `~` is followed by a digit, we fold the sign into the literal at lex time — the result is a single `intlit` or `dbllit` token whose value carries the `~`. When `~` is followed by an identifier or paren, we emit a separate `~` operator token. This means the parser doesn't need a unary-minus production for literals — they already arrive negated. For variables, the parser uses the `~` token as a unary prefix in expressions."
702
+
703
+ **Q: Why are comments stripped at the lexer instead of just turned into tokens that the parser ignores?**
704
+
705
+ > "Comments have no semantic role anywhere in the compiler. Carrying them through as tokens would complicate every later stage. Stripping at lex time is cleanest. We do still track line numbers carefully through multi-line comments so error messages stay accurate."
706
+
707
+ **Q: How does the lexer recover from errors? Does it stop on the first one?**
708
+
709
+ > "It never stops. Every error path appends a `LexicalError` to the errors list, calls `self.advance()` to skip past the bad character, and `continue`s the loop. This way the user sees all lexical errors in one pass instead of fixing them one at a time."
710
+
711
+ **Q: How does the lexer handle Windows line endings?**
712
+
713
+ > "In the constructor we strip `\\r` from the source: `source_code.replace('\\r', '')`. After that, the rest of the lexer only ever has to consider `\\n` for line endings. This is a defensive normalization that prevents Windows users from seeing wrong line counts."
714
+
715
+ **Q: What is maximal munch, and where do you apply it?**
716
+
717
+ > "Maximal munch is the lexer rule 'always read the longest valid token.' We apply it to every multi-character operator: `=` vs `==`, `<` vs `<=`, `+` vs `++` vs `+=`, etc. Each branch peeks at the next character and emits the longer token if applicable, otherwise the shorter one. There are no ambiguous cases that survive."
718
+
719
+ **Q: What happens if a string literal is unclosed at end of file?**
720
+
721
+ > "We detect this in the main while loop: `while self.current_char is not None and (self.current_char != '\"' or escape_character)`. If we exit the loop and `self.current_char` is `None` (EOF) or `\\n` (newline), we emit `LexicalError(pos, 'Missing closing \"...')` with the position of the *opening* quote. The lexer then returns. The parser doesn't run because the server short-circuits on lexical errors."
722
+
723
+ **Q: Why does the lexer enforce digit limits like 8 digits for integers?**
724
+
725
+ > "These are documented constraints in the GAL specification. An 8-digit cap means the user cannot accidentally write `9999999999999` and overflow the runtime's 32-bit integer logic. The lexer enforces them up front so the user gets a clear error pointing at the bad number, rather than a confusing arithmetic-overflow at runtime."
726
+
727
+ **Q: Why are there two functions — `run` and `lex`?**
728
+
729
+ > "`run` is a legacy entry point kept for backward compatibility with grading scripts. `lex` is the production entry used by `server.py` — it does the same scanning but additionally converts each `LexicalError` object to its formatted string via `as_string()`, because the JSON layer needs strings, not objects."
730
+
731
+ ---
732
+
733
+ ## 7. SIMPLE WALKTHROUGH EXAMPLE
734
+
735
+ Sample source:
736
+
737
+ ```
738
+ root() {
739
+ seed age = 10;
740
+ plant(age);
741
+ reclaim;
742
+ }
743
+ ```
744
+
745
+ How the lexer scans this character by character:
746
+
747
+ | Step | `pos` | `current_char` | Branch entered | Output |
748
+ |---|---|---|---|---|
749
+ | 1 | (0,1,0) | `r` | `current_char in ALPHA` → `r` branch → spell `root` | `Token('root', 'root', 1, 0)` |
750
+ | 2 | (4,1,4) | `(` | `current_char == "("` | `Token('(', '(', 1, 4)` |
751
+ | 3 | (5,1,5) | `)` | `current_char == ")"` | `Token(')', ')', 1, 5)` |
752
+ | 4 | (6,1,6) | ` ` | `current_char == ' '` → consume whitespace | (no token) |
753
+ | 5 | (7,1,7) | `{` | `current_char == "{"` | `Token('{', '{', 1, 7)` |
754
+ | 6 | (8,1,8) | `\n` | `current_char == '\n'` | `Token('\n', '\\n', 1, 8)` |
755
+ | 7 | (9,2,0) | ` ` | space-skip loop | (no token) |
756
+ | 8 | (13,2,4) | `s` | `s` branch → spell `seed` | `Token('seed', 'seed', 2, 4)` |
757
+ | 9 | (17,2,8) | ` ` | whitespace | (no token) |
758
+ | 10 | (18,2,9) | `a` | `a` is not a keyword start letter → identifier loop | `Token('id', 'age', 2, 9)` |
759
+ | 11 | (21,2,12) | ` ` | whitespace | (no token) |
760
+ | 12 | (22,2,13) | `=` | `=` branch → next char is `space`, not `=` → assignment | `Token('=', '=', 2, 13)` |
761
+ | 13 | (23,2,14) | ` ` | whitespace | (no token) |
762
+ | 14 | (24,2,15) | `1` | digit branch → read `10` | `Token('intlit', '10', 2, 15)` |
763
+ | 15 | (26,2,17) | `;` | `;` branch | `Token(';', ';', 2, 17)` |
764
+ | 16 | (27,2,18) | `\n` | newline | `Token('\n', '\\n', 2, 18)` |
765
+ | 17 | … | … | continues for `plant(age);`, `reclaim;`, `}` | … |
766
+ | last | EOF | `None` | loop ends | `Token('EOF', '', 5, 1)` |
767
+
768
+ The final `(tokens, errors)` returned to the caller:
769
+
770
+ - `tokens` is the list above (22 tokens including 4 newlines and EOF).
771
+ - `errors` is `[]` because the source is well-formed.
772
+
773
+ If instead the user typed `seed age = 10@;` (with an illegal `@`):
774
+
775
+ | Step | `current_char` | Action |
776
+ |---|---|---|
777
+ | … | `1` then `0` | digit loop builds `10` |
778
+ | | `@` | next char isn't `.`, isn't whitespace, isn't a valid delimiter for an integer; the digit branch's delimiter check at line 1418's exit triggers → `LexicalError(pos, "Invalid delimiter '@' after '10'")`. Lexer advances past `@` and continues. |
779
+ | | `;` | normal `;` token emitted |
780
+
781
+ The result is the same token list as the valid case, but `errors` contains one entry. The server sees `errors` is non-empty and short-circuits the pipeline at the lexical stage.
782
+
783
+ ---
784
+
785
+ ## 8. DEFENSE-READY EXPLANATION (memorize this)
786
+
787
+ > "**`lexer.py` is the scanner of my compiler.** **It receives** GAL source code as a Python string. **It walks the source character by character** in one pass, dispatching each character to the correct scanner branch — keywords, identifiers, numbers, strings, characters, operators, comments, or whitespace. **It produces** a list of `Token` objects with type, value, line, and column, plus a list of `LexicalError` objects for any problems it finds. **It never raises an exception** — every error is collected and the scanner advances past the bad character so we can report multiple errors in one pass. **Keywords are recognized via a hand-written transition diagram** that mirrors the FSMs in our compiler proposal. **The `~` character is special**: when it precedes a digit we fold it into a negative literal at scan time; when it precedes an identifier we emit it as a separate negation operator. **Multi-character operators use the maximal-munch rule** — we always emit the longest valid token. **Comments are consumed but not emitted**; they vanish from the token stream entirely. **Whitespace is skipped except for newlines**, which we emit once per logical line break so the parser can track lines. **The lexer always appends a synthetic EOF token at the end** so the parser knows when input ends. **It exposes two functions to the rest of the system** — `run` (legacy, returns raw error objects) and `lex` (production, returns string-formatted errors for JSON serialization)."
788
+
789
+ ---
790
+
791
+ *Next file in the defense-prep series: `cfg.py` and `Gal_Parser.py` — the LL(1) grammar and the table-driven parser.*
Docus & mps/DEFENSE_03_lexer.pdf ADDED
@@ -0,0 +1,448 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ %PDF-1.4
2
+ %���� ReportLab Generated PDF document (opensource)
3
+ 1 0 obj
4
+ <<
5
+ /F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 5 0 R /F5 6 0 R /F6 8 0 R
6
+ /F7 10 0 R
7
+ >>
8
+ endobj
9
+ 2 0 obj
10
+ <<
11
+ /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
12
+ >>
13
+ endobj
14
+ 3 0 obj
15
+ <<
16
+ /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
17
+ >>
18
+ endobj
19
+ 4 0 obj
20
+ <<
21
+ /BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
22
+ >>
23
+ endobj
24
+ 5 0 obj
25
+ <<
26
+ /BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font
27
+ >>
28
+ endobj
29
+ 6 0 obj
30
+ <<
31
+ /BaseFont /Symbol /Name /F5 /Subtype /Type1 /Type /Font
32
+ >>
33
+ endobj
34
+ 7 0 obj
35
+ <<
36
+ /Contents 31 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
37
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
38
+ >> /Rotate 0 /Trans <<
39
+
40
+ >>
41
+ /Type /Page
42
+ >>
43
+ endobj
44
+ 8 0 obj
45
+ <<
46
+ /BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F6 /Subtype /Type1 /Type /Font
47
+ >>
48
+ endobj
49
+ 9 0 obj
50
+ <<
51
+ /Contents 32 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
52
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
53
+ >> /Rotate 0 /Trans <<
54
+
55
+ >>
56
+ /Type /Page
57
+ >>
58
+ endobj
59
+ 10 0 obj
60
+ <<
61
+ /BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding /Name /F7 /Subtype /Type1 /Type /Font
62
+ >>
63
+ endobj
64
+ 11 0 obj
65
+ <<
66
+ /Contents 33 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
67
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
68
+ >> /Rotate 0 /Trans <<
69
+
70
+ >>
71
+ /Type /Page
72
+ >>
73
+ endobj
74
+ 12 0 obj
75
+ <<
76
+ /Contents 34 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
77
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
78
+ >> /Rotate 0 /Trans <<
79
+
80
+ >>
81
+ /Type /Page
82
+ >>
83
+ endobj
84
+ 13 0 obj
85
+ <<
86
+ /Contents 35 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
87
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
88
+ >> /Rotate 0 /Trans <<
89
+
90
+ >>
91
+ /Type /Page
92
+ >>
93
+ endobj
94
+ 14 0 obj
95
+ <<
96
+ /Contents 36 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
97
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
98
+ >> /Rotate 0 /Trans <<
99
+
100
+ >>
101
+ /Type /Page
102
+ >>
103
+ endobj
104
+ 15 0 obj
105
+ <<
106
+ /Contents 37 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
107
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
108
+ >> /Rotate 0 /Trans <<
109
+
110
+ >>
111
+ /Type /Page
112
+ >>
113
+ endobj
114
+ 16 0 obj
115
+ <<
116
+ /Contents 38 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
117
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
118
+ >> /Rotate 0 /Trans <<
119
+
120
+ >>
121
+ /Type /Page
122
+ >>
123
+ endobj
124
+ 17 0 obj
125
+ <<
126
+ /Contents 39 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
127
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
128
+ >> /Rotate 0 /Trans <<
129
+
130
+ >>
131
+ /Type /Page
132
+ >>
133
+ endobj
134
+ 18 0 obj
135
+ <<
136
+ /Contents 40 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
137
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
138
+ >> /Rotate 0 /Trans <<
139
+
140
+ >>
141
+ /Type /Page
142
+ >>
143
+ endobj
144
+ 19 0 obj
145
+ <<
146
+ /Contents 41 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
147
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
148
+ >> /Rotate 0 /Trans <<
149
+
150
+ >>
151
+ /Type /Page
152
+ >>
153
+ endobj
154
+ 20 0 obj
155
+ <<
156
+ /Contents 42 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
157
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
158
+ >> /Rotate 0 /Trans <<
159
+
160
+ >>
161
+ /Type /Page
162
+ >>
163
+ endobj
164
+ 21 0 obj
165
+ <<
166
+ /Contents 43 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
167
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
168
+ >> /Rotate 0 /Trans <<
169
+
170
+ >>
171
+ /Type /Page
172
+ >>
173
+ endobj
174
+ 22 0 obj
175
+ <<
176
+ /Contents 44 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
177
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
178
+ >> /Rotate 0 /Trans <<
179
+
180
+ >>
181
+ /Type /Page
182
+ >>
183
+ endobj
184
+ 23 0 obj
185
+ <<
186
+ /Contents 45 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
187
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
188
+ >> /Rotate 0 /Trans <<
189
+
190
+ >>
191
+ /Type /Page
192
+ >>
193
+ endobj
194
+ 24 0 obj
195
+ <<
196
+ /Contents 46 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
197
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
198
+ >> /Rotate 0 /Trans <<
199
+
200
+ >>
201
+ /Type /Page
202
+ >>
203
+ endobj
204
+ 25 0 obj
205
+ <<
206
+ /Contents 47 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
207
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
208
+ >> /Rotate 0 /Trans <<
209
+
210
+ >>
211
+ /Type /Page
212
+ >>
213
+ endobj
214
+ 26 0 obj
215
+ <<
216
+ /Contents 48 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
217
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
218
+ >> /Rotate 0 /Trans <<
219
+
220
+ >>
221
+ /Type /Page
222
+ >>
223
+ endobj
224
+ 27 0 obj
225
+ <<
226
+ /Contents 49 0 R /MediaBox [ 0 0 612 792 ] /Parent 30 0 R /Resources <<
227
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
228
+ >> /Rotate 0 /Trans <<
229
+
230
+ >>
231
+ /Type /Page
232
+ >>
233
+ endobj
234
+ 28 0 obj
235
+ <<
236
+ /PageMode /UseNone /Pages 30 0 R /Type /Catalog
237
+ >>
238
+ endobj
239
+ 29 0 obj
240
+ <<
241
+ /Author (\(anonymous\)) /CreationDate (D:20260507223138+08'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260507223138+08'00') /Producer (ReportLab PDF Library - \(opensource\))
242
+ /Subject (\(unspecified\)) /Title (DEFENSE_03_lexer.md) /Trapped /False
243
+ >>
244
+ endobj
245
+ 30 0 obj
246
+ <<
247
+ /Count 19 /Kids [ 7 0 R 9 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R 17 0 R 18 0 R
248
+ 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R 26 0 R 27 0 R ] /Type /Pages
249
+ >>
250
+ endobj
251
+ 31 0 obj
252
+ <<
253
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2376
254
+ >>
255
+ stream
256
+ Gatm=gN)%,&:O:Slq=6Ma+aoWfsb;S9KMUkNRd9OAhl%D98n-H8B"RNqX$H(9sOmo8lBqDaoE5;]@]9YMf>ul_qX'?:A!S*Y&?=?LLs?#4m(/YNc&GFIpM\&Oe.A3d#Tt9N'*HUr_kDV!:O!5]RY8;3Bk?l3E^9M\>,\=]LjuZk\']:Md"QaEC-\D;A+IHZ]?s?:2fV`[N:b)YmQ1I@M,hRSFOtr]pP2A5C")jiVqstH$[s*>6(lbHDad.22HGI*m)sGOqmpEZKGhrb4TfJ$I0e;gLacMk[5kGU4*GW@ug^6m6:W[TJ0hm!4gH"*g)WXo\FKf#Fi;uf$3)E]MdJ68n/4.C=Tku<G,.WoCXhX5DZP@j2MS\CQ`fJ6U7ZinU=99b1F+?05"keDlHjHl,SSPXNke08fgOYBo.JoP>'I`V+iPJVrM@uI#e;rafKq2oi!6^l@mIP[2b61#^82[an(qXR`aqi"m<?tMq2cqZtX-Q'VObt4e;+#X%l&[N4Nog@2s-n1_CU^6=cR8Umf'G#);FuHIq@,?WIf4P^&m4-'Uq=3+F35DWjqEAM.a2<&[F,>g#"d1E;VgL'''lUQ5ilAO7P^k17:0[Va186IsctX,&Wb90<#CeE"D#ZBjd>>gQ-C(A0!LZk/4iAlD;!oe0dMXJ?J'WS5HF"XK4iHTn?]Q>0_u!l/%V%019$/Lu^4#+HqK@>1ap\^=X.6=sr7=!=ukH]0dtaJEX0rc+K@%1.\,ei5L+=\*j4QQq<aFceLp=WH.Cf6)kReeM=?T&kaQJob`,k"q9_G=Xq*=lbtk1@geg0brF@'R\GTonW75qg@LK*k;Z]o1n_./;+":Ck6;=DqZ\$Hk,f9A>&A@X(<ZC%r<"TBSbQKA"I_RIL=4n;NHC<[Zo/oR)Ks!^:V"Nq`irps7UDQihX)$K]C&7OG4P?60T&1iP)/sf0C.!A@]khLl80/jgDqF?Vs7_eg<Rp;^C?>3E#H7d\\[k,=1omX^esmM`Q8[&[n[?^HZTa0Ci7R:0kr9rR>0jK4_`M^q!.MWBRHY;Cl"ceBCjXCR%H+?-"%THe`H;3"^KYP!O%^,'D_/q4VtCQNNE8#e.m9;80s3/_I#U6:;#+RaQS&&km.%0277^=HXB?MI+_C"ZAT0D`OfY?XjET#"G(r&]<Abj%#Loo/ESkM1?\lq:V'RR6cTGD"QLpSQ>!Nbgs<2?sSrn,h8bbAb95l01-4C)bNMYdo'`e;n('$3R0'jm,1"hi%@REdEW?@n#)\.LSo"IR;DB!Cg_W/i`I[a'P]bY1s=qmYAAXQP&c\!AjBZTf(if;KHunL[Hs&kZ)k/+KSug"Yo&\`QsY!Qf@I-)\QC6-S-_'])\$Z4IHli*[(hoB*/YC%$JV14"ZM=Rgo#O`4Wg9E$GHPcl:N=S@s&P@JF=tFC]jROFZ*348*e?s^2c7P(p4rT-uk8K"=>_W"2M35s,kg_6T'8nPq4cIVc4QtUo0)>$#mFepT$_4Q:g4>D5i4]Y#nrBW3g7M6amT@?;auMiUp_t<\1$b30$fEc43V&S7YpUj6$RYarTArZs^i3Y9;M[d1&2SW]m9#H3T/<q<ca@T8l%L-(6&.Ths*RWMBN><:F+K3q\`SY,D.L;uUhY]:UkA^EZaIp#j,'34sR1Z7;uPk/S,afu7.'\^5A)m;D2.FJtWZ":fQo%h:lUD"BVOFg^u!9A3dfG_#0Ze>).XC*IuVajY=sIKKX"HLg;.B'i^-oB?e+gKU]q:\*'2RF9>Wl)?84CYmBAa"1augI8L1Jpp/_/Ro=]H.r:*pqQ5*5$.WA5VN#9G"UQI)kT3@0XYrUNTtPPY5;<bG5^IR/doq[#"Jk)SM(FTd@a@=1hhJ6&\KLNPTu:6@>^M"kkCeOT+Kdl`t9M^7A9*=dElLD\g*'"6W]:(h"bmoh,0-n#SGkKBltohN"WU=Saf$agm#Z/j=,N;1T;Zjiu3@Ag9!Y,JSAGUWmB:oD-T#-iE,@I\mM4#g09&N*A'0d45W-/,n)-(ONqMG7jgN4DpLTT&,5d<mn*H4FdP7a^j^8ZdF94LilaWY=%R`fS*m$4_a;q28uqK^B%d@4e/JHIlu]*GVOHPBD*NKZJ#<[-W^KWQC0f=Y7A08-l?\O&3[pM8NK=KHh+X#d/qqU"/E.>^e6*jd<b*<?>P^J&b77/"o8GW;P-V%<qHe25#`DU3h;MPpG)t#f<Yt[Nq:"2W:l`P+9UnVCi><LB3"9t[>$Ikr7W<V!6=E,((d[!6bq4rNacL:!,er9p`sW[Js&JQ&s7uZ]"o/%-@.:hlE.#poTg-Z3S*L9iH$ei$@<rbX"rdd:FVmOr3fN'62p)50T;>kis#Me"\t"KA9_YZ]pq?X"MuNdJM,#Q~>endstream
257
+ endobj
258
+ 32 0 obj
259
+ <<
260
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2952
261
+ >>
262
+ stream
263
+ Gb!;f=``=W&q801kh:Ge-"YI`Gg;eB3*B%&Clb^b<,K1g"d>%e0b4^bfrP&Im05"B#=Xcs^9!N#'S$Dam]XHG@/,MHhdHl]E<<%F3,en^.<+%I@<)\;PBVMiCM%s_#V<G&[qsC"-&:=&ie[qcZb*GIb8)3?$hmA(o_%P`53;#k:36N/oi,S#L3k(+R&_SDi]U!7KZOH[i-.;0[>fgNJ1GK[7p^2jnm21`^^=3%1E.n&@ug$,i>E4]+7(,c1WMgITjdfVS](bVg]2:)+!!FV3'I3a+>>R/[D_B@+^jtob`$A]`^!];8S.P6ka=7t]8XIsJ6T<q9#Ef(q*2Uf+#?n_N.9<%?<$%&A#+2umjClX)(\B#mHhTu&!7m`S\$XX?utbHYl!)jMh1>l;=N5l:i6-\4Ipq`CG&\)(mc^pWj4)aXnhOTdX*br3?Ih19O6r`kechpWS.s>O/@1'AY*Y8FBOn'muNj^B"dt.?F]#9k*U(nbZe3K<pI(GD$i-uR7`e&otsDFjo).#T.t@*ju9aoi_cGB<4Kl&Y%@p86V_u4_S`VX@8"Pt;\-?>0f(XYmRL]WQ&AV.YbdNnK6A9R]n7]gC),\N1C^0)n"J4'X9u(-r3AA*Uf5JG;-_B[[=lZTV\X0!`IEBOZTRIYa+<'mgTR!uiH:\]djC:,ErpPtgimb*D%/3UJeRfB9k2cAP1SUEH=fmh2?qk.=Z\.El]BN<<:g$r^I2`/lFHb2P>1k]S(u\V]kt2AW8<',[q[7=hfWO0SjZs@A)3G"g[[buPS:ROe6hUG0P2)ACagZ(?9@1kK!(54g4:S#`ENU<3BCi>="P:=dW:sJOCt5lAMoCP-cj]Y$?S.j)1OHFG']@=E>@ZiW@eNO@:>nQP.[BD;%gWW^s@?"*:bOAY$@#"k9K#p;_3hB9Sb#qcUa)AW`?St.[(Adc6+b27+"TWiT+E(kL8m#Sbf&b$MuW^^P3;[U`\7fllGsCo9+k3-shSUp27ZX*C"moW+f)Zn^b,R,^7=Z>NKo;+rq5#Lh7!*8&/[tK\6nLThelZ#(jJaZIb87,LoKa7PJ8e`G[]e\!&m5L!Sp@k?";%Y<H6^h]8s<o.A""jiqu)B'MoIi*9BePR[tKV^uqQU")S>+GRf'\:-gcK@Z0lfQ.Vsp*11Oj^FZ[G6*MjE\'8hR=YWTWeBiPaB-3k;4hVD\0(?F*E8k6SQ2N:'):WC\nD-dUG1.8bDS[G'ZK$)'e6<W3m^[Z;SfkHcI]mLl<f7TTNSPGhC<O3ZZ+?u)M(g,WoT\59H/]&>d[?b+hh,j>\,?/='T4?S&UkV.*\hDWDP<8)Z2d#N?2lO:dOd.W+f5Td_C]$^Ys@4/n0eds%'#mn[E1-<OVCdWSrqh.YEi,'dg[jL`uVa<G6C%[n8'tY+-nG@!6t:/.M1SH=Wg$24bV0W6:>d@(OEG,(eFVRUN%C16+3Tku<F<M0-o\ooA@57>T-r1OBRY/GQ^Xood@XnYj#X3It6@:CHe@j@]Gm6qo(Ed%8j*-C^uX2.:+^^hDNpi1bf7lPXGFOi>k<M@J:*Us0\j)R?B!mDU'ZTZ]Hi^g/!FlcQfK4oqa.q?;#1i:h*q,aP6uAs4DZ%5<^8#SGolP!>tB%V;"CH.l6\'MX_Rnea`3Y\'gqfb"XT7-bCTD+e)Ob]f`l,K6c[o,!$)$J["-.6SogB\\2+C-RG-Qn[H!=FDQW<JK]@*YId'f1@Cih?P8r([FMj7nIE!D?oOn9$OD`$^I!\](i+Uhe'rX)u?$Ag;rP+I3d8rk0HXs;Q?KLc]Y,]:;Z^_Yejd*-ttt]9Msjl87?:.X>0gM-s_$*BjRrIrhTN+(7::?cb^[X9fIS3_UZniEO92+GpK66/C[,>pf\oa@?k?U'^ZH"$>-gRVO2/0s8U/6"J3Td,t%`BH0r<o>h2UI/2WP+I(d2l8=+/E=*Kk7.tc7KF`r+Op@7\j5VmV,m:An/^R7-G7g&lE)+\B^CNW*LG<]$i"Nr@(.(,6sJ7BT,gRZB6Ahgp)-PfYT0`WnfC$.huJ"srC5%;d/-HdXQ9H`'NmDY%]XI2,8PU.fCHNrT#)q:Ipe`H!P6LKKQ,:.kVm$d"M>m._jNm?t&>RVlFr[d"g#$5;sP'tFRK(<aY]9CI)No_t,`@X0n&GQWLl-XO#E2Y+$o]]UO#L>BXVje%(O4HP_,47@-,oF8_hu>mT^$^ZY5@8fOR.OTTRgrPLH2Ye$g#^ICch]6nG&q_R4+q#*d]7<$*DkZPGblAIp$G+>D`'CPg'SW"!h&>)qBF&mk)?akYH.-u-K327)?)1k]RZr86jWO(KR<et%HrnYb#f'^+/s)2idIeRUgag2%1.Ff"4ri,25%:q:p\+`77^iYcS]nM"3:V6a5Qa=.gCPkECUEa$Z*1))bMG'k%`ic-M%CE\Q6fP1Y\j"`bLbIYVZ"Y?Ch:NAP7Nf,&AW3-g96;m-!$I#UIicE\'+r!toE1=.t)!Lq6q#1.t(%!GLddlg9.ja3eu70<_]->GMKQ>$q(n3fFT4e6:9MS090,eB""H6s#&Uee^j$eSqOS5js=<ChonnP2rfg"ec:i4r+IedcZuMT;Qg1\(SZ,HPKTOMb]RJPG@ZH'&hREauDP,D:Z9#ep7GLqEpcErk*<ZRehhe[.;])*;AnF.d2"?P3:/+VH&:%Tu6&6h69d1O)Wlr]6NnAJ_\8VeD<CTq:cXS.Y3Y]I*<bV_Zek,R\h0tC-JOGKgukAS)TE3dJkbb(\p0H<DkcUs/8.SbT]jDCLbgHR(GnfeDj$Agg6q3hCos+P+^Dp"$jHe"?*nVFM)9.E8e*pl6bhdg:)g9[JssO9V":nBJllJqcAYi'E%L&OY5&X?cQ'E:esm3`S2!t++/pOnIDHq_q\^k3F*Q[H\$RC%rK"XDLK>C)dS5d(+THHOM>Cl#n*kD*p\pAfP,c'GGKe3Yei?i_n5pM-NK3E~>endstream
264
+ endobj
265
+ 33 0 obj
266
+ <<
267
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2189
268
+ >>
269
+ stream
270
+ Gau0D>Ar7S'RnB33']2d.2#+GmbR`dA]ZVK8@ui.+6LC9A3/9k9.E@jaaX0u.G:"=g/]kJ/eWPV3VVte.G4D_p&AP'nFHo<D^\EdUDZmp\1kLJld<i;P?&;G5t(YEHf>7'lVQ5^MFTOT[];49-S>M`&R9M\f!"O[iMp"EBuU>S_Il!73/e^_TSssQ3+jrA#=boI#/B3LX(=Cu"Tgb0+mOCE_[""jKil8ko'(p3`$^5l2"FM#S`dF:e4+kBV\H\SE?J5aBId'u=V]7pUag,An4?MO3<6\n3ThOE-V3j7Q;C/8k)V#-Ri,d7_<1=r@e`c!WD&4tCo-rl5G(</k563^+rd.3VC&\^4NI,X3/=S+@PrO[flkF^RE&d5LjG*qM2mL6DS%oC2^nmb'ff?ilh<>nguq6LEO?nc,!Ta0T2/#=;B#>7qa?e5H;7"&KS]b^_sDNtc1i)3?D]c?FB[@WZYfXc*l/c>A#\"c:7F`WW?c-[,]PU&eN)^c>1>PN>X;61.`J&/5@d2['"D7gnKR-5&E"EQ;3igp0$uX8K4QU^p`[PYMV6,k.d/BOX@<&D:Lru%1N7/ich*U-VA@j*@c(6n5cAUEUZW2,O3!/]&UN)Ne-C/hgIZ15ZV&o1EfFS.'9E2AfJ&bgf\I-Dq12>fhI[7dHa1!F*ogBkU-09$Xo#7uj@)fo6K><^>Yha:lM2U#(NUcirP%f]kmV7#AZ.2%$!c<#]>)+pLNdsW^s/Kq=/4[0hq]@aR2890@:n%Pg5:o$5'87[6ffnInM^2mE0A+Ticoc+%D,V]Ga?[3D[0W/$XZKhZ+bs";5%\-1[NW,T<ZkD;SiX%A8tVcfP2(u;c1%%R>ZM7@FpG/.EJCg(<*Z+pdN2h4G-e--`Z^)(DCpU74l2LIr*,s:"p9t@CI)TB5?0_Y1B^Wc3<C8i,W-tX!@SYF/_1+W';E,0L9LpLpJ9/]pS/@T]oWVFeBooZqsJ!Up(=:.J-d$!HHo9AibGpTcNaX`cs8,Uj4F;PHiY(]QFlm/T"p,'R3X9fYN8/Bffe=%r<e91UOZpgPW]G]oc"T6167p6,tAVa)flgmEI\j$E&5Ys0b"X#[V+__T16lGUuV9iUh5%q.@?mrjNoX^S'b?^DGBVGRMmUC96h6MPnWW=8VDFHInJn[M*`VFfF8U4rZdu<U\..msjh[.hI,=W""HmZT?8p&\,h\TH+hMMXhl$(O=2bNmro$qntDQK+ip?kX`*@e0C4Rb*i=XAmgZUgFR,k/a-+*VKA,mXY5U<c=2WaT`!/YKf$!/$5ReUSkU`kRS&\pE)==2FJEdFDUCF''p\.4]FAqePdk`1&be=Wi;tgT3QO@85o:CAKR&R^*nGK&iLki6&gBJBe,<^]W9Y&9N]a-bqkd2=SA-2!7''!2BoHN?AHd4UBm5U*`V<$=%j\CK9hSlKQO"3!<&)RWaM!M08eZU1q%T%M$td$%G\k/OKZ:"u^#0b'@]&#61!`h"7a0+`!!-"HA5\hY+ClZ2(.P,0RiG'<UiLh)dACGF2.Er[cu%DE`=s7.H$tDQ]8?)Y+n'bdIn/q0@dRrPANO2ZLQLh:p,Bl1'RoS#?#mQ5S,?/sQ'EW7/h.7hRD]@4gKQe:3.4XT\]T'=#(?CO]/aFPA+?'l09g\R;,_1^HIR0`dcRns2QW7LLgjnS\\Wlj'n&*fXO$pFd3CT(!D,n`%WMitAR-LF4//\BPJ@T_bb_FT0EX\S^)-fYHh^Z,`Wj^W*TUJA1![a;rL++]H7RB%E%We'`4=HRW73]1/9OIf2/8$V%A6=16X:-UdC6m!DaXNl9h8nY(FJVbA3:t.DLJ`6le@(65<I*1'T,aDlDaq2A`',Bjb:GH3)UV.e(S'C&L0Y\H6T.q1sjM'ZaHVsHi#]W4#f?E8`[CM"5!Vq>)&W0"6)h>3c#Iis+ppQO_0kWL;Bk#Mb4+Z?mbJZ>L]!VF0<]#XM0+=/,YH),<$U<K/9@^bI"5FbP-PI0Y\U"rO>Z!,K(:u^^e$:V`B6mC\#5KW?rstY+M9XAl-JQJnd.g9Lk7)AG[u/4a5OA,n3#sq7]U259eCgb[M`IL>>[pmm'_[Z;Rj9_2=F?#],`HFcG)KC$3LaFF/SO_K>De^aWgA0FC4(Vc[>1^-K1+Fh#X1k)+u$oNub.Wm&Vd)Q@Mi8Lpbm[C^^EA!9]C-3Yds!QQ2s"o~>endstream
271
+ endobj
272
+ 34 0 obj
273
+ <<
274
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2164
275
+ >>
276
+ stream
277
+ Gatm<gMYb8&:O:S9O/?p"+/;S9r*>&o\ouWS2P3foH=PMRTrFCGr&%2<PQ7\QV0u9<g'"QM'\'A1V8!Gk0/cE=np%fH^kcJ1ni+%S@D:W)0)"R1qB=GaiVGW?4#[ZaF*rV\`:JJ3,O/rF/cs_FkcSWCQn-?fZe.&m`-:C\]h*2'/f_4AtirA9l55N<AYNQT$cUT9jZ!PrkR*u)%Tb]libNAE*1!j\+J+d#n(%aa$+?iia;q0hdbG_4ku./2.g+m;@Ar,5-3r"(@sm>XmYaB/U9ZIABnA+!uh)rR3tkj$L>mE0PecX1F6JG#*#c!^_0.s\5L[%(MTQT4YB,gf>#(s["80(?AR[4[%+IgCIC'jnZo;ddGDm$W&C$S'60Fu`h<97=bp>e7b;!8]qQj6M?:N)X.pkF&<7=Z2n^"4G&YHqCrpK'qp.l"KNf^90kZ+ufQFZ71%#u*_&n#Mkt!)8Tb[d)kkH\Om[62u./.tWHcA*,QlT?mKK2!\mBK1*EC7oMhK%T@21eGHF<gbs29VbAESHfR#l*XtHDZCBP9ZNVZEsW2%M(4;i7M=5ZjT/-&_/Iu1\E&X`jGSKG^SC\JSTqZEs',J_hVD^Sk!WJOq1D1SM2\"KhUA"*+h%JS&N"TQ+%/_%rs9g)C8i^K<*/IS"<pY#9FI`h&<u#O.QX&,m&>6#7j7/QaK,h.cj#4gA$rPA[Qgc[[28EJ7iOCr9:gP.L_*1P-=>20h,9>]6$g4lp>7J%4"ptghC."U&tM^bchhVhRlhn!fO'N'ZkGRO^IW5\OA]Se*6,-K&`B4b@T//Xh3,X?.O]fF08q47%^(21=%jK"d5Q`3_#__7s5'-<(.9$H\fp,c>.oe=JT:lA"kj-_u_37S1#mb7kN/`/GAU;;_IB<gr<o7TU"cp&LR#jC<"1$IJ+XOJrnXd2^!..I9`9;Q7^W,R7tr.67=13D+Q>+SGt2)bMY+,03P/X<lgb9^o*r9\39B7V?'+j&Yca3XL2h4Kt9RT]_a8>[\9Wj%dJ[Cdl>LQjUq3U3T>9Bn5s(9-<tJjQQBI>YQ%q1-uB8\Ct_&IJeIQ[iiJ&N?V;\R6u`U+d;7^Z2U+l<jm-qI?Zc-I=]X/W_V#:,&IXskq0sTE[$>p#,&:rCom)]!X)b/>+1Y2ZM`d84\!33lBe1as,3qL`aLNdX4$b\-3V][Q)LZWIbq.HM>36aj3f[Nm39cP]L@?P.*U)g<W4=sp5@8>LR+&Ri\F\]ZKU-,Y#?-`igUYB7&MrP/0jWsB]@-\m;SM%JHWA<!&Z()Q&@+LM9:;<],OA$\\KsYC*.<LqVfU?f@iDD6;R1sHNd07Y;]]uB)MZKWZp3+.s6AVA0l7^47"fY(E`[[mT\(A>M`+1cVN\j\Nu`$VrndtHG].i.4G)bM1s>^td[)@TP?t-PCbMQO9PiCXG=IUah.F++LN=G.05^6C_iOCf5BG*7-q>2F(eR$`f8i\WUXAs]@jf0hDj-=u>g^P!7ME`-/?PbL2Q9AU=u/qui\UZR+db4`8l#t78M0XDoP;i>W`.D_O+QeRW;6g/]`S=A&gAAcMH*_C>^_mgE$3tsFm_5=g9R!MP@Co+"abDuAqV-nZ^%57Lnq(^3jGEdl(9f/4:J/-B;nMqk4pcJ;ctiU]"H3S%Wi&3:),Xt%VZ4C]:4R,1cHWP\6jR=7"\g!F#B_=cQP(343U/RmA^V2?h!&PaP@_f5YmaQed\*W%[%!.>7I9I9J%o]AL9#b3%MnbPZ9IkoM"r=Em.MaL9&*N2F,spR$gS`7umE&3^24mXCE0@G!R#V&#Z>'2e!iI/"/&J=;CW>7Jtt\W"A<_]BLb8Q$X8)%,/Ue9Bj)425Qa<hO6C/^!eM8Q*@p=Y/b_Rn6Q_Rne-@H<Mmi5TIKPECPN!^fr@W?$^WX;m_H'$7NsT]H"UK6M.-8gNJ#h[.SX.)Y%LSIU?35PA-W6/3V+hs#!mcV0s&'7>())n2)dF.C!5`0-#YC]B6=#u1?%)^I!qMPZQ@O6;i*Md/OqJ-]_R`8D>REVl+B?PKmWeYj6Dn>9SQ+rFQKYYkfCP9LO6;np3gj8[bEF6SD;^CD00Q/`'@K]7h$B+0g?]7MlI0`1.r1ro3,/'9D%*n`e-=S>.F[FoJDoB#.]i(a8jX%*"(/inZQe:2^HemImuB)?N~>endstream
278
+ endobj
279
+ 35 0 obj
280
+ <<
281
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2210
282
+ >>
283
+ stream
284
+ Gat=,D/\/g')p`p0h?;_ZY)(ghVCOrUttaugK^3%)X&5M+J:%7Ag<4;MN6`Q5JKQXNanQ9]iBSZerV\XpP5R&i?,K-ZN\.V&R9^Z5^aJDJVGG'd1q$G^%hOp91]S$8E0>)$'R1S..!"0AeraZ]-#$<oYHRonm+NLhj7F6?7m^)E!8Jt.5,HHA)C(T@P\MA3K1\ikU.V5IjfW\-:0>Hi3#u5.t/k`OO>D/r=OaM.$I':&9WMRP/rT>_t9iOMZOSY4Za[\,pt=?e0D\_b<1T9,hT8G@KW&#9lM>U5IFP"G4s.HWL`#l0BeC0P(;*_ia_IKmhPb/g`)lpK^HVtL`5oUDjL0&8u6(4bd<J.@hgZ)>!jT)WF8s$*%#HVe=*FbY"5raj?VY0#+"Gh#[g*+L.mmm=kCGl2@$CL<.O<]#[M?gg7(^B?s9>@=t<Iqi*J*m?rl/CFLT\HR.-'n^9-[m7\cH2s*Xcc%0]sG5a@l&Fj%Pf6RanJXS#ha+=H&lVJEIN?\]6U,p]i@G!Lq?5th(QWGap*G!5.Q4Sr,gCqk/giefsVN"n&7<QdrW11N2EVC^cfo-7J!dt#ft^""NG8OjDI`X,4MCh''6A9_S-LEThM9Fb.kfO[;.?&%#H!*7Z$F<?5CS6<7HX8*\+9"o.k[3&[$Cd5nn:M5GKV3^6%4Hi!R][BjIKOo?XVD*<OXA2HIM("$`_b0,QbS85p`7C=h'aBd^9:Z\:_gaOVg;[rm=XNh,VXOn]9m)XY""aapIPb2-A!0,0m8=nfMV"+M7`4UDc>p:U1e\''`#kL32->(lKNLf5GOU9Mp`1VEBh9.C;.(Ht+*Xdc@s1!-=VD?'^t?O.*fP+bLO8)gq93mk#0e&cGHeun6[=X7\3iV%OMH('U6N)3<$'j27],:p-r)KYr*\a;pe^cUFc?61Q`8Ld,&m5NqSV7Irs*.h$[?mgjo$jp[s`f<^YN.#?=/^VJ%:$bNDZ4UpZb6rA:Ki,+<F#1VgGQ3q3mGaKUS?\b:&+mWC=]8,8(D0djQH%KH3M!2XDZ:EeKi7OVmh5l:Ahs]ApA(hI0]0[nI"tjbu9%MCI[4G&gp!hJ2IdQd(pHYobkqpSo*g!`lD4ZPgB:[0En7Usc?oO2YM$=IIF=!/T&uP:FV9J8]42<Q1@Mn,[T[%F%;B:dlO/9tRU^Jg4C7:9)IgOE6D0XW_AT[+UUO)%nkH7f/T2p7o,ZK6gXClK+c)Y?9?MK)Z*(`#/q]fYG'")][F2<]2gQI/[Uq%pap:eY6<[>[t5rATaf.7YiL'GK16C@7r?n5P4.N6TRoG$:[:4E9R+'$(l$1FOVX""V\7eI(_jB?\f[VR$\6Q;4Xtt`6gJpJfCTt-L3th"s:VZ(G/^E&gJ\.d_RX0>"mGF:REDpeP:Ndju0#bgaN.-a)3S;?4^l$_htl]mOCajbkcE[d/upDs%oaCk"<mV.ERlJTn9a#&l!m`?JU"?I/OoZJ<.*g_0PMS?G5&9<O0W*Q4^io9NLIL,`$NM/6pW[]RdE2frhD^H2i85\EmV7S\alDbWYr)pm,9RE-:jmi+8Cd#KqR(.jo2sfe"q64Z3foUm(KbpcUB9)MI"m_<pk5Y%;=iRQD_Y$5)]CNobE2c.P3R*@I^2QMJ$L1-]aqh>[9<p>)p=fC(rs[g)5PacntG@8i-24"RdbG)F>h8[dutNOeC0-5t>/I>M&1s-J#9bOug>R=f(o/mB)pgbX@60Aas30.OY!Q-Zh,cW$<uFobN(n;5W%S98nC.Cn0+]sJJSjp(Q(qDJ%qNo!4Vp&X!.-Tg.>q`_*)C>jWPMgaTq@35+$Q?;I?+n/&AV%))I8UTe($"6Le9^K;>4rILW@6ifpqR`e)95<o;FtYq#q@[8@UM$iMblIuhG>cNK%W][,f7E6$3bGTo!db0((G'[9]a0-n0K^^7#^f$afo(BhMcjj?QR_$_Em#YFJVlTnBb\-I7=6FS"457<;;3Z!B">4&*<RB).Qf"%Y/$'2DA$1sXp_+0=VdFU>EEBam1qG<Eb4dnj,Vhfm(g4Ob82h9eBAL!9s&RJIrfQsQ*FCt?N4iVQi,ek+LC"t*fk"qf\.^sa)TF+_nJL)J%;^H%]B9iR`9J>`ohbXqmna(fWscHb6GnYToX`&@71b&W<j)08UG.)6s@Y,d,0V*hr\^A5E.O!&Bp,oi\URQOUHNP`RObOOZOT-`Fa&Xi\*"3<Ib~>endstream
285
+ endobj
286
+ 36 0 obj
287
+ <<
288
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 3010
289
+ >>
290
+ stream
291
+ Gau0ED3*F0')nJ06#?!$DelZlotEjYlm8-EJY\W*h$,hU#\]X7H''CAU3EqF1r'!$W#&YRD9KW)A.`H+%`oSPoC/019e?'Tl[Rq(+b,uEmpFhfAn8Iu[S'm]I7*G"cTXRoT7lt^U43&(FbA%`Ci];RXO+bcB4nAC>t12O@GVG2rHS3o]Z`:E9LM0QM5<a96"Z&Z,j-[Dr+e(d(R]`1$iC*mDPlr3((s^b%:QI04cN_$%X`<l$&b],Z=r=0hubq@gP*s?OQEsLNEe-0YZVKlleN%-$Q4)&1S6^\X[3qnXS*iNLW$HsLJbDN=m4>>n=-6q@_l;[1p_gbkbrq0R^LI3^WBC!AKoY<=_7h7CB4H278f3%br!"_LU&2pK7i53:W,_uMCY*k,[9PPqt$k?VkqmQ(6Yj.^+&qX':ETV4S6-Io]CZoH'.2kaV.;7Ge@p[E-BfQBp^V]F-nf0MF*PQQ7cRs)9GcB?G4&V&(S6oZckj3a_g.I//="e9(GZQMK&>^T8Y:`/,ejK?%#uNG+c<.#NoO=4C&MtaG/k("JHC38tKu`3nUiaeND0YO0Y=J(D!6>ocg1R9\RU@?7,HM4X^tK(=:Fui=k-;US6n1crmRj%VWnWb]>n`_@)<=k#1)pd)^@/4j]'P;L?WuCanLne;ZT(6(M!Xh/X@?/9[^o%XR/=QWh5IZ68L<FZI;2r\Q"8'?0$rG^@Sk"^+)gCnq+F0"-TjjR/#Q>%!%^'f(N&R:f_m*nMA4s+KVf#[cQo!n4WMQQ!/E^0MQg\IbCBO>E`Li5V:05\'btZ]S[6aMDGR,hXE1NO5JKm.ps>nPU&.39da)rEpIK0,'e@aV16qK,)EY%U<I*d!*sKZ"]S%5`bTPrRj%S+!cpqDs=eD/+I1+kG;8lScbP".?CO1i\B17$f!n5!sV:FEaE]2a9,6!U:N9U-1Z@SAA^9$jlE\.8r8eFroG_,,hf)<=H(iUre-r.kp2D,l@iKF&Tn.Q!@MX?$U]G_ZW/LT/J`!?dYn#hABB?=!^F7QD(VALb`K8GLrH8uGWA3GeFG5f52Zj-3,fB:*:J.e/VYq:1Q(_:5\gNU%5(g.e-fBpr[%)!P=kQWO?7J3!Im`Bopj'p9QV[5.9$V8Gp2s\'(SQ>'fG+.gn]\IR[,(mjsL%8@%oAI1M%D,)!3aijL.9lG!-'/:0!E&g1+*27CHL(OZ7OnYS*o8l>JLPM#n$5A/h[@^*HjI_\@&G'\fu_H%ge^TT3d_3);;#le)PB\g3ug-BW($6>[#;N;PJcrr_;!'*Wr%2UQMURXGf_9mVepP)IVhj(`o_iR/VX9'P]Rn,>>Y#UAVL^?@cg]_^%=B+:s9E<phjTl;)\'d?-iek`D#SLbnf%tF_?.0Q&T98LcO#"tZ4RkqYZ6"Bf3?+Q_65Pj]X6@epiE8]Qk4!<d#e@+_bLLTZ/Zg3AU\J[;s3$bRGZ*bg<#GjtW1u<fgLJU?)'F=)u;2#)TB-ZGHKWuSMWjt'?b-K6:/7nn-felN7QmAe#jL1a"&br+4'd\Pq$4o.35VemZI/i0cb?s.#mshs?hK<dg0H<G3:sq<rE4sPEQl.[8m]Ip>o8(R1TCA22I[N@NG-,PXa5"CSpXANU^V9(>5SQXfliQZGI$$-ZmdSua#eV.@jjedZ0BYKW4o`4)bTG/H7JH`S2HkSm^Zn6Y)tLrM'LCHXPMn;4nua(^co$FlY9.sbMV3b62FVVK,M7ngW$E0aQ+Hf,&#+=&8Q94=opA$6LhXm;E@0:BeD/9\?+bC6!-*RV=,>kqU:](O*KVPV,-2P"^&-)^I5WtU#eH*OlIu5k;?><%G\Og?@N]dg!:nKY%oo/B!R#]:SPJEh$`,Y4mFq!41LQ51*Tl8tpr@_6kC^lM_/(kXc-cnoE_sF'NP7SPa7ksMBZ'P1j)G0WB*D7HHWdJ]i*<npMIn\,^./D3d]rk=\p6/<Kf[jm]+"[tg!nG>(KC5^TT6Ik5`d`KK&84daRs>0/nh@p+2Y/r)D(_ffU,o??F\XQ4LFADBW[XL(:EMU#O"r*:VpGek#u6e[E0("9;NN5_BRhY4@TSX#C#[@+)_9Xb>+(M%SGY'?4g!];"d1<fjoZK=#kn^O^ANR1Z,52'%4Y1O$H,K"?*Lg9abFr.G(mQ=h;Iem8X(8XKtW(8'/r7C;u!!X`,5_p,do+b1`<sa#&*gD^VKRa&(VbYaKE@Z7pD'#0G`u56hZTci8Y,G!)+GAf8h0k0Y'<E1f%HHo*gm^WmReY'X;9h%-G#KVuEGE.^VA]K9!S"oEOW#.um5-NL]<U?FP47L$ZZ[F0.=kdAFN]]_7?qJG,pDIqEBb-;RU]MOtAM*P324+Kgs,3C[WUL1'oNRVE6A+K:GDkX,Ni[qV1"Tf;J>I9B7Z>785C=UpJ,iX-bW<W\DF__2^]Pc0V8u_T[%N'^9lHSTG"Or0.!!2rV2F*]RZqUA6na469`9`7a[j/3n14Hsdm&019S,OrdqeMaBYYdqn-+'h12.I-/6_ld,o^eruSh.,Y\J?0B5"b5n^+_rkO#(!!A6LH:e-DWR;-2<`.h[kO\'Pi=.EguT]8NH[blU^9joU^V;>o^KW/UlDg'fN0;:qK1RaGlmX3rPt?S>:m@GOMJReBnB&\,(jMs7=l0+)iT<ZI-)9G3!h:YIqZE7l7tSo=8/rh<P'e92e*aI_%M)ste4,OoaBrLZ(kbc)\TN<f.^U=7`^H$q^/HQT`=8d4QX!XZd^NqUQ!4+@g!#,>N7<)l`G7$X!WQ(GMen3ou\(5d&i<)<LO%YNTMalp2NN`=de?BD4k=#Ye[6Z*\J88]]4etYC1d+"e,'h_m*VsB9E,&G7uI=_<q=4nWFHeSSY@!7%=:q(?FpN[$d\m.h'l^AG!]fM8BAr`kp$);X>L4%U>+[$*@e)[-Fn,NCPrl=nM[r"t/pcZt38elmq8aikLNIj=E6+jeo4fiKbC>4eh[S7JF[!Lb_1DB;.E8fFj^3`.^j5@qHn'5@9q/boXFk2XerrE8kU%J~>endstream
292
+ endobj
293
+ 37 0 obj
294
+ <<
295
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2392
296
+ >>
297
+ stream
298
+ Gau0E>Ar7S'RnB33(l!EBbOOCmKG?gD:>XQR^Rj\]a-$"M70hWi_"6]ChS:p%OK8!g6't2!Gk9eiOSM@(K3$WO4Nc.$Li'AcehQl%#/8b(9q7l%9LHBDb"Q]P7'Qoe8o*0Sn1gPr[]CZJ?%(djUd=NZO*4m_VjhC28%)\=e(9L?Al)08c\s&0$O)YJ9qX@5@O=d1AHO(gLG%^"Y@tI*m/g$o>a1Vo-39r-)-I5i(&G=e9=`FXj9^MW.FMA`0QQKIq+'X^S8#5W\a_KH31:I,5_eh!?r,q.8O?;a&rS^+;5Dp`O>oCHp1.jE8&IHUlNJlMI]DtGu9C!q@ZPK!>cPk9TEKHCmH_@M"Z+ZImrB/5+@B[$3iln07F>E]`.Erjn70s]AXXGO^q<i`>Kq@-I,H5P(\)nS8'=5Y;";&31Ghs7?Ng$0AdGQBpD.,Ll!OegJDgrr$@4J0e/d@d:C"BVa%V%=ql7e;XmrG`?A$[jO7LeWgpp#pg%qhLq?K>W.^Dm`T]L=I#J)/F"37FWd@QRq9%j!1`ou0hai?;nLPLs)gEoA#iHN4_QE3fq"WebT!_)\oB*ZSiRQ\`hu4R=/iPnD#KZHC@lR'NKns,Y&%jXK$P7#W!AC,VAc_^$'YMRIjVE\2OQ-sknk;TdBGND6]`.]ljiuu_BT3Z2Jgq&3P?n4W29*nkgWSQfhlh?p6L/*/7!B$L>FrbF?N)3>;do0dr4SlmpClKFAo0!_pCj9^`L<5c[lb$e0^,0\(B.R.=>g*F/icl_I6/Xe7B,Ugp*W18#1R]#o6mEVLl!MjKn/^BFc8/mC]KXL$/kUuL9T@hUf%.,',^X%jV:`nN.t2m,?..C-lZCB.7EPF^i1bG&U.obWXufm61$C.HQG"SeKW%9*KPo]2D"WOM8#&]MmE`N)(['10MdC]iOeBoL=LI,@oG]7^"j*(/NmQ%L3X<E1N1`[LMcDqKK5>MW@5ZsfoaMOLhj5`bbSp8Nb"a:BY).J87:2sf'Wl*N6n.iI%U34Qr(]:;??MiO*K1G\oONI@MmUq\b33c.cVq_*^X$WnJ)f0V1%Fs/7M_0S])ElT%2:sN-U*MBB@e@IpZ5/,HN'Rkr7a'@Q7,"ar]MZ1.H(Kem1r_/`J4ZSpiIY"!N3B*JWnQV7NpIkXdYq8]^uQA8=0'akdrC$jM;WaI2HiH[!)FT8@Qn]+sY(\hZc1,"-bYAN\(FQ'\7&M+ik1):uEhe4<r&Eh6797c:d6Rj?1!G&@l/UQjcKMbVbPpX^>h-d;m:8<g"=UGG_RPY/">!AePW:cHXN--EBf3d/n!g!=PMRE%<G7d-/sb"=!</=<59Z.bS?EO"rU-EY5qBrOCdf,J7/?-EX!bDhTrB]q.BAFX$:;F/1]A"H,hY/=7]bHb!]U3%XfE]?LVNn$-#g)afg1Ej*o<qnT?R0f:@fu*G58S2HbV2!fkULdQGoe!XJU><*#Z4L"M=a0Ni$W3`b'dd>BT1W.1MFo(p@C*-!Zk1'tT%lG`o^oQQ1JITR$-Htn^$:q*d:$N0choh23<%rg/0UsS#;=XOFCtO[S[52'M8q>W7YDfm1QL"$5IeGn#hQnC@tQYeJP_9X$4BIW@`Tn")\bL&6,CgdRi&OLJ:g.a`P])I:C#XS)\#O]4@T'=20*@6-t-$C2!)o`U@(FZ9KVj)(\a##.ocWPjuC)=r;t<2%@=TBa(6.Ofjg,"mg)(fY/-p">5G\X3NZbM)QlLf@SP`Mh8:YEVD&W]IN)d0Wp?D?+A/J7fq2_3Q@7+8+_*0Y4Vh":.NfHg/*j%ODO:ZHlZY?MiQt7R#&@7S*ZT+0FB7JM4KQn#1.@01Cej*)736U/:3gB32aaeri$?XW-K#4,-+_-%<>;\dQ_G+;K2f=mLcNnW/rO:g3%KDEjf[1j]/<COagrr>M3-%VZ'Il>Ef1jMB)*X'HVp=7k#5gd<JXdPdDf?'43P7aPVeGSLEYVH)]fFbUh8krB&(>mP;WkZNuHS7,]imT\^\[&b-MTnYJs?)Wf,MQA;am)&;;`?G9*]X:6'eN=,2M1c;rFR<D9R\b@Zofp\.qh?@.^73Cjmd9guWCN7p6t#&UaNM,G*lniiV\BO94kg/[F_86Q4"*E',/iZ$l4WXt$n/[:ErUllA2DY$t:etk4rD*;elD>e(h(iH$DRVVj3L:e42lZVS]RG$6)kp)V,U^^ksbDA7k/.%\Z"#2Cb?sE5F%&%:?m^>>)f_&e2`fPO#kI*K5:Zkk?>o?,#3YOr=fg=![8i3A=cRJJ0eWam2fFio2j"T(`.mNMj!G1E-*t%_c7cfa3Vl_-BqN,rW@UnRP0AAY7W,m-s1FYFG7bfNCL$"/GQ!DWV'<K[\ErSQ%_sls?s#84d`:jMIl:/#1-J<-s#Y4mp26P\u~>endstream
299
+ endobj
300
+ 38 0 obj
301
+ <<
302
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2667
303
+ >>
304
+ stream
305
+ GauGcCN%rcn9]W'X["s,N>7S%DsN-qI@rsTY-!8(0sEAjD/7P:Q/jqHp>^@mhD$V(8Ro-9)*X)T^*A[AFSnYipFHIBFTRo5#nRH-"V=Tg@Ian7:!UJE'dKjun2.c@f1a4B%0F"gPGMAH$L$!H23S*L1kZgbkfo$0n66m8rI?9bOtV'EEgTbi^mZi8\5-Q(2b_N9"s7jN&r_N@^d5&,`"i/,cQpH6iV"pB*e?lkc*2$iW;p-Y`)"6YESeB$DFBW"C3kL@r&C,k-lD7gd1)9PQu'`@AB*_H$:G]J$TVK_J2$hPAJn:<+!a:<Zc/.@Cf``NCrKhk8J3(U0O(f8c#>_fi_;+^1h0)]grDD]0Haj[!FjHR7=38mQ=8*]`3lFb!Q?rd^!1bYSTF:%*8Z14+M<ll\fdl`q"apSl-g$mEb#ZL9C*IDP308UgXhB$XZ=-s@)+P.2W?[K"gDYMF$B3Yr.gTrpI29\6;#r"%G@=Z%"18h\_e)AEP]^bf0gmNgh9;"#Mq'_PU&,:%3Ebmfip2BTZ,Ue5qRGEc=.3,ki_RBEO8,:B(7a>Zu0&aa1*K_+,&KeIC-*Q+e>dq,TDWKD/7'j9?<jHd+>^#'kEP06kiZY=nsN)s*ahQfo7)Z!5_Ge>:C7\3Yc@>!D?@@"p)J)>*;UqiK9Wp@_nAt;HP:4WYQ5IoKOnrk=qsHO*ZU@M<:7Aii,ibWMQTG_PFXenY+=C'NSlr!>f@']Ki9>bf(@SMCS.iLh],,?IVECTqBgsh/d]P1tU,,f.HrpJZdDm4S7E=8kTsm.'[S!YS3LlknW7blog1dXl;gX0,R`F53j6Sr7R-s!C'++E<q_LBBV#/buG!j_a)W**Vq&Of)ZuVc@jM^D:=.b(3_IYYQk:o0tS1e\h)*&=P@tI>TShn7hctqa7DKGP_^;0&E+32gC5"<49_>fP?77!0H0]GoCG.0;enq0V5%82OJI/Sdk"/tgR*31GBD*94L&RE.VD])d;>O/-3jcEAU-XfUe$,+31BGtA%m\se4rJn2+pi0Whh";>KN*Bas%=IGaj?<:Yo&$VBa=!jui.:6s/B`Y2!hMO/"g4I@pOM&@-)3g#>3RalLdiVmh/gHhH[ahA-`i%!t2sWUeM[_c'snG)O:/QPT?U`fhZCVGB:tMOqh9rR>=XG=831cZ&#*6+b#`'Xmd%5*);TkPa0`S@bKbd),U(TQ%uVr9d\G&<EDL36uo(1E;B!gc@n5dr=ar`1B-HpQMV`n?Y:r<^_CP)*7UCA2s"@iF"K;0>m=)Qjh$K1+\:[ehT(;,sq?jiH_%(#GZ9b)4mH2PMpej%(gC@mNY)FOt>\"7u#kS&RsmKKFCR\ZZ5,IM_(l26l4#%.=*b"AjrkK!A$cOK`YLc.MLQ9T(C!R+'$AOd4>bp*bF?^;#s1\E!RiH"IX`>9V:IpLInb@P:5;J*lT(W`Vo_Mj$*?`*eqef8^c6=4\WR/((ZtTk#cgM?Y$E/1rOJmC89Al8*_BL.lbj$bq"B@-_n6XQFFE$T2><8-gGdLN30E\Jqr[p-Z_BZIt%:oc+@&,^3KZU!<R[OI1WPe$B&:(YU0&^!X:lP(WN#Di&dMArgHT/FRH;^HaMb$iqkfdr]\dN_kEA"[spWU3C>j9eWk2X>WRdd!1sX_.=:_gTAGr8NiU_MBUVpc[]=k0f)=5Rqe9P(D9So;q6W/SeGG,HfhYk^l5/ifhlc2XmAf'FpD*)$hlFB&]%<pDE>l>D:b6s5&*1"20lPUT6)leDNo[<_jJ/`X5RgA-e3tF9<c"d/+N1OBTcWZSW*))_>kYS]7<]+):sGc4>_Y<L9n3Yie>Oa5(8V*O\="c.&Go!/B\9mcM6XOgAQ>VXG(Zfhns@m%P[J'V:3j=XkKOn[1KeV_>4pk'rZYA@g<U/()f[mJ:&KsJ$Esr1^m-B*Pa+.0MjqaL]mXl\93AdJMg'VNH/*NTcSmY"$(7.A@-_GUaEHm#Ys<q5gPqO=b3E=NZ344laeLi!%q[>HSp`NWlV'a9.bLsJNqe;6(atg[?)4m&6!fhBd-Q'm;2fml8!1C@r-^A=QhY=b''JW@%>5^r:jYral7^E1jXkBJ\jL)*,+=+bod93@\Iu0Ki9s*`Z&<A.Ng!.1>I!ji7l[1XMA.>jM#ss?f6%dGo9sqAMg#2APjt6EVeh<hU_.aGP3?4,eDiFqbXu,T*;A7+1l8(k7c+5[Lf'Ja=BLf*OVnPf>H9`c180>8n62oZVjR<X86j\r\'jP^-KeTljVCa22>C'bRs_&`.TsM<\H).Fj4<N(@ES,'bD.G>[1h2JW!1.eKh<4UVfV>Z6WL,C9%s@iql;]jDOA#j0]?^cr$21H!asuP^YJV;%^(&bj_39*0hY"sUqn_.#)*77U\o4X^puVc?R`7NNqh38g0;"T4rm\apKUGk!!U,lSE_gO4"`NKE"E,6G26ZG%7X.LZK/#1!iaDmgC^eK:EO6XL](k8D#/'P5WWRQ?[/`NrkBG1ZNCS4Vc0jkp_997+!V(jq0H%7[G,qmH6]#9R>0\K^"65@&DPWDq,Bf&2%e9bgn-JSE;X;gpbP,BG.AbbE>b?9?pg\&_'#k41)dN=jlnD?fM.3oI,n9qTf2]$M<?$^]^+:EBpN24E8qaZb"4DR;\fX!o[<g?&:jlLgRk1?PCO12&tJn2bJHK!~>endstream
306
+ endobj
307
+ 39 0 obj
308
+ <<
309
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 1975
310
+ >>
311
+ stream
312
+ Gau0D>Ar7S'RnB33"%FYko<aR`KCQ26bBeEJ>26-"+?PkJ<B(uZRdRO'uq0bhfhUgG&/\;ZZ\rKffHd9lZYOMJqnj*Ic_#gG@PmrOTP2a49ZXd&B:@#_t`TtbXiEl8BJq9-XiNu!JT@A]JC5">MTf[,kSp6#d1di_67cA_(T7p(F>F;SkjX.3+T`F6d>$YUmEe7$c]Bo#/B3Lh(fSF!ca<`0L98s6o8kWq_R60*_f/':bqV%#Y5N(T"h%e#D(:couFSK3&5Xd,$aIj?^=."LS3>f&6-npVrD_tB\r`[Z"elCmN<I9YmOQ(7TVF>6$BeM_nN,l-$7XP77]MfO'a0)$FsPJo>qdqfbpL'.!5(+IG6=<JKMoXC2F>$0ji<fC5q7b0a5P>.ENMXH)5HM)3]#f%2W/J?+fD9*roWT:iP6N`igX(odUnsN3d#53A'A16U5k*YCBg)5D`^s*.GDPnbD8<VsSWOeW(oVY'DnH#%R6<DeAJMc83,5o-(J,BK%TNbFQ=$(aX[_)LVWQ4sPa`Z@+qs49+&)qb*@#Nb4I[<on_TVrm!8ir)f8:Z/-dTJ'Y3(R6VQL3F01i*]1@*W:nQ)5+A'''&5H(FRP6!:Dr,]:-2JSF:7K5ueFuhNp#OZF^W-K60MEYSVA4`-7sQ1X?F%J?je@+5t2tM/<`TY;<%AcO'ibV9%gR&R<"0N.+(ZPK<4E,Rg4L0g%lUN"NsOm\j=nUQEDXRUjp@5-]=R@J]9Y1n'fF[`1O#c31'Jc7=s#@?b.a))%P[[PKu)4"nDmUN$]\6"(kNGZquok]R%5#U\uuB(hl$5<u.:7:G*p+2EKM3I6hjiZX+,0IXnGOgEJei,,7$of#_bLoO]'2YHHg99i1b\(QqD<g1?gHdfc&ak:2.XG`EXX?AjtgBh`D&X?!i.r9ZmVUS%o5/:].4E#?3^bI3=22AV%()7`:&A"mM\$gUF,IrD#rM5+&.7m!k#us5^F=b'p,<A<W'ifqjAO!!!FF1Yu$;lF+;2&7EXlD:mN+-AO1Y!91>pC9\P[J#(HWQMei2:XdatAg>#TM]Z5O(*?i'b\/+Y&[>7Of=(dd!YcP8\d)7NFXE8S-8'jX<>+!?Z<VMa/@DTNBb/5^1VlqXPjh7q7&q#d$O_HGZtg=dq(h!c-_Njd9276KLm9n2Xrf+ZZEF2Q2;PAlgqEjY?.dPk7>&*sCYh`!TEUV8s(-_/<o:@A#o:MP:lX$njb`RNZQ_4)IB;;^Wk7nY;F;To!RUd]ER(+LGe0<jN(,m3;.KMX9YFARj@k?BtZ\"5TDW)Vces=YL4WqUA1g9QH%[eJ*p4[W&8/7;W5[IdX2EG<BLISiSDlnjb=AOAY]#XXUo*U#i#J[%"G9n:V`AWt=I0%Pl(WY&&q`Pr83?&o/>LQo665cNc'KIS-2i#;0)d=Nk9Mic"9MlmQP3?>L=%./:)R^=OCK6I0s?D-V0moslef?![KD[7c;Rh=#i>lpVRALg%(k$eMU"duEcF+gK%Ho3p'<oYF^.UE9Cu<jb+(P5\B$9g^9h<jr*dUVPG2&quN"0FY4K,eb-:GpgqT$64>j+\L'<+)e@W4BE:Fi;9c?m?lF&2KoV)kaS0jiUQI>",71-\\)i?FtN(1o4LV<qL<E0)qV&'M\_OO`_T%Pf/TD&\As>'b:5'80e<>]\DeLus%':hoR55=QDUAE7/&cbQ6$Q*pL41[Hc]ik"8>+@]IfAO>E*ITh[G(:KO/^`VOZa8i/]n%ob4-?miO5CE`;)U7/i"%gU[]8W,7=I&4O+Jp-.s?5mmq0i*k:TG5o)ZQHc<0+9MgQ%"DB]'k'+o=d\=V+K%Tb/[D8o*.XIm;[oIEHptFtG5chPe:CEnrZ_jE@OM$7QTpTU/5%N4:e73kD-B\lLI.]36aUj<0P*&IN\f!/r/)qWW4.$a'[You#-iC=71b&Rg.tM=fL`g=2,O)=[m9,[ci9n!Z1S*er<o[>BZL~>endstream
313
+ endobj
314
+ 40 0 obj
315
+ <<
316
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 1682
317
+ >>
318
+ stream
319
+ Gau0D;01_T&:Vs/f[B#;E&iK.D'7:i[!,+)Aoa6n*7I*9:.DJl\?TU8Z9r<'s1Kr9L'3E"OqoA]]W9TN\"@iqU!U\924m/9nFIL.k7jisj!dfk\1kXIZgklf5p[C`_2.m:IGt`kDP+f.<R14<>$6&SQdCj*N^qH8!ps?D\pt<*P!q*ln<$MW:`LgB1OtG/37-LoN;nQN7rRo42m3[95'l:K-lJbg#<uHb5##V*nskJ:9X4aeHajTtZ#P3W%dei53lKLMFO0h<e6aq8We5$g^(cX+KSB.o"FSXh*7aK@5GJca9:_`;P)K6!Qno&HVpO_;:&r"`DipF+r-]Ok%RHO/W,i$rDZ(SrrfG`$NBq&2e>?1tiSA4sHp`=OP:M@+*:^H3)(?,2%UW+UNeu,WnJt(SR>BEc_r`KIgrn:l'mV&3hE[OM>I!U\=FVs_4PGJ"",%6LFT6QHVeI<klQArb_5D7t@`;]<Lb2/9%t1"Z/6*r.+b,#d8F@QCk$las&sX4fi7C75o#]:*_5#c"2_Fr)o@W>*"2\*:gY/[<'>5245)">7M^I0NlUGo<CR&p6d[oFb8+1)3[J_5u0>h)NN4p>Tgg*kC&Nob=\Wj'mKOl#;iM:n<+/4;)BDV%lNBB1TC$Ti9'\4qaB(Yc#dldglc*::krk1Y]T>T7@BM53\:\1'9q5FP2s8!Gmkq2V%'eEkn'//D3O.Ukaqg,p3n(8oO)"`psdb'Gm1I9aCJq`JYrk-VtCJ,ZVLhh<O;rm['dG4g@\WdSOfXt[?'f[uXaiNdn\C;mS*$.@cR!'N0hB)=4Y"R#Ed62]X(RNCUBARY5mGI%7qr8Z3j%Z$J[h,EAQ(XPeUsa1V$A[niIsnqEdF=CgJYk(=AbqA,pC"FJ0Cnht#qX?b]fr.(*>k;Y9$n,V*#t=742sr7i`gu-6_K(0cqk*,Ph71gKkt?MeJpm]Na4sd#mYq*jUu"Ao3GnJ2jgsjMVJo.8-EoEU'-s?7TnZRJfbA;BLUIla_QASXWtCog6]u;n0HFL)),&fH(0k.IgL?P,;k7U9G=b+=TZZ_c4WCSOlZ%q4J+&`Eo31Ck8+S4iq6RFL!-FT'@.\50Ai.Ca-ukM2HZ0_9XN+Cl8U1?&DPiH\7=P5*Zid:NZlI9\!f<h"&U=&g/oWIVI2-U$9h0cFm/2_>VF'$#'4=nN?6bi-eGfi0eUXIRFga'>#YtPm7+9o)Cb'^91ch"Z\qR\&RRl&k;1oNS`%4>_5H$#*(K\T"l;%oIO62^\7Bk7G6R+&p']%7aJePl=3C7FasD!AZUjFcW)o+\.,@*9cQP[->,&"V<hd4(D.rOZg&'.%5!'+@OEeX:*-mL[W`3j$:J7(]HObOFR6ncqa<<jSdcqI30r_B#V%Ui>-,`K$-^E`0ms5cE<b.WZ-,":i!i@VkSF7Or3Q;+A__(&>.Vj<@,\B\d.S;ID[b_0.52gjK'tSrp8TrL23$cC*G/L"[2qYGhiY/u^F0r7KQb\niJaQ92o@XY!35Zi>reEfde!3\PCjElcZ3%G%[D4tTN8.NJVNZO=UWW'N0mU^^E.hQ!#@IIl`DI3.nPZhrac25'NV#Q\*fE#p3k8p$cZ,h0ZapmH6%q23E+2i.0CbB66l:uQoT=;h+fj,8TlQ0+Q4<qR["q)>-*`Q`>[,:V.e>a#j?'.]&fgfWdlbYX~>endstream
320
+ endobj
321
+ 41 0 obj
322
+ <<
323
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2121
324
+ >>
325
+ stream
326
+ Gau0DD,8nW&H9tY(f?hVZsiM$h4/f>[6TG!-s*6HknL+#lj`JnHX1t-jaR0QY3dK`8HQ"H83#;sH01N-Akg+W5H=a=.DWP5S6Sm`-Hm5jD.:EL$I38hh[Z(r?ZcLiD;'j6q6i_cs"*Tf"PTqpg,>XU$`6:1i=mU\rj[RS,0f/$(N@A14=`G9:"+`bh/T+[#\O+Pm'YR,:Y`TgaDp`<Y3uuF:Q+TcYUT6MkWa(a$uCQ`T!.:EG[>,P_-uk[o3;LP%WU!TW&F;/_?=VPQA$Agi'K,3cc<?^OVaqlBH![Yj91nuGMRA>RjPHfDCLH5<^]b2XB`W*Q.StLOE-Z+fj.aM*Ju]8R@HTI,r.YZif((qUA,mlpb=;Bpb&&EcqID[)2jHh(QPqh,'i)hQTTuV-ce<_a5qkDeH?ci/g4K*Jq]@(7"MPm/qFaPUTCOp*l2\>ET@5uKVu)>4Sip&)(tI_OiV:LI]X\)[q4MrmuXlM<%EID_F0Wuf[,conj5`ELepFT^W.KjJ/<nfi%^PB.\_kJg&tlYI]p0r3EKn%86]l*:L4RZ-h[!>4"M<@aM\%H8Ad'82I4BY1GBMgZ,&:\#DcprL=p(H!LBJ-abA?dNhZk;EKGIt<I0RbQ6FF,Htn/ORH/S)5l@qo@BFD\N_GfgZq;SgooH(f3qK+0(0CU2m\g;6aJS9iRt;ji;l1O\K+'^^<#LA*g3\!;U'@!V=,2PtgonPj<#`i@GQB*d(*ou=!hK3gYm]rN^X#,m4M1N13BLMl&+C5=*$VCV_HS]T4ihK1?HN=r%M(X,8-`t\gYc-GMYq0P=eekjYG(k4`HUj\/Ja6<81U!B)n$[]$9iGF!D='P6VFphn8X8/(oPI->i:X5eK:-V@q/o2O9l6F,3.D'07do.AT-E,*=c<tpu^s_QbdW(Jjg2$$i)->)]64po'fsW=4_8a.#J08"Mu?O6emko,+._DAW.XJdD=m_B]prhKIAF/2E[fM7B2A"_]Mtn7niL-9p!;mEn8lf.IL'K$-Q16UA8>sIc=l2p$C`%G?<s/Qa>op_C;E+S3kK0A:E#a9RRHS).s[+!Ua.`&Q@Ykj:kGd)is]T)KYQ>i/[n];i$O%X-IF]O@J37b3hnKS,OjM;:[<ihC!m(;qe5P"3a*;Pu4Fqe8s*I<XRUKo%Ri6Q"JRP4ZHair2mbA?I-n]S:Au.(Hc96')-gqpJE$5%4o[L^-/WTVU9L6lRDT-'&^r2k>AVb2A$cCOl5>'+n0'b1Q?NEHY@PP2(Y:oN8n;pFLk]./[_<5C5!P8:"Qk,p3[n2p02l%:KH4.Tk#`m.d?Q/P48Wm?)ss):;9@QZMUSt(TbogZPoU)6i=a>R4ba6X0M?F>?B/`=-s+C(F(es6?uZROJ.l8[3KIbBE>.CfCG]fm7WNT@NPlY\H:a/#$D*.C8HmF@45N2@X[#\[*"EMm9u'TMV@7'`-$o&>mG$-_YhH&18g_qK"hefa^mi7q./]VP4N?HUP\c+^J5q`hkASmI@`.kBA;if2Z>q<T/FP*Z!8'7^Vk/o,Y&6)Ba5G^$WYjJ7Y_3)54P<&0(la$F_$t9.V0a"bW*X`SjfYCs-FO(Z7QEGG!lK%0SRS6(+`4,_g9]g"j@f`Z*+"E4'Wb86<-l%K=0D(UO<pT`q/u`TW\G4$9fcPRLd"VbqY%?H>8c/Cq4"=>L^quM(iI5-WuI?*3@LV-`p"1iLG=XGnq:D4k'eZ%e^b*b[^@WEus;J5%O%4J!2LX)3j1-4h=+"TD7I@2/68gf?`5q[bZ(,'ae7a<o6KCcTRm?)Mdo/jTk^hX#-La1ZeCC/YGha*g2s+"l!u1W*S*1r>rm'Ai$KOH?[C3U@I57eA3j./Nlb?np0Z1+<XuHmJ36>#,\Sjc_;bkIUJJV1@4hCN./%<4!W_*IQH1C_*Z`>.&W#hQL@]monI30+H"Edj^Du>9'Js/Y+T[(jAKN5I>UI>WpVX[`S*T1>cG@'B_FfOA6!0:c8If0jc`^PN5GB9-Cdc!;DkX'4Q>0h't&0j8`KVIroflJh&AR_c'f_KiL]XGkF5YI6sX]]YArR-rsgRljh<2^PDVAL.ri8"kGL2FP?_P<Z:P!^k;;Xop;ec`$Q@iVKDtpH5Fbp~>endstream
327
+ endobj
328
+ 42 0 obj
329
+ <<
330
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 1686
331
+ >>
332
+ stream
333
+ Gatm;D/\/e&H;*)EUtkdku(QH-!ANT!IJO<!a3pQ!rAT?!_/o$/i'8bFL*76J)?BOj4KMn(RpD;'(;*0ceZt_I/Hn:5@4KiR_l*]$8d9T"uISKV!%5.*F'+Y8n&**'"@``S0['\_X=Gd<e.X4K.nQm)FG&J<4iA&bqJ8L>ICP$aVFa!B3]0]=V+9"Aoj!pO!+B?dMLKQT4iVS.#QEI315j2]cI%??L_0pQHU1P]P!*2#kcRT]!8SZ]0guP@hMp??Cd'!Z&a-5C<ttc'[)K7,V(N_V@8t]k1L"<M1,X`K9FE$,<LLL;&_19pYdef,"`e#lHC4Dp]cubHrqK/6d^qZ;p01Oa9).!X5sMb6*moV]o[up\T6I9jG>X-o3f-+*P2j"B;7O+PL,#m9+%G[F?LbqOO?]/].6?S>)<g1']Y(Oi\5`L4TAqaVW6<K4,=k'7B'([P;)i&@s!T;Qu(i\$(5\,Sfe19-4N5=WrNM@[,u>e]<@ZU2^UBR>qB:+Zucg2H!W)5L6f1YFV7u2T6`MGs''X?nRp\f#?K]c>7FZ(f>%e]QtZYfjD`.>"`.eT$I+/i_/lkl-0P\hEQYpkZY7]TPiX.N'Y6#cif7<1W*TRYU0?M3<WT!(dFclD#[Ne`(@k(4Tad?CCgjLTZ#N0Fgl&lP;::Q/[o8!Zge(SnPH&bd@8c!%Fj^r%Ft;Ec2.bdD(`9?W98o"YR?Y32c3c[T=h97UHtC54N1QCEUQ97;-0,H*?YR=LA7O*.[B?_h$%1g'6C,]To-X<7*_N\*/Juc\[D[=[!ebZ+gG<u3RV!aV[[`hARC%..WOD<D#o[6@B*JlO+H$m(Ks;V5__6Gt8(agrA2iF(\^T+c4;DI8g9+V:]<u-$Ms/;"<j)3(\3=P6<!YL.+@;!?WbO5FM=PYm#?mHEZhD4Z[QC-u&E4.k#>,[X,RO@!&rp2E=5"@J'&pqT8ks3OM%8el0fCF-'2Y3N#7;b38\0Yb:crn4NZ&1!g'LH)W?#A+<g,M16pScNe.3On,;Of\Qj8Rm.58oQCg2-F>\k<Hn.a-#CrLU.b-hZ$*4?V$O6K:U:P8#t.ljh>2sAKeNp)5g?Y6Z\lFfQRQT._t04uP;.>;>ROY<*-"*HF?D%B+l`!@feXo00sH.qJt8!6sHD<>\1m!(KZ[,t+B:/Gi+lP\7YmkaInBobXN4]F;*Q@?NIb`8?-B>kZ6F8j\]?Lub,q^iQV1QnLH(hK*T*Q,rTcXq:Sjh#GE=a"^D+4b?@ICqp?*EkYMZ=_qOI->gf@/?US`s#PEl4;Ol!j@#8_8</p.g,8,@'XW"o=@'A\I@6)eS]?3UQ`tX&1"l(?)Epm`uj!Z5em(P$p$_I3k@QMWp/C*[\u*WR]m\2<FjrHrs.^Pq:b8rL"(;(g$l,^%P<Rh"[(9,MBf^d[!1;M(h#MA]BTmmT72)AR]7+kp]$=qH2aI`bIW8`rnqlmmrri&o<;6%hoI+hr@;+$P2Fnm$()"cVH]PfbZi3%X>DU(7.g9`5LW1b11+l>#<0a(bHeVWJ;6Da&#$E(_8ag(QjYHeH`>Cs;m%4FGRlSsDA)q>1t<=Ir#SS1p(`qdi^<RogNRS]hknGrJRboE4bdPePT;Ql-Mi0RiGYXnGo06p_Y%;b-f(3ilUeRr]JeAEn)FI&8&el70?Yi[_M]SpFJ3k1_r+n$4#6s~>endstream
334
+ endobj
335
+ 43 0 obj
336
+ <<
337
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2004
338
+ >>
339
+ stream
340
+ GatU4gMYb8&:O:S9FV]1;eMleSLOJuVG:O7%FRX5?N^K?\J!TB9:;TM\3^,-B9s=7$Yba%Jlqa7b]*:"baDUSRc5F@5GL<7he)N?%4?&ACdHig2U-.(H?OI]f'N0H,@GDqc>:h9/P_)Y`DS/S`k#m=N!Cu'%YN_%1>]aVV:YP!.a:@I^Pdf-V4bA5HF+$GK",qhZ[ZZ^9KhB24FCqcET*$mq98QkDTA&W2d?#h/?h//>WVe;CD'E^R)N>9W\1Vs;CVf$T'\S`IBo68guTFXNQY;'/@<>0QH7tm#Ee-E:/I2]b#^p,E_5!b(N6BU_`2S#*fV"Qn!$=tE<C"7@=4OJ;d]@2GF0bC9^]6d!sBalVc2aPJ\\tJ.%#rWLbP\S$&^L;6rDB9<b\EcM6ac6NX<t'E\&]_-sVU)m/rA+Bp"*BWj)GuUeN'&kX%L@MJj6s.fsc:/Lco`gSH<R]5eomBeE28`ANG5R)oE5#1u>_%#YL;34$.Q<m(r>n*mSc^<]J;(o_(A?07h[8#DcpVPBDA(u4LDE.!CD.RTtY.FWc8gdJi'fo]t>\NJ0>b>,lgW8REDJj4tslF!ekkn\1O%P$k2I&IZXR3Db3<^jT)Wldb11t(f#W>[_dCRCr&!3$\,CEXqMkDh/O;&":qWi.I4Pj:HoO3Jp(Kp']APfBV`%Fce!_'<@m@bG:k7,p%5?I>baObf-)T-*ns[MJrqV6Wd)5p;MD?U[<$V'`>,DnmoRV0&t<A-D<uNuZ*:QV+_u]uFri#[.hHLegGD]jX`J*-B@hf;e"mi%=S0:\Po@JFe7Wj"S'Y9=mHWbs$QGICORsp@`+Ld5Nri@-CESVQWFDHs0%=feFRm(@*MuGeOLmTLorNeYN](f<G[6Z>mY).o@LAG!i&7'JE@@/43=o-`r'CFqsSeK!GqLo8=:@F"g"$[rYYlctVdI'9ShL8\ie9E]_Z'4/2=jno.,<?lBkd'fg_CLkV*X@OAgGiai@:C/`.U`K:s58>TXnnh3?'8#6c*emY[0KXn?ZX(7.IktXKP#(uGuRM`brU/I-!;86<f;!!P,@#BM&G@;443+nCmkVY3^J[_F7-R>^`GM<dL&"lCg%'\fKJ"%'N!cX<!`Ykj8c0LP8S-44aW)E^E;R:En6u<4Yc5It)nkfA"0%E=N<&-X?oT"o^d-f*r)oH:$FWtTPcIp^Ra@,k#//Un`('\iPo<DIOiaW4'[=$b"HuGgHNEhj>c<)Y3ZF/8>^1@C5=$rpi:>P#E4/^8?HcHJ)\`p9"hNn2H/sN6teO?OmP!nT9g/6,\0$H)9J!E:E7u8\uS[(E-Gam=P<3EMK]N9[;G,Fg^;fp9%g5kZ)7in;!D_.oCMgca#qI@&!i@$WUV&^n+Ut^bbrb<?u6ZJrsfQ\F9.0E8-7N_jtP1@rY0j3IeVJ\R)rS:\ZmP]r7eDeaAf7^A,OtMq,s/WiDU<kEk/4?jg:Xi#l[V%D:m%tU]BXUYFK3j)?OpOiY<JNBscJp[(X:C\tJ#p!6"Eb#3FU<B=)\clg;t],P'9m:l.`a/&R$u:0im[3OrO4"_?!'PO)]lo#N>[oufWb@D1u$bt)<bY3"dS@.kWe7%kKPYT`5#:6l'r37HK42_KimC>)AtTlH['nW\2k5"_sdO_4rf*_%54[opiVmSfR]),1/,'Oa;-=1(PRs9^=Uia'qJ.G?a_s`pbZjaMC+P#oig<n'o@l<D&L*o-so-]NCO\+/cKd5m(pE+g(!)G+UI;Q8.q5\l6<g62djV5&6aobJmR>SaC]ODQV5<;EJMJ.*AFEf+(c0?hW.dDI6M.Aq/Wjk&-#%;9963K\@(m'iV2E$0\;k2:LquV_tKioiQ^@eZh'<I+6U>;@umAPa8M%^4=F@B!c,esj0n+&CUH2^OG9*@Z00uf(d"?soO)a-B<u&!H3O0ih<4Q8#e"E=QL9ZX.l=d0a85UB`cXX',^+[5V1*p)I?1A>@W1=r2i5S.OD87>dRZ-9XOXJ7R\8p35JFo%QN~>endstream
341
+ endobj
342
+ 44 0 obj
343
+ <<
344
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2205
345
+ >>
346
+ stream
347
+ Gau`TD/\/e&H88.EQ^%<8J>.SM^<6(J2BpN!bp5&0)A"%b/grl7]$l^:)XPsDr6\?CcRYgV_,+iM.6#::;#b]HVP8kr(uuDR01)A_=L_BVure$:lfiT3et&hhT]@i''b%(%.!f/$UW19nF0UVo`A=cmW]eHd1@:ii5TiBIQoiJdsPJt))'r-52ehKL`IjnJk\6D5(M$.(`d?)J"lIF,CbLj%6^&2kj@5&mn,dcb;iLYO5I4*m1F*.*H^>XFkn'Q6Y$j;Hh.*"$_dP9T9ebTZ2fC&$"R;Z<[n5*iraPr!plNuQcom:o-9dM$[!!%N0TL$MO,lH_#VK&_A8Q&TQ4E_$^P`fLF"pVZO7pem2jRp>5o=Nf/PG,]Te'a"W-4O3p3-aKOnfmDJU&u4G(]SBk)8Lh0^@\,e6`&'u3&o@!3'kB_dGOm)KA$6-#X)Q&5``#*slk^W,ap4W3LfGSseY^-;AYr6=F2Uaf:t4[Le)56>qe,^Irqo$BX?kadNS-MH7=S(9qcHR//1%>OBAMD,Tf[dAaXE(F5%)O)3gLQ=)+3lEmKW.W1KD,&rNW,&8a6Mq9B&5n^'cX/\gbR09:q34g^50TAq2+o6#AU/;*j.+:"%44m:q%fKuf=X:\N;_9n!>h+B$("K7?L;Y'7_WNa/$A;"(MKGYbp$4o&pT>]:65(JAb:**\54#LoV(-]?#;AO\#bd[eTK5K#Tp82T/aD:L:^F0RU(ZK3W%@lYJG=gEkcCVXC845.6jP[%XZUc#=1LpZe#=q4h,As0WT8uib\R!n0CHC'.02NDK`j'fm+Rf!C?F,&ua3qcAFMQL<VM2pnU(JN+ijQ4Ld-:)^;FWc?-jim*[/tf%?4@oThFh)BWdRQY5c1=Hj:%(*!9f),4Ct%#=g\=8=IL+nqt:!_Rj$qG2tsL4Y(AMnUsF11:?,$GT__dGg9hI,e=N6[R<E;=-D!Nd%&))-dTBRjA@o%(sNg%CPkD[foTgqe2;!::"fP:31K4(]7$04\-1,@r@+0i@V-s'(Cj65gK?46WN2YmGgMY=YBMpRsWZ*Gk^cm(V'.bQ;hh:OPj4-o^4tcI?+LoMq/2rDQdr;oOC5EnZo@$D(Gf;/[B&M'M5.1!$IclV7FRs6&c_],9noKfi!0!9sskK,;TcV*P$K9Q;>u*.T:K+2>+Dr4]@l-g22^7PjD##X_1keNYNjHnUrLTatoI3[>cV.m\)'#C!#MKGa_,\6@lMeh+$aURf8k,m'pIeK\18gXe8PCLI4e'`:Y>/kn^l\#D/gmn4a,^,_D@6\Q1-d(SgE'9IH3`JuKHtbmTK!b&qrNP"8;Td4l*IBI+*HGjcc+pH%aeaZA>3*8pcih18GdP%PGk/BSSoc_XM=fH:Sd%b=W@l<JR2c)i70E?ABq1bU$`[m1Wb1Y]OEbqu23I*4?]459E'KZP?W"W&*NRKL/XoIt#,a]3/JSA0E!Eq0,\4G,q9rVOK]*"QFb^;[+dMEuXZFe-SmEQbY0N:>-@\P?0Br6t3!b5g1j)I&fVQU-*[o&t)cFV@t_Ps6lr:U!c#gAN);MA'DYmVc,GO4H[&kh34('&&A,LtA\O@V5rCG!ClV'#tN,-?U93?(mCqo)crB8DlO@=bs'6?NrXmq_^D1[/k:k:2<tnA!^Jp]<H2hQ<DJsLPHV"+0SPjiSfriQ=5iV],AWoSEJOCA5#Z5Cl5CNjbmrV^$;m"XN)sA>u)\35,,WB2l^.$/>J+t>rl;W14s!:UD[u];_mCTp!QdWpnHj"o*PD![0e&uYq@/DemaNs9Qs7cIpGl+X<CKH;B]=FO,p@S>PQ15764"#jooP#Xo>fFdO:,VL/gRKWcU`=KDr$2L/C+@,qV4iV6iDX2>7#."k#hLNN)n,B>d1n6X9qrC<F,UhaPYn*bcbck?#4F36U@%)"[;6,pUu$e@[2#0X<*$FPIWM3#J?/.ZpZm2?r=1)P+$>Ik-T!@Xb..Uq:jS97D#QjpRqLd(,Gs2JrZh2K;$8LcG@MPbN8AFqLV(1D)Q&X@,CW./F!]U?bn.D8aIaaeAqF<d1)p(nP8]N/2DC]i2T_a_Ircg<ck,9:D7o=WO;Sl'@,He'JtMdk)8Z5MDdAU3bl>KF8ju7bo9ae)a/tD)No.[K'IqTZ]XYX4$_Dd3Fi[G@mkPR=*FlQKjQCrGKQ0MQQ>>CX\0e$R;BBbVV>"H'alX#B*[OmlqF2n'_~>endstream
348
+ endobj
349
+ 45 0 obj
350
+ <<
351
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2670
352
+ >>
353
+ stream
354
+ Gau0DD/\1M&cV3*0ecEl^<.C7q4=</dYiM_i6*FOML6"DXN?aGRcMmib)1PUs5%CTe2q4lBIh,sbiS9<c91^B1N[;`+34AQ'L[Eme(\Yn*)>NC3?Id*Hp^uqZcBCi,VfHV$bH5Z$R<u?B`G)FAqJL6c974KEBr;l=Lb$?0CNiCB2qo6/iA'=;d%\7-CfijM4#X0^S(,3B`+(IiX7YO/`[/@..CIW_:l4[IF`G=F<R)BVOrPXB?V6%+.0<Wh)34j;*8=%Z/k;[99K%-dlQVb"5<TBXd-&WW%(rIPJN7VSg>Sq13Y*u9%?:tSq!$5e5%irV:$e=U+B;3FX(uqbH.+qT_c4/=8=q(F8(#+Ms@H_oH/"s-Pqu)eLB+>b.O&/%dop'b/[JI9fC7lY$Wo:0m:J:N#^VG'UC<eEbD'&e6;!5-IO8=-?:m*45hXOaE'?T3W2'19ToYlH1QB7n&N)LDdP/2Gg&:.R_th]dg\HXUBJ>?$^/[F)hk!KKf!*[.1Ao,??<o\"jY3gkSXiDbsb"E4KI^1=31Q@9%L,*Cf5E%%k*oFWT[[+98Ld)HBJCB-Zb[c0jR\_4uekN>&Q+k-:ntUK0\S$f32gM-r[,fZ>+O[OYLoRM7TsMh2?Aj_-0]QY`Y2,K9<S1fT,P5I,r<XF+R`mq-Mhc4eAq2F.=qWr@@HBUkgf[Fon"T6ih@g-afc7:G:&b4O/38fNE*J`*Z<pM3[D.A**398+CB"\ufM+_2!jIomfK0Mj(c0dp7051O[Ud9g`OG<pCEXH8"f/$&6kq1)UCj0?P!T,t^g"+/_"f$]kWG[;'6E*D:tJLH?#\.<gEY'IA@6BU/ZsJdQ<[F.$+Y`<n0@*!Vqf=b@2e)g&HrcW_`&8ue\7+>K2a\-+jDkc?XC9,pg:h_"9tVdc3`HCGP&(7uUdP?\HSP8:I,61jVHLCH.sl>6=u>&>X'3GHjr3^7`>CG9rW(4!SIpYqhbHL+/Y941th3)S7"WV\r&e.H3#30dFIaI<oSBNZe?^uOPJ<b<R_W@E*3d,<;>c-#D1f\/I&,*U4+OIMp1E/Gs2\Zd3V]0rV$ghm`.0h`%)Cg]s21(f&@6!(C&6#D4VMF*TX4BIE+F/e7>na"H]GAMjTDG=B6dU14d)O]c#6I?],2+H`SG,LP0Nbr:bB]-QP?p=#iI,K*6i&;\r5lmAe"[)F6\R%DXHh%6"BVe/-dS[_Y(-[Ah\GGS2N\/`8GgKuUQH_a_1`>53XN:Ke>rn+k2g+PE`Lu$3#,@d[s&'rLr\8g(#-^N[=_J95h\d]-o`(`04[%/j#Cq8/lGr$_>fM!W_2usgLLcE-,ZK2XW-l4aG;Nbldk3HCPf$-OhF/!NrYk5lJO\#n7EPpV>bCo%gmH;LYtFPJKjK./UgBS1Ts3Q*[$s#eMdNH#rsS'7VM6Tp!Yut1H]$'g%T2(=0itA!"L852%>_D+7^,Q=5k$\KQBFnBggj"&\o$5L(:NbhLsE7c"9'T-CFgX^@UonMKWb%d^8@BhahX<L:a>CL9.G)1hYeCG&^@U8rN["2_72r!+tKeH!emRAk>?#g<G$"s>?apo(3sZ<qEq6JL><8E5sqYuV:)lVa8CBPjc4q1kS:1>hu]Pm;%T?NVpP3,m@;Y'KZp]"Fs6^&)E@g;*U_B,YQ'Z;'1E@-')>Eff,[P%))M?%;'jVk5[a4X<`Y-5d<LX/MaUQ?Ze7[gF<,g7@1I:3<UO$=rH/@B/,XO>moX@`JAnY0g*VMWqgbOQ[%9[WV6,k.,.4[ZVPb.g%f+!=Pmrd7$]YXH%>.FJ0]+`0g:n[C^K'CJ7&c0M"(hrr!E(eoYdZPR-su`h"MUFZj'M.)HfXZeOO91("s+0LlR6t&2e37[%mAg_hf/K9!nb%&F!iqJq73X'YVNL3$Q+<%]"\#_HUV<@H$)4JptI1mr:T@HqlfJ5pK&PoZo_aoaCALp<Z,s('R\fi?f'2>q6NAr62uRb[PHT\L&en!.$mR<E!+HuA_fWARIjV27^ZniPMaJ=Ss3hYPGqIDkJ+]X#Uf>]#JI$S@+sh/dd/,V_'l)j;h<S"R4*/[(e$V\[+R)p[5<X[j$j8]g?DSY@ipg.d7GD=jB-$e8&c^MS]d+qIA(i<o025JGVE]5ogKS+]8XCr.E9V)7e#EsKs\u-_pN86e^APoU/k*=FIh[-)%tZ;1d`)-5dM8pQ#ILZ%9f/\1Z6*ZQt]EjlBe:^g@Pd?Mnr"9BZ$)<0RBLLF0k*3Vcnt40#`,:3-6Tt\:/AnQ_A^)+n2n(\UFDW1Qo0gabhR7"Ve)C7bnH..$1VM15uO6>I79Sg0)nmK7#UU5jHNm!i7Zud-8Dj]u[%48s7HOYfH)5rET&LQF3V7B_f/gch`mM]:R&ihd&n[4\t'";jHN\$,L/#._9.[C"1<#f*[u>d7PjiXHP&e0X\#IU+uTiA=DrC<pd-1p$Jrkb:aIr.69="D64S[q9#*]$&1`kg[oBQ(=YlK>Nj"oOt*gmflnrZpNp+s'D-P*MrR/@e?If:=ZqcF/CpA3C4r5\ai:(C:!G`=#Kuflq<&e,qKG0+?pf'jrVA3g]9-0!)9s4^V#;I.i#ujs-s3kt7llgbPoD3s5G24Si,%1Q.@+Rg"/d]U\hBDZ>eB[S%9_2S!O/,0<?.G&gcKWle]Gc\71/\MFd89<rW='cOZ3~>endstream
355
+ endobj
356
+ 46 0 obj
357
+ <<
358
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 3340
359
+ >>
360
+ stream
361
+ Gau0F?#SIe(4FN4R-dPsen2uH.?`KrMJaAW"!kK,C*5/6!h($!;c=Zi6X'1IoXF;"1SdEAj,!?92IP4.Y<2L=giG+h0H]2'q,qMNqr]h`I2/u:Zg/nF+tmEWn(HI]=.`iB,:O(4hRn4'77eDO!IOZGY@p5KmEVKJ$aMeQZ%n;tD"c&5n(CKOZ^%Acg!=+V.P99^k6]o*/&?i52sgBbG5X!5nLG+<2i?d[BV*M_'[l!OQUO3%bh:H@*+*+jmdV]8&[quM&ZZ(>If&5,d6-sIH-0jSg^D0*8hr%mK5$6g&:.3>`Jg]n<e[66qK&tm%(piGZ62fR&.6GDJAZir<e^#DcHY\^B8+]@aJ8NPft]%gPXR=Hi")0gkOY)<n>[MRKl=Z=_P'.&0:Bjpl^2r@5,&10o-B48ak5r1j!h;VQOQ&KDadgOC;j0,Y\#K>STrqhHGRh$f2pp[bF',Td60W41qPHB.e1li@\)+r6+_#<h6:,"Ed"(AEkrNcPT*1=`aa4.r3!MS+YFbtr7uM:l*QqJ@pU5[5,i*?R_iS'Q7`K?ApLpmk>f,+[4KsZ\%rB3V["nY4ein8jI:(hEislg^r1kAE+H@aKrUSFQ#)kTV8db^g=;WLMPg+,cW6bq@`a>&)S))o\5[3i6)lHdm'`2@K!o_+,997jp337J@Kk,/8QnCe(k!!WrMIT\VQEiE#.!^$A]2)dQ%H4,P\2$,X!?[d`NB?2C;B.WB^U(3B5e<rjT@@;A'>cXQHql:=+)LerI'(b9nDp%p[$r:OY)f:l0aW#&Kb[q>H:1s#eDQkaQ6=L:^Oat'o]&VeggNO1\ZrY0:4ii+/f(aRJY%[o+N0TeHFAI[,EP=[Z=[Tpg-Ff9O#JGW8<TpM2<@5OZekaX0U+4l,;Wp`c.M/2Mh:$q`n/$G3hJXYk[6^\3g!%GAo-6=fS#pYhMYjlp@jc"(2]4Hsm"Fb>e_AZC&L$!oCS#H,E8E^`'cJL]\+;6FUN9i"4)3<Op/C@o0-CCuZ'seIK,+\#"HF.1?r:>t^lN/>Ep;Z2[0oeIYP#qDPM`O*1cd'hD9!$A"n`)(?4t>A1O_L?=(/]3aOYNQ<Vs1$k`V+9=uD%K<d6BTSN&>0bhOY9,DVZ>+Le)N@]2KKijWB1BSD*UZkW,%'7A3kV@)[t;[/O'P&7qn/6jD(5+r:kVkFd<0**>k\jt2R/JWn?%>[*q2j=8?9eiGt`$/EoU;iF[Md.orre%dQq?;C^@@*id,^$7?M%<)jjbah:-JW,n4(!"95:S?g.c@,6\":Le?.I($=/!0p%@9h$U3lrG<-K$J.ECfeE^KE9@t22!K`Y562>5qHaLO5P6sAkMumU%_TpBkQM(=!"Z+OGAAHGU+^VhU+7KOp(Mi:On^">Dt[uM(@MsB;f0(t?_>o7ZCnuEpB(=jk(Z8^-p^*2N4*H,+k.VIM@uU*FG&3\L]YeeA]YieYreTlVug)RXf++NJQT?lq069USO=EiPe8i:&(X`Se2;W%!saJ^AFCKZ:_YM#mPoEL&h8!nVO@`2s,o0m?h20cWL[T-#J[<.TqF9OXOY<_Y('hDdi;bUDU]H/a\6'a)K#ikFiM`O:kR7lN?UUSL<`Ttc656H8i($T`RlXfncN'XVPC31+9`&XBJQBDSkGi,'U\`/T#Sm1l^N)$Y4opteQ.%`X`7J/0\a6kP62\YLuf+#Hk3qtjQ0U7mDMG'-Yl)ZYXS[H%%haKjDsMHMu1.:`!pI5PO/kQ$F\K/EXVEE7A!eWe@oP*0]g4:!E;l<EJROR46Juid&!NY_Lio;PRBb6W<auq46a'LFU$c!1`jNt+_1ZSpNT!a3TWnkoPsC:AofVKe(G9R'$pU%LdQU"!;q6JiDr$WYm*+Ar9#1b9W/Wa(,PTpTl]%S..YfsM3B(TZE_Uh,sJ!BYge2amQ)W0IanR=Rj;=gT/BqCZJg3%@?JmLD#.QP%nMUW&*#*2UT(:R9H/[TkJn57M5g>WT7RYQ20^2##i+5i'j$_(?S2I:3Q,lbe^fHLh??#RjAV`f_Q1YabR&cZkiZCGrlG?@qKU"/>_.I\ee)ntMa='q`C+5$g3it$WdHX&!MN&S_H\$"gf64n1mRC,d*OIe4"N06bJH)&%Ja#s-84J1F!Am3W;o^:W:u$#oJf,*Vl^:,JqRaJ>2a*a03ZR?$"i+jR@??mIb5+C#g>Jqi)E,*%heU<s/Cm`blF'OJOVf&QBE(A/=SG7`_lQC6'n?G+4EO^_K^Co*5nYFcpHE!DLl0-d,O2@UG;sgQ;*<^+.&G/#Y'llAE'<hKI2O'C4abfE$gA>geH`DiR*FSLQTah#]#@Zfc`XfJim^9"_Yk*WYL6"D=H8j[t>0"q7U-5baVL=+-Mr3+$-ZTmHfG/2\%gWGEJscNg[&InNY$2BIC@oE,GL.fPSAB5LXnbl"IiVW<HPiA?W*HGIfGGWQ3i\)$E!VHkb=i=WZ'e#XV5qIB[24[U=,ibQ]\E>D`fc0VR>p/Sq"]X4irA&d5uQ5u_ToeBBk\En.0j+#i)8h"DX/Rr7P=@.ZEPjn.]W?.?ZX]:kR$lIsU6D(]V0Y/,P@+bTA2#YLq1`rPqT'&N1a+i\pPeA`qY&GAKS!&ap[-Ieb9#+/)!dLt"KbGXPE?T,$')?>L=^>0/0_B]aG9ZI6bC66_:]O:(5llHB9^aHe!jRA-_Rne<_bY,I2Oa\<D7Dm?-lnWmd4'i_&.\g*<Gs#-n8T^=`hGu(J&\:sUe<*$#dglia\`[JU?eS6[4VE`&#Si1F>/n7t-2!iAc))b0jVp9r.e]U=l"/*e6;@RdH=unh;t!bBIb;p3FRJ&CYW]Z@!ZpnVLoerl^(m:6GjHd0n!6odco]-n"[>-D[(e;Z^tf5[]e&!Z1&#;Rp-2W?gtCA1NhbLU.^:5p9^b)8FD@S#\ZKm.gFBn?2a0c,Y9/MP.nHBuHNB99Vk5Beo6SFHI'LP3Z<>pW0(ptnor^O\n#0pKc`Lqu9']ST6gkh+6![o9T0M5J5>HKH>HqC0jDCMF7;Wr>PWCH*=Vi[O?&3ITE>b)Z",,glh2r!@W#L%k?@7.S3"Zn*Y!Ud-9?b&]VtS6'@&\RO9j&gD7Y!^nCSkX)(V6ZCR!0e<Os:TUas.!)C%)p=jtO3OXCe/`Q?pbadFIK3Nb/eIoWL6#.gih_<]F=k'erPWdOGXp4a?X03c.;l!Bp_%m0@X$L;mlsU+l&3ne-=q=%h^<Vel.iE,m.Fe661EC1go>Tn\gOETF3iL&CKW&p@:XXK5qeo_d#":PbP*oX.o'Q`Gk0me_@5"T;,KC%'Z%B2qOg7]q&08f^U[h7m?jq.n_DW+_HrQL-Bg45XJMrW`fPIb4~>endstream
362
+ endobj
363
+ 47 0 obj
364
+ <<
365
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2471
366
+ >>
367
+ stream
368
+ Gb"/)D/\/e&H88.E@<M?.3)Ba7(m[jL3.4#FkN3A*kDjd$:Ru.26u:8E`448J)=+AIa\\$1g.*&7P'6`*fn?scQ+H3;"72b?Zu_D@LQ%>;4n?;k<O0a_tY'TNqYa+'bX.FCgn+?6oQ]'UTf0+015nGBP4nOW,2Op";T6JH$soG5=`&j+*]O<igkF)ik^:&'B[So#LqOanL#/<&RE&ec:^U]5`8<J&IY_cN@IBH!f_/mSRt>UI:WCY7EIP$7]C*@+<"R.'E;^Bc@qOV33f)^cFhYN&#(^`Hlb]-i1po;_UP3',Vqi6Zsh:`7215-PBKAE.n$$(Loh%H@/Gi,$?=:SE+Xrm(9th$@LpbVZo;GR7CL3[)Qig(h0'1,gnJCfiIlF$i5=Xh*,M0PHK+Z[K(DFpVLB4+q93A%Gkt%5ROdTsU2Zr-!@ODge.''o]6/U<GH5..6B,0X)OaNZ3o%k+0q$-LB79]Xfd`[BleBY3Ls8p03/qUJ.G5&jM\SsHMb8$@EB0FJ%Z1T8&Zp65;6.ut/;Qf5'5agF[%DjNJTp(_9CTeT?G\hq_\B8dGm`_3$tkTIFm[+GE,hj=WIO%8I_(2J>]=Wo4&\AVJAdHGH('gqaDCO,&;>BL9c"[09+38[%?&/o_V)4a?fK&7^r^t,UGYEKT>EGUErChN_]RJ:6Xf*0+pDU?ogO@*&1hfh+mMZ5n/V2.Zs]Z<A+-Je3l0!!NoHK;UU*afRmJ$%YDMc"bXka?4@s&1i>:CN)1e!!biKLLZG3G^"D==lTEDJ3]K(E;#6`<b))h-"Bi=aU=-8FaN7,S'7#pF=V@cJ)?][r-X?iX#Ka?9[f>Ip&YFG'ViiF[H'uS3l9Jr$$fKb/\'ZKp7=:&1qKu^W%ic#DdeCG/%gBKCt8'$gk1fc7be3\h@03/t<.5re_e4d1d20K4s%iqVs\'iDgAeI*%p%O[1Qgiu'pp]e@qmV'h5(],N*K%/rH/j36Mt5<%1(m,QJo^/#joMWGBG%l5Z]<=nJrTWbW#MfLrGWBreKQtm@V:`u'iP<Yf%+um8?/DIdS(+O_Fg8")+ROR<XRV]fE_="\/IW.):,S`NuOg=i.T_cKp2I08aO!=j3Lb[J%)7&\o&+^hWMJI(S^nH5Jl2D/8\oe>h+Fs"Bclm\sMV92oS*o^?V>NM:%_de-81=K`j\W)>M#Z@B6hjKu>`HDHV616=W_hAD<L'*ACLu0?Oja2W>ZgNH*c,L+"0]B>\.X>$5tU)B\1.e'sjGNg-O^1!DNBXcZWNPt>[IRFF>k)JroM$Yk)`fusd!Rc5sZ(h;PqJVQ^a1mJ]=h89%B@OH7N708!bj0Z?=`/$FdQa_lp^.>`?Y:C3%>-Ojf_tp4c^`'5!U8T:t;N!fsL6o3$::qDQ\Y'XA\hV'<-=mH0brr@82+s99A0&5W#)6QOAkD^9GWWU&m69jlZ^iPg/gnUKiUHX'k\qoW:s/Ein'!lR7RJMse8;L7l=M'/ji_O<-ct-OK%d##7*Me[bZ$#&?tYj*=gB!LU8n-MMB`:%F`UU<O]1V3j?"f!g^e)h[7/>W@(,rh'&K[EbctpEXW$P)ZQ&f%kfO8\9"mlAS6mbIPQdgs<A`8,3eB90_c:QR_s!>-1A,&*'1GEgf"7?]lJZWK\sS:SWg:j`qAh]bZ=s+qKrE]5X>T50NR_4(If:>X]l!#HQE>&MF$2X100CW>U5Yp3=ql`l4c[,M1S[B[jZQdL3Rmo1D[)qS96FJ=NhE)YJfE-C)dVCu*1Aa"h)%&Q+lu79>_;,+-R!=]UnTmFAE<b[F8M+WpRS.%%lF#6dbK9Rc0[I=>T6tAIC;"lMtBc5)m"@[(eA^;2pG>cFO#S$R,hH(NCp&j"8:K=C\c`OKopa((Qc3#:0?_$UG,ip]Lr4sV4W(Ugi:";::gZd_?eS+A[J1XBS>L'W#d"m9glB<Ja3+=hD_"1Rm+dYL=go!(V4rQn0)oRa$]SqIH8+V%bto#_-naE)P%9qS=;)U33/P,Un]hZ[s>P?R=q+FB?=$<I5'I=@(R<7XsgGH.1>SZctk$hGo,<Fa7XC]8Qe2OK6s1b%lnFno5`O"fQ[X6c!,/?4_gQ^G,gA)ju0g/?jqG[_<`GXTpd?d4^p1m":_mhEHeiK)*5PaI6U9*r&FmWeGRr_?i7gt.$_j=".og#Sb#'Fo0f8j!^PaBK75IL)OfPpW(u9H:W^B)_cdoj8SY]-GOrmT]M6mu`qFgD8U,Jh.[0ke5npAmdMTuICB3[HPVDUB_!WPS_&R&2LIl%AZ3Ltc'Z1-8:\koCYl@mZf,OYbZq!g7A=UR2p&42>gfe&dYNF)eQh/.D!2kN<B8&/qa_Ri7F\@!_VK'&EMt^dCZ`L03gfNTQp"=Y>C95SJ^+?0tp$#Y.\lPH+e[JRK=t;-!ar%j)bF0lVB%tJd0!l>%.h>J2,[)fNDHAT*)]=ZhYe4=72-WQZ#[)UX9&=,df_Yo"2B-'~>endstream
369
+ endobj
370
+ 48 0 obj
371
+ <<
372
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2710
373
+ >>
374
+ stream
375
+ Gb"/*h2g@"&V%R1K'5l%JdY:N?W7I::0K_M?o1DqDcKZU]=^5E3b^*YIE=kVpC8X/P'4C1`:I9;5]#)Rji7ciReb25\J,YN9@a'sH\B,H7^(ZI6lESM6.Eq=])I6:?!mNmU?gdD,K=0DNr=e2*_",AeZG?,46k&a0o\Q=!XsbNdH8&Z5+oZVp\QKX(&FE0&Oe9J_H;Kbl)d48?_Zjnd.LJ'`D=:^-PV6<,*+P(@C=IBGmJmDKOYX9iZlYl&o]JV(GNZ5$1d*nR"!9sWW]p/l2jmRK.odA#`jNYGADX"StT9RRcutN[`J&CbE8a#l1TW>%ck?gk_OVP_NSLg5<!%9g!"\&P^#0H7auGE;]:ARpp8]cbi(OIUt`SMf$Nu9p"n.Jl'I>eqm&Dt(.K/7egr*S5RX*KZ9;0P.%5X(n'^LfRQNnk@?6NL[oHUJmgq/cQ.VYj"$.(*F8>@Qljq>Qoe@%=B1B?IET9]K?*ddM-QC43fN"GH=uE0i@F^_VHgV6)>.'%&b>ahu\WtO<9,S+SK<cC1AV3nQ8c89Y<a+*5Fd#i8b!cC^Lq8GZM6pCsSe,c9,`QUF)P#Vo5Tqf(o6A^J0aSZ<!U+kB+K6-pm.c%n7!,ak,j<FFP`:6'Fpd/S[#R`AXW)baL\'#(j>#lD:/E!L%0r_J7*E`GOYj@ZjE:8i'Zifn`obV78%+n7^![hP21VHm%RB@fc.P0\=QG?=e;@5N[$(roJ5hcdTh=p\WX*SKWd0D@h;lIZeqeXEDM?()+!JXu7#fWi=V^G:UC&]e$FnLg'jsoC]EKe3o6=GWou?F%(:qb#D`*S&*p,Wq'XUM@EQ#fG*q>6+,CXH=0*diQ6&#)6a&<op,"hmhN?7k5#(r;I^65Y/T0AZN>,TgNe%3hBMgKEd2LG)o(ZgUBcNjg;>3fdBhKsskm$!7e9K6mGYF*/B-a+!mVJkLQGiUeRrmol+ocDoY/>@^8`i`_9=i&aY2Lr%[_:Z5LZ0(S'q.&S^0)!>H&E=sa/>_F)!kqqD>\Sftpeh9I"Y('893*+uO3bk==r"n#fd$*-b[MHp:U?KmI%Z2tmBYKJH%_6C!)\SpBCLd7AV!T((N&j@I*r?Kc\;A!;oIcXY4@Tg3-7/lmuP4oMHD]\f$(%KSMj3J`*(!D;5\2u(t^RbPr<#J-o!/SJ4]aH<4#ud1$L\7@Z'#Z5f-i.V<O'!p@er4?^l]&f4WH!U<&iR8mgdDU.Arf&Qd\:,*>8*^&UUCZHR5FPZV>,8Q+2l`-&hKGf[5.(?EKY@-Wf)o?/RB5=%-R/)o5Y,"YOaW+]YcQi[u5k.$Ng#$a_IN1>r.3qIh6g:]X&N!lGU`iCq=WYRMA@32&%4cW-iVF5*%(/7gL7#c(VI1eZaBD-US1l4>u81k@Fb*?sE-+8)fh4)D';PsIt!:EEb-GZo3ffZC_f,_8[F!UbQa7iWd[^9kGd)jtIrOn`m4M>NOQ!mh`OXPD9Da^t9rah@5=*TJ-NiGU,Vfck"a"&hB,U]A#L7`Tfg,fJrSW(kY#Pe&:"cg6O"T^[`r5X!t!2C)$%aocL$V<PFki]ApYk,Tpn(UCf!^1Bn2bT,mVU0c6dFPYFW:cP8n^s5<f0iSNs$cOPEMRJsW8@N3mU^CjhTf!SqO?pI@UIt]:qb]VBWm@*l]KN)4Ud*hGh28(e4tdB)Z.*O53qoMTJ)p[4(CW>4SS5j+O:;X?8rSr<+]Yd0eL^H87Wu!h:G;UN2<@t>7$EX<aF$Ia'M,=JVt`-L@g3QL*L<u$@(06_)'udP_Z9]8]]RYdBbq/lT:K"'kqRT\]I<@\*GOiWiE/ccH`:uLe9LZWXq8APc+UlgGI5Fop>86<UJ8upl'/S+"mY:k2QG`BdQ[]\$KKB$&p.Hf%Z1RD\:)sk#pN5oOI]"+F1?M*Wsn?/%57^QPI!fPe+f77VT+p!,0J#[Km&`ne#*8'fn<;/VAL$EOGXO(>%g7J,[Vjc4\n(:^\T*\i`qr+X]L14T?>:c?lh&8rmAsNB3n0GtC7hWK1O18@&@*?[=]X30e.Qo5V3E[,9bkqUCKe0p"-j=]D?qD(eQf#do1pGn9WY[(S=s#F!D"f%biETa^;XenErZ:Zj$j(<^8O^enbZZgP*TqIS_\h>3uG8T+Jr<$kcG-!dlpNSS`hhe\d`4K_#1M9K=WV4h[!IkJG"`#Lh'd-&;jL4a0)7@l`,SD"^FAmmBiR01.r`@]dhkRlJ!*(hkNP4ms7V,&0D=hZ\#nB;Ii]^F]'4R(^fpFLNphHH_ckYNLWi%>/SK0lb5R!]0#8Mn_+//)&is,nUp>ZBKZ2&Bh,iAr"o[,5(H7A\&R4RW6QNk7J<Ae9cRriEP+)V>Ko?A:i'-+I[bZn[ph2H@Cb-OpqpL@"YV</Nl;H+$(%O_=EV]YP**'"ImK9$rH!;8$!r`V<3GKTN@AC^*5\40ea;;Etj#@q#DnDgq<m,_"!m4+L%jh#a5&nZ'Mq66C_5j:Uik<11hb`!d:R;p5+9ics56Wnrcf-mtfLUY_c@nrB(dYJCJ[!>Er<B+U@GjKhWtdn;R:;C_1f`RC7E[B#C[_X5e3WM_f<<a`OM&RKtoM&mT:(D,aK"'&9MX"l:Qi8lo;h[M0@s2\kQf.@8rXjONKT4-5hNFtAG7\ffL1obHsiMc0!Wh0]2%pek$To?'QYsLS_oK?"L`_KMYe5P77X@@/<N7_^sg8Q.)p`E<,'T<~>endstream
376
+ endobj
377
+ 49 0 obj
378
+ <<
379
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2026
380
+ >>
381
+ stream
382
+ Gb!;d>Ar7S'RoMS37sF!`2[shgS_,qMJ[(]XTl37!<u`%D)N$'O`VT9@D@44.JXb&C%f%NW@en2ofM%kN)(\roA0FL8bD&%?=3Nh#;fYH+*eICY%]qDnb7rZAS`/0?IHO]U3%B/5!?W[V;:'RdXrt=r(04@lp5S^K+F=#oWBZZ;/etmq1;8akr&fFWnEQ!5C#i,Y;CT;<W!3c>=!61Mc/1bL:)9p9d8Ij'7,%[H3nH&(]*/Hr1Gb:gf8>t]R"m.Pk\'qZKK"Dr2*e:*>smM;3HSG4DaA^#`9#Ia=].$k9ENo_/.(68$<:f6Bf6LAgJg'h/Q#?d"Y["qOSEGVi5>=61_K-(Pp[EiD/Nc.oe%S^#/,o:f^0*K[`sm:0\^fG\$J^Y3lm6c+/;;3#hdXokFJRAL3,EXA)&Uk+l(D1;ceaCb8=rFY.?7#cM=S4W"#^A?6njOA>6mRA]9h!G3sV4\I#<gqT)4PAU[TLdV&,O0?SH*)Y?8mEj*9B0K4a@KRUqYoGo1*lo^X:*S<XJ\/fEZ2MrqC$Gk74A5hf2:K/ONOgDqO/e%G>Bt[VTTBtCPJBshSSqdEaD\1#43tnf]q8V*Dn\o#^J-B=s%1[(5$q[R>g@fpF@3NiP*_FHhZ2/kd'k[#:1Ot_?4uoL*;S?cn("N.V*Q#`AW(f_f&8E"ejlf2E<>#o[Qa9Ob\af&8!M$OZY/]^&hcpGRZ%P3ceK4p-=.Soc74>19qJt6lpVCIa*S<%C@.We>#]Fn-eSOJ$`pFs5_<\_V6i[KjeEnmM#]EVPufp#8p\9(>KY*UP[KYh6"L/0C&-NL2C&MH:1a?6@"-,74kDjSgO>fr[E:JIk1l+CUX+p&<>$:GKNri:1:McRCfk]/);0jL0uYmMCZitATguMPN\>1Fo`aGDf?@bU-m[*DeU\Q93Up7Ki5]0o2C<La,eeIcm#F#o9')-^Eq$;8#d3Y>fB(fDZl\1<-QVq]bnW%"]gZI)m'A@qhSYU4*7e]6587(t.UQi%iFQka6/GAc5-li>B2:Db$9pCbKNXFOC@ibCVDTulkV$0gaJr]TapY5-[GEFeRXCpn]'Tc%gMNP/[\slc2qFCB_+RM>cpGfYT5e%TgY*>T)U475iXZp1NMu\9Ek/I42rpDK@(hIN4=OY<c^eEu?t]9u1(3>38DDq^/3gq(Y%Ro>5e#`1)C(M\ntIa]X$h.3gM*rYlZ;3T%Q)+g*>Pkp.7(U,h$\taY$fh"UP(@h(C[OFL%Q(/AP:"b*cK:1]sncY%G'mH0-@;N4$ugl],J-JXt.bS50N:$EJg68H?`m@'ekBFGpZX5C>'W\XPef:O9Hrk2KNhJM&2!/U+12q-6t($+i-f`^`#;@$^?4ZBE@R<MTCU:^[7.3%uS]UjeW],>&)HtL8BWKiXs7Kq0@>Z*dID+k&e+WDca$If%`^'A.PDF`NWTO)GoaOT0j`;@E!sY\i%Th99ib&TW9+4gebMe_i:%'OA,!pG%B+7N[>`T0`:0X$,"oa;-([C#G+_nG\^;;cm=BPd6^j0Z_8C.5u!l7G'Xj[(JPtkIbtabf#6C7W:*,[_hPT,>qo!dZ$as:8f($e5chE)WDI/Z\0;ha2a"[&EXmHaClu7_P:6pHY1QPQg"erQr4nA'(ScQ1G7M]sbA@p.@'.Wn+;tOi7V"@SFOe@)Rq;+Y:F_DW\s(Z6G9E.Cg)NV;TB@m,J?f8^c).3=TOY7*\%P9$QF%YQ2;7Q63d6rP/PieBV*K.u--M_ba>Rf;<JkWS2XDi:5NN>*(&#oZ]oq.L@ia2pD`cbd5U`$hj-C?114K4S&JMt_7u2)d#]F(YW:-UIZ\)kC'13W/&"5I4V#<q0:(6O<s8'YFil'cInISW<s&gP)Sp+`=PHd&=_tZG;R=en!iA,T2`r;B7Fan-i*EDh=jW"2,4$M@GqPFFFhYqY*#\L7\>e#73K?A#8gs<,nZVN615Hs.Nc`VHgGIa`ZlE@C0#QF*`Z<anLC-*L'C;_gM.DoDa7ELQ!^2r-?_u4kI?Mk0?cG&i~>endstream
383
+ endobj
384
+ xref
385
+ 0 50
386
+ 0000000000 65535 f
387
+ 0000000061 00000 n
388
+ 0000000156 00000 n
389
+ 0000000263 00000 n
390
+ 0000000375 00000 n
391
+ 0000000480 00000 n
392
+ 0000000563 00000 n
393
+ 0000000640 00000 n
394
+ 0000000835 00000 n
395
+ 0000000950 00000 n
396
+ 0000001145 00000 n
397
+ 0000001265 00000 n
398
+ 0000001461 00000 n
399
+ 0000001657 00000 n
400
+ 0000001853 00000 n
401
+ 0000002049 00000 n
402
+ 0000002245 00000 n
403
+ 0000002441 00000 n
404
+ 0000002637 00000 n
405
+ 0000002833 00000 n
406
+ 0000003029 00000 n
407
+ 0000003225 00000 n
408
+ 0000003421 00000 n
409
+ 0000003617 00000 n
410
+ 0000003813 00000 n
411
+ 0000004009 00000 n
412
+ 0000004205 00000 n
413
+ 0000004401 00000 n
414
+ 0000004597 00000 n
415
+ 0000004667 00000 n
416
+ 0000004954 00000 n
417
+ 0000005143 00000 n
418
+ 0000007611 00000 n
419
+ 0000010655 00000 n
420
+ 0000012936 00000 n
421
+ 0000015192 00000 n
422
+ 0000017494 00000 n
423
+ 0000020596 00000 n
424
+ 0000023080 00000 n
425
+ 0000025839 00000 n
426
+ 0000027906 00000 n
427
+ 0000029680 00000 n
428
+ 0000031893 00000 n
429
+ 0000033671 00000 n
430
+ 0000035767 00000 n
431
+ 0000038064 00000 n
432
+ 0000040826 00000 n
433
+ 0000044258 00000 n
434
+ 0000046821 00000 n
435
+ 0000049623 00000 n
436
+ trailer
437
+ <<
438
+ /ID
439
+ [<448c678ec75143473aed934ad841dca0><448c678ec75143473aed934ad841dca0>]
440
+ % ReportLab generated PDF document -- digest (opensource)
441
+
442
+ /Info 29 0 R
443
+ /Root 28 0 R
444
+ /Size 50
445
+ >>
446
+ startxref
447
+ 51741
448
+ %%EOF
Docus & mps/DEFENSE_04_parser_ast_semantic_icg_interpreter.md ADDED
@@ -0,0 +1,2290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # File 4 of 7: Parser, AST, Semantic, ICG, and Interpreter
2
+
3
+ This section continues the defense guide after `server.py`, tokens/errors, and `lexer.py`. It covers the rest of the backend compiler pipeline up to execution.
4
+
5
+ Compiler path covered here:
6
+
7
+ ```text
8
+ lexer tokens -> cfg.py grammar -> Gal_Parser.py LL(1) parser -> GALsemantic.py AST builder -> GALsemantic.py semantic validator -> icg.py TAC generator -> GALinterpreter.py execution
9
+ ```
10
+
11
+ Important implementation note:
12
+
13
+ - `GALsemantic.py` is not only semantic analysis. In this codebase, it also defines AST node classes and contains the AST builder.
14
+ - `icg.py` currently generates intermediate code from the validated token stream, not from the AST.
15
+ - The GAL PDF says arrays start at index 1. The current interpreter uses Python-style index checks and access, so list/vine runtime indexing is 0-based. This is a mismatch to disclose.
16
+
17
+ ---
18
+
19
+ ## A. Backend/cfg.py
20
+
21
+ ### 1. FILE PURPOSE
22
+
23
+ `cfg.py` stores the context-free grammar and computes the FIRST, FOLLOW, and PREDICT sets used by the LL(1) parser.
24
+
25
+ It fits between lexer and parser:
26
+
27
+ ```text
28
+ tokens from lexer.py + grammar sets from cfg.py -> LL1Parser in Gal_Parser.py
29
+ ```
30
+
31
+ `server.py` does not directly parse the grammar. It imports `cfg`, `first_sets`, and `predict_sets`, then passes them into `LL1Parser`.
32
+
33
+ ### 2. IMPORTS / DEPENDENCIES
34
+
35
+ Code:
36
+
37
+ ```python
38
+ import sys
39
+ from collections import defaultdict
40
+ ```
41
+
42
+ Explanation:
43
+
44
+ - `sys` is used to reconfigure console encoding on Windows.
45
+ - `defaultdict` is used for grammar sets so each non-terminal can collect terminals without manually initializing every set.
46
+ - If `defaultdict` is removed, FIRST/FOLLOW computation would need manual dictionary initialization.
47
+
48
+ ### 3. GLOBAL CONSTANTS / VARIABLES
49
+
50
+ Code:
51
+
52
+ ```python
53
+ EPSILON = "lambda symbol in source"
54
+ cfg = {...}
55
+ first_sets = compute_first(cfg)
56
+ follow_sets = compute_follow(cfg, first_sets)
57
+ predict_sets = compute_predict(cfg, first_sets, follow_sets)
58
+ ```
59
+
60
+ Explanation:
61
+
62
+ - `EPSILON` represents an empty production.
63
+ - `cfg` is the grammar dictionary.
64
+ - `first_sets` stores what terminals can begin each non-terminal.
65
+ - `follow_sets` stores what terminals can legally follow each non-terminal.
66
+ - `predict_sets` stores the final LL(1) decision sets.
67
+ - If `predict_sets` is wrong, the parser will choose the wrong production or report syntax errors incorrectly.
68
+
69
+ ### 4. CLASSES AND FUNCTIONS
70
+
71
+ `compute_first(cfg)`
72
+
73
+ - Input: grammar dictionary.
74
+ - Output: FIRST set dictionary.
75
+ - Stage: parser preparation.
76
+ - Purpose: Know which terminals can start each grammar rule.
77
+
78
+ `compute_follow(cfg, first)`
79
+
80
+ - Input: grammar and FIRST sets.
81
+ - Output: FOLLOW set dictionary.
82
+ - Stage: parser preparation.
83
+ - Purpose: Know what can appear after a non-terminal, especially when epsilon is possible.
84
+
85
+ `compute_predict(cfg, first, follow)`
86
+
87
+ - Input: grammar, FIRST, FOLLOW.
88
+ - Output: PREDICT set dictionary.
89
+ - Stage: parser preparation.
90
+ - Purpose: Build the LL(1) production-selection data.
91
+
92
+ ### 5. LINE-BY-LINE / BLOCK-BY-BLOCK EXPLANATION
93
+
94
+ Code:
95
+
96
+ ```python
97
+ def compute_first(cfg):
98
+ first = defaultdict(set)
99
+ epsilon = EPSILON
100
+ ```
101
+
102
+ Explanation:
103
+
104
+ - Defines the FIRST computation function.
105
+ - `first` maps each non-terminal to a set of starting terminals.
106
+ - `epsilon` stores the empty-production symbol locally for readability.
107
+
108
+ Code:
109
+
110
+ ```python
111
+ for lhs, productions in cfg.items():
112
+ for prod in productions:
113
+ if not prod:
114
+ continue
115
+ if prod[0] == epsilon:
116
+ first[lhs].add(epsilon)
117
+ elif prod[0] not in cfg:
118
+ first[lhs].add(prod[0])
119
+ ```
120
+
121
+ Explanation:
122
+
123
+ - Loops through every grammar rule.
124
+ - `lhs` is the non-terminal on the left side.
125
+ - `prod` is one right-side production.
126
+ - Empty productions are skipped.
127
+ - If the production directly starts with epsilon, epsilon is added.
128
+ - If the first symbol is a terminal, that terminal is added.
129
+ - This is the first pass before recursive dependencies are resolved.
130
+
131
+ Code:
132
+
133
+ ```python
134
+ changed = True
135
+ while changed:
136
+ changed = False
137
+ ```
138
+
139
+ Explanation:
140
+
141
+ - FIRST sets depend on one another, so one pass is not enough.
142
+ - The loop repeats until no FIRST set changes.
143
+ - This is a fixed-point algorithm.
144
+
145
+ Code:
146
+
147
+ ```python
148
+ if symbol in cfg:
149
+ first[lhs] |= (first[symbol] - {epsilon})
150
+ if epsilon not in first[symbol]:
151
+ break
152
+ else:
153
+ if symbol != epsilon:
154
+ first[lhs].add(symbol)
155
+ break
156
+ ```
157
+
158
+ Explanation:
159
+
160
+ - If a production symbol is a non-terminal, copy its FIRST set into the current rule.
161
+ - Epsilon is excluded first because epsilon does not consume input.
162
+ - If that non-terminal cannot become epsilon, stop scanning the production.
163
+ - If the symbol is terminal, add it and stop.
164
+
165
+ ### 6. DEFENSE QUESTIONS
166
+
167
+ Q: Why do you need FIRST and FOLLOW sets?
168
+
169
+ A: They turn the grammar into parser decisions. FIRST tells what can start a rule, and FOLLOW helps decide when an empty production is allowed.
170
+
171
+ Q: Why use PREDICT sets?
172
+
173
+ A: PREDICT sets tell the LL(1) parser exactly which production to use based on the current non-terminal and one lookahead token.
174
+
175
+ ### 7. MEMORIZED EXPLANATION
176
+
177
+ `cfg.py` is the grammar preparation file. It stores the GAL grammar and computes FIRST, FOLLOW, and PREDICT sets. The parser uses those sets to choose grammar productions during LL(1) parsing.
178
+
179
+ ---
180
+
181
+ ## B. Backend/Gal_Parser.py
182
+
183
+ ### 1. FILE PURPOSE
184
+
185
+ `Gal_Parser.py` performs syntax analysis using LL(1) parsing. It also bridges syntax analysis to AST construction through `parse_and_build()`.
186
+
187
+ Pipeline position:
188
+
189
+ ```text
190
+ tokens -> parser.parse() -> syntax result
191
+ tokens -> parser.parse_and_build() -> syntax result + AST + symbol table
192
+ ```
193
+
194
+ ### 2. IMPORTS / DEPENDENCIES
195
+
196
+ Code:
197
+
198
+ ```python
199
+ from __future__ import annotations
200
+ from dataclasses import dataclass
201
+ from typing import Any, Dict, Iterable, List, Mapping, Optional, Sequence, Set, Tuple
202
+ ```
203
+
204
+ Explanation:
205
+
206
+ - Future annotations simplify type hints.
207
+ - `dataclass` is used for normalized token views.
208
+ - `typing` makes parser inputs and outputs clearer.
209
+
210
+ Code:
211
+
212
+ ```python
213
+ from GALsemantic import (
214
+ build_ast as _build_ast,
215
+ symbol_table as _builder_st,
216
+ SemanticError as _SemanticError,
217
+ )
218
+ ```
219
+
220
+ Explanation:
221
+
222
+ - `_build_ast` is called after syntax succeeds.
223
+ - `_builder_st` is read after AST construction to serialize variables/functions.
224
+ - `_SemanticError` catches AST-building errors.
225
+ - This is why AST construction is connected to the parser even though AST node classes live in `GALsemantic.py`.
226
+
227
+ ### 3. GLOBAL CONSTANTS / VARIABLES
228
+
229
+ No major global parser object is created here. The parser instance is created in `server.py`.
230
+
231
+ ### 4. CLASSES AND FUNCTIONS
232
+
233
+ `_TokView`
234
+
235
+ - Input: normalized token data.
236
+ - Purpose: Give the parser a consistent token format.
237
+
238
+ `_as_tok(token)`
239
+
240
+ - Input: token object or dictionary.
241
+ - Returns: `_TokView`.
242
+ - Purpose: Make parser reusable from lexer objects or JSON-like dictionaries.
243
+
244
+ `LL1Parser.__init__`
245
+
246
+ - Receives grammar, FIRST sets, PREDICT sets, start symbol, EOF marker, skip token types, aliases.
247
+ - Builds the parsing table.
248
+
249
+ `construct_parsing_table()`
250
+
251
+ - Receives no external input except parser state.
252
+ - Returns LL(1) table.
253
+ - Detects LL(1) conflicts.
254
+
255
+ `parse(tokens)`
256
+
257
+ - Input: token sequence.
258
+ - Returns: `(success, errors)`.
259
+ - Stage: syntax analysis.
260
+
261
+ `parse_and_build(tokens)`
262
+
263
+ - Input: token sequence.
264
+ - Returns: dictionary with `success`, `errors`, `ast`, and `symbol_table`.
265
+ - Stage: syntax + AST construction.
266
+
267
+ ### 5. LINE-BY-LINE / BLOCK-BY-BLOCK EXPLANATION
268
+
269
+ Code:
270
+
271
+ ```python
272
+ @dataclass(frozen=True)
273
+ class _TokView:
274
+ type: str
275
+ value: str
276
+ line: int
277
+ col: int = 0
278
+ ```
279
+
280
+ Explanation:
281
+
282
+ - `_TokView` is a read-only token representation.
283
+ - The parser only needs token type, value, line, and column.
284
+ - `frozen=True` means parser logic cannot accidentally mutate token data.
285
+
286
+ Code:
287
+
288
+ ```python
289
+ def _as_tok(token):
290
+ if isinstance(token, Mapping):
291
+ return _TokView(...)
292
+ return _TokView(...)
293
+ ```
294
+
295
+ Explanation:
296
+
297
+ - If the input token is a dictionary, fields are read with `.get()`.
298
+ - If it is a lexer `Token` object, fields are read with `getattr()`.
299
+ - This protects the parser from depending on only one token representation.
300
+
301
+ Code:
302
+
303
+ ```python
304
+ class LL1Parser:
305
+ def __init__(self, cfg, predict_sets, first_sets, *, start_symbol="<program>", end_marker="EOF", epsilon_symbols=(...), skip_token_types=None, token_type_alias=None):
306
+ self.cfg = cfg
307
+ self.predict_sets = predict_sets
308
+ self.first_sets = first_sets
309
+ ```
310
+
311
+ Explanation:
312
+
313
+ - Defines the parser class.
314
+ - Receives grammar and parsing sets from `cfg.py`.
315
+ - Stores start symbol and EOF marker.
316
+ - Allows skipped token types such as newline.
317
+ - Allows token aliases when lexer names and grammar names differ.
318
+
319
+ Code:
320
+
321
+ ```python
322
+ self.skip_token_types = set(skip_token_types or {"\n"})
323
+ self.token_type_alias = token_type_alias or {
324
+ 'idf': 'id',
325
+ 'dbllit': 'dblit',
326
+ }
327
+ self.parsing_table = self.construct_parsing_table()
328
+ ```
329
+
330
+ Explanation:
331
+
332
+ - Newline is skipped by default.
333
+ - Token aliases handle naming inconsistencies.
334
+ - The parsing table is built immediately when the parser is constructed.
335
+
336
+ Code:
337
+
338
+ ```python
339
+ def construct_parsing_table(self):
340
+ table = {}
341
+ for non_terminal, productions in self.cfg.items():
342
+ row = {}
343
+ ```
344
+
345
+ Explanation:
346
+
347
+ - Creates the LL(1) table.
348
+ - Each non-terminal gets one row.
349
+
350
+ Code:
351
+
352
+ ```python
353
+ key = (non_terminal, tuple(production))
354
+ terms = self.predict_sets.get(key, set())
355
+ for terminal in terms:
356
+ if terminal in row and row[terminal] != production:
357
+ raise ValueError(...)
358
+ row[terminal] = production
359
+ ```
360
+
361
+ Explanation:
362
+
363
+ - Looks up the PREDICT set for that production.
364
+ - For each lookahead terminal, stores which production to use.
365
+ - If two productions claim the same lookahead, that is an LL(1) conflict.
366
+
367
+ Code:
368
+
369
+ ```python
370
+ def parse(self, tokens):
371
+ toks = [_as_tok(t) for t in tokens]
372
+ toks = [_TokView(self._normalize_token_type(t.type), t.value, t.line, t.col) for t in toks]
373
+ toks = self._ensure_eof(toks)
374
+ ```
375
+
376
+ Explanation:
377
+
378
+ - Converts tokens into parser view objects.
379
+ - Normalizes token type names.
380
+ - Ensures EOF exists.
381
+
382
+ Code:
383
+
384
+ ```python
385
+ stack = [self.end_marker, self.start_symbol]
386
+ index = 0
387
+ ```
388
+
389
+ Explanation:
390
+
391
+ - LL(1) parsing uses a stack.
392
+ - EOF is bottom marker.
393
+ - `<program>` is the first grammar symbol to expand.
394
+ - `index` points to the current input token.
395
+
396
+ Code:
397
+
398
+ ```python
399
+ while stack:
400
+ top = stack[-1]
401
+ tok = current_token()
402
+ token_type = tok.type
403
+ ```
404
+
405
+ Explanation:
406
+
407
+ - Main parser loop.
408
+ - `top` is the grammar symbol currently being matched or expanded.
409
+ - `tok` is the current lookahead token.
410
+
411
+ Code:
412
+
413
+ ```python
414
+ if token_type in self.skip_token_types and top != token_type:
415
+ index += 1
416
+ continue
417
+ ```
418
+
419
+ Explanation:
420
+
421
+ - Skips newline tokens.
422
+ - This is the skipped token filtering requested in the defense prompt.
423
+ - It lets the lexer keep newlines while the parser ignores them.
424
+
425
+ Code:
426
+
427
+ ```python
428
+ if top in self.parsing_table:
429
+ row = self.parsing_table[top]
430
+ if token_type in row:
431
+ production = row[token_type]
432
+ ```
433
+
434
+ Explanation:
435
+
436
+ - If `top` is a non-terminal, the parser uses the parsing table.
437
+ - The lookahead token chooses one production.
438
+
439
+ Code:
440
+
441
+ ```python
442
+ stack.pop()
443
+ if production is not epsilon:
444
+ stack.extend(reversed(production))
445
+ continue
446
+ ```
447
+
448
+ Explanation:
449
+
450
+ - Removes the non-terminal.
451
+ - Pushes the right-hand side of the chosen production.
452
+ - Uses reverse order because stacks process last-in-first-out.
453
+
454
+ Code:
455
+
456
+ ```python
457
+ expected = set(row.keys())
458
+ error_msg = self._generate_helpful_error(...)
459
+ return False, [error_msg]
460
+ ```
461
+
462
+ Explanation:
463
+
464
+ - If no production matches, syntax fails.
465
+ - The parser generates a helpful message with expected tokens.
466
+
467
+ Code:
468
+
469
+ ```python
470
+ if top == token_type:
471
+ ...
472
+ ```
473
+
474
+ Explanation:
475
+
476
+ - If the stack top is a terminal and equals the current token type, the parser consumes the token.
477
+ - This is a successful match.
478
+
479
+ Code:
480
+
481
+ ```python
482
+ elif expecting_value_for_type is not None and token_type in {...}:
483
+ type_value_map = {...}
484
+ ```
485
+
486
+ Explanation:
487
+
488
+ - The parser includes extra validation for simple declaration assignments.
489
+ - This is partially semantic checking inside the parser for better immediate messages.
490
+ - Full semantic validation still happens later through `validate_ast()`.
491
+
492
+ Code:
493
+
494
+ ```python
495
+ def parse_and_build(self, tokens):
496
+ syntax_ok, syntax_errors = self.parse(tokens)
497
+ if not syntax_ok:
498
+ return {"success": False, "errors": syntax_errors, "ast": None, "symbol_table": {}}
499
+ ```
500
+
501
+ Explanation:
502
+
503
+ - `parse_and_build()` starts by running syntax validation.
504
+ - If syntax fails, AST construction is skipped.
505
+ - This protects AST builder from invalid token order.
506
+
507
+ Code:
508
+
509
+ ```python
510
+ filtered = [t for t in tokens if getattr(t, 'type', '') != '\n']
511
+ ast = _build_ast(filtered)
512
+ ```
513
+
514
+ Explanation:
515
+
516
+ - Removes newline tokens before AST construction.
517
+ - Calls `build_ast()` from `GALsemantic.py`.
518
+
519
+ Code:
520
+
521
+ ```python
522
+ st = {
523
+ "variables": [...],
524
+ "functions": {...},
525
+ }
526
+ ```
527
+
528
+ Explanation:
529
+
530
+ - Converts the AST builder's symbol table into a JSON-friendly dictionary.
531
+ - Returned to server and frontend.
532
+
533
+ Code:
534
+
535
+ ```python
536
+ except _SemanticError as e:
537
+ return {"success": False, "errors": [str(e)], "ast": None, "symbol_table": {}, "error_stage": "semantic"}
538
+ ```
539
+
540
+ Explanation:
541
+
542
+ - AST builder can detect semantic-like errors while building.
543
+ - The parser reports those as semantic-stage errors, not pure syntax errors.
544
+
545
+ ### 6. DEFENSE QUESTIONS
546
+
547
+ Q: Why does the parser skip newline tokens?
548
+
549
+ A: The lexer emits newlines for display and accurate lines, but grammar matching should not depend on formatting. So the parser skips `\n`.
550
+
551
+ Q: Why does `parse_and_build()` parse first before building AST?
552
+
553
+ A: AST construction assumes valid structure. Parsing first prevents invalid syntax from creating a broken tree.
554
+
555
+ Q: Why are there semantic checks inside the parser?
556
+
557
+ A: Some checks are added for clearer early diagnostics, but the full semantic pass still runs after AST construction.
558
+
559
+ ### 7. WALKTHROUGH EXAMPLE
560
+
561
+ For:
562
+
563
+ ```gal
564
+ root() {
565
+ seed age = 10;
566
+ plant(age);
567
+ reclaim;
568
+ }
569
+ ```
570
+
571
+ The parser matches the grammar for `root`, parameter parentheses, function body, declaration, print statement, reclaim statement, closing brace, and EOF.
572
+
573
+ ### 8. MEMORIZED EXPLANATION
574
+
575
+ `Gal_Parser.py` validates GAL syntax using LL(1) parsing. It uses the grammar and PREDICT sets from `cfg.py`, skips newline tokens, reports syntax errors, and only after successful parsing does it call the AST builder.
576
+
577
+ ---
578
+
579
+ ## C. Backend/GALsemantic.py: AST Nodes and AST Builder
580
+
581
+ ### 1. FILE PURPOSE
582
+
583
+ `GALsemantic.py` has two responsibilities:
584
+
585
+ 1. It defines AST node classes and builds the AST from validated tokens.
586
+ 2. It validates the AST semantically.
587
+
588
+ This section covers the AST-building part first.
589
+
590
+ ### 2. IMPORTS / DEPENDENCIES
591
+
592
+ Code:
593
+
594
+ ```python
595
+ import re
596
+ ```
597
+
598
+ Explanation:
599
+
600
+ - Used for pattern checks inside semantic parsing/validation.
601
+ - If removed, regex-based validation would fail where used.
602
+
603
+ ### 3. GLOBAL CONSTANTS / VARIABLES
604
+
605
+ Important state:
606
+
607
+ - `symbol_table`: records variables, functions, scopes, and bundle types during AST construction.
608
+ - `context_stack`: helps know whether parser is inside loop/switch-like contexts.
609
+
610
+ Important warning:
611
+
612
+ - Because `symbol_table` is shared state, `build_ast()` resets it at the start of each compilation.
613
+
614
+ ### 4. CLASSES AND FUNCTIONS
615
+
616
+ `SemanticError`
617
+
618
+ - Exception class for line-numbered semantic/syntax messages.
619
+
620
+ `ASTNode`
621
+
622
+ - Base class for all AST nodes.
623
+
624
+ AST subclasses include:
625
+
626
+ - `ProgramNode`
627
+ - `VariableDeclarationNode`
628
+ - `AssignmentNode`
629
+ - `BinaryOpNode`
630
+ - `FunctionDeclarationNode`
631
+ - `FunctionCallNode`
632
+ - `IfStatementNode`
633
+ - `ForLoopNode`
634
+ - `WhileLoopNode`
635
+ - `DoWhileLoopNode`
636
+ - `PrintNode`
637
+ - `ReturnNode`
638
+ - `SwitchNode`
639
+ - `ListNode`
640
+ - `ListAccessNode`
641
+ - `MemberAccessNode`
642
+ - `BundleDefinitionNode`
643
+
644
+ `SymbolTable`
645
+
646
+ - Tracks declarations and scopes during AST construction.
647
+
648
+ `build_ast(tokens)`
649
+
650
+ - Entry point for AST construction.
651
+
652
+ `parse_function(...)`
653
+
654
+ - Builds function declaration nodes for `root()` and `pollinate` functions.
655
+
656
+ `parse_statement(...)`
657
+
658
+ - Dispatches statements based on token type/value.
659
+
660
+ ### 5. LINE-BY-LINE / BLOCK-BY-BLOCK EXPLANATION
661
+
662
+ Code:
663
+
664
+ ```python
665
+ class ASTNode:
666
+ def __init__(self, node_type, value=None, line=None):
667
+ self.node_type = node_type
668
+ self.value = value
669
+ self.children = []
670
+ self.parent = None
671
+ self.line = line
672
+ ```
673
+
674
+ Explanation:
675
+
676
+ - All AST nodes share this structure.
677
+ - `node_type` tells what kind of construct it is.
678
+ - `value` stores things like identifier names, literal values, or operators.
679
+ - `children` store nested syntax structure.
680
+ - `parent` gives reverse navigation.
681
+ - `line` supports error reporting.
682
+
683
+ Code:
684
+
685
+ ```python
686
+ def add_child(self, child):
687
+ child.parent = self
688
+ self.children.append(child)
689
+ ```
690
+
691
+ Explanation:
692
+
693
+ - Adds a child node.
694
+ - Also records the parent pointer.
695
+ - Parent pointers are used later, especially by interpreter input handling.
696
+
697
+ Code:
698
+
699
+ ```python
700
+ class VariableDeclarationNode(ASTNode):
701
+ def __init__(self, var_type, var_name, value=None, line=None):
702
+ super().__init__("VariableDeclaration", line=line)
703
+ self.add_child(ASTNode("Type", var_type, line=line))
704
+ self.add_child(ASTNode("Identifier", var_name, line=line))
705
+ if value:
706
+ self.add_child(value)
707
+ ```
708
+
709
+ Explanation:
710
+
711
+ - Represents declarations like `seed age = 10;`.
712
+ - Child 0 is type.
713
+ - Child 1 is identifier.
714
+ - Optional child 2 is initializer.
715
+ - The interpreter relies on this exact child order.
716
+
717
+ Code:
718
+
719
+ ```python
720
+ class FunctionDeclarationNode(ASTNode):
721
+ def __init__(self, return_type, name, params, line=None):
722
+ super().__init__("FunctionDeclaration", name, line=line)
723
+ self.add_child(ASTNode("ReturnType", return_type, line=line))
724
+ self.add_child(params)
725
+ ```
726
+
727
+ Explanation:
728
+
729
+ - Represents both `root()` and `pollinate` functions.
730
+ - Function name is stored in `value`.
731
+ - Return type and parameter list are children.
732
+ - The function body block is added later.
733
+
734
+ Code:
735
+
736
+ ```python
737
+ class SymbolTable:
738
+ def __init__(self):
739
+ self.variables = {}
740
+ self.global_variables = {}
741
+ self.functions = {}
742
+ self.scopes = [{}]
743
+ self.current_func_name = None
744
+ self.function_variables = {}
745
+ self.bundle_types = {}
746
+ ```
747
+
748
+ Explanation:
749
+
750
+ - Tracks declared names during AST construction.
751
+ - `variables` stores global variables.
752
+ - `functions` stores function declarations.
753
+ - `scopes` tracks local scopes.
754
+ - `current_func_name` tells whether we are inside a function.
755
+ - `function_variables` detects duplicate local variables.
756
+ - `bundle_types` stores struct-like definitions.
757
+
758
+ Code:
759
+
760
+ ```python
761
+ def declare_variable(self, name, type_, value=None, is_list=False, is_fertile=False):
762
+ scope = self.scopes[-1]
763
+ current_func = self.current_func_name
764
+ ```
765
+
766
+ Explanation:
767
+
768
+ - Declares a variable in the active scope.
769
+ - Uses the current function name to distinguish locals from globals.
770
+ - Stores whether the variable is an array/list or constant.
771
+
772
+ Code:
773
+
774
+ ```python
775
+ if name in self.functions:
776
+ return f"Semantic Error: Variable '{name}' already declared as a function."
777
+ ```
778
+
779
+ Explanation:
780
+
781
+ - Prevents a variable from reusing a function name.
782
+ - This is a semantic rule because the name is lexically valid but invalid in context.
783
+
784
+ Code:
785
+
786
+ ```python
787
+ def lookup_variable(self, name):
788
+ for scope in reversed(self.scopes):
789
+ if name in scope:
790
+ return scope[name]
791
+ if name in self.variables:
792
+ return self.variables[name]
793
+ return f"Semantic Error: Variable '{name}' used before declaration."
794
+ ```
795
+
796
+ Explanation:
797
+
798
+ - Searches local scope first, then globals.
799
+ - Supports normal scoping behavior.
800
+ - Reports declaration-before-use errors.
801
+
802
+ Code:
803
+
804
+ ```python
805
+ def build_ast(tokens):
806
+ root = ProgramNode()
807
+ symbol_table.variables = {}
808
+ symbol_table.functions = {}
809
+ symbol_table.scopes = [{}]
810
+ symbol_table.function_variables = {}
811
+ symbol_table.bundle_types = {}
812
+ index = 0
813
+ ```
814
+
815
+ Explanation:
816
+
817
+ - Creates the AST root.
818
+ - Resets old compiler state.
819
+ - Begins token scanning at index 0.
820
+ - Resetting matters because the server may compile many programs in one run.
821
+
822
+ Code:
823
+
824
+ ```python
825
+ while index < len(tokens):
826
+ token = tokens[index]
827
+ ```
828
+
829
+ Explanation:
830
+
831
+ - Main AST-building loop.
832
+ - Reads top-level program constructs: global declarations, `pollinate`, `bundle`, and `root`.
833
+
834
+ Code:
835
+
836
+ ```python
837
+ if tokens[index].value in {"seed", "tree", "vine", "leaf", "branch"}:
838
+ id_type = token.value
839
+ index += 1
840
+ if tokens[index].type != "id":
841
+ raise SemanticError(...)
842
+ id_name = tokens[index].value
843
+ index += 1
844
+ node, index = parse_variable(tokens, index, id_name, id_type)
845
+ ```
846
+
847
+ Explanation:
848
+
849
+ - Handles top-level variable declarations.
850
+ - Reads data type then identifier.
851
+ - Delegates initializer/list handling to `parse_variable()`.
852
+
853
+ Code:
854
+
855
+ ```python
856
+ elif tokens[index].value in {"pollinate"}:
857
+ index += 1
858
+ if tokens[index].value in {"seed", "tree", "vine", "leaf", "branch", "empty"}:
859
+ id_type = tokens[index].value
860
+ index += 1
861
+ id_name = tokens[index].value
862
+ index += 1
863
+ node, index = parse_function(tokens, index, id_name, id_type)
864
+ ```
865
+
866
+ Explanation:
867
+
868
+ - Handles user-defined function declarations.
869
+ - `pollinate` must be followed by return type.
870
+ - Then function name is read.
871
+ - `parse_function()` handles parameters and body.
872
+
873
+ Code:
874
+
875
+ ```python
876
+ elif token.value in {"root"}:
877
+ func_name = token.value
878
+ func_type = "empty"
879
+ node, index = parse_function(tokens, index, func_name, func_type)
880
+ ```
881
+
882
+ Explanation:
883
+
884
+ - Handles the main entry point.
885
+ - `root()` is treated as an empty-return function.
886
+ - Later, the interpreter explicitly calls `root()`.
887
+
888
+ Code:
889
+
890
+ ```python
891
+ elif token.value == "bundle":
892
+ bundle_name = tokens[index + 1].value
893
+ members = {}
894
+ ```
895
+
896
+ Explanation:
897
+
898
+ - Handles bundle/struct definitions.
899
+ - Collects member fields and stores the type definition.
900
+
901
+ Code:
902
+
903
+ ```python
904
+ def parse_function(tokens, index, func_name, func_type):
905
+ symbol_table.current_func_name = func_name
906
+ ```
907
+
908
+ Explanation:
909
+
910
+ - Begins function parsing.
911
+ - Sets current function context so local declarations go into function scope.
912
+
913
+ Code:
914
+
915
+ ```python
916
+ if func_name in {"root"}:
917
+ symbol_table.enter_scope()
918
+ index += 1
919
+ if tokens[index].type == "(":
920
+ index += 1
921
+ if tokens[index].type != ")":
922
+ raise SemanticError(...)
923
+ ```
924
+
925
+ Explanation:
926
+
927
+ - Special handling for `root()`.
928
+ - Enters a local scope for root body.
929
+ - Requires empty parameter list.
930
+ - Rejects `root(seed x)` because root should not receive parameters.
931
+
932
+ Code:
933
+
934
+ ```python
935
+ while tokens[index].type != ")":
936
+ if tokens[index].value in {"seed", "tree", "vine", "leaf", "branch", "empty"}:
937
+ param_type = tokens[index].value
938
+ ...
939
+ params_node.add_child(param_node)
940
+ symbol_table.declare_variable(param_name, param_type, is_list=is_list)
941
+ ```
942
+
943
+ Explanation:
944
+
945
+ - Parses pollinate function parameters.
946
+ - Builds parameter AST nodes.
947
+ - Declares each parameter in the function's local scope.
948
+
949
+ Code:
950
+
951
+ ```python
952
+ while tokens[index].type != "}":
953
+ stmt, index = parse_statement(tokens, index, func_type)
954
+ if stmt:
955
+ block_node.add_child(stmt)
956
+ if _contains_return(stmt):
957
+ has_any_return = True
958
+ ```
959
+
960
+ Explanation:
961
+
962
+ - Parses statements inside the function body.
963
+ - Adds them to a block node.
964
+ - Tracks whether `reclaim` appears.
965
+
966
+ Code:
967
+
968
+ ```python
969
+ if (func_type != "empty" and not all_paths) and func_name not in {"root"}:
970
+ raise SemanticError(...)
971
+ ```
972
+
973
+ Explanation:
974
+
975
+ - Non-empty functions must return a value on all paths.
976
+ - This enforces `reclaim value;` for functions like `pollinate seed add(...)`.
977
+
978
+ Code:
979
+
980
+ ```python
981
+ if not has_any_return:
982
+ if func_name == "root":
983
+ raise SemanticError("root() must end with 'reclaim;'", line)
984
+ ```
985
+
986
+ Explanation:
987
+
988
+ - Enforces required termination in `root()`.
989
+ - This matches the GAL specification.
990
+
991
+ Code:
992
+
993
+ ```python
994
+ def parse_statement(tokens, index, func_type=None):
995
+ token = tokens[index]
996
+ if token.type == ";":
997
+ return None, index + 1
998
+ ```
999
+
1000
+ Explanation:
1001
+
1002
+ - Dispatches individual statements.
1003
+ - Ignores stray semicolons safely.
1004
+
1005
+ Code:
1006
+
1007
+ ```python
1008
+ if token.value in {"seed", "tree", "vine", "leaf", "branch"}:
1009
+ var_type = token.value
1010
+ var_name = tokens[index + 1].value
1011
+ node, index = parse_variable(tokens, index, var_name, var_type)
1012
+ ```
1013
+
1014
+ Explanation:
1015
+
1016
+ - Handles local variable declarations.
1017
+ - Produces a `VariableDeclarationNode` or declaration list node.
1018
+
1019
+ Code:
1020
+
1021
+ ```python
1022
+ elif token.type == "id" and tokens[index + 1].type == "(":
1023
+ func_name = token.value
1024
+ error = symbol_table.lookup_function(func_name)
1025
+ func_call_node, index = parse_function_call(...)
1026
+ ```
1027
+
1028
+ Explanation:
1029
+
1030
+ - Detects function calls.
1031
+ - Checks that the function exists.
1032
+ - Builds a function call AST node.
1033
+
1034
+ ### 6. DEFENSE QUESTIONS
1035
+
1036
+ Q: Why does `GALsemantic.py` build the AST?
1037
+
1038
+ A: In this implementation, AST node definitions and AST building are grouped with semantic logic. The parser calls it only after syntax succeeds.
1039
+
1040
+ Q: Why reset the symbol table in `build_ast()`?
1041
+
1042
+ A: The server can compile multiple programs. Resetting prevents old variables/functions from leaking into a new compilation.
1043
+
1044
+ Q: Why store parent links in AST nodes?
1045
+
1046
+ A: Parent links help when a node needs context. For example, the interpreter checks where an input node appears to determine the target variable and type.
1047
+
1048
+ ### 7. WALKTHROUGH EXAMPLE
1049
+
1050
+ For:
1051
+
1052
+ ```gal
1053
+ seed age = 10;
1054
+ plant(age);
1055
+ reclaim;
1056
+ ```
1057
+
1058
+ The AST block contains:
1059
+
1060
+ ```text
1061
+ VariableDeclaration(Type seed, Identifier age, Value 10)
1062
+ PrintStatement(Value age)
1063
+ Return
1064
+ ```
1065
+
1066
+ ### 8. MEMORIZED EXPLANATION
1067
+
1068
+ `GALsemantic.py` defines the AST structure and builds the tree from validated tokens. It also uses a symbol table to record declarations, scopes, functions, and bundles while building that tree.
1069
+
1070
+ ---
1071
+
1072
+ ## D. Backend/GALsemantic.py: Semantic Analyzer
1073
+
1074
+ ### 1. FILE PURPOSE
1075
+
1076
+ After the AST is built, the semantic analyzer walks the tree and validates meaning. It checks context and structure that grammar alone cannot fully guarantee.
1077
+
1078
+ Examples of semantic concerns:
1079
+
1080
+ - Is `prune` inside a loop or switch?
1081
+ - Is `skip` inside a loop?
1082
+ - Is a declaration structurally complete?
1083
+ - Does a function have valid return structure?
1084
+ - Are blocks and expressions well formed?
1085
+
1086
+ ### 2. CLASSES AND FUNCTIONS
1087
+
1088
+ `ASTValidator`
1089
+
1090
+ - Input: AST and serialized symbol table.
1091
+ - Output: dictionary containing success, errors, warnings, symbol table, and AST.
1092
+ - Stage: semantic analysis.
1093
+
1094
+ `validate_ast(ast, symbol_table_data)`
1095
+
1096
+ - Public API used by `server.py`.
1097
+ - Creates a validator and returns validation result.
1098
+
1099
+ ### 3. LINE-BY-LINE / BLOCK-BY-BLOCK EXPLANATION
1100
+
1101
+ Code:
1102
+
1103
+ ```python
1104
+ class ASTValidator:
1105
+ def __init__(self):
1106
+ self.errors = []
1107
+ self.warnings = []
1108
+ self._in_loop = 0
1109
+ self._in_switch = 0
1110
+ self._in_function = False
1111
+ self._current_func_type = None
1112
+ ```
1113
+
1114
+ Explanation:
1115
+
1116
+ - `errors` stores semantic errors.
1117
+ - `warnings` stores non-fatal notices.
1118
+ - `_in_loop` tracks loop nesting.
1119
+ - `_in_switch` tracks harvest/switch nesting.
1120
+ - `_in_function` tracks function context.
1121
+ - `_current_func_type` tracks expected return type while walking a function.
1122
+
1123
+ Code:
1124
+
1125
+ ```python
1126
+ def validate(self, ast, symbol_table_data):
1127
+ self._walk(ast)
1128
+ return {
1129
+ "success": len(self.errors) == 0,
1130
+ "errors": self.errors,
1131
+ "warnings": self.warnings,
1132
+ "symbol_table": symbol_table_data,
1133
+ "ast": ast,
1134
+ }
1135
+ ```
1136
+
1137
+ Explanation:
1138
+
1139
+ - Starts validation by walking the AST root.
1140
+ - Success is true only when no errors were collected.
1141
+ - Returns the AST again so later stages can use the validated tree.
1142
+
1143
+ Code:
1144
+
1145
+ ```python
1146
+ def _walk(self, node):
1147
+ if node is None:
1148
+ return
1149
+ handler = getattr(self, f'_check_{node.node_type}', None)
1150
+ if handler:
1151
+ handler(node)
1152
+ else:
1153
+ for child in getattr(node, 'children', []):
1154
+ self._walk(child)
1155
+ ```
1156
+
1157
+ Explanation:
1158
+
1159
+ - This is recursive tree walking.
1160
+ - It looks for a method named after the node type, such as `_check_FunctionDeclaration`.
1161
+ - If a specific handler exists, it uses it.
1162
+ - Otherwise, it walks all children by default.
1163
+
1164
+ Code:
1165
+
1166
+ ```python
1167
+ def _check_FunctionDeclaration(self, node):
1168
+ if not node.value:
1169
+ self.errors.append("Function declaration missing name")
1170
+ prev_in_func = self._in_function
1171
+ prev_func_type = self._current_func_type
1172
+ self._in_function = True
1173
+ if node.children:
1174
+ self._current_func_type = node.children[0].value
1175
+ ```
1176
+
1177
+ Explanation:
1178
+
1179
+ - Verifies the function has a name.
1180
+ - Saves previous context before entering this function.
1181
+ - Sets current function information while walking the body.
1182
+
1183
+ Code:
1184
+
1185
+ ```python
1186
+ for child in node.children:
1187
+ self._walk(child)
1188
+ self._in_function = prev_in_func
1189
+ self._current_func_type = prev_func_type
1190
+ ```
1191
+
1192
+ Explanation:
1193
+
1194
+ - Walks return type, parameters, and body.
1195
+ - Restores previous context afterward.
1196
+ - This prevents one function's context from leaking into another.
1197
+
1198
+ Code:
1199
+
1200
+ ```python
1201
+ def _check_ForLoop(self, node):
1202
+ self._in_loop += 1
1203
+ for child in node.children:
1204
+ self._walk(child)
1205
+ self._in_loop -= 1
1206
+ ```
1207
+
1208
+ Explanation:
1209
+
1210
+ - Marks that validation is inside a loop.
1211
+ - Validates all loop children.
1212
+ - Decrements loop depth afterward.
1213
+
1214
+ Code:
1215
+
1216
+ ```python
1217
+ def _check_Switch(self, node):
1218
+ self._in_switch += 1
1219
+ for child in node.children:
1220
+ self._walk(child)
1221
+ self._in_switch -= 1
1222
+ ```
1223
+
1224
+ Explanation:
1225
+
1226
+ - Marks that validation is inside a `harvest` switch.
1227
+ - Needed because `prune` is valid inside a switch.
1228
+
1229
+ Code:
1230
+
1231
+ ```python
1232
+ def _check_Break(self, node):
1233
+ if self._in_loop == 0 and self._in_switch == 0:
1234
+ self.errors.append("'prune' used outside a loop or switch")
1235
+ ```
1236
+
1237
+ Explanation:
1238
+
1239
+ - `prune` is only valid in loops or harvest/switch blocks.
1240
+ - If there is no loop or switch context, it is a semantic error.
1241
+
1242
+ Code:
1243
+
1244
+ ```python
1245
+ def _check_Continue(self, node):
1246
+ if self._in_loop == 0:
1247
+ self.errors.append("'skip' used outside a loop")
1248
+ ```
1249
+
1250
+ Explanation:
1251
+
1252
+ - `skip` only makes sense inside loops.
1253
+ - Using it elsewhere is syntactically possible but semantically wrong.
1254
+
1255
+ Code:
1256
+
1257
+ ```python
1258
+ def validate_ast(ast, symbol_table_data):
1259
+ validator = ASTValidator()
1260
+ return validator.validate(ast, symbol_table_data)
1261
+ ```
1262
+
1263
+ Explanation:
1264
+
1265
+ - This is the public function called by `server.py`.
1266
+ - It creates a fresh validator for every compilation.
1267
+ - It returns a dictionary that the server can send as JSON.
1268
+
1269
+ ### 4. DEFENSE QUESTIONS
1270
+
1271
+ Q: Why validate semantics after AST construction?
1272
+
1273
+ A: The AST gives structured meaning. It is easier to validate loops, functions, returns, and nested statements after syntax is organized as a tree.
1274
+
1275
+ Q: Why use counters like `_in_loop` instead of booleans?
1276
+
1277
+ A: Loops can be nested. A counter correctly handles multiple levels of nesting.
1278
+
1279
+ Q: Why collect errors instead of immediately throwing?
1280
+
1281
+ A: The validator can gather semantic issues in a structured result and return them to the frontend.
1282
+
1283
+ ### 5. MEMORIZED EXPLANATION
1284
+
1285
+ `validate_ast()` is the semantic validation phase. It walks the AST and checks context-sensitive rules, such as whether `prune` and `skip` are used in valid locations and whether AST structures are complete.
1286
+
1287
+ ---
1288
+
1289
+ ## E. Backend/icg.py
1290
+
1291
+ ### 1. FILE PURPOSE
1292
+
1293
+ `icg.py` generates intermediate code, specifically three-address code or TAC. This is a lower-level representation of the program.
1294
+
1295
+ Pipeline position:
1296
+
1297
+ ```text
1298
+ validated token stream -> generate_icg() -> TAC list + TAC text
1299
+ ```
1300
+
1301
+ Important implementation detail:
1302
+
1303
+ - The ICG module reads tokens directly.
1304
+ - The server validates lexer, parser, AST, and semantic stages before calling ICG.
1305
+
1306
+ ### 2. IMPORTS / DEPENDENCIES
1307
+
1308
+ Code:
1309
+
1310
+ ```python
1311
+ from __future__ import annotations
1312
+ from dataclasses import dataclass, field
1313
+ from typing import Any, Dict, List, Optional, Tuple
1314
+ ```
1315
+
1316
+ Explanation:
1317
+
1318
+ - Future annotations support cleaner type hints.
1319
+ - `dataclass` is used for token views and TAC instructions.
1320
+ - `typing` documents the structures passed around.
1321
+ - `field` appears possibly unused in this file; do not remove during defense unless verified.
1322
+
1323
+ ### 3. GLOBAL CONSTANTS / VARIABLES
1324
+
1325
+ Code:
1326
+
1327
+ ```python
1328
+ GAL_TYPE_MAP = {
1329
+ "seed": "int",
1330
+ "tree": "float",
1331
+ "leaf": "char",
1332
+ "branch": "bool",
1333
+ "vine": "string",
1334
+ "empty": "void",
1335
+ }
1336
+ DATA_TYPE_TOKENS = set(GAL_TYPE_MAP.keys())
1337
+ ASSIGN_OPS = {"=", "+=", "-=", "*=", "/=", "%="}
1338
+ ```
1339
+
1340
+ Explanation:
1341
+
1342
+ - `GAL_TYPE_MAP` converts GAL type names into conventional intermediate-code type names.
1343
+ - `DATA_TYPE_TOKENS` lets the generator quickly ask whether a token is a type.
1344
+ - `ASSIGN_OPS` lists assignment operators that ICG can translate.
1345
+
1346
+ ### 4. CLASSES AND FUNCTIONS
1347
+
1348
+ `_Tok`
1349
+
1350
+ - Normalized token view for ICG.
1351
+
1352
+ `_as_tok(raw)`
1353
+
1354
+ - Converts lexer tokens or dictionaries into `_Tok`.
1355
+
1356
+ `TACInstruction`
1357
+
1358
+ - Represents one intermediate instruction with `op`, `arg1`, `arg2`, and `result`.
1359
+
1360
+ `ICGenerator`
1361
+
1362
+ - Main class that reads tokens and emits TAC.
1363
+
1364
+ `generate_icg(tokens)`
1365
+
1366
+ - Public API used by `server.py`.
1367
+
1368
+ ### 5. LINE-BY-LINE / BLOCK-BY-BLOCK EXPLANATION
1369
+
1370
+ Code:
1371
+
1372
+ ```python
1373
+ @dataclass(frozen=True)
1374
+ class _Tok:
1375
+ type: str
1376
+ value: str
1377
+ line: int
1378
+ col: int = 0
1379
+ ```
1380
+
1381
+ Explanation:
1382
+
1383
+ - Gives ICG a stable token format.
1384
+ - Prevents ICG from depending on the exact lexer `Token` class.
1385
+
1386
+ Code:
1387
+
1388
+ ```python
1389
+ @dataclass
1390
+ class TACInstruction:
1391
+ op: str
1392
+ arg1: Optional[str] = None
1393
+ arg2: Optional[str] = None
1394
+ result: Optional[str] = None
1395
+ ```
1396
+
1397
+ Explanation:
1398
+
1399
+ - Stores one TAC instruction.
1400
+ - `op` is the operation.
1401
+ - `arg1` and `arg2` are operands.
1402
+ - `result` is destination or label depending on the instruction.
1403
+
1404
+ Code:
1405
+
1406
+ ```python
1407
+ def __str__(self):
1408
+ if self.op == "LABEL":
1409
+ return f"{self.result}:"
1410
+ if self.op == "GOTO":
1411
+ return f"goto {self.result}"
1412
+ if self.op == "PRINT":
1413
+ return f"print {self.arg1}"
1414
+ ```
1415
+
1416
+ Explanation:
1417
+
1418
+ - Converts TAC objects into human-readable TAC text.
1419
+ - This is what `/api/icg` can display in the frontend.
1420
+
1421
+ Code:
1422
+
1423
+ ```python
1424
+ class ICGenerator:
1425
+ def __init__(self, tokens):
1426
+ self.tokens = self._prepare(tokens)
1427
+ self.pos = 0
1428
+ self.code = []
1429
+ self.errors = []
1430
+ self._temp_counter = 0
1431
+ self._label_counter = 0
1432
+ ```
1433
+
1434
+ Explanation:
1435
+
1436
+ - Prepares tokens by normalizing and skipping newlines.
1437
+ - `pos` tracks current token index.
1438
+ - `code` stores generated instructions.
1439
+ - `errors` stores ICG errors.
1440
+ - Counters generate temporary names and labels.
1441
+
1442
+ Code:
1443
+
1444
+ ```python
1445
+ def _prepare(self, raw_tokens):
1446
+ toks = []
1447
+ for t in raw_tokens:
1448
+ tv = _as_tok(t)
1449
+ if tv.type == "\n":
1450
+ continue
1451
+ toks.append(tv)
1452
+ ```
1453
+
1454
+ Explanation:
1455
+
1456
+ - Filters newline tokens, similar to parser and AST builder.
1457
+ - ICG does not need newline tokens to generate code.
1458
+
1459
+ Code:
1460
+
1461
+ ```python
1462
+ if not toks or toks[-1].type != "EOF":
1463
+ toks.append(_Tok("EOF", "EOF", last_line))
1464
+ ```
1465
+
1466
+ Explanation:
1467
+
1468
+ - Ensures the token stream has EOF.
1469
+ - EOF prevents reading beyond the input.
1470
+
1471
+ Code:
1472
+
1473
+ ```python
1474
+ def _emit(self, op, arg1=None, arg2=None, result=None):
1475
+ self.code.append(TACInstruction(op, arg1, arg2, result))
1476
+ ```
1477
+
1478
+ Explanation:
1479
+
1480
+ - Central helper for creating TAC.
1481
+ - Every declaration, expression, loop, and statement uses this to append instructions.
1482
+
1483
+ Code:
1484
+
1485
+ ```python
1486
+ def _new_temp(self):
1487
+ name = f"t{self._temp_counter}"
1488
+ self._temp_counter += 1
1489
+ return name
1490
+ ```
1491
+
1492
+ Explanation:
1493
+
1494
+ - Generates temporary variables like `t0`, `t1`.
1495
+ - Used for intermediate expression results.
1496
+
1497
+ Code:
1498
+
1499
+ ```python
1500
+ def _new_label(self):
1501
+ name = f"L{self._label_counter}"
1502
+ self._label_counter += 1
1503
+ return name
1504
+ ```
1505
+
1506
+ Explanation:
1507
+
1508
+ - Generates labels like `L0`, `L1`.
1509
+ - Used for jumps in loops and conditionals.
1510
+
1511
+ Code:
1512
+
1513
+ ```python
1514
+ def generate(self):
1515
+ try:
1516
+ self._program()
1517
+ except Exception as exc:
1518
+ self.errors.append(f"ICG internal error: {exc}")
1519
+ return self.code, self.errors
1520
+ ```
1521
+
1522
+ Explanation:
1523
+
1524
+ - Starts generating TAC from the whole program.
1525
+ - Catches unexpected generator failures.
1526
+ - Returns generated code and errors.
1527
+
1528
+ Code:
1529
+
1530
+ ```python
1531
+ def _program(self):
1532
+ self._global_declaration()
1533
+ self._function_definition()
1534
+ self._expect("root")
1535
+ self._expect("(")
1536
+ self._expect(")")
1537
+ self._expect("{")
1538
+ self._emit("FUNC", "root")
1539
+ ```
1540
+
1541
+ Explanation:
1542
+
1543
+ - Follows GAL program structure.
1544
+ - Handles globals and pollinate functions before `root`.
1545
+ - Emits a TAC function start for root.
1546
+
1547
+ Code:
1548
+
1549
+ ```python
1550
+ self._declaration()
1551
+ self._statement()
1552
+ ```
1553
+
1554
+ Explanation:
1555
+
1556
+ - Emits declarations first.
1557
+ - Emits executable statements next.
1558
+ - Mirrors the GAL rule that local declarations come before statements.
1559
+
1560
+ Code:
1561
+
1562
+ ```python
1563
+ if self._peek().type == "reclaim":
1564
+ self._advance()
1565
+ if self._peek().type != ";":
1566
+ val = self._expression()
1567
+ self._emit("RETURN", val)
1568
+ else:
1569
+ self._emit("RETURN")
1570
+ ```
1571
+
1572
+ Explanation:
1573
+
1574
+ - Converts `reclaim;` or `reclaim expression;` into TAC return.
1575
+ - For `root()`, return usually has no value.
1576
+
1577
+ Code:
1578
+
1579
+ ```python
1580
+ def _simple_stmt(self):
1581
+ if tok.type == "id":
1582
+ self._id_stmt()
1583
+ elif tok.type in ("water", "plant"):
1584
+ self._io_stmt()
1585
+ elif tok.type == "spring":
1586
+ self._conditional_stmt()
1587
+ elif tok.type in ("grow", "cultivate", "tend"):
1588
+ self._loop_stmt()
1589
+ ```
1590
+
1591
+ Explanation:
1592
+
1593
+ - Dispatches based on statement starter token.
1594
+ - Each GAL construct has its own TAC generation path.
1595
+
1596
+ Code:
1597
+
1598
+ ```python
1599
+ if op_tok.type == "=":
1600
+ self._emit("=", rhs, None, lhs)
1601
+ else:
1602
+ base_op = op_tok.type[0]
1603
+ tmp = self._new_temp()
1604
+ self._emit(base_op, lhs, rhs, tmp)
1605
+ self._emit("=", tmp, None, lhs)
1606
+ ```
1607
+
1608
+ Explanation:
1609
+
1610
+ - Assignment becomes one TAC instruction.
1611
+ - Compound assignment becomes operation plus assignment.
1612
+ - Example: `x += y` becomes `t0 = x + y`, then `x = t0`.
1613
+
1614
+ Code:
1615
+
1616
+ ```python
1617
+ def _while_loop(self):
1618
+ start_label = self._new_label()
1619
+ end_label = self._new_label()
1620
+ self._emit("LABEL", None, None, start_label)
1621
+ cond = self._expression()
1622
+ self._emit("IFFALSE", cond, None, end_label)
1623
+ self._statement()
1624
+ self._emit("GOTO", None, None, start_label)
1625
+ self._emit("LABEL", None, None, end_label)
1626
+ ```
1627
+
1628
+ Explanation:
1629
+
1630
+ - `grow` loop is translated into labels and jumps.
1631
+ - If condition is false, jump to end.
1632
+ - After body, jump back to start.
1633
+
1634
+ Code:
1635
+
1636
+ ```python
1637
+ def _expression(self):
1638
+ return self._logic_or()
1639
+ ```
1640
+
1641
+ Explanation:
1642
+
1643
+ - Expression generation starts at the lowest precedence level.
1644
+ - Deeper functions handle logical, relational, arithmetic, and factor parsing.
1645
+
1646
+ Code:
1647
+
1648
+ ```python
1649
+ def generate_icg(tokens):
1650
+ gen = ICGenerator(tokens)
1651
+ code, errors = gen.generate()
1652
+ tac_dicts = [instr.to_dict() for instr in code]
1653
+ tac_text = "\n".join(str(instr) for instr in code)
1654
+ return {...}
1655
+ ```
1656
+
1657
+ Explanation:
1658
+
1659
+ - Public API called by `server.py`.
1660
+ - Creates a generator, runs it, converts instructions to JSON-friendly dictionaries and readable text.
1661
+
1662
+ ### 6. DEFENSE QUESTIONS
1663
+
1664
+ Q: Why have ICG if the interpreter can run the AST?
1665
+
1666
+ A: ICG shows an intermediate compiler representation. It can be used for future optimization or target-code generation, while the interpreter is for immediate execution.
1667
+
1668
+ Q: Why use temporary variables?
1669
+
1670
+ A: TAC breaks complex expressions into simple operations with at most two operands.
1671
+
1672
+ Q: Why use labels?
1673
+
1674
+ A: Loops and conditionals need jump targets. Labels represent those targets.
1675
+
1676
+ ### 7. WALKTHROUGH EXAMPLE
1677
+
1678
+ For the sample program, ICG output is:
1679
+
1680
+ ```text
1681
+ func root:
1682
+ declare age : int
1683
+ age = 10
1684
+ print age
1685
+ return
1686
+ endfunc
1687
+ ```
1688
+
1689
+ ### 8. MEMORIZED EXPLANATION
1690
+
1691
+ `icg.py` converts validated GAL tokens into three-address code. It emits declarations, assignments, labels, jumps, input/output, function calls, and returns. It is separate from execution because it represents the compiler's intermediate form.
1692
+
1693
+ ---
1694
+
1695
+ ## F. Backend/GALinterpreter.py
1696
+
1697
+ ### 1. FILE PURPOSE
1698
+
1699
+ `GALinterpreter.py` is the execution engine. It walks the validated AST and performs the actual program behavior.
1700
+
1701
+ Pipeline position:
1702
+
1703
+ ```text
1704
+ validated AST -> Interpreter.interpret(ast) -> runtime output / input / errors
1705
+ ```
1706
+
1707
+ ### 2. IMPORTS / DEPENDENCIES
1708
+
1709
+ Code:
1710
+
1711
+ ```python
1712
+ from GALsemantic import (ProgramNode, VariableDeclarationNode, AssignmentNode, ...)
1713
+ import threading
1714
+ import sys
1715
+ sys.setrecursionlimit(10000)
1716
+ ```
1717
+
1718
+ Explanation:
1719
+
1720
+ - Imports AST node classes so the interpreter can identify node types.
1721
+ - `threading` is fallback support for input waiting.
1722
+ - `sys.setrecursionlimit(10000)` allows deeper recursive interpretation/function calls.
1723
+
1724
+ Code:
1725
+
1726
+ ```python
1727
+ try:
1728
+ import eventlet.event as _ev
1729
+ _USE_EVENTLET = True
1730
+ except ImportError:
1731
+ _USE_EVENTLET = False
1732
+ ```
1733
+
1734
+ Explanation:
1735
+
1736
+ - Uses eventlet events when available.
1737
+ - Eventlet lets `water()` wait without blocking the whole Socket.IO server.
1738
+ - Falls back to threading events if eventlet is unavailable.
1739
+
1740
+ ### 3. GLOBAL CONSTANTS / VARIABLES
1741
+
1742
+ There are no major global compiler constants here. The runtime state is inside each `Interpreter` object:
1743
+
1744
+ - variables
1745
+ - functions
1746
+ - scopes
1747
+ - bundle types
1748
+ - input events
1749
+ - output socket
1750
+ - loop flags
1751
+
1752
+ ### 4. CLASSES AND FUNCTIONS
1753
+
1754
+ `ReturnValue`
1755
+
1756
+ - Internal exception used to implement `reclaim`.
1757
+ - Carries return value out of a function body.
1758
+
1759
+ `_CancelledError`
1760
+
1761
+ - Raised when a previous interpreter is cancelled by a new run.
1762
+
1763
+ `InterpreterError`
1764
+
1765
+ - Runtime error with line-numbered message.
1766
+
1767
+ `Interpreter`
1768
+
1769
+ - Main runtime class.
1770
+ - Executes AST nodes.
1771
+ - Stores variables, functions, scopes, bundle types, loop flags, and input state.
1772
+
1773
+ ### 5. LINE-BY-LINE / BLOCK-BY-BLOCK EXPLANATION
1774
+
1775
+ Code:
1776
+
1777
+ ```python
1778
+ class Interpreter:
1779
+ def __init__(self, socketio=None):
1780
+ self.output = []
1781
+ self.loop_stack = []
1782
+ self.break_flag = False
1783
+ self.continue_flag = False
1784
+ self.input_required = False
1785
+ self.socketio = socketio
1786
+ ```
1787
+
1788
+ Explanation:
1789
+
1790
+ - Creates one runtime environment.
1791
+ - `output` stores printed output in compatibility paths.
1792
+ - `loop_stack`, `break_flag`, and `continue_flag` implement `prune` and `skip`.
1793
+ - `input_required` marks whether `water()` is waiting.
1794
+ - `socketio` receives output and input events.
1795
+
1796
+ Code:
1797
+
1798
+ ```python
1799
+ self.input_events = {}
1800
+ self.input_values = {}
1801
+ self.variables = {}
1802
+ self.global_variables = {}
1803
+ self.functions = {}
1804
+ self.scopes = [{}]
1805
+ self.current_func_name = None
1806
+ self.function_variables = {}
1807
+ self.bundle_types = {}
1808
+ ```
1809
+
1810
+ Explanation:
1811
+
1812
+ - `input_events` stores waiting input requests.
1813
+ - `input_values` stores input that arrived early.
1814
+ - `variables` and `global_variables` store runtime values.
1815
+ - `functions` stores function declarations.
1816
+ - `scopes` models local scope stack.
1817
+ - `bundle_types` stores struct-like type definitions.
1818
+
1819
+ Code:
1820
+
1821
+ ```python
1822
+ def declare_variable(self, name, type_, value=None, is_list=False, is_fertile=False):
1823
+ scope = self.scopes[-1]
1824
+ if name not in self.scopes[-1]:
1825
+ scope[name] = {
1826
+ "type": type_,
1827
+ "value": value,
1828
+ "is_list": is_list,
1829
+ "is_fertile": is_fertile
1830
+ }
1831
+ ```
1832
+
1833
+ Explanation:
1834
+
1835
+ - Stores a variable in the current runtime scope.
1836
+ - Keeps type, value, array/list flag, and constant flag.
1837
+
1838
+ Code:
1839
+
1840
+ ```python
1841
+ def lookup_variable(self, name):
1842
+ for scope in reversed(self.scopes):
1843
+ if name in scope:
1844
+ return scope[name]
1845
+ if name in self.variables:
1846
+ return self.variables[name]
1847
+ return f"Semantic Error: Variable '{name}' used before declaration."
1848
+ ```
1849
+
1850
+ Explanation:
1851
+
1852
+ - Searches from innermost scope outward.
1853
+ - Falls back to global variables.
1854
+ - Returns an error string if variable does not exist.
1855
+
1856
+ Code:
1857
+
1858
+ ```python
1859
+ def interpret(self, node):
1860
+ if isinstance(node, ProgramNode):
1861
+ return self.eval_program(node)
1862
+ elif isinstance(node, VariableDeclarationNode):
1863
+ return self.eval_variable_declaration(node)
1864
+ elif isinstance(node, AssignmentNode):
1865
+ return self.eval_assignment(node)
1866
+ ```
1867
+
1868
+ Explanation:
1869
+
1870
+ - This is the main AST dispatcher.
1871
+ - Each node type is routed to the correct evaluator.
1872
+ - This is how the interpreter walks and executes the AST.
1873
+
1874
+ Code:
1875
+
1876
+ ```python
1877
+ elif node.node_type == "Identifier":
1878
+ var_info = self.lookup_variable(node.value)
1879
+ if isinstance(var_info, str):
1880
+ raise InterpreterError(var_info, node.line)
1881
+ return var_info["value"]
1882
+ ```
1883
+
1884
+ Explanation:
1885
+
1886
+ - Identifier evaluation means reading the current runtime value.
1887
+ - If the variable is missing, execution stops with an error.
1888
+
1889
+ Code:
1890
+
1891
+ ```python
1892
+ def eval_program(self, node):
1893
+ for child in node.children:
1894
+ self.interpret(child)
1895
+ main_call = FunctionCallNode("root", [], node.line)
1896
+ return self.interpret(main_call)
1897
+ ```
1898
+
1899
+ Explanation:
1900
+
1901
+ - First registers global declarations, bundles, and functions.
1902
+ - Then creates a call to `root()`.
1903
+ - This implements GAL's entry point rule.
1904
+
1905
+ Code:
1906
+
1907
+ ```python
1908
+ def eval_variable_declaration(self, node):
1909
+ var_type = node.children[0].value
1910
+ var_name = node.children[1].value
1911
+ value_node = node.children[2] if len(node.children) > 2 else None
1912
+ ```
1913
+
1914
+ Explanation:
1915
+
1916
+ - Reads type, name, and optional initializer from AST children.
1917
+ - The interpreter relies on the AST layout created by `VariableDeclarationNode`.
1918
+
1919
+ Code:
1920
+
1921
+ ```python
1922
+ default_values = {
1923
+ "seed": 0,
1924
+ "tree": 0.0,
1925
+ "leaf": '',
1926
+ "vine": "",
1927
+ "branch": False,
1928
+ }
1929
+ ```
1930
+
1931
+ Explanation:
1932
+
1933
+ - Provides default values for declarations without initializers.
1934
+ - Example: `seed x;` becomes `x = 0` at runtime.
1935
+
1936
+ Code:
1937
+
1938
+ ```python
1939
+ if value_node:
1940
+ value = self.interpret(value_node)
1941
+ if var_type == "seed" and isinstance(value, float):
1942
+ value = int(value)
1943
+ else:
1944
+ value = default_values.get(var_type, None)
1945
+ ```
1946
+
1947
+ Explanation:
1948
+
1949
+ - If there is an initializer, evaluate it.
1950
+ - If the variable is `seed` and value is float, convert to int.
1951
+ - If there is no initializer, use default value.
1952
+
1953
+ Code:
1954
+
1955
+ ```python
1956
+ self.declare_variable(var_name, var_type, value, is_list=is_list)
1957
+ ```
1958
+
1959
+ Explanation:
1960
+
1961
+ - Stores the variable in the current runtime scope.
1962
+ - After this line, later statements can access the variable.
1963
+
1964
+ Code:
1965
+
1966
+ ```python
1967
+ def eval_assignment(self, node):
1968
+ target_node = node.children[0]
1969
+ value_node = node.children[1]
1970
+ value = self.interpret(value_node)
1971
+ ```
1972
+
1973
+ Explanation:
1974
+
1975
+ - Evaluates the right-hand side first.
1976
+ - Then assigns it to the target.
1977
+ - The target can be a normal variable, list element, or bundle member.
1978
+
1979
+ Code:
1980
+
1981
+ ```python
1982
+ if target_node.node_type == "ListAccess":
1983
+ indices = []
1984
+ current = target_node
1985
+ while current.node_type == "ListAccess":
1986
+ idx = self.interpret(current.children[1].children[0])
1987
+ if not isinstance(idx, int):
1988
+ raise InterpreterError(...)
1989
+ indices.append(idx)
1990
+ ```
1991
+
1992
+ Explanation:
1993
+
1994
+ - Handles assignment to array/list elements.
1995
+ - Evaluates each index expression.
1996
+ - Requires indexes to be integers.
1997
+
1998
+ Code:
1999
+
2000
+ ```python
2001
+ if final_idx < 0 or final_idx >= len(target):
2002
+ raise InterpreterError("Index out of bounds", node.line)
2003
+ target[final_idx] = value
2004
+ ```
2005
+
2006
+ Explanation:
2007
+
2008
+ - Performs runtime bounds check.
2009
+ - Writes the new value.
2010
+ - Current implementation uses 0-based indexing. This differs from the GAL PDF's 1-based rule.
2011
+
2012
+ Code:
2013
+
2014
+ ```python
2015
+ def eval_binary_op(self, node):
2016
+ left = self.interpret(node.children[0])
2017
+ right = self.interpret(node.children[1])
2018
+ operator = node.value
2019
+ ```
2020
+
2021
+ Explanation:
2022
+
2023
+ - Evaluates both operands recursively.
2024
+ - Reads the operator from the AST node.
2025
+
2026
+ Code:
2027
+
2028
+ ```python
2029
+ if operator == '`':
2030
+ result = str(left) + str(right)
2031
+ return result
2032
+ ```
2033
+
2034
+ Explanation:
2035
+
2036
+ - Implements GAL string concatenation using backtick.
2037
+ - Converts both operands to string.
2038
+
2039
+ Code:
2040
+
2041
+ ```python
2042
+ elif operator == '/':
2043
+ if right == 0:
2044
+ raise InterpreterError("Runtime Error: Division by zero is undefined", node.line)
2045
+ return left / right
2046
+ ```
2047
+
2048
+ Explanation:
2049
+
2050
+ - Executes division.
2051
+ - Checks division by zero at runtime because actual values are known only during execution.
2052
+
2053
+ Code:
2054
+
2055
+ ```python
2056
+ def eval_block(self, block_node):
2057
+ for statement in block_node.children:
2058
+ self.interpret(statement)
2059
+ if self.break_triggered():
2060
+ return
2061
+ if self.continue_flag:
2062
+ return
2063
+ ```
2064
+
2065
+ Explanation:
2066
+
2067
+ - Executes statements in source order.
2068
+ - Stops block execution if `prune` or `skip` changes control flow.
2069
+
2070
+ Code:
2071
+
2072
+ ```python
2073
+ def plant(self, value):
2074
+ self.socketio.emit('output', {'output': str(value)})
2075
+ ```
2076
+
2077
+ Explanation:
2078
+
2079
+ - Implements output.
2080
+ - The interpreter emits to whatever socket-like object it was given.
2081
+ - In Socket.IO mode, output goes live to the frontend.
2082
+ - In REST mode, `OutputCollector` catches it.
2083
+
2084
+ Code:
2085
+
2086
+ ```python
2087
+ def eval_return(self, node):
2088
+ value = self.interpret(node.children[0]) if node.children else None
2089
+ raise ReturnValue(value)
2090
+ ```
2091
+
2092
+ Explanation:
2093
+
2094
+ - Implements `reclaim`.
2095
+ - Raises `ReturnValue` to immediately exit the current function.
2096
+ - Carries return value if present.
2097
+
2098
+ Code:
2099
+
2100
+ ```python
2101
+ def eval_function_call(self, node):
2102
+ function_name = node.value
2103
+ args = [self.interpret(arg.children[0]) for arg in node.children]
2104
+ func_info = self.lookup_function(function_name)
2105
+ ```
2106
+
2107
+ Explanation:
2108
+
2109
+ - Evaluates function call arguments.
2110
+ - Looks up the function declaration.
2111
+
2112
+ Code:
2113
+
2114
+ ```python
2115
+ self.enter_scope()
2116
+ try:
2117
+ for i, param in enumerate(expected_params):
2118
+ self.declare_variable(param_name, param_type, arg_value, is_list=is_list)
2119
+ self.eval_block(function_node.children[2])
2120
+ except ReturnValue as ret:
2121
+ return ret.value
2122
+ finally:
2123
+ self.exit_scope()
2124
+ ```
2125
+
2126
+ Explanation:
2127
+
2128
+ - Function call creates a new local scope.
2129
+ - Parameters become local variables.
2130
+ - Function body executes.
2131
+ - `ReturnValue` captures `reclaim`.
2132
+ - Scope is cleaned up after the call.
2133
+
2134
+ Code:
2135
+
2136
+ ```python
2137
+ def provide_input(self, var_name, input_value):
2138
+ evt = self.input_events.get(var_name)
2139
+ if evt is None:
2140
+ self.input_values[var_name] = input_value
2141
+ return
2142
+ ```
2143
+
2144
+ Explanation:
2145
+
2146
+ - Receives input from `server.py`.
2147
+ - If interpreter is not waiting yet, stores the value.
2148
+ - Prevents lost input.
2149
+
2150
+ Code:
2151
+
2152
+ ```python
2153
+ def wait_for_input(self, var_name):
2154
+ if var_name in self.input_values:
2155
+ return self.input_values.pop(var_name)
2156
+ ```
2157
+
2158
+ Explanation:
2159
+
2160
+ - If input already arrived, returns it immediately.
2161
+ - Otherwise waits for eventlet/threading event.
2162
+
2163
+ Code:
2164
+
2165
+ ```python
2166
+ def eval_input(self, node):
2167
+ parent_node = node.parent
2168
+ if isinstance(parent_node, VariableDeclarationNode):
2169
+ var_name = parent_node.children[1].value
2170
+ var_type = parent_node.children[0].value
2171
+ ```
2172
+
2173
+ Explanation:
2174
+
2175
+ - Figures out where `water()` is being used.
2176
+ - If it is inside a declaration, the target variable and type come from the parent declaration.
2177
+
2178
+ Code:
2179
+
2180
+ ```python
2181
+ self.emit_input_request(var_name, prompt)
2182
+ input_value = self.wait_for_input(var_name)
2183
+ ```
2184
+
2185
+ Explanation:
2186
+
2187
+ - Tells the frontend input is needed.
2188
+ - Waits until the user responds.
2189
+
2190
+ Code:
2191
+
2192
+ ```python
2193
+ if var_type == "seed":
2194
+ if input_value.startswith('-'):
2195
+ raise InterpreterError("GAL uses '~' for negative numbers", node.line)
2196
+ if input_value.startswith('~'):
2197
+ input_value = '-' + input_value[1:]
2198
+ input_value = int(float(input_value))
2199
+ ```
2200
+
2201
+ Explanation:
2202
+
2203
+ - Converts input string to integer.
2204
+ - Enforces GAL negative syntax using `~` instead of `-`.
2205
+ - Raises runtime error if conversion fails.
2206
+
2207
+ ### 6. DEFENSE QUESTIONS
2208
+
2209
+ Q: Why execute the AST instead of tokens?
2210
+
2211
+ A: Tokens are flat. The AST already shows program structure, so execution can naturally follow blocks, expressions, functions, and control flow.
2212
+
2213
+ Q: Why does `reclaim` use an exception?
2214
+
2215
+ A: A return must immediately exit the current function, even from nested blocks. `ReturnValue` carries the return value out cleanly.
2216
+
2217
+ Q: How does `plant()` output reach the frontend?
2218
+
2219
+ A: The interpreter calls `self.socketio.emit('output', ...)`. In live mode this is Socket.IO; in REST mode it is an `OutputCollector`.
2220
+
2221
+ Q: How does `water()` work?
2222
+
2223
+ A: The interpreter emits an input request, waits on an event, and `server.py` later calls `provide_input()` when the frontend sends user input.
2224
+
2225
+ Q: What array indexing issue should you mention?
2226
+
2227
+ A: The GAL document says arrays are 1-based, but the interpreter currently checks `index < 0` and accesses `list_value[index]`, so runtime behavior is 0-based.
2228
+
2229
+ ### 7. WALKTHROUGH EXAMPLE
2230
+
2231
+ For:
2232
+
2233
+ ```gal
2234
+ root() {
2235
+ seed age = 10;
2236
+ plant(age);
2237
+ reclaim;
2238
+ }
2239
+ ```
2240
+
2241
+ Execution steps:
2242
+
2243
+ 1. `eval_program()` registers declarations and functions.
2244
+ 2. It creates a `FunctionCallNode("root", [])`.
2245
+ 3. `eval_function_call()` enters a scope for root.
2246
+ 4. `eval_variable_declaration()` stores `age` as a `seed` with value `10`.
2247
+ 5. `eval_print()` reads `age` and emits `10`.
2248
+ 6. `eval_return()` raises `ReturnValue(None)`.
2249
+ 7. The function call catches return and exits.
2250
+ 8. `server.py` returns output to frontend.
2251
+
2252
+ ### 8. MEMORIZED EXPLANATION
2253
+
2254
+ `GALinterpreter.py` is the runtime engine. It walks the AST, stores variables in scopes, registers functions, evaluates expressions, executes loops and conditionals, handles `plant()` output, handles `water()` input, and uses `ReturnValue` to implement `reclaim`.
2255
+
2256
+ ---
2257
+
2258
+ # Final Full-Pipeline Defense Explanation
2259
+
2260
+ `server.py` receives source code from the frontend. It sends the raw text to `lexer.py`, which converts characters into tokens and reports lexical errors. Those tokens go to `Gal_Parser.py`, which uses the grammar and PREDICT sets from `cfg.py` to validate syntax with LL(1) parsing. If syntax succeeds, `parse_and_build()` calls the AST builder in `GALsemantic.py`. The AST builder creates structured nodes and a symbol table. Then `validate_ast()` walks the AST for semantic checks. If the user requests ICG, `icg.py` generates three-address code. If the user runs the program, `GALinterpreter.py` walks the AST, calls `root()`, executes declarations, statements, expressions, functions, loops, `plant()`, `water()`, and `reclaim`, then sends the output back through the server.
2261
+
2262
+ # Common Panel Questions For The Whole System
2263
+
2264
+ Q: Why did you separate the compiler into files?
2265
+
2266
+ A: Each file represents a compiler responsibility. Lexer handles characters, parser handles grammar, AST/semantic handles meaning, ICG handles intermediate representation, and interpreter handles execution.
2267
+
2268
+ Q: What happens if lexical analysis fails?
2269
+
2270
+ A: The server stops immediately and returns lexical errors. Parser does not run because invalid tokens would make syntax analysis unreliable.
2271
+
2272
+ Q: What happens if syntax analysis fails?
2273
+
2274
+ A: AST construction does not happen. The server returns syntax errors from the parser.
2275
+
2276
+ Q: What happens if semantic analysis fails?
2277
+
2278
+ A: ICG and interpreter are skipped. The server returns semantic errors.
2279
+
2280
+ Q: What happens if runtime execution fails?
2281
+
2282
+ A: The interpreter raises `InterpreterError`; `server.py` catches it and sends a runtime error to the frontend.
2283
+
2284
+ Q: Why is `root()` called by the interpreter instead of just executing top to bottom?
2285
+
2286
+ A: Top-level declarations and function definitions must be registered first. Actual program execution begins at `root()`, as required by the GAL specification.
2287
+
2288
+ Q: What is one known implementation/spec mismatch?
2289
+
2290
+ A: The GAL PDF specifies 1-based arrays, but the current interpreter uses 0-based indexing for lists/vines. That should be acknowledged honestly during defense.
Docus & mps/DEFENSE_FULL_PIPELINE.md ADDED
The diff for this file is too large to render. See raw diff
 
Docus & mps/DEFENSE_FULL_PIPELINE.pdf ADDED
The diff for this file is too large to render. See raw diff
 
GAL_COMPILER_KNOWLEDGE_BASE.md → Docus & mps/GAL_COMPILER_KNOWLEDGE_BASE.md RENAMED
File without changes
GAL_PROGRAMS_EXPLANATION.pdf.md → Docus & mps/GAL_PROGRAMS_EXPLANATION.pdf.md RENAMED
File without changes
GAL_RESERVED_WORDS_EXPLANATION.md → Docus & mps/GAL_RESERVED_WORDS_EXPLANATION.md RENAMED
File without changes
GAL_RESERVED_WORDS_EXPLANATION.pdf → Docus & mps/GAL_RESERVED_WORDS_EXPLANATION.pdf RENAMED
File without changes
GAL_SYSTEM_DOCUMENTATION.md → Docus & mps/GAL_SYSTEM_DOCUMENTATION.md RENAMED
File without changes
Docus & mps/cfg_to_pred_extracted.txt ADDED
@@ -0,0 +1,943 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ BERCASIO, E. M. S. MIRALLES, K. L.
2
+ BAYNA, C. L. TARINO, J. L. A.
3
+ HULIGANGA, S. K. E. TOMINIO, M.
4
+ RAMOS, J. GrowALanguage
5
+
6
+
7
+
8
+ 78
9
+ X. CONTEXT-FREE GRAMMAR
10
+
11
+ # Production Production Set
12
+ 1 <program> -> <global_declaration> <function_definition> root ( ) { <statement> }
13
+ 2 <global_declaration> -> bundle id <bundle_or_var> <global_declaration>
14
+ 3 <global_declaration> -> <data_type> id <array_dec> <var_value> ; <global_declaration>
15
+ 4 <global_declaration> -> fertile <data_type> id = <init_val> <const_next> ; <global_declaration>
16
+ 5 <global_declaration> -> λ
17
+ 6 <bundle_or_var> -> { <bundle_members> } ;
18
+ 7 <bundle_or_var> -> <bundle_mem_dec> ;
19
+ 8 <declaration> -> <var_dec> ; <declaration>
20
+ 9 <declaration> -> <const_dec> ; <declaration>
21
+ 10 <declaration> -> λ
22
+ 11 <data_type> -> seed
23
+ 12 <data_type> -> tree
24
+ 13 <data_type> -> leaf
25
+ 14 <data_type> -> branch
26
+ BERCASIO, E. M. S. MIRALLES, K. L.
27
+ BAYNA, C. L. TARINO, J. L. A.
28
+ HULIGANGA, S. K. E. TOMINIO, M.
29
+ RAMOS, J. GrowALanguage
30
+
31
+
32
+
33
+ 79
34
+ 15 <data_type> -> vine
35
+ 16 <const_dec> -> fertile <data_type> id = <init_val> <const_next>
36
+ 17 <const_next> -> , id = <init_val> <const_next>
37
+ 18 <const_next> -> λ
38
+ 19 <var_dec> -> <data_type> id <array_dec> <var_value>
39
+ 20 <var_dec> -> bundle id <bundle_mem_dec>
40
+ 21 <bundle_mem_dec> -> id <array_dec> <var_value_next>
41
+ 22 <bundle_mem_dec> -> , id <var_value_next>
42
+ 23 <bundle_mem_dec> -> λ
43
+ 24 <var_value> -> = <init_val> <var_value_next>
44
+ 25 <var_value> -> <var_value_next>
45
+ 26 <var_value_next> -> , id <array_dec> <var_value>
46
+ 27 <var_value_next> -> λ
47
+ 28 <init_val> -> <array_init_opt>
48
+ 29 <init_val> -> water ( <water_arg> )
49
+ 30 <init_val> -> <expression>
50
+ 31 <array_dec> -> [ <array_dim_opt> ] <array_dec>
51
+ BERCASIO, E. M. S. MIRALLES, K. L.
52
+ BAYNA, C. L. TARINO, J. L. A.
53
+ HULIGANGA, S. K. E. TOMINIO, M.
54
+ RAMOS, J. GrowALanguage
55
+
56
+
57
+
58
+ 80
59
+ 32 <array_dec> -> λ
60
+ 33 <array_dim_opt> -> intlit
61
+ 34 <array_dim_opt> -> dblit
62
+ 35 <array_dim_opt> -> λ
63
+ 36 <array_init_opt> -> { <init_vals> }
64
+ 37 <array_init_opt> -> λ
65
+ 38 <init_vals> -> <init_val_item> <init_vals_next>
66
+ 39 <init_vals> -> λ
67
+ 40 <init_vals_next> -> , <init_val_item> <init_vals_next>
68
+ 41 <init_vals_next> -> λ
69
+ 42 <init_val_item> -> { <init_vals> }
70
+ 43 <init_val_item> -> <expression>
71
+ 44 <bundle_declaration> -> bundle id { <bundle_members> }
72
+ 45 <bundle_members> -> <data_type> id ; <bundle_members>
73
+ 46 <bundle_members> -> id id ; <bundle_members>
74
+ 47 <bundle_members> -> λ
75
+ 48 <function_definition> -> pollinate <return_type> id ( <parameters> ) { <statement> } <function_definition>
76
+ BERCASIO, E. M. S. MIRALLES, K. L.
77
+ BAYNA, C. L. TARINO, J. L. A.
78
+ HULIGANGA, S. K. E. TOMINIO, M.
79
+ RAMOS, J. GrowALanguage
80
+
81
+
82
+
83
+ 81
84
+ 49 <function_definition> -> λ
85
+ 50 <return_type> -> <data_type>
86
+ 51 <return_type> -> empty
87
+ 52 <return_type> -> id
88
+ 53 <parameters> -> λ
89
+ 54 <parameters> -> <param> <param_next>
90
+ 55 <param> -> <data_type> id <param_array>
91
+ 56 <param> -> id id
92
+ 57 <param_array> -> λ
93
+ 58 <param_array> -> [ ]
94
+ 59 <param_next> -> λ
95
+ 60 <param_next> -> , <param> <param_next>
96
+ 61 <reclaim_opt> -> reclaim <reclaim_value>
97
+ 62 <reclaim_opt> -> λ
98
+ 63 <reclaim_value> -> <expression> ;
99
+ 64 <reclaim_value> -> ;
100
+ 65 <statement> -> <simple_stmt> <statement>
101
+ BERCASIO, E. M. S. MIRALLES, K. L.
102
+ BAYNA, C. L. TARINO, J. L. A.
103
+ HULIGANGA, S. K. E. TOMINIO, M.
104
+ RAMOS, J. GrowALanguage
105
+
106
+
107
+
108
+ 82
109
+ 66 <statement> -> λ
110
+ 67 <simple_stmt> -> id <id_stmt>
111
+ 68 <simple_stmt> -> <inc_dec_op> id ;
112
+ 69 <simple_stmt> -> <io_stmt>
113
+ 70 <simple_stmt> -> <conditional_stmt>
114
+ 71 <simple_stmt> -> <loop_stmt>
115
+ 72 <simple_stmt> -> <switch_stmt>
116
+ 73 <simple_stmt> -> <control_stmt>
117
+ 74 <simple_stmt> -> reclaim <reclaim_value>
118
+ 75 <simple_stmt> -> <var_dec> ;
119
+ 76 <simple_stmt> -> <const_dec> ;
120
+ 77 <id_stmt> -> <id_next> <assign_op> <assign_rhs> ;
121
+ 78 <id_stmt> -> <inc_dec_op> ;
122
+ 79 <id_stmt> -> ( <arguments> ) ;
123
+ 80 <assignment_stmt> -> <value> <assign_op> <assign_rhs> ;
124
+ 81 <assign_rhs> -> water ( <water_arg> )
125
+ 82 <assign_rhs> -> <expression>
126
+ BERCASIO, E. M. S. MIRALLES, K. L.
127
+ BAYNA, C. L. TARINO, J. L. A.
128
+ HULIGANGA, S. K. E. TOMINIO, M.
129
+ RAMOS, J. GrowALanguage
130
+
131
+
132
+
133
+ 83
134
+ 83 <assign_op> -> =
135
+ 84 <assign_op> -> +=
136
+ 85 <assign_op> -> -=
137
+ 86 <assign_op> -> *=
138
+ 87 <assign_op> -> /=
139
+ 88 <assign_op> -> %=
140
+ 89 <value> -> id <id_next>
141
+ 90 <id_next> -> <array_access> <post_array_access>
142
+ 91 <id_next> -> <struct_access>
143
+ 92 <id_next> -> λ
144
+ 93 <array_access> -> [ <expression> ] <array_access_more>
145
+ 94 <array_access_more> -> [ <expression> ] <array_access_more>
146
+ 95 <array_access_more> -> λ
147
+ 96 <struct_access> -> . id <struct_access_more>
148
+ 97 <struct_access_more> -> . id <struct_access_more>
149
+ 98 <struct_access_more> -> λ
150
+ 99 <post_array_access> -> . id <post_array_access>
151
+ BERCASIO, E. M. S. MIRALLES, K. L.
152
+ BAYNA, C. L. TARINO, J. L. A.
153
+ HULIGANGA, S. K. E. TOMINIO, M.
154
+ RAMOS, J. GrowALanguage
155
+
156
+
157
+
158
+ 84
159
+ 100 <post_array_access> -> λ
160
+ 101 <io_stmt> -> plant ( <arguments> ) ;
161
+ 102 <io_stmt> -> water ( <water_arg> ) ;
162
+ 103 <water_arg> -> <data_type>
163
+ 104 <water_arg> -> id <water_id_tail>
164
+ 105 <water_arg> -> λ
165
+ 106 <water_id_tail> -> [ <expression> ] <water_id_tail>
166
+ 107 <water_id_tail> -> λ
167
+ 108 <arguments> -> <expression> <arg_next>
168
+ 109 <arguments> -> λ
169
+ 110 <arg_next> -> , <expression> <arg_next>
170
+ 111 <arg_next> -> λ
171
+ 112 <conditional_stmt> -> spring ( <expression> ) { <statement> } <elseif_chain> <else_opt>
172
+ 113 <elseif_chain> -> bud ( <expression> ) { <statement> } <elseif_chain>
173
+ 114 <elseif_chain> -> λ
174
+ 115 <else_opt> -> wither { <statement> }
175
+ 116 <else_opt> -> λ
176
+ BERCASIO, E. M. S. MIRALLES, K. L.
177
+ BAYNA, C. L. TARINO, J. L. A.
178
+ HULIGANGA, S. K. E. TOMINIO, M.
179
+ RAMOS, J. GrowALanguage
180
+
181
+
182
+
183
+ 85
184
+ 117 <loop_stmt> -> grow ( <expression> ) { <statement> }
185
+ 118 <loop_stmt> -> cultivate ( <for_init> ; <expression> ; <for_update> ) { <statement> }
186
+ 119 <loop_stmt> -> tend { <statement> } grow ( <expression> ) ;
187
+ 120 <for_init> -> <data_type> id <array_dec> <var_value>
188
+ 121 <for_init> -> id <id_next> <assign_op> <expression>
189
+ 122 <for_init> -> λ
190
+ 123 <for_update> -> id <for_update_type>
191
+ 124 <for_update> -> λ
192
+ 125 <for_update_type> -> <inc_dec_op>
193
+ 126 <for_update_type> -> <id_next> <assign_op> <expression>
194
+ 127 <unary_stmt> -> id <inc_dec_op> ;
195
+ 128 <inc_dec_op> -> ++
196
+ 129 <inc_dec_op> -> --
197
+ 130 <switch_stmt> -> harvest ( <expression> ) { <case_list> <default_opt> }
198
+ 131 <case_list> -> variety <case_literal> : <case_statements> <case_list>
199
+ 132 <case_list> -> λ
200
+ BERCASIO, E. M. S. MIRALLES, K. L.
201
+ BAYNA, C. L. TARINO, J. L. A.
202
+ HULIGANGA, S. K. E. TOMINIO, M.
203
+ RAMOS, J. GrowALanguage
204
+
205
+
206
+
207
+ 86
208
+ 133 <case_literal> -> intlit
209
+ 134 <case_literal> -> dblit
210
+ 135 <case_literal> -> chrlit
211
+ 136 <case_literal> -> stringlit
212
+ 137 <case_literal> -> sunshine
213
+ 138 <case_literal> -> frost
214
+ 139 <case_statements> -> <case_statement> <case_statements>
215
+ 140 <case_statements> -> λ
216
+ 141 <case_statement> -> id <id_stmt>
217
+ 142 <case_statement> -> <inc_dec_op> id ;
218
+ 143 <case_statement> -> <var_dec> ;
219
+ 144 <case_statement> -> <io_stmt>
220
+ 145 <case_statement> -> <conditional_stmt>
221
+ 146 <case_statement> -> <loop_stmt>
222
+ 147 <case_statement> -> <switch_stmt>
223
+ 148 <case_statement> -> { <case_statements> }
224
+ 149 <case_statement> -> prune ;
225
+ BERCASIO, E. M. S. MIRALLES, K. L.
226
+ BAYNA, C. L. TARINO, J. L. A.
227
+ HULIGANGA, S. K. E. TOMINIO, M.
228
+ RAMOS, J. GrowALanguage
229
+
230
+
231
+
232
+ 87
233
+ 150 <case_statement> -> skip ;
234
+ 151 <case_statement> -> reclaim <reclaim_value>
235
+ 152 <default_opt> -> soil : <case_statements>
236
+ 153 <default_opt> -> λ
237
+ 154 <control_stmt> -> prune ;
238
+ 155 <control_stmt> -> skip ;
239
+ 156 <function_call> -> id ( <arguments> ) ;
240
+ 157 <expression> -> <logic_or>
241
+ 158 <logic_or> -> <logic_and> <logic_or_next>
242
+ 159 <logic_or_next> -> || <logic_and> <logic_or_next>
243
+ 160 <logic_or_next> -> λ
244
+ 161 <logic_and> -> <relational> <logic_and_next>
245
+ 162 <logic_and_next> -> && <relational> <logic_and_next>
246
+ 163 <logic_and_next> -> λ
247
+ 164 <relational> -> <arithmetic> <relational_next>
248
+ 165 <relational_next> -> <relational_op> <arithmetic>
249
+ 166 <relational_next> -> λ
250
+ BERCASIO, E. M. S. MIRALLES, K. L.
251
+ BAYNA, C. L. TARINO, J. L. A.
252
+ HULIGANGA, S. K. E. TOMINIO, M.
253
+ RAMOS, J. GrowALanguage
254
+
255
+
256
+
257
+ 88
258
+ 167 <relational_op> -> >
259
+ 168 <relational_op> -> <
260
+ 169 <relational_op> -> >=
261
+ 170 <relational_op> -> <=
262
+ 171 <relational_op> -> ==
263
+ 172 <relational_op> -> !=
264
+ 173 <arithmetic> -> <term> <arithmetic_next>
265
+ 174 <arithmetic_next> -> + <term> <arithmetic_next>
266
+ 175 <arithmetic_next> -> - <term> <arithmetic_next>
267
+ 176 <arithmetic_next> -> ` <term> <arithmetic_next>
268
+ 177 <arithmetic_next> -> λ
269
+ 178 <term> -> <factor> <term_next>
270
+ 179 <term_next> -> * <factor> <term_next>
271
+ 180 <term_next> -> / <factor> <term_next>
272
+ 181 <term_next> -> % <factor> <term_next>
273
+ 182 <term_next> -> λ
274
+ 183 <factor> -> ( <paren_expr>
275
+ BERCASIO, E. M. S. MIRALLES, K. L.
276
+ BAYNA, C. L. TARINO, J. L. A.
277
+ HULIGANGA, S. K. E. TOMINIO, M.
278
+ RAMOS, J. GrowALanguage
279
+
280
+
281
+
282
+ 89
283
+ 184 <factor> -> <unary_op> <factor>
284
+ 185 <factor> -> id <factor_id_next>
285
+ 186 <factor> -> intlit
286
+ 187 <factor> -> dblit
287
+ 188 <factor> -> chrlit
288
+ 189 <factor> -> stringlit
289
+ 190 <factor> -> sunshine
290
+ 191 <factor> -> frost
291
+ 192 <paren_expr> -> <data_type> ) <factor>
292
+ 193 <paren_expr> -> <expression> )
293
+ 194 <unary_op> -> ~
294
+ 195 <unary_op> -> !
295
+ 196 <factor_id_next> -> <array_access> <post_array_access>
296
+ 197 <factor_id_next> -> <struct_access>
297
+ 198 <factor_id_next> -> ( <arguments> )
298
+ 199 <factor_id_next> -> λ
299
+
300
+
301
+
302
+ BERCASIO, E. M. S. MIRALLES, K. L.
303
+ BAYNA, C. L. TARINO, J. L. A.
304
+ HULIGANGA, S. K. E. TOMINIO, M.
305
+ RAMOS, J. GrowALanguage
306
+
307
+
308
+
309
+ 90
310
+ XI. FIRST SET
311
+
312
+ # Nonterminal -> First Set
313
+ 1 <global_declaration> -> { branch, bundle, fertile, leaf, seed, tree, vine, λ }
314
+ 2 <bundle_or_var> -> { ,, ;, id, { }
315
+ 3 <declaration> -> { branch, bundle, fertile, leaf, seed, tree, vine, λ }
316
+ 4 <data_type> -> { branch, leaf, seed, tree, vine }
317
+ 5 <const_dec> -> { fertile }
318
+ 6 <const_next> -> { ,, λ }
319
+ 7 <var_dec> -> { branch, bundle, leaf, seed, tree, vine }
320
+ 8 <bundle_mem_dec> -> { ,, id, λ }
321
+ 9 <var_value> -> { ,, =, λ }
322
+ 10 <var_value_next> -> { ,, λ }
323
+ 11 <init_val> -> { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, water, {,
324
+ ~, λ }
325
+ 12 <array_dec> -> { [, λ }
326
+ 13 <array_dim_opt> -> { dblit, intlit, λ }
327
+ 14 <array_init_opt> -> { {, λ }
328
+ BERCASIO, E. M. S. MIRALLES, K. L.
329
+ BAYNA, C. L. TARINO, J. L. A.
330
+ HULIGANGA, S. K. E. TOMINIO, M.
331
+ RAMOS, J. GrowALanguage
332
+
333
+
334
+
335
+ 91
336
+ 15 <init_vals> -> { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, {, ~, λ }
337
+ 16 <init_vals_next> -> { ,, λ }
338
+ 17 <init_val_item> -> { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, {, ~ }
339
+ 18 <bundle_declaration> -> { bundle }
340
+ 19 <bundle_members> -> { branch, id, leaf, seed, tree, vine, λ }
341
+ 20 <function_definition> -> { pollinate, λ }
342
+ 21 <return_type> -> { branch, empty, id, leaf, seed, tree, vine }
343
+ 22 <parameters> -> { branch, id, leaf, seed, tree, vine, λ }
344
+ 23 <param> -> { branch, id, leaf, seed, tree, vine }
345
+ 24 <param_array> -> { [, λ }
346
+ 25 <param_next> -> { ,, λ }
347
+ 26 <reclaim_opt> -> { reclaim, λ }
348
+ 27 <reclaim_value> -> { !, (, ;, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
349
+ 28 <statement> ->
350
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
351
+ leaf, plant, prune, reclaim, seed, skip, spring, tend, tree,
352
+ vine, water, λ }
353
+ 29 <simple_stmt> ->
354
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
355
+ leaf, plant, prune, reclaim, seed, skip, spring, tend, tree,
356
+ vine, water }
357
+ 30 <id_stmt> -> { %=, (, *=, ++, +=, --, -=, ., /=, =, [ }
358
+ BERCASIO, E. M. S. MIRALLES, K. L.
359
+ BAYNA, C. L. TARINO, J. L. A.
360
+ HULIGANGA, S. K. E. TOMINIO, M.
361
+ RAMOS, J. GrowALanguage
362
+
363
+
364
+
365
+ 92
366
+ 31 <assign_rhs> -> { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, water, ~
367
+ }
368
+ 32 <assign_op> -> { %=, *=, +=, -=, /=, = }
369
+ 33 <value> -> { id }
370
+ 34 <id_next> -> { ., [, λ }
371
+ 35 <array_access> -> { [ }
372
+ 36 <array_access_more> -> { [, λ }
373
+ 37 <struct_access> -> { . }
374
+ 38 <struct_access_more> -> { ., λ }
375
+ 39 <post_array_access> -> { ., λ }
376
+ 40 <io_stmt> -> { plant, water }
377
+ 41 <water_arg> -> { branch, id, leaf, seed, tree, vine, λ }
378
+ 42 <water_id_tail> -> { [, λ }
379
+ 43 <arguments> -> { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~, λ }
380
+ 44 <arg_next> -> { ,, λ }
381
+ 45 <conditional_stmt> -> { spring }
382
+ 46 <elseif_chain> -> { bud, λ }
383
+ BERCASIO, E. M. S. MIRALLES, K. L.
384
+ BAYNA, C. L. TARINO, J. L. A.
385
+ HULIGANGA, S. K. E. TOMINIO, M.
386
+ RAMOS, J. GrowALanguage
387
+
388
+
389
+
390
+ 93
391
+ 47 <else_opt> -> { wither, λ }
392
+ 48 <loop_stmt> -> { cultivate, grow, tend }
393
+ 49 <for_init> -> { branch, id, leaf, seed, tree, vine, λ }
394
+ 50 <for_update> -> { id, λ }
395
+ 51 <unary_stmt> -> { id }
396
+ 52 <inc_dec_op> -> { ++, -- }
397
+ 53 <switch_stmt> -> { harvest }
398
+ 54 <case_list> -> { variety, λ }
399
+ 55 <case_literal> -> { chrlit, dblit, frost, intlit, stringlit, sunshine }
400
+ 56 <case_statements> ->
401
+ { ++, --, branch, bundle, cultivate, grow, harvest, id, leaf,
402
+ plant, prune, reclaim, seed, skip, spring, tend, tree, vine,
403
+ water, {, λ }
404
+ 57 <case_statement> ->
405
+ { ++, --, branch, bundle, cultivate, grow, harvest, id, leaf,
406
+ plant, prune, reclaim, seed, skip, spring, tend, tree, vine,
407
+ water, { }
408
+ 58 <default_opt> -> { soil, λ }
409
+ 59 <control_stmt> -> { prune, skip }
410
+ 60 <function_call> -> { id }
411
+ 61 <logic_or_next> -> { ||, λ }
412
+ 62 <logic_and_next> -> { &&, λ }
413
+ BERCASIO, E. M. S. MIRALLES, K. L.
414
+ BAYNA, C. L. TARINO, J. L. A.
415
+ HULIGANGA, S. K. E. TOMINIO, M.
416
+ RAMOS, J. GrowALanguage
417
+
418
+
419
+
420
+ 94
421
+ 63 <relational_next> -> { !=, <, <=, ==, >, >=, λ }
422
+ 64 <relational_op> -> { !=, <, <=, ==, >, >= }
423
+ 65 <arithmetic_next> -> { +, -, `, λ }
424
+ 66 <term_next> -> { %, *, /, λ }
425
+ 67 <factor> -> { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
426
+
427
+
428
+ XII. FOLLOW SET
429
+
430
+ # Nonterminal -> Follow Set
431
+ 1 <program> -> { EOF }
432
+ 2 <global_declaration> -> { pollinate, root }
433
+ 3 <function_definition> -> { root }
434
+ 4 <statement> -> { } }
435
+ 5 <bundle_or_var> -> { branch, bundle, fertile, leaf, pollinate, root, seed, tree,
436
+ vine }
437
+ 6 <data_type> -> { ), id }
438
+ 7 <array_dec> -> { ,, ;, = }
439
+ 8 <var_value> -> { ; }
440
+ 9 <init_val> -> { ,, ; }
441
+ BERCASIO, E. M. S. MIRALLES, K. L.
442
+ BAYNA, C. L. TARINO, J. L. A.
443
+ HULIGANGA, S. K. E. TOMINIO, M.
444
+ RAMOS, J. GrowALanguage
445
+
446
+
447
+
448
+ 95
449
+ 10 <const_next> -> { ; }
450
+ 11 <bundle_members> -> { } }
451
+ 12 <bundle_mem_dec> -> { ; }
452
+ 13 <var_dec> -> { ; }
453
+ 14 <declaration> -> { }
454
+ 15 <const_dec> -> { ; }
455
+ 16 <var_value_next> -> { ; }
456
+ 17 <array_init_opt> -> { ,, ; }
457
+ 18 <water_arg> -> { ) }
458
+ 19 <expression> -> { ), ,, ;, ], } }
459
+ 20 <array_dim_opt> -> { ] }
460
+ 21 <init_vals> -> { } }
461
+ 22 <init_val_item> -> { ,, } }
462
+ 23 <init_vals_next> -> { } }
463
+ 24 <return_type> -> { id }
464
+ 25 <parameters> -> { ) }
465
+ 26 <param> -> { ), , }
466
+ BERCASIO, E. M. S. MIRALLES, K. L.
467
+ BAYNA, C. L. TARINO, J. L. A.
468
+ HULIGANGA, S. K. E. TOMINIO, M.
469
+ RAMOS, J. GrowALanguage
470
+
471
+
472
+
473
+ 96
474
+ 27 <param_next> -> { ) }
475
+ 28 <param_array> -> { ), , }
476
+ 29 <reclaim_value> ->
477
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
478
+ leaf, plant, prune, reclaim, seed, skip, soil, spring, tend,
479
+ tree, variety, vine, water, {, } }
480
+ 30 <reclaim_opt> -> { }
481
+ 31 <simple_stmt> ->
482
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
483
+ leaf, plant, prune, reclaim, seed, skip, spring, tend, tree,
484
+ vine, water, } }
485
+ 32 <id_stmt> ->
486
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
487
+ leaf, plant, prune, reclaim, seed, skip, soil, spring, tend,
488
+ tree, variety, vine, water, {, } }
489
+ 33 <inc_dec_op> -> { ), ;, id }
490
+ 34 <io_stmt> ->
491
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
492
+ leaf, plant, prune, reclaim, seed, skip, soil, spring, tend,
493
+ tree, variety, vine, water, {, } }
494
+ 35 <conditional_stmt> ->
495
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
496
+ leaf, plant, prune, reclaim, seed, skip, soil, spring, tend,
497
+ tree, variety, vine, water, {, } }
498
+ 36 <loop_stmt> ->
499
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
500
+ leaf, plant, prune, reclaim, seed, skip, soil, spring, tend,
501
+ tree, variety, vine, water, {, } }
502
+ 37 <switch_stmt> ->
503
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
504
+ leaf, plant, prune, reclaim, seed, skip, soil, spring, tend,
505
+ tree, variety, vine, water, {, } }
506
+ 38 <control_stmt> ->
507
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
508
+ leaf, plant, prune, reclaim, seed, skip, spring, tend, tree,
509
+ vine, water, } }
510
+ 39 <id_next> -> { %=, *=, +=, -=, /=, = }
511
+ BERCASIO, E. M. S. MIRALLES, K. L.
512
+ BAYNA, C. L. TARINO, J. L. A.
513
+ HULIGANGA, S. K. E. TOMINIO, M.
514
+ RAMOS, J. GrowALanguage
515
+
516
+
517
+
518
+ 97
519
+ 40 <assign_op> -> { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, water, ~
520
+ }
521
+ 41 <assign_rhs> -> { ; }
522
+ 42 <arguments> -> { ) }
523
+ 43 <value> -> { %=, *=, +=, -=, /=, = }
524
+ 44 <array_access> -> { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, ., /, /=, ;, <, <=, =, ==,
525
+ >, >=, ], `, ||, } }
526
+ 45 <post_array_access> -> { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, /, /=, ;, <, <=, =, ==, >,
527
+ >=, ], `, ||, } }
528
+ 46 <struct_access> -> { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, /, /=, ;, <, <=, =, ==, >,
529
+ >=, ], `, ||, } }
530
+ 47 <array_access_more> -> { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, ., /, /=, ;, <, <=, =, ==,
531
+ >, >=, ], `, ||, } }
532
+ 48 <struct_access_more> -> { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, /, /=, ;, <, <=, =, ==, >,
533
+ >=, ], `, ||, } }
534
+ 49 <water_id_tail> -> { ) }
535
+ 50 <arg_next> -> { ) }
536
+ 51 <elseif_chain> ->
537
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
538
+ leaf, plant, prune, reclaim, seed, skip, soil, spring, tend,
539
+ tree, variety, vine, water, wither, {, } }
540
+ 52 <else_opt> ->
541
+ { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id,
542
+ leaf, plant, prune, reclaim, seed, skip, soil, spring, tend,
543
+ tree, variety, vine, water, {, } }
544
+ 53 <for_init> -> { ; }
545
+ 54 <for_update> -> { ) }
546
+ BERCASIO, E. M. S. MIRALLES, K. L.
547
+ BAYNA, C. L. TARINO, J. L. A.
548
+ HULIGANGA, S. K. E. TOMINIO, M.
549
+ RAMOS, J. GrowALanguage
550
+
551
+
552
+
553
+ 98
554
+ 55 <for_update_type> -> { ) }
555
+ 56 <case_list> -> { soil, } }
556
+ 57 <default_opt> -> { } }
557
+ 58 <case_literal> -> { : }
558
+ 59 <case_statements> -> { soil, variety, } }
559
+ 60 <case_statement> ->
560
+ { ++, --, branch, bundle, cultivate, grow, harvest, id, leaf,
561
+ plant, prune, reclaim, seed, skip, soil, spring, tend, tree,
562
+ variety, vine, water, {, } }
563
+ 61 <logic_or> -> { ), ,, ;, ], } }
564
+ 62 <logic_and> -> { ), ,, ;, ], ||, } }
565
+ 63 <logic_or_next> -> { ), ,, ;, ], } }
566
+ 64 <relational> -> { &&, ), ,, ;, ], ||, } }
567
+ 65 <logic_and_next> -> { ), ,, ;, ], ||, } }
568
+ 66 <arithmetic> -> { !=, &&, ), ,, ;, <, <=, ==, >, >=, ], ||, } }
569
+ 67 <relational_next> -> { &&, ), ,, ;, ], ||, } }
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
578
+ BERCASIO, E. M. S. MIRALLES, K. L.
579
+ BAYNA, C. L. TARINO, J. L. A.
580
+ HULIGANGA, S. K. E. TOMINIO, M.
581
+ RAMOS, J. GrowALanguage
582
+
583
+
584
+
585
+ 99
586
+ XIII. PREDICT SET
587
+
588
+ No. FIRST / Expression Form Basis Predict Set
589
+ 1
590
+ first(<global_declaration>
591
+ <function_definition> root ( ) {
592
+ <statement> })
593
+ first(<global_declaration>)
594
+ { branch, bundle, fertile,
595
+ leaf, pollinate, root, seed,
596
+ tree, vine }
597
+ 2 first(bundle id <bundle_or_var>
598
+ <global_declaration>) first(bundle) { bundle }
599
+ 3
600
+ first(<data_type> id <array_dec>
601
+ <var_value> ;
602
+ <global_declaration>)
603
+ first(<data_type>) { branch, leaf, seed, tree,
604
+ vine }
605
+ 4
606
+ first(fertile <data_type> id =
607
+ <init_val> <const_next> ;
608
+ <global_declaration>)
609
+ first(fertile) { fertile }
610
+ 5 first(λ) ∪
611
+ follow(<global_declaration>) follow(<global_declaration>) { pollinate, root }
612
+ 6 first({ <bundle_members> } ;) first({) { { }
613
+ 7 first(<bundle_mem_dec> ;) first(<bundle_mem_dec>) { ,, ;, id }
614
+ 8 first(<var_dec> ; <declaration>) first(<var_dec>) { branch, bundle, leaf,
615
+ seed, tree, vine }
616
+ 9 first(<const_dec> ; <declaration>) first(<const_dec>) { fertile }
617
+ BERCASIO, E. M. S. MIRALLES, K. L.
618
+ BAYNA, C. L. TARINO, J. L. A.
619
+ HULIGANGA, S. K. E. TOMINIO, M.
620
+ RAMOS, J. GrowALanguage
621
+
622
+
623
+
624
+ 100
625
+ 10 first(λ) ∪ follow(<declaration>) follow(<declaration>) { }
626
+ 11 first(seed) first(seed) { seed }
627
+ 12 first(tree) first(tree) { tree }
628
+ 13 first(leaf) first(leaf) { leaf }
629
+ 14 first(branch) first(branch) { branch }
630
+ 15 first(vine) first(vine) { vine }
631
+ 16 first(fertile <data_type> id =
632
+ <init_val> <const_next>) first(fertile) { fertile }
633
+ 17 first(, id = <init_val> <const_next>) first(,) { , }
634
+ 18 first(λ) ∪ follow(<const_next>) follow(<const_next>) { ; }
635
+ 19 first(<data_type> id <array_dec>
636
+ <var_value>) first(<data_type>) { branch, leaf, seed, tree,
637
+ vine }
638
+ 20 first(bundle id
639
+ <bundle_mem_dec>) first(bundle) { bundle }
640
+ 21 first(id <array_dec>
641
+ <var_value_next>) first(id) { id }
642
+ 22 first(, id <var_value_next>) first(,) { , }
643
+ BERCASIO, E. M. S. MIRALLES, K. L.
644
+ BAYNA, C. L. TARINO, J. L. A.
645
+ HULIGANGA, S. K. E. TOMINIO, M.
646
+ RAMOS, J. GrowALanguage
647
+
648
+
649
+
650
+ 101
651
+ 23 first(λ) ∪
652
+ follow(<bundle_mem_dec>) follow(<bundle_mem_dec>) { ; }
653
+ 24 first(= <init_val>
654
+ <var_value_next>) first(=) { = }
655
+ 25 first(<var_value_next>) first(<var_value_next>) { ,, ;, λ }
656
+ 26 first(, id <array_dec> <var_value>) first(,) { , }
657
+ 27 first(λ) ∪ follow(<var_value_next>) follow(<var_value_next>) { ; }
658
+ 28 first(<array_init_opt>) first(<array_init_opt>) { ,, ;, {, λ }
659
+ 29 first(water ( <water_arg> )) first(water) { water }
660
+ 30 first(<expression>) first(<expression>) { !, (, chrlit, dblit, frost, id,
661
+ intlit, stringlit, sunshine, ~ }
662
+ 31 first([ <array_dim_opt> ]
663
+ <array_dec>) first([) { [ }
664
+ 32 first(λ) ∪ follow(<array_dec>) follow(<array_dec>) { ,, ;, = }
665
+ 33 first(intlit) first(intlit) { intlit }
666
+ 34 first(dblit) first(dblit) { dblit }
667
+ 35 first(λ) ∪ follow(<array_dim_opt>) follow(<array_dim_opt>) { ] }
668
+ 36 first({ <init_vals> }) first({) { { }
669
+ 37 first(λ) ∪ follow(<array_init_opt>) follow(<array_init_opt>) { ,, ; }
670
+ BERCASIO, E. M. S. MIRALLES, K. L.
671
+ BAYNA, C. L. TARINO, J. L. A.
672
+ HULIGANGA, S. K. E. TOMINIO, M.
673
+ RAMOS, J. GrowALanguage
674
+
675
+
676
+
677
+ 102
678
+ 38 first(<init_val_item>
679
+ <init_vals_next>) first(<init_val_item>)
680
+ { !, (, chrlit, dblit, frost, id,
681
+ intlit, stringlit, sunshine, {,
682
+ ~ }
683
+ 39 first(λ) ∪ follow(<init_vals>) follow(<init_vals>) { } }
684
+ 40 first(, <init_val_item>
685
+ <init_vals_next>) first(,) { , }
686
+ 41 first(λ) ∪ follow(<init_vals_next>) follow(<init_vals_next>) { } }
687
+ 42 first({ <init_vals> }) first({) { { }
688
+ 43 first(<expression>) first(<expression>) { !, (, chrlit, dblit, frost, id,
689
+ intlit, stringlit, sunshine, ~ }
690
+ 44 first(bundle id {
691
+ <bundle_members> }) first(bundle) { bundle }
692
+ 45 first(<data_type> id ;
693
+ <bundle_members>) first(<data_type>) { branch, leaf, seed, tree,
694
+ vine }
695
+ 46 first(id id ; <bundle_members>) first(id) { id }
696
+ 47 first(λ) ∪
697
+ follow(<bundle_members>) follow(<bundle_members>) { } }
698
+ 48
699
+ first(pollinate <return_type> id (
700
+ <parameters> ) { <statement> }
701
+ <function_definition>)
702
+ first(pollinate) { pollinate }
703
+ 49 first(λ) ∪
704
+ follow(<function_definition>) follow(<function_definition>) { root }
705
+ 50 first(<data_type>) first(<data_type>) { branch, leaf, seed, tree,
706
+ vine }
707
+ BERCASIO, E. M. S. MIRALLES, K. L.
708
+ BAYNA, C. L. TARINO, J. L. A.
709
+ HULIGANGA, S. K. E. TOMINIO, M.
710
+ RAMOS, J. GrowALanguage
711
+
712
+
713
+
714
+ 103
715
+ 51 first(empty) first(empty) { empty }
716
+ 52 first(id) first(id) { id }
717
+ 53 first(λ) ∪ follow(<parameters>) follow(<parameters>) { ) }
718
+ 54 first(<param> <param_next>) first(<param>) { branch, id, leaf, seed,
719
+ tree, vine }
720
+ 55 first(<data_type> id
721
+ <param_array>) first(<data_type>) { branch, leaf, seed, tree,
722
+ vine }
723
+ 56 first(id id) first(id) { id }
724
+ 57 first(λ) ∪ follow(<param_array>) follow(<param_array>) { ), , }
725
+ 58 first([ ]) first([) { [ }
726
+ 59 first(λ) ∪ follow(<param_next>) follow(<param_next>) { ) }
727
+ 60 first(, <param> <param_next>) first(,) { , }
728
+ 61 first(reclaim <reclaim_value>) first(reclaim) { reclaim }
729
+ 62 first(λ) ∪ follow(<reclaim_opt>) follow(<reclaim_opt>) { }
730
+ 63 first(<expression> ;) first(<expression>) { !, (, chrlit, dblit, frost, id,
731
+ intlit, stringlit, sunshine, ~ }
732
+ 64 first(;) first(;) { ; }
733
+ 65 first(<simple_stmt> <statement>) first(<simple_stmt>) { ++, --, branch, bundle,
734
+ cultivate, fertile, grow,
735
+ BERCASIO, E. M. S. MIRALLES, K. L.
736
+ BAYNA, C. L. TARINO, J. L. A.
737
+ HULIGANGA, S. K. E. TOMINIO, M.
738
+ RAMOS, J. GrowALanguage
739
+
740
+
741
+
742
+ 104
743
+ harvest, id, leaf, plant,
744
+ prune, reclaim, seed, skip,
745
+ spring, tend, tree, vine,
746
+ water }
747
+ 66 first(λ) ∪ follow(<statement>) follow(<statement>) { } }
748
+ 67 first(id <id_stmt>) first(id) { id }
749
+ 68 first(<inc_dec_op> id ;) first(<inc_dec_op>) { ++, -- }
750
+ 69 first(<io_stmt>) first(<io_stmt>) { plant, water }
751
+ 70 first(<conditional_stmt>) first(<conditional_stmt>) { spring }
752
+ 71 first(<loop_stmt>) first(<loop_stmt>) { cultivate, grow, tend }
753
+ 72 first(<switch_stmt>) first(<switch_stmt>) { harvest }
754
+ 73 first(<control_stmt>) first(<control_stmt>) { prune, skip }
755
+ 74 first(reclaim <reclaim_value>) first(reclaim) { reclaim }
756
+ 75 first(<var_dec> ;) first(<var_dec>) { branch, bundle, leaf,
757
+ seed, tree, vine }
758
+ 76 first(<const_dec> ;) first(<const_dec>) { fertile }
759
+ 77 first(<id_next> <assign_op>
760
+ <assign_rhs> ;) first(<id_next>) { %=, *=, +=, -=, ., /=, =, [ }
761
+ 78 first(<inc_dec_op> ;) first(<inc_dec_op>) { ++, -- }
762
+ 79 first(( <arguments> ) ;) first(() { ( }
763
+ 80 first(<value> <assign_op>
764
+ <assign_rhs> ;) first(<value>) { id }
765
+ BERCASIO, E. M. S. MIRALLES, K. L.
766
+ BAYNA, C. L. TARINO, J. L. A.
767
+ HULIGANGA, S. K. E. TOMINIO, M.
768
+ RAMOS, J. GrowALanguage
769
+
770
+
771
+
772
+ 105
773
+ 81 first(water ( <water_arg> )) first(water) { water }
774
+ 82 first(<expression>) first(<expression>) { !, (, chrlit, dblit, frost, id,
775
+ intlit, stringlit, sunshine, ~ }
776
+ 83 first(=) first(=) { = }
777
+ 84 first(+=) first(+=) { += }
778
+ 85 first(-=) first(-=) { -= }
779
+ 86 first(*=) first(*=) { *= }
780
+ 87 first(/=) first(/=) { /= }
781
+ 88 first(%=) first(%=) { %= }
782
+ 89 first(id <id_next>) first(id) { id }
783
+ 90 first(<array_access>
784
+ <post_array_access>) first(<array_access>) { [ }
785
+ 91 first(<struct_access>) first(<struct_access>) { . }
786
+ 92 first(λ) ∪ follow(<id_next>) follow(<id_next>) { %=, *=, +=, -=, /=, = }
787
+ 93 first([ <expression> ]
788
+ <array_access_more>) first([) { [ }
789
+ 94 first([ <expression> ]
790
+ <array_access_more>) first([) { [ }
791
+ 95 first(λ) ∪
792
+ follow(<array_access_more>) follow(<array_access_more>)
793
+ { !=, %, %=, &&, ), *, *=, +,
794
+ +=, ,, -, -=, ., /, /=, ;, <, <=,
795
+ =, ==, >, >=, ], `, ||, } }
796
+ 96 first(. id <struct_access_more>) first(.) { . }
797
+ BERCASIO, E. M. S. MIRALLES, K. L.
798
+ BAYNA, C. L. TARINO, J. L. A.
799
+ HULIGANGA, S. K. E. TOMINIO, M.
800
+ RAMOS, J. GrowALanguage
801
+
802
+
803
+
804
+ 106
805
+ 97 first(. id <struct_access_more>) first(.) { . }
806
+ 98 first(λ) ∪
807
+ follow(<struct_access_more>) follow(<struct_access_more>)
808
+ { !=, %, %=, &&, ), *, *=, +,
809
+ +=, ,, -, -=, /, /=, ;, <, <=, =,
810
+ ==, >, >=, ], `, ||, } }
811
+ 99 first(. id <post_array_access>) first(.) { . }
812
+ 100 first(λ) ∪
813
+ follow(<post_array_access>) follow(<post_array_access>)
814
+ { !=, %, %=, &&, ), *, *=, +,
815
+ +=, ,, -, -=, /, /=, ;, <, <=, =,
816
+ ==, >, >=, ], `, ||, } }
817
+ 101 first(plant ( <arguments> ) ;) first(plant) { plant }
818
+ 102 first(water ( <water_arg> ) ;) first(water) { water }
819
+ 103 first(<data_type>) first(<data_type>) { branch, leaf, seed, tree,
820
+ vine }
821
+ 104 first(id <water_id_tail>) first(id) { id }
822
+ 105 first(λ) ∪ follow(<water_arg>) follow(<water_arg>) { ) }
823
+ 106 first([ <expression> ]
824
+ <water_id_tail>) first([) { [ }
825
+ 107 first(λ) ∪ follow(<water_id_tail>) follow(<water_id_tail>) { ) }
826
+ 108 first(<expression> <arg_next>) first(<expression>) { !, (, chrlit, dblit, frost, id,
827
+ intlit, stringlit, sunshine, ~ }
828
+ 109 first(λ) ∪ follow(<arguments>) follow(<arguments>) { ) }
829
+ 110 first(, <expression> <arg_next>) first(,) { , }
830
+ 111 first(λ) ∪ follow(<arg_next>) follow(<arg_next>) { ) }
831
+ BERCASIO, E. M. S. MIRALLES, K. L.
832
+ BAYNA, C. L. TARINO, J. L. A.
833
+ HULIGANGA, S. K. E. TOMINIO, M.
834
+ RAMOS, J. GrowALanguage
835
+
836
+
837
+
838
+ 107
839
+ 112
840
+ first(spring ( <expression> ) {
841
+ <statement> } <elseif_chain>
842
+ <else_opt>)
843
+ first(spring) { spring }
844
+ 113 first(bud ( <expression> ) {
845
+ <statement> } <elseif_chain>) first(bud) { bud }
846
+ 114 first(λ) ∪ follow(<elseif_chain>) follow(<elseif_chain>)
847
+ { ++, --, branch, bundle,
848
+ cultivate, fertile, grow,
849
+ harvest, id, leaf, plant,
850
+ prune, reclaim, seed, skip,
851
+ soil, spring, tend, tree,
852
+ variety, vine, water,
853
+ wither, {, } }
854
+ 115 first(wither { <statement> }) first(wither) { wither }
855
+ 116 first(λ) ∪ follow(<else_opt>) follow(<else_opt>)
856
+ { ++, --, branch, bundle,
857
+ cultivate, fertile, grow,
858
+ harvest, id, leaf, plant,
859
+ prune, reclaim, seed, skip,
860
+ soil, spring, tend, tree,
861
+ variety, vine, water, {, } }
862
+ 117 first(grow ( <expression> ) {
863
+ <statement> }) first(grow) { grow }
864
+ 118
865
+ first(cultivate ( <for_init> ;
866
+ <expression> ; <for_update> ) {
867
+ <statement> })
868
+ first(cultivate) { cultivate }
869
+ 119 first(tend { <statement> } grow (
870
+ <expression> ) ;) first(tend) { tend }
871
+ 120 first(<data_type> id <array_dec>
872
+ <var_value>) first(<data_type>) { branch, leaf, seed, tree,
873
+ vine }
874
+ 121 first(id <id_next> <assign_op>
875
+ <expression>) first(id) { id }
876
+ 122 first(λ) ∪ follow(<for_init>) follow(<for_init>) { ; }
877
+ 123 first(id <for_update_type>) first(id) { id }
878
+ BERCASIO, E. M. S. MIRALLES, K. L.
879
+ BAYNA, C. L. TARINO, J. L. A.
880
+ HULIGANGA, S. K. E. TOMINIO, M.
881
+ RAMOS, J. GrowALanguage
882
+
883
+
884
+
885
+ 108
886
+ 124 first(λ) ∪ follow(<for_update>) follow(<for_update>) { ) }
887
+ 125 first(<inc_dec_op>) first(<inc_dec_op>) { ++, -- }
888
+ 126 first(<id_next> <assign_op>
889
+ <expression>) first(<id_next>) { %=, *=, +=, -=, ., /=, =, [ }
890
+ 127 first(id <inc_dec_op> ;) first(id) { id }
891
+ 128 first(++) first(++) { ++ }
892
+ 129 first(--) first(--) { -- }
893
+ 130 first(harvest ( <expression> ) {
894
+ <case_list> <default_opt> }) first(harvest) { harvest }
895
+ 131 first(variety <case_literal> :
896
+ <case_statements> <case_list>) first(variety) { variety }
897
+ 132 first(λ) ∪ follow(<case_list>) follow(<case_list>) { soil, } }
898
+ 133 first(intlit) first(intlit) { intlit }
899
+ 134 first(dblit) first(dblit) { dblit }
900
+ 135 first(chrlit) first(chrlit) { chrlit }
901
+ 136 first(stringlit) first(stringlit) { stringlit }
902
+ 137 first(sunshine) first(sunshine) { sunshine }
903
+ 138 first(frost) first(frost) { frost }
904
+ 139 first(<case_statement>
905
+ <case_statements>) first(<case_statement>)
906
+ { ++, --, branch, bundle,
907
+ cultivate, grow, harvest, id,
908
+ leaf, plant, prune, reclaim,
909
+ seed, skip, spring, tend,
910
+ tree, vine, water, { }
911
+ BERCASIO, E. M. S. MIRALLES, K. L.
912
+ BAYNA, C. L. TARINO, J. L. A.
913
+ HULIGANGA, S. K. E. TOMINIO, M.
914
+ RAMOS, J. GrowALanguage
915
+
916
+
917
+
918
+ 109
919
+ 140 first(λ) ∪
920
+ follow(<case_statements>) follow(<case_statements>) { soil, variety, } }
921
+ 141 first(id <id_stmt>) first(id) { id }
922
+ 142 first(<inc_dec_op> id ;) first(<inc_dec_op>) { ++, -- }
923
+ 143 first(<var_dec> ;) first(<var_dec>) { branch, bundle, leaf,
924
+ seed, tree, vine }
925
+ 144 first(<io_stmt>) first(<io_stmt>) { plant, water }
926
+ 145 first(<conditional_stmt>) first(<conditional_stmt>) { spring }
927
+ 146 first(<loop_stmt>) first(<loop_stmt>) { cultivate, grow, tend }
928
+ 147 first(<switch_stmt>) first(<switch_stmt>) { harvest }
929
+ 148 first({ <case_statements> }) first({) { { }
930
+ 149 first(prune ;) first(prune) { prune }
931
+ 150 first(skip ;) first(skip) { skip }
932
+ 151 first(reclaim <reclaim_value>) first(reclaim) { reclaim }
933
+
934
+
935
+
936
+
937
+
938
+
939
+
940
+
941
+
942
+ XIV. Lexical Test Scripts
943
+
convert_defense_to_pdf.py → Docus & mps/convert_defense_to_pdf.py RENAMED
File without changes
convert_to_pdf.py → Docus & mps/convert_to_pdf.py RENAMED
File without changes
Docus & mps/gal_server_codex.err.log ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ C:\Users\clarence\Downloads\AUTOMATA-COMPILER-main (1)\AUTOMATA-COMPILER-main\my GAL code\Backend\server.py:23: DeprecationWarning:
2
+ Eventlet is deprecated. It is currently being maintained in bugfix mode, and
3
+ we strongly recommend against using it for new projects.
4
+
5
+ If you are already using Eventlet, we recommend migrating to a different
6
+ framework. For more detail see
7
+ https://eventlet.readthedocs.io/en/latest/asyncio/migration.html
8
+
9
+ import eventlet
10
+ 1 RLock(s) were not greened, to fix this error make sure you run eventlet.monkey_patch() before importing any other modules.
Docus & mps/gal_server_codex.log ADDED
File without changes
payslip.gal → Docus & mps/payslip.gal RENAMED
File without changes
Docus & mps/system_cfg_first_follow_predict_current.txt ADDED
@@ -0,0 +1,559 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CFG PRODUCTIONS
2
+ 1. <program> -> <global_declaration> <function_definition> root ( ) { <statement> }
3
+ 2. <global_declaration> -> bundle id <bundle_or_var> <global_declaration>
4
+ 3. <global_declaration> -> <data_type> id <array_dec> <var_value> ; <global_declaration>
5
+ 4. <global_declaration> -> fertile <data_type> id = <init_val> <const_next> ; <global_declaration>
6
+ 5. <global_declaration> -> λ
7
+ 6. <bundle_or_var> -> { <bundle_members> } ;
8
+ 7. <bundle_or_var> -> <bundle_mem_dec> ;
9
+ 8. <declaration> -> <var_dec> ; <declaration>
10
+ 9. <declaration> -> <const_dec> ; <declaration>
11
+ 10. <declaration> -> λ
12
+ 11. <data_type> -> seed
13
+ 12. <data_type> -> tree
14
+ 13. <data_type> -> leaf
15
+ 14. <data_type> -> branch
16
+ 15. <data_type> -> vine
17
+ 16. <const_dec> -> fertile <data_type> id = <init_val> <const_next>
18
+ 17. <const_next> -> , id = <init_val> <const_next>
19
+ 18. <const_next> -> λ
20
+ 19. <var_dec> -> <data_type> id <array_dec> <var_value>
21
+ 20. <var_dec> -> bundle id <bundle_mem_dec>
22
+ 21. <bundle_mem_dec> -> id <array_dec> <var_value_next>
23
+ 22. <bundle_mem_dec> -> , id <var_value_next>
24
+ 23. <bundle_mem_dec> -> λ
25
+ 24. <var_value> -> = <init_val> <var_value_next>
26
+ 25. <var_value> -> <var_value_next>
27
+ 26. <var_value_next> -> , id <array_dec> <var_value>
28
+ 27. <var_value_next> -> λ
29
+ 28. <init_val> -> <array_init_opt>
30
+ 29. <init_val> -> water ( <water_arg> )
31
+ 30. <init_val> -> <expression>
32
+ 31. <array_dec> -> [ <array_dim_opt> ] <array_dec>
33
+ 32. <array_dec> -> λ
34
+ 33. <array_dim_opt> -> intlit
35
+ 34. <array_dim_opt> -> dblit
36
+ 35. <array_dim_opt> -> λ
37
+ 36. <array_init_opt> -> { <init_vals> }
38
+ 37. <array_init_opt> -> λ
39
+ 38. <init_vals> -> <init_val_item> <init_vals_next>
40
+ 39. <init_vals> -> λ
41
+ 40. <init_vals_next> -> , <init_val_item> <init_vals_next>
42
+ 41. <init_vals_next> -> λ
43
+ 42. <init_val_item> -> { <init_vals> }
44
+ 43. <init_val_item> -> <expression>
45
+ 44. <bundle_declaration> -> bundle id { <bundle_members> }
46
+ 45. <bundle_members> -> <data_type> id ; <bundle_members>
47
+ 46. <bundle_members> -> id id ; <bundle_members>
48
+ 47. <bundle_members> -> λ
49
+ 48. <function_definition> -> pollinate <return_type> id ( <parameters> ) { <statement> } <function_definition>
50
+ 49. <function_definition> -> λ
51
+ 50. <return_type> -> <data_type>
52
+ 51. <return_type> -> empty
53
+ 52. <return_type> -> id
54
+ 53. <parameters> -> λ
55
+ 54. <parameters> -> <param> <param_next>
56
+ 55. <param> -> <data_type> id <param_array>
57
+ 56. <param> -> id id
58
+ 57. <param_array> -> λ
59
+ 58. <param_array> -> [ ]
60
+ 59. <param_next> -> λ
61
+ 60. <param_next> -> , <param> <param_next>
62
+ 61. <reclaim_opt> -> reclaim <reclaim_value>
63
+ 62. <reclaim_opt> -> λ
64
+ 63. <reclaim_value> -> <expression> ;
65
+ 64. <reclaim_value> -> ;
66
+ 65. <statement> -> <simple_stmt> <statement>
67
+ 66. <statement> -> λ
68
+ 67. <simple_stmt> -> id <id_stmt>
69
+ 68. <simple_stmt> -> <inc_dec_op> id ;
70
+ 69. <simple_stmt> -> <io_stmt>
71
+ 70. <simple_stmt> -> <conditional_stmt>
72
+ 71. <simple_stmt> -> <loop_stmt>
73
+ 72. <simple_stmt> -> <switch_stmt>
74
+ 73. <simple_stmt> -> <control_stmt>
75
+ 74. <simple_stmt> -> reclaim <reclaim_value>
76
+ 75. <simple_stmt> -> <var_dec> ;
77
+ 76. <simple_stmt> -> <const_dec> ;
78
+ 77. <id_stmt> -> <id_next> <assign_op> <assign_rhs> ;
79
+ 78. <id_stmt> -> <inc_dec_op> ;
80
+ 79. <id_stmt> -> ( <arguments> ) ;
81
+ 80. <assignment_stmt> -> <value> <assign_op> <assign_rhs> ;
82
+ 81. <assign_rhs> -> water ( <water_arg> )
83
+ 82. <assign_rhs> -> <expression>
84
+ 83. <assign_op> -> =
85
+ 84. <assign_op> -> +=
86
+ 85. <assign_op> -> -=
87
+ 86. <assign_op> -> *=
88
+ 87. <assign_op> -> /=
89
+ 88. <assign_op> -> %=
90
+ 89. <value> -> id <id_next>
91
+ 90. <id_next> -> <array_access> <post_array_access>
92
+ 91. <id_next> -> <struct_access>
93
+ 92. <id_next> -> λ
94
+ 93. <array_access> -> [ <expression> ] <array_access_more>
95
+ 94. <array_access_more> -> [ <expression> ] <array_access_more>
96
+ 95. <array_access_more> -> λ
97
+ 96. <struct_access> -> . id <struct_access_more>
98
+ 97. <struct_access_more> -> . id <struct_access_more>
99
+ 98. <struct_access_more> -> λ
100
+ 99. <post_array_access> -> . id <post_array_access>
101
+ 100. <post_array_access> -> λ
102
+ 101. <io_stmt> -> plant ( <arguments> ) ;
103
+ 102. <io_stmt> -> water ( <water_arg> ) ;
104
+ 103. <water_arg> -> <data_type>
105
+ 104. <water_arg> -> id <water_id_tail>
106
+ 105. <water_arg> -> λ
107
+ 106. <water_id_tail> -> [ <expression> ] <water_id_tail>
108
+ 107. <water_id_tail> -> λ
109
+ 108. <arguments> -> <expression> <arg_next>
110
+ 109. <arguments> -> λ
111
+ 110. <arg_next> -> , <expression> <arg_next>
112
+ 111. <arg_next> -> λ
113
+ 112. <conditional_stmt> -> spring ( <expression> ) { <statement> } <elseif_chain> <else_opt>
114
+ 113. <elseif_chain> -> bud ( <expression> ) { <statement> } <elseif_chain>
115
+ 114. <elseif_chain> -> λ
116
+ 115. <else_opt> -> wither { <statement> }
117
+ 116. <else_opt> -> λ
118
+ 117. <loop_stmt> -> grow ( <expression> ) { <statement> }
119
+ 118. <loop_stmt> -> cultivate ( <for_init> ; <expression> ; <for_update> ) { <statement> }
120
+ 119. <loop_stmt> -> tend { <statement> } grow ( <expression> ) ;
121
+ 120. <for_init> -> <data_type> id <array_dec> <var_value>
122
+ 121. <for_init> -> id <id_next> <assign_op> <expression>
123
+ 122. <for_init> -> λ
124
+ 123. <for_update> -> id <for_update_type>
125
+ 124. <for_update> -> λ
126
+ 125. <for_update_type> -> <inc_dec_op>
127
+ 126. <for_update_type> -> <id_next> <assign_op> <expression>
128
+ 127. <unary_stmt> -> id <inc_dec_op> ;
129
+ 128. <inc_dec_op> -> ++
130
+ 129. <inc_dec_op> -> --
131
+ 130. <switch_stmt> -> harvest ( <expression> ) { <case_list> <default_opt> }
132
+ 131. <case_list> -> variety <case_literal> : <case_statements> <case_list>
133
+ 132. <case_list> -> λ
134
+ 133. <case_literal> -> intlit
135
+ 134. <case_literal> -> dblit
136
+ 135. <case_literal> -> chrlit
137
+ 136. <case_literal> -> stringlit
138
+ 137. <case_literal> -> sunshine
139
+ 138. <case_literal> -> frost
140
+ 139. <case_statements> -> <case_statement> <case_statements>
141
+ 140. <case_statements> -> λ
142
+ 141. <case_statement> -> id <id_stmt>
143
+ 142. <case_statement> -> <inc_dec_op> id ;
144
+ 143. <case_statement> -> <var_dec> ;
145
+ 144. <case_statement> -> <io_stmt>
146
+ 145. <case_statement> -> <conditional_stmt>
147
+ 146. <case_statement> -> <loop_stmt>
148
+ 147. <case_statement> -> <switch_stmt>
149
+ 148. <case_statement> -> { <case_statements> }
150
+ 149. <case_statement> -> prune ;
151
+ 150. <case_statement> -> skip ;
152
+ 151. <case_statement> -> reclaim <reclaim_value>
153
+ 152. <default_opt> -> soil : <case_statements>
154
+ 153. <default_opt> -> λ
155
+ 154. <control_stmt> -> prune ;
156
+ 155. <control_stmt> -> skip ;
157
+ 156. <function_call> -> id ( <arguments> ) ;
158
+ 157. <expression> -> <logic_or>
159
+ 158. <logic_or> -> <logic_and> <logic_or_next>
160
+ 159. <logic_or_next> -> || <logic_and> <logic_or_next>
161
+ 160. <logic_or_next> -> λ
162
+ 161. <logic_and> -> <relational> <logic_and_next>
163
+ 162. <logic_and_next> -> && <relational> <logic_and_next>
164
+ 163. <logic_and_next> -> λ
165
+ 164. <relational> -> <arithmetic> <relational_next>
166
+ 165. <relational_next> -> <relational_op> <arithmetic>
167
+ 166. <relational_next> -> λ
168
+ 167. <relational_op> -> >
169
+ 168. <relational_op> -> <
170
+ 169. <relational_op> -> >=
171
+ 170. <relational_op> -> <=
172
+ 171. <relational_op> -> ==
173
+ 172. <relational_op> -> !=
174
+ 173. <arithmetic> -> <term> <arithmetic_next>
175
+ 174. <arithmetic_next> -> + <term> <arithmetic_next>
176
+ 175. <arithmetic_next> -> - <term> <arithmetic_next>
177
+ 176. <arithmetic_next> -> ` <term> <arithmetic_next>
178
+ 177. <arithmetic_next> -> λ
179
+ 178. <term> -> <factor> <term_next>
180
+ 179. <term_next> -> * <factor> <term_next>
181
+ 180. <term_next> -> / <factor> <term_next>
182
+ 181. <term_next> -> % <factor> <term_next>
183
+ 182. <term_next> -> λ
184
+ 183. <factor> -> ( <paren_expr>
185
+ 184. <factor> -> <unary_op> <factor>
186
+ 185. <factor> -> id <factor_id_next>
187
+ 186. <factor> -> intlit
188
+ 187. <factor> -> dblit
189
+ 188. <factor> -> chrlit
190
+ 189. <factor> -> stringlit
191
+ 190. <factor> -> sunshine
192
+ 191. <factor> -> frost
193
+ 192. <paren_expr> -> <data_type> ) <factor>
194
+ 193. <paren_expr> -> <expression> )
195
+ 194. <unary_op> -> ~
196
+ 195. <unary_op> -> !
197
+ 196. <factor_id_next> -> <array_access> <post_array_access>
198
+ 197. <factor_id_next> -> <struct_access>
199
+ 198. <factor_id_next> -> ( <arguments> )
200
+ 199. <factor_id_next> -> λ
201
+
202
+ FIRST SETS
203
+ First(<global_declaration>) = { branch, bundle, fertile, leaf, seed, tree, vine, λ }
204
+ First(<bundle_or_var>) = { ,, ;, id, { }
205
+ First(<declaration>) = { branch, bundle, fertile, leaf, seed, tree, vine, λ }
206
+ First(<data_type>) = { branch, leaf, seed, tree, vine }
207
+ First(<const_dec>) = { fertile }
208
+ First(<const_next>) = { ,, λ }
209
+ First(<var_dec>) = { branch, bundle, leaf, seed, tree, vine }
210
+ First(<bundle_mem_dec>) = { ,, id, λ }
211
+ First(<var_value>) = { ,, =, λ }
212
+ First(<var_value_next>) = { ,, λ }
213
+ First(<init_val>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, water, {, ~, λ }
214
+ First(<array_dec>) = { [, λ }
215
+ First(<array_dim_opt>) = { dblit, intlit, λ }
216
+ First(<array_init_opt>) = { {, λ }
217
+ First(<init_vals>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, {, ~, λ }
218
+ First(<init_vals_next>) = { ,, λ }
219
+ First(<init_val_item>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, {, ~ }
220
+ First(<bundle_declaration>) = { bundle }
221
+ First(<bundle_members>) = { branch, id, leaf, seed, tree, vine, λ }
222
+ First(<function_definition>) = { pollinate, λ }
223
+ First(<return_type>) = { branch, empty, id, leaf, seed, tree, vine }
224
+ First(<parameters>) = { branch, id, leaf, seed, tree, vine, λ }
225
+ First(<param>) = { branch, id, leaf, seed, tree, vine }
226
+ First(<param_array>) = { [, λ }
227
+ First(<param_next>) = { ,, λ }
228
+ First(<reclaim_opt>) = { reclaim, λ }
229
+ First(<reclaim_value>) = { !, (, ;, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
230
+ First(<statement>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water, λ }
231
+ First(<simple_stmt>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water }
232
+ First(<id_stmt>) = { %=, (, *=, ++, +=, --, -=, ., /=, =, [ }
233
+ First(<assign_rhs>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, water, ~ }
234
+ First(<assign_op>) = { %=, *=, +=, -=, /=, = }
235
+ First(<value>) = { id }
236
+ First(<id_next>) = { ., [, λ }
237
+ First(<array_access>) = { [ }
238
+ First(<array_access_more>) = { [, λ }
239
+ First(<struct_access>) = { . }
240
+ First(<struct_access_more>) = { ., λ }
241
+ First(<post_array_access>) = { ., λ }
242
+ First(<io_stmt>) = { plant, water }
243
+ First(<water_arg>) = { branch, id, leaf, seed, tree, vine, λ }
244
+ First(<water_id_tail>) = { [, λ }
245
+ First(<arguments>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~, λ }
246
+ First(<arg_next>) = { ,, λ }
247
+ First(<conditional_stmt>) = { spring }
248
+ First(<elseif_chain>) = { bud, λ }
249
+ First(<else_opt>) = { wither, λ }
250
+ First(<loop_stmt>) = { cultivate, grow, tend }
251
+ First(<for_init>) = { branch, id, leaf, seed, tree, vine, λ }
252
+ First(<for_update>) = { id, λ }
253
+ First(<unary_stmt>) = { id }
254
+ First(<inc_dec_op>) = { ++, -- }
255
+ First(<switch_stmt>) = { harvest }
256
+ First(<case_list>) = { variety, λ }
257
+ First(<case_literal>) = { chrlit, dblit, frost, intlit, stringlit, sunshine }
258
+ First(<case_statements>) = { ++, --, branch, bundle, cultivate, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water, {, λ }
259
+ First(<case_statement>) = { ++, --, branch, bundle, cultivate, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water, { }
260
+ First(<default_opt>) = { soil, λ }
261
+ First(<control_stmt>) = { prune, skip }
262
+ First(<function_call>) = { id }
263
+ First(<logic_or_next>) = { ||, λ }
264
+ First(<logic_and_next>) = { &&, λ }
265
+ First(<relational_next>) = { !=, <, <=, ==, >, >=, λ }
266
+ First(<relational_op>) = { !=, <, <=, ==, >, >= }
267
+ First(<arithmetic_next>) = { +, -, `, λ }
268
+ First(<term_next>) = { %, *, /, λ }
269
+ First(<factor>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
270
+ First(<unary_op>) = { !, ~ }
271
+ First(<factor_id_next>) = { (, ., [, λ }
272
+ First(<program>) = { branch, bundle, fertile, leaf, pollinate, root, seed, tree, vine }
273
+ First(<expression>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
274
+ First(<assignment_stmt>) = { id }
275
+ First(<for_update_type>) = { %=, *=, ++, +=, --, -=, ., /=, =, [ }
276
+ First(<logic_or>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
277
+ First(<logic_and>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
278
+ First(<relational>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
279
+ First(<arithmetic>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
280
+ First(<term>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
281
+ First(<paren_expr>) = { !, (, branch, chrlit, dblit, frost, id, intlit, leaf, seed, stringlit, sunshine, tree, vine, ~ }
282
+
283
+ FOLLOW SETS
284
+ Follow(<program>) = { EOF }
285
+ Follow(<global_declaration>) = { pollinate, root }
286
+ Follow(<function_definition>) = { root }
287
+ Follow(<statement>) = { } }
288
+ Follow(<bundle_or_var>) = { branch, bundle, fertile, leaf, pollinate, root, seed, tree, vine }
289
+ Follow(<data_type>) = { ), id }
290
+ Follow(<array_dec>) = { ,, ;, = }
291
+ Follow(<var_value>) = { ; }
292
+ Follow(<init_val>) = { ,, ; }
293
+ Follow(<const_next>) = { ; }
294
+ Follow(<bundle_members>) = { } }
295
+ Follow(<bundle_mem_dec>) = { ; }
296
+ Follow(<var_dec>) = { ; }
297
+ Follow(<declaration>) = { }
298
+ Follow(<const_dec>) = { ; }
299
+ Follow(<var_value_next>) = { ; }
300
+ Follow(<array_init_opt>) = { ,, ; }
301
+ Follow(<water_arg>) = { ) }
302
+ Follow(<expression>) = { ), ,, ;, ], } }
303
+ Follow(<array_dim_opt>) = { ] }
304
+ Follow(<init_vals>) = { } }
305
+ Follow(<init_val_item>) = { ,, } }
306
+ Follow(<init_vals_next>) = { } }
307
+ Follow(<return_type>) = { id }
308
+ Follow(<parameters>) = { ) }
309
+ Follow(<param>) = { ), , }
310
+ Follow(<param_next>) = { ) }
311
+ Follow(<param_array>) = { ), , }
312
+ Follow(<reclaim_value>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, {, } }
313
+ Follow(<reclaim_opt>) = { }
314
+ Follow(<simple_stmt>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water, } }
315
+ Follow(<id_stmt>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, {, } }
316
+ Follow(<inc_dec_op>) = { ), ;, id }
317
+ Follow(<io_stmt>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, {, } }
318
+ Follow(<conditional_stmt>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, {, } }
319
+ Follow(<loop_stmt>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, {, } }
320
+ Follow(<switch_stmt>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, {, } }
321
+ Follow(<control_stmt>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water, } }
322
+ Follow(<id_next>) = { %=, *=, +=, -=, /=, = }
323
+ Follow(<assign_op>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, water, ~ }
324
+ Follow(<assign_rhs>) = { ; }
325
+ Follow(<arguments>) = { ) }
326
+ Follow(<value>) = { %=, *=, +=, -=, /=, = }
327
+ Follow(<array_access>) = { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, ., /, /=, ;, <, <=, =, ==, >, >=, ], `, ||, } }
328
+ Follow(<post_array_access>) = { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, /, /=, ;, <, <=, =, ==, >, >=, ], `, ||, } }
329
+ Follow(<struct_access>) = { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, /, /=, ;, <, <=, =, ==, >, >=, ], `, ||, } }
330
+ Follow(<array_access_more>) = { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, ., /, /=, ;, <, <=, =, ==, >, >=, ], `, ||, } }
331
+ Follow(<struct_access_more>) = { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, /, /=, ;, <, <=, =, ==, >, >=, ], `, ||, } }
332
+ Follow(<water_id_tail>) = { ) }
333
+ Follow(<arg_next>) = { ) }
334
+ Follow(<elseif_chain>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, wither, {, } }
335
+ Follow(<else_opt>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, {, } }
336
+ Follow(<for_init>) = { ; }
337
+ Follow(<for_update>) = { ) }
338
+ Follow(<for_update_type>) = { ) }
339
+ Follow(<case_list>) = { soil, } }
340
+ Follow(<default_opt>) = { } }
341
+ Follow(<case_literal>) = { : }
342
+ Follow(<case_statements>) = { soil, variety, } }
343
+ Follow(<case_statement>) = { ++, --, branch, bundle, cultivate, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, {, } }
344
+ Follow(<logic_or>) = { ), ,, ;, ], } }
345
+ Follow(<logic_and>) = { ), ,, ;, ], ||, } }
346
+ Follow(<logic_or_next>) = { ), ,, ;, ], } }
347
+ Follow(<relational>) = { &&, ), ,, ;, ], ||, } }
348
+ Follow(<logic_and_next>) = { ), ,, ;, ], ||, } }
349
+ Follow(<arithmetic>) = { !=, &&, ), ,, ;, <, <=, ==, >, >=, ], ||, } }
350
+ Follow(<relational_next>) = { &&, ), ,, ;, ], ||, } }
351
+ Follow(<relational_op>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
352
+ Follow(<term>) = { !=, &&, ), +, ,, -, ;, <, <=, ==, >, >=, ], `, ||, } }
353
+ Follow(<arithmetic_next>) = { !=, &&, ), ,, ;, <, <=, ==, >, >=, ], ||, } }
354
+ Follow(<factor>) = { !=, %, &&, ), *, +, ,, -, /, ;, <, <=, ==, >, >=, ], `, ||, } }
355
+ Follow(<term_next>) = { !=, &&, ), +, ,, -, ;, <, <=, ==, >, >=, ], `, ||, } }
356
+ Follow(<paren_expr>) = { !=, %, &&, ), *, +, ,, -, /, ;, <, <=, ==, >, >=, ], `, ||, } }
357
+ Follow(<unary_op>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
358
+ Follow(<factor_id_next>) = { !=, %, &&, ), *, +, ,, -, /, ;, <, <=, ==, >, >=, ], `, ||, } }
359
+
360
+ PREDICT SETS
361
+ Predict(<program> -> <global_declaration> <function_definition> root ( ) { <statement> }) = { branch, bundle, fertile, leaf, pollinate, root, seed, tree, vine }
362
+ Predict(<global_declaration> -> bundle id <bundle_or_var> <global_declaration>) = { bundle }
363
+ Predict(<global_declaration> -> <data_type> id <array_dec> <var_value> ; <global_declaration>) = { branch, leaf, seed, tree, vine }
364
+ Predict(<global_declaration> -> fertile <data_type> id = <init_val> <const_next> ; <global_declaration>) = { fertile }
365
+ Predict(<global_declaration> -> λ) = { pollinate, root }
366
+ Predict(<bundle_or_var> -> { <bundle_members> } ;) = { { }
367
+ Predict(<bundle_or_var> -> <bundle_mem_dec> ;) = { ,, ;, id }
368
+ Predict(<declaration> -> <var_dec> ; <declaration>) = { branch, bundle, leaf, seed, tree, vine }
369
+ Predict(<declaration> -> <const_dec> ; <declaration>) = { fertile }
370
+ Predict(<declaration> -> λ) = { }
371
+ Predict(<data_type> -> seed) = { seed }
372
+ Predict(<data_type> -> tree) = { tree }
373
+ Predict(<data_type> -> leaf) = { leaf }
374
+ Predict(<data_type> -> branch) = { branch }
375
+ Predict(<data_type> -> vine) = { vine }
376
+ Predict(<const_dec> -> fertile <data_type> id = <init_val> <const_next>) = { fertile }
377
+ Predict(<const_next> -> , id = <init_val> <const_next>) = { , }
378
+ Predict(<const_next> -> λ) = { ; }
379
+ Predict(<var_dec> -> <data_type> id <array_dec> <var_value>) = { branch, leaf, seed, tree, vine }
380
+ Predict(<var_dec> -> bundle id <bundle_mem_dec>) = { bundle }
381
+ Predict(<bundle_mem_dec> -> id <array_dec> <var_value_next>) = { id }
382
+ Predict(<bundle_mem_dec> -> , id <var_value_next>) = { , }
383
+ Predict(<bundle_mem_dec> -> λ) = { ; }
384
+ Predict(<var_value> -> = <init_val> <var_value_next>) = { = }
385
+ Predict(<var_value> -> <var_value_next>) = { ,, ;, λ }
386
+ Predict(<var_value_next> -> , id <array_dec> <var_value>) = { , }
387
+ Predict(<var_value_next> -> λ) = { ; }
388
+ Predict(<init_val> -> <array_init_opt>) = { ,, ;, {, λ }
389
+ Predict(<init_val> -> water ( <water_arg> )) = { water }
390
+ Predict(<init_val> -> <expression>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
391
+ Predict(<array_dec> -> [ <array_dim_opt> ] <array_dec>) = { [ }
392
+ Predict(<array_dec> -> λ) = { ,, ;, = }
393
+ Predict(<array_dim_opt> -> intlit) = { intlit }
394
+ Predict(<array_dim_opt> -> dblit) = { dblit }
395
+ Predict(<array_dim_opt> -> λ) = { ] }
396
+ Predict(<array_init_opt> -> { <init_vals> }) = { { }
397
+ Predict(<array_init_opt> -> λ) = { ,, ; }
398
+ Predict(<init_vals> -> <init_val_item> <init_vals_next>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, {, ~ }
399
+ Predict(<init_vals> -> λ) = { } }
400
+ Predict(<init_vals_next> -> , <init_val_item> <init_vals_next>) = { , }
401
+ Predict(<init_vals_next> -> λ) = { } }
402
+ Predict(<init_val_item> -> { <init_vals> }) = { { }
403
+ Predict(<init_val_item> -> <expression>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
404
+ Predict(<bundle_declaration> -> bundle id { <bundle_members> }) = { bundle }
405
+ Predict(<bundle_members> -> <data_type> id ; <bundle_members>) = { branch, leaf, seed, tree, vine }
406
+ Predict(<bundle_members> -> id id ; <bundle_members>) = { id }
407
+ Predict(<bundle_members> -> λ) = { } }
408
+ Predict(<function_definition> -> pollinate <return_type> id ( <parameters> ) { <statement> } <function_definition>) = { pollinate }
409
+ Predict(<function_definition> -> λ) = { root }
410
+ Predict(<return_type> -> <data_type>) = { branch, leaf, seed, tree, vine }
411
+ Predict(<return_type> -> empty) = { empty }
412
+ Predict(<return_type> -> id) = { id }
413
+ Predict(<parameters> -> λ) = { ) }
414
+ Predict(<parameters> -> <param> <param_next>) = { branch, id, leaf, seed, tree, vine }
415
+ Predict(<param> -> <data_type> id <param_array>) = { branch, leaf, seed, tree, vine }
416
+ Predict(<param> -> id id) = { id }
417
+ Predict(<param_array> -> λ) = { ), , }
418
+ Predict(<param_array> -> [ ]) = { [ }
419
+ Predict(<param_next> -> λ) = { ) }
420
+ Predict(<param_next> -> , <param> <param_next>) = { , }
421
+ Predict(<reclaim_opt> -> reclaim <reclaim_value>) = { reclaim }
422
+ Predict(<reclaim_opt> -> λ) = { }
423
+ Predict(<reclaim_value> -> <expression> ;) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
424
+ Predict(<reclaim_value> -> ;) = { ; }
425
+ Predict(<statement> -> <simple_stmt> <statement>) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water }
426
+ Predict(<statement> -> λ) = { } }
427
+ Predict(<simple_stmt> -> id <id_stmt>) = { id }
428
+ Predict(<simple_stmt> -> <inc_dec_op> id ;) = { ++, -- }
429
+ Predict(<simple_stmt> -> <io_stmt>) = { plant, water }
430
+ Predict(<simple_stmt> -> <conditional_stmt>) = { spring }
431
+ Predict(<simple_stmt> -> <loop_stmt>) = { cultivate, grow, tend }
432
+ Predict(<simple_stmt> -> <switch_stmt>) = { harvest }
433
+ Predict(<simple_stmt> -> <control_stmt>) = { prune, skip }
434
+ Predict(<simple_stmt> -> reclaim <reclaim_value>) = { reclaim }
435
+ Predict(<simple_stmt> -> <var_dec> ;) = { branch, bundle, leaf, seed, tree, vine }
436
+ Predict(<simple_stmt> -> <const_dec> ;) = { fertile }
437
+ Predict(<id_stmt> -> <id_next> <assign_op> <assign_rhs> ;) = { %=, *=, +=, -=, ., /=, =, [ }
438
+ Predict(<id_stmt> -> <inc_dec_op> ;) = { ++, -- }
439
+ Predict(<id_stmt> -> ( <arguments> ) ;) = { ( }
440
+ Predict(<assignment_stmt> -> <value> <assign_op> <assign_rhs> ;) = { id }
441
+ Predict(<assign_rhs> -> water ( <water_arg> )) = { water }
442
+ Predict(<assign_rhs> -> <expression>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
443
+ Predict(<assign_op> -> =) = { = }
444
+ Predict(<assign_op> -> +=) = { += }
445
+ Predict(<assign_op> -> -=) = { -= }
446
+ Predict(<assign_op> -> *=) = { *= }
447
+ Predict(<assign_op> -> /=) = { /= }
448
+ Predict(<assign_op> -> %=) = { %= }
449
+ Predict(<value> -> id <id_next>) = { id }
450
+ Predict(<id_next> -> <array_access> <post_array_access>) = { [ }
451
+ Predict(<id_next> -> <struct_access>) = { . }
452
+ Predict(<id_next> -> λ) = { %=, *=, +=, -=, /=, = }
453
+ Predict(<array_access> -> [ <expression> ] <array_access_more>) = { [ }
454
+ Predict(<array_access_more> -> [ <expression> ] <array_access_more>) = { [ }
455
+ Predict(<array_access_more> -> λ) = { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, ., /, /=, ;, <, <=, =, ==, >, >=, ], `, ||, } }
456
+ Predict(<struct_access> -> . id <struct_access_more>) = { . }
457
+ Predict(<struct_access_more> -> . id <struct_access_more>) = { . }
458
+ Predict(<struct_access_more> -> λ) = { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, /, /=, ;, <, <=, =, ==, >, >=, ], `, ||, } }
459
+ Predict(<post_array_access> -> . id <post_array_access>) = { . }
460
+ Predict(<post_array_access> -> λ) = { !=, %, %=, &&, ), *, *=, +, +=, ,, -, -=, /, /=, ;, <, <=, =, ==, >, >=, ], `, ||, } }
461
+ Predict(<io_stmt> -> plant ( <arguments> ) ;) = { plant }
462
+ Predict(<io_stmt> -> water ( <water_arg> ) ;) = { water }
463
+ Predict(<water_arg> -> <data_type>) = { branch, leaf, seed, tree, vine }
464
+ Predict(<water_arg> -> id <water_id_tail>) = { id }
465
+ Predict(<water_arg> -> λ) = { ) }
466
+ Predict(<water_id_tail> -> [ <expression> ] <water_id_tail>) = { [ }
467
+ Predict(<water_id_tail> -> λ) = { ) }
468
+ Predict(<arguments> -> <expression> <arg_next>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
469
+ Predict(<arguments> -> λ) = { ) }
470
+ Predict(<arg_next> -> , <expression> <arg_next>) = { , }
471
+ Predict(<arg_next> -> λ) = { ) }
472
+ Predict(<conditional_stmt> -> spring ( <expression> ) { <statement> } <elseif_chain> <else_opt>) = { spring }
473
+ Predict(<elseif_chain> -> bud ( <expression> ) { <statement> } <elseif_chain>) = { bud }
474
+ Predict(<elseif_chain> -> λ) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, wither, {, } }
475
+ Predict(<else_opt> -> wither { <statement> }) = { wither }
476
+ Predict(<else_opt> -> λ) = { ++, --, branch, bundle, cultivate, fertile, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, soil, spring, tend, tree, variety, vine, water, {, } }
477
+ Predict(<loop_stmt> -> grow ( <expression> ) { <statement> }) = { grow }
478
+ Predict(<loop_stmt> -> cultivate ( <for_init> ; <expression> ; <for_update> ) { <statement> }) = { cultivate }
479
+ Predict(<loop_stmt> -> tend { <statement> } grow ( <expression> ) ;) = { tend }
480
+ Predict(<for_init> -> <data_type> id <array_dec> <var_value>) = { branch, leaf, seed, tree, vine }
481
+ Predict(<for_init> -> id <id_next> <assign_op> <expression>) = { id }
482
+ Predict(<for_init> -> λ) = { ; }
483
+ Predict(<for_update> -> id <for_update_type>) = { id }
484
+ Predict(<for_update> -> λ) = { ) }
485
+ Predict(<for_update_type> -> <inc_dec_op>) = { ++, -- }
486
+ Predict(<for_update_type> -> <id_next> <assign_op> <expression>) = { %=, *=, +=, -=, ., /=, =, [ }
487
+ Predict(<unary_stmt> -> id <inc_dec_op> ;) = { id }
488
+ Predict(<inc_dec_op> -> ++) = { ++ }
489
+ Predict(<inc_dec_op> -> --) = { -- }
490
+ Predict(<switch_stmt> -> harvest ( <expression> ) { <case_list> <default_opt> }) = { harvest }
491
+ Predict(<case_list> -> variety <case_literal> : <case_statements> <case_list>) = { variety }
492
+ Predict(<case_list> -> λ) = { soil, } }
493
+ Predict(<case_literal> -> intlit) = { intlit }
494
+ Predict(<case_literal> -> dblit) = { dblit }
495
+ Predict(<case_literal> -> chrlit) = { chrlit }
496
+ Predict(<case_literal> -> stringlit) = { stringlit }
497
+ Predict(<case_literal> -> sunshine) = { sunshine }
498
+ Predict(<case_literal> -> frost) = { frost }
499
+ Predict(<case_statements> -> <case_statement> <case_statements>) = { ++, --, branch, bundle, cultivate, grow, harvest, id, leaf, plant, prune, reclaim, seed, skip, spring, tend, tree, vine, water, { }
500
+ Predict(<case_statements> -> λ) = { soil, variety, } }
501
+ Predict(<case_statement> -> id <id_stmt>) = { id }
502
+ Predict(<case_statement> -> <inc_dec_op> id ;) = { ++, -- }
503
+ Predict(<case_statement> -> <var_dec> ;) = { branch, bundle, leaf, seed, tree, vine }
504
+ Predict(<case_statement> -> <io_stmt>) = { plant, water }
505
+ Predict(<case_statement> -> <conditional_stmt>) = { spring }
506
+ Predict(<case_statement> -> <loop_stmt>) = { cultivate, grow, tend }
507
+ Predict(<case_statement> -> <switch_stmt>) = { harvest }
508
+ Predict(<case_statement> -> { <case_statements> }) = { { }
509
+ Predict(<case_statement> -> prune ;) = { prune }
510
+ Predict(<case_statement> -> skip ;) = { skip }
511
+ Predict(<case_statement> -> reclaim <reclaim_value>) = { reclaim }
512
+ Predict(<default_opt> -> soil : <case_statements>) = { soil }
513
+ Predict(<default_opt> -> λ) = { } }
514
+ Predict(<control_stmt> -> prune ;) = { prune }
515
+ Predict(<control_stmt> -> skip ;) = { skip }
516
+ Predict(<function_call> -> id ( <arguments> ) ;) = { id }
517
+ Predict(<expression> -> <logic_or>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
518
+ Predict(<logic_or> -> <logic_and> <logic_or_next>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
519
+ Predict(<logic_or_next> -> || <logic_and> <logic_or_next>) = { || }
520
+ Predict(<logic_or_next> -> λ) = { ), ,, ;, ], } }
521
+ Predict(<logic_and> -> <relational> <logic_and_next>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
522
+ Predict(<logic_and_next> -> && <relational> <logic_and_next>) = { && }
523
+ Predict(<logic_and_next> -> λ) = { ), ,, ;, ], ||, } }
524
+ Predict(<relational> -> <arithmetic> <relational_next>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
525
+ Predict(<relational_next> -> <relational_op> <arithmetic>) = { !=, <, <=, ==, >, >= }
526
+ Predict(<relational_next> -> λ) = { &&, ), ,, ;, ], ||, } }
527
+ Predict(<relational_op> -> >) = { > }
528
+ Predict(<relational_op> -> <) = { < }
529
+ Predict(<relational_op> -> >=) = { >= }
530
+ Predict(<relational_op> -> <=) = { <= }
531
+ Predict(<relational_op> -> ==) = { == }
532
+ Predict(<relational_op> -> !=) = { != }
533
+ Predict(<arithmetic> -> <term> <arithmetic_next>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
534
+ Predict(<arithmetic_next> -> + <term> <arithmetic_next>) = { + }
535
+ Predict(<arithmetic_next> -> - <term> <arithmetic_next>) = { - }
536
+ Predict(<arithmetic_next> -> ` <term> <arithmetic_next>) = { ` }
537
+ Predict(<arithmetic_next> -> λ) = { !=, &&, ), ,, ;, <, <=, ==, >, >=, ], ||, } }
538
+ Predict(<term> -> <factor> <term_next>) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
539
+ Predict(<term_next> -> * <factor> <term_next>) = { * }
540
+ Predict(<term_next> -> / <factor> <term_next>) = { / }
541
+ Predict(<term_next> -> % <factor> <term_next>) = { % }
542
+ Predict(<term_next> -> λ) = { !=, &&, ), +, ,, -, ;, <, <=, ==, >, >=, ], `, ||, } }
543
+ Predict(<factor> -> ( <paren_expr>) = { ( }
544
+ Predict(<factor> -> <unary_op> <factor>) = { !, ~ }
545
+ Predict(<factor> -> id <factor_id_next>) = { id }
546
+ Predict(<factor> -> intlit) = { intlit }
547
+ Predict(<factor> -> dblit) = { dblit }
548
+ Predict(<factor> -> chrlit) = { chrlit }
549
+ Predict(<factor> -> stringlit) = { stringlit }
550
+ Predict(<factor> -> sunshine) = { sunshine }
551
+ Predict(<factor> -> frost) = { frost }
552
+ Predict(<paren_expr> -> <data_type> ) <factor>) = { branch, leaf, seed, tree, vine }
553
+ Predict(<paren_expr> -> <expression> )) = { !, (, chrlit, dblit, frost, id, intlit, stringlit, sunshine, ~ }
554
+ Predict(<unary_op> -> ~) = { ~ }
555
+ Predict(<unary_op> -> !) = { ! }
556
+ Predict(<factor_id_next> -> <array_access> <post_array_access>) = { [ }
557
+ Predict(<factor_id_next> -> <struct_access>) = { . }
558
+ Predict(<factor_id_next> -> ( <arguments> )) = { ( }
559
+ Predict(<factor_id_next> -> λ) = { !=, %, &&, ), *, +, ,, -, /, ;, <, <=, ==, >, >=, ], `, ||, } }