Update trash files ehe
Browse files- Backend/GALinterpreter.py +282 -44
- Backend/GALsemantic.py +149 -23
- Backend/Gal_Parser.py +75 -2
- Backend/cfg.py +39 -8
- Backend/icg.py +23 -2
- Backend/lexer.py +126 -118
- Backend/main.js +0 -569
- Backend/server.py +144 -28
- Backend/test_array_param.py +0 -45
- Backend/test_curly_init.py +0 -41
- Backend/test_mp16.py +0 -77
- Backend/test_mp16_full.py +0 -113
- Docus & mps/CFG_FIRST_FOLLOW_PREDICT.txt +0 -0
- Docus & mps/CFG_Latest_1_extracted.txt +214 -0
- Docus & mps/CFG_Latest_First_Follow_Predict_Set_extracted.txt +1441 -0
- Docus & mps/CFG_Latest_extracted.txt +225 -0
- Docus & mps/CFG_live_from_code.txt +199 -0
- DEFENSE_01_server.md → Docus & mps/DEFENSE_01_server.md +0 -0
- DEFENSE_01_server.pdf → Docus & mps/DEFENSE_01_server.pdf +0 -0
- DEFENSE_02_tokens_errors.md → Docus & mps/DEFENSE_02_tokens_errors.md +0 -0
- DEFENSE_02_tokens_errors.pdf → Docus & mps/DEFENSE_02_tokens_errors.pdf +0 -0
- Docus & mps/DEFENSE_03_lexer.md +791 -0
- Docus & mps/DEFENSE_03_lexer.pdf +448 -0
- Docus & mps/DEFENSE_04_parser_ast_semantic_icg_interpreter.md +2290 -0
- Docus & mps/DEFENSE_FULL_PIPELINE.md +0 -0
- Docus & mps/DEFENSE_FULL_PIPELINE.pdf +0 -0
- GAL_COMPILER_KNOWLEDGE_BASE.md → Docus & mps/GAL_COMPILER_KNOWLEDGE_BASE.md +0 -0
- GAL_PROGRAMS_EXPLANATION.pdf.md → Docus & mps/GAL_PROGRAMS_EXPLANATION.pdf.md +0 -0
- GAL_RESERVED_WORDS_EXPLANATION.md → Docus & mps/GAL_RESERVED_WORDS_EXPLANATION.md +0 -0
- GAL_RESERVED_WORDS_EXPLANATION.pdf → Docus & mps/GAL_RESERVED_WORDS_EXPLANATION.pdf +0 -0
- GAL_SYSTEM_DOCUMENTATION.md → Docus & mps/GAL_SYSTEM_DOCUMENTATION.md +0 -0
- Docus & mps/cfg_to_pred_extracted.txt +943 -0
- convert_defense_to_pdf.py → Docus & mps/convert_defense_to_pdf.py +0 -0
- convert_to_pdf.py → Docus & mps/convert_to_pdf.py +0 -0
- Docus & mps/gal_server_codex.err.log +10 -0
- Docus & mps/gal_server_codex.log +0 -0
- payslip.gal → Docus & mps/payslip.gal +0 -0
- Docus & mps/system_cfg_first_follow_predict_current.txt +559 -0
Backend/GALinterpreter.py
CHANGED
|
@@ -1,22 +1,58 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 56 |
-
self.
|
| 57 |
-
self.
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
self.
|
| 61 |
-
self.
|
| 62 |
-
self.
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
self.current_parent = None
|
| 65 |
|
| 66 |
-
|
| 67 |
-
self.
|
| 68 |
-
self.
|
| 69 |
-
self.
|
| 70 |
-
self.
|
| 71 |
-
self.
|
| 72 |
-
self.
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
class SemanticAnalyzer:
|
| 15 |
def __init__(self, symbol_table):
|
| 16 |
self.symbol_table = symbol_table
|
| 17 |
self.visited_nodes = set()
|
| 18 |
|
| 19 |
|
| 20 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
#
|
| 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"
|
| 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"
|
| 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"
|
| 616 |
index += 1
|
| 617 |
elif func_name == "root":
|
| 618 |
-
raise SemanticError("
|
| 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"
|
| 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"
|
| 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"
|
| 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"
|
| 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"
|
| 714 |
elif func_type == "empty":
|
| 715 |
-
raise SemanticError(f"
|
| 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"
|
| 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"
|
| 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 =
|
| 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 =
|
| 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 |
-
#
|
| 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.
|
|
|
|
| 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 |
-
["<
|
| 773 |
],
|
| 774 |
|
| 775 |
"<term_next>": [
|
| 776 |
-
["*", "<
|
| 777 |
-
["/", "<
|
| 778 |
-
["%", "<
|
| 779 |
[EPSILON], # End
|
| 780 |
],
|
| 781 |
|
| 782 |
-
# Level 6:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.
|
| 991 |
while self._peek().type in ("*", "/", "%"):
|
| 992 |
op = self._advance().type
|
| 993 |
-
right = self.
|
| 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 = []
|
| 327 |
-
line = 1
|
| 328 |
-
errors = []
|
| 329 |
-
pos = self.pos.copy()
|
| 330 |
-
|
| 331 |
-
# Main loop:
|
| 332 |
-
while self.current_char != None:
|
| 333 |
-
|
| 334 |
# =====================================================================
|
| 335 |
# KEYWORD & IDENTIFIER RECOGNITION
|
| 336 |
-
#
|
|
|
|
|
|
|
| 337 |
# =====================================================================
|
| 338 |
-
if self.current_char in ALPHA:
|
| 339 |
-
ident_str = ''
|
| 340 |
-
pos = self.pos.copy()
|
| 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":
|
| 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 |
-
#
|
|
|
|
| 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":
|
| 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":
|
| 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:
|
| 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":
|
| 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":
|
| 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 |
-
#
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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'}
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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()
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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'@]=!`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	lM>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> -> λ) = { !=, %, &&, ), *, +, ,, -, /, ;, <, <=, ==, >, >=, ], `, ||, } }
|