appropiate printing for the printer function in the case of immidiate values
[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) + (5*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)
56                 //fmt.Print(tree.Value - 48)
57         case tree.Op == arg:
58                 fmt.Printf("%c", tree.Value)
59         default:
60                 fmt.Print("(")
61                 switch tree.Op {
62                 case min:
63                         fmt.Print("-")
64                 case plus:
65                         fmt.Print("+")
66                 case div:
67                         fmt.Print("/")
68                 case mul:
69                         fmt.Print("*")
70                 }
71                 fmt.Print(",")
72                 printer(tree.Left)
73                 fmt.Print(",")
74                 printer(tree.Right)
75                 fmt.Print(")")
76
77         }
78 }
79
80 func firstPass(variables, program []rune, node *AST) {
81         pass := node
82         switch program[0] {
83         case '-':
84                 node.Op = min
85         case '+':
86                 node.Op = plus
87         case '*':
88                 node.Op = mul
89         case '/':
90                 node.Op = div
91         case '(':
92                 if node.Left == nil {
93                         node.Left = &AST{}
94                         node.Left.Parent = node
95                         pass = node.Left
96                 } else {
97                         node.Right = &AST{}
98                         node.Right.Parent = node
99                         pass = node.Right
100                 }
101         case ')':
102                 pass = node.Parent
103
104         default:
105                 if program[0] > 47 && program[0] < 58 {
106                         var zeroOp op
107                         if node.Op == zeroOp {
108                                 node.Left = &AST{Op: imm, Value: int(program[0]) - 48}
109                                 //a := &AST{Op: imm, N: 5
110                         } else {
111                                 node.Right = &AST{Op: imm, Value: int(program[0]) - 48}
112                         }
113                 } else if slices.Contains(variables, program[0]) {
114                         //var zeroOp op
115                         if node.Op != 2 && node.Op != 3 && node.Op != 4 && node.Op != 5 {
116                                 node.Left = &AST{Op: arg, Value: int(program[0])}
117                                 //a := &AST{Op: imm, N: 5
118                         } else {
119                                 node.Right = &AST{Op: arg, Value: int(program[0])}
120                         }
121
122                 }
123
124         }
125         if len(program) > 1 {
126                 firstPass(variables, program[1:], pass)
127
128         }
129         return
130
131 }
132
133 // extractVariables receives the original program string and converts it in
134 // two rune slices, the first containing the variables and a second containing
135 // the trimmed program
136 func extractVariables(input string) ([]rune, []rune) {
137         variables := strings.Split(input, "]")
138         // Cleaning out the variables that are gettting extracted
139         variables[0] = strings.Split(variables[0], "[")[1]
140         variables[0] = strings.Trim(variables[0], " ")
141         cleanVariables := []rune(variables[0])
142         var resultVariables []rune
143         for _, v := range cleanVariables {
144                 if v != ' ' {
145                         resultVariables = append(resultVariables, v)
146                 }
147         }
148
149         //Cleaning out the program that is getting extracted
150         variables[1] = strings.Trim(variables[1], " ")
151         cleanProgram := []rune(variables[1])
152         var resultProgram []rune
153         for _, v := range cleanProgram {
154                 if v != ' ' {
155                         resultProgram = append(resultProgram, v)
156
157                 }
158
159         }
160
161         return resultVariables, resultProgram
162 }