ayse
ayse

Reputation: 23

how to parsing with ply-pyhton

I'm studying over parsing with ply-python. I have some problems. My parse output is not exactly what I wanted but in the right order. so please help or suggest something that can help. the first question is why does the parser take "F 100 R 90" but write just F 100? the second one is why I have None as an output?

import ply.lex as lex
import ply.yacc as yacc

filepath = "C:/Users/Pc/source/repos/automata/text.txt"
file = open(filepath, "r")
program = file.read()

tokens = ('F', 'R', 'L', 'COLOR', 'PEN',
          'NUMBER', 
          'COLOR_TYPE',
          'LBRACKET','RBRACKET' )

t_F = r'F'
t_R = r'R'
t_L = r'L'
t_COLOR = r'COLOR'
t_PEN = r'PEN'

t_NUMBER = r"\d+"

t_COLOR_TYPE = r"K|Y|M|S"

t_LBRACKET = r'\['
t_RBRACKET = r'\]'

t_ignore = " \t"

def t_newline(t):
    r'\n+'
    t.lexer.lineno += t.value.count("\n")

def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

lexer = lex.lex()
lexer.input(program)
for token in lexer:
    print(token)

"""   
precedence = (
        ('right','R'),
        ('right', 'F'),
        ('right','L'),
        ('right','PEN','COLOR'),
        )
"""
run = []

# start = 'instructions'

def p_statememt_expr(t):
    'statement : expression'
    run.append(t[1])
    print(t[1])
    print("p_statememt_expr")
    print(*t, "\n")

def p_expression_loop_type(t):
    'expression : L NUMBER LBRACKET expression RBRACKET' # !
    run.append( [ t[1],t[2], [ t[4] ] ] )
    print("p_expression_loop_type")
    print(*t, "\n")

def p_expression_loop_type1(t):
    'expression : L NUMBER LBRACKET instructions RBRACKET'
    run.append([t[1], t[2] , [ t[4] ] ])
    print("p_expression_loop1")
    print(*t, "\n")

def p_expression_loop_type2(t):
    'expression : L NUMBER LBRACKET instructions RBRACKET quality'
    run.append([t[1], t[2], [ t[4] ] ,t[6] ])
    print("p_expression_loop_type2")
    print(*t, "\n")

def p_expression_loop_type_3(t):
    'expression : L NUMBER LBRACKET instructions quality RBRACKET'
    run.append([t[1], t[2], [ t[4] ,t[5] ] ])
    print("p_expression_loop_type_3")
    print(*t, "\n")

def p_expression_loop_type4(t):
    'expression : L NUMBER LBRACKET instructions quality RBRACKET quality'
    run.append([t[1], t[2], [ t[4] ,t[5] ] ,t[7] ])
    print("p_expression_loop_type4")
    print(*t, "\n")

def p_expression_loop_type5(t):
    'expression : L NUMBER LBRACKET instructions quality RBRACKET instructions quality' # !
    run.append([t[8], t[1], t[2], [ t[5] ,t[4] ] ,t[7] ])
    print("p_expression_loop_type5")
    print(*t, "\n")

def p_instruction(t):
    '''instructions : F NUMBER R NUMBER
                    | R NUMBER
                    | F NUMBER
                  '''
    run.append([t[1],t[2]])
    print("p_instruction")
    print(*t, "\n")

def p_quality(t):
    '''quality : COLOR COLOR_TYPE
               | PEN NUMBER
               | COLOR COLOR_TYPE PEN NUMBER
               '''
    run.append([t[1],t[2]])
    print("p_quality")
    print(*t, "\n")

def p_error(t):
    print("Syntax error at '%s'" % t.value)
    print("p_error")
    print(*t, "\n")

parser = yacc.yacc()
parser.parse(program)
print(run)

output is

LexToken(L,'L',1,0)
LexToken(NUMBER,'36',1,2)
LexToken(LBRACKET,'[',1,5)
LexToken(L,'L',1,7)
LexToken(NUMBER,'4',1,9)
LexToken(LBRACKET,'[',1,11)
LexToken(F,'F',1,13)
LexToken(NUMBER,'100',1,15)
LexToken(R,'R',1,19)
LexToken(NUMBER,'90',1,21)
LexToken(PEN,'PEN',1,24)
LexToken(NUMBER,'2',1,28)
LexToken(RBRACKET,']',1,30)
LexToken(R,'R',1,32)
LexToken(NUMBER,'10',1,34)
LexToken(COLOR,'COLOR',1,37)
LexToken(COLOR_TYPE,'K',1,43)
LexToken(RBRACKET,']',1,45)
p_instruction
None F 100 R 90

p_quality
None PEN 2

p_instruction
None R 10

p_quality
None COLOR K

p_expression_loop_type5
None L 4 [ None None ] None None

p_expression_loop_type
None L 36 [ None ]

None
p_statememt_expr
None None

[['F', '100'], ['PEN', '2'], ['R', '10'], ['COLOR', 'K'], [None, 'L', '4', [None, None], None], ['L', '36', [None]], None]

in the text file I have this instruction

L 36 [ L 4 [ F 100 R 90 PEN 2 ] R 10 COLOR K ]

and they are meaning

F n -> go on n step
R n -> turn right n degree
L n -> Repeat the parentheses n times, so it will be loop
COLOR f -> f: line color
PEN n -> line thickness

finally if i have take the true parse output i will use them with turtle and draw something in GUI. for example drawing output of program in the text will be

enter image description here

Upvotes: 0

Views: 641

Answers (1)

rici
rici

Reputation: 241671

why does the parser take "F 100 R 90" but write just F 100?

Because that's what your action says it should do:

# I abbreviated the rule for space
def p_instruction(t):
'''instructions : F NUMBER R NUMBER```
    run.append([t[1],t[2]])

The R and associated number are not used by the action.

Hint: You shouldn't assume that there are only one or two instructions. You need to right a grammar which accepts any number of commands. Also, there is no need to special case the other commands, not even Loop. A list of commands is just a list of commands.

why I have None as an output?

Because you are using the semantic value of the non-terminal instructions but that non-terminal does not return any value. So its value is None. Instead of appending to run, you should build up the list by returning semantic values from each production, which you do by assigning to p[0].

Additional hint:

I think I've said this before, but trying to cut and paste bits and pieces of a grammar designed for a completely different purpose (an expression evaluator) is not helping you at all. Figure out how Ply works and write your own grammar.

Upvotes: 1

Related Questions