0

I'm trying to parse a text with the Shunting-yard algorithm but I've come across a problem. I don't know where to start parsing functions.

This is my goal: print('Hello ' + in())

The current tokens: [ID print, LPAREN, STRING "Hello ", PLUS, ID in, LPAREN, RPAREN, RPAREN]

My current parser:

class Parser:
    def __init__(self, tokens:list, variables:dict):
        self.tokens = tokens
        self.idx = -1
        self.tok = None
        self.variables = variables
        self.value_stack = []
        self.operator_stack = []
        self.next_token()

    def next_token(self):
        self.idx += 1
        self.tok = self.tokens[self.idx] if self.idx < len(self.tokens) else None

    def pop(self):
        newop = self.operator_stack.pop()
        val1 = self.value_stack.pop()
        val2 = self.value_stack.pop()

        self.value_stack.append(eval_(val1, val2, newop))

    def parse(self):
        while self.tok:
            if self.tok.type in VALUE_TYPE:
                self.value_stack.append(self.tok.value)

            elif self.tok.type == TT_ID:
                self.id()
                continue

            elif self.tok.type == TT_LPAREN:
                self.operator_stack.append(TT_LPAREN)

            elif self.tok.type in OPERATORS:
                op = self.tok.type

                while self.operator_stack and PRESCEDENCE.get(self.operator_stack[-1], 0) >= PRESCEDENCE.get(op, 0):
                    self.pop()
                
                self.operator_stack.append(op)

            elif self.tok.type == TT_RPAREN:
                while self.operator_stack and self.operator_stack[-1] != TT_LPAREN:
                    self.pop()
                
                self.operator_stack.pop()

            self.next_token()

        while self.operator_stack:
            self.pop()

        return self.value_stack[-1] if self.value_stack else None

    def id(self):
        tok = self.tok
        self.next_token()

        if not self.tok: return

        if self.tok.type == TT_EQUALS:
            self.next_token()
            self.variables[tok.value] = self.parse()

        elif self.tok.type == TT_LPAREN:
            self.operator_stack.append(tok.value)

        else:
            self.value_stack.append(self.variables.get(tok.value, 'null'))

How would I implement function handling? Every time I try to execute a function I get this error:

Traceback (most recent call last):
  File "lang.py", line 19, in <module>
    out = evaluate(text, variables)
  File "lang.py", line 10, in evaluate
    parser.parse()
  File "parsing.py", line 85, in parse
    self.pop()
  File "parsing.py", line 52, in pop
    val2 = self.value_stack.pop()
IndexError: pop from empty list

Any help is appreciated.

  • Here are some similar questions to check out: [Shunting-yard algorithm with trigonometric functions](https://stackoverflow.com/questions/13532309/shunting-yard-algorithm-with-trigonometric-functions), [Handling extra operators in shunting-yard](https://stackoverflow.com/a/16392115/1566221), and maybe [Shunting-yard algorithm with function support](https://stackoverflow.com/q/58595603/1566221). – rici Mar 14 '21 at 23:16
  • I've seen all of these questions but none of them help me understand the process of which I need to take. –  Mar 15 '21 at 00:33

0 Answers0