4ad5e55090da421ad08fc1a97dd652d970657464
[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         var Tree AST
39         firstPass(program, &Tree)
40         //si es una letra y el stack esta sin setear pon en el A del stack un AST arg
41         //si es una operacion setea la op en el stack
42         //si es un abrir parentesis apunta al lado que este disponible del AST
43         //si es una letra y ya esta seteada la op mete un AST arg a la otra letra
44         //si es un cerrar parentesis coge para el pai.
45
46         //los numeros se portan justo como las letras.
47
48 }
49
50 func firstPass(variables, program []rune, node *AST) {
51         switch program[0] {
52         case '-':
53                 node.Op = min
54                 firstPass(variables, program[1:], node)
55         case '+':
56                 node.Op = plus
57                 firstPass(variables, program[1:], node)
58         case '*':
59                 node.Op = mul
60                 firstPass(variables, program[1:], node)
61         case '/':
62                 node.Op = div
63                 firstPass(variables, program[1:], node)
64         case '(':
65                 if node.Left != nil {
66                         firstPass(variables, program[1:], node.Left)
67                 } else {
68                         firstPass(variables, program[1:], node.Right)
69                 }
70         case ')':
71                 return
72
73         default:
74                 if program[0] > 47 && program[0] < 58 {
75                         var zeroOp op
76                         if node.Op == zeroOp {
77                                 node.Left = &AST{Op: imm, Value: int(program[0]) - 48}
78                                 firstPass(variables, program[1:], node)
79                                 //a := &AST{Op: imm, N: 5
80                         } else {
81                                 node.Right = &AST{Op: imm, Value: int(program[0]) - 48}
82                                 firstPass(variables, program[1:], node)
83                         }
84                 } else if slices.Contains(variables, program[0]) {
85                         var zeroOp op
86                         if node.Op == zeroOp {
87                                 node.Left = &AST{Op: imm, Value: int(program[0]) - 48}
88                                 firstPass(variables, program[1:], node)
89                                 //a := &AST{Op: imm, N: 5
90                         } else {
91                                 node.Right = &AST{Op: imm, Value: int(program[0]) - 48}
92                                 firstPass(variables, program[1:], node)
93                         }
94
95                 }
96
97         }
98         return
99
100 }
101
102 // extractVariables receives the original program string and converts it in
103 // two rune slices, the first containing the variables and a second containing
104 // the trimmed program
105 func extractVariables(input string) ([]rune, []rune) {
106         variables := strings.Split(input, "]")
107         // Cleaning out the variables that are gettting extracted
108         variables[0] = strings.Split(variables[0], "[")[1]
109         variables[0] = strings.Trim(variables[0], " ")
110         cleanVariables := []rune(variables[0])
111         var resultVariables []rune
112         for _, v := range cleanVariables {
113                 if v != ' ' {
114                         resultVariables = append(resultVariables, v)
115                 }
116         }
117
118         //Cleaning out the program that is getting extracted
119         variables[1] = strings.Trim(variables[1], " ")
120         cleanProgram := []rune(variables[1])
121         var resultProgram []rune
122         for _, v := range cleanProgram {
123                 if v != ' ' {
124                         resultProgram = append(resultProgram, v)
125
126                 }
127
128         }
129
130         return resultVariables, resultProgram
131 }