Skip to content

Instantly share code, notes, and snippets.

@alcides
Created February 12, 2021 18:29
Show Gist options
  • Save alcides/a4fc3efa4332c02bf4461574c8d8411e to your computer and use it in GitHub Desktop.
Save alcides/a4fc3efa4332c02bf4461574c8d8411e to your computer and use it in GitHub Desktop.
O meu primeiro compilador
# Depende do Lark: pip3 install lark-parser
import os
import sys
from lark import Lark
from lark.lexer import Token
def get_contents(fname):
return open(fname).read()
def parse(source):
l = Lark(
"""start: expr*
expr: INT
| expr "+" expr
%import common.INT
%import common.WS // imports from terminal library
%ignore WS // Disregard spaces in text
"""
)
return l.parse(source)
class Node(object):
pass
class Program(Node):
def __init__(self, linhas):
self.linhas = linhas
def __str__(self):
return "Program({})".format(", ".join(map(str, self.linhas)))
class Sum(Node):
def __init__(self, left, right):
self.right = right
self.left = left
def __str__(self):
return "Sum({}, {})".format(self.left, self.right)
class Literal(Node):
def __init__(self, value):
self.value = value
def __str__(self):
return "Literal({})".format(self.value)
def convert_cst_to_ast(cst):
if cst.data == "start":
cc = [convert_cst_to_ast(c) for c in cst.children]
return Program(cc)
elif cst.data == "expr" and len(cst.children) == 1:
return Literal(int(str(cst.children[0])))
elif cst.data == "expr" and len(cst.children) == 2:
l = convert_cst_to_ast(cst.children[0])
r = convert_cst_to_ast(cst.children[1])
return Sum(l, r)
return None
def interpretador(ast):
if isinstance(ast, Program):
for linha in ast.linhas:
print(interpretador(linha))
elif isinstance(ast, Literal):
return ast.value
elif isinstance(ast, Sum):
l = interpretador(ast.left)
r = interpretador(ast.right)
return l + r
def comp(ast):
if isinstance(ast, Program):
ls = ['printf("%d\\n",{});'.format(comp(l)) for l in ast.linhas]
return "\n".join(ls)
elif isinstance(ast, Literal):
return str(ast.value)
elif isinstance(ast, Sum):
l = comp(ast.left)
r = comp(ast.right)
return "({} + {})".format(l, r)
def compilador(ast):
codigo_interno = comp(ast)
return """
#include<stdio.h>
int main() {{
{}
}}
""".format(
codigo_interno
)
pass
fname = sys.argv[1]
" Frontend "
source = get_contents(fname)
cst = parse(source)
ast = convert_cst_to_ast(cst)
" MiddleEnd "
# TypeChecking
" Backend "
# interpretador(ast)
codigo_maquina = compilador(ast)
open("output.c", "w").write(codigo_maquina)
os.system("clang -o output output.c")
1 + 2 + 4
1 + 2
1 + 1
123
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment