简体   繁体   English

如何避免在不使用 python 中说 function 的情况下打印变量?

[英]How to avoid printing a variable without using the say function in python sly?

So I am using a python package sly which has a lexer and parser class.所以我正在使用 python package sly ,它有一个词法分析器和解析器 class。 I am making my own programming language called NoobPy.我正在制作自己的编程语言,称为 NoobPy。 So currently, the code will open test.noob and read each line and parse it.所以目前,代码将打开 test.noob 并读取每一行并解析它。 Now, if I were to define a variable, let's say x , and just write x in a line, it would print it, and I don't want that.现在,如果我要定义一个变量,比方说x ,只需将x写在一行中,它就会打印它,而我不希望这样。 I want it to print only if it's passed in the say function which I made.我希望它仅在我制作的say中通过时才打印。 Lexer class莱克斯 class

class NoobpyLexer(Lexer):
    tokens = {NUMBER, STRING, FALSE, TRUE, NAME, WHILE, IF, ELSE, SAY,
              PLUS, MINUS, TIMES, DIVIDE, ASSIGN,
              EQ, LT, LE, GT, GE, NEQ}

    literals = {'(', ')', ':'}

    # String containing ignored characters
    ignore = ' \t'

    # Regular expression rules for tokens
    STRING = r'\".*?\"'
    PLUS = r'\+'
    MINUS = r'-'
    TIMES = r'\*'
    DIVIDE = r'/'
    EQ = r'=='
    NEQ = r'!='
    ASSIGN = r'='
    LE = r'<='
    GE = r'>='
    LT = r'<'
    GT = r'>'

    @_(r'\d+')
    def NUMBER(self, t):
        t.value = int(t.value)
        return t

    # @_(r'^((true$|false$)$)')
    # def BOOL(self, t):
    #     return t

    @_(r'true')
    def TRUE(self, t):
        return t

    @_(r'false')
    def FALSE(self, t):
        return t

    # Identifiers and keywords
    NAME = r'\b(?!((true$|false$)$)\b)\w+'  # [a-zA-Z_][a-zA-Z0-9_]*$
    NAME['if'] = IF
    NAME['else'] = ELSE
    NAME['while'] = WHILE
    NAME['say'] = SAY

    ignore_comment = r'\#.*'

    # Line number tracking
    @_(r'\n+')
    def ignore_newline(self, t):
        self.lineno += t.value.count('\n')

    def error(self, t):
        print("t: ", t)
        print('Line %d: Bad character %r' % (self.lineno, t.value[0]))
        self.index += 1

Parser class解析器 class

class NoobpyParser(Parser):
    # Get the token list from the lexer (required)
    tokens = NoobpyLexer.tokens
    log = logging.getLogger()
    log.setLevel(logging.ERROR)
    # debugfile = 'parser.out'

    precedence = (
        ('left', PLUS, MINUS),
        ('left', TIMES, DIVIDE),
        ('right', UMINUS)
    )

    def __init__(self):
        self.variables = {}

    @_('')
    def statement(self, p):
        pass

    @_('SAY expr')
    def statement(self, p):
        return 'say', p.expr

    @_('NAME')
    def expr(self, p):
        return 'var', p.NAME

    @_('var_assign')
    def statement(self, p):
        return p.var_assign

    @_('NAME ASSIGN expr')
    def var_assign(self, p):
        return 'var_assign', p.NAME, p.expr

    @_('expr')
    def statement(self, p):
        return p.expr

    @_('expr PLUS expr')
    def expr(self, p):
        return 'add', p.expr0, p.expr1

    @_('expr MINUS expr')
    def expr(self, p):
        return 'sub', p.expr0, p.expr1

    @_('expr TIMES expr')
    def expr(self, p):
        return 'mul', p.expr0, p.expr1

    @_('expr DIVIDE expr')
    def expr(self, p):
        return 'div', p.expr0, p.expr1

    @_('MINUS expr %prec UMINUS')
    def expr(self, p):
        expression = list(p.expr)
        if isinstance(expression[1], tuple):
            res = 0
            for i in expression[1]:
                res += i
            expression[1] = res
        expression[1] = -expression[1]
        return expression

    @_('expr EQ expr')
    def expr(self, p):
        return 'eq', p.expr0, p.expr1

    @_('"(" expr ")"')
    def expr(self, p):
        return p.expr

    @_('NUMBER')
    def expr(self, p):
        return 'num', p.NUMBER

    @_('STRING')
    def expr(self, p):
        return 'str', p.STRING

    @_('TRUE')
    def expr(self, p):
        return p.TRUE

    @_('FALSE')
    def expr(self, p):
        return p.FALSE

Execute class执行 class

class NoobpyExecute:
    def __init__(self, tree, variables):
        self.variables = variables
        result = self.walkTree(tree)
        if result is None:
            pass
        elif result is not None and type(result) in [int, float]:
            print(result)
        elif isinstance(result, str):
            print(result)
        elif isinstance(result, bool):
            if result is True:
                print("true")
            else:
                print("false")

    def walkTree(self, node):
        if isinstance(node, int):
            return node
        if isinstance(node, str):
            return node

        if node is None:
            return None

        if node[0] == 'say':
            return self.walkTree(node[1])
        if node[0] == 'num':
            return node[1]
        if node[0] == 'str':
            return node[1]
        if node[0] == 'eq':
            return self.walkTree(node[1]) == self.walkTree(node[2])

        if node[0] == 'add':
            return self.walkTree(node[1]) + self.walkTree(node[2])
        elif node[0] == 'sub':
            return self.walkTree(node[1]) - self.walkTree(node[2])
        elif node[0] == 'mul':
            return self.walkTree(node[1]) * self.walkTree(node[2])
        elif node[0] == 'div':
            return self.walkTree(node[1]) / self.walkTree(node[2])

        if node[0] == 'var_assign':
            self.variables[node[1]] = self.walkTree(node[2])

        if node[0] == 'var':
            try:
                return self.variables[node[1]]
            except LookupError:
                print("Undefined name '{}'".format(node[1]))
                return 0

This:这个:

if __name__ == '__main__':
    lexer = NoobpyLexer()
    parser = NoobpyParser()
    variables = {}

    args = argparse.ArgumentParser()
    args.add_argument(metavar='filename', dest="filename", type=str, help='name of the file you want to run')
    args = args.parse_args()

    with open(args.filename) as file:
        for line in file.readlines():
            tree = parser.parse(lexer.tokenize(line))
            NoobpyExecute(tree, variables)

Example test.noob示例 test.noob

x = 2
x

^ prints 2 ^ 打印 2

In your NoobPy constructor, you print out the result of evaluating the syntax tree (unless it's None, which will happen if you evaluate an assignment):在你的NoobPy构造函数中,你打印出评估语法树的结果(除非它是 None,如果你评估一个赋值,就会发生这种情况):

        if result is None:
            pass
        elif result is not None and type(result) in [int, float]:
            print(result)
        elif isinstance(result, str):
            print(result)
        elif isinstance(result, bool):
            if result is True:
                print("true")
            else:
                print("false")

Leaving aside the fact that all that could be simplified, the code seems to clearly indicate that the intention of printing the result of the evaluation.撇开所有可以简化的事实不谈,代码似乎清楚地表明了打印评估结果的意图。 If you now don't want to print the result of the evaluation, you shouldn't print the result of the evaluation.如果您现在不想打印评估结果,则不应打印评估结果。

When you see a say function in the tree, you return the result of evaluating its argument:当您在树中看到say时,您返回评估其参数的结果:

        if node[0] == 'say':
            return self.walkTree(node[1]) 

If you want the say function to have the effect of printing the result of the evaluation of its argument, you should print the result of the evaluation of its argument instead of returning the result of the evaluation of its argument (or as well as returning the result, depending on what you think the semantics of say are).如果您希望say function 具有打印其参数的评估结果的效果,您应该打印其参数的评估结果而不是返回其参数的评估结果(或返回结果,取决于您认为say的语义是什么)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM