add functions and some operators 2
This commit is contained in:
parent
27fff15972
commit
287a2a066a
|
@ -134,7 +134,7 @@ def repl():
|
||||||
ptr = 0
|
ptr = 0
|
||||||
raise BFError(f"You can't go to a cell before 0 (code before : {prog[:index]}, code after : {prog[index:]})")
|
raise BFError(f"You can't go to a cell before 0 (code before : {prog[:index]}, code after : {prog[index:]})")
|
||||||
elif instr == '.':
|
elif instr == '.':
|
||||||
print(chr(ar[ptr]),end='')
|
print(chr(ar[ptr]),end='',flush=True)
|
||||||
elif instr == ',':
|
elif instr == ',':
|
||||||
val = input()
|
val = input()
|
||||||
if len(val) > 1:
|
if len(val) > 1:
|
||||||
|
@ -159,7 +159,7 @@ def repl():
|
||||||
if prog[index+1] == '(':
|
if prog[index+1] == '(':
|
||||||
index = index+2
|
index = index+2
|
||||||
while prog[index] != ')':
|
while prog[index] != ')':
|
||||||
print(prog[index],end='')
|
print(prog[index],end='',flush=True)
|
||||||
index += 1
|
index += 1
|
||||||
print(' ',end='')
|
print(' ',end='')
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -189,10 +189,10 @@ There is also some special command :
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) == 2:
|
if len(sys.argv) == 2:
|
||||||
interpret(open(sys.argv[2]).read())
|
interpret(open(sys.argv[1]).read())
|
||||||
elif len(sys.argv) == 3:
|
elif len(sys.argv) == 3:
|
||||||
if sys.argv[1] == '-i': #oui c'est de lam erde comme manière de faire
|
if sys.argv[1] == '-i': #oui c'est de lam erde comme manière de faire
|
||||||
interpret(sys.argv[2])
|
interpret(sys.argv[1])
|
||||||
else:
|
else:
|
||||||
repl()
|
repl()
|
||||||
|
|
||||||
|
|
16
grammar.ebnf
16
grammar.ebnf
|
@ -1,12 +1,17 @@
|
||||||
program = statement, {statement}
|
program = statement, {statement}
|
||||||
|
|
||||||
block = "{",{statement}, "}"
|
block = "{",{statement}, "}"
|
||||||
statement = short_statement | while_block | if_block
|
statement = short_statement | while_block | if_block | function_def
|
||||||
short_statement = declaration | assignement | expression | inc-dec, ";"
|
short_statement = print | return | input | declaration | assignement | expression | inc-dec, ";"
|
||||||
assignement = name, assignement_symbol, expression
|
|
||||||
declaration = "var" , name , {",",name}, ";"
|
assignement = name, assignement_symbol, expression
|
||||||
|
declaration = "var" , name , {",",name}
|
||||||
|
return = "return", expression
|
||||||
|
|
||||||
|
expression = compar_op | function_call
|
||||||
|
|
||||||
|
function_call = name, '(',[expression,{','expression,}]
|
||||||
|
|
||||||
expression = compar
|
|
||||||
|
|
||||||
compar = calcul, [compar_op, calcul]
|
compar = calcul, [compar_op, calcul]
|
||||||
calcul = terme, [('+'|'-'), terme]
|
calcul = terme, [('+'|'-'), terme]
|
||||||
|
@ -18,6 +23,7 @@ inc-dec = name, ("++" | "--")
|
||||||
condition = '(', expression, ')'
|
condition = '(', expression, ')'
|
||||||
while_block = "while", condition, block
|
while_block = "while", condition, block
|
||||||
if_block = "if", condition, block, ["else", block]
|
if_block = "if", condition, block, ["else", block]
|
||||||
|
function_def = "def", name, '(',[name,{',',name}],')',block
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import re
|
import re
|
||||||
from collections import namedtuple
|
from collections import namedtuple, ChainMap
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from termcolor import cprint
|
from termcolor import cprint
|
||||||
|
@ -9,16 +9,17 @@ os.system('color')
|
||||||
REGEXS = [(re.compile(i),j) for i,j in (
|
REGEXS = [(re.compile(i),j) for i,j in (
|
||||||
(r'\s+','WHITESPACE'),
|
(r'\s+','WHITESPACE'),
|
||||||
(r'//[^\n]*|/\*(?s:.)*\*/','COMMENTS'),
|
(r'//[^\n]*|/\*(?s:.)*\*/','COMMENTS'),
|
||||||
(r'if|for|while|else|var','KEYWORD'),
|
(r'if|for|while|else|var|def|return','KEYWORD'),
|
||||||
|
|
||||||
(r'>=|<=|==|>|<','COMPAR_OP'),
|
(r'>=|<=|==|>|<|!=','COMPAR_OP'),
|
||||||
(r'\+=|-=|\*=|/=|=','ASSIGNEMENT_OP'),
|
(r'\+=|-=|\*=|/=|=','ASSIGNEMENT_OP'),
|
||||||
(r'\+\+|--','INC_DEC_OP'),
|
(r'\+\+|--','INC_DEC_OP'),
|
||||||
(r'\+|\*\*|\*|-|/','BIN_OP'),
|
(r'\+|\*\*|\*|-|/','BIN_OP'),
|
||||||
(r'\(|\)|\{|\}|;|,','CONTROL_CHAR'),
|
(r'\(|\)|\{|\}|;|,','CONTROL_CHAR'),
|
||||||
|
|
||||||
(r'[a-zA-Z]\w*','IDENTIFIERS'),
|
(r'[a-zA-Z]\w*','IDENTIFIERS'),
|
||||||
(r'\d[\d_]*','NUMBERS')
|
(r'\d[\d_]*','NUMBERS'),
|
||||||
|
(r"'.'",'CHAR')
|
||||||
|
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
@ -50,15 +51,18 @@ def clean_tokens(tokens):
|
||||||
#****************************
|
#****************************
|
||||||
|
|
||||||
|
|
||||||
ProgramNode = namedtuple('ProgramNode',('list_of_statement'))
|
ProgramNode = namedtuple('ProgramNode',('list_of_statement','name'))
|
||||||
BlockNode = namedtuple('BlockNode',('list_of_statement'))
|
BlockNode = namedtuple('BlockNode',('list_of_statement'))
|
||||||
|
|
||||||
IfNode = namedtuple('IfNode',('condition','block','else_block'))
|
IfNode = namedtuple('IfNode',('condition','block','else_block'))
|
||||||
WhileNode = namedtuple('WhileNode',('condition','block'))
|
WhileNode = namedtuple('WhileNode',('condition','block'))
|
||||||
|
FunctionDefNode = namedtuple('FunctionDefNode',('name','args','block'))
|
||||||
|
|
||||||
AssignementNode = namedtuple('AssignementNode',('target','operator','expression'))
|
AssignementNode = namedtuple('AssignementNode',('target','operator','expression'))
|
||||||
IncDecNode = namedtuple('IncDecNode',('name','operator'))
|
IncDecNode = namedtuple('IncDecNode',('name','operator'))
|
||||||
DeclarationNode = namedtuple('DeclarationNode',('names'))
|
DeclarationNode = namedtuple('DeclarationNode',('names'))
|
||||||
|
FunctionCallNode = namedtuple('FunctionCallNode',('name','args'))
|
||||||
|
ReturnNode = namedtuple('ReturnNode',('expr'))
|
||||||
BinOpNode = namedtuple('BinOpNode',('left','op','right'))
|
BinOpNode = namedtuple('BinOpNode',('left','op','right'))
|
||||||
|
|
||||||
IdentifierNode = namedtuple('IdentifierNode',('name'))
|
IdentifierNode = namedtuple('IdentifierNode',('name'))
|
||||||
|
@ -107,7 +111,7 @@ class Parser:
|
||||||
break
|
break
|
||||||
if not len(nodes):
|
if not len(nodes):
|
||||||
raise ValueError("Your program seems to be empty")
|
raise ValueError("Your program seems to be empty")
|
||||||
return ProgramNode(nodes)
|
return ProgramNode(nodes,'__main__') #plus simple pour le debug
|
||||||
|
|
||||||
def block(self):
|
def block(self):
|
||||||
#print(f"enter block ({self.pos})")
|
#print(f"enter block ({self.pos})")
|
||||||
|
@ -128,7 +132,7 @@ class Parser:
|
||||||
|
|
||||||
def statement(self):
|
def statement(self):
|
||||||
#print(f"enter statement ({self.pos})")
|
#print(f"enter statement ({self.pos})")
|
||||||
for func in (self.short_statement,self.while_block, self.if_block):
|
for func in (self.short_statement,self.while_block, self.if_block,self.function_block):
|
||||||
node = func()
|
node = func()
|
||||||
if node:
|
if node:
|
||||||
#cprint("statement",'green')
|
#cprint("statement",'green')
|
||||||
|
@ -138,7 +142,7 @@ class Parser:
|
||||||
|
|
||||||
def short_statement(self):
|
def short_statement(self):
|
||||||
#print(f"enter short_statement ({self.pos})")
|
#print(f"enter short_statement ({self.pos})")
|
||||||
for func in (self.declaration, self.assignement,self.inc_dec,self.expression,):
|
for func in (self.declaration, self.assignement,self.inc_dec,self.expression,self.return_):
|
||||||
node = func()
|
node = func()
|
||||||
if node:
|
if node:
|
||||||
if self.accept_text(";"):
|
if self.accept_text(";"):
|
||||||
|
@ -149,6 +153,14 @@ class Parser:
|
||||||
#cprint("no short_statement",'red')
|
#cprint("no short_statement",'red')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def return_(self):
|
||||||
|
if not self.accept_text('return'):
|
||||||
|
return None
|
||||||
|
expr = self.expression()
|
||||||
|
if not expr:
|
||||||
|
raise SyntaxError("Bad Return")
|
||||||
|
return ReturnNode(expr)
|
||||||
|
|
||||||
def declaration(self):
|
def declaration(self):
|
||||||
if not self.accept_text('var'):
|
if not self.accept_text('var'):
|
||||||
return None
|
return None
|
||||||
|
@ -162,7 +174,7 @@ class Parser:
|
||||||
if name:
|
if name:
|
||||||
names.append(IdentifierNode(name.text))
|
names.append(IdentifierNode(name.text))
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("Expected an identifiers after a ',' in a declaration statemement")
|
raise SyntaxError("Expected an identifiers after a ',' in a declaration statement")
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -177,7 +189,6 @@ class Parser:
|
||||||
sym = self.accept_tag('ASSIGNEMENT_OP')
|
sym = self.accept_tag('ASSIGNEMENT_OP')
|
||||||
if not sym:
|
if not sym:
|
||||||
self.pos -= 1 #for the name
|
self.pos -= 1 #for the name
|
||||||
#cprint("no assignement (no op)",'red')
|
|
||||||
return None
|
return None
|
||||||
expr = self.expression()
|
expr = self.expression()
|
||||||
if not expr:
|
if not expr:
|
||||||
|
@ -200,15 +211,35 @@ class Parser:
|
||||||
return IncDecNode(IdentifierNode(name.text),op.text)
|
return IncDecNode(IdentifierNode(name.text),op.text)
|
||||||
|
|
||||||
def expression(self):
|
def expression(self):
|
||||||
#print(f"enter expression ({self.pos})")
|
|
||||||
compar = self.compar()
|
compar = self.compar()
|
||||||
if compar:
|
if compar:
|
||||||
#cprint("expression",'green')
|
|
||||||
return compar
|
return compar
|
||||||
|
|
||||||
#cprint("no expression",'red')
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def call_function(self):
|
||||||
|
name = self.accept_tag('IDENTIFIERS')
|
||||||
|
if not name:
|
||||||
|
return None
|
||||||
|
if not self.accept_text('('):
|
||||||
|
self.pos -= 1
|
||||||
|
return None
|
||||||
|
|
||||||
|
expr = self.expression()
|
||||||
|
args = []
|
||||||
|
if expr:
|
||||||
|
args.append(expr)
|
||||||
|
while self.accept_text(','):
|
||||||
|
expr = self.expression()
|
||||||
|
if not expr:
|
||||||
|
raise SyntaxError("missing argument")
|
||||||
|
args.append(expr)
|
||||||
|
if not self.accept_text(')'):
|
||||||
|
raise SyntaxError("A function call must have a ')' at the end")
|
||||||
|
|
||||||
|
return FunctionCallNode(name.text,args)
|
||||||
|
|
||||||
|
|
||||||
def compar(self):
|
def compar(self):
|
||||||
calcul1 = self.calcul()
|
calcul1 = self.calcul()
|
||||||
if not calcul1:
|
if not calcul1:
|
||||||
|
@ -281,12 +312,22 @@ class Parser:
|
||||||
|
|
||||||
def value(self):
|
def value(self):
|
||||||
#print(f"enter value ({self.pos})")
|
#print(f"enter value ({self.pos})")
|
||||||
|
func = self.call_function() #The orders matters !!!
|
||||||
|
if func:
|
||||||
|
return func
|
||||||
|
|
||||||
name = self.accept_tag('IDENTIFIERS')
|
name = self.accept_tag('IDENTIFIERS')
|
||||||
if name:
|
if name:
|
||||||
return IdentifierNode(name.text)
|
return IdentifierNode(name.text)
|
||||||
|
|
||||||
number = self.accept_tag('NUMBERS')
|
number = self.accept_tag('NUMBERS')
|
||||||
if number:
|
if number:
|
||||||
return NumberNode(int(number.text))
|
return NumberNode(int(number.text))
|
||||||
|
|
||||||
|
char = self.accept_tag('CHAR')
|
||||||
|
if char:
|
||||||
|
return NumberNode(ord(char.text[1]))
|
||||||
|
|
||||||
if self.accept_text('('):
|
if self.accept_text('('):
|
||||||
expr = self.expression()
|
expr = self.expression()
|
||||||
if not (expr and self.accept_text(')')):
|
if not (expr and self.accept_text(')')):
|
||||||
|
@ -340,6 +381,35 @@ class Parser:
|
||||||
#cprint("if_block",'green')
|
#cprint("if_block",'green')
|
||||||
return IfNode(cond,block,None)
|
return IfNode(cond,block,None)
|
||||||
|
|
||||||
|
def function_block(self):
|
||||||
|
if not self.accept_text('def'):
|
||||||
|
return None
|
||||||
|
name = self.accept_tag('IDENTIFIERS')
|
||||||
|
if not name:
|
||||||
|
raise SyntaxError("A function need a name")
|
||||||
|
if not self.accept_text('('):
|
||||||
|
raise SyntaxError("Bad function block")
|
||||||
|
arg = self.accept_tag('IDENTIFIERS')
|
||||||
|
args = []
|
||||||
|
if arg:
|
||||||
|
args.append(IdentifierNode(arg.text))
|
||||||
|
while self.accept_text(','):
|
||||||
|
arg = self.accept_tag('IDENTIFIERS')
|
||||||
|
if not arg:
|
||||||
|
raise SyntaxError("Bad function block")
|
||||||
|
args.append(IdentifierNode(arg.text))
|
||||||
|
|
||||||
|
if not self.accept_text(')'):
|
||||||
|
raise SyntaxError("Bad function block")
|
||||||
|
|
||||||
|
block = self.block()
|
||||||
|
if not block:
|
||||||
|
raise SyntaxError("Bad function block")
|
||||||
|
|
||||||
|
return FunctionDefNode(name.text,args,block)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parse(prog):
|
def parse(prog):
|
||||||
tokens = clean_tokens(lex(prog))
|
tokens = clean_tokens(lex(prog))
|
||||||
|
@ -349,27 +419,59 @@ def parse(prog):
|
||||||
|
|
||||||
#***************
|
#***************
|
||||||
|
|
||||||
|
BUILT_IN_FUNCTIONS = ChainMap({
|
||||||
|
'putc':[('PUTC',)],
|
||||||
|
'scanc':[('SCANC',)],
|
||||||
|
'mod':[
|
||||||
|
|
||||||
|
('')
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
class Ast_to_IR:
|
class Ast_to_IR:
|
||||||
|
|
||||||
def __init__(self,ast):
|
def __init__(self,ast,functions=BUILT_IN_FUNCTIONS):
|
||||||
self.ast = ast
|
self.ast = ast
|
||||||
|
self.functions = functions
|
||||||
|
|
||||||
def add(self,val):
|
def add(self,val):
|
||||||
self.ir.append(val)
|
self.ir.append(val)
|
||||||
|
|
||||||
def convert(self):
|
def convert(self):
|
||||||
|
|
||||||
|
if isinstance(self.ast,ProgramNode):
|
||||||
|
statements = self.ast.list_of_statement
|
||||||
|
args = []
|
||||||
|
block = self.ast
|
||||||
|
elif isinstance(self.ast,FunctionDefNode):
|
||||||
|
statements = self.ast.block.list_of_statement
|
||||||
|
args = self.ast.args
|
||||||
|
block = self.ast.block
|
||||||
|
|
||||||
|
|
||||||
self.ir = []
|
self.ir = []
|
||||||
|
self.functions = self.functions.new_child()
|
||||||
|
for statement in statements:
|
||||||
|
if isinstance(statement,FunctionDefNode):
|
||||||
|
self.functions[statement.name] = Ast_to_IR(statement,self.functions).convert()
|
||||||
|
|
||||||
|
|
||||||
vars_ = []
|
vars_ = []
|
||||||
for statemement in self.ast.list_of_statement:
|
for statement in statements:
|
||||||
if isinstance(statemement,DeclarationNode):
|
if isinstance(statement,DeclarationNode):
|
||||||
vars_.extend(statemement.names)
|
vars_.extend(statement.names)
|
||||||
vars_ = {val:index for index,val in enumerate(vars_)}
|
|
||||||
self.vars = vars_
|
all_vars = {val:index for index,val in enumerate((args+vars_)[::-1])}
|
||||||
|
self.vars = all_vars
|
||||||
self.pos = 0
|
self.pos = 0
|
||||||
|
|
||||||
self.add(('INIT',len(vars_)))
|
nb_decalage = len(vars_) - (1 if isinstance(self.ast,ProgramNode) else 0)
|
||||||
self.push_block(self.ast)
|
self.add(('INIT_FUNCTION',nb_decalage ,self.ast.name))
|
||||||
|
self.push_block(block)
|
||||||
|
if isinstance(self.ast,FunctionDefNode):
|
||||||
|
self.add(('END_FUNCTION',len(all_vars),self.ast.name))
|
||||||
return self.ir
|
return self.ir
|
||||||
|
|
||||||
def push_block(self,node):
|
def push_block(self,node):
|
||||||
|
@ -390,6 +492,9 @@ class Ast_to_IR:
|
||||||
self.add(('ASSIGN',assign_distance,node.target.name))
|
self.add(('ASSIGN',assign_distance,node.target.name))
|
||||||
self.pos -= 1
|
self.pos -= 1
|
||||||
|
|
||||||
|
def return_to_ir(self,node):
|
||||||
|
self.push_expr(node.expr)
|
||||||
|
|
||||||
def expression_statement_to_ir(self,node):
|
def expression_statement_to_ir(self,node):
|
||||||
self.push_expr(node)
|
self.push_expr(node)
|
||||||
self.pos -= 1
|
self.pos -= 1
|
||||||
|
@ -403,6 +508,19 @@ class Ast_to_IR:
|
||||||
self.add(('DEC',assign_distance,node.name.name))
|
self.add(('DEC',assign_distance,node.name.name))
|
||||||
|
|
||||||
def push_expr(self,node):
|
def push_expr(self,node):
|
||||||
|
|
||||||
|
if isinstance(node,FunctionCallNode):
|
||||||
|
for arg in node.args:
|
||||||
|
self.push_expr(arg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.ir.extend(self.functions[node.name])
|
||||||
|
except KeyError:
|
||||||
|
raise SyntaxError(f"The function {node.name} doesn't exist")
|
||||||
|
self.pos -= len(node.args)
|
||||||
|
self.pos += 1
|
||||||
|
return
|
||||||
|
|
||||||
if isinstance(node,NumberNode):
|
if isinstance(node,NumberNode):
|
||||||
self.pos += 1
|
self.pos += 1
|
||||||
self.add(('PUSH_NUMBER',node.value))
|
self.add(('PUSH_NUMBER',node.value))
|
||||||
|
@ -449,7 +567,9 @@ class Ast_to_IR:
|
||||||
|
|
||||||
methods = {
|
methods = {
|
||||||
DeclarationNode: lambda self,node:None,
|
DeclarationNode: lambda self,node:None,
|
||||||
|
FunctionDefNode: lambda self,node:None,
|
||||||
AssignementNode: Ast_to_IR.assignement_to_ir,
|
AssignementNode: Ast_to_IR.assignement_to_ir,
|
||||||
|
ReturnNode: Ast_to_IR.return_to_ir,
|
||||||
WhileNode: Ast_to_IR.while_to_ir,
|
WhileNode: Ast_to_IR.while_to_ir,
|
||||||
IfNode: Ast_to_IR.if_to_ir,
|
IfNode: Ast_to_IR.if_to_ir,
|
||||||
IncDecNode: Ast_to_IR.inc_dec_to_ir,
|
IncDecNode: Ast_to_IR.inc_dec_to_ir,
|
||||||
|
@ -459,8 +579,14 @@ default = Ast_to_IR.expression_statement_to_ir
|
||||||
|
|
||||||
#************
|
#************
|
||||||
|
|
||||||
def init(nb):
|
|
||||||
return '>' * (nb-1) + f' INIT {nb}'
|
|
||||||
|
def init_function(nb,name):
|
||||||
|
return '>' * nb + f' INIT_FUNCTION {name}'
|
||||||
|
|
||||||
|
def end_function(nb,name):
|
||||||
|
return '<[-]' * nb + '>' * nb + (f"[-{'<'*nb}+{'>'*nb}]" if nb else "") + '<' * nb+ f' END_FUNCTION {name}'
|
||||||
|
|
||||||
|
|
||||||
def assign(val,name):
|
def assign(val,name):
|
||||||
return f"{'<'*val}[-]{'>'*val}[-{'<'*val}+{'>'*val}]< ASSIGN {name}"
|
return f"{'<'*val}[-]{'>'*val}[-{'<'*val}+{'>'*val}]< ASSIGN {name}"
|
||||||
|
@ -481,13 +607,34 @@ def push_var(val,name):
|
||||||
return '<' * (val-1) + f"[-{'>'*val}+>+<{'<'*val}]" + f"{'>'*val}>[-<{'<'*val}+>{'>'*val}]<" + f" PUSH_VAR {name}"
|
return '<' * (val-1) + f"[-{'>'*val}+>+<{'<'*val}]" + f"{'>'*val}>[-<{'<'*val}+>{'>'*val}]<" + f" PUSH_VAR {name}"
|
||||||
|
|
||||||
def bin_op(op):
|
def bin_op(op):
|
||||||
if op == "+":
|
if op == '+':
|
||||||
bf = "[-<+>]<"
|
bf = "[-<+>]<"
|
||||||
elif op == "-":
|
elif op == '-':
|
||||||
bf = "[-<->]<"
|
bf = "[-<->]<"
|
||||||
|
elif op == '*':
|
||||||
|
bf = "<[->>+<<]>[->[-<<+>>>+<]>[-<+>]<<]>[-]<<"
|
||||||
|
elif op == '/':
|
||||||
|
bf = "[->+>>+<<<]<[->+>>+<<<]>>>[>[->+>+<<]>>[-<<+>>]+<[>-<[-]]>[->+>+<<]>>[-<<+>>]<[<<<<[-]+>+>>>-]<<<-<-]+>[<->[-]]<"
|
||||||
|
"[-<[-<->>+<]>[-<+>]<<<+>[->>+>+<<<]>>>[-<<<+>>>]<<[->>+>+<<<]>>>[-<<<+>>>]<<[>[->+>+<<]>>[-<<+>>]+<[>-<[-]]>[->+>+<<]>"
|
||||||
|
">[-<<+>>]<[<<<<[-]+>+>>>-]<<<-<-]>>>[<<<+>>>-]<<<#]<[-]<[-]<"
|
||||||
|
|
||||||
|
elif op == '==':
|
||||||
|
bf = "<[>[->+>+<<]>>[-<<+>>]+<[>-<[-]]>[->+>+<<]>>[-<<+>>]<[<<<<[-]+>+>>>-]<<<-<-]" + "+>[<->[-]]>>[<<<->>>-]<<<"
|
||||||
|
elif op == '!=':
|
||||||
|
bf = "<[>[->+>+<<]>>[-<<+>>]+<[>-<[-]]>[->+>+<<]>>[-<<+>>]<[<<<<[-]+>+>>>-]<<<-<-]" + ">[<+>[-]]>>[<<<+>>>-]<<<"
|
||||||
|
elif op == '>':
|
||||||
|
bf = "<[>[->+>+<<]>>[-<<+>>]+<[>-<[-]]>[->+>+<<]>>[-<<+>>]<[<<<<[-]+>+>>>-]<<<-<-]" + ">>>[<<<+>>>-]<<<"
|
||||||
|
elif op == '>=':
|
||||||
|
bf = "<[>[->+>+<<]>>[-<<+>>]+<[>-<[-]]>[->+>+<<]>>[-<<+>>]<[<<<<[-]+>+>>>-]<<<-<-]" + "+>[<->[-]]<"
|
||||||
|
elif op == '<':
|
||||||
|
bf = "<[>[->+>+<<]>>[-<<+>>]+<[>-<[-]]>[->+>+<<]>>[-<<+>>]<[<<<<[-]+>+>>>-]<<<-<-]" + ">[<+>[-]]<"
|
||||||
|
elif op == '<=':
|
||||||
|
bf = "<[>[->+>+<<]>>[-<<+>>]+<[>-<[-]]>[->+>+<<]>>[-<<+>>]<[<<<<[-]+>+>>>-]<<<-<-]" + "+>>>[<<<->>>-]<<<"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception(f"bin_op {op} not implemented yet")
|
raise Exception(f"bin_op {op} not implemented yet")
|
||||||
return bf + f" BIN_OP {op if op not in ('+','-') else {'+':'plus','-':'minus'}[op]}"
|
return bf + f" BIN_OP " +\
|
||||||
|
(op if op not in ('+','-','<','>','<=','>=') else {'+':'plus','-':'minus','>':'gt','<':'st','>=':'gt_eq','<=':'st_eq'}[op])
|
||||||
|
|
||||||
def while_enter():
|
def while_enter():
|
||||||
return "[[-]< WHILE_ENTER"
|
return "[[-]< WHILE_ENTER"
|
||||||
|
@ -507,16 +654,47 @@ def else_end():
|
||||||
def if_end():
|
def if_end():
|
||||||
return "<]>[-]<< IF_END"
|
return "<]>[-]<< IF_END"
|
||||||
|
|
||||||
|
def putc():
|
||||||
|
return ". PRINT"
|
||||||
|
|
||||||
|
def scanc():
|
||||||
|
return ", INPUT"
|
||||||
|
|
||||||
|
|
||||||
def compile_ir(ir):
|
def compile_ir(ir):
|
||||||
return '\n'.join(globals()[i[0].lower()](*i[1:]) for i in ir)
|
return '\n'.join(globals()[i[0].lower()](*i[1:]) for i in ir)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#**************
|
#**************
|
||||||
|
|
||||||
def compile(prog):
|
def compile(prog,level=4):
|
||||||
tokens = lex(prog)
|
tokens = lex(prog)
|
||||||
|
if level == 1:
|
||||||
|
return tokens
|
||||||
ast = Parser(tokens).parse()
|
ast = Parser(tokens).parse()
|
||||||
|
if level == 2:
|
||||||
|
return ast
|
||||||
ir = Ast_to_IR(ast).convert()
|
ir = Ast_to_IR(ast).convert()
|
||||||
|
if level == 3:
|
||||||
|
return ir
|
||||||
brainfuck = compile_ir(ir)
|
brainfuck = compile_ir(ir)
|
||||||
return brainfuck
|
return brainfuck
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import sys
|
||||||
|
try:
|
||||||
|
file = sys.argv[1]
|
||||||
|
except IndexError:
|
||||||
|
raise Exception("You must set a file")
|
||||||
|
|
||||||
|
prog = open(file).read()
|
||||||
|
bf_prog = compile(prog)
|
||||||
|
with open(os.path.splitext(file)[0]+'.bf','w') as f:
|
||||||
|
f.write(bf_prog)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue