@exgod
Трудно быть Богом.

Что означают определённые строки в файлах?

Добрый вечер, есть два файла, один из которых:
# 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]])

Пожалуйста, помогите разобраться.
  • Вопрос задан
  • 145 просмотров
Пригласить эксперта
Ответы на вопрос 2
@pfemidi
Тут могло бы быть краткое описание меня
В документации и в примерах на PLY всё чётко и понятно изложено.
Ответ написан
Комментировать
@mactep3230
могу ошибаться, но мне кажется здесь
def t_COMMENT(t):
    r'({*(.|\n)*?})'
    pass

должно быть
t_COMMENT = r'({*(.|\n)*?})'

и здесь
def t_NEWLINE(t):
    r'(\n)'
    pass

соответственно
t_NEWLINE = r'(\n)'
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы