当前位置:网站首页>编译原理-语法分析器设计
编译原理-语法分析器设计
2022-07-13 17:45:00 【Stories Untold.】
语法分析器设计
实验环境
- 操作系统:Windows 11
- 编程语言:C++
- 编译器:GCC version 8.1.0
实验目的
1、为初等函数运算语言构造LL(1)语法分析器。
2、掌握LL(1)语法分析器的方法,加深对自上而下语法分析原理的理解。
3、掌握设计、编制并调试LL(1)语法分析程序的思想和方法。
实验内容及要求
一、根据初等函数运算语言运算法则,将语法模式用上下文无关文法表达。
注意运算的优先性,避免产生二义性文法。
二、将上述文法改写为LL(1)文法。
三、根据LL(1)文法给出预测分析表。
四、根据预测分析表,给出解析LL(1)文法的递归下降子程序。
五、本语法分析程序的输入是实验一生成的记号流;本程序需定义语法树的数据结构;语法分析的输出是一棵语法树。
六、当输入存在语法错误时,需给出语法错误的提示,指出语法错误发生的位置和错误类型。
实验步骤
用上下文无关文法表达







改写为LL(1)文法











First集与Follow集
| First集 | Follow集 | |
|---|---|---|
| S | id, ε, ? | # |
| L | id, ε | ? |
| A | id | ; |
| B | sin,cos,tg,ctg,log,In,(,-,id,num | ;, ), , |
| B’ | +, -, ε | ), ;, #, , |
| T | sin,cos,tg,ctg,log,In,(,-,id,num | +, -, ε |
| T’ | *, /, ε | +. -. ), ;, #, , |
| F | sin, cos, tg, ctg, log, In, (, -, id, num | *, /, ε |
| N | ^, ε | *, /, +. -. ), ;, # |
| M | sin, cos, tg, ctg, log, In, (, -, id, num | *, /, ε |
| E | (, -, id, num | *, /, ε |
预测分析表
| 变量 | 常量 | ? | ; | ( | ) | + | - | * | / | Fun | Log | # | , | ^ | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| S | L?B | L?B | K | ||||||||||||
| L | A;L | K | |||||||||||||
| A | ID=B | ||||||||||||||
| B | TB’ | TB’ | |||||||||||||
| B1 | K | K | +TB’ | -TB’ | K | ||||||||||
| T | FT’ | FT’ | FT’ | FT’ | FT’ | FT’ | |||||||||
| T1 | K | K | K | K | *FT’ | /FT’ | K | ||||||||
| F | EN | EN | EN | EN | funE | logN | |||||||||
| N | K | K | K | K | K | K | K | ^E | |||||||
| M | B | B | (B,B) | B | B | B | |||||||||
| E | ID | num | (B) | -E |
结果分析



利用预测分析表进行匹配,若表中元素与公式匹配则成立节点,否则把结果压入栈,以此类推,完成预测分析。
由于python有treelib数据包,因此本实验主要利用python作为主要环境。
源代码
from treelib import Tree # 建语法树所用包
import numpy as np
calcultate = ['sin', 'cos', 'tg', 'ctg', 'log', 'lg', 'In']
print("实验一输入的公式:", "x = 0.5*PI;y = E;z = 3;?1/3*(ln(y)+5*sin(x))+(7+z)^2;#")
class Stack(object):
def __init__(self): # 创建空列表实现栈
self.__list = []
def is_empty(self): # 判断是否为空
return self.__list == []
def push(self, item): # 压栈,添加元素
self.__list.append(item)
def pop(self): # 弹栈,弹出最后压入栈的元素
if self.is_empty():
return
else:
return self.__list.pop()
def top(self): # 取最后压入栈的元素
if self.is_empty():
return
else:
return self.__list[-1]
stack = Stack()
stack.push('#')
stack.push('S')
def AnalyseColumn(s): # 判断矩阵列的下标
if s == 21:
return 0
elif s == 20:
return 1
elif s == 10:
return 2
elif s == 11:
return 3
elif s == 12:
return 4
elif s == 13:
return 5
elif s == 14:
return 6
elif s == 15:
return 7
elif s == 16:
return 8
elif s == 17:
return 9
elif (s >= 0 and s <= 4) or s == 6:
return 10
elif s == 5:
return 11
elif s == 23:
return 12
elif s == 24:
return 13
elif s == 19:
return 14
else:
return -1
def AnalyseRow(s): # 判断矩阵的行的下标
if s == 'S':
return 0
elif s == 'L':
return 1
elif s == 'A':
return 2
elif s == 'B':
return 3
elif s == 'b': # b 为B1
return 4
elif s == 'T':
return 5
elif s == 't': # t为T1
return 6
elif s == 'F':
return 7
elif s == 'N':
return 8
elif s == 'M':
return 9
elif s == 'E':
return 10
else:
return -1
def BuildPrediction(): # 构建预测分析表
prediction = np.zeros([11, 15], dtype=(str, 16))
prediction[0][0] = "L?B"
prediction[0][2] = "S?B"
prediction[0][12] = "k" # k为空集
prediction[1][0] = "A;L"
prediction[1][2] = "k"
prediction[2][0] = "id=B"
prediction[3][0] = "Tb"
prediction[3][1] = "Tb"
prediction[3][7] = "Tb"
prediction[3][10] = "Tb"
prediction[3][11] = "Tb"
prediction[3][12] = "Tb"
prediction[4][3] = 'k'
prediction[4][5] = "k"
prediction[4][6] = "+Tb"
prediction[4][7] = "-Tb"
prediction[4][13] = "k"
prediction[5][0] = "Ft"
prediction[5][1] = "Ft"
prediction[5][4] = "Ft"
prediction[5][7] = "Ft"
prediction[5][10] = "Ft"
prediction[5][11] = "Ft"
prediction[6][3] = "k"
prediction[6][5] = "k"
prediction[6][6] = "k"
prediction[6][7] = "k"
prediction[6][8] = "*Ft"
prediction[6][9] = "/Ft"
prediction[6][13] = "k"
prediction[7][0] = "FN"
prediction[7][1] = "FN"
prediction[7][4] = "FN"
prediction[7][7] = "FN"
prediction[7][10] = "fF"
prediction[7][11] = "logF"
prediction[8][3] = "k"
prediction[8][5] = "k"
prediction[8][6] = "k"
prediction[8][7] = "k"
prediction[8][8] = "k"
prediction[8][9] = "k"
prediction[8][12] = "k"
prediction[8][14] = "^E"
prediction[9][0] = "B"
prediction[9][1] = "B"
prediction[9][4] = "(B,B)"
prediction[9][7] = "B"
prediction[9][10] = "B"
prediction[9][11] = "B"
prediction[10][0] = "id"
prediction[10][1] = "num"
prediction[10][4] = "(B)"
prediction[10][7] = "-E"
return prediction
prediction = BuildPrediction()
key = ['x', '=', '0.5', '*', 'PI', ';', 'y', '=', 'E', ';', '?', '1', '/', '3', '*', '(', 'In', '(', 'y', ')', '+',
'5', '*', 'sin', '(', 'x', ')', ')', '+', '(', '7', '+', 'z', ')', ';', '#']
value = [21, 18, 20, 15, 8, 11, 21, 18, 9, 19, 10, 20, 17, 20, 16, 12, 7, 13, 21, 16, 14, 20, 16, 1, 12, 21, 13, 13,
14, 12, 20, 14, 21, 13, 11, 23]
def process(k, v, prediction, stack):
i1 = 0
node = {
} # 可能存在值一样,位置不同的节点,该节点负责更新其值对应的最新的节点下标在哪
j = 0
tree = Tree()
tree.create_node(stack.top(), i1)
node[stack.top()] = i1
i1 = i1+1
while not stack.is_empty():
if j < len(k):
word = stack.pop()
print("word:", word)
column = AnalyseColumn(v[j]) # 匹配出分析表的列号
print("column:", column)
row = AnalyseRow(word) # 匹配出分析表的行号
print("row=", row)
if column == -1 or row == -1: # 任意一个为-1则说明该输入存在问题
print("wrong input in ", word)
print("row:", row)
result = prediction[row][column]
print("result:", result)
if result == 'k': # k为空
continue
elif result == 0: # 此时说明该文法存在问题,无法从分析表中得到结果
print("Wrong input for ", k[j])
print("plz reput now")
break
elif word == k[j] or (word == 'id' and v[j] == 21) or (word == 'num' and v[j] == 20) or (word == 'f' and key[j] in calcultate): # 匹配成功
# 分为特殊符号终结符匹配成功,变量与实数匹配成功,函数匹配成功
j = j+1
for r in result:
if node.__contains__(r): # 如果该节点已经存在,则进行寻找到最新的节点下标名进行建树
parent = node[r]
tree.create_node(r, i1, parent=parent)
node[r] = i1
i1 = i1 + 1
else:
tree.create_node(r, i1, parent=word)
node[r] = i1
i1 = i1+1
else:
if result != 'id' or result != 'num' or result != 'logF' or result != 'id=B':
for w in reversed(result):
stack.push(w)
elif result == 'id' or 'num':
stack.push(result)
elif result == 'id=B':
stack.push('B')
stack.push('=')
stack.push('id')
else:
stack.push('log')
stack.push('F')
else:
print("文法错误!") # 此时可能出现文法错误但匹配依旧出现的情况,需重新进行排查
break
return tree
tree = process(key, value, prediction, stack)
tree.show() # 打印出语法树
边栏推荐
猜你喜欢
![[Huang ah code] getting started with MySQL - 2. Using data definition language (DDL) to operate the database](/img/c2/4d0b230e7ab96380ae4ce3e1fbc712.png)
[Huang ah code] getting started with MySQL - 2. Using data definition language (DDL) to operate the database

MySQL master-slave server configuration experiment centos7

Log blacklist can really save you money!

网络安全应急响应-电子数据取证技术

暑期沉淀web学习——php基础

Solutions to Oracle database error codes

win10下测试mysql主从同步

Intranet penetration notes - Sticky Keys and system command information collection

网络通信安全部分笔记二

39.js-- scope
随机推荐
JS numeric serial number to alphabetic serial number
[Huang ah code] redis realizes fuzzy query and deletes | redis obtains the key according to the prefix
38.js-- prototype exercise cases (face-to-face examination questions for proofreading)
[prettier] the code automatically formatted by prettier does not take effect
Buuctf backdoor killing
El button display and disable
[NCTF2019]Fake XML cookbook
SNMP started
: class modify style
Memory leak caused by ThreadLocal
What if there is no scroll bar on the right side of the page and you can't see the content beyond it?
网络通信安全部分笔记二
网络安全应急响应-电子数据取证技术
网络安全应急响应-恶意代码分析技术
Cross domain exceptions where the admin system is nested in a third-party system
Garbage collection mechanism
2022第十五届全国大学生信息安全竞赛(ciscn)西南赛区部分WP
For some problems encountered in using crontab, errors are reported /var/spool/cron: permission denied and bash: /usr/bin/chattr: permission denied
Oracle learning
Componentized coding process -- todo list case