commit b2281d6e27a480f0647922c11546c6630702a225 Author: Gary Gan Date: Wed Jun 11 19:51:42 2025 +0800 初始化仓库 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3040d64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +.vscode/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..48a1652 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 John Kindem + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3e65be5 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# C(缩减版)语言编译器前端 +## 是什么 +NUAA 2017年编译原理课设,词法分析使用正则表达式,语法分析使用LL(1)文法分析器, +语义分析使用自上而下翻译,使用 Python 语言编写,面向配置化,稍加改造可以适用其他文法 + +## 怎么使用 +``` +git clone https://github.com/FlyAndNotDown/CSub-CompilerFrontend.git +``` +在 PyCharm 中打开新建项目导入代码即可,Python 使用版本为 3 以上,请不要使用 Python2 运行该项目 + +## 代码结构说明 +* main.py 编译器主程序 +* error.py 存放错误相关的类和代码 +* test.c 要编译的文件 +* lexical 词法分析 +* syntax 语法分析 +* semantic 语义分析 + +另外,三大分析中 rule.py 即是支持编译器的所有文法、词法、语义规则,加以改动即可面向一些其他的文法和语言使用 + +## 关于 +NUAA 161520311 John Kindem diff --git a/error.py b/error.py new file mode 100644 index 0000000..410696e --- /dev/null +++ b/error.py @@ -0,0 +1,68 @@ +""" +错误 +""" + + +class Error: + """ + 错误 + """ + def __init__(self, error_info): + """ + 构造 + :param error_info: 错误信息 + """ + self.info = error_info + + +class LexicalError(Error): + """ + 词法错误 + """ + def __init__(self, error_info, error_line): + """ + 构造 + :param error_info: 错误信息 + :param error_line: 错误行数 + """ + super().__init__(error_info) + self.line = error_line + + +class SyntaxRuleError(Error): + """ + 语法分析规则错误 + """ + def __init__(self, error_info): + """ + 构造 + :param error_info: 信息 + """ + super().__init__(error_info) + + +class SyntaxError(Error): + """ + 语法错误 + """ + def __init__(self, error_info, error_line): + """ + 构造 + :param error_info: 错误信息 + :param line: 错误行数 + """ + super().__init__(error_info) + self.line = error_line + + +class SemanticError(Error): + """ + 语义分析错误 + """ + def __init__(self, info): + super().__init__(info) + + +class SemanticRuleError(Error): + def __init__(self, info): + super().__init__(info) \ No newline at end of file diff --git a/lexical/lexical.py b/lexical/lexical.py new file mode 100644 index 0000000..16649f2 --- /dev/null +++ b/lexical/lexical.py @@ -0,0 +1,281 @@ +""" +词法分析器 +""" +from lexical.rule import * +from error import LexicalError +import re + + +class Token: + """ + Token + """ + def __init__(self, token_type='', token_str='', token_line=-1): + """ + 构造 + :param token_type: Token 的类型 + :param token_str: Token 的内容 + :param token_line: Token 所在行数 + """ + self.type = token_type + self.str = token_str + self.line = token_line + + +class Lexical: + """ + 词法分析器 + """ + def __init__(self): + """ + 构造 + """ + # 错误 + self.__error = None + + # 源代码 + self.__source = '' + + # 分隔出来的每一行 + self.__lines = list() + + # 结果 + self.__tokens = list() + + def load_source(self, source): + """ + 装载源代码 + :param source: 源代码 + """ + self.__source = source + '\n'; + + def execute(self): + """ + 执行词法分析 + :return: 词法分析是否成功 + """ + self.__replace_useless_chars() + if self.__del_notes(): + self.__split_lines() + if self.__split_tokens(): + self.__del_spaces() + return True + else: + return False + else: + return False + + def get_result(self): + """ + 获取结果 + :return: token 列表 + """ + return self.__tokens + + def get_error(self): + """ + 获取错误 + :return: 错误原因 + """ + return self.__error + + def __replace_useless_chars(self): + """ + 替换无用的字符 + """ + # 将 \r 替换成 \n + self.__source = self.__source.replace('\r', '\n') + # 将 \t 替换成四个空格 + self.__source = self.__source.replace('\t', ' ') + + def __del_notes(self): + """ + 删除注释 + :return: 是否删除成功 + """ + # 计数器,用来确认注释开始符和注释结束符的数量是否相等 + note_count = 0 + # 缓冲区 + buffer = self.__source + # 结果 + result = self.__source + + # // + while True: + match = re.compile(regex_dict[note_char_type[2]]).search(buffer) + if match: + note_single_start = match.start() + note_single_end = buffer.find('\n', note_single_start) + + # 删除注释内容 + result = result[:note_single_start] + result[note_single_end:] + buffer = result + continue + + else: + # 如果没有找到,说明已经找完了,跳出 + break + + # /**/ + # 判断是否匹配到了末尾 + while True: + # 尝试匹配 */ + match = re.compile(regex_dict[note_char_type[0]]).search(buffer) + # 如果匹配到了 + if match: + left_note_start = match.start() + # 开始匹配 */ + match2 = re.compile(regex_dict[note_char_type[1]]).search(buffer) + # 如果匹配到了 + if match2: + right_note_end = match2.end() + # 判断匹配到的区间中有几行 + line_count = result[left_note_start:right_note_end].count('\n') + # 执行删除 + result = result.replace(result[left_note_start:right_note_end], '\n' * line_count) + # 删除完毕之后进入下一次循环 + buffer = result + continue + # 如果没有匹配到,说明两者数量不匹配,报错 + else: + # 判断错误所在的行数 + enter_location = list() + enter_location.append(0) + for i in range(0, len(result)): + if result[i] == '\n': + enter_location.append(i) + find = False + + error_line = 0 + for i in range(0, len(enter_location) - 1): + if enter_location[i] < left_note_start < enter_location[i + 1]: + error_line = i + 1 + find = True + break + if not find: + error_line = len(enter_location) + + # 报错 + self.__error = LexicalError('/* 没有相匹配的 */', error_line) + return False + # 如果没有匹配到 + else: + # 尝试寻找有没有落单的 */ + match2 = re.compile(regex_dict[note_char_type[1]]).search(buffer) + # 如果找到了说明错误了 + if match2: + right_note_start = match2.start() + # 判断错误所在的行数 + enter_location = list() + enter_location.append(0) + for i in range(0, len(result)): + if result[i] == '\n': + enter_location.append(i) + find = False + + error_line = 0 + for i in range(0, len(enter_location) - 1): + if enter_location[i] < right_note_start < enter_location[i + 1]: + error_line = i + 1 + find = True + break + if not find: + error_line = len(enter_location) + + # 报错 + self.__error = LexicalError('多余的 */', error_line) + return False + # 如果没有找到那就说明已经找完了,跳出 + else: + break + + # 将 result 保存到 __source 中 + self.__source = result + return True + + def __split_lines(self): + """ + 将完成源代码分割成行序列 + """ + # 清空 __tokens + self.__tokens.clear() + # 按行分割 + temp = self.__source.split('\n') + # 将分割出来的行序列添加到 __tokens 中 + for t in temp: + self.__lines.append(' ' + t) + + def __split_tokens(self): + """ + 从行序列中分割出 token + :return: 是否分割成功 + """ + # 先将 __lines 拷贝一份到临时变量中 + lines = list() + for line in self.__lines: + lines.append(line) + # 缓冲区 + buffer = '' + # 当前所在行数 + current_line_num = 0 + # 结果 + tokens = list() + + # 参与匹配的 type 名 + types = list() + for i in split_char_type: + types.append(i) + for i in token_type: + types.append(i) + for i in note_char_type: + types.append(i) + + while len(lines) > 0: + # 当前循环中是否匹配成功 + match_this_time = False + + # 如果缓冲区中没有数据了,就填充一行到缓冲区 + if buffer == '': + buffer = lines[0] + lines = lines[1:] + # 行号自增 + current_line_num += 1 + + # 开始匹配 + # 尝试用所有的正则表达式来匹配 + for t in types: + match = re.compile(regex_dict[t]).match(buffer) + # 如果匹配到了 + if match: + # 将其添加到 tokens 中 + tokens.append(Token(t, buffer[match.start():match.end()], current_line_num)) + # buffer 去除已经匹配的部分 + buffer = buffer[match.end():] + match_this_time = True + break + # 如果匹配完所有的正则表达式都不成功 + if not match_this_time: + # 报错 + self.__error = LexicalError('词法错误', current_line_num) + # 返回失败 + return False + # 循环正常结束则说明完全匹配成功,将结果保存到 __tokens 中,返回成功 + for token in tokens: + self.__tokens.append(token) + return True + + def __del_spaces(self): + """ + 删除 __tokens 中的空格 + """ + # 新建临时变量 + tokens = list() + # 将 __tokens 中的内容拷贝到 tokens 中 + for token in self.__tokens: + tokens.append(token) + # 清空 __tokens + self.__tokens.clear() + # 如果不是空格就添加进原来的 __tokens,相当于从原来的列表中去除了空格 + for token in tokens: + if token.type != split_char_type[0]: + self.__tokens.append(token) diff --git a/lexical/rule.py b/lexical/rule.py new file mode 100644 index 0000000..290140a --- /dev/null +++ b/lexical/rule.py @@ -0,0 +1,89 @@ +# 所有的 token 的类型 +token_type = [ + 'right-arrow', + 'else', + 'if', + 'i32', + 'f32', + 'return', + 'void', + 'while', + 'addition', + 'subtraction', + 'fn', + 'multiplication', + 'division', + 'bigger', + 'bigger-equal', + 'smaller', + 'smaller-equal', + 'equal', + 'not-equal', + 'evaluate', + 'semicolon', + 'comma', + 'colon', + 'left-parentheses', + 'right-parentheses', + 'left-bracket', + 'right-bracket', + 'left-brace', + 'right-brace', + 'id', + 'float-num', + 'int-num', + +] + +# 分隔符号 +split_char_type = [ + 'space' +] + +# 注释 +note_char_type = ( + 'note-start', + 'note-end', + 'note-single' +) + +# 正则表达式字典 +regex_dict = { + 'right-arrow':r'->', + 'space': r' +', + 'note-start': r'/\*', + 'note-end': r'\*/', + 'note-single': r'//', + 'else': r'else', + 'if': r'if', + 'i32': r'i32', + 'f32':r'f32', + 'return': r'return', + 'void': r'void', + 'fn':r'fn', + 'while': r'while', + 'addition': r'\+', + 'subtraction': r'-', + 'multiplication': r'\*', + 'division': r'/', + 'bigger': r'>', + 'bigger-equal': r'>=', + 'smaller': r'<', + 'smaller-equal': r'<=', + 'equal': r'==', + 'not-equal': r'!=', + 'evaluate': r'=', + 'semicolon': r';', + 'colon': r':', + 'comma': r',', + 'left-parentheses': r'\(', + 'right-parentheses': r'\)', + 'left-bracket': r'\[', + 'right-bracket': r'\]', + 'left-brace': r'\{', + 'right-brace': r'\}', + 'id': r'[a-zA-Z][a-zA-Z]*', + 'float-num': r'^.*?([0-9]*\.[0-9]+|[0-9]+[eE][+-]?[0-9]+).*$', + 'int-num': r'[1-9][0-9]*|0', + +} \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..8279f68 --- /dev/null +++ b/main.py @@ -0,0 +1,44 @@ +""" +主程序 +""" +from lexical.lexical import Lexical +from syntax.syntax import Syntax +from syntax.syntax import PredictingAnalysisTable + +# print(PredictingAnalysisTable().compile()) + +# 新建词法分析器 +lexical = Lexical() +# 载入源代码 +lexical.load_source(open('test9.c', encoding='utf-8', errors='ignore').read()) +# 执行词法分析 +lexical_success = lexical.execute() +# 打印结果 +print('词法分析是否成功:\t', lexical_success) +if lexical_success: + lexical_result = lexical.get_result() + print() + print('词法分析结果:') + for i in lexical_result: + print(i.type, i.str, i.line) + print() + + # 开始执行语法分析 + syntax = Syntax() + syntax.put_source(lexical_result) + syntax_success = syntax.execute() + print('语法分析和语义分析是否成功\t', syntax_success) + if not syntax_success: + print('错误原因:\t', syntax.get_error().info) +# if syntax_success: +# print() +# print('语义分析结果:\t') +# print('三地址代码:\t') +# i = -1 +# for code in syntax.get_result().root.code: +# i += 1 +# print(i, ' \t', code) +# else: +# print('错误原因:\t', syntax.get_error().info, syntax.get_error().line, '行') +# else: +# print('错误原因:\t', lexical.get_error().info) diff --git a/rule_back.py b/rule_back.py new file mode 100644 index 0000000..b67b647 --- /dev/null +++ b/rule_back.py @@ -0,0 +1,488 @@ +class Sign: + """ + 符号 + """ + def __init__(self, sign_type, sign_str='', sign_line=-1): + """ + 构造 + :param sign_type: 符号的类型 + :param sign_str: 符号的内容(可以为空) + :param sign_line: 符号所在行数(可以为空) + """ + self.type = sign_type + self.str = sign_str + self.line = sign_line + + def is_terminal_sign(self): + """ + 是不是终结符 + :return: True/False + """ + if self.type == 'empty': + return True + else: + for i in terminal_sign_type: + if i == self.type: + return True + return False + + def is_non_terminal_sign(self): + """ + 是不是非终结符 + :return: True/False + """ + for i in non_terminal_sign_type: + if i == self.type: + return True + return False + + def is_empty_sign(self): + """ + 是不是空字 + :return: True/False + """ + return self.type == 'empty' + + +class Production: + """ + 产生式 + """ + def __init__(self, left_type, right_types, semantic_start, semantic_children, semantic_end): + """ + 产生式左边 + :param left_type: 产生式左边的符号类型 + :param right_types: 产生式右边的符号类型列表 + :param semantic_start: 语义操作关键字 - 开始 + :param semantic_children: 语义操作关键字 - 孩子 + :param semantic_end: 语义操作关键字 - 结束 + """ + self.left = Sign(left_type) + self.right = list() + for i in right_types: + self.right.append(Sign(i)) + + # 调试用的 + self.str = self.left.type + ' ->' + for i in self.right: + self.str += ' ' + i.type + + # 语义操作关键字 + self.semantic_start = semantic_start + self.semantic_children = list() + for c in semantic_children: + self.semantic_children.append(c) + self.semantic_end = semantic_end + + +""" +1. program -> define-list +2. define-list -> define define-list + | empty +3. define -> type ID define-type +4. define-type -> var-define-follow + | fun-define-follow +5. var-define-follow -> ; + | [ NUM ] ; +6. type -> int + | void +7. fun-define-follow -> ( params ) code-block +8. params -> param-list + | empty +9. param-list -> param param-follow +10. param-follow -> , param param-follow + | empty +11. param -> type ID array-subscript +12. array-subscript -> [ ] + | empty +13. code-block -> { local-define-list code-list } +14. local-define-list -> local-var-define local-define-list + | empty +15. local-var-define -> type ID var-define-follow +16. code-list -> code code-list + | empty +17. code -> normal-statement + | selection-statement + | iteration-statement + | return-statement +18. normal-statement -> ; + | ID normal-statement-follow +19. normal-statement-follow -> var-follow = expression ; + | call-follow ; +20. call-follow -> ( call-params ) +21. call-params -> call-param-list + | empty +22. call-param-list -> expression call-param-follow +23. call-param-follow -> , expression call-param-follow + | empty +24. selection-statement -> if ( expression ) { code-list } selection-follow +25. selection-follow -> else { code-list } + | empty +26. iteration-statement -> while ( expression ) iteration-follow +27. iteration-follow -> { code-list } + | code +28. return-statement -> return return-follow +29. return-follow -> ; + | expression ; +30. var-follow -> [ expression ] + | empty +31. expression -> additive-expr expression-follow +32. expression-follow -> rel-op additive-expr + | empty +33. rel-op -> <= + | < + | > + | >= + | == + | != +34. additive-expr -> term additive-expr-follow +35. additive-expr-follow -> add-op term additive-expr-follow + | empty +36. add-op -> + + | - +37. term -> factor term-follow +38. term-follow -> mul-op factor term-follow + | empty +39. mul-op -> * + | / + | % +40. factor -> ( expression ) + | ID id-factor-follow | NUM +41. id-factor-follow -> var-follow + | ( args ) +42. args -> arg-list + | empty +43. arg-list -> expression arg-list-follow +44. arg-list-follow -> , expression arg-list-follow + | empty +""" + + +# 所有终结符的类型 +# 终结符是文法中不能再被展开的基本单元,直接来源于词法分析器的 token.type。 +# 这些类型用于语法分析过程中与输入 token 的类型进行匹配。 +terminal_sign_type = [ + 'else', # else 关键字 + 'if', # if 关键字 + 'int', # int 关键字,表示整型变量 + 'return', # return 关键字,函数返回语句 + 'void', # void 关键字,表示无返回值或无参数 + 'while', # while 关键字,用于循环结构 + + 'addition', # 加法运算符 '+' + 'subtraction', # 减法运算符 '-' + 'multiplication', # 乘法运算符 '*' + 'division', # 除法运算符 '/' + 'remainder', # 取余运算符 '%' + + 'bigger', # 大于操作符 '>' + 'bigger-equal', # 大于等于操作符 '>=' + 'smaller', # 小于操作符 '<' + 'smaller-equal', # 小于等于操作符 '<=' + 'equal', # 等于比较操作符 '==' + 'not-equal', # 不等于比较操作符 '!=' + 'evaluate', # 赋值操作符 '=' + + 'semicolon', # 分号 ';' + 'comma', # 逗号 ',' + 'left-parentheses', # 左圆括号 '(' + 'right-parentheses', # 右圆括号 ')' + 'left-bracket', # 左方括号 '[' + 'right-bracket', # 右方括号 ']' + 'left-brace', # 左花括号 '{' + 'right-brace', # 右花括号 '}' + + 'id', # 标识符,例如变量名、函数名 + 'num', # 数字常量,例如整数 + + # 特殊标记:结束符 + # 注意:不要在 'pound' 之前添加非终结符类型!这是语法分析器内部使用的结束标志。 + 'pound' # 输入结束标志 '#' +] + +# 所有非终结符的类型 +# 非终结符是文法中可以进一步被展开的语法成分,通常由产生式定义。 +# 每个非终结符会在语法分析过程中被替换成终结符或其它非终结符组成的序列。 +non_terminal_sign_type = [ + 'program', # 程序整体结构 + 'define-list', # 定义列表(全局变量和函数定义) + 'define', # 单个定义(变量或函数) + 'define-type', # 定义类型(变量定义或函数定义) + + 'var-define-follow', # 变量定义后续部分(如分号或数组声明) + 'type', # 类型(int 或 void) + 'fun-define-follow', # 函数定义后续部分(参数列表和函数体) + + 'params', # 参数列表 + 'param-list', # 参数列表主体 + 'param-follow', # 参数后续部分(可能包含更多参数) + 'param', # 单个参数定义 + + 'array-subscript', # 数组下标部分 '[ ]' + 'code-block', # 代码块 '{ ... }' + 'local-define-list', # 局部变量定义列表 + 'local-var-define', # 局部变量定义 + 'code-list', # 代码语句列表 + 'code', # 单条语句(控制结构、表达式等) + + 'normal-statement', # 正常语句(赋值、声明等) + 'normal-statement-follow', # 正常语句后续部分(赋值或函数调用) + + 'call-follow', # 函数调用后续部分(参数列表) + 'call-params', # 函数调用参数列表 + 'call-param-list', # 函数调用参数主体 + 'call-param-follow', # 函数调用后续参数处理 + + 'selection-statement', # 选择语句(if) + 'selection-follow', # else 分支 + + 'iteration-statement', # 循环语句(while) + 'iteration-follow', # 循环体(可能是代码块或单条语句) + + 'return-statement', # 返回语句 + 'return-follow', # 返回值部分 + + # 'eval-statement', # 表达式语句(已被注释) + # 'var', # 变量引用(已被注释) + + 'var-follow', # 变量后续部分(数组访问 [expr]) + 'expression', # 表达式 + 'expression-follow', # 表达式后续部分(关系运算符 + 表达式) + + 'rel-op', # 关系运算符(<=, <, >, >=, ==, !=) + + 'additive-expr', # 加减表达式 + 'additive-expr-follow', # 加减表达式的递归部分 + + 'add-op', # 加减运算符 '+' 或 '-' + + 'term', # 项(乘除操作单位) + 'term-follow', # 项的递归部分(乘除表达式) + + 'mul-op', # 乘除余运算符 '*' 或 '/' 或 '%' + + 'factor', # 因子(基本表达式单元) + 'id-factor-follow', # 标识符后的扩展(可能是数组或函数调用) + + 'args', # 函数调用参数 + 'arg-list', # 参数列表 + 'arg-list-follow', # 参数后续部分(多个参数间的递归) +] + +# 文法产生式 +productions = [ + # 0 + Production('program', ['define-list'], + 'Program0S', [None], 'Program0E'), + # 1 + Production('define-list', ['define', 'define-list'], + None, [None, None], 'DefineList0E'), + Production('define-list', [], + None, [], 'DefineList1E'), + # 2 + Production('define', ['type', 'id', 'define-type'], + None, [None, None, 'Define0C2'], 'Define0E'), + # 3 + Production('define-type', ['var-define-follow'], + 'DefineType0S', ['DefineType0C0'], 'DefineType0E'), + Production('define-type', ['fun-define-follow'], + 'DefineType1S', ['DefineType1C0'], 'DefineType1E'), + # 4 + Production('var-define-follow', ['semicolon'], + None, [None], 'VarDefineFollow0E'), + Production('var-define-follow', ['left-bracket', 'num', 'right-bracket', 'semicolon'], + None, [None, None, None, None], 'VarDefineFollow1E'), + # 5 + Production('type', ['int'], + 'Type0S', [None], None), + Production('type', ['void'], + 'Type1S', [None], None), + # 6 + Production('fun-define-follow', ['left-parentheses', 'params', 'right-parentheses', 'code-block'], + None, [None, 'FunDefineFollow0C1', None, 'FunDefineFollow0C3'], 'FunDefineFollow0E'), + # 7 + Production('params', ['param-list'], + 'Params0S', ['Params0C0'], None), + Production('params', [], + 'Params1S', [], None), + # 8 + Production('param-list', ['param', 'param-follow'], + None, ['ParamList0C0', 'ParamList0C1'], None), + # 9 + Production('param-follow', ['comma', 'param', 'param-follow'], + None, [None, 'ParamFollow0C1', 'ParamFollow0C2'], None), + Production('param-follow', [], + None, [], None), + # 10 + Production('param', ['type', 'id', 'array-subscript'], + None, [None, None, None], 'Param0E'), + # 11 + Production('array-subscript', ['left-bracket', 'right-bracket'], + 'ArraySubscript0S', [None, None], None), + Production('array-subscript', [], + 'ArraySubscript1S', [], None), + # 12 + Production('code-block', ['left-brace', 'local-define-list', 'code-list', 'right-brace'], + None, [None, 'CodeBlock0C1', 'CodeBlock0C2', None], 'CodeBlock0E'), + # 13 + Production('local-define-list', ['local-var-define', 'local-define-list'], + None, ['LocalDefineList0C0', 'LocalDefineList0C1'], None), + Production('local-define-list', [], + None, [], None), + # 14 + Production('local-var-define', ['type', 'id', 'var-define-follow'], + None, [None, None, None], 'LocalVarDefine0E'), + # 15 + Production('code-list', ['code', 'code-list'], + None, ['CodeList0C0', 'CodeList0C1'], 'CodeList0E'), + Production('code-list', [], + None, [], 'CodeList1E'), + # 16 + Production('code', ['normal-statement'], + None, ['Code0C0'], 'Code0E'), + Production('code', ['selection-statement'], + None, ['Code1C0'], 'Code1E'), + Production('code', ['iteration-statement'], + None, ['Code2C0'], 'Code2E'), + Production('code', ['return-statement'], + None, ['Code3C0'], 'Code3E'), + # Production('normal-statement', ['eval-statement', 'semicolon']), + # Production('normal-statement', ['semicolon']), + # 17 + Production('normal-statement', ['semicolon'], + None, [None], 'NormalStatement0E'), + Production('normal-statement', ['id', 'normal-statement-follow'], + None, [None, 'NormalStatement1C1'], 'NormalStatement1E'), + # 18 + Production('normal-statement-follow', ['var-follow', 'evaluate', 'expression', 'semicolon'], + None, ['NormalStatementFollow0C0', None, 'NormalStatementFollow0C2', None], 'NormalStatementFollow0E'), + Production('normal-statement-follow', ['call-follow', 'semicolon'], + None, ['NormalStatementFollow1C0', None], 'NormalStatementFollow1E'), + # 19 + Production('call-follow', ['left-parentheses', 'call-params', 'right-parentheses'], + None, [None, 'CallFollow0C1', None], 'CallFollow0E'), + # 20 + Production('call-params', ['call-param-list'], + None, ['CallParams0C0'], 'CallParams0E'), + Production('call-params', [], + None, [], 'CallParams1E'), + # 21 + Production('call-param-list', ['expression', 'call-param-follow'], + None, ['CallParamList0C0', 'CallParamList0C1'], 'CallParamList0E'), + # 22 + Production('call-param-follow', ['comma', 'expression', 'call-param-follow'], + None, [None, 'CallParamFollow0C1', 'CallParamFollow0C2'], 'CallParamFollow0E'), + Production('call-param-follow', [], + None, [], 'CallParamFollow1E'), + # 23 + Production('selection-statement', + ['if', 'left-parentheses', 'expression', 'right-parentheses', 'left-brace', + 'code-list', 'right-brace', 'selection-follow'], + None, [None, None, 'SelectionStatement0C2', None, None, 'SelectionStatement0C5', + None, 'SelectionStatement0C5'], 'SelectionStatement0E'), + # 24 + Production('selection-follow', ['else', 'left-brace', 'code-list', 'right-brace'], + None, [None, None, 'SelectionFollow0C2', None], 'SelectionFollow0E'), + Production('selection-follow', [], + None, [], 'SelectionFollow1E'), + # 25 + Production('iteration-statement', ['while', 'left-parentheses', 'expression', + 'right-parentheses', 'iteration-follow'], + None, [None, None, 'IterationStatement0C2', None, 'IterationStatement0C4'], 'IterationStatement0E'), + # 26 + Production('iteration-follow', ['left-brace', 'code-list', 'right-brace'], + None, [None, 'IterationFollow0C1', None], 'IterationFollow0E'), + Production('iteration-follow', ['code'], + None, ['IterationFollow1C0'], 'IterationFollow1E'), + # 27 + Production('return-statement', ['return', 'return-follow'], + None, [None, 'ReturnStatement0C1'], 'ReturnStatement0E'), + # 28 + Production('return-follow', ['semicolon'], + None, [None], 'ReturnFollow0E'), + Production('return-follow', ['expression', 'semicolon'], + None, ['ReturnFollow1C0', None], 'ReturnFollow1E'), + # Production('eval-statement', ['var', 'evaluate', 'expression']), + # Production('var', ['id', 'var-follow']), + # 29 + Production('var-follow', ['left-bracket', 'expression', 'right-bracket'], + None, [None, 'VarFollow0C1', None], 'VarFollow0E'), + Production('var-follow', [], + None, [], 'VarFollow1E'), + # 30 + Production('expression', ['additive-expr', 'expression-follow'], + None, ['Expression0C0', 'Expression0C1'], 'Expression0E'), + # 31 + Production('expression-follow', ['rel-op', 'additive-expr'], + None, [None, 'ExpressionFollow0C1'], 'ExpressionFollow0E'), + Production('expression-follow', [], + None, [], 'ExpressionFollow1E'), + # 32 + Production('rel-op', ['smaller-equal'], + None, [None], 'RelOp0E'), + Production('rel-op', ['smaller'], + None, [None], 'RelOp1E'), + Production('rel-op', ['bigger'], + None, [None], 'RelOp2E'), + Production('rel-op', ['bigger-equal'], + None, [None], 'RelOp3E'), + Production('rel-op', ['equal'], + None, [None], 'RelOp4E'), + Production('rel-op', ['not-equal'], + None, [None], 'RelOp5E'), + # 33 + Production('additive-expr', ['term', 'additive-expr-follow'], + None, ['AdditiveExpr0C0', 'AdditiveExpr0C1'], 'AdditiveExpr0E'), + # 34 + Production('additive-expr-follow', ['add-op', 'term', 'additive-expr-follow'], + None, [None, 'AdditiveExprFollow0C1', 'AdditiveExprFollow0C2'], 'AdditiveExprFollow0E'), + Production('additive-expr-follow', [], + None, [], 'AdditiveExprFollow1E'), + # 35 + Production('add-op', ['addition'], + None, [None], 'AddOp0E'), + Production('add-op', ['subtraction'], + None, [None], 'AddOp1E'), + # 36 + Production('term', ['factor', 'term-follow'], + None, ['Term0C0', 'Term0C1'], 'Term0E'), + # 37 + Production('term-follow', ['mul-op', 'factor', 'term-follow'], + None, [None, 'TermFollow0C1', 'TermFollow0C2'], 'TermFollow0E'), + Production('term-follow', [], + None, [], None), + # 38 + Production('mul-op', ['multiplication'], + None, [None], 'MulOp0E'), + Production('mul-op', ['division'], + None, [None], 'MulOp1E'), + Production('mul-op', ['remainder'], + None, [None], 'MulOp2E'), + # 39 + Production('factor', ['left-parentheses', 'expression', 'right-parentheses'], + None, [None, 'Factor0C1', None], 'Factor0E'), + Production('factor', ['id', 'id-factor-follow'], + None, [None, 'Factor1C1'], 'Factor1E'), + Production('factor', ['num'], + None, [None], 'Factor2E'), + # 40 + Production('id-factor-follow', ['var-follow'], + None, [None], 'IdFactorFollow0E'), + Production('id-factor-follow', ['left-parentheses', 'args', 'right-parentheses'], + None, [None, 'IdFactorFollow1C1', None], 'IdFactorFollow1E'), + # 41 + Production('args', ['arg-list'], + None, ['Args0C0'], 'Args0E'), + Production('args', [], + None, [], 'Args1E'), + # 42 + Production('arg-list', ['expression', 'arg-list-follow'], + None, ['ArgList0C0', 'ArgList0C1'], 'ArgList0E'), + Production('arg-list-follow', ['comma', 'expression', 'arg-list-follow'], + None, [None, 'ArgListFollow0C1', 'ArgListFollow0C2'], 'ArgListFollow0E'), + Production('arg-list-follow', [], + None, [], 'ArgListFollow1E') +] + +# 文法开始符号 +grammar_start = Sign('program') \ No newline at end of file diff --git a/semantic/code.py b/semantic/code.py new file mode 100644 index 0000000..f6f5e96 --- /dev/null +++ b/semantic/code.py @@ -0,0 +1,24 @@ +current_var_num = 0 +current_block_num = 0 + + +def get_temp_var_name(): + """ + 获取一个新的临时变量名 + :return: 临时变量名 + """ + global current_var_num + name = '_v' + str(current_var_num) + current_var_num += 1 + return name + + +def get_temp_block_name(): + """ + 获取一个新的代码块名 + :return: 代码块名 + """ + global current_block_num + name = '__b' + str(current_block_num) + current_block_num += 1 + return name diff --git a/semantic/rule.py b/semantic/rule.py new file mode 100644 index 0000000..765be65 --- /dev/null +++ b/semantic/rule.py @@ -0,0 +1,745 @@ +from semantic.symbol import * +from error import SemanticError +from semantic.code import get_temp_block_name, get_temp_var_name + + + +""" +添加语义规则的文法 +0. program{code} ->{.init} define-list +1. define-list{code} -> define define-list + {code} | empty +2. define{code} -> type ID define-type{type id} +3. define-type{code .enter} ->{.judge} var-define-follow{type id} + {code} |{.judge} fun-define-follow{type fun} +4. var-define-follow{type} -> ; + {type length} | [ NUM ] ; +5. type ->{type} int + |{type} void +6. fun-define-follow{code} -> ( params{type fun} ) code-block{fun} +7. params{.create} -> param-list{fun} + {.create} | empty +8. param-list -> param{fun} param-follow{fun} +9. param-follow -> , param{fun} param-follow{fun} + | empty +10. param -> type ID array-subscript +11. array-subscript{type} -> [ ] + {type} | empty +12. code-block{code} -> { local-define-list{fun} code-list{fun} } +13. local-define-list -> local-var-define{fun} local-define-list{fun} + | empty +14. local-var-define -> type ID var-define-follow +15. code-list{code} -> code{fun} code-list{fun} + | empty +16. code{code} -> normal-statement{fun} + | selection-statement{fun} + | iteration-statement{fun} + | return-statement{fun} +17. normal-statement -> ; + | ID normal-statement-follow{fun id} +18. normal-statement-follow{code} -> var-follow{fun} = expression{fun} ; + {code} | call-follow{fun id} ; +19. call-follow{code} -> ( call-params{fun id} ) +20. call-params{code} -> call-param-list{fun} + | empty +21. call-param-list{num code} -> expression{fun} call-param-follow{fun} +22. call-param-follow{num code names} -> , expression{fun} call-param-follow{fun} + | empty +23. selection-statement{code} -> if ( expression{fun} ) { code-list{fun} } selection-follow{fun} +24. selection-follow{code} -> else { code-list{fun} } + {code} | empty +25. iteration-statement -> while ( expression{fun} ) iteration-follow{fun} +26. iteration-follow{code} -> { code-list{fun} } + {code} | code{fun} +27. return-statement{code} -> return return-follow{fun} +28. return-follow -> ; + | expression{fun} ; +29. var-follow{code name type} -> [ expression{fun} ] + {type} | empty +30. expression{code name bool} -> additive-expr{fun} expression-follow{fun} +31. expression-follow{bool code op name} -> rel-op additive-expr{fun} + {bool} | empty +32. rel-op{op} -> <= + | < + | > + | >= + | == + | != +33. additive-expr{name code} -> term{fun} additive-expr-follow{fun} +34. additive-expr-follow{add op code name} -> add-op term{fun} additive-expr-follow{fun} + {add} | empty +35. add-op{op} -> + + | - +36. term{name code} -> factor{fun} term-follow{fun} +37. term-follow{mul op code name} -> mul-op factor{fun} term-follow{fun} + {mul} | empty +38. mul-op{op} -> * + | / + | % +39. factor{name code} -> ( expression{fun} ) + | ID id-factor-follow{id fun} + | NUM +40. id-factor-follow -> var-follow{fun} + | ( args{fun} ) +41. args{code num} -> arg-list{fun} + | empty +42. arg-list{code num} -> expression{fun} arg-list-follow{fun} +43. arg-list-follow{code num names} -> , expression{fun} arg-list-follow{fun} + | empty +""" + + +# 定义一个符号表池,每次调用函数的时候使用深拷贝从这里取局部变量表 +symbol_table_pool = SymbolTablePool() + + +class SemanticRule: + """ + 语义规则 + """ + def __init__(self, node): + """ + 构造 + :param node: 树节点 + """ + self.node = node + self.errors = list() + + def __rule(self, node): + """ + 实际的语义规则,需要复写 + :param node: + """ + return [] + + def execute(self): + """ + 执行语义规则 + """ + self.__rule(self.node) + + def have_no_errors(self): + """ + 是否没有错误 + :return: 是否没有错误 + """ + return len(self.errors) == 0 + + +class SemanticRuleFactory: + """ + 语义规则工厂,根据给出的 rule_key 返回相应的实例 + """ + @classmethod + def get_instance(cls, rule_key, node): + """ + 获取语义规则实例 + :param rule_key: 关键字 + :param node: 目标节点 + :return: 实例 + """ + # 0 + if rule_key == 'Program0S': + return Program0S(node) + if rule_key == 'Program0E': + return Program0E(node) + + # 1 + if rule_key == 'DefineLists1E': + return DefineLists1E(node) + + # 2 + if rule_key == 'DefineLists2E': + return DefineLists2E(node) + + # 3 + if rule_key == 'DefineList3E': + return DefineList3E(node) + + # 4 + if rule_key == 'DefineList4E': + return DefineList4E(node) + + # 5 + if rule_key == 'FunDefine5C3': + return FunDefine5C3(node) + if rule_key == 'FunDefine5C5': + return FunDefine5C5(node) + if rule_key == 'FunDefine5C7': + return FunDefine5C7(node) + if rule_key == 'FunDefine5E': + return FunDefine5E(node) + + # 6 + if rule_key == 'Params6S': + return Params6S(node) + + # 7 + if rule_key == 'Params7S': + return Params7S(node) + if rule_key == 'Params7C0': + return Params7C0(node) + + # 8 + if rule_key == 'ParamList8C0': + return ParamList8C0(node) + if rule_key == 'ParamList8C1': + return ParamList8C1(node) + + # 9 + if rule_key == 'ParamFollow9C1': + return ParamFollow9C1(node) + if rule_key == 'ParamFollow9C2': + return ParamFollow9C2(node) + + # 11 + if rule_key == 'Param11E': + return Param11E(node) + + # 12 + if rule_key == 'ArrayList12S': + return ArrayList12S(node) + + # 13 + if rule_key == 'ArrayList13S': + return ArrayList13S(node) + + # 14 + if rule_key == 'FunReturn14S': + return FunReturn14S(node) + + # 15 + if rule_key == 'FunReturn15E': + return FunReturn15E(node) + + # 16 + if rule_key == 'Type16S': + return Type16S(node) + # 17 + if rule_key == 'Type17S': + return Type17S(node) + # 18 + if rule_key == 'Type18S': + return Type18S(node) + # 19 + if rule_key == 'GlobalVarDefine19C3': + return GlobalVarDefine19C3(node) + if rule_key == 'GlobalVarDefine19E': + return GlobalVarDefine19E(node) + # 20 + if rule_key == 'GlobalVarDefineFllow20E': + return GlobalVarDefineFllow20E(node) + if rule_key == 'GlobalVarDefineFllow20C2': + return GlobalVarDefineFllow20C2(node) + + # 81 + if rule_key == 'ArrayListWithNum81E': + return ArrayListWithNum81E(node) + + # 82 + if rule_key == 'ArrayListWithNum82E': + return ArrayListWithNum82E(node) + return None + +# S 产生式开始 +# E 产生式结束 +# CN 产生式第N个元素应用之后 + + +# 0 +class Program0S(SemanticRule): + def __rule(self, node): + symbol_table_pool.init() + + def execute(self): + self.__rule(self.node) + + +class Program0E(SemanticRule): + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + symbol_table_pool.debug() + + def execute(self): + self.__rule(self.node) + + +# 1 +class DefineLists1E(SemanticRule): + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + for c in node.children[1].code: + node.code.append(c) + + def execute(self): + self.__rule(self.node) + +# 2 +class DefineLists2E(SemanticRule): + def __rule(self, node): + node.code.clear() + + def execute(self): + self.__rule(self.node) + +# 3 +class DefineList3E(SemanticRule): + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + def execute(self): + self.__rule(self.node) + +# 4 +class DefineList4E(SemanticRule): + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + def execute(self): + self.__rule(self.node) + + +# 5 +class FunDefine5C3(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.parent.id = node.get_pre_brother(2).lexical + if symbol_table_pool.fun_table.exist(node.parent.id): + self.errors.append(SemanticError('函数名' + node.id + '重定义')) + node.fun = node.parent.id + +class FunDefine5C5(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.id + +class FunDefine5C7(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.id + +class FunDefine5E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[3].code: + node.code.append(c) + for c in node.children[7].code: + node.code.append(c) + + node.type = node.children[7].type + +class Params6S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + symbol_table_pool.append( + LocalVarTable(node.fun, symbol_table_pool.global_var_table) + ) + symbol_table_pool.fun_table.append( + Fun(node.fun, None, symbol_table_pool.query(node.fun)) + ) + +class Params7S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + symbol_table_pool.append( + LocalVarTable(node.fun, symbol_table_pool.global_var_table) + ) + symbol_table_pool.fun_table.append( + Fun(node.fun, None, symbol_table_pool.query(node.fun)) + ) + +class Params7C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class ParamList8C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class ParamList8C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class ParamFollow9C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class ParamFollow9C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class Param11E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if node.children[2].type == 'void': + self.errors.append(SemanticError('参数' + node.children[0].lexical + '不能定义为void类型')) + if node.children[2].type == 'i32': + if symbol_table_pool.query(node.fun).exist(node.children[0].lexical): + self.errors.append(SemanticError('参数' + node.children[0].lexical + '重定义')) + else: + if node.children[3].type == 'array': + symbol_table_pool.query(node.fun).append( + LocalVar(node.children[0].lexical, 'address', 4, True) + ) + if node.children[3].type == 'var': + symbol_table_pool.query(node.fun).append( + LocalVar(node.children[0].lexical, 'i32', 4, True) + ) + if node.children[2].type == 'f32': + if symbol_table_pool.query(node.fun).exist(node.children[0].lexical): + self.errors.append(SemanticError('参数' + node.children[1].lexical + '重定义')) + else: + if node.children[3].type == 'array': + symbol_table_pool.query(node.fun).append( + LocalVar(node.children[0].lexical, 'address', 4, True) + ) + if node.children[3].type == 'var': + symbol_table_pool.query(node.fun).append( + LocalVar(node.children[0].lexical, 'f32', 4, True) + ) + +class ArrayList12S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'var' + +class ArrayList13S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'array' + +class FunReturn14S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'void' + if not symbol_table_pool.change_fun_type(node.fun, node.type): + self.errors.append(SemanticError('函数' + node.fun + '没有定义')) + +class FunReturn15E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if node.children[1].type == 'void' and node.children[2].type =='var': + if not symbol_table_pool.change_fun_type(node.fun, 'void'): + self.errors.append(SemanticError('函数' + node.fun + '没有定义')) + if node.children[1].type == 'void' and node.children[2].type =='array': + if not symbol_table_pool.change_fun_type(node.fun, 'void[]'): + self.errors.append(SemanticError('函数' + node.fun + '没有定义')) + if node.children[1].type == 'i32': + if node.children[2].type == 'array': + if not symbol_table_pool.change_fun_type(node.fun, 'i32[]'): + self.errors.append(SemanticError('函数' + node.fun + '没有定义')) + if node.children[2].type == 'var': + if not symbol_table_pool.change_fun_type(node.fun, 'i32'): + self.errors.append(SemanticError('函数' + node.fun + '没有定义')) + if node.children[1].type == 'f32': + if node.children[2].type == 'array': + if not symbol_table_pool.change_fun_type(node.fun, 'f32[]'): + self.errors.append(SemanticError('函数' + node.fun + '没有定义')) + if node.children[2].type == 'var': + if not symbol_table_pool.change_fun_type(node.fun, 'f32'): + self.errors.append(SemanticError('函数' + node.fun + '没有定义')) + +class Type16S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'i32' + +class Type17S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'f32' + +class Type18S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'void' + +class GlobalVarDefine19C3(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = None + node.length = 0 + node.array = None + if node.get_pre_brother(3).type == 'void' and node.get_pre_brother(2).type =='var': + self.errors.append(SemanticError('变量' + node.id + '不能定义为void类型')) + if node.get_pre_brother(3).type == 'void' and node.get_pre_brother(2).type =='array': + self.errors.append(SemanticError('变量' + node.id + '不能定义为void[]类型')) + if node.get_pre_brother(3).type == 'i32': + if node.get_pre_brother(2).type == 'array': + node.type = 'i32[]' + node.length = node.get_pre_brother(2).length + node.array = True + if node.get_pre_brother(2).type == 'var': + node.type = 'i32' + node.array = False + if node.get_pre_brother(3).type == 'f32': + if node.get_pre_brother(2).type == 'array': + node.type = 'f32[]' + node.array = True + node.length = node.get_pre_brother(2).length + if node.get_pre_brother(2).type == 'var': + node.type = 'f32' + node.array = False + + if node.type == None: + self.errors.append(SemanticError('变量' + node.get_pre_brother(1).lexical + '声明类型不支持')) + +class ArrayListWithNum82E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'array' + node.length = node.children[1].lexical + +class ArrayListWithNum81E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'var' + + +class GlobalVarDefine19E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.id = node.children[2].lexical + if symbol_table_pool.global_var_table.exist(node.id): + self.errors.append(SemanticError('变量' + node.id + '重定义')) + + node.type = None + node.length = 0 + if node.children[0].type == 'void' and node.children[1].type =='var': + self.errors.append(SemanticError('变量' + node.id + '不能定义为void类型')) + if node.children[0].type == 'void' and node.children[1].type =='array': + self.errors.append(SemanticError('变量' + node.id + '不能定义为void[]类型')) + if node.children[0].type == 'i32': + if node.children[1].type == 'array': + node.type = 'i32[]' + node.length = int(node.children[1].length) + symbol_table_pool.global_var_table.append( + GlobalVar(node.id, 'i32[]', 4 * node.length) + ) + if node.children[1].type == 'var': + node.type = 'i32' + symbol_table_pool.global_var_table.append( + GlobalVar(node.id, 'i32', 4) + ) + if node.children[0].type == 'f32': + if node.children[1].type == 'array': + node.type = 'f32[]' + node.length = int(node.children[1].length) + symbol_table_pool.global_var_table.append( + GlobalVar(node.id, 'f32[]', 4 * node.length) + ) + if node.children[1].type == 'var': + node.type = 'f32' + symbol_table_pool.global_var_table.append( + GlobalVar(node.id, 'f32', 4) + ) + if node.type == None: + self.errors.append(SemanticError('变量' + node.get_pre_brother(1).lexical + '声明类型不支持')) + + +class GlobalVarDefineFllow20C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = node.parent.type + node.length = node.parent.length + node.array = node.parent.array + +class GlobalVarDefineFllow20E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.id = node.children[1].lexical + if symbol_table_pool.global_var_table.exist(node.id): + self.errors.append(SemanticError('变量' + node.id + '重定义')) + + symbol_table_pool.global_var_table.append( + GlobalVar(node.id, node.type, 4 * int(node.length)) + ) + +class CodeList22C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class CodeList22E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.code.append("(fun, _, _, " + node.fun + ")") + for c in node.children[0].code: + node.code.append(c) + +class CodeList23C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class CodeList23C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class CodeList23E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + for c in node.children[1].code: + node.code.append(c) + +class CodeList24E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.code.clear() + + +class CodeList25C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class Code25E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + +class CodeList26C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class Code26E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + +class CodeList27C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class Code27E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + +class CodeList28C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class Code28E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + +class CodeList29C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + +class Code29E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + + + + + diff --git a/semantic/symbol.py b/semantic/symbol.py new file mode 100644 index 0000000..db3c46b --- /dev/null +++ b/semantic/symbol.py @@ -0,0 +1,307 @@ +class Symbol: + """ + 符号基类 + """ + def __init__(self, name): + """ + 构造 + :param name: 符号名 + """ + self.name = name + + +class SymbolTable: + """ + 符号表 + """ + def __init__(self): + """ + 构造 + """ + self._table = list() + + def exist(self, name): + """ + 给定名字的符号是否存在 + :param name: + :return: True/False + """ + for s in self._table: + if s.name == name: + return True + return False + + def query(self, name): + """ + 查询特定名字的符号 + :param name: 名字 + :return: 符号 + """ + for symbol in self._table: + if symbol.name == name: + return symbol + return None + + def append(self, symbol): + """ + 填入符号 + :param symbol: 符号 + """ + pass + + def num(self): + """ + 获取符号总数 + :return: 符号总数 + """ + return len(self._table) + + def get(self, index): + """ + 根据索引来获取符号 + :param index: 索引 + :return: 符号 + """ + return self._table[index] + + +class SymbolTablePool: + """ + 符号表池 + """ + def __init__(self): + """ + 构造 + """ + self.global_var_table = None + self.local_var_tables = None + self.fun_table = None + + def init(self): + """ + 初始化符号表池 + """ + self.global_var_table = GlobalVarTable() + self.local_var_tables = list() + self.fun_table = FunTable() + + # 添加 output 和 input 的支持 + self.local_var_tables.append( + LocalVarTable('input', self.global_var_table) + ) + self.local_var_tables.append( + LocalVarTable('output', self.global_var_table) + ) + self.query('output').append( + LocalVar('output_name', 'i32', 4, True) + ) + self.fun_table.append( + Fun('input', 'i32', self.query('input')) + ) + self.fun_table.append( + Fun('output', 'void', self.query('output')) + ) + + def change_fun_type(self, fun_name, type): + """ + 修改函数的返回类型 + :param fun_name: 函数名 type: 返回类型 + :return: bool + """ + return self.fun_table.chang_fun_type(fun_name=fun_name, type=type) + + + def query(self, local_var_table_name): + """ + 查询局部变量表 + :param local_var_table_name: 表名 + :return: 局部变量表 + """ + for table in self.local_var_tables: + if table.name == local_var_table_name: + return table + return None + + def append(self, local_var_table): + """ + 添加一张局部变量表 + :param local_var_table: 局部变量表 + """ + self.local_var_tables.append(local_var_table) + + def debug(self): + print("Global Variable Table:") + for symbol in self.global_var_table._table: + print(vars(symbol)) + print("\nFunction Table:") + for fun in self.fun_table._table: + print(f"Function: {fun.name}, Return Type: {fun.return_type}") + if hasattr(fun, 'table'): + print(f" Local Variable Table ({fun.table.name}):") + for local_var in fun.table._table: + print(f" {vars(local_var)}") + print("\nLocal Variable Tables:") + for table in self.local_var_tables: + print(f"LocalVarTable: {table.name}") + for symbol in table._table: + print(f" {vars(symbol)}") + + +class GlobalVarTable(SymbolTable): + """ + 全局变量表 + """ + def __init__(self): + """ + 构造 + :param name: + """ + super().__init__() + self.__width = 0 + + def append(self, symbol): + """ + 添加符号 + :param symbol: 符号 + """ + self._table.append(symbol) + self._table[-1].offset = self.__width + self.__width += self._table[-1].width + + +class GlobalVar(Symbol): + """ + 全局变量 + """ + def __init__(self, g_name, g_type, g_width): + """ + 全局变量 + :param g_name: 名字 + :param g_type: 类型 + :param g_width: 长度 + """ + super().__init__(g_name) + self.type = g_type + self.width = g_width + + +class LocalVarTable(SymbolTable): + """ + 局部变量表 + """ + def __init__(self, name, global_var_table): + """ + 构造 + :param name: 表名 + :param global_var_table 全局变量表 + """ + super().__init__() + self.name = name + self.outer = global_var_table + self.__width = 0 + + def append(self, symbol): + """ + 填入新符号 + :param symbol: + """ + self._table.append(symbol) + self._table[-1].offset = self.__width + self.__width += symbol.width + + def exist(self, name): + """ + 是否已经存在 + :param name: 符号名 + :return: True/False + """ + if self.outer.exist(name): + return True + else: + for symbol in self._table: + if symbol.name == name: + return True + return False + + def get_params_num(self): + """ + 获取参数个数 + :return: 参数个数 + """ + num = 0 + for symbol in self._table: + if symbol.is_param: + num += 1 + return num + + def get_params(self): + """ + 获取参数列表 + :return: 参数列表 + """ + params = list() + for symbol in self._table: + if symbol.is_param: + params.append(symbol) + return params + + +class LocalVar(Symbol): + """ + 局部变量 + """ + def __init__(self, l_name, l_type, l_width, l_is_param): + """ + 构造 + :param l_name: 名字 + :param l_type: 类型 + :param l_width: 占空间 + :param l_is_param: 是否为参数 + """ + super().__init__(l_name) + self.type = l_type + self.width = l_width + self.is_param = l_is_param + + +class FunTable(SymbolTable): + """ + 函数表 + """ + def __init__(self): + """ + 构造 + """ + super().__init__() + + def append(self, symbol): + """ + 填入一个新的函数 + :param symbol: 函数 + """ + self._table.append(symbol) + + def chang_fun_type(self, fun_name, type): + for record in self._table: + if record.name == fun_name: + record.return_type = type + return True + + return False + + +class Fun(Symbol): + """ + 函数 + """ + def __init__(self, name, return_type, local_var_table): + """ + 构造 + :param name: 函数名 + :param return_type: 返回类型 + :param local_var_table: 对应的局部变量表 + """ + super().__init__(name) + self.param_types = list() + self.return_type = return_type + self.table = local_var_table diff --git a/semantic_rule_back.py b/semantic_rule_back.py new file mode 100644 index 0000000..b89ba46 --- /dev/null +++ b/semantic_rule_back.py @@ -0,0 +1,1908 @@ +from semantic.symbol import * +from error import SemanticError +from semantic.code import get_temp_block_name, get_temp_var_name + + +""" +添加语义规则的文法 +0. program{code} ->{.init} define-list +1. define-list{code} -> define define-list + {code} | empty +2. define{code} -> type ID define-type{type id} +3. define-type{code .enter} ->{.judge} var-define-follow{type id} + {code} |{.judge} fun-define-follow{type fun} +4. var-define-follow{type} -> ; + {type length} | [ NUM ] ; +5. type ->{type} int + |{type} void +6. fun-define-follow{code} -> ( params{type fun} ) code-block{fun} +7. params{.create} -> param-list{fun} + {.create} | empty +8. param-list -> param{fun} param-follow{fun} +9. param-follow -> , param{fun} param-follow{fun} + | empty +10. param -> type ID array-subscript +11. array-subscript{type} -> [ ] + {type} | empty +12. code-block{code} -> { local-define-list{fun} code-list{fun} } +13. local-define-list -> local-var-define{fun} local-define-list{fun} + | empty +14. local-var-define -> type ID var-define-follow +15. code-list{code} -> code{fun} code-list{fun} + | empty +16. code{code} -> normal-statement{fun} + | selection-statement{fun} + | iteration-statement{fun} + | return-statement{fun} +17. normal-statement -> ; + | ID normal-statement-follow{fun id} +18. normal-statement-follow{code} -> var-follow{fun} = expression{fun} ; + {code} | call-follow{fun id} ; +19. call-follow{code} -> ( call-params{fun id} ) +20. call-params{code} -> call-param-list{fun} + | empty +21. call-param-list{num code} -> expression{fun} call-param-follow{fun} +22. call-param-follow{num code names} -> , expression{fun} call-param-follow{fun} + | empty +23. selection-statement{code} -> if ( expression{fun} ) { code-list{fun} } selection-follow{fun} +24. selection-follow{code} -> else { code-list{fun} } + {code} | empty +25. iteration-statement -> while ( expression{fun} ) iteration-follow{fun} +26. iteration-follow{code} -> { code-list{fun} } + {code} | code{fun} +27. return-statement{code} -> return return-follow{fun} +28. return-follow -> ; + | expression{fun} ; +29. var-follow{code name type} -> [ expression{fun} ] + {type} | empty +30. expression{code name bool} -> additive-expr{fun} expression-follow{fun} +31. expression-follow{bool code op name} -> rel-op additive-expr{fun} + {bool} | empty +32. rel-op{op} -> <= + | < + | > + | >= + | == + | != +33. additive-expr{name code} -> term{fun} additive-expr-follow{fun} +34. additive-expr-follow{add op code name} -> add-op term{fun} additive-expr-follow{fun} + {add} | empty +35. add-op{op} -> + + | - +36. term{name code} -> factor{fun} term-follow{fun} +37. term-follow{mul op code name} -> mul-op factor{fun} term-follow{fun} + {mul} | empty +38. mul-op{op} -> * + | / + | % +39. factor{name code} -> ( expression{fun} ) + | ID id-factor-follow{id fun} + | NUM +40. id-factor-follow -> var-follow{fun} + | ( args{fun} ) +41. args{code num} -> arg-list{fun} + | empty +42. arg-list{code num} -> expression{fun} arg-list-follow{fun} +43. arg-list-follow{code num names} -> , expression{fun} arg-list-follow{fun} + | empty +""" + + +# 定义一个符号表池,每次调用函数的时候使用深拷贝从这里取局部变量表 +symbol_table_pool = SymbolTablePool() + + +class SemanticRule: + """ + 语义规则 + """ + def __init__(self, node): + """ + 构造 + :param node: 树节点 + """ + self.node = node + self.errors = list() + + def __rule(self, node): + """ + 实际的语义规则,需要复写 + :param node: + """ + return [] + + def execute(self): + """ + 执行语义规则 + """ + self.__rule(self.node) + + def have_no_errors(self): + """ + 是否没有错误 + :return: 是否没有错误 + """ + return len(self.errors) == 0 + + +class SemanticRuleFactory: + """ + 语义规则工厂,根据给出的 rule_key 返回相应的实例 + """ + @classmethod + def get_instance(cls, rule_key, node): + """ + 获取语义规则实例 + :param rule_key: 关键字 + :param node: 目标节点 + :return: 实例 + """ + # 0 + if rule_key == 'Program0S': + return Program0S(node) + if rule_key == 'Program0E': + return Program0E(node) + + # 1 + if rule_key == 'DefineList0E': + return DefineList0E(node) + if rule_key == 'DefineList1E': + return DefineList1E(node) + + # 2 + if rule_key == 'Define0E': + return Define0E(node) + if rule_key == 'Define0C2': + return Define0C2(node) + + # 3 + if rule_key == 'DefineType0S': + return DefineType0S(node) + if rule_key == 'DefineType0E': + return DefineType0E(node) + if rule_key == 'DefineType0C0': + return DefineType0C0(node) + if rule_key == 'DefineType1S': + return DefineType1S(node) + if rule_key == 'DefineType1C0': + return DefineType1C0(node) + if rule_key == 'DefineType1E': + return DefineType1E(node) + + # 4 + if rule_key == 'VarDefineFollow0E': + return VarDefineFollow0E(node) + if rule_key == 'VarDefineFollow1E': + return VarDefineFollow1E(node) + + # 5 + if rule_key == 'Type0S': + return Type0S(node) + if rule_key == 'Type1S': + return Type1S(node) + + # 6 + if rule_key == 'FunDefineFollow0E': + return FunDefineFollow0E(node) + if rule_key == 'FunDefineFollow0C1': + return FunDefineFollow0C1(node) + if rule_key == 'FunDefineFollow0C3': + return FunDefineFollow0C3(node) + + # 7 + if rule_key == 'Params0S': + return Params0S(node) + if rule_key == 'Params0C0': + return Params0C0(node) + if rule_key == 'Params1S': + return Params1S(node) + + # 8 + if rule_key == 'ParamList0C0': + return ParamList0C0(node) + if rule_key == 'ParamList0C1': + return ParamList0C1(node) + + # 9 + if rule_key == 'ParamFollow0C1': + return ParamFollow0C1(node) + if rule_key == 'ParamFollow0C2': + return ParamFollow0C2(node) + + # 10 + if rule_key == 'Param0E': + return Param0E(node) + + # 11 + if rule_key == 'ArraySubscript0S': + return ArraySubscript0S(node) + if rule_key == 'ArraySubscript1S': + return ArraySubscript1S(node) + + # 12 + if rule_key == 'CodeBlock0E': + return CodeBlock0E(node) + if rule_key == 'CodeBlock0C1': + return CodeBlock0C1(node) + if rule_key == 'CodeBlock0C2': + return CodeBlock0C2(node) + + # 13 + if rule_key == 'LocalDefineList0C0': + return LocalDefineList0C0(node) + if rule_key == 'LocalDefineList0C1': + return LocalDefineList0C1(node) + + # 14 + if rule_key == 'LocalVarDefine0E': + return LocalVarDefine0E(node) + + # 15 + if rule_key == 'CodeList0E': + return CodeList0E(node) + if rule_key == 'CodeList0C0': + return CodeList0C0(node) + if rule_key == 'CodeList0C1': + return CodeList0C1(node) + if rule_key == 'CodeList1E': + return CodeList1E(node) + + # 16 + if rule_key == 'Code0E': + return Code0E(node) + if rule_key == 'Code0C0': + return Code0C0(node) + if rule_key == 'Code1E': + return Code1E(node) + if rule_key == 'Code1C0': + return Code1C0(node) + if rule_key == 'Code2E': + return Code2E(node) + if rule_key == 'Code2C0': + return Code2C0(node) + if rule_key == 'Code3E': + return Code3E(node) + if rule_key == 'Code3C0': + return Code3C0(node) + + # 17 + if rule_key == 'NormalStatement0E': + return NormalStatement0E(node) + if rule_key == 'NormalStatement1E': + return NormalStatement1E(node) + if rule_key == 'NormalStatement1C1': + return NormalStatement1C1(node) + + # 18 + if rule_key == 'NormalStatementFollow0E': + return NormalStatementFollow0E(node) + if rule_key == 'NormalStatementFollow0C0': + return NormalStatementFollow0C0(node) + if rule_key == 'NormalStatementFollow0C2': + return NormalStatementFollow0C2(node) + if rule_key == 'NormalStatementFollow1E': + return NormalStatementFollow1E(node) + if rule_key == 'NormalStatementFollow1C0': + return NormalStatementFollow1C0(node) + + # 19 + if rule_key == 'CallFollow0E': + return CallFollow0E(node) + if rule_key == 'CallFollow0C1': + return CallFollow0C1(node) + + # 20 + if rule_key == 'CallParams0E': + return CallParams0E(node) + if rule_key == 'CallParams0C0': + return CallParams0C0(node) + if rule_key == 'CallParams1E': + return CallParams1E(node) + + # 21 + if rule_key == 'CallParamList0E': + return CallParamList0E(node) + if rule_key == 'CallParamList0C0': + return CallParamList0C0(node) + if rule_key == 'CallParamList0C1': + return CallParamList0C1(node) + + # 22 + if rule_key == 'CallParamFollow0E': + return CallParamFollow0E(node) + if rule_key == 'CallParamFollow0C1': + return CallParamFollow0C1(node) + if rule_key == 'CallParamFollow0C2': + return CallParamFollow0C2(node) + if rule_key == 'CallParamFollow1E': + return CallParamFollow1E(node) + + # 23 + if rule_key == 'SelectionStatement0E': + return SelectionStatement0E(node) + if rule_key == 'SelectionStatement0C2': + return SelectionStatement0C2(node) + if rule_key == 'SelectionStatement0C5': + return SelectionStatement0C5(node) + if rule_key == 'SelectionStatement0C7': + return SelectionStatement0C7(node) + + # 24 + if rule_key == 'SelectionFollow0E': + return SelectionFollow0E(node) + if rule_key == 'SelectionFollow0C2': + return SelectionFollow0C2(node) + if rule_key == 'SelectionFollow1E': + return SelectionFollow1E(node) + + # 25 + if rule_key == 'IterationStatement0E': + return IterationStatement0E(node) + if rule_key == 'IterationStatement0C2': + return IterationStatement0C2(node) + if rule_key == 'IterationStatement0C4': + return IterationStatement0C4(node) + + # 26 + if rule_key == 'IterationFollow0E': + return IterationFollow0E(node) + if rule_key == 'IterationFollow0C1': + return IterationFollow0C1(node) + if rule_key == 'IterationFollow1E': + return IterationFollow1E(node) + if rule_key == 'IterationFollow1C0': + return IterationFollow1C0(node) + + # 27 + if rule_key == 'ReturnStatement0E': + return ReturnStatement0E(node) + if rule_key == 'ReturnStatement0C1': + return ReturnStatement0C1(node) + + # 28 + if rule_key == 'ReturnFollow0E': + return ReturnFollow0E(node) + if rule_key == 'ReturnFollow1E': + return ReturnFollow1E(node) + if rule_key == 'ReturnFollow1C0': + return ReturnFollow1C0(node) + + # 29 + if rule_key == 'VarFollow0E': + return VarFollow0E(node) + if rule_key == 'VarFollow0C1': + return VarFollow0C1(node) + if rule_key == 'VarFollow1E': + return VarFollow1E(node) + + # 30 + if rule_key == 'Expression0E': + return Expression0E(node) + if rule_key == 'Expression0C0': + return Expression0C0(node) + if rule_key == 'Expression0C1': + return Expression0C1(node) + + # 31 + if rule_key == 'ExpressionFollow0E': + return ExpressionFollow0E(node) + if rule_key == 'ExpressionFollow0C1': + return ExpressionFollow0C1(node) + if rule_key == 'ExpressionFollow1E': + return ExpressionFollow1E(node) + + # 32 + if rule_key == 'RelOp0E': + return RelOp0E(node) + if rule_key == 'RelOp1E': + return RelOp1E(node) + if rule_key == 'RelOp2E': + return RelOp2E(node) + if rule_key == 'RelOp3E': + return RelOp3E(node) + if rule_key == 'RelOp4E': + return RelOp4E(node) + if rule_key == 'RelOp5E': + return RelOp5E(node) + + # 33 + if rule_key == 'AdditiveExpr0E': + return AdditiveExpr0E(node) + if rule_key == 'AdditiveExpr0C0': + return AdditiveExpr0C0(node) + if rule_key == 'AdditiveExpr0C1': + return AdditiveExpr0C1(node) + + # 34 + if rule_key == 'AdditiveExprFollow0E': + return AdditiveExprFollow0E(node) + if rule_key == 'AdditiveExprFollow0C1': + return AdditiveExprFollow0C1(node) + if rule_key == 'AdditiveExprFollow0C2': + return AdditiveExprFollow0C2(node) + if rule_key == 'AdditiveExprFollow1E': + return AdditiveExprFollow1E(node) + + # 35 + if rule_key == 'AddOp0E': + return AddOp0E(node) + if rule_key == 'AddOp1E': + return AddOp1E(node) + + # 36 + if rule_key == 'Term0E': + return Term0E(node) + if rule_key == 'Term0C0': + return Term0C0(node) + if rule_key == 'Term0C1': + return Term0C1(node) + + # 37 + if rule_key == 'TermFollow0E': + return TermFollow0E(node) + if rule_key == 'TermFollow0C1': + return TermFollow0C1(node) + if rule_key == 'TermFollow0C2': + return TermFollow0C2(node) + + # 38 + if rule_key == 'MulOp0E': + return MulOp0E(node) + if rule_key == 'MulOp1E': + return MulOp1E(node) + if rule_key == 'MulOp2E': + return MulOp2E(node) + + # 39 + if rule_key == 'Factor0E': + return Factor0E(node) + if rule_key == 'Factor0C1': + return Factor0C1(node) + if rule_key == 'Factor1E': + return Factor1E(node) + if rule_key == 'Factor1C1': + return Factor1C1(node) + if rule_key == 'Factor2E': + return Factor2E(node) + + # 40 + if rule_key == 'IdFactorFollow0E': + return IdFactorFollow0E(node) + if rule_key == 'IdFactorFollow1E': + return IdFactorFollow1E(node) + if rule_key == 'IdFactorFollow1C1': + return IdFactorFollow1C1(node) + + # 41 + if rule_key == 'Args0E': + return Args0E(node) + if rule_key == 'Args0C0': + return Args0C0(node) + if rule_key == 'Args1E': + return Args1E(node) + + # 42 + if rule_key == 'ArgList0E': + return ArgList0E(node) + if rule_key == 'ArgList0C0': + return ArgList0C0(node) + if rule_key == 'ArgList0C1': + return ArgList0C1(node) + + # 43 + if rule_key == 'ArgListFollow0E': + return ArgListFollow0E(node) + if rule_key == 'ArgListFollow0C1': + return ArgListFollow0C1(node) + if rule_key == 'ArgListFollow0C2': + return ArgListFollow0C2(node) + if rule_key == 'ArgListFollow1E': + return ArgListFollow1E(node) + + return None + +# S 产生式开始 +# E 产生式结束 +# CN 产生式第N个元素应用之后 + + +# 0 +class Program0S(SemanticRule): + def __rule(self, node): + symbol_table_pool.init() + + def execute(self): + self.__rule(self.node) + + +class Program0E(SemanticRule): + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + def execute(self): + self.__rule(self.node) + + +# 1 +class DefineList0E(SemanticRule): + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + for c in node.children[1].code: + node.code.append(c) + + def execute(self): + self.__rule(self.node) + + +class DefineList1E(SemanticRule): + def __rule(self, node): + node.code.clear() + + def execute(self): + self.__rule(self.node) + + +# 2 +class Define0E(SemanticRule): + def __rule(self, node): + for c in node.children[2].code: + node.code.append(c) + + def execute(self): + self.__rule(self.node) + + +class Define0C2(SemanticRule): + def __rule(self, node): + node.type = node.get_pre_brother(2).type + node.id = node.get_pre_brother(1).lexical + + def execute(self): + self.__rule(self.node) + + +# 3 +class DefineType0S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + # 检查 type 是否是 void + if node.type == 'void': + self.errors.append(SemanticError('变量' + node.id + '不能定义为void类型')) + if node.type == 'int': + # 检查是否重定义 + if symbol_table_pool.global_var_table.exist(node.id): + self.errors.append(SemanticError('变量' + node.id + '重定义')) + + +class DefineType0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if node.children[0].type == 'var': + symbol_table_pool.global_var_table.append( + GlobalVar(node.id, 'int', 4) + ) + if node.children[0].type == 'array': + symbol_table_pool.global_var_table.append( + GlobalVar(node.id, 'array', 4 * node.children[0].length) + ) + + +class DefineType0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = node.parent.type + node.id = node.parent.id + + +class DefineType1S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + # 检查是否重定义 + if symbol_table_pool.fun_table.exist(node.id): + self.errors.append(SemanticError('函数名' + node.id + '重定义')) + + +class DefineType1C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = node.parent.type + node.fun = node.parent.id + + +class DefineType1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + +# 4 +class VarDefineFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'var' + + +class VarDefineFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'array' + node.length = node.children[1].lexical + + +# 5 +class Type0S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'int' + + +class Type1S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'void' + + +# 6 +class FunDefineFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[3].code: + node.code.append(c) + + +class FunDefineFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = node.parent.type + node.fun = node.parent.fun + + +class FunDefineFollow0C3(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 7 +class Params0S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + symbol_table_pool.append( + LocalVarTable(node.fun, symbol_table_pool.global_var_table) + ) + symbol_table_pool.fun_table.append( + Fun(node.fun, node.type, symbol_table_pool.query(node.fun)) + ) + + +class Params0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class Params1S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + symbol_table_pool.append( + LocalVarTable(node.fun, symbol_table_pool.global_var_table) + ) + symbol_table_pool.fun_table.append( + Fun(node.fun, node.type, symbol_table_pool.query(node.fun)) + ) + + +# 8 +class ParamList0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class ParamList0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 9 +class ParamFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class ParamFollow0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 10 +class Param0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + # 先判断 type 是否为 void + if node.children[0].type == 'void': + self.errors.append(SemanticError('参数' + node.children[1].lexical + '不能定义为void类型')) + if node.children[0].type == 'int': + # 判断是否重定义 + if symbol_table_pool.query(node.fun).exist(node.children[1].lexical): + self.errors.append(SemanticError('参数' + node.children[1].lexical + '重定义')) + else: + if node.children[2].type == 'array': + symbol_table_pool.query(node.fun).append( + LocalVar(node.children[1].lexical, 'address', 4, True) + ) + if node.children[2].type == 'var': + symbol_table_pool.query(node.fun).append( + LocalVar(node.children[1].lexical, 'int', 4, True) + ) + + +# 11 +class ArraySubscript0S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'array' + + +class ArraySubscript1S(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'var' + + +# 12 +class CodeBlock0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.code.append(node.fun + ':') + for c in node.children[2].code: + node.code.append(c) + + +class CodeBlock0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class CodeBlock0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 13 +class LocalDefineList0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class LocalDefineList0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 14 +class LocalVarDefine0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if node.children[0].type == 'void': + self.errors.append(SemanticError('变量' + node.children[1].lexical + '不能定义为void类型')) + if node.children[0].type == 'int': + if symbol_table_pool.query(node.fun).exist(node.children[1].lexical): + self.errors.append(SemanticError('变量' + node.children[1].lexical + '重定义')) + else: + if node.children[2].type == 'var': + symbol_table_pool.query(node.fun).append( + LocalVar(node.children[1].lexical, 'int', 4, False) + ) + if node.children[2].type == 'array': + symbol_table_pool.query(node.fun).append( + LocalVar(node.children[1].lexical, 'array', 4 * node.children[2].length, False) + ) + + +# 15 +class CodeList0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + for c in node.children[1].code: + node.code.append(c) + + +class CodeList0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class CodeList0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class CodeList1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.code.clear() + + +# 16 +class Code0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + +class Code0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class Code1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + +class Code1C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class Code2E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + +class Code2C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class Code3E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + +class Code3C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 17 +class NormalStatement0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.code.clear() + + +class NormalStatement1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[1].code: + node.code.append(c) + + +class NormalStatement1C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + node.id = node.get_pre_brother(1).lexical + + +# 18 +class NormalStatementFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if node.children[0].type == 'var': + for c in node.children[2].code: + node.code.append(c) + node.code.append(node.id + ' := ' + node.children[2].name) + if node.children[0].type == 'array': + for c in node.children[0].code: + node.code.append(c) + for c in node.children[2].code: + node.code.append(c) + node.code.append(node.id + '[' + node.children[0].name + ']' + ' := ' + node.children[2].name) + + +class NormalStatementFollow0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class NormalStatementFollow0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class NormalStatementFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + node.code.append('call ' + node.id + ', ' + str(symbol_table_pool.query(node.id).get_params_num())) + + +class NormalStatementFollow1C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + node.id = node.parent.id + + +# 19 +class CallFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[1].code: + node.code.append(c) + + +class CallFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + node.id = node.parent.id + + +# 20 +class CallParams0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if symbol_table_pool.query(node.id).get_params_num() != node.children[0].num: + self.errors.append(SemanticError('函数体' + node.fun + '调用' + node.id + '的时候,参数数量不匹配')) + else: + for c in node.children[0].code: + node.code.append(c) + + +class CallParams0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class CallParams1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if symbol_table_pool.query(node.fun).get_params_num() != 0: + self.errors.append(SemanticError('函数体' + node.fun + '调用' + node.id + '的时候,参数数量不匹配')) + + +# 21 +class CallParamList0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.num = 1 + node.children[1].num + for c in node.children[0].code: + node.code.append(c) + for c in node.children[1].code: + node.code.append(c) + node.code.append('param ' + node.children[0].name) + for name in node.children[1].names: + node.code.append('param ' + name) + + +class CallParamList0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class CallParamList0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 22 +class CallParamFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.num = 1 + node.children[2].num + for c in node.children[1].code: + node.code.append(c) + for c in node.children[2].code: + node.code.append(c) + node.names.append(node.children[1].name) + for n in node.children[2].names: + node.names.append(n) + + +class CallParamFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class CallParamFollow0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class CallParamFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.num = 0 + node.code.clear() + node.names.clear() + + +# 23 +class SelectionStatement0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if not node.children[2].bool: + self.errors.append(SemanticError('if-结构中的表达式不是bool表达式')) + else: + for c in node.children[2].code: + node.code.append(c) + if_block = get_temp_block_name() + else_block = get_temp_block_name() + next_block = get_temp_block_name() + node.code.append('if ' + node.children[2].name + ' goto ' + if_block) + + + node.code.append(if_block + ':') + for c in node.children[5].code: + node.code.append(c) + node.code.append('goto ' + next_block) + + node.code.append(else_block + ':') + + for c in node.children[7].code: + node.code.append(c) + node.code.append('goto ' + next_block) + + + node.code.append(next_block + ':') + + +class SelectionStatement0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class SelectionStatement0C5(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class SelectionStatement0C7(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 24 +class SelectionFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[2].code: + node.code.append(c) + + +class SelectionFollow0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class SelectionFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.code.clear() + + +# 25 +class IterationStatement0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + judge_block = get_temp_block_name() + iteration_block = get_temp_block_name() + next_block = get_temp_block_name() + node.code.append(judge_block + ':') + for c in node.children[2].code: + node.code.append(c) + node.code.append('if ' + node.children[2].name + ' goto ' + iteration_block) + node.code.append('goto ' + next_block) + node.code.append(iteration_block + ':') + for c in node.children[4].code: + node.code.append(c) + node.code.append('goto ' + judge_block) + node.code.append(next_block + ':') + + +class IterationStatement0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class IterationStatement0C4(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 26 +class IterationFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[1].code: + node.code.append(c) + + +class IterationFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class IterationFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + + +class IterationFollow1C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 27 +class ReturnStatement0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[1].code: + node.code.append(c) + + +class ReturnStatement0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 28 +class ReturnFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.code.append('return') + + +class ReturnFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + node.code.append('return ' + node.children[0].name) + + +class ReturnFollow1C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 29 +class VarFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'array' + node.name = node.children[1].name + for c in node.children[1].code: + node.code.append(c) + + +class VarFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class VarFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.type = 'var' + + +# 30 +class Expression0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.bool = node.children[1].bool + if node.children[1].bool: + node.name = get_temp_var_name() + for c in node.children[0].code: + node.code.append(c) + for c in node.children[1].code: + node.code.append(c) + node.code.append(node.name + ' := ' + node.children[0].name + ' ' + + node.children[1].op + ' ' + node.children[1].name) + else: + node.name = node.children[0].name + for c in node.children[0].code: + node.code.append(c) + + +class Expression0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class Expression0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 31 +class ExpressionFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.bool = True + node.op = node.children[0].op + node.name = node.children[1].name + for c in node.children[1].code: + node.code.append(c) + + +class ExpressionFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class ExpressionFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.bool = False + + +# 32 +class RelOp0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +class RelOp1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +class RelOp2E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +class RelOp3E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +class RelOp4E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +class RelOp5E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +# 33 +class AdditiveExpr0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if node.children[1].add: + node.name = get_temp_var_name() + for c in node.children[0].code: + node.code.append(c) + for c in node.children[1].code: + node.code.append(c) + node.code.append(node.name + ' := ' + node.children[0].name + ' ' + node.children[1].op + + ' ' + node.children[1].name) + else: + node.name = node.children[0].name + for c in node.children[0].code: + node.code.append(c) + + +class AdditiveExpr0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class AdditiveExpr0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 34 +class AdditiveExprFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.add = True + node.op = node.children[0].op + if node.children[2].add: + node.name = get_temp_var_name() + for c in node.children[1].code: + node.code.append(c) + for c in node.children[2].code: + node.code.append(c) + node.code.append(node.name + ' := ' + node.children[1].name + ' ' + node.children[2].op + + ' ' + node.children[2].name) + else: + node.name = node.children[1].name + for c in node.children[1].code: + node.code.append(c) + + +class AdditiveExprFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class AdditiveExprFollow0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class AdditiveExprFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.add = False + + +# 35 +class AddOp0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +class AddOp1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +# 36 +class Term0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if node.children[1].mul: + node.name = get_temp_var_name() + for c in node.children[0].code: + node.code.append(c) + for c in node.children[1].code: + node.code.append(c) + node.code.append(node.name + ' := ' + node.children[0].name + ' ' + node.children[1].op + + ' ' + node.children[1].name) + else: + node.name = node.children[0].name + for c in node.children[0].code: + node.code.append(c) + + +class Term0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class Term0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 37 +class TermFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.mul = True + node.op = node.children[0].op + if node.children[2].mul: + node.name = get_temp_var_name() + for c in node.children[1].code: + node.code.append(c) + for c in node.children[2].code: + node.code.append(c) + node.code.append(node.name + ' := ' + node.children[1].name + ' ' + node.children[2].op + + ' ' + node.children[2].name) + else: + node.name = node.children[1].name + for c in node.children[1].code: + node.code.append(c) + + +class TermFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class TermFollow0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 38 +class MulOp0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +class MulOp1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + +class MulOp2E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.op = node.children[0].lexical + + +# 39 +class Factor0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[1].code: + node.code.append(c) + node.name = node.children[1].name + + +class Factor0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class Factor1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[1].code: + node.code.append(c) + node.name = node.children[1].name + + +class Factor1C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.id = node.get_pre_brother(1).lexical + node.fun = node.parent.fun + + +class Factor2E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.name = get_temp_var_name() + node.code.append(node.name + ' := ' + node.children[0].lexical) + + +# 40 +class IdFactorFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if symbol_table_pool.query(node.fun).exist(node.id): + if node.children[0].type == 'var': + node.name = node.id + if node.children[0].type == 'array': + node.name = get_temp_var_name() + for c in node.children[0].code: + node.code.append(c) + node.code.append(node.name + ' := ' + node.id + '[' + node.children[0].name + ']') + else: + self.errors.append('变量' + node.id + '未定义') + + +class IdFactorFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + if symbol_table_pool.fun_table.exist(node.id): + if node.children[1].num != symbol_table_pool.query(node.id).get_params_num(): + self.errors.append('调用函数' + node.id + '的时候参数数量不匹配') + else: + for c in node.children[1].code: + node.code.append(c) + node.code.append('call ' + node.id + ', ' + str(symbol_table_pool.query(node.fun).get_params_num())) + node.name = get_temp_var_name() + node.code.append(node.name + ' := ' + 'result') + else: + self.errors.append('函数' + node.id + '未定义') + + +class IdFactorFollow1C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 41 +class Args0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + for c in node.children[0].code: + node.code.append(c) + node.num = node.children[0].num + + +class Args0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class Args1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.code.clear() + node.num = 0 + + +# 42 +class ArgList0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.num = 1 + node.children[1].num + for c in node.children[0].code: + node.code.append(c) + for c in node.children[1].code: + node.code.append(c) + node.code.append('param ' + node.children[0].name) + for name in node.children[1].names: + node.code.append('param ' + name) + + +class ArgList0C0(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class ArgList0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +# 43 +class ArgListFollow0E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.num = 1 + node.children[2].num + for c in node.children[1].code: + node.code.append(c) + for c in node.children[2].code: + node.code.append(c) + node.names.append(node.children[1].name) + for name in node.children[2].names: + node.names.append(name) + + +class ArgListFollow0C1(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class ArgListFollow0C2(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.fun = node.parent.fun + + +class ArgListFollow1E(SemanticRule): + def execute(self): + self.__rule(self.node) + + def __rule(self, node): + node.num = 0 + node.code.clear() + node.names.clear() diff --git a/syntax/rule.py b/syntax/rule.py new file mode 100644 index 0000000..4ccc29e --- /dev/null +++ b/syntax/rule.py @@ -0,0 +1,655 @@ +class Sign: + """ + 符号 + """ + def __init__(self, sign_type, sign_str='', sign_line=-1): + """ + 构造 + :param sign_type: 符号的类型 + :param sign_str: 符号的内容(可以为空) + :param sign_line: 符号所在行数(可以为空) + """ + self.type = sign_type + self.str = sign_str + self.line = sign_line + + def is_terminal_sign(self): + """ + 是不是终结符 + :return: True/False + """ + if self.type == 'empty': + return True + else: + for i in terminal_sign_type: + if i == self.type: + return True + return False + + def is_non_terminal_sign(self): + """ + 是不是非终结符 + :return: True/False + """ + for i in non_terminal_sign_type: + if i == self.type: + return True + return False + + def is_empty_sign(self): + """ + 是不是空字 + :return: True/False + """ + return self.type == 'empty' + + +class Production: + """ + 产生式 + """ + def __init__(self, left_type, right_types, semantic_start, semantic_children, semantic_end): + """ + 产生式左边 + :param left_type: 产生式左边的符号类型 + :param right_types: 产生式右边的符号类型列表 + :param semantic_start: 语义操作关键字 - 开始 + :param semantic_children: 语义操作关键字 - 孩子 + :param semantic_end: 语义操作关键字 - 结束 + """ + self.left = Sign(left_type) + self.right = list() + for i in right_types: + self.right.append(Sign(i)) + + # 调试用的 + self.str = self.left.type + ' ->' + for i in self.right: + self.str += ' ' + i.type + + # 语义操作关键字 + self.semantic_start = semantic_start + self.semantic_children = list() + for c in semantic_children: + self.semantic_children.append(c) + self.semantic_end = semantic_end + + +""" +1. program -> define-list +2. define-list -> define define-list + | empty +3. define -> type ID define-type +4. define-type -> var-define-follow + | fun-define-follow +5. var-define-follow -> ; + | [ NUM ] ; +6. type -> int + | void +7. fun-define-follow -> ( params ) code-block +8. params -> param-list + | empty +9. param-list -> param param-follow +10. param-follow -> , param param-follow + | empty +11. param -> type ID array-subscript +12. array-subscript -> [ ] + | empty +13. code-block -> { local-define-list code-list } +14. local-define-list -> local-var-define local-define-list + | empty +15. local-var-define -> type ID var-define-follow +16. code-list -> code code-list + | empty +17. code -> normal-statement + | selection-statement + | iteration-statement + | return-statement +18. normal-statement -> ; + | ID normal-statement-follow +19. normal-statement-follow -> var-follow = exp ; + | call-follow ; +20. call-follow -> ( call-params ) +21. call-params -> call-param-list + | empty +22. call-param-list -> exp call-param-follow +23. call-param-follow -> , exp call-param-follow + | empty +24. selection-statement -> if ( exp ) { code-list } selection-follow +25. selection-follow -> else { code-list } + | empty +26. iteration-statement -> while ( exp ) iteration-follow +27. iteration-follow -> { code-list } + | code +28. return-statement -> return return-follow +29. return-follow -> ; + | exp ; +30. var-follow -> [ exp ] + | empty +31. exp -> additive-expr exp-follow +32. exp-follow -> rel-op additive-expr + | empty +33. rel-op -> <= + | < + | > + | >= + | == + | != +34. additive-expr -> term additive-expr-follow +35. additive-expr-follow -> add-op term additive-expr-follow + | empty +36. add-op -> + + | - +37. term -> factor term-follow +38. term-follow -> mul-op factor term-follow + | empty +39. mul-op -> * + | / +40. factor -> ( exp ) + | ID id-factor-follow | NUM +41. id-factor-follow -> var-follow + | ( args ) +42. args -> arg-list + | empty +43. arg-list -> exp arg-list-follow +44. arg-list-follow -> , exp arg-list-follow + | empty +""" + + +# 所有终结符的类型 +terminal_sign_type = [ + 'fn', + 'else', + 'if', + 'int', + 'return', + 'void', + 'while', + 'addition', + 'subtraction', + 'multiplication', + 'division', + 'bigger', + 'bigger-equal', + 'smaller', + 'smaller-equal', + 'equal', + 'not-equal', + 'evaluate', + 'semicolon', + 'comma', + 'left-parentheses', + 'right-parentheses', + 'left-bracket', + 'right-bracket', + 'left-brace', + 'right-brace', + 'float-num', + 'int-num', + 'id', + 'colon', + 'right-arrow', + 'i32', + 'f32', + # 在这之前添加非终结符类型,请务必不要动 'pound' + 'pound' +] + +# 所有非终结符的类型 +non_terminal_sign_type = [ + 'program', + 'define-lists', + 'define-list', + 'define', + 'define-type', + 'var-define-follow', + 'type', + 'fun-define', + 'fun-define-follow', + 'params', + 'param-list', + 'param-follow', + 'param', + 'arraylist', + 'code-block', + 'local-define-list', + 'local-var-define', + 'code-list', + 'code', + 'normal-statement', + 'normal-statement-follow', + 'call-follow', + 'call-params', + 'call-param-list', + 'call-param-follow', + 'selection-statement', + 'selection-follow', + 'iteration-statement', + 'iteration-follow', + 'return-statement', + 'return-follow', + # 'eval-statement', + # 'var', + 'var-follow', + 'exp', + 'exp-follow', + 'rel-op', + 'additive-expr', + 'additive-expr-follow', + 'add-op', + 'term', + 'term-follow', + 'mul-op', + 'factor', + 'id-factor-follow', + 'args', + 'arg-list', + 'arg-list-follow', + 'global-var-define', + 'fun-return', + 'paramlist', + 'arraylist', + 'global-var-define-follow', + 'local-define', + 'local-define-follow', + 'arraylist-with-num' + +] + +""" +0. program -> define-lists +1. define-lists -> define-list define-lists +2. define-lists -> +3. define-list -> fun-define +4. define-list -> global-var-define +5. fun-define -> fn id left-parentheses params right-parentheses fun-return left-brace code-block right-brace +6. params -> +7. params -> paramlist +8. paramlist -> param param-follow +9. param-follow -> comma param-follow +10. param-follow -> +11. param -> id colon type arraylist +12. arraylist -> +13. arraylist -> left-bracket right-bracket +14. fun-return -> +15. fun-return -> right-arrow type arraylist +16. type -> i32 +17. type -> f32 +18. type -> void +19. global-var-define -> type arraylist id global-var-define-follow +20. global-var-define-follow -> comma id global-var-define-follow +21. global-var-define-follow -> semicolon +22. code-block -> code-list +23. code-list -> code code-list +24. code-list -> +25. code -> local-define +26. code -> normal-statement +27. code -> selection-statement +28. code -> iteration-statement +29. code -> return-statement +30. local-define -> type arraylist id local-define-follow +31. local-define-follow -> comma id local-define-follow +32. local-define-follow -> semicolon +33. normal-statement -> semicolon +34. normal-statement -> id normal-statement-follow +35. normal-statement-follow -> var-follow equal exp semicolon +36. normal-statement-follow -> call-follow semicolon +37. var-follow -> +38. var-follow -> left-bracket exp right-bracket +39. call-follow -> left-parentheses call-params right-parentheses +40. call-params -> call-param-list +41. call-params -> +42. call-param-list -> exp call-param-follow +43. call-param-follow -> comma exp call-param-follow +44. call-param-follow -> +45. selection-statement -> if exp left-brace code-list right-brace selection-follow +46. selection-follow -> else left-brace code-list right-brace +47. selection-follow -> +48. iteration-statement -> while exp left-brace code-list right-brace +49. return-statement -> return return-follow +50. return-follow -> semicolon +51. return-follow -> exp semicolon +52. exp -> additive-expr exp-follow +53. exp-follow -> rel-op additive-expr +54. exp-follow -> +55. rel-op -> smaller-equal +56. rel-op -> smaller +57. rel-op -> bigger +58. rel-op -> bigger-equal +59. rel-op -> equal +60. rel-op -> not-equal +61. additive-expr -> term additive-expr-follow +62. additive-expr-follow -> add-op term additive-expr-follow +63. additive-expr-follow -> +64. add-op -> addition +65. add-op -> subtraction +66. term -> factor term-follow +67. term-follow -> mul-op factor term-follow +68. term-follow -> +69. mul-op -> multiplication +70. mul-op -> division +71. factor -> left-parentheses exp right-parentheses +72. factor -> id id-factor-follow +73. factor -> num +74. id-factor-follow -> var-follow +75. id-factor-follow -> left-parentheses args right-parentheses +76. args -> arg-list +77. args -> +78. arg-list -> exp arg-list-follow +79. arg-list-follow -> comma exp arg-list-follow +80. arg-list-follow -> + + +""" + + +# 文法产生式 +productions = [ + # 0 + Production('program', ['define-lists'], + 'Program0S', [None], 'Program0E'), + # 1 + Production('define-lists', ['define-list', 'define-lists'], + None, [None, None], 'DefineLists1E'), + # 2 + Production('define-lists', [], + None, [], 'DefineLists2E'), + # 3 + Production('define-list', ['fun-define'], + None, [None], 'DefineList3E', + ), + # 4 + Production('define-list', ['global-var-define'], + None, [None], 'DefineList4E', + ), + # 5 + Production('fun-define', + ['fn', 'id', 'left-parentheses', 'params', 'right-parentheses', 'fun-return', 'left-brace', 'code-block', + 'right-brace'], + None, [None, None, None, 'FunDefine5C3', None, 'FunDefine5C5', None, None, 'FunDefine5C7'], 'FunDefine5E', + ), + # 6 + Production('params', [], + 'Params6S', [], None, + ), + # 7 + Production('params', ['paramlist'], + 'Params7S', ['Params7C0'], None, + ), + # 8 + Production('paramlist', ['param', 'param-follow'], + None, ['ParamList8C0', 'ParamList8C1'], None, + ), + # 9 + Production('param-follow', ['comma', 'param', 'param-follow'], + None, [None, 'ParamFollow9C1', 'ParamFollow9C2'], None, + ), + # 10 + Production('param-follow', [], + None, [], None, + ), + # 11 + Production('param', ['id', 'colon', 'type', 'arraylist'], + None, [None, None, None, None], 'Param11E', + ), + # 12 + Production('arraylist', [], + 'ArrayList12S', [], None, + ), + # 13 + Production('arraylist', ['left-bracket', 'right-bracket'], + 'ArrayList13S', [None, None], None, + ), + # 14 + Production('fun-return', [], + 'FunReturn14S', [], None, + ), + # 15 + Production('fun-return', ['right-arrow', 'type', 'arraylist'], + None, [None, None, None], 'FunReturn15E', + ), + # 16 + Production('type', ['i32'], + 'Type16S', [None], None, + ), + # 17 + Production('type', ['f32'], + 'Type17S', [None], None, + ), + # 18 + Production('type', ['void'], + "Type18S", [None], None, + ), + # 19 + Production('global-var-define', ['type', 'arraylist-with-num', 'id', 'global-var-define-follow'], + None, [None, None, None, 'GlobalVarDefine19C3'], 'GlobalVarDefine19E', + ), + # 20 + Production('global-var-define-follow', ['comma', 'id', 'global-var-define-follow'], + None, [None, None, 'GlobalVarDefineFllow20C2'], 'GlobalVarDefineFllow20E', + ), + # 21 + Production('global-var-define-follow', ['semicolon'], + None, [None], None, + ), + # 22 + Production('code-block', ['code-list'], + None, ['CodeBlock22C0'], 'CodeBlock22E', + ), + # 23 + Production('code-list', ['code', 'code-list'], + None, ["CodeList23C0", 'CodeList23C1'], 'CodeList23E', + ), + # 24 + Production('code-list', [], + None, [], 'CodeList24E', + ), + # 25 + Production('code', ['local-define'], + None, ['Code25C0'], 'Code25E', + ), + # 26 + Production('code', ['normal-statement'], + None, ['Code26C0'], 'Code26E', + ), + # 27 + Production('code', ['selection-statement'], + None, ['Code27C0'], 'Code26E', + ), + # 28 + Production('code', ['iteration-statement'], + None, ['Code28C0'], 'Code25E', + ), + # 29 + Production('code', ['return-statement'], + None, ['Code29C0'], 'Code25E', + ), + # # 30 + # Production('local-define', ['type', 'arraylist', 'id', 'local-define-follow'], + # None, [None, None, None, None], None, + # ), + # # 31 + # Production('local-define-follow', ['comma', 'id', 'local-define-follow'], + # None, [None, None, None], None, + # ), + # # 32 + # Production('local-define-follow', ['semicolon'], + # None, [None], None, + # ), + # # 33 + # Production('normal-statement', ['semicolon'], + # None, [None], None, + # ), + # # 34 + # Production('normal-statement', ['id', 'normal-statement-follow'], + # None, [None, None], None, + # ), + # # 35 + # Production('normal-statement-follow', ['var-follow', 'equal', 'exp', 'semicolon'], + # None, [None, None, None, None], None, + # ), + # # 36 + # Production('normal-statement-follow', ['call-follow', 'semicolon'], + # None, [None], None, + # ), + # # 37 + # Production('var-follow', [], + # None, [], None, + # ), + # # 38 + # Production('var-follow', ['left-bracket', 'exp', 'right-bracket'], + # None, [None, None, None], None, + # ), + # # 39 + # Production('call-follow', ['left-parentheses', 'call-params', 'right-parentheses'], + # None, [None, None, None], None, + # ), + # # 40 + # Production('call-params', ['call-param-list'], + # None, [None], None, + # ), + # # 41 + # Production('call-params', [], + # None, [], None, + # ), + # # 42 + # Production('call-param-list', ['exp', 'call-param-follow'], + # None, [None, None], None, + # ), + # # 43 + # Production('call-param-follow', ['comma', 'exp', 'call-param-follow'], + # None, [None, None, None], None, + # ), + # # 44 + # Production('call-param-follow', [], + # None, [], None, + # ), + # # 45 + # Production('selection-statement', ['if', 'exp', 'left-brace', 'code-list', 'right-brace', 'selection-follow'], + # None, [None, None, None, None, None, None], None, + # ), + # # 46 + # Production('selection-follow', ['else', 'left-brace', 'code-list', 'right-brace'], + # None, [None, None, None, None], None, + # ), + # # 47 + # Production('selection-follow', [], + # None, [], None, + # ), + # # 48 + # Production('iteration-statement', ['while', 'exp', 'left-brace', 'code-list', 'right-brace'], + # None, [None, None, None, None, None], None, + # ), + # # 49 + # Production('return-statement', ['return', 'return-follow'], + # None, [None, None], None, + # ), + # # 50 + # Production('return-follow', ['semicolon'], + # None, [None], None, + # ), + # # 51 + # Production('return-follow', ['exp', 'semicolon'], + # None, [None, None], None, + # ), + # # 52 + # Production('exp', ['additive-expr', 'exp-follow'], + # None, ['exp0C0', 'exp0C1'], 'exp0E'), + # # 53 + # Production('exp-follow', ['rel-op', 'additive-expr'], + # None, [None, 'expFollow0C1'], 'expFollow0E'), + # # 54 + # Production('exp-follow', [], + # None, [], 'expFollow1E'), + # # 55 + # Production('rel-op', ['smaller-equal'], + # None, [None], 'RelOp0E'), + # # 56 + # Production('rel-op', ['smaller'], + # None, [None], 'RelOp1E'), + # # 57 + # Production('rel-op', ['bigger'], + # None, [None], 'RelOp2E'), + # # 58 + # Production('rel-op', ['bigger-equal'], + # None, [None], 'RelOp3E'), + # # 59 + # Production('rel-op', ['equal'], + # None, [None], 'RelOp4E'), + # # 60 + # Production('rel-op', ['not-equal'], + # None, [None], 'RelOp5E'), + # # 61 + # Production('additive-expr', ['term', 'additive-expr-follow'], + # None, ['AdditiveExpr0C0', 'AdditiveExpr0C1'], 'AdditiveExpr0E'), + # # 62 + # Production('additive-expr-follow', ['add-op', 'term', 'additive-expr-follow'], + # None, [None, 'AdditiveExprFollow0C1', 'AdditiveExprFollow0C2'], 'AdditiveExprFollow0E'), + # # 63 + # Production('additive-expr-follow', [], + # None, [], 'AdditiveExprFollow1E'), + # # 64 + # Production('add-op', ['addition'], + # None, [None], 'AddOp0E'), + # # 65 + # Production('add-op', ['subtraction'], + # None, [None], 'AddOp1E'), + # # 66 + # Production('term', ['factor', 'term-follow'], + # None, ['Term0C0', 'Term0C1'], 'Term0E'), + # # 67 + # Production('term-follow', ['mul-op', 'factor', 'term-follow'], + # None, [None, 'TermFollow0C1', 'TermFollow0C2'], 'TermFollow0E'), + # # 68 + # Production('term-follow', [], + # None, [], None), + # # 69 + # Production('mul-op', ['multiplication'], + # None, [None], 'MulOp0E'), + # # 70 + # Production('mul-op', ['division'], + # None, [None], 'MulOp1E'), + # # 71 + # Production('factor', ['left-parentheses', 'exp', 'right-parentheses'], + # None, [None, 'Factor0C1', None], 'Factor0E'), + # # 72 + # Production('factor', ['id', 'id-factor-follow'], + # None, [None, 'Factor1C1'], 'Factor1E'), + # # 73 + # Production('factor', ['num'], + # None, [None], 'Factor2E'), + # # 74 + # Production('id-factor-follow', ['var-follow'], + # None, [None], 'IdFactorFollow0E'), + # # 75 + # Production('id-factor-follow', ['left-parentheses', 'args', 'right-parentheses'], + # None, [None, 'IdFactorFollow1C1', None], 'IdFactorFollow1E'), + # # 76 + # Production('args', ['arg-list'], + # None, ['Args0C0'], 'Args0E'), + # # 77 + # Production('args', [], + # None, [], 'Args1E'), + # # 78 + # Production('arg-list', ['exp', 'arg-list-follow'], + # None, ['ArgList0C0', 'ArgList0C1'], 'ArgList0E'), + # # 79 + # Production('arg-list-follow', ['comma', 'exp', 'arg-list-follow'], + # None, [None, 'ArgListFollow0C1', 'ArgListFollow0C2'], 'ArgListFollow0E'), + # # 80 + # Production('arg-list-follow', [], + # None, [], 'ArgListFollow1E'), + + # 81 + Production('arraylist-with-num', [], + None, [], 'ArrayListWithNum81E', + ), + # 82 + Production('arraylist-with-num', ['left-bracket', 'int-num', 'right-bracket'], + None, [None, None, None], 'ArrayListWithNum82E', + ) +] + +# 文法开始符号 +grammar_start = Sign('program') \ No newline at end of file diff --git a/syntax/syntax.py b/syntax/syntax.py new file mode 100644 index 0000000..0d39a92 --- /dev/null +++ b/syntax/syntax.py @@ -0,0 +1,767 @@ +""" +语法分析 +""" +from syntax.rule import Sign, Production, terminal_sign_type, non_terminal_sign_type, productions, grammar_start +from error import SyntaxRuleError, SyntaxError, SemanticRuleError +from semantic.rule import SemanticRule, SemanticError, SemanticRuleFactory + + +class PredictingAnalysisTable: + """ + 预测分析表 + """ + def __init__(self): + """ + 构造 + """ + # 错误 + self.__error = None + + # 预测分析表 + self.__table = list() + + # 所有的非终结符 + self.__non_terminal_signs = list() + # 所有的终结符 + self.__terminal_signs = list() + + # 载入所有的符号 + for i in non_terminal_sign_type: + self.__non_terminal_signs.append(Sign(i)) + for i in terminal_sign_type: + self.__terminal_signs.append(Sign(i)) + + # 根据非终结符和终结符的数量为预测分析表分配空间,并且为每一个格子预先填上 None + for i in non_terminal_sign_type: + self.__table.append(list()) + for i in range(0, len(non_terminal_sign_type)): + for j in terminal_sign_type: + self.__table[i].append(None) + + # 为每一个非终结符建立 first 集和 follow 集 + self.__firsts = list() + self.__follows = list() + + # 为每一个非终结符的 first 集和 follow 集分配空间 + for i in non_terminal_sign_type: + self.__firsts.append(list()) + self.__follows.append(list()) + + def compile(self): + """ + 编译预测分析表 + """ + # 对每一个文法元素求其 first 集 + self.__calculate_firsts() + # 对每一个文法元素求其 follow 集 + self.__calculate_follows() + # 根据 first 集和 follow 集生成预测分析表 + success = self.__generate_table() + return success + + + def get_production(self, non_terminal_sign, terminal_sign): + """ + 从预测分析表中获取产生式 + :param non_terminal_sign: 非终结符 + :param terminal_sign: 终结符 + :return: 产生式 + """ + x = self.__get_non_terminal_sign_index(non_terminal_sign) + y = self.__get_terminal_sign_index(terminal_sign) + return self.__table[x][y] + + @classmethod + def __set_add(cls, container, sign): + """ + 将 sign 添加到 container 中并返回 True,如果其中已经有该元素了则返回 False + :param container: 要添加到的集合 + :param sign: 符号 + :return: 添加是否成功 + """ + exist = False + for elem in container: + if elem.type == sign.type: + exist = True + if not exist: + container.append(sign) + return not exist + + def __get_terminal_sign_index(self, terminal_sign): + """ + 获取终结符的索引 + :param terminal_sign: 终结符 + :return: 索引(寻找失败返回 -1) + """ + for i in range(0, len(self.__terminal_signs)): + if terminal_sign.type == self.__terminal_signs[i].type: + return i + return -1 + + def __get_non_terminal_sign_index(self, non_terminal_sign): + """ + 获取非终结符的索引 + :param non_terminal_sign: 非终结符 + :return: 索引(寻找失败返回 -1) + """ + for i in range(0, len(self.__non_terminal_signs)): + if non_terminal_sign.type == self.__non_terminal_signs[i].type: + return i + return -1 + + def __get_non_terminal_sign_first(self, non_terminal_sign): + """ + 获取目标非终结符的 first 集的引用 + :param non_terminal_sign: 目标非终结符 + :return: 其 first 集的引用 + """ + return self.__firsts[self.__get_non_terminal_sign_index(non_terminal_sign)] + + def __get_non_terminal_sign_first_no_empty(self, non_terminal_sign): + """ + 获取目标非终结符的 first 集的非空拷贝 + :param non_terminal_sign: 目标非终结符 + :return: 其 first 集的非空拷贝 + """ + result = list() + for i in self.__get_non_terminal_sign_first(non_terminal_sign): + if not i.is_empty_sign(): + result.append(i) + return result + + def __is_empty_in_non_terminal_sign_first(self, non_terminal_sign): + """ + 目标非终结符的 first 集中是否有空字 + :param non_terminal_sign: 目标非终结符 + :return: True/False + """ + for i in self.__get_non_terminal_sign_first(non_terminal_sign): + if i.is_empty_sign(): + return True + return False + + def __get_non_terminal_sign_follow(self, non_terminal_sign): + """ + 获取非终结符的 follow 集 + :param non_terminal_sign: 非终结符 + :return: 其 follow 集 + """ + return self.__follows[self.__get_non_terminal_sign_index(non_terminal_sign)] + + def __calculate_firsts(self): + """ + 求所有的 first 集 + """ + # 立一个 flag,用来标志 firsts 集是否增大 + flag = True + # 开始循环 + while flag: + flag = False + # 在每一次循环之中遍历所有产生式 + for production in productions: + # 如果产生式右边为空 + if len(production.right) == 0: + # 将空字加入其 first 集 + if self.__set_add(self.__get_non_terminal_sign_first(production.left), Sign('empty')): + flag = True + # 如果产生式右边不为空 + else: + # 如果是以终结符开头,将终结符添加到其 first 集 + if production.right[0].is_terminal_sign(): + if self.__set_add(self.__get_non_terminal_sign_first(production.left), production.right[0]): + flag = True + # 如果是以非终结符开头 + elif production.right[0].is_non_terminal_sign(): + # (1) 将开头非终结符的 first 集中的所有非空元素添加到产生式左边非终结符的 first 集中 + bigger = False + for i in self.__get_non_terminal_sign_first_no_empty(production.right[0]): + if self.__set_add(self.__get_non_terminal_sign_first(production.left), i): + bigger = True + if bigger: + flag = True + + # (2) 从第一个非终结符开始循环,如果其 first 集中包含空字,那么将它下一个符号的 first + # 集添加到产生式左边非终结符的 first 集中去 + for i in range(0, len(production.right)): + if production.right[i].is_non_terminal_sign(): + # 如果包含空字 + if self.__is_empty_in_non_terminal_sign_first(production.right[i]): + # 如果它是最后一个,将空字填入 + if i == len(production.right) - 1: + if self.__set_add(self.__get_non_terminal_sign_first(production.left), + Sign('empty')): + flag = True + # 如果不是最后一个 + else: + # 如果它之后是终结符 + if production.right[i + 1].is_terminal_sign(): + if self.__set_add(self.__get_non_terminal_sign_first(production.left), + production.right[i + 1]): + flag = True + # 如果它之后是非终结符 + elif production.right[i + 1].is_non_terminal_sign(): + bigger = False + for j in self.__get_non_terminal_sign_first_no_empty( + production.right[i + 1]): + if self.__set_add( + self.__get_non_terminal_sign_first(production.left), j): + bigger = True + if bigger: + flag = True + else: + self.__error = SyntaxRuleError('终结符或非终结符类型错误') + return False + # 如果不包含空字 + else: + break + else: + break + # 否则报错 + else: + self.__error = SyntaxRuleError('终结符或非终结符类型错误') + return False + + def __calculate_follows(self): + """ + 求所有的 follow 集 + """ + first = list() + flag = True + while flag: + flag = False + # 遍历所有产生式 + for production in productions: + # 如果产生式左边是开始符号 + if production.left.type == grammar_start.type: + if self.__set_add(self.__get_non_terminal_sign_follow(production.left), Sign('pound')): + flag = True + + # 遍历产生式右边 + for i in range(0, len(production.right)): + # 如果是非终结符 + if production.right[i].is_non_terminal_sign(): + # 如果它是产生式最后一个符号 + if i == len(production.right) - 1: + # 将产生式左边非终结符的 follow 集添加到这个符号的 follow 集中 + bigger = False + for j in self.__get_non_terminal_sign_follow(production.left): + if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), j): + bigger = True + if bigger: + flag = True + # 否则观察其之后的元素 + else: + # 求他之后所有符号集合的 first 集 + first.clear() + first += self.__calculate_set_first(production.right[i + 1:]) + # (1) 将 first 中所有非空元素填入 follow + empty_find = False + for f in first: + if not f.is_empty_sign(): + self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), f) + else: + empty_find = True + + # (2) 如果 first 中含有空 + if empty_find: + # 将产生式左边非终结符的 follow 集添加到这个符号的 follow 集中 + bigger = False + for j in self.__get_non_terminal_sign_follow(production.left): + if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), j): + bigger = True + if bigger: + flag = True + + # # 如果他后面是一个终结符 + # if production.right[i + 1].is_terminal_sign(): + # if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), + # production.right[i + 1]): + # flag = True + # # 如果他后面是一个非终结符 + # elif production.right[i + 1].is_non_terminal_sign(): + # # (1) 将后面非终结符的 first 集中的所有非空元素填入 + # bigger = False + # for j in self.__get_non_terminal_sign_first_no_empty(production.right[i + 1]): + # if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), j): + # bigger = True + # if bigger: + # flag = True + # + # # (2) 如果后面所有的非终结符 first 集都包含空 + # # 那么,则将产生式左边的 follow 集添加到该非终结符的 follow 集中去 + # all_empty_in_first = True + # for j in range(i + 1, len(production.right)): + # if not self.__is_empty_in_non_terminal_sign_first(production.right[j]): + # all_empty_in_first = False + # break + # if all_empty_in_first: + # bigger = False + # for j in self.__get_non_terminal_sign_follow(production.left): + # if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), j): + # bigger = True + # if bigger: + # flag = True + # # 否则报错 + # else: + # self.__error = SyntaxRuleError('终结符或非终结符类型错误') + # return False + # 如果是终结符 + elif production.right[i].is_terminal_sign(): + continue + # 否则报错 + else: + self.__error = SyntaxRuleError('终结符或非终结符类型错误') + return False + + def __calculate_set_first(self, container): + """ + 计算一系列符号的 first 集 + :param container: 符号集合 + :return: first 集 + """ + first = list() + + # 开始求 first 集 + # 如果集合为空 + first = list() + + # 开始求 first 集 + # 如果产生式右边为空 + if len(container) == 0: + # 将空字加入其 first 集 + self.__set_add(first, Sign('empty')) + # 如果产生式右边补位空 + else: + # 如果是以终结符开头,将终结符添加到 first 集 + if container[0].is_terminal_sign(): + self.__set_add(first, container[0]) + # 如果是以非终结符开头 + elif container[0].is_non_terminal_sign(): + # (1) 将开头非终结符的 first 集中的所有非空元素添加到 first 中 + for i in self.__get_non_terminal_sign_first_no_empty(container[0]): + self.__set_add(first, i) + + # (2) 从第一个非终结符开始循环,如果其 first 集中包含空字,那么将它的下一个符号的 first + # 集添加到 first 中 + for i in range(0, len(container)): + if container[i].is_non_terminal_sign(): + # 如果包含空字 + if self.__is_empty_in_non_terminal_sign_first(container[i]): + # 如果它是最后一个,将空字填入 + if i == len(container) - 1: + self.__set_add(first, Sign('empty')) + # 如果不是最后一个 + else: + # 如果它之后是终结符 + if container[i + 1].is_terminal_sign(): + self.__set_add(first, container[i + 1]) + # 如果它之后是非终结符 + elif container[i + 1].is_non_terminal_sign(): + for j in self.__get_non_terminal_sign_first_no_empty(container[i + 1]): + self.__set_add(first, j) + # 否则报错 + else: + self.__error = SyntaxRuleError('终结符或非终结符类型错误') + return False + # 如果不含空字 + else: + break + else: + break + # 否则报错 + else: + self.__error = SyntaxRuleError('终结符或非终结符类型错误') + return False + + return first + + def __insert_to_table(self, production, terminal): + """ + 将产生式插入预测分析表对应位置 + :param production: 产生式 + :param terminal: 终结符 + :return: 是否插入成功 + """ + # 先判断应该插入到的位置 + x = self.__get_non_terminal_sign_index(production.left) + y = self.__get_terminal_sign_index(terminal) + + # 如果那个位置已经有产生式了 + if self.__table[x][y]: + # 判断这个产生式是不是与要插入的产生式一样 + same_left = production.left.type == self.__table[x][y].left.type + if same_left: + same_right = True + if len(production.right) != len(self.__table[x][y].right): + self.__error = SyntaxRuleError("文法非LL(1)" + production.str) + return False + else: + for i in range(0, len(production.right)): + if production.right[i].type != self.__table[x][y].right[i].type: + same_right = False + if same_right: + # 执行插入 + del self.__table[x][y] + self.__table[x].insert(y, production) + return True + else: + self.__error = SyntaxRuleError("文法非LL(1)" + production.str) + return False + else: + self.__error = SyntaxRuleError("文法非LL(1)" + production.str) + return False + # 如果那个位置为空,说明可以填入 + else: + # 执行插入 + del self.__table[x][y] + self.__table[x].insert(y, production) + return True + + @classmethod + def __set_have_repeat(cls, set1, set2): + """ + 判断两个集合是否有交集 + :param set1: 集合1 + :param set2: 集合2 + :return: 是否有交集 + """ + for i in set1: + for j in set2: + if i.type == j.type: + return True + return False + + def __grammar_rule_debug(self): + """ + 调试使用,求一个非终结符对应的所有产生式右边的 first 集中是否有相交元素 + """ + # 一个非终结符对应的所有产生式 + his_productions = list() + # 那些产生式对应的 first 集 + firsts = list() + # 错误 + errors = list() + + # 对于所有的非终结符 + for non_terminal_sign in self.__non_terminal_signs: + # 寻找他对应的所有产生式 + his_productions.clear() + firsts.clear() + for production in productions: + if non_terminal_sign.type == production.left.type: + his_productions.append(production) + + # 对于那些产生式,分别求 first 集 + for production in his_productions: + firsts.append(self.__calculate_set_first(production.right)) + + + + # 是否有交集 + have_repeat = False + # 查看这些产生式的 first 集两两之间是否有交集 + for i in range(0, len(his_productions) - 1): + for j in range(i + 1, len(his_productions)): + + if self.__set_have_repeat(firsts[i], firsts[j]): + have_repeat = True + break + + + # 如果有交集 + if have_repeat: + errors.append('产生式 First 集重叠 ' + '非终结符: ' + non_terminal_sign.type) + + # 如果非终结符的 First 集中包含空字 + if self.__is_empty_in_non_terminal_sign_first(non_terminal_sign): + # 如果他的 First 集和 Follow 集有交集 + if self.__set_have_repeat(self.__get_non_terminal_sign_first(non_terminal_sign), + self.__get_non_terminal_sign_follow(non_terminal_sign)): + errors.append('产生式 First 集和 Follow 集重叠 ' + '非终结符: ' + non_terminal_sign.type) + return + + def __generate_table(self): + """ + 根据 first 集和 follow 集生成预测分析表 + :return: 是否生成成功 + """ + # 调试 + self.__grammar_rule_debug() + + # 对每一条产生式应用规则 + for production in productions: + # 先求出该产生式右边部分的 first 集 + first = self.__calculate_set_first(production.right) + + # 对每一个 first 集中的每一个终结符执行操作 + empty_find = False + for i in list(first): + if i.type == 'empty': + empty_find = True + else: + if not self.__insert_to_table(production, i): + return False + + # 如果其 first 集中有空字,则对 follow 集中的每一个终结符执行操作 + if empty_find: + for i in self.__get_non_terminal_sign_follow(production.left): + if not self.__insert_to_table(production, i): + return False + + return True + + +class Node: + """ + 树节点 + """ + def __init__(self, data): + """ + 树节点 + :param data: 节点数据 + """ + self.data = data + self.str = data.type + self.children = list() + self.parent = None + + # 属性 + self.lexical = None + self.array = None + self.code = list() + self.type = None + self.id = None + self.length = None + self.fun = None + self.num = None + self.names = list() + self.bool = None + self.op = None + self.add = None + self.mul = None + + def get_pre_brother(self, index): + """ + 获取它前 index 位的兄弟 + :param index: .. + :return: 兄弟 + """ + self_index = 0 + for i in range(0, len(self.parent.children)): + if self.parent.children[i] is self: + self_index = i + return self.parent.children[self_index - index] + + +class Tree: + """ + 树 + """ + def __init__(self, root): + """ + 构造 + :param root: 树的根节点 + """ + self.root = root + + +class Stack: + """ + 栈 + """ + def __init__(self): + """ + 构造 + """ + self.__container = list() + + def push(self, elem): + """ + 入栈 + :param elem: 入栈元素 + """ + self.__container.append(elem) + + def pop(self): + """ + 将栈顶元素出栈 + :return: 栈顶元素 + """ + top = self.top() + self.__container.pop() + return top + + def top(self): + """ + 获取栈顶元素 + :return: 栈顶元素 + """ + return self.__container[-1] + + def empty(self): + """ + 栈是否为空 + :return: 栈是否为空 + """ + return len(self.__container) == 0 + + +class Syntax: + """ + 语法分析器 + """ + def __init__(self): + """ + 构造 + """ + # 语法树的构建 + self.__grammar_tree = None + # 准备存放错误 + self.__error = list() + # 预测分析表的构建 + self.__pa_table = PredictingAnalysisTable() + # 编译预测分析表 + if self.__pa_table.compile(): + self.__error.append(SyntaxRuleError('预测分析表编译失败')) + # 准备存放词法分析的结果 + self.__source = list() + # 将词法分析产生的 token 转换成的终结符 + self.__terminals = list() + + def put_source(self, source): + """ + 装填词法分析结果 + :param source: 词法分析结果 + """ + self.__source.clear() + self.__terminals.clear() + # 装填词法分析结果 + for s in source: + self.__source.append(s) + # 将 tokens 转换成终结符 + for s in self.__source: + self.__terminals.append(Sign(s.type, s.str, s.line)) + # 在所有 tokens 的最后填入一个 # + self.__terminals.append(Sign('pound')) + + def get_result(self): + """ + 获取语法树 + :return: 语法树 + """ + return self.__grammar_tree + + def get_error(self): + """ + 获取错误 + :return: 错误 + """ + return self.__error + + def execute(self): + """ + 执行操作 + :return: 语法分析是否成功 + """ + # 新建栈 + stack = Stack() + # 清空错误 + self.__error = None + # 新建临时语法树 + grammar_tree = Tree(Node(Sign(grammar_start.type))) + + # 将 # 入栈 + stack.push(Node(Sign('pound'))) + # 将语法树根节点入栈 + stack.push(grammar_tree.root) + + # 拷贝转换之后的终结符到输入串 + inputs = list() + for sign in self.__terminals: + inputs.append(sign) + # 设置当前输入符号索引 + input_index = 0 + + # 立下 flag + flag = True + while flag: + + # 如果栈顶是语义动作 + if isinstance(stack.top(), SemanticRule): + stack.top().execute() + if len(stack.top().errors) > 0: + self.__error = stack.top().errors[-1] + break + else: + stack.pop() + # 如果栈顶是符号 + else: + # 如果 top 是非终结符 + if stack.top().data.is_non_terminal_sign(): + # 查看分析表 + production = self.__pa_table.get_production(stack.top().data, inputs[input_index]) + # 如果分析表对应位置存有产生式 + if production: + # 判断语义规则是否合法 + if len(production.right) != len(production.semantic_children): + self.__error = SemanticRuleError('语义规则数量与产生式右边数量不一致 ' + production.str) + break + + # 执行 start 语义 + semantic_start = SemanticRuleFactory.get_instance(production.semantic_start, stack.top()) + if semantic_start: + semantic_start.execute() + if len(semantic_start.errors) > 0: + self.__error = semantic_start.errors[-1] + break + + # 将语法树按照产生式进行生长 + for i in range(0, len(production.right)): + stack.top().children.append(Node(Sign(production.right[i].type))) + stack.top().children[i].parent = stack.top() + + # 将 top 出栈 + top = stack.pop() + + # 将 end 语义规则入栈 + semantic_end = SemanticRuleFactory.get_instance(production.semantic_end, top) + if semantic_end: + stack.push(semantic_end) + + # 将 top 的孩子节点反序入栈 + for i in range(len(production.right) - 1, -1, -1): + # for child in top.children[::-1]: + stack.push(top.children[i]) + semantic_child = SemanticRuleFactory.get_instance(production.semantic_children[i], + top.children[i]) + if semantic_child: + stack.push(semantic_child) + # 如果分析表中存放着错误信息 + else: + self.__error = SyntaxError('语法错误 ' + inputs[input_index].str, inputs[input_index].line) + break + # 如果 top 是终结符 + else: + # 如果 top = input + if stack.top().data.type == inputs[input_index].type: + # 如果 top = #,宣布分析成功 + if stack.top().data.type == 'pound': + flag = False + # 如果 top != # + else: + # 计算 top 的 lexical 属性 + stack.top().lexical = inputs[input_index].str + # 将 top 出栈,让 input_index 自增 + stack.pop() + input_index += 1 + # 如果 top != input + else: + self.__error = SyntaxError('语法错误 ' + inputs[input_index].str, inputs[input_index].line) + break + + if self.__error: + return False + else: + self.__grammar_tree = grammar_tree + + return True diff --git a/test.c b/test.c new file mode 100644 index 0000000..33372d9 --- /dev/null +++ b/test.c @@ -0,0 +1,18 @@ +/* A program to perform Euclid s Algorithm to compute gcd. */ +int gcd(int u, int v) { + if (v == 0) { + return u; + } else { + return gcd(v, u-u/v*v); + } + /* u-u/v*v* == u mod v */ +} + +void main() { + int x; + int y; + x = input(); + y = input(); + output(gcd(x, y)); + return; +} diff --git a/test.py b/test.py new file mode 100644 index 0000000..9e0d1a7 --- /dev/null +++ b/test.py @@ -0,0 +1,5 @@ +from syntax.syntax import PredictingAnalysisTable + + +pa_table = PredictingAnalysisTable() +pa_table.compile() diff --git a/test1.c b/test1.c new file mode 100644 index 0000000..ab5dad4 --- /dev/null +++ b/test1.c @@ -0,0 +1,17 @@ +/*test1:斐波那契数列(控制流 + 函数调用)*/ +int fib(int n) { + if (n < 1){ + return n; + } else { + return fib(n - 1) + fib(n - 2); + } +} + +int main() { + int y; + int x; + x = 5 * 2 + 2; + a = 2 == 2; + x = fib(6); + return x; +} diff --git a/test2.c b/test2.c new file mode 100644 index 0000000..3cb5e90 --- /dev/null +++ b/test2.c @@ -0,0 +1,14 @@ +/* test2:阶乘计算(while 循环 + 局部变量)*/ +int fact(int n) { + int result; + result = 1; + while (n > 0) { + result = result * n; + n = n - 1; + } + return result; +} + +int main() { + return fact(5); +} diff --git a/test3.c b/test3.c new file mode 100644 index 0000000..7fa6b6c --- /dev/null +++ b/test3.c @@ -0,0 +1,21 @@ +/* test3:多函数协作(函数调用 + 全局变量)*/ +int a; +int b; + +int sum() { + return a + b; +} + +int product() { + return a * b; +} + +int main() { + int s; + int p; + a = 3; + b = 4; + s = sum(); + p = product(); + return s + p; +} diff --git a/test4.c b/test4.c new file mode 100644 index 0000000..84df68b --- /dev/null +++ b/test4.c @@ -0,0 +1,19 @@ +/* test4:嵌套 if 判断(复杂控制流)*/ +int max(int x, int y) { + if (x > y) { + return x; + } + else { + return y; + } +} + +int main() { + int a; + int b; + int c; + a = 10; + b = 20; + c = max(a, b); + return c; +} diff --git a/test5.c b/test5.c new file mode 100644 index 0000000..29ccedf --- /dev/null +++ b/test5.c @@ -0,0 +1,29 @@ +/* test5:冒泡排序(数组访问模拟)*/ +int swap(int i, int j) { + int temp; + temp = i; + i = j; + j = temp; + return 0; +} + +int main() { + int a; + int b; + int c; + int d; + int e; + a = 5; + b = 3; + c = 8; + d = 1; + e = 9; + + /* 冒泡排序模拟 */ + if (a > b) { swap(a, b); } + if (b > c) { swap(b, c); } + if (c > d) { swap(c, d); } + if (d > e) { swap(d, e); } + + return e; +} diff --git a/test6.c b/test6.c new file mode 100644 index 0000000..fcc98b9 --- /dev/null +++ b/test6.c @@ -0,0 +1,13 @@ +/* test6:逻辑表达式优先级测试 */ +int main() { + int a; + int b; + int c; + a = 1; + b = 2; + c = 3; + + int result; + result = a == 1 && b < c || c != 4; + return result; +} \ No newline at end of file diff --git a/test7.c b/test7.c new file mode 100644 index 0000000..e6a3328 --- /dev/null +++ b/test7.c @@ -0,0 +1,19 @@ +/* test7:嵌套循环(while + if)*/ +int is_prime(int n) { + int i; + if (n <= 1) { + return 0; + } + i = 2; + while (i * i <= n) { + if (n % i == 0) { + return 0; + } + i = i + 1; + } + return 1; +} + +int main() { + return is_prime(17); +} diff --git a/test8.c b/test8.c new file mode 100644 index 0000000..cfc36a3 --- /dev/null +++ b/test8.c @@ -0,0 +1,19 @@ +/* test8:带错误的语法测试(用于验证报错机制)*/ +int main() { + int x; + x = ; /* 错误:缺少右值 */ + return x; +} + +int main1() { + int x; + x == 10; /* 错误:应为赋值 = */ + return x; +} + +int main2() { + int x; + if (x) /* 错误:if 条件必须是整型表达式 */ + return 1; + return 0; +} diff --git a/test9.c b/test9.c new file mode 100644 index 0000000..7c7e147 --- /dev/null +++ b/test9.c @@ -0,0 +1,3 @@ +fn main(a:i32[], b:i32, c:f32[], d:i32) -> f32 { + +}