File size: 4,346 Bytes
d02548d
 
 
 
57aca7a
 
 
 
 
 
26b5c29
 
d02548d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26b5c29
 
 
d02548d
57aca7a
 
 
 
 
 
d02548d
 
 
26b5c29
 
 
 
 
 
d02548d
 
 
 
 
 
 
 
 
57aca7a
d02548d
57aca7a
d02548d
 
 
 
 
 
 
 
57aca7a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d02548d
 
57aca7a
d02548d
 
 
 
 
 
 
 
 
71df62b
 
57aca7a
 
 
 
 
 
 
 
 
d02548d
71df62b
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
from typing import List, Tuple, Any

Token = Tuple[str, str]

FUNCTIONS = {
    "MOVE_FORWARD", "MOVE_BACKWARD", "ROTATE", "STOP", "WAIT", "TURN_LEFT",
    "TURN_RIGHT", "TOGGLE_LIGHT", "CALIBRATE", "PRINT", "SET", "READ_SENSOR",
    "ACTIVATE_SENSOR", "DEACTIVATE_SENSOR", "START", "REBOOT", "SHUTDOWN"
}

TYPES = {"int", "float", "boolean"}

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] in TYPES:
            return self.declaration()
        elif token[0] == "IF":
            return self.if_statement()
        elif token[0] == "WHILE":
            return self.while_statement()
        elif token[0] in FUNCTIONS:
            return self.function_call()
        elif token[0] == "IDENTIFIER":
            return self.assignment()
        else:
            raise SyntaxError(f"Instrucci贸n no v谩lida: {token}")

    def declaration(self):
        tipo = self.match(self.current()[0])[0]
        nombre = self.match("IDENTIFIER")[1]
        self.match("SEMICOLON")
        return {"type": "declaration", "var": nombre, "datatype": tipo}

    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")
        self.match("OPEN_PAREN")
        condition = self.expression()
        self.match("CLOSE_PAREN")
        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 while_statement(self):
        self.match("WHILE")
        self.match("OPEN_PAREN")
        condition = self.expression()
        self.match("CLOSE_PAREN")
        self.match("THEN")
        self.match("OPEN_BRACE")
        body = []
        while self.current()[0] != "CLOSE_BRACE":
            body.append(self.instruction())
        self.match("CLOSE_BRACE")
        return {"type": "while", "condition": condition, "body": body}

    def function_call(self):
        func_name = self.current()[0]
        self.match(func_name)
        self.match("OPEN_PAREN")
        arg = None
        if self.current()[0] not in ("CLOSE_PAREN",):
            arg = self.expression()
        self.match("CLOSE_PAREN")
        self.match("SEMICOLON")
        return {"type": "function", "name": func_name, "arg": arg}

    def expression(self):
        left = self.term()
        while self.current()[0] in ("PLUS", "MINUS", "EQUAL", "NOT_EQUAL", "GREATER", "LESS", "AND", "OR"):
            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 in ("INT", "FLOAT"):
            return {"type": "num", "value": self.match(token_type)[1]}
        elif token_type in ("TRUE", "FALSE"):
            return {"type": "bool", "value": self.match(token_type)[0]}
        elif token_type == "STRING":
            return {"type": "string", "value": self.match("STRING")[1]}
        elif token_type == "OPEN_PAREN":
            self.match("OPEN_PAREN")
            expr = self.expression()
            self.match("CLOSE_PAREN")
            return expr
        else:
            raise SyntaxError(f"Expresi贸n inv谩lida: {self.current()}")