X-Git-Url: https://git.josue.xyz/?a=blobdiff_plain;f=compiler.go;h=ec17a44ee24a6738ed662608bcef72ef0ed40d3d;hb=05081b20e8fd940323137692ba21ba095bfedd6c;hp=1585cb3e53c5342dd0e3b4d158e639dfa9fd110c;hpb=c30c4fa892bda93ae2af21986ca0aea1a5d6e4c4;p=TinyThreePassCompiler%2F.git diff --git a/compiler.go b/compiler.go index 1585cb3..ec17a44 100644 --- a/compiler.go +++ b/compiler.go @@ -1,45 +1,185 @@ package main -import "fmt" +import ( + "fmt" + "strings" + + "golang.org/x/exp/slices" +) type op int const ( - imm op = iota - arg - plus - min - mul - div + imm op = iota + arg + plus + min + mul + div ) type AST struct { - Op op - A *AST - B *AST - N int + Op op + Left *AST + Right *AST + Value int + Parent *AST } +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) + (5*5)" + + variables, program := extractVariables(input) + fmt.Println(variables, program) + Tree := AST{} + firstPass(variables, program, &Tree) + fmt.Println(Tree) + secondPass(&Tree) + printer(&Tree) -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) - for index, char := range value { - //make a stack and start pusing the [] to identify the start of a function and its end - //also check on a *-+/ for starting new operations with the last value and the next - //or can be a ( which pushes last value to a stack and picks up a new "first value" for this operation and ) indicating that order of operation is finish and - //you should pull again the last value that you pushed - - //found [ start registering args to a map - // variable inside [] add to map of variables - // found ] stop registering new variables for the map - // found variable put to stack - // found inmmediate number put to stack - // found operation activate operation mode and upon next variable or inmediate add to the structure - // found ( can push another variable to stack and increment the indent counter - // found ) if no operation mode (that would be an error) then add the operations to the structure and decrement the indnet counter - } +} + +func printer(tree *AST) { + switch { + case tree.Op == imm: + fmt.Print(tree.Value) + case tree.Op == arg: + fmt.Printf("%c", tree.Value) + default: + fmt.Print("(") + switch tree.Op { + case min: + fmt.Print("-") + case plus: + fmt.Print("+") + case div: + fmt.Print("/") + case mul: + fmt.Print("*") + } + fmt.Print(",") + printer(tree.Left) + fmt.Print(",") + printer(tree.Right) + fmt.Print(")") + + } +} + +func firstPass(variables, program []rune, node *AST) { + pass := node + switch program[0] { + case '-': + node.Op = min + case '+': + node.Op = plus + case '*': + node.Op = mul + case '/': + node.Op = div + case '(': + if node.Left == nil { + node.Left = &AST{} + node.Left.Parent = node + pass = node.Left + } else { + node.Right = &AST{} + node.Right.Parent = node + pass = node.Right + } + case ')': + pass = node.Parent + + default: + if program[0] > 47 && program[0] < 58 { + 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 { + 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) + + } + return + +} +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) + } +} + +// extractVariables receives the original program string and converts it in +// two rune slices, the first containing the variables and a second containing +// the trimmed program +func extractVariables(input string) ([]rune, []rune) { + variables := strings.Split(input, "]") + // Cleaning out the variables that are gettting extracted + variables[0] = strings.Split(variables[0], "[")[1] + variables[0] = strings.Trim(variables[0], " ") + cleanVariables := []rune(variables[0]) + var resultVariables []rune + for _, v := range cleanVariables { + if v != ' ' { + resultVariables = append(resultVariables, v) + } + } + + //Cleaning out the program that is getting extracted + variables[1] = strings.Trim(variables[1], " ") + cleanProgram := []rune(variables[1]) + var resultProgram []rune + for _, v := range cleanProgram { + if v != ' ' { + resultProgram = append(resultProgram, v) + + } + + } + + return resultVariables, resultProgram }