def set_parse_action_magic(rule_name: str, parser_element: pp.ParserElement) -> None: if rule_name == rule_name.upper(): return if getattr(parser_element, 'name', None) and parser_element.name.isidentifier(): rule_name = parser_element.name if rule_name in ('bin_op', ): def bin_op_parse_action(s, loc, tocs): node = tocs[0] if not isinstance(node, AstNode): node = bin_op_parse_action(s, loc, node) for i in range(1, len(tocs) - 1, 2): second_node = tocs[i + 1] if not isinstance(second_node, AstNode): second_node = bin_op_parse_action(s, loc, second_node) node = BinOpNode(BinOp(tocs[i]), node, second_node, loc=loc) return node parser_element.setParseAction(bin_op_parse_action) else: cls = ''.join(x.capitalize() for x in rule_name.split('_')) + 'Node' with suppress(NameError): cls = eval(cls) if not inspect.isabstract(cls): def parse_action(s, loc, tocs): if cls is FuncNode: return FuncNode(tocs[0], tocs[1], tocs[2:-1], tocs[-1], loc=loc) else: return cls(*tocs, loc=loc) parser_element.setParseAction(parse_action)
def set_parse_action_magic(rule_name: str, parser: pp.ParserElement)->None: if rule_name == rule_name.upper(): return if getattr(parser, 'name', None) and parser.name.isidentifier(): rule_name = parser.name if rule_name in ('bin_op', ): def bin_op_parse_action(s, loc, tocs): node = tocs[0] if not isinstance(node, AstNode): node = bin_op_parse_action(s, loc, node) for i in range(1, len(tocs) - 1, 2): secondNode = tocs[i + 1] if not isinstance(secondNode, AstNode): secondNode = bin_op_parse_action(s, loc, secondNode) node = BinOpNode(BinOp(tocs[i]), node, secondNode) return node parser.setParseAction(bin_op_parse_action) else: cls = ''.join(x.capitalize() for x in rule_name.split('_')) + 'Node' #разбитие названия переменной на куски по _, создание заглавной первой буквы и прибавление Node with suppress(NameError): cls = eval(cls) if not inspect.isabstract(cls): def parse_action(s, loc, tocs): return cls(*tocs) parser.setParseAction(parse_action)
def set_parse_action_magic(rule_name: str, parser: pp.ParserElement) -> None: if rule_name == rule_name.upper(): return if rule_name in ('mult', 'add', 'cond', 'cond_list'): def bin_op_parse_action(s, loc, tocs): node = tocs[0] for i in range(1, len(tocs) - 1, 2): node = BOperNode(BinOperation(tocs[i]), node, tocs[i + 1]) return node parser.setParseAction(bin_op_parse_action) else: cls = ''.join(x.capitalize() or '_' for x in rule_name.split('_')) + 'Node' with suppress(NameError): cls = eval(cls) parser.setParseAction(lambda s, loc, tocs: cls(*tocs))
def __set_parse_action(self, rule_name: str, rule: pp.ParserElement): """ Этот метод задаёт то, какой конструктор вызывается при успешном распознавании правила грамматики. """ # если rule_name написан КАПСОМ, то никаких действий совершать не нужно, # потому что КАПСОМ мы обозначили названия переменных, в которых описываются различные операторы. if rule_name == rule_name.upper(): return # Каждому правилу присваивется название соответствующего класса, если оно было задано методом setName(). if getattr(rule, 'name', None) and rule.name.isidentifier(): rule_name = rule.name # Если имя правила — "BinExpr", то определяется метод, который будет разбирать бинарное выражение. if rule_name in ('BinExpr', ): # Этот метод вернёт экземпляр класса BinExprNode. def bin_op_parse_action(s, loc, toks): # toks - список распознанных элементов node = toks[0] if not isinstance(node, TreeNode): node = bin_op_parse_action(s, loc, node) for i in range(1, len(toks) - 1, 2): secondNode = toks[i + 1] if not isinstance(secondNode, TreeNode): secondNode = bin_op_parse_action(s, loc, secondNode) # Когда распознана правая часть, создаётся экземпляр класса BinExprNode. node = BinExprNode(self._locs[loc][0], self._locs[loc][1], Operators(toks[i]), node, secondNode) return node # Задаётся действие при успешном распознавании текущего правила - вызов функции bin_op_parse_action. rule.setParseAction(bin_op_parse_action) # Если имя правила — "UnaryExpr", то определяется метод, который будет разбирать унарное выражение. elif rule_name in ('UnaryExpr', ): # Этот метод вернёт экземпляр класса UnaryExprNode. def un_op_parse_action(s, loc, toks): # toks - список распознанных элементов node = toks[0] if not isinstance(node, TreeNode): node = un_op_parse_action(s, loc, node) for i in range(1, len(toks)): # Создаётся экземпляр класса UnaryExprNode. node = UnaryExprNode(self._locs[loc][0], self._locs[loc][1], Operators(toks[i]), node) return node # Задаётся действие при успешном распознавании текущего правила - вызов функции un_op_parse_action. rule.setParseAction(un_op_parse_action) # В случае, когда не выполнилось ни одно из предшествующих условий, выполняется следующий фрагмент кода: else: # cls хранит название класса в виде: название_правила + Node, # это соответствует названию классов в фалйе Nodes.py. cls = rule_name + 'Node' # Во избежание вызова исключения NameError используется конструкция with suppress(NameError): with suppress(NameError): # Теперь в переменой cls хранится тип узла, который соответствует разбираемому правилу. cls = eval(cls) # Если csl не является абстрактным классом, в нашем случае это EvalNode, ValueNode, ExprNode, # определяется метод parse_action. if not inspect.isabstract(cls): # Этот метод вернёт экземпляр класса, который соответствует разбираемому правилу. def parse_action(s, loc, toks): return cls(self._locs[loc][0], self._locs[loc][1], *toks) # Задаётся действие при успешном распознавании текущего правила - вызов функции parse_action. rule.setParseAction(parse_action)
def set_parse_action_magic(rule_name: str, parser: pp.ParserElement) -> None: if rule_name == rule_name.upper(): return if rule_name in ('mult', 'add'): def bin_op_parse_action(s, loc, tocs): node = tocs[0] for i in range(1, len(tocs) - 1, 2): node = BinOpNode(BinOp(tocs[i]), node, tocs[i + 1]) return node parser.setParseAction(bin_op_parse_action) else: cls = ''.join(x.capitalize() for x in rule_name.split('_')) + 'Node' with suppress(NameError): cls = eval(cls) if not inspect.isabstract(cls): def parse_action(s, loc, tocs): return cls(*tocs) parser.setParseAction(parse_action)