diff --git a/example/LISPtoPOSFIX/LICENSE b/example/LISPtoPOSFIX/LICENSE new file mode 100644 index 0000000..bc16ae5 --- /dev/null +++ b/example/LISPtoPOSFIX/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Gabriel Fredes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/example/LISPtoPOSFIX/__pycache__/ast.cpython-311.pyc b/example/LISPtoPOSFIX/__pycache__/ast.cpython-311.pyc new file mode 100644 index 0000000..addc9ff Binary files /dev/null and b/example/LISPtoPOSFIX/__pycache__/ast.cpython-311.pyc differ diff --git a/example/LISPtoPOSFIX/__pycache__/parsetab.cpython-311.pyc b/example/LISPtoPOSFIX/__pycache__/parsetab.cpython-311.pyc new file mode 100644 index 0000000..edbfad4 Binary files /dev/null and b/example/LISPtoPOSFIX/__pycache__/parsetab.cpython-311.pyc differ diff --git a/example/LISPtoPOSFIX/__pycache__/tokenizer.cpython-311.pyc b/example/LISPtoPOSFIX/__pycache__/tokenizer.cpython-311.pyc new file mode 100644 index 0000000..0e3f8a6 Binary files /dev/null and b/example/LISPtoPOSFIX/__pycache__/tokenizer.cpython-311.pyc differ diff --git a/example/LISPtoPOSFIX/__pycache__/trabalho.cpython-311.pyc b/example/LISPtoPOSFIX/__pycache__/trabalho.cpython-311.pyc new file mode 100644 index 0000000..6c3acd0 Binary files /dev/null and b/example/LISPtoPOSFIX/__pycache__/trabalho.cpython-311.pyc differ diff --git a/example/LISPtoPOSFIX/input.txt b/example/LISPtoPOSFIX/input.txt new file mode 100644 index 0000000..518f4cc --- /dev/null +++ b/example/LISPtoPOSFIX/input.txt @@ -0,0 +1 @@ +(/ 10 (* (+ 10 -5) 2)) \ No newline at end of file diff --git a/example/LISPtoPOSFIX/parser.out b/example/LISPtoPOSFIX/parser.out new file mode 100644 index 0000000..9de2d8a --- /dev/null +++ b/example/LISPtoPOSFIX/parser.out @@ -0,0 +1,286 @@ +Created by PLY version 3.11 (http://www.dabeaz.com/ply) + +Grammar + +Rule 0 S' -> E +Rule 1 E -> ABRE_PAREN MAIS E E FECHA_PAREN +Rule 2 E -> ABRE_PAREN MENOS E E FECHA_PAREN +Rule 3 E -> ABRE_PAREN VEZES E E FECHA_PAREN +Rule 4 E -> ABRE_PAREN DIVIDIR E E FECHA_PAREN +Rule 5 E -> ID +Rule 6 E -> NUMERO + +Terminals, with rules where they appear + +ABRE_PAREN : 1 2 3 4 +DIVIDIR : 4 +FECHA_PAREN : 1 2 3 4 +ID : 5 +MAIS : 1 +MENOS : 2 +NUMERO : 6 +VEZES : 3 +error : + +Nonterminals, with rules where they appear + +E : 1 1 2 2 3 3 4 4 0 + +Parsing method: LALR + +state 0 + + (0) S' -> . E + (1) E -> . ABRE_PAREN MAIS E E FECHA_PAREN + (2) E -> . ABRE_PAREN MENOS E E FECHA_PAREN + (3) E -> . ABRE_PAREN VEZES E E FECHA_PAREN + (4) E -> . ABRE_PAREN DIVIDIR E E FECHA_PAREN + (5) E -> . ID + (6) E -> . NUMERO + + ABRE_PAREN shift and go to state 2 + ID shift and go to state 3 + NUMERO shift and go to state 4 + + E shift and go to state 1 + +state 1 + + (0) S' -> E . + + + +state 2 + + (1) E -> ABRE_PAREN . MAIS E E FECHA_PAREN + (2) E -> ABRE_PAREN . MENOS E E FECHA_PAREN + (3) E -> ABRE_PAREN . VEZES E E FECHA_PAREN + (4) E -> ABRE_PAREN . DIVIDIR E E FECHA_PAREN + + MAIS shift and go to state 5 + MENOS shift and go to state 6 + VEZES shift and go to state 7 + DIVIDIR shift and go to state 8 + + +state 3 + + (5) E -> ID . + + $end reduce using rule 5 (E -> ID .) + ABRE_PAREN reduce using rule 5 (E -> ID .) + ID reduce using rule 5 (E -> ID .) + NUMERO reduce using rule 5 (E -> ID .) + FECHA_PAREN reduce using rule 5 (E -> ID .) + + +state 4 + + (6) E -> NUMERO . + + $end reduce using rule 6 (E -> NUMERO .) + ABRE_PAREN reduce using rule 6 (E -> NUMERO .) + ID reduce using rule 6 (E -> NUMERO .) + NUMERO reduce using rule 6 (E -> NUMERO .) + FECHA_PAREN reduce using rule 6 (E -> NUMERO .) + + +state 5 + + (1) E -> ABRE_PAREN MAIS . E E FECHA_PAREN + (1) E -> . ABRE_PAREN MAIS E E FECHA_PAREN + (2) E -> . ABRE_PAREN MENOS E E FECHA_PAREN + (3) E -> . ABRE_PAREN VEZES E E FECHA_PAREN + (4) E -> . ABRE_PAREN DIVIDIR E E FECHA_PAREN + (5) E -> . ID + (6) E -> . NUMERO + + ABRE_PAREN shift and go to state 2 + ID shift and go to state 3 + NUMERO shift and go to state 4 + + E shift and go to state 9 + +state 6 + + (2) E -> ABRE_PAREN MENOS . E E FECHA_PAREN + (1) E -> . ABRE_PAREN MAIS E E FECHA_PAREN + (2) E -> . ABRE_PAREN MENOS E E FECHA_PAREN + (3) E -> . ABRE_PAREN VEZES E E FECHA_PAREN + (4) E -> . ABRE_PAREN DIVIDIR E E FECHA_PAREN + (5) E -> . ID + (6) E -> . NUMERO + + ABRE_PAREN shift and go to state 2 + ID shift and go to state 3 + NUMERO shift and go to state 4 + + E shift and go to state 10 + +state 7 + + (3) E -> ABRE_PAREN VEZES . E E FECHA_PAREN + (1) E -> . ABRE_PAREN MAIS E E FECHA_PAREN + (2) E -> . ABRE_PAREN MENOS E E FECHA_PAREN + (3) E -> . ABRE_PAREN VEZES E E FECHA_PAREN + (4) E -> . ABRE_PAREN DIVIDIR E E FECHA_PAREN + (5) E -> . ID + (6) E -> . NUMERO + + ABRE_PAREN shift and go to state 2 + ID shift and go to state 3 + NUMERO shift and go to state 4 + + E shift and go to state 11 + +state 8 + + (4) E -> ABRE_PAREN DIVIDIR . E E FECHA_PAREN + (1) E -> . ABRE_PAREN MAIS E E FECHA_PAREN + (2) E -> . ABRE_PAREN MENOS E E FECHA_PAREN + (3) E -> . ABRE_PAREN VEZES E E FECHA_PAREN + (4) E -> . ABRE_PAREN DIVIDIR E E FECHA_PAREN + (5) E -> . ID + (6) E -> . NUMERO + + ABRE_PAREN shift and go to state 2 + ID shift and go to state 3 + NUMERO shift and go to state 4 + + E shift and go to state 12 + +state 9 + + (1) E -> ABRE_PAREN MAIS E . E FECHA_PAREN + (1) E -> . ABRE_PAREN MAIS E E FECHA_PAREN + (2) E -> . ABRE_PAREN MENOS E E FECHA_PAREN + (3) E -> . ABRE_PAREN VEZES E E FECHA_PAREN + (4) E -> . ABRE_PAREN DIVIDIR E E FECHA_PAREN + (5) E -> . ID + (6) E -> . NUMERO + + ABRE_PAREN shift and go to state 2 + ID shift and go to state 3 + NUMERO shift and go to state 4 + + E shift and go to state 13 + +state 10 + + (2) E -> ABRE_PAREN MENOS E . E FECHA_PAREN + (1) E -> . ABRE_PAREN MAIS E E FECHA_PAREN + (2) E -> . ABRE_PAREN MENOS E E FECHA_PAREN + (3) E -> . ABRE_PAREN VEZES E E FECHA_PAREN + (4) E -> . ABRE_PAREN DIVIDIR E E FECHA_PAREN + (5) E -> . ID + (6) E -> . NUMERO + + ABRE_PAREN shift and go to state 2 + ID shift and go to state 3 + NUMERO shift and go to state 4 + + E shift and go to state 14 + +state 11 + + (3) E -> ABRE_PAREN VEZES E . E FECHA_PAREN + (1) E -> . ABRE_PAREN MAIS E E FECHA_PAREN + (2) E -> . ABRE_PAREN MENOS E E FECHA_PAREN + (3) E -> . ABRE_PAREN VEZES E E FECHA_PAREN + (4) E -> . ABRE_PAREN DIVIDIR E E FECHA_PAREN + (5) E -> . ID + (6) E -> . NUMERO + + ABRE_PAREN shift and go to state 2 + ID shift and go to state 3 + NUMERO shift and go to state 4 + + E shift and go to state 15 + +state 12 + + (4) E -> ABRE_PAREN DIVIDIR E . E FECHA_PAREN + (1) E -> . ABRE_PAREN MAIS E E FECHA_PAREN + (2) E -> . ABRE_PAREN MENOS E E FECHA_PAREN + (3) E -> . ABRE_PAREN VEZES E E FECHA_PAREN + (4) E -> . ABRE_PAREN DIVIDIR E E FECHA_PAREN + (5) E -> . ID + (6) E -> . NUMERO + + ABRE_PAREN shift and go to state 2 + ID shift and go to state 3 + NUMERO shift and go to state 4 + + E shift and go to state 16 + +state 13 + + (1) E -> ABRE_PAREN MAIS E E . FECHA_PAREN + + FECHA_PAREN shift and go to state 17 + + +state 14 + + (2) E -> ABRE_PAREN MENOS E E . FECHA_PAREN + + FECHA_PAREN shift and go to state 18 + + +state 15 + + (3) E -> ABRE_PAREN VEZES E E . FECHA_PAREN + + FECHA_PAREN shift and go to state 19 + + +state 16 + + (4) E -> ABRE_PAREN DIVIDIR E E . FECHA_PAREN + + FECHA_PAREN shift and go to state 20 + + +state 17 + + (1) E -> ABRE_PAREN MAIS E E FECHA_PAREN . + + $end reduce using rule 1 (E -> ABRE_PAREN MAIS E E FECHA_PAREN .) + ABRE_PAREN reduce using rule 1 (E -> ABRE_PAREN MAIS E E FECHA_PAREN .) + ID reduce using rule 1 (E -> ABRE_PAREN MAIS E E FECHA_PAREN .) + NUMERO reduce using rule 1 (E -> ABRE_PAREN MAIS E E FECHA_PAREN .) + FECHA_PAREN reduce using rule 1 (E -> ABRE_PAREN MAIS E E FECHA_PAREN .) + + +state 18 + + (2) E -> ABRE_PAREN MENOS E E FECHA_PAREN . + + $end reduce using rule 2 (E -> ABRE_PAREN MENOS E E FECHA_PAREN .) + ABRE_PAREN reduce using rule 2 (E -> ABRE_PAREN MENOS E E FECHA_PAREN .) + ID reduce using rule 2 (E -> ABRE_PAREN MENOS E E FECHA_PAREN .) + NUMERO reduce using rule 2 (E -> ABRE_PAREN MENOS E E FECHA_PAREN .) + FECHA_PAREN reduce using rule 2 (E -> ABRE_PAREN MENOS E E FECHA_PAREN .) + + +state 19 + + (3) E -> ABRE_PAREN VEZES E E FECHA_PAREN . + + $end reduce using rule 3 (E -> ABRE_PAREN VEZES E E FECHA_PAREN .) + ABRE_PAREN reduce using rule 3 (E -> ABRE_PAREN VEZES E E FECHA_PAREN .) + ID reduce using rule 3 (E -> ABRE_PAREN VEZES E E FECHA_PAREN .) + NUMERO reduce using rule 3 (E -> ABRE_PAREN VEZES E E FECHA_PAREN .) + FECHA_PAREN reduce using rule 3 (E -> ABRE_PAREN VEZES E E FECHA_PAREN .) + + +state 20 + + (4) E -> ABRE_PAREN DIVIDIR E E FECHA_PAREN . + + $end reduce using rule 4 (E -> ABRE_PAREN DIVIDIR E E FECHA_PAREN .) + ABRE_PAREN reduce using rule 4 (E -> ABRE_PAREN DIVIDIR E E FECHA_PAREN .) + ID reduce using rule 4 (E -> ABRE_PAREN DIVIDIR E E FECHA_PAREN .) + NUMERO reduce using rule 4 (E -> ABRE_PAREN DIVIDIR E E FECHA_PAREN .) + FECHA_PAREN reduce using rule 4 (E -> ABRE_PAREN DIVIDIR E E FECHA_PAREN .) + diff --git a/example/LISPtoPOSFIX/parser_lf.py b/example/LISPtoPOSFIX/parser_lf.py new file mode 100644 index 0000000..d465a41 --- /dev/null +++ b/example/LISPtoPOSFIX/parser_lf.py @@ -0,0 +1,158 @@ +import ply.lex as lex +import ply.yacc as yacc + +# Tokenizer +# Lista com nome dos tokens +tokens = ( + "ID", + "NUMERO", + "MAIS", + "MENOS", + "VEZES", + "DIVIDIR", + "ABRE_PAREN", + "FECHA_PAREN", +) + +# Expressões regulares para os tokens +# t_ é um prefixo especial (palavra reservada) que indica que a função é um token + +t_MAIS = r"\+" +t_MENOS = r"-" # O sinal de menos é um token separado para evitar ambiguidade +t_VEZES = r"\*" +t_DIVIDIR = r"/" # O sinal de divisão é um token separado para evitar ambiguidade +t_ABRE_PAREN = r"\(" +t_FECHA_PAREN = r"\)" + + +# Função para tratar números +def t_NUMERO(t): + r'-?\d+(\.\d+)?' + t.value = int(t.value) # Considera positivo ou negativo e float + return t + +# Função para tratar ID +def t_ID(t): + r"-?[a-zA-Z]+" # Apenas letras do alfabeto portugues (podendo ser negativo) + return t + +# Ignorar espaços em branco +t_ignore = " \t" + +# Ignorar comentários +def t_COMENTARIO(t): + r'\#.*' + pass + +# Numero da linha +def t_newline(t): + r"\n+" + t.lexer.lineno += len( + t.value + ) # Incrementa o número da linha para cada nova linha encontrada + # lexer é um objeto global que contém informações sobre o estado do analisador léxico + # lineno é um atributo de lexer que armazena o número da linha atual + + +# Tratamento de erro +def t_error(t): + print("O caractere ilegal '%s' foi pulado" % t.value[0]) + t.lexer.skip(1) # Pula o caractere ilegal + +# Construir o lexer +lexer = lex.lex() + +#################### +# Classes Tree # +#################### +#################### +# Não interferem # +# Na análise # +# É só para arvore # +#################### +class ASTNode: + pass + +class BinaryOpNode(ASTNode): + def __init__(self, op, left, right): + self.op = op + self.left = left + self.right = right + + def __repr__(self): + return f"({self.op} {self.left} {self.right})" + +class IdNode(ASTNode): + def __init__(self, name): + self.name = name + + def __repr__(self): + return self.name + +class NumberNode(ASTNode): + def __init__(self, value): + self.value = value + + def __repr__(self): + return str(self.value) + +def print_tree(node, indent="", is_right=False): + if isinstance(node, BinaryOpNode): + op_str = f"{indent}{'└─' if is_right else '├─'}{node.op}" + print(op_str) + new_indent = indent + (" " if is_right else "│ ") + print_tree(node.left, new_indent, False) + print_tree(node.right, new_indent, True) + elif isinstance(node, IdNode) or isinstance(node, NumberNode): + node_str = f"{indent}{'└─' if is_right else '├─'}{node}" + print(node_str) + +def tradutor_toposfix(node): + if isinstance(node, BinaryOpNode): + left_expr = tradutor_toposfix(node.left) + right_expr = tradutor_toposfix(node.right) + return f"{left_expr} {right_expr} {node.op}" + elif isinstance(node, IdNode): + return node.name + elif isinstance(node, NumberNode): + return str(node.value) + +################## +# --- Parser --- # +################## + +# Regras de produção +def p_E_binop(p): + '''E : ABRE_PAREN MAIS E E FECHA_PAREN + | ABRE_PAREN MENOS E E FECHA_PAREN + | ABRE_PAREN VEZES E E FECHA_PAREN + | ABRE_PAREN DIVIDIR E E FECHA_PAREN''' + p[0] = BinaryOpNode(p[2], p[3], p[4]) + +def p_E_id(p): + 'E : ID' + p[0] = IdNode(p[1]) + +def p_E_numero(p): + 'E : NUMERO' + p[0] = NumberNode(p[1]) + +def p_error(p): + print(f'Erro de sintaxe: {p.value!r}') + +# Construir o parser +parser = yacc.yacc() + +# Função para analisar a entrada do arquivo input.txt +arquivo = open('LISPtoPOSFIX/input.txt', 'r') +entrada = arquivo.read() +arquivo.close() + +# Chama o parser para entrada lida +ast = parser.parse(entrada) +print("Entrada: %s\nÁrvore:" % ast) +# Imprime a árvore +print_tree(ast) +# Imprime a expressão pós-fixa +print("Pósfixada: %s" % tradutor_toposfix(ast)) + diff --git a/example/LISPtoPOSFIX/parsetab.py b/example/LISPtoPOSFIX/parsetab.py new file mode 100644 index 0000000..24a2607 --- /dev/null +++ b/example/LISPtoPOSFIX/parsetab.py @@ -0,0 +1,36 @@ + +# parsetab.py +# This file is automatically generated. Do not edit. +# pylint: disable=W,C,R +_tabversion = '3.10' + +_lr_method = 'LALR' + +_lr_signature = 'ABRE_PAREN DIVIDIR FECHA_PAREN ID MAIS MENOS NUMERO VEZESE : ABRE_PAREN MAIS E E FECHA_PAREN\n | ABRE_PAREN MENOS E E FECHA_PAREN\n | ABRE_PAREN VEZES E E FECHA_PAREN\n | ABRE_PAREN DIVIDIR E E FECHA_PARENE : IDE : NUMERO' + +_lr_action_items = {'ABRE_PAREN':([0,3,4,5,6,7,8,9,10,11,12,17,18,19,20,],[2,-5,-6,2,2,2,2,2,2,2,2,-1,-2,-3,-4,]),'ID':([0,3,4,5,6,7,8,9,10,11,12,17,18,19,20,],[3,-5,-6,3,3,3,3,3,3,3,3,-1,-2,-3,-4,]),'NUMERO':([0,3,4,5,6,7,8,9,10,11,12,17,18,19,20,],[4,-5,-6,4,4,4,4,4,4,4,4,-1,-2,-3,-4,]),'$end':([1,3,4,17,18,19,20,],[0,-5,-6,-1,-2,-3,-4,]),'MAIS':([2,],[5,]),'MENOS':([2,],[6,]),'VEZES':([2,],[7,]),'DIVIDIR':([2,],[8,]),'FECHA_PAREN':([3,4,13,14,15,16,17,18,19,20,],[-5,-6,17,18,19,20,-1,-2,-3,-4,]),} + +_lr_action = {} +for _k, _v in _lr_action_items.items(): + for _x,_y in zip(_v[0],_v[1]): + if not _x in _lr_action: _lr_action[_x] = {} + _lr_action[_x][_k] = _y +del _lr_action_items + +_lr_goto_items = {'E':([0,5,6,7,8,9,10,11,12,],[1,9,10,11,12,13,14,15,16,]),} + +_lr_goto = {} +for _k, _v in _lr_goto_items.items(): + for _x, _y in zip(_v[0], _v[1]): + if not _x in _lr_goto: _lr_goto[_x] = {} + _lr_goto[_x][_k] = _y +del _lr_goto_items +_lr_productions = [ + ("S' -> E","S'",1,None,None,None), + ('E -> ABRE_PAREN MAIS E E FECHA_PAREN','E',5,'p_E_binop','parser_lf.py',126), + ('E -> ABRE_PAREN MENOS E E FECHA_PAREN','E',5,'p_E_binop','parser_lf.py',127), + ('E -> ABRE_PAREN VEZES E E FECHA_PAREN','E',5,'p_E_binop','parser_lf.py',128), + ('E -> ABRE_PAREN DIVIDIR E E FECHA_PAREN','E',5,'p_E_binop','parser_lf.py',129), + ('E -> ID','E',1,'p_E_id','parser_lf.py',133), + ('E -> NUMERO','E',1,'p_E_numero','parser_lf.py',137), +]