def unary_prefix_evaluator(parser, sym): arg = parser.parse_to(sym.rprio) if arg is None: return CompositeNode(sym.token, [Node(lexer.Token('ERROR', 'MISSING VALUE'))]) else: return CompositeNode(sym.token, [arg])
def question_evaluator(args): if (len(args) != 5 or type(args[0]) == SymbolDesc or type(args[1]) != SymbolDesc or args[1].symbol != '?' or type(args[2]) == SymbolDesc or type(args[3]) != SymbolDesc or args[3].symbol != ':' or type(args[4]) == SymbolDesc): return CompositeNode('? ERROR', args) return CompositeNode('?', [args[0], args[2], args[4]])
def binary_evaluator(parser, left_arg, sym): right_arg = parser.parse_to(sym.rprio) if right_arg is None: return CompositeNode( sym.token, [left_arg, Node(lexer.Token('ERROR', 'MISSING VALUE'))]) else: return CompositeNode(sym.token, [left_arg, right_arg])
def open_bracket_evaluator(args): if (len(args) == 4 and type(args[0]) != SymbolDesc and type(args[1]) == SymbolDesc and args[1].symbol == '[' and type(args[2]) != SymbolDesc and type(args[3]) == SymbolDesc and args[3].symbol == ']'): return CompositeNode('get', [args[0], args[2]]) else: return CompositeNode('[ ERROR', args)
def unary_evaluator(args): if len(args) != 2: return CompositeNode('UNARY ERROR', args) if type(args[0]) == SymbolDesc and type(args[1]) != SymbolDesc: return CompositeNode(args[0].symbol, [args[1]]) elif type(args[0]) != SymbolDesc and type(args[1]) == SymbolDesc: return CompositeNode('post' + args[1].symbol, [args[0]]) else: return CompositeNode('UNARY ERROR', args)
def question_evaluator(parser, left_arg, sym): true_exp = parser.parse_to(sym.rprio) sym = parser.postfix_sym() if sym is not None and sym.token == ':': parser.advance() false_exp = parser.parse_to(sym.rprio) return CompositeNode('?', [left_arg, true_exp, false_exp]) else: return CompositeNode('? ERROR', [left_arg, true_exp])
def postfix_open_bracket_evaluator(parser, left_arg, sym): result = parser.parse_to(sym.rprio) if parser.cur_token is not None: if parser.cur_token.lexem == ']': parser.advance() return CompositeNode('get ' + str(left_arg), [result]) elif parser.cur_token.lexem == ')': parser.advance() return CompositeNode('get [) ' + str(left_arg), [result]) return CompositeNode('[ ERROR', [left_arg, result])
def prefix_open_parenthesis_evaluator(parser, sym): result = parser.parse_to(sym.rprio) if parser.cur_token is not None: if parser.cur_token.lexem == ')': parser.advance() return result elif parser.cur_token.lexem == ']': parser.advance() return CompositeNode('(] ERROR', [result]) else: return CompositeNode('( ERROR', [result])
def unary_or_binary_evaluator(args): if (len(args) == 2 and type(args[0]) == SymbolDesc and type(args[1]) != SymbolDesc): return CompositeNode(args[0].symbol, [args[1]]) elif (len(args) == 2 and type(args[0]) != SymbolDesc and type(args[1]) == SymbolDesc): return CompositeNode('post' + args[1].symbol, [args[0]]) elif (len(args) == 3 and type(args[0]) != SymbolDesc and type(args[1]) == SymbolDesc and type(args[2]) != SymbolDesc): return CompositeNode(args[1].symbol, [args[0], args[2]]) else: return CompositeNode('1,2-ARY ERROR', args)
def parse(self, s): self.reset() previous_was_id = False for tk in lexer.tokenize(s): if tk.kind == 'NUMBER' or tk.kind == 'ID': self.values_stack.append(Node(tk)) elif tk.lexem == '(': self.operators_stack.append(self.operators[tk.lexem]) self.previous_coma_interpretation.append( self.coma_interpretation) if previous_was_id: self.coma_interpretation = 2 else: self.coma_interpretation = 0 elif tk.lexem == '[': self.operators_stack.append(self.operators[tk.lexem]) self.previous_coma_interpretation.append( self.coma_interpretation) self.coma_interpretation = 1 elif tk.lexem in self.operators: self.push_operator(self.operators[tk.lexem]) if tk.lexem == ')': self.operators_stack.pop() self.operators_stack.pop() if self.coma_interpretation == 2: val2 = self.values_stack.pop() val1 = self.values_stack.pop() self.values_stack.append( CompositeNode('call', [val1, val2])) self.coma_interpretation = self.previous_coma_interpretation.pop( ) elif tk.lexem == ']': self.operators_stack.pop() self.operators_stack.pop() val2 = self.values_stack.pop() val1 = self.values_stack.pop() self.values_stack.append( CompositeNode('index', [val1, val2])) self.coma_interpretation = self.previous_coma_interpretation.pop( ) else: raise RuntimeError('Syntax error at {}'.format(tk.lexem)) previous_was_id = tk.kind == 'ID' while len(self.operators_stack) > 0: self.evaluate_operator() if len(self.values_stack) != 1: raise RuntimeError('Internal error: value left on stack') return self.values_stack.pop()
def NullIncDec(p, token, rbp): """ ++x or ++x[1] """ right = p.ParseUntil(rbp) if right.token not in ('ID', 'get') and ( right.token is Token and right.token.kind not in ('ID', 'get')): raise ParseError("Can't assign to %r (%s)" % (right, right.token)) return CompositeNode(token.kind, [right])
def LeftIndex(p, token, unused_rbp, left): """ index f[x+1] or f[x][y] """ if left.token.kind not in ('ID', 'get'): raise ParseError("%s can't be indexed" % left) index = p.ParseUntil(0) p.Eat("]") token.kind = 'get' return CompositeNode(token.kind, [left, index])
def prefix_close_parenthesis(parser): op1 = parser.operators_stack.pop() if op1.oper != '(' or op1.evaluator != infix_open_parenthesis: parser.dump() raise RuntimeError('Empty parenthesis') val1 = parser.values_stack.pop() parser.values_stack.append(CompositeNode('call', [val1])) parser.waiting_value = False
def LeftComma(p, token, rbp, left): """ foo, bar, baz - Could be sequencing operator, or tuple without parens """ r = p.ParseUntil(rbp) if not left.parenthesis and left.token == ',': # Keep adding more children left.children.append(r) return left children = [left, r] return CompositeNode(token.kind, children)
def NullPrefixOp(p, token, rbp): """Prefix operator Low precedence: return, raise, etc. return x+y is return (x+y), not (return x) + y High precedence: logical negation, bitwise complement, etc. !x && y is (!x) && y, not !(x && y) """ r = p.ParseUntil(rbp) return CompositeNode(token.kind, [r])
def postfix_close_brackets(parser): op1 = parser.operators_stack.pop() op2 = parser.operators_stack.pop() if op2.oper != '[' or op2.evaluator != infix_open_brackets: parser.dump() raise RuntimeError('Unopened close bracket') val1 = parser.values_stack.pop() val2 = parser.values_stack.pop() parser.values_stack.append(CompositeNode('get', [val2, val1]))
def coma_evaluator(parser, left_arg, sym): args = [left_arg] while True: args.append(parser.parse_to(sym.rprio)) sym = parser.postfix_sym() if sym is None or sym.token != ',': break parser.advance() return CompositeNode(',', args)
def infix_colon(parser): op1 = parser.operators_stack.pop() op2 = parser.operators_stack.pop() if op2.oper != '?': parser.dump() raise RuntimeError(': wihout ?') val1 = parser.values_stack.pop() val2 = parser.values_stack.pop() val3 = parser.values_stack.pop() parser.values_stack.append(CompositeNode('?', [val3, val2, val1]))
def coma_evaluator(parser): oper = parser.operators_stack.pop() val2 = parser.values_stack.pop() val1 = parser.values_stack.pop() if type(val1 ) is CompositeNode and val1.token == ',' and not val1.parenthesis: val1.children.append(val2) parser.values_stack.append(val1) else: parser.values_stack.append(CompositeNode(oper.oper, [val1, val2]))
def parse_for_operator(self, tk): if tk.lexem in self.postfix_actions: self.postfix_actions[tk.lexem](self) elif tk.lexem in self.postfix_operators: self.push_operator(self.postfix_operators[tk.lexem]) elif tk.lexem in self.infix_operators: self.waiting_value = True self.push_operator(self.infix_operators[tk.lexem]) else: val = self.values_stack.pop() self.values_stack.append( CompositeNode('MISSING OPERATOR', [val, Node(tk)]))
def open_parenthesis_evaluator(args): if (len(args) == 3 and type(args[0]) == SymbolDesc and args[0].symbol == '(' and type(args[1]) != SymbolDesc and type(args[2]) == SymbolDesc and args[2].symbol == ')'): return args[1] elif (len(args) == 3 and type(args[0]) != SymbolDesc and type(args[1]) == SymbolDesc and args[1].symbol == '(' and type(args[2]) == SymbolDesc and args[2].symbol == ')'): return CompositeNode('call', [args[0]]) elif (len(args) == 4 and type(args[0]) != SymbolDesc and type(args[1]) == SymbolDesc and args[1].symbol == '(' and type(args[2]) != SymbolDesc and type(args[3]) == SymbolDesc and args[3].symbol == ')'): if args[2].token == ',': callargs = args[2].children else: callargs = [args[2]] callargs.insert(0, args[0]) return CompositeNode('call', callargs) else: return CompositeNode('( ERROR', args)
def LeftFuncCall(p, token, unused_rbp, left): """ Function call f(a, b). """ children = [left] # f(x) or f[i](x) # if left.token.kind not in ('ID', 'get'): # raise tdop.ParseError("%s can't be called" % left) while not p.AtToken(')'): # We don't want to grab the comma, e.g. it is NOT a sequence operator. children.append(p.ParseUntil(COMMA_PREC)) if p.AtToken(','): p.Next() p.Eat(")") token.kind = 'call' return CompositeNode(token.kind, children)
def LeftTernaryOp(p, token, rbp, left): """ e.g. a > 1 ? x : y """ # 0 binding power since any operators allowed until ':'. See: # # http://en.cppreference.com/w/c/language/operator_precedence#cite_note-2 # # "The expression in the middle of the conditional operator (between ? and # :) is parsed as if parenthesized: its precedence relative to ?: is # ignored." true_expr = p.ParseUntil(0) p.Eat(':') false_expr = p.ParseUntil(rbp) children = [left, true_expr, false_expr] return CompositeNode(token.kind, children)
def postfix_close_parenthesis(parser): op1 = parser.operators_stack.pop() op2 = parser.operators_stack.pop() if op2.oper != '(': parser.dump() raise RuntimeError('Unopened close parenthesis') if op2.evaluator == infix_open_parenthesis: val1 = parser.values_stack.pop() val2 = parser.values_stack.pop() if type(val1) == CompositeNode and val1.token == ',': args = [val2] + val1.children else: args = [val2, val1] parser.values_stack.append(CompositeNode('call', args)) else: parser.values_stack[-1].parenthesis = True
def parse(self, s): self.reset(s) while True: sym = self.cur_sym(type(self.stack[-1]) == SymbolDesc) if sym is None: break while self.tos_symbol().rprio > sym.lprio: self.evaluate() sym = self.cur_sym(False) self.stack.append(sym) self.advance() while len(self.stack) > 2 or (len(self.stack) == 2 and type(self.stack[-1]) == SymbolDesc): self.evaluate() if len(self.stack) == 1: res = None elif len(self.stack) == 2: res = self.stack[1] if self.cur_token is not None: res = CompositeNode('REMAINING INPUT', [res, self.cur_token]) return res
def postfix_open_parenthesis_evaluator(parser, left_arg, sym): if parser.cur_token is not None and parser.cur_token.lexem == ')': parser.advance() return CompositeNode('call ' + str(left_arg), []) else: result = parser.parse_to(sym.rprio) if parser.cur_token is not None: if parser.cur_token.lexem == ')': parser.advance() if result.token == ',': return CompositeNode('call ' + str(left_arg), result.children) else: return CompositeNode('call ' + str(left_arg), [result]) elif parser.cur_token.lexem == ']': parser.advance() if result.token == ',': return CompositeNode('call (] ' + str(left_arg), result.children) else: return CompositeNode('call (] ' + str(left_arg), [result]) return CompositeNode('( ERROR', [result])
def binary_evaluator(parser): val2 = parser.stack.pop() oper = parser.stack.pop() val1 = parser.stack.pop() parser.stack.append(CompositeNode(oper.oper, [val1, val2]))
def unary_evaluator(parser): val = parser.stack.pop() oper = parser.stack.pop() parser.stack.append(CompositeNode(oper.oper, [val]))
def unary_evaluator(parser): oper = parser.operators_stack.pop() parser.values_stack.append(CompositeNode(oper.oper, [parser.values_stack.pop()]))
def binary_evaluator(args): if len(args) != 3 or type( args[0]) == SymbolDesc or type(args[1]) != SymbolDesc or type( args[2]) == SymbolDesc: return CompositeNode('BINARY ERROR', args) return CompositeNode(args[1].symbol, [args[0], args[2]])