/
misc.go
134 lines (116 loc) · 3.5 KB
/
misc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package basparser
// misc.go extracted from header/footer of parser.y
import (
"fmt"
"log"
"strings"
"github.com/udhos/basgo/node"
)
type ParserResult struct {
Root []node.Node
LineNumbers map[string]node.LineNumber // used by GOTO GOSUB etc
LibReadData bool
LibGosubReturn bool
LibMath bool
Baslib bool
ForStack []*node.NodeFor
WhileStack []*node.NodeWhile
CountFor int
CountNext int
ArrayTable map[string]node.ArraySymbol
CountGosub int
CountReturn int
CountWhile int
CountWend int
CountIf int
FuncTable map[string]node.FuncSymbol
Imports map[string]struct{}
Declarations []string
RestoreTable map[string]int
DataOffset int
TypeTable []int
Graphics bool
}
// parser auxiliary variables
var (
//Result = newResult()
Result ParserResult
nodeListStack [][]node.Node // support nested node lists (1)
expListStack [][]node.NodeExp // support nested exp lists (2)
lineList []node.Node
constList []node.NodeExp
varList []node.NodeExp
numberList []string
identList []string
lastLineNum string // basic line number for parser error reporting
rangeList [][]string
// (1) stmt IF-THEN can nest list of stmt: THEN CLS:IF:CLS
// (2) exp can nest list of exp: array(exp,exp,exp)
nodeExpNull = &node.NodeExpNull{}
)
func newResult() ParserResult {
r := ParserResult{
LineNumbers: map[string]node.LineNumber{},
ArrayTable: map[string]node.ArraySymbol{},
FuncTable: map[string]node.FuncSymbol{},
Imports: map[string]struct{}{},
RestoreTable: map[string]int{},
}
r.TypeTable = make([]int, 26, 26)
defineType(&r, 0, 25, node.TypeFloat) // DEFSNG A-Z
return r
}
func defineType(r *ParserResult, first, last, t int) {
log.Printf("defineType: range %c-%c as %s", byte('a'+first), byte('a'+last), node.TypeLabel(t))
for i := first; i <= last; i++ {
r.TypeTable[i] = t
}
}
func defineTypeRange(r *ParserResult, list [][]string, t int) {
for _, p := range list {
first := int(p[0][0] - 'a')
last := int(p[1][0] - 'a')
defineType(&Result, first, last, t)
}
}
func Reset() {
Result = newResult()
nodeListStack = [][]node.Node{}
expListStack = [][]node.NodeExp{}
}
func isSymbol(ident, symbol string) bool {
return strings.ToLower(ident) == strings.ToLower(symbol)
}
func unsupportedEmpty(keyword string) *node.NodeEmpty {
log.Printf("ignoring unsupported keyword %s", keyword)
return &node.NodeEmpty{}
}
func createEndNode(result *ParserResult, msg string) *node.NodeEnd {
result.Baslib = true
return &node.NodeEnd{Message: msg}
}
func unsupportedEnd(result *ParserResult, keyword string) *node.NodeEnd {
log.Printf("unsupported keyword %s will halt the program", keyword)
msg := fmt.Sprintf("stopping on unsupported keyword %s", keyword)
result.Imports["log"] = struct{}{} // NodeEnd.Message uses log
return createEndNode(result, msg)
}
func captureRawLine(label string, list []node.Node, rawLine string) {
last := len(list) - 1
if last < 0 {
log.Printf("captureRawLine: %s last line index=%d < 0", label, last)
return
}
switch n := list[last].(type) {
case *node.LineNumbered:
n.RawLine = rawLine
list[last] = n
//log.Printf("captureRawLine: %s numbered index=%d raw=[%s]", label, last, n.RawLine)
case *node.LineImmediate:
n.RawLine = rawLine
list[last] = n
//log.Printf("captureRawLine: %s immediate index=%d raw=[%s]", label, last, n.RawLine)
default:
log.Printf("captureRawLine: %s non-line node: %v", label, list[last])
}
}