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