File size: 6,163 Bytes
d02548d
 
 
 
57aca7a
0179803
 
 
 
 
 
 
 
57aca7a
 
26b5c29
 
d02548d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26b5c29
 
 
d02548d
57aca7a
 
 
 
 
 
d02548d
 
 
26b5c29
 
 
 
 
 
d02548d
 
 
 
 
 
 
 
 
57aca7a
d02548d
57aca7a
d02548d
 
 
 
 
 
 
 
57aca7a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0179803
f9ada29
 
 
 
 
0179803
f9ada29
 
 
 
 
 
 
 
0179803
f9ada29
419af58
 
f9ada29
57aca7a
f9ada29
 
 
0179803
f9ada29
419af58
 
f9ada29
 
0179803
f9ada29
 
 
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
from typing import List, Tuple, Any

Token = Tuple[str, str]

FUNCTIONS = {
    "ACTIVATE_ALARM", "ACTIVATE_SENSOR", "BREAK", "CHARGE_BATTERY", "CHECK_BATTERY",
    "CLOSE_DOOR", "CONTINUE", "DEACTIVATE_ALARM", "DEACTIVATE_SENSOR", "DECREASE_SPEED",
    "DOWNLOAD", "REBOOT", "READ_SENSOR", "RESET", "RESUME", "REVERSE", "SHUTDOWN",
    "SHUT_OFF", "START", "STOP", "STOP_IMMEDIATELY", "TOGGLE_LIGHT", "TURN_DOWN",
    "TURN_LEFT", "TURN_RIGHT", "TURN_UP", "UNLOCK", "LOG", "INIT", "LOCK", "LOW_BATTERY",
    "OPEN_DOOR", "PAUSE", "CALIBRATE", "COPY_FILE", "DELETE_FILE", "MOVE_BACKWARD",
    "MOVE_FORWARD", "MOVE_TO", "PRINT", "RENAME_FILE", "ROTATE", "SAVE_FILE", "SCAN",
    "SET", "SET_SPEED", "UPLOAD", "UPLOAD_FILE", "WAIT"
}

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)

        funciones_con_argumento = {
            "CALIBRATE", "COPY_FILE", "DELETE_FILE", "MOVE_BACKWARD", "MOVE_FORWARD", "MOVE_TO",
            "PRINT", "RENAME_FILE", "ROTATE", "SAVE_FILE", "SCAN", "SET", "SET_SPEED", "UPLOAD",
            "UPLOAD_FILE", "WAIT"
        }

        funciones_sin_argumento = {
            "ACTIVATE_ALARM", "ACTIVATE_SENSOR", "BREAK", "CHARGE_BATTERY", "CHECK_BATTERY",
            "CLOSE_DOOR", "CONTINUE", "DEACTIVATE_ALARM", "DEACTIVATE_SENSOR", "DECREASE_SPEED",
            "DOWNLOAD", "REBOOT", "READ_SENSOR", "RESET", "RESUME", "REVERSE", "SHUTDOWN",
            "SHUT_OFF", "START", "STOP", "STOP_IMMEDIATELY", "TOGGLE_LIGHT", "TURN_DOWN",
            "TURN_LEFT", "TURN_RIGHT", "TURN_UP", "UNLOCK", "LOG", "INIT", "LOCK", "LOW_BATTERY",
            "OPEN_DOOR", "PAUSE"
        }

        if func_name in funciones_con_argumento:
            if self.current()[0] != "OPEN_PAREN":
                raise SyntaxError(f"La funci贸n '{func_name}' requiere un argumento entre par茅ntesis.")
            self.match("OPEN_PAREN")
            arg = self.expression()
            self.match("CLOSE_PAREN")
            self.match("SEMICOLON")
            return {"type": "function", "name": func_name, "arg": arg}

        elif func_name in funciones_sin_argumento:
            if self.current()[0] == "OPEN_PAREN":
                raise SyntaxError(f"La funci贸n '{func_name}' no debe llevar argumentos ni par茅ntesis.")
            self.match("SEMICOLON")
            return {"type": "function", "name": func_name, "arg": None}

        else:
            raise SyntaxError(f"Funci贸n '{func_name}' no reconocida o mal definida.")

    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()}")