This repository has been archived by the owner on Apr 8, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathparser.go
136 lines (126 loc) · 3.43 KB
/
parser.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
135
136
package yoo
import (
"errors"
"strconv"
"io/ioutil"
)
func expression(ba *ByteArray, pool *[]string) (Any, error) {
ret, err := ba.ReadInt8()
if err != nil { return nil, err }
switch ret {
case CONSTANT_TRUE:
return true, nil
case CONSTANT_FALSE:
return false, nil
case CONSTANT_STRING:
id, err := ba.ReadInt16()
if err != nil { return nil, err }
return (*pool)[int(id)], nil
case CONSTANT_NUMBER:
length, err := ba.ReadInt16()
if err != nil { return nil, err }
text, err := ba.ReadString(int(length))
if err != nil { return nil, err }
return strconv.ParseFloat(text, 64)
case CONSTANT_IDENTIFIER:
return NewIdentifier(ba, pool)
case CONSTANT_CALL:
return NewCall(ba, pool)
case CONSTANT_MEMBER:
return NewMember(ba, pool)
case CONSTANT_VARIABLE:
return NewVariable(ba, pool)
case CONSTANT_IMPORT:
return NewImport(ba, pool)
case CONSTANT_NULL:
return nil, nil
case CONSTANT_ARROW_FUNCTION:
return NewArrowFunction(ba, pool)
case CONSTANT_NEW:
return NewMakeClass(ba, pool)
default:
return nil, errors.New("No such token: 0x" + strconv.FormatInt(int64(ret), 16))
}
}
func ParseFile(file string) (*Block, error) {
f, err := ioutil.ReadFile(file)
if err != nil { return nil, err }
return ParseBytes(f)
}
func ParseBytes(buff []byte) (ret Any, err error) {
ba := CreateByteArray(buff)
head, err := ba.ReadString(3)
if err != nil || head != "YOO" {
return errors.New("Header error")
}
version, _ := ba.ReadInt8()
if version != VERSION {
return errors.New("Version error")
}
length, _ := ba.ReadLength()
if err != nil {
return errors.New("Strings pool error")
}
pool := make([]string, length, length)
for i := 0; i < length; i++ {
len, err = ba.ReadLength()
if err != nil {
return
}
str, err = ba.ReadString(len)
if err != nil { return }
pool[i] = str
}
for {
t, err = ba.ReadInt8()
if err != nil { return }
switch t {
case CONSTANT_BLOCK:
length, err = ba.ReadLength()
if err != nil { return }
block := make(Block, length, length)
for i := int16(0); i < length; i++ {
expr, err := expression(ba, pool)
if err != nil { return nil, err }
block[i] = expr
}
case CONSTANT_TRUE:
return true, nil
case CONSTANT_FALSE:
return false, nil
case CONSTANT_STRING:
id, err := ba.ReadInt16()
if err != nil { return nil, err }
return (*pool)[int(id)], nil
case CONSTANT_NUMBER:
length, err := ba.ReadInt16()
if err != nil { return nil, err }
text, err := ba.ReadString(int(length))
if err != nil { return nil, err }
return strconv.ParseFloat(text, 64)
case CONSTANT_IDENTIFIER:
return NewIdentifier(ba, pool)
case CONSTANT_CALL:
return NewCall(ba, pool)
case CONSTANT_MEMBER:
return NewMember(ba, pool)
case CONSTANT_VARIABLE:
return NewVariable(ba, pool)
case CONSTANT_IMPORT:
return NewImport(ba, pool)
case CONSTANT_NULL:
return nil, nil
case CONSTANT_ARROW_FUNCTION:
return NewArrowFunction(ba, pool)
case CONSTANT_NEW:
return NewMakeClass(ba, pool)
default:
return nil, errors.New("No such token: 0x" + strconv.FormatInt(int64(ret), 16))
}
length, err := ba.ReadLength()
if err != nil {
return nil, errors.New("Strings pool error")
}
}
return NewBlock(ba, &pool)
}