编译原理实现一个小型语法编译器,给出代码(要求可视化,可进行此法和语法分析)
时间: 2024-03-01 18:52:13 浏览: 29
很高兴能回答您的问题!编写一个小型语法编译器需要包含以下几个步骤:词法分析、语法分析、语义分析、中间代码生成和目标代码生成。其中,词法分析和语法分析的过程可以通过可视化工具展示出来。
以下是一个简单的语法编译器的实现,主要实现了词法分析和语法分析的功能。该编译器可以识别简单的算术表达式,并将其转换为语法树。
```python
from enum import Enum
# Token类型
class TokenType(Enum):
PLUS = "+"
MINUS = "-"
MUL = "*"
DIV = "/"
INTEGER = "INTEGER"
LPAREN = "("
RPAREN = ")"
EOF = "EOF"
# Token类
class Token(object):
def __init__(self, type, value):
self.type = type
self.value = value
def __str__(self):
return f"Token({self.type}, {self.value})"
# Lexer类
class Lexer(object):
def __init__(self, text):
self.text = text
self.pos = 0
self.current_char = self.text[self.pos]
def error(self):
raise Exception("Invalid character")
def advance(self):
self.pos += 1
if self.pos > len(self.text) - 1:
self.current_char = None
else:
self.current_char = self.text[self.pos]
def skip_whitespace(self):
while self.current_char is not None and self.current_char.isspace():
self.advance()
def integer(self):
result = ""
while self.current_char is not None and self.current_char.isdigit():
result += self.current_char
self.advance()
return int(result)
def get_next_token(self):
while self.current_char is not None:
if self.current_char.isspace():
self.skip_whitespace()
continue
if self.current_char.isdigit():
return Token(TokenType.INTEGER, self.integer())
if self.current_char == "+":
self.advance()
return Token(TokenType.PLUS, "+")
if self.current_char == "-":
self.advance()
return Token(TokenType.MINUS, "-")
if self.current_char == "*":
self.advance()
return Token(TokenType.MUL, "*")
if self.current_char == "/":
self.advance()
return Token(TokenType.DIV, "/")
if self.current_char == "(":
self.advance()
return Token(TokenType.LPAREN, "(")
if self.current_char == ")":
self.advance()
return Token(TokenType.RPAREN, ")")
self.error()
return Token(TokenType.EOF, None)
# AST节点类
class AST(object):
pass
class BinOp(AST):
def __init__(self, left, op, right):
self.left = left
self.token = self.op = op
self.right = right
# 数字节点
class Num(AST):
def __init__(self, token):
self.token = token
self.value = token.value
# 解析器
class Parser(object):
def __init__(self, lexer):
self.lexer = lexer
self.current_token = self.lexer.get_next_token()
def error(self):
raise Exception("Invalid syntax")
def eat(self, token_type):
if self.current_token.type == token_type:
self.current_token = self.lexer.get_next_token()
else:
self.error()
def factor(self):
token = self.current_token
if token.type == TokenType.INTEGER:
self.eat(TokenType.INTEGER)
return Num(token)
elif token.type == TokenType.LPAREN:
self.eat(TokenType.LPAREN)
node = self.expr()
self.eat(TokenType.RPAREN)
return node
def term(self):
node = self.factor()
while self.current_token.type in (TokenType.MUL, TokenType.DIV):
token = self.current_token
if token.type == TokenType.MUL:
self.eat(TokenType.MUL)
elif token.type == TokenType.DIV:
self.eat(TokenType.DIV)
node = BinOp(left=node, op=token, right=self.factor())
return node
def expr(self):
node = self.term()
while self.current_token.type in (TokenType.PLUS, TokenType.MINUS):
token = self.current_token
if token.type == TokenType.PLUS:
self.eat(TokenType.PLUS)
elif token.type == TokenType.MINUS:
self.eat(TokenType.MINUS)
node = BinOp(left=node, op=token, right=self.term())
return node
# 可视化输出AST树
def print_ast(ast, indent=0):
print(" " * indent, end="")
print(ast.token.type)
for child in ast.__dict__.values():
if isinstance(child, AST):
print_ast(child, indent + 4)
# 测试
def main():
while True:
try:
text = input("calc> ")
except EOFError:
break
if not text:
continue
lexer = Lexer(text)
parser = Parser(lexer)
ast = parser.expr()
print_ast(ast)
if __name__ == '__main__':
main()
```
通过运行上述代码,可以在控制台输入算术表达式进行词法分析和语法分析,并可视化输出语法树。