【问题标题】:*class name* object is not callable [python]*类名*对象不可调用[python]
【发布时间】:2022-06-16 00:29:53
【问题描述】:

我正在学习编写解释器的教程,以创建我自己的编程语言。我做了与教程相同的事情,但我的代码没有按预期工作,它返回一个错误,这个:

Traceback (most recent call last):
  File "/home/ricky/PycharmProjects/interpreter/shell.py", 
line 6, in <module>
    result, error = bs.run('<stdin>', text)
  File "/home/ricky/PycharmProjects/interpreter/basic.py", 
line 232, in run
    ast = parser.parse()
  File "/home/ricky/PycharmProjects/interpreter/basic.py", 
line 189, in parse
    res = self.expr()
  File "/home/ricky/PycharmProjects/interpreter/basic.py", 
line 204, in expr
    return self.bin_op(self.term(), (TT_PLUS, TT_MINUS))
  File "/home/ricky/PycharmProjects/interpreter/basic.py", 
line 201, in term
    return self.bin_op(self.factor(), (TT_MUL, TT_DIV))
  File "/home/ricky/PycharmProjects/interpreter/basic.py", line 207, in bin_op
left = func()
TypeError: 'NumberNode' object is not callable

这是代码(2个文件),抱歉太长了:

#######################################
# CONSTANTS
#######################################

DIGITS = '0123456789'


#######################################
# ERRORS
#######################################

class Error:
    def __init__(self, pos_start, pos_end, error_name, details):
        self.pos_start = pos_start
        self.pos_end = pos_end
        self.error_name = error_name
        self.details = details

    def as_string(self):
        result = f'{self.error_name}: {self.details}\n'
        result += f'File {self.pos_start.fn}, line {self.pos_start.ln + 1}'
        return result


class InvalidChar(Error):
    def __init__(self, pos_start, pos_end, details):
        super().__init__(pos_start, pos_end, 'Invalid Character', details)


#######################################
# POSITION
#######################################

class Position:
    def __init__(self, idx, ln, col, fn, ftxt):
        self.idx = idx
        self.ln = ln
        self.col = col
        self.fn = fn
        self.ftxt = ftxt

    def advance(self, current_char):
        self.idx += 1
        self.col += 1

        if current_char == '\n':
            self.ln += 1
            self.col = 0

        return self

    def copy(self):
        return Position(self.idx, self.ln, self.col, self.fn, self.ftxt)


#######################################
# TOKENS
#######################################

TT_INT = 'INT'
TT_FLOAT = 'FLOAT'
TT_PLUS = 'PLUS'
TT_MINUS = 'MINUS'
TT_MUL = 'MUL'
TT_DIV = 'DIV'
TT_LPAREN = 'LPAREN'
TT_RPAREN = 'RPAREN'


class Token:
    def __init__(self, type_, value=None):
        self.type = type_
        self.value = value

    def __repr__(self):
        if self.value: return f'{self.type}:{self.value}'
        return f'{self.type}'


#######################################
# LEXER
#######################################

class Lexer:
    def __init__(self, fn, text):
        self.fn = fn
        self.text = text
        self.pos = Position(-1, 0, -1, fn, text)
        self.current_char = None
        self.advance()

    def advance(self):
        self.pos.advance(self.current_char)
        self.current_char = self.text[self.pos.idx] if self.pos.idx < len(self.text) else None

    def make_tokens(self):
        tokens = []

        while self.current_char != None:
            if self.current_char in ' \t':
                self.advance()
            elif self.current_char in DIGITS:
                tokens.append(self.make_number())
            elif self.current_char == '+':
                tokens.append(Token(TT_PLUS))
                self.advance()
            elif self.current_char == '-':
                tokens.append(Token(TT_MINUS))
                self.advance()
            elif self.current_char == '*':
                tokens.append(Token(TT_MUL))
                self.advance()
            elif self.current_char == '/':
                tokens.append(Token(TT_DIV))
                self.advance()
            elif self.current_char == '(':
                tokens.append(Token(TT_LPAREN))
                self.advance()
            elif self.current_char == ')':
                tokens.append(Token(TT_RPAREN))
                self.advance()
            else:
                pos_start = self.pos.copy()
                char = self.current_char
                self.advance()
                return [], InvalidChar(pos_start, self.pos, "'" + char + "'")

        return tokens, None

    def make_number(self):
        num_str = ''
        dot_count = 0

        while self.current_char != None and self.current_char in DIGITS + '.':
            if self.current_char == '.':
                if dot_count == 1: break
                dot_count += 1
                num_str += '.'
            else:
                num_str += self.current_char
            self.advance()

        if dot_count == 0:
            return Token(TT_INT, int(num_str))
        else:
            return Token(TT_FLOAT, float(num_str))


#######################################
# NODES
#######################################

class NumberNode:
    def __init__(self, tok):
        self.tok = tok

    def __repr__(self):
        return f'{self.tok}'

class BinOpNode:
    def __init__(self, lnode, op_tok, rnode):
        self.lnode = lnode
        self.op_tok = op_tok
        self.rnode = rnode

    def __repr__(self):
        return f'({self.lnode}, {self.op_tok}, {self.rnode})'


#######################################
# PARSER
#######################################

class Parser:
    def __init__(self, tokens):
        self.tokens = tokens
        self.tok_idx = -1
        self.advance()

    def advance(self):
        self.tok_idx += 1
        if self.tok_idx < len(self.tokens):
            self.cur_tok = self.tokens[self.tok_idx]
        return self.cur_tok

#############################################################

    def parse(self):
        res = self.expr()
        return res

    def factor(self):
        tok = self.cur_tok

        if tok.type in (TT_INT, TT_FLOAT):
            self.advance()
            node = NumberNode(tok)
            return node

    def term(self):
        return self.bin_op(self.factor(), (TT_MUL, TT_DIV))

    def expr(self):
        return self.bin_op(self.term(), (TT_PLUS, TT_MINUS))

    def bin_op(self, func, ops):
        left = func()

        while self.cur_tok.type in ops:
            op_tok = self.cur_tok
            self.advance()
            right = func()
            left = BinOpNode(left, op_tok, right)

        return left

#############################################################


#######################################
# RUN
#######################################

def run(fn, text):
    # Generate Tokens
    lexer = Lexer(fn, text)
    tokens, error = lexer.make_tokens()
    if error: return None, error

    # Generate AST
    parser = Parser(tokens)
    ast = parser.parse()

    return ast, None

第二个文件:

import basic as bs        # basic.py is the first file

while True:
    text = input('Basic > ')
    if text == 'exit': break
    result, error = bs.run('<stdin>', text)

    if error: print(error.as_string())
    else: print(result)

(我不知道如何使用语法高亮,对不起)

【问题讨论】:

  • 您可能希望将self.factor 而非self.factor() 传递给self.bin_op(基于参数名称,假设参数是函数/可调用的)。
  • 你有教程的链接吗?您可能没有正确复制某些内容。我怀疑应该是left = func 没有()

标签: python


猜你喜欢
  • 2019-08-27
  • 1970-01-01
  • 2021-05-26
  • 1970-01-01
  • 2021-02-23
  • 2015-12-19
  • 2020-10-03
  • 2017-09-19
  • 1970-01-01
相关资源
最近更新 更多