Reputation: 23
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
Upvotes: 0
Views: 641
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]
.
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