X-Git-Url: https://git.josue.xyz/?a=blobdiff_plain;f=compiler.go;h=e928218affb8275dac9a52a98f29b6c603c29b4e;hb=HEAD;hp=6cd94fd9c70a8003efb97fbc030955e9a4228291;hpb=cca4b9fd2a0839a6eb50edc9f09963288b5f0e41;p=TinyThreePassCompiler%2F.git diff --git a/compiler.go b/compiler.go index 6cd94fd..e928218 100644 --- a/compiler.go +++ b/compiler.go @@ -27,32 +27,28 @@ type AST struct { } func main() { - //a := &AST{Op: imm, N: 5 - //b := &AST{Op: plus, A: a, B: &AST{Op: arg, N: 0}} - input := "[ a b ] (a*a) + (b*b)" - //value := []rune(input) + //TODO(josuer08): Change this for a argv reader and all of the printing can + // be moved to writing to a file or just use standalone with redirection not + //quite sure about it. + input := "[ a b ] ((a*b) + (5*5))-3" variables, program := extractVariables(input) - - fmt.Println(variables, program) + //fmt.Println(variables, program) Tree := AST{} firstPass(variables, program, &Tree) - fmt.Println(Tree) - printer(&Tree) - //si es una letra y el stack esta sin setear pon en el A del stack un AST arg - //si es una operacion setea la op en el stack - //si es un abrir parentesis apunta al lado que este disponible del AST - //si es una letra y ya esta seteada la op mete un AST arg a la otra letra - //si es un cerrar parentesis coge para el pai. - - //los numeros se portan justo como las letras. + //fmt.Println(Tree) + secondPass(&Tree) + slices.Sort(variables) + thirdPass(&Tree, variables) + //printer(&Tree) } +// printer si a function that prints in Reverse Pollish Notation the AST func printer(tree *AST) { switch { case tree.Op == imm: - fmt.Print(tree.Value - 48) + fmt.Print(tree.Value) case tree.Op == arg: fmt.Printf("%c", tree.Value) default: @@ -76,6 +72,8 @@ func printer(tree *AST) { } } +// firstPass Is a function that makes the first pass of the compiler, +// it converts the variable and program into an AST func firstPass(variables, program []rune, node *AST) { pass := node switch program[0] { @@ -105,27 +103,107 @@ func firstPass(variables, program []rune, node *AST) { var zeroOp op if node.Op == zeroOp { node.Left = &AST{Op: imm, Value: int(program[0]) - 48} - //a := &AST{Op: imm, N: 5 } else { node.Right = &AST{Op: imm, Value: int(program[0]) - 48} } } else if slices.Contains(variables, program[0]) { - //var zeroOp op - if node.Op != 2 && node.Op != 3 && node.Op != 4 && node.Op != 5 { + if node.Op != plus && node.Op != min && node.Op != mul && node.Op != div { node.Left = &AST{Op: arg, Value: int(program[0])} - //a := &AST{Op: imm, N: 5 } else { node.Right = &AST{Op: arg, Value: int(program[0])} } - } - } if len(program) > 1 { firstPass(variables, program[1:], pass) + } +} + +// secondPass takes an AST and reduces the operations that only include imm +// values so the program results in a more compact one with precalculated imms +func secondPass(node *AST) { + if node.Op == arg { + return + } + if node.Op == imm { + return + } + if node.Right.Op == imm && node.Left.Op == imm { + switch node.Op { + case min: + node.Value = node.Left.Value - node.Right.Value + case plus: + node.Value = node.Left.Value + node.Right.Value + case mul: + node.Value = node.Left.Value * node.Right.Value + case div: + node.Value = node.Left.Value / node.Right.Value + } + node.Op = imm + node.Left = nil + node.Right = nil + return + } + if node.Left.Op != arg && node.Left.Op != imm { + secondPass(node.Left) + } + if node.Right.Op != arg && node.Right.Op != imm { + secondPass(node.Right) + } +} + +func thirdPass(node *AST, variables []rune) { + switch node.Op { + case arg: + number, found := slices.BinarySearch(variables, rune(node.Value)) + if found { + fmt.Printf("AR %d\n", number) + } + case imm: + fmt.Printf("IM %d\n", node.Value) + default: + switch node.Left.Op { + case arg: + number, valid := slices.BinarySearch(variables, rune(node.Left.Value)) + if valid { + fmt.Printf("AR %d\n", number) + } + case imm: + fmt.Printf("IM %d\n", node.Left.Value) + default: + thirdPass(node.Left, variables) + } + switch node.Right.Op { + case arg: + fmt.Println("SW") + number, valid := slices.BinarySearch(variables, rune(node.Right.Value)) + if valid { + fmt.Printf("AR %d\n", number) + } + fmt.Println("SW") + case imm: + fmt.Println("SW") + fmt.Printf("IM %d\n", node.Right.Value) + fmt.Println("SW") + default: + fmt.Println("PU") + thirdPass(node.Right, variables) + fmt.Println("SW") + fmt.Println("PO") + } + switch node.Op { + case mul: + fmt.Println("MU") + case div: + fmt.Println("DI") + case min: + fmt.Println("SU") + case plus: + fmt.Println("AD") + + } } - return } @@ -144,7 +222,6 @@ func extractVariables(input string) ([]rune, []rune) { resultVariables = append(resultVariables, v) } } - //Cleaning out the program that is getting extracted variables[1] = strings.Trim(variables[1], " ") cleanProgram := []rune(variables[1]) @@ -152,10 +229,7 @@ func extractVariables(input string) ([]rune, []rune) { for _, v := range cleanProgram { if v != ' ' { resultProgram = append(resultProgram, v) - } - } - return resultVariables, resultProgram }