def parse(self, string): self.lexer(string) self._token_list = [ 'ANSWER', 'OPTION', 'QUESTION', 'TRUE_VALUE', 'FALSE_VALUE', 'LBRACKET', 'RBRACKET', 'FEEDBACK' ] print(self.lexer(string)) parser = ox.make_parser([ ('question : statement', lambda x: x), ('statement : cmd LBRACKET TRUE_VALUE RBRACKET', lambda x1, x2, x3, x4: (x1, x3)), ('statement : cmd LBRACKET FALSE_VALUE RBRACKET', lambda x1, x2, x3, x4: (x1, x3)), ('statement : cmd LBRACKET answer options RBRACKET', lambda x, a, y, z, b: (x, y, z)), ('cmd : QUESTION', lambda x: x), ('options : options option', lambda x, y: x + [y]), ('options : option', lambda x: [x]), ('option : option FEEDBACK', lambda x, y: (x, y)), ('option : OPTION', lambda x: x[1:].rstrip()), ('option : TRUE_VALUE', lambda x: x), ('option : FALSE_VALUE', lambda x: x), ('answer : answer FEEDBACK', lambda x, y: (x, y)), ('answer : ANSWER', lambda x: x[1:].rstrip()), ], self._token_list) ast = parser(self.lexer(string)) return ast
def make_parser(lexer, tokens): parser = ox.make_parser([ ("json : object", identity), ("json : array", identity), ("json : atom", identity), # Objects ("object : LBRACE RBRACE", lambda x, y: {}), ("object : LBRACE pairs RBRACE", lambda x, y, z: dict(y)), ("pairs : pair COMMA pairs", lambda x, _, xs: [x, *xs]), ("pairs : pair", lambda x: [x]), ("pair : string COLON json", lambda x, _, y: (x, y)), # Arrays ("array : LBRACK RBRACK", lambda x, y: []), ("array : LBRACK items RBRACK", lambda x, y, z: y), ("items : json COMMA items", lambda x, _, xs: [x, *xs]), ("items : json", lambda x: [x]), # Terminals ("string : STRING", clean_string), ("atom : NUMBER", float), ("atom : KEYWORD", lambda x: keywords[x]), ("atom : string", identity), ], tokens) return lambda src: parser(lexer(src))
def make_parser(lexer): parser = ox.make_parser([ ("module : expr", identity), ("expr : atom", identity), ("atom : number", identity), ("number : NUMBER", float), # ... ]) return lambda src: parser(lexer(src))
def make_parser(): return ox.make_parser([ ("expr : NUMBER", lambda x: as_expr(float(x))), ("expr : STRING", lambda x: as_expr(clean_string(x))), ("expr : NAME", var), ("expr : SYMBOL", var.read), ("expr : 'if'", handle_if), ("expr : 'let'", handle_let), ("expr : '(' 'items' ')'", handle_eval), ])
def parse(string): token_list = ['ANSWER', 'OPTION', 'ANY'] parser_exec = ox.make_parser([ ('question : cmd options answer', lambda x, y, z: (x.rstrip(), y, z)), ('cmd : cmd ANY', lambda x, y: x + y), ('cmd : ANY', lambda x: x), ('options : options option', lambda x, y: x + [y]), ('options : option', lambda x: [x]), ('option : OPTION ANY', lambda x, y: (x.strip(), y.strip())), ('answer : ANSWER', lambda x: x[7:].strip()), ], token_list) ast = parser_exec(lexer(string)) return ast
def make_parser(): return ox.make_parser([ ('module : statement SEMICOLON', lambda x, _: [x]), ('module : statement SEMICOLON module', statements), ('statement : NAME EQ expr', var_def), ('expr : atom OP expr', op_call), ('expr : atom', identity), ('atom : NUMBER', lambda x: Atom(float(x))), ('atom : STRING', lambda x: Atom(x[1:-1])), ('atom : BOOL', lambda x: Atom(x == 'true')), ('atom : LPAR expr RPAR', lambda x, y, z: y), ('atom : fcall', identity), ('fcall : NAME LPAR RPAR', lambda x, y, z: FCall(x, [])), ('fcall : NAME LPAR args RPAR', fcall), ('args : expr COMMA args', lambda x, _, xs: [x, *xs]), ('args : expr', lambda x: [x]), ], tokens=tokens)
('NUMBER', r'\d+(\.\d*)?'), # /d = [0-9] ('OP_S', r'[-+]'), ('OP_M', r'[*/]'), ]) # Função recebe o token jogado na funcao func, retorna objeto que é associado à "átomo" #Converte string func = float em número par uso posterior tokens_list = ['NUMBER','OP'] infix = lambda x, op, y : (op, x, y) #Só organiza a ordem dos operadores #Lambda define uma funcao simples (lambda argumentos e :retorno) atom = lambda x: ('atom',float(x)) # Expressão "SEXY ;p" -- função átomo recebe um token e retorna a árvore sintática parser = ox.make_parser([ ('expr : expr OP_S term', infix), ('expr : term', lambda x : x), ('term : term OP_M atom', infix), ('term : atom', lambda x : x), ('atom : NUMBER', atom) # Reduz numéro em um átomo # ('expr : atom OP atom', --> (OP x y)) # lisp (lista em python) - Operadores infixo, prefixo, sufixo ], tokens_list) # ------------------------FUNÇÕES ---------------------------------------------------------------------------- OP_TO_FUNC = { '+': lambda x , y : x + y, '-': lambda x , y : x - y, '*': lambda x , y : x * y, '/': lambda x , y : x / y, } def eval(ast): # Pega algo que veio de parser e avalia a expressão #( incluindo árvores sintáticas)
lexer = ox.make_lexer([('NAME', r'[-a-zA-Z]+'), ('NUMBER', r'\d+'), ('PARENTESE_A', r'\('), ('PARENTESE_F', r'\)'), ('COMMENT', r';.*'), ('NEWLINE', r'\n'), ('SPACE', r'\s+')]) tokens = ['PARENTESE_F', 'PARENTESE_A', 'NUMBER', 'NAME'] name = lambda name: (name) number = lambda number: (int(number)) op = lambda op: (op) parser = ox.make_parser([ ('program : PARENTESE_A expr PARENTESE_F', lambda x, y, z: y), ('program : PARENTESE_A PARENTESE_F', lambda x, y: '()'), ('expr : operator expr', lambda x, y: (x, ) + y), ('expr : operator', lambda x: (x, )), ('operator : program', op), ('operator : NAME', name), ('operator : NUMBER', number), ], tokens) @click.command() @click.argument('source', type=click.File('r')) def make_tree(source): program = source.read() print('program: ', program) tokens = lexer(program) # removing space and comment tokens before passing list to parser parser_tokens = [
('ignore_NEWLINE', r'\s+'), ('ignore_COMMENT', r';[^\n]*'), ] parser_rules = [ ('block : OPEN_PARANTHESIS CLOSE_PARANTHESIS', lambda x, y: '()'), ('block : OPEN_PARANTHESIS expr CLOSE_PARANTHESIS', lambda x, y, z: y), ('atom : TEXT', lambda x: x), ('atom : DIGITS', lambda x: x), ('expr : atom expr', lambda x, y: (x, ) + y), ('expr : atom', lambda x: (x, )), ('atom : block', lambda x: x), ] lexer = ox.make_lexer(lexer_rules) parser = ox.make_parser(parser_rules, tokens) @click.command() @click.argument('lispfcktree', type=click.File('r')) def ast(lispfcktree): """Create ast.""" lispcode = lispfcktree.read() tokens = lexer(lispcode) tree = parser(tokens) pprint.pprint(tree) if __name__ == '__main__': ast()
('NAME',r'[a-zA-Z]+'), ('NUMBER', r'\d+'), ('OPENING_PARENTHESES', r'\('), ('CLOSING_PARENTHESES', r'\)'), ]) tokens_list = ['NUMBER', 'NAME','OPENING_PARENTHESES','CLOSING_PARENTHESES','COMMA'] atom_number = lambda value: ('atom_number', float(value)) parser = ox.make_parser([ ('simple_block : simple_block simple_term', lambda first, second: (first, second)), ('simple_block : simple_term', lambda simple_block: simple_block), ('simple_term : OPENING_PARENTHESES simple_term CLOSING_PARENTHESES', lambda opening_paretheses, term, closing_parentheses: (opening_paretheses, term, closing_parentheses)), ('simple_term : atom simple_term',lambda first_term, second_term : (first_term, second_term)), ('simple_term : atom COMMA simple_term',lambda atom, comma, simple_term : (atom, comma, simple_term)), ('simple_term : atom', lambda term: term), ('atom : OPENING_PARENTHESES atom CLOSING_PARENTHESES', lambda opening_paretheses, term, closing_parentheses: (opening_paretheses, term, closing_parentheses)), ('atom : NUMBER', atom_number), ('atom : NAME',lambda name : name), ], tokens_list) def pretty_print(code_p): indent = 0 for element in code_p: if(element.find('(') != -1): if(not indent): print(lexer(element)) indent += 4 else:
('FNAME', r'[a-z]+'), ('COMMA', r'\,'), ]) tokens = ['NUMBER', 'OP', 'LPAR', 'RPAR', 'FNAME', 'COMMA'] # # Calc parser # identity = (lambda x: x) op_call = (lambda x, op, y: BinOp(op, x, y)) fcall = (lambda x, y, z, w: FCall(x, z)) parser = ox.make_parser([ ('expr : atom OP expr', op_call), ('expr : atom', identity), ('atom : NUMBER', lambda x: Number(int(x))), ('atom : LPAR expr RPAR', lambda x, y, z: y), ('atom : fcall', identity), ('fcall : FNAME LPAR RPAR', lambda x, y, z: FCall(x, [])), ('fcall : FNAME LPAR args RPAR', fcall), ('args : expr COMMA args', lambda x, _, xs: [x, *xs]), ('args : expr', lambda x: [x]), ], tokens=tokens) while True: print(parser(lexer(input('expr: '))))
] operator = lambda type_op: (type_op) op = lambda op: (op) opr = lambda op, num: (op, num) parser = ox.make_parser([ ('program : PARENTESE_A expr PARENTESE_F', lambda x, y, z: y), ('program : PARENTESE_A PARENTESE_F', lambda x, y: '()'), ('expr : operator expr', lambda x, y: (x, ) + y), ('expr : operator', lambda x: (x, )), ('operator : program', op), ('operator : LOOP', operator), ('operator : DO', operator), ('operator : RIGHT', operator), ('operator : LEFT', operator), ('operator : READ', operator), ('operator : INC', operator), ('operator : DEC', operator), ('operator : DEF', operator), ('operator : PRINT', operator), ('operator : ADD', operator), ('operator : SUB', operator), ('operator : NAME', operator), ('operator : NUMBER', operator), ], tokens) @click.command() @click.argument('source', type=click.File('r')) def make_tree(source): program = source.read()
]) tokens = [ 'PARANTHESIS_OPENED', 'PARANTHESIS_CLOSED', 'PLAIN_TEXT', 'NUMBERS', 'ignore_NEWLINE', 'ignore_COMMENT', ] parser = ox.make_parser([ ('atom : PLAIN_TEXT', lambda x: x), ('atom : NUMBERS', lambda x: x), ('expr : atom expr', lambda x, y: (x, ) + y), ('expr : atom', lambda x: (x, )), ('block : PARANTHESIS_OPENED PARANTHESIS_CLOSED', lambda x, y: '()'), ('block : PARANTHESIS_OPENED expr PARANTHESIS_CLOSED', lambda x, y, z: y), ('atom : block', lambda x: x), ], tokens) @click.command() @click.argument('lisp_file', type=click.File('r')) def printTree(lisp_file): tokens = lexer(lisp_file.read()) pprint.pprint(parser(tokens)) printTree()
'READ','DEF','PARENTHESIS_A','PARENTHESIS_B'] op = lambda op: (op) operator = lambda type_op: (type_op) #making parser parser = ox.make_parser([ ('program : PARENTHESIS_B expr PARENTHESIS_A', lambda x,y,z: y), ('program : PARENTHESIS_B PARENTHESIS_A', lambda x,y: '()'), ('expr : operator expr', lambda x,y: [x,] + y), ('expr : operator', lambda x: [x,]), ('operator : program', operator), ('operator : LOOP', operator), ('operator : DO', operator), ('operator : RIGHT', operator), ('operator : LEFT', operator), ('operator : READ', operator), ('operator : INC', operator), ('operator : DEC', operator), ('operator : DEF', operator), ('operator : PRINT', operator), ('operator : ADD', operator), ('operator : SUB', operator), ('operator : NAME', operator), ('operator : NUMBER', lambda x: float(x)), ], tokens) pp = pprint.PrettyPrinter(width=60, compact=True) tokens = lexer(code) tokens = [token for token in tokens if token.type != 'COMMENT' and token.type != 'SPACE']
OPERATORS = {'+': op.add, '-': op.sub, '*': op.mul, '/': op.truediv} lexer = ox.make_lexer([ ('NUMBER', r'[0-9]+(\.[0-9]+)?'), ('OP_SUM', r'[+-]'), ('OP_MUL', r'[*/]'), ('LPAR', r'\('), ('RPAR', r'\)'), ]) identity = lambda x: x def compute_operation(x, op, y): return OPERATORS[op](x, y) parser = ox.make_parser([ ('expr : term OP_SUM expr', compute_operation), ('expr : term', identity), ('term : atom OP_MUL term', compute_operation), ('term : atom', identity), ('atom : NUMBER', float), ('atom : LPAR expr RPAR', lambda x, y, z: y), ], ['NUMBER', 'OP_SUM', 'OP_MUL', 'LPAR', 'RPAR']) while True: from pprint import pprint pprint(parser(lexer(input('expr: '))))
('SELECT', r'SELECT'), ('WHATEVER', r'.+'), # ..., ] # Regras para montar o parser parser_rules = [ ('sql : SELECT WHATEVER', lambda x, y: {x: y}), # ..., ] # Criamos o parser e o lexer lexer = ox.make_lexer(token_rules) parser = ox.make_parser(parser_rules, tokens=[x for (x, y) in token_rules]) # Testamos em algums exemplos examples = [ 'SELECT name FROM users;', 'SELECT * FROM users;', 'SELECT username, password FROM users WHERE username = password;', ] results = [ {'SELECT': ['name'], 'FROM': 'users'}, {'SELECT': None, 'FROM': 'users'}, {'SELECT': ['username', 'password'], 'FROM': 'users', 'WHERE': ['=', 'username', 'password']}, ]
import ox lexer = ox.make_lexer([('NUMBER', r'[0-9]+(\.[0-9]+?)'), ('OP_PRI', r'[*/]'), ('OP_SEC', r'[-+]')]) OPERATORS = { '+': lambda x, y: x + y, '-': lambda x, y: x - y, '*': lambda x, y: x * y, '/': lambda x, y: x / y, } tokens = ['NUMBER', 'OP'] parser = ox.make_parser([('term : term OP atom', lambda a, op, b: OPERATORS[op] (a, b)), ('term : atom', lambda x: x), ('atom : NUMBER', float)], tokens) st = input('expr: ') tokens = lexer(st) print(lexer(st)) res = parser(tokens) print(res)
]) token_list = [ 'NAME', 'NUMBER', 'OPEN_BRACKET', 'CLOSE_BRACKET', ] identity = lambda x: x parser = ox.make_parser([ ('tuple : OPEN_BRACKET elements CLOSE_BRACKET', lambda a, x, b: x), ('tuple : OPEN_BRACKET CLOSE_BRACKET', lambda a, b: '[]'), ('elements : term elements', lambda x, xs: [x] + xs), ('elements : term', lambda x: [x]), ('term : atom', identity), ('term : tuple', identity), ('atom : NAME', identity), ('atom : NUMBER', lambda x: int(x)), ], token_list) data = [0] ptr = 0 code_ptr = 0 breakpoints = [] @click.command() @click.argument('source_file', type=click.File('r')) def build(source_file):
def operator_expr(operator, expr): return (operator, ) + expr def composed_operator(operator): return (operator, ) #Define parser rules lisp_parser = ox.make_parser([ ('program : PARENT_OPEN expr PARENT_CLOSE', parent_expr), ('program : PARENT_OPEN PARENT_CLOSE', parent), ('expr : operator expr', operator_expr), ('expr : operator', composed_operator), ('operator : program', single_operator), ('operator : NAME', name), ('operator : NUMBER', number), ], tokens) #Create tree @click.command() @click.argument('source', type=click.File('r')) def create_tree(source): program = source.read() tokens = lisp_lexer(program) # remove spaces and comments before do parser parser_tokens = [
('NUMBER', r'[0-9]+'), ('ignore_COMMENT', r';[^\n]*'), ('ignore_NEWLINE', r'\s+'), ]) tokens = ['OP', 'NUMBER', 'OPEN_P', 'CLOSE_P'] atom = lambda x: x term = lambda x: (x, ) comp = lambda x, y: (x, ) + y pare = lambda x, y: '()' expr = lambda x, y, z: y parser = ox.make_parser([ ('expr : OPEN_P term CLOSE_P', expr), ('expr : OPEN_P CLOSE_P', pare), ('term : atom term', comp), ('term : atom', term), ('atom : expr', atom), ('atom : OP', atom), ('atom : NUMBER', atom), ], tokens) @click.command() @click.argument('file', type=click.File('r')) def tree(file): pprint.pprint(parser(lexer(file.read()))) tree()
tokens_list = [ 'DEC', 'INC', 'LOOP', 'LEFT_PAR', 'RIGHT_PAR', 'RIGHT', 'LEFT', 'PRINT', 'READ', 'DO', 'DO_AFTER', 'DO_BEFORE', 'ADD', 'SUB', 'NUMBER', 'DEF', 'FUCTION' ] parser = ox.make_parser([('expr : LEFT_PAR RIGHT_PAR', lambda x, y: '()'), ('expr : LEFT_PAR term RIGHT_PAR', lambda x, y, z: y), ('term : atom term', lambda x, y: (x, ) + y), ('term : atom', lambda x: (x, )), ('atom : expr', lambda x: x), ('atom : DEC', lambda x: x), ('atom : INC', lambda x: x), ('atom : LOOP', lambda x: x), ('atom : RIGHT', lambda x: x), ('atom : LEFT', lambda x: x), ('atom : PRINT', lambda x: x), ('atom : READ', lambda x: x), ('atom : DO', lambda x: x), ('atom : DO_AFTER', lambda x: x), ('atom : DO_BEFORE', lambda x: x), ('atom : ADD', lambda x: x), ('atom : SUB', lambda x: x), ('atom : NUMBER', int), ('atom : DEF', lambda x: x), ('atom : FUCTION', lambda x: x)], tokens_list) def do_after(command, old_array): new_array = [] i = 0 while i < len(old_array):
def section_body(body_section, subsection): return (body_section, subsection) # Defining tokens that will be used in the parser tokens_list = create_tokens() parser = ox.make_parser([ ('document : document section', section_all), ('document : section', lambda x: x), ('section : SECTION_TITLE body_section', section), ('body_section : body_section subsection', section_body), ('body_section : subsection', lambda x: x), ('body_section : body', lambda x: x), ('subsection : SUBSECTION_TITLE body', subsection), ('body : attribute body', body), ('body : attribute', lambda x: x), ('attribute : STRING EQUAL DATA', attribute_data), ('attribute : STRING EQUAL STRING', attribute_data), ], tokens_list) def eval(ast, document, last_create=None): head, *tail = ast if head[0] == 'section': section = Section(head[1].rstrip()) document.sections.append(section) if tail:
OP_TO_FUNCTION = {'+': op.add, '-': op.sub, '*': op.mul, '/': op.truediv} # # Lexer # lexer = ox.make_lexer([ ('NUMBER', r'[0-9]+(\.[0-9]+)?'), ('OP', r'[-+*/]'), ]) # # Parser # binop = (lambda a, op, b: OP_TO_FUNCTION[op](a, b)) parser = ox.make_parser([ ('term : term OP atom', binop), ('term : atom', lambda x: x), ('atom : NUMBER', float), ]) # # # if __name__ == '__main__': st = input('expr: ') tokens = lexer(st) print('tokens:', tokens) value = parser(tokens) print('res:', value)
def call_func(name, lpar, args, rpar): return func_dic[name](*args) expr_parser = ox.make_parser([ ('expr : op_expr', id), ('atom : NUMBER', int), ('atom : STRING', id), ('atom : call_func', id), ('atom : tuple', id), ('atom : LPAR expr RPAR', lambda x, y, z: y), ('op_expr : atom OP op_expr', exec_op), ('op_expr : atom', id), ('call_func : VARNAME LPAR args RPAR', call_func), ('args : expr', lambda x: [x]), ('args : expr COMMA args', lambda x, _, y: [x, *y]), ('tuple : LPAR RPAR', lambda x, y: ()), ('tuple : LPAR expr COMMA args RPAR', lambda x, y, z, w, v: (y, ) + tuple(w)), ], [ 'NUMBER', 'STRING', 'VARNAME', 'TYPENAME', 'EQUAL', 'COMMA', 'COLON', 'LPAR', 'RPAR', 'OP' ]) def ast_evaluatuator(src): return src
OP_TO_FUNC = {'+': op.add, '-': op.sub, '*': op.mul, '/': op.truediv} lexer = ox.make_lexer([ ('NUMBER', r'\d+(\.\d*)?'), ('TERM_OP', r'[*/]'), ('EXP_OP', r'[-+]'), ('LPAREN', r'\('), ('RPAREN', r'\)') ]) parser = ox.make_parser([ ('expr : expr EXP_OP term', lambda x, op, y: (op, x, y)), ('term : term TERM_OP value', lambda x, op, y: (op, x, y)), ('expr : term', lambda x: x), ('term : value', lambda x: x), ('value : NUMBER', lambda x: ('atom', x)), ], ['NUMBER', 'TERM_OP', 'EXP_OP']) def eval(ast): head, *tail = ast if head == 'atom': return float(tail[0]) else: x, y = tail return OP_TO_FUNC[head](eval(x), eval(y)) if __name__ == '__main__':
import ox import operator as op lexer_rules = [('NUMBER', r'\d+'), ('ADD', r'\+'), ('SUB', r'\-'), ('MUL', r'\*'), ('DIV', r'\/'), ('LPAR', r'\('), ('RPAR', r'\)'), ('VAR', r'[a-zA-Z_]+')] lexer = ox.make_lexer(lexer_rules) tokens = [x for x, _ in lexer_rules] binop = (lambda x, op, y: (op, x, y)) parser = ox.make_parser([ ('expr : term ADD expr', binop), ('expr : term SUB expr', binop), ('expr : term', lambda x: x), ('term : atom MUL term', binop), ('term : atom DIV term', binop), ('term : atom', lambda x: x), ('atom : NUMBER', int), ('atom : VAR', lambda x: ('var', x)), ('atom : LPAR expr RPAR', lambda x, y, z: y), ], tokens) def find_vars(ast, vars=()): if not isinstance(ast, tuple): return set() head, *tail = ast if head == 'var': return {tail[0], *vars} result = set()
def make_parser(): return ox.make_parser([ # Um módulo é uma lista de declarações ("module : statement ';'", singleton), ("module : statement ';' module", cons), # Declarações ("statement : vardef", identity), ("statement : fundef", identity), # ("statement : typedef", identity), # ("statement : opdef", identity), # ("statement : export", identity), # ("statement : import", identity), # Definição de tipos # ("typedef : ...", ...), # Definição de operadores # ("opdef : ...", ...), # Exports # ("export : ...", ...), # Imports # ("import : ...", ...), # Declaração de funções e variáveis ("vardef : NAME '=' expr", Stmt.Assign), ("fundef : NAME '(' defargs ')' '=' expr", Stmt.Fundef), ("defargs : NAME", singleton), ("defargs : NAME ',' defargs", cons), # Expressões ("expr : elem", identity), # ("expr : letexpr", identity), # ("expr : caseexpr", identity), # Elementos ("elem : value", identity), ("elem : value OP value", op_call), ("elem : ifexpr", identity), ("elem : '+' value", lambda x: Expr.Call(Expr.Name('pos'), [x])), ("elem : '-' value", lambda x: Expr.Call(Expr.Name('neg'), [x])), ("elem : 'not' value", lambda x: Expr.Call(Expr.Name('negate'), [x])), # ("elem : unaryop", identity), # ("elem : lambda", identity), # ("elem : constructor", identity), # Valores ("value : atom", identity), ("value : fcall", identity), ("value : '(' expr ')'", identity), # ("value : getattr", identity), # Valores atômicos ("atom : NUMBER", lambda x: Atom(float(x))), ("atom : STRING", lambda x: Atom(x[1:-1])), ("atom : TRUE", lambda x: Atom(True)), ("atom : FALSE", lambda x: Atom(False)), ("atom : TYPENAME", Enum), ("atom : NAME", Name), # ("atom : list", identity), # ("atom : record", identity), # Chamada de função ("fcall : value '(' ')'", lambda x: Call(x, [])), ("fcall : value '(' fargs ')'", Call), # ("fcall : value LPAR letexpr RPAR", fcallexpr), # ("fcall : value LPAR caseexpr RPAR", fcallexpr), ("fargs : elem", singleton), ("fargs : elem ',' fargs", cons), # Acesso a atributo # ("getattr : ...", ...), # Operadores unários # ("unary : ...", ...), # Lambdas # ("lambda : ...", ...), # If ("ifexpr : 'if' value 'then' elem 'else' elem", Expr.If), # Let # ("letexpr : ...", ...), # Case # ("caseexpr : ...", ...), # Listas # ("list : ...", ...), # Records # ("record : ...", ...), # Construtor # ("constructor : ...", ...), ])
('OP_S', r'[-+]'), ('OP_M', r'[*/]'), ('OP_P', r'[\^]'), ('PAR_O', r'\('), ('PAR_C', r'\)'), ]) tokens_list = ['NUMBER', 'OP_S', 'OP_M', 'OP_P', 'PAR_O', 'PAR_C'] infix = lambda x, op, y: (op, x, y) atom = lambda x: ('atom', float(x)) parser = ox.make_parser([ ('expr : expr OP_S term', infix), ('expr : term', lambda x: x), ('term : term OP_M res', infix), ('term : res', lambda x: x), ('res : res OP_P atom', infix), ('res : atom', lambda x: x), ('atom : NUMBER', atom), ], tokens_list) OP_TO_FUNC = { '+': lambda x, y: x + y, '-': lambda x, y: x - y, '*': lambda x, y: x * y, '/': lambda x, y: x / y, '^': lambda x, y: x**y, } def eval(ast):
def make_parser(): return ox.make_parser([ # Um módulo é uma lista de declarações ("module : statement ';'", singleton), ("module : statement ';' module", cons), # Declarações ("statement : vardef", identity), ("statement : fundef", identity), ("statement : typedef", identity), ("statement : import", identity), # ("statement : opdef", identity), # ("statement : export", identity), # Definição de tipos ("typedef : 'type' TYPENAME '=' casedeflist", handle_type), ("casedeflist : casedef", singleton), ("casedeflist : casedef '|' casedeflist", cons), ("casedef : TYPENAME TYPENAME", lambda x, y: (x, y)), ("casedef : TYPENAME", lambda x: (x, None)), # Definição de operadores # ("opdef : ...", ...), # Exports # ("export : ...", ...), # Imports ("import : 'import' '(' list_names ')' 'from' STRING", handle_list_imports_module), ("list_names : NAME ',' list_names", lambda x, xs: [x, *xs]), ("list_names : NAME 'as' NAME ',' list_names", lambda x, name, xs: [{ x: name }, *xs]), ("list_names : NAME 'as' NAME", lambda x, name: [{ x: name }]), ("list_names : NAME", identity), # Declaração de funções e variáveis ("vardef : NAME '=' expr", Stmt.Assign), ("fundef : NAME '(' defargs ')' '=' expr", Stmt.Fundef), ("defargs : NAME", singleton), ("defargs : NAME ',' defargs", cons), # Expressões ("expr : elem", identity), # ("expr : letexpr", identity), # ("expr : caseexpr", identity), # Elementos ("elem : lambda", identity), ("elem : value", identity), ("elem : value OP value", op_call), ("elem : ifexpr", identity), ("elem : '+' value", lambda x: Expr.Call(Expr.Name('pos'), [x])), ("elem : '-' value", lambda x: Expr.Call(Expr.Name('neg'), [x])), ("elem : 'not' value", lambda x: Expr.Call(Expr.Name('negate'), [x])), # ("elem : unaryop", identity), # ("elem : constructor", identity), # Valores ("value : atom", identity), ("value : fcall", identity), ("value : '(' expr ')'", identity), # ("value : getattr", identity), # Valores atômicos ("atom : NUMBER", lambda x: Atom(float(x))), ("atom : STRING", lambda x: Atom(x[1:-1])), ("atom : TRUE", lambda x: Atom(True)), ("atom : FALSE", lambda x: Atom(False)), ("atom : TYPENAME", Name), ("atom : TYPENAME atom", handle_type_creation), ("atom : NAME", Name), ("atom : list", identity), ("atom : tuple", identity), ("atom : record", identity), # Chamada de função ("fcall : value '(' ')'", lambda x: Call(x, [])), ("fcall : value '(' fargs ')'", Call), # ("fcall : value LPAR letexpr RPAR", fcallexpr), # ("fcall : value LPAR caseexpr RPAR", fcallexpr), ("fargs : elem", singleton), ("fargs : elem ',' fargs", cons), # Acesso a atributo # ("getattr : ...", ...), # Operadores unários # ("unary : ...", ...), # Lambdas ("lambda : 'fn' '(' defargs ')' '=>' expr", lambd_def), # If ("ifexpr : 'if' value 'then' elem 'else' elem", Expr.If), # Let # ("letexpr : ...", ...), # Case # ("caseexpr : ...", ...), # Listas/Tuplas ("list : '[' ']'", lambda: Expr.List([])), ("list : '[' items ']'", lambda x: Expr.List(x)), ("tuple : '(' ')'", lambda: Expr.Tuple(())), ("tuple : '(' elem ',' items ')'", lambda x, xs: Expr.Tuple((x, *xs))), ("items: elem", lambda x: [x]), ("items: elem ',' items", lambda x, z: [x, *z]), ("items: elem ',' items ','", lambda x, z: [x, *z]), # Records ("record : '{' objvalue '}'", lambda y: Expr.Record(y)), ("objvalue : NAME ':' elem", lambda x, z: { x: z }), ("objvalue : NAME ':' elem ',' objvalue", lambda k, y, z: { k: y, **z }), ])
lexer = ox.make_lexer([ ('NUMBER', r'\d+'), ('NAME', r'[-a-zA-Z]+'), ('LPARAN', r'[(]'), ('RPARAN', r'[)]'), ('COMMENT', r';.*'), ('NEWLINE', r'\s+'), ]) tokens_list = ['NAME', 'NUMBER', 'LPARAN', 'RPARAN'] parser = ox.make_parser([ ('stmt : LPARAN RPARAN', lambda x,y: '()'), ('stmt : LPARAN expr RPARAN', lambda x,y,z: y), ('expr : term expr', lambda x,y: [x] + y), ('expr : term', lambda x: [x]), ('term : stmt', lambda x: x), ('term : NUMBER', lambda x: int(x)), ('term : NAME', lambda x: x), ], tokens_list) collection = [0] p = 0 @click.command() @click.argument('lispf_data', type=click.File('r')) def ast(lispf_data): """ Generate ast of lispf_code """ collection = lispf_data.read()