Simple arithmetic expression grammar G[E] in given class C language:
E→E+T | E-T | T
T→T*F | T/F | F
F→(E) | id
According to the grammar, the operator priority analyzer is written.
1) Input: any string. (id in grammar corresponds to the identifier identified in lexical analysis, + - * / respectively corresponds to the operator obtained from lexical analysis);
2) Output: determine whether the input string is a legal arithmetic expression defined by the grammar;
Experimental steps
1) Supplement the above grammar with a new start symbol e 'and a new production (E' → #e#), and determine whether the given grammar is an OPG grammar;
2) Construct Firstvt and Lastvt set algorithms to solve all non terminators in the grammar;
3) According to the idea of operator priority analysis, the priority relationship table of all terminators is constructed;
4) Using stack, the input test cases are analyzed and identified, and the corresponding results are given;
5) Analyze and study the program and draw the corresponding flow chart.
VII Experimental results (draw the flow chart, give the screenshot of operation results, and describe the method of error detection)
1, Manual analysis process
1) Supplement the above grammar with a new start symbol e 'and a new production (E' → #e#), and determine whether the given grammar is an OPG grammar;
After completion, the grammar is:
S→#E#
E→E+T
E→E-T
E→T
T→T*F
T→T/F
T→F
F→(E)
F → i this grammar has no form of E → FT, no empty production, and there is at most one priority relationship between the two terminators, so this grammar is an operator priority grammar.
2) Construct Firstvt and Lastvt set algorithms to solve all non terminators in the grammar;
Find the FIRSTVT and LASTVT sets of each terminator of the grammar:
FIRSTVT(E')={#}
FIRSTVT(E)={+,-,*,/,(,i}
FIRSTVT(T)={*,/,(,i }
FIRSTVT(F)={(,i }
LASTVT(E')={#}
LASTVT(E)={+,-,*,/,) ,i}
LASTVT(T)={*,/,) ,i }
LASTVT(F)={) ,i }
3) According to the idea of operator priority analysis, the priority relationship table of all terminators is constructed;
1. Seek < relationship
#E yes # < FIRSTVT (E)
+T + < FIRSTVT (T)
-T yes - < FIRSTVT (T)
*F * < FIRSTVT (f)
/F yes / < FIRSTVT (f)
(e < FIRSTVT (E)
2. Seek > relationship
E # yes # > LASTVT
E + > LASTVT (E)
E-yes - > LASTVT (E)
T * yes * > LASTVT (T)
T / yes / > LASTVT (T)
E) Yes) > LASTVT (E)
3. Seek = relationship
E '→ #e # get # =#
F → (E) gets (=)
According to the above analysis, the priority relationship table is as follows:
Table I priority relationship
+ | - | * | / | ( | ) | i | # | |
+ | > | > | < | < | < | > | < | > |
- | > | > | < | < | < | > | < | > |
* | > | > | > | > | < | > | < | > |
/ | > | > | > | > | < | > | < | > |
( | < | < | < | < | < | = | < | |
) | > | > | > | > | > | > | ||
i | > | > | > | > | > | > | ||
# | < | < | < | < | < | < | = |
rule.txt input is as follows:
S→#E#
E→E+T
E→E-T
E→T
T→T*F
T→T/F
T→F
F→(E)
F→i
stop
preservation
Enter the corresponding formula in the program to see the protocol stack and results
The code is as follows:
from collections import deque first=[[] for i in range(10)] last=[[] for i in range(10)] dfirst = {} dvt={} stack = deque() satck_int = deque() mode=1 def findfirst(l,r): for i in range(time+1): if left[i] == r: for x in range(len(right[i])): if right[i][x] in vt: if right[i][x] not in first[dfirst[l]]: first[dfirst[l]].append(right[i][x]) break elif right[i][x] in vn and right[i][x] != left[i]and x==0: findfirst(l, right[i][x]) continue def findlast(l,r): for i in range(time+1): if left[i] == r: for x in range(len(right[i])): if right[i][x] in vt: if right[i][x] not in last[dfirst[l]]: last[dfirst[l]].append(right[i][x]) break if right[i][x] in vn and right[i][x] != left[i]and x==0: findlast(l, right[i][x]) continue def getfirstvt(mode): for i in range(time+1): if left[i] in vn: for x in range(len(right[i])): if mode==1: if right[i][x] in vt :#Non Terminator if right[i][x] not in first[dfirst[left[i]]]: first[dfirst[left[i]]].append(right[i][x]) break elif right[i][x] in vn and right[i][x] != left[i] and x==0:#Terminator findfirst(left[i],right[i][x]) continue elif mode==2: if right[i][x] in vt :#Non Terminator if right[i][x] not in last[dfirst[left[i]]]: last[dfirst[left[i]]].append(right[i][x]) break if right[i][x] in vn and right[i][x] != left[i] and x==0:#Terminator findlast(left[i],right[i][x]) continue def getchar(): input("scan your rules(change id to i and end with stop)") global vt, vn, left, right, time vt = set() vn = set() k = 1 time = -1 left = [] right = [[0 for i in range(10)] for i in range(10)] f = open("D:\\desktop\\rule.txt",encoding='utf-8') while True: rule = f.readline().strip('\n') if rule == 'stop': break case = 0 time += 1 y = 0 for index in range(len(rule)): if case == 0 and rule[index] != '→' and rule[index] != ''': left.append(rule[index]) if case == 1: right[time][y] = rule[index] y += 1 if rule[index] > "A" and rule[index] < "Z": vn.add(rule[index]) elif not (rule[index] == "→" or rule[index] == "'"): vt.add(rule[index]) if rule[index] == '→': case = 1 index += 1 def creat_flvt(): l_vn=list(vn) for i in range(len(l_vn)): dfirst[l_vn[i]] = i l_vt=list(vt) for i in range(len(l_vt)): dvt[l_vt[i]] = i global lenth_vt lenth_vt=len(l_vt) for x in range(len(right)): while 0 in right[x]: right[x].remove(0) def printvnvt():#Unmark the content you want to view print('VT and VN:') print(vt) print(vn) print('left and right:') print(right) print(left) #print(time + 1) print('VN') print(dfirst.keys()) print('firstvt and lastvt') print(first) print(last) print('VT') print(dvt.keys()) print('TABLE') for i in range(len(table)): print(table[i]) def gettable(): global table table = [[0 for i in range(lenth_vt)] for i in range(lenth_vt)] for i in range(time+1): for x in range(len(right[i])-1): rig = right[i][x] riger = right[i][x+1] if rig in vt and riger in vn: for s in first[dfirst[riger]]: table[dvt[rig]][dvt[s]] = '<' if rig in vn and riger in vt: for f in last[dfirst[rig]]: table[dvt[f]][dvt[riger]] = '>' if rig in vt and riger in vt: table[dvt[rig]][dvt[riger]] = '=' for x in range(len(right[i])-2): if right[i][x] in vt and right[i][x+1] in vn and right[i][x+2] in vt: if right[i][x]== right[i][x+2]: table[dvt[right[i][x]]][dvt[right[i][x+2]]] = '=' table[dvt[right[i][x+2]]][dvt[right[i][x]]] = '=' else: table[dvt[right[i][x]]][dvt[right[i][x + 2]]] = '=' def turndown(): for i in range(time + 1): right[i].reverse() # Invert right 2D array def simplify(): sentence=input("input your sentence:") sentence=list(sentence) sentence.append('#') stack.append('#') x=0 y=0 while(len(stack)): print() print(satck_int) print(stack) if(sentence[y]>'0'and sentence[y]<'9'): num=int(ord(sentence[y])-ord('0')) y+=1 while(sentence[y]>'0'and sentence[y]<'9'): num=num*10+int(ord(sentence[y])-ord('0')) y+=1 satck_int.append(num) if sentence[y] in {'+','-','*','/','#','(',')'}: t1=stack[len(stack)-1] t2=sentence[y] z1=dvt[t1] z2=dvt[t2] if table[z1][z2]=="0": print("Error!") return if table[z1][z2]=="<": stack.append(t2) x+=1 y+=1 continue elif table[z1][z2] == "=": stack.pop() x-=1 y+=1 else:#if table[z1][z2]==">" calculate(t1) continue else: print("Error!") return out=satck_int.pop() print(out) def count(a,b,c): if c=='+': return a+b elif c=='-': return a-b elif c=='*': return a*b elif c=='/': return b/a def calculate(t1): d1=satck_int[len(satck_int)-1] satck_int.pop() d2=satck_int[len(satck_int)-1] satck_int.pop() satck_int.append(count(d1,d2,t1)) stack.pop() def main(): getchar() creat_flvt() getfirstvt(1)#Positive order search under mode 1 turndown() getfirstvt(2)#Under Mode 2, search in reverse order turndown() gettable() #printvnvt() simplify() return main() '''rule.txt Content of S→#E# E→E+T E→E-T E→T T→T*F T→T/F T→F F→(E) F→i stop '''
There are too many final assignments. In fact, there is still a lot of room for optimization. I'll make it up in the winter vacation.