本篇博客是接着上两篇博客讲解的,
https://blog.csdn.net/shixiongtao/article/details/104059437
https://blog.csdn.net/shixiongtao/article/details/104071621。
首先给出代码的链接:https://download.csdn.net/download/shixiongtao/12119227。
程序分为,Lexer.py,Parser.py,Ast.py,和主程序run.py组成。
文件结构如下:
├── LearnPLY
│ ├── Ast.py
│ ├── Lexer.py
│ ├── parser.out
│ ├── Parser.py
│ └── parsetab.py
├── run_lexer.py
├── run.py
└── test.ply
Ast.py中定义了抽象语法树,Lexer.py定义了词法结构,Parser.py定义了语法结构,parser.out和parsetab.py是自动生成的文件,run_lexer.py是单独测试Lexer.py的程序,run.py是主程序,test.ply是待解释的程序。
首先来看Lexer.py文件:
### 导入包 ###
import ply.lex as lex
### 是否打印详细信息 ###
LexerDebug = False
### 定义词法解析类 ###
class Lexer(object):
def __init__(self):
self.lexer = lex.lex(object=self)
def input(self, text):
self.lexer.input(text)
def token(self):
return self.lexer.token()
### 定义保留字,字典,静态变量 ###
reserved = {
'print': 'PRINT',
'if': 'IF',
'else': 'ELSE',
'for': 'FOR',
'while': 'WHILE',
'break': 'BREAK',
'continue': 'CONTINUE',
'and': 'AND',
'or': 'OR',
'return': 'RETURN'
}
### 定义token,静态变量 ###
tokens = [
#变量名
'NAME',
#整数,浮点数,字符串
'INT', 'FLOAT', 'STRING',
#加,减,乘,除,模,赋值
'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD', 'ASSIGN',
#(,),[,],{,}
'LPAREN', 'RPAREN', 'LSQBRACK', 'RSQBRACK', 'LBRACK', 'RBRACK',
#大于,大于等于,小于,小于等于,等于,不等于,真,假,空
'GT', 'GTE', 'LT', 'LTE', 'EQ', 'NEQ', 'TRUE', 'FALSE', 'NONE',
#冒号,分号,逗号,注释
'COLON', 'SEMICOLON', 'COMMA', 'COMMENT',
]
### 将保留字和token合并到一块查询,静态变量 ###
tokens = tokens + list(reserved.values())
### 声明正则表达式,顺序代表了优先级,静态变量 ###
#省略空格
t_ignore = ' \t'
#特殊符号,需要转义
#t_PLUS = '\+'
def t_PLUS(self, t):
'\+'
if LexerDebug == True: print('t_PLUS')
return t
#t_MINUS = '-'
def t_MINUS(self, t):
'-'
if LexerDebug == True: print('t_MINUS')
return t
#特殊符号,需要转义
#t_TIMES = '\*'
def t_TIMES(self, t):
'\*'
if LexerDebug == True: print('t_TIMES')
return t
#t_DIVIDE = '/'
def t_DIVIDE(self, t):
'/'
if LexerDebug == True: print('t_DIVIDE')
return t
#t_MOD = '%'
def t_MOD(self, t):
'%'
if LexerDebug == True: print('t_DIVIDE')
return t
#特殊符号,需要转义
#t_LPAREN = '\('
def t_LPAREN(self, t):
'\('
if LexerDebug == True: print('t_LPAREN')
return t
#特殊符号,需要转义
#t_RPAREN = '\)'
def t_RPAREN(self, t):
'\)'
if LexerDebug == True: print('t_RPAREN')
return t