First past and printer function are totally ready
[TinyThreePassCompiler/.git] / compiler.go
1 package main
2
3 import (
4         "fmt"
5         "strings"
6
7         "golang.org/x/exp/slices"
8 )
9
10 type op int
11
12 const (
13         imm op = iota
14         arg
15         plus
16         min
17         mul
18         div
19 )
20
21 type AST struct {
22         Op     op
23         Left   *AST
24         Right  *AST
25         Value  int
26         Parent *AST
27 }
28
29 func main() {
30         //a := &AST{Op: imm, N: 5
31         //b := &AST{Op: plus, A: a, B: &AST{Op: arg, N: 0}}
32         input := "[ a b ] (a*a) + (b*b)"
33         //value := []rune(input)
34
35         variables, program := extractVariables(input)
36
37         fmt.Println(variables, program)
38         Tree := AST{}
39         firstPass(variables, program, &Tree)
40         fmt.Println(Tree)
41         printer(&Tree)
42         //si es una letra y el stack esta sin setear pon en el A del stack un AST arg
43         //si es una operacion setea la op en el stack
44         //si es un abrir parentesis apunta al lado que este disponible del AST
45         //si es una letra y ya esta seteada la op mete un AST arg a la otra letra
46         //si es un cerrar parentesis coge para el pai.
47
48         //los numeros se portan justo como las letras.
49
50 }
51
52 func printer(tree *AST) {
53         switch {
54         case tree.Op == imm:
55                 fmt.Print(tree.Value - 48)
56         case tree.Op == arg:
57                 fmt.Printf("%c", tree.Value)
58         default:
59                 fmt.Print("(")
60                 switch tree.Op {
61                 case min:
62                         fmt.Print("-")
63                 case plus:
64                         fmt.Print("+")
65                 case div:
66                         fmt.Print("/")
67                 case mul:
68                         fmt.Print("*")
69                 }
70                 fmt.Print(",")
71                 printer(tree.Left)
72                 fmt.Print(",")
73                 printer(tree.Right)
74                 fmt.Print(")")
75
76         }
77 }
78
79 func firstPass(variables, program []rune, node *AST) {
80         pass := node
81         switch program[0] {
82         case '-':
83                 node.Op = min
84         case '+':
85                 node.Op = plus
86         case '*':
87                 node.Op = mul
88         case '/':
89                 node.Op = div
90         case '(':
91                 if node.Left == nil {
92                         node.Left = &AST{}
93                         node.Left.Parent = node
94                         pass = node.Left
95                 } else {
96                         node.Right = &AST{}
97                         node.Right.Parent = node
98                         pass = node.Right
99                 }
100         case ')':
101                 pass = node.Parent
102
103         default:
104                 if program[0] > 47 && program[0] < 58 {
105                         var zeroOp op
106                         if node.Op == zeroOp {
107                                 node.Left = &AST{Op: imm, Value: int(program[0]) - 48}
108                                 //a := &AST{Op: imm, N: 5
109                         } else {
110                                 node.Right = &AST{Op: imm, Value: int(program[0]) - 48}
111                         }
112                 } else if slices.Contains(variables, program[0]) {
113                         //var zeroOp op
114                         if node.Op != 2 && node.Op != 3 && node.Op != 4 && node.Op != 5 {
115                                 node.Left = &AST{Op: arg, Value: int(program[0])}
116                                 //a := &AST{Op: imm, N: 5
117                         } else {
118                                 node.Right = &AST{Op: arg, Value: int(program[0])}
119                         }
120
121                 }
122
123         }
124         if len(program) > 1 {
125                 firstPass(variables, program[1:], pass)
126
127         }
128         return
129
130 }
131
132 // extractVariables receives the original program string and converts it in
133 // two rune slices, the first containing the variables and a second containing
134 // the trimmed program
135 func extractVariables(input string) ([]rune, []rune) {
136         variables := strings.Split(input, "]")
137         // Cleaning out the variables that are gettting extracted
138         variables[0] = strings.Split(variables[0], "[")[1]
139         variables[0] = strings.Trim(variables[0], " ")
140         cleanVariables := []rune(variables[0])
141         var resultVariables []rune
142         for _, v := range cleanVariables {
143                 if v != ' ' {
144                         resultVariables = append(resultVariables, v)
145                 }
146         }
147
148         //Cleaning out the program that is getting extracted
149         variables[1] = strings.Trim(variables[1], " ")
150         cleanProgram := []rune(variables[1])
151         var resultProgram []rune
152         for _, v := range cleanProgram {
153                 if v != ' ' {
154                         resultProgram = append(resultProgram, v)
155
156                 }
157
158         }
159
160         return resultVariables, resultProgram
161 }