初始化仓库

This commit is contained in:
Gary Gan 2025-06-11 19:51:42 +08:00
commit b2281d6e27
25 changed files with 5599 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
__pycache__/
.vscode/

21
LICENSE Normal file
View File

@ -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.

23
README.md Normal file
View File

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

68
error.py Normal file
View File

@ -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)

281
lexical/lexical.py Normal file
View File

@ -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)

89
lexical/rule.py Normal file
View File

@ -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',
}

44
main.py Normal file
View File

@ -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)

488
rule_back.py Normal file
View File

@ -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')

24
semantic/code.py Normal file
View File

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

745
semantic/rule.py Normal file
View File

@ -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)

307
semantic/symbol.py Normal file
View File

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

1908
semantic_rule_back.py Normal file

File diff suppressed because it is too large Load Diff

655
syntax/rule.py Normal file
View File

@ -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')

767
syntax/syntax.py Normal file
View File

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

18
test.c Normal file
View File

@ -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;
}

5
test.py Normal file
View File

@ -0,0 +1,5 @@
from syntax.syntax import PredictingAnalysisTable
pa_table = PredictingAnalysisTable()
pa_table.compile()

17
test1.c Normal file
View File

@ -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;
}

14
test2.c Normal file
View File

@ -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);
}

21
test3.c Normal file
View File

@ -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;
}

19
test4.c Normal file
View File

@ -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;
}

29
test5.c Normal file
View File

@ -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;
}

13
test6.c Normal file
View File

@ -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;
}

19
test7.c Normal file
View File

@ -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);
}

19
test8.c Normal file
View File

@ -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;
}

3
test9.c Normal file
View File

@ -0,0 +1,3 @@
fn main(a:i32[], b:i32, c:f32[], d:i32) -> f32 {
}