Skip to content

Instantly share code, notes, and snippets.

@tautologico
Created June 21, 2016 04:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tautologico/e93ce90c8fe8bf31c9e867d24b1b8fec to your computer and use it in GitHub Desktop.
Save tautologico/e93ce90c8fe8bf31c9e867d24b1b8fec to your computer and use it in GitHub Desktop.
//
// Linguagem de expressoes aritmeticas
// Interpretador, compilador para maquina de pilha
//
//--- expressoes aritmeticas ---------------------
enum Exp {
case Const(Int)
indirect case Soma(Exp, Exp)
indirect case Sub(Exp, Exp)
indirect case Mult(Exp, Exp)
}
func showExp(e: Exp) -> String {
switch e {
case let .Const(i):
return String(i)
case let .Soma(e1, e2):
return "(\(showExp(e1)) + \(showExp(e2)))"
case let .Sub(e1, e2):
return "(\(showExp(e1)) - \(showExp(e2)))"
case let .Mult(e1, e2):
return "(\(showExp(e1)) * \(showExp(e2)))"
}
}
func eval(e: Exp) -> Int {
switch e {
case let .Const(i):
return i
case let .Soma(e1, e2):
return eval(e1) + eval(e2)
case let .Sub(e1, e2):
return eval(e1) - eval(e2)
case let .Mult(e1, e2):
return eval(e1) * eval(e2)
}
}
//--- maquina de pilha ---------------------------
enum Operacao {
case OpSoma
case OpSub
case OpMult
}
enum Instrucao {
case Empilha(Int)
case Oper(Operacao)
}
struct Pilha {
var itens = [Int]()
mutating func empilha(i: Int) {
self.itens.append(i)
}
func topo() -> Int? {
return self.itens.last
}
mutating func operandos() -> (Int, Int)? {
if self.itens.count < 2 {
return nil
} else {
let r1 = self.itens.removeLast()
let r2 = self.itens.removeLast()
return (r1, r2)
}
}
}
extension Operacao {
func oper() -> (Int, Int) -> Int {
switch self {
case .OpSoma:
return (+)
case .OpSub:
return (-)
case .OpMult:
return (*)
}
}
}
func execInst(i: Instrucao, inout pilha: Pilha) {
switch i {
case let .Empilha(i):
pilha.empilha(i)
case let .Oper(op):
if let (v1, v2) = pilha.operandos() {
pilha.empilha(op.oper()(v1, v2))
}
}
}
func execProg(prog: [Instrucao]) -> Pilha {
var p = Pilha()
for i in prog {
execInst(i, pilha: &p)
}
return p
}
func executa(prog: [Instrucao]) -> Int? {
let pilha = execProg(prog)
return pilha.topo()
}
let p1 = [Instrucao.Empilha(5),
Instrucao.Empilha(7),
Instrucao.Oper(Operacao.OpSoma),
Instrucao.Empilha(10),
Instrucao.Oper(Operacao.OpMult)]
if let res = executa(p1) {
print("resultado do programa: \(res)")
} else {
print("programa sem resultado")
}
func compila(e: Exp) -> [Instrucao] {
switch e {
case let .Const(i):
return [Instrucao.Empilha(i)]
case let .Soma(e1, e2):
var prog = compila(e2)
prog.appendContentsOf(compila(e1))
prog.append(Instrucao.Oper(Operacao.OpSoma))
return prog
case let .Sub(e1, e2):
var prog = compila(e2)
prog.appendContentsOf(compila(e1))
prog.append(Instrucao.Oper(Operacao.OpSub))
return prog
case let .Mult(e1, e2):
var prog = compila(e2)
prog.appendContentsOf(compila(e1))
prog.append(Instrucao.Oper(Operacao.OpMult))
return prog
}
}
let e1 = Exp.Mult(Exp.Const(3),
Exp.Soma(Exp.Const(4), Exp.Const(2)))
print(compila(e1))
print(eval(e1))
print(executa(compila(e1)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment