File size: 2,266 Bytes
d02548d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
from typing import List, Tuple, Any

Token = Tuple[str, str]

class Parser:
    def __init__(self, tokens: List[Token]):
        self.tokens = tokens
        self.pos = 0
        self.ast = []

    def current(self) -> Token:
        return self.tokens[self.pos] if self.pos < len(self.tokens) else ("EOF", "")

    def match(self, expected_type: str) -> Token:
        if self.current()[0] == expected_type:
            tok = self.current()
            self.pos += 1
            return tok
        raise SyntaxError(f"Se esperaba {expected_type} pero se encontr贸 {self.current()}")

    def parse(self):
        while self.current()[0] != "EOF":
            self.ast.append(self.instruction())
        return self.ast

    def instruction(self) -> Any:
        token = self.current()
        if token[0] == "IDENTIFIER":
            return self.assignment()
        elif token[0] == "IF":
            return self.if_statement()
        else:
            raise SyntaxError(f"Instrucci贸n no v谩lida: {token}")

    def assignment(self):
        ident = self.match("IDENTIFIER")[1]
        self.match("ASSIGN")
        expr = self.expression()
        self.match("SEMICOLON")
        return {"type": "assign", "var": ident, "value": expr}

    def if_statement(self):
        self.match("IF")
        condition = self.expression()
        self.match("THEN")
        self.match("OPEN_BRACE")
        body = []
        while self.current()[0] != "CLOSE_BRACE":
            body.append(self.instruction())
        self.match("CLOSE_BRACE")
        return {"type": "if", "condition": condition, "body": body}

    def expression(self):
        left = self.term()
        while self.current()[0] in ("PLUS", "MINUS"):
            op = self.match(self.current()[0])[0]
            right = self.term()
            left = {"type": "binop", "op": op, "left": left, "right": right}
        return left

    def term(self):
        token_type, token_value = self.current()
        if token_type == "IDENTIFIER":
            return {"type": "var", "value": self.match("IDENTIFIER")[1]}
        elif token_type == "NUMERO":
            return {"type": "num", "value": self.match("NUMERO")[1]}
        else:
            raise SyntaxError(f"Expresi贸n inv谩lida: {self.current()}")