Добрый вечер, есть два файла, один из которых:
# coding=utf8
import ply.lex as lex
from ply.lex import TOKEN
import re
# без этой штуки ничего не съинтерпретируется, потому что этот массив шарится между лексером и парсером и кроме того используется внутренне библиотекой
tokens = (
'START', 'COMMENT', 'DEF', 'IDENT', 'COLON', 'NEWLINE', 'NUM', 'ASSIGN', 'OPEN', 'CLOSE', 'DIVMUL', 'PLUSMINUS', 'COMPARE', 'LOGIC',
'IF', 'THEN', 'ELSE', 'END', 'WHILE', 'DO', 'COMA', 'INPUT', 'PRINT', 'PASSIGN', 'MINASSIGN', 'DASSIGN', 'MULASSIGN'
)
# определим регулярку для абстрактного идетификатора
# для каждого токена из массива мы должны написать его определение вида t_ИМЯТОКЕНА = регулярка
t_START = r'[\$][_a-zA-Z0-9]\w*[\$]'
t_IF = r'if'
t_THEN = r'then'
t_ELSE = r'else'
t_END = r'end'
t_WHILE = r'while'
t_DEF = r'def'
t_DO = r'do'
t_INPUT = r'input'
t_PRINT = r'print'
t_ASSIGN = r'='
t_PASSIGN = r'(\+\=)'
t_MINASSIGN = r'(\-\=)'
t_DASSIGN = r'(/\=)'
t_MULASSIGN = r'(\*\=)'
t_NUM = r'[0-9]+([\.|\.]?[0-9]*)?([eE][\+\-]?[0-9]+)?'
t_COLON = r';'
t_COMA = r','
t_OPEN = r'\('
t_CLOSE = r'\)'
t_DIVMUL = r'\*|/'
t_PLUSMINUS = r'\+|\-'
t_COMPARE = r'(==)|(<=)|(>=)|(!=)|(>)|(<)'
t_LOGIC = r'(\|\|)|(\&\&)'
ident = r'[_a-zA-Z][_a-zA-Z0-9]*'
# игнорируем комментарии
def t_COMMENT(t):
r'({*(.|\n)*?})'
pass
@TOKEN(ident)
def t_IDENT(t):
if t.value == 'def':
t.type = 'DEF'
elif t.value == 'if':
t.type = 'IF'
elif t.value == 'then':
t.type = 'THEN'
elif t.value == 'else':
t.type = 'ELSE'
elif t.value == 'end':
t.type = 'END'
elif t.value == 'while':
t.type = 'WHILE'
elif t.value == 'do':
t.type = 'DO'
elif t.value == 'print':
t.type = 'PRINT'
elif t.value == 'input':
t.type = 'INPUT'
else: t.type = 'IDENT'
return t
def t_NEWLINE(t):
r'(\n)'
pass
# здесь мы игнорируем незначащие символы
t_ignore = ' \r\t\f'
# а здесь мы обрабатываем ошибки. Кстати заметьте формат названия функции
def t_error(t):
print ("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
lexer = lex.lex(reflags=re.UNICODE | re.DOTALL | re.IGNORECASE)
if __name__=="__main__":
data = ''' '''
lexer.input(data)
while True:
tok = lexer.token() # читаем следующий токен
if not tok: break # закончились печеньки
print (tok)
Что в данном файле означает строка:
def t_NEWLINE(t):
r'(\n)'
pass
И второй файл:
# coding=utf8
from lexer import tokens
import ply.yacc as yacc
class Node:
def parts_str(self):
st = []
for part in self.parts:
st.append( str( part ) )
return "\n".join(st)
def __repr__(self):
return self.type + ":\n\t" + self.parts_str().replace("\n", "\n\t")
def add_parts(self, parts):
self.parts += parts
return self
def __init__(self, type, parts):
self.type = type
self.parts = parts
def p_text(p):
'''text :
| START commands'''
if len(p) == 1:
p[0] = None
else:
p[0] = p[2]
def p_commands(p):
'''commands :
| commands lines'''
if len(p) > 1:
if p[1] is None:
p[1] = Node('text', [])
p[0] = p[1].add_parts([p[2]])
else:
p[0] = Node('text', [])
def p_lines(p):
'''lines : assign
| passign
| dassign
| mulassign
| minassign
| def
| op_if
| while
| input
| print'''
p[0] = p[1]
def p_passign(p):
'''passign : IDENT PASSIGN expr COLON'''
p[0] = Node('assign', [p[1], Node('+', [p[1], p[3]])])
def p_dassign(p):
'''dassign : IDENT DASSIGN expr COLON'''
p[0] = Node('assign', [p[1], Node('/', [p[1], p[3]])])
def p_mulassign(p):
'''mulassign : IDENT MULASSIGN expr COLON'''
p[0] = Node('assign', [p[1], Node('*', [p[1], p[3]])])
def p_minassign(p):
'''minassign : IDENT MINASSIGN expr COLON'''
p[0] = Node('assign', [p[1], Node('-', [p[1], p[3]])])
def p_input(p):
'''input : INPUT OPEN IDENT CLOSE COLON'''
p[0] = Node('input', [p[3]])
def p_print(p):
'''print : PRINT OPEN args CLOSE COLON'''
p[0] = Node('print', [p[3]])
def p_args(p):
'''args :
| expr
| args COMA expr'''
if len(p) == 1:
p[0] = Node('args', [])
elif len(p) == 2:
p[0] = Node('args', [p[1]])
else:
p[0] = p[1].add_parts([p[3]])
def p_def(p):
'''def : DEF IDENT COLON
| DEF assign'''
if len(p) > 3:
p[0] = Node('define', [p[2]])
else:
p[0] = Node('define', [p[2]])
def p_assign(p):
'''assign : IDENT ASSIGN expr COLON'''
p[0] = Node('assign', [p[1], p[3]])
def p_expr(p):
'''expr : term
| expr PLUSMINUS expr
| expr DIVMUL expr'''
if len(p) == 2:
p[0] = p[1]
else:
p[0] = Node(p[2], [p[1], p[3]])
def p_compare(p):
'''compare : arg COMPARE arg'''
p[0] = Node(p[2], [p[1],p[3]])
def p_logic(p):
'''logic : OPEN compare CLOSE LOGIC OPEN compare CLOSE
| compare
| expr'''
if len(p) == 2:
p[0] = p[1]
else:
p[0] = Node(p[4], [p[2],p[6]])
def p_op_if(p):
'''op_if : IF OPEN logic CLOSE then else END COLON
| IF OPEN logic CLOSE then END COLON'''
if len(p) == 8:
p[0] = Node('if', [p[3], p[5]])
else:
p[0] = Node('if', [p[3], p[5], p[6]])
def p_while(p):
'''while : WHILE OPEN logic CLOSE do END COLON'''
p[0] = Node('while', [p[3], p[5]])
def p_do(p):
'''do : DO
| do lines'''
if len(p) == 2:
p[0] = Node('do', [])
else:
p[0] = p[1].add_parts([p[2]])
def p_then(p):
'''then : THEN
| then lines'''
if len(p) == 2:
p[0] = Node('then', [])
else:
p[0] = p[1].add_parts([p[2]])
def p_else(p):
'''else : ELSE
| else lines'''
if len(p) == 2:
p[0] = Node('else', [])
else:
p[0] = p[1].add_parts([p[2]])
def p_term(p):
'''term : arg
| OPEN expr CLOSE'''
if len(p) == 2:
p[0] = p[1]
else:
p[0] = p[2]
def p_arg(p):
'''arg : NUM
| IDENT'''
p[0] = Node('arg', [p[1]])
def p_error(p):
print ('Unexpected token:', p)
parser = yacc.yacc()
def build_tree(code):
return (parser.parse(code))
Что в данном файле означает строка:
p[0] = Node('input', [p[3]])
Пожалуйста, помогите разобраться.