Operator priority analysis method to realize the analysis and recognition of a given expression (Python)

Posted by Onloac on Thu, 23 Dec 2021 15:33:48 +0100

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.

Topics: Python Back-end