0%

Js-Go:完善语句+实现类

语法分析

完善 switch 语句:

1
2
3
4
5
6
stm: ......
| 'switch' '(' expr ')' '{' case* default? '}'
......

case : 'case' expr ':' (stm ';'?)*;
default: 'default' ':' (stm ';'?)*;

核心代码如下:

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
if str_1 == "switch" {
var key bool = false
vaule, _ := h.handExpr(stm.GetChild(2).(*Jsp.ExprContext))
for i := 0; i < stm.GetChildCount()-7; i++ {
num, _ := h.handExpr(stm.GetChild(i + 5).GetChild(1).(*Jsp.ExprContext))
if num.getString() == vaule.getString() || key {
key = true
if h.isBreak {
h.isBreak = false
break
}
for y := 0; y < stm.GetChild(i+5).GetChildCount()-2; y++ {
if stm.GetChild(i+5).GetChild(y+2).GetChild(0) != nil {
h.handStm(stm.GetChild(i + 5).GetChild(y + 2).(*Jsp.StmContext))
}
}
}
}
if !key {
for y := 0; y < stm.GetChild(stm.GetChildCount()-2).GetChildCount(); y++ {
if stm.GetChild(stm.GetChildCount()-2).GetChild(y).GetChild(0) != nil {
h.handStm(stm.GetChild(stm.GetChildCount() - 2).GetChild(y).(*Jsp.StmContext))
}
}
}
}

为了使 switch 语句成立,这里添加了 break continue 语句的实现:

1
2
3
4
5
6
7
8
if str_1 == "break" {
h.isBreak = true
return nil, 0
}
if str_1 == "continue" {
h.isContinue = true
return nil, 0
}
  • 另外在 for 语句和 while 语句中也添加了对 break continue 的处理
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
if str_1 == "while" {
for {
if h.isBreak {
h.isBreak = false
break
}
if h.isContinue {
h.isContinue = false
continue
}
vaule, typ := h.handExpr(stm.GetChild(2).(*Jsp.ExprContext))
if ok := h.checkExpr(vaule, typ); !ok {
break
}
h.handBlock(stm.GetChild(4).(*Jsp.BlockContext))
}
}
if str_1 == "for" {
var smts [3]*Jsp.StmContext
var index int = 0
for _, c := range stm.GetChildren() {
_, ok := c.(*Jsp.StmContext)
if tmp := fmt.Sprintf("%v", c); tmp == ";" {
index++
}
if c.GetChild(0) != nil && ok {
smts[index] = c.(*Jsp.StmContext)
}
}
if smts[0] != nil {
h.handStm(smts[0])
}
for {
if h.isBreak {
h.isBreak = false
break
}
if h.isContinue {
h.isContinue = false
continue
}
if smts[1] != nil {
vaule, typ := h.handStm(smts[1])
if ok := h.checkExpr(vaule, typ); !ok {
break
}
}
h.handBlock(stm.GetChild(stm.GetChildCount() - 1).(*Jsp.BlockContext))
if smts[2] != nil {
h.handStm(smts[2])
}
}
}

Class 的实现

对于一个类而言,需要记录的数据有:名称,变量,方法

1
2
3
4
5
type Class struct {
name string
vars []string
funcs map[string]*Fuction
}

将 Class 添加到 SymTable 中:

1
2
3
4
5
6
type SymTable struct {
Fuctions []Fuction
Classes []*Class
InFuctions inFunction
scope *Scope
}
  • 附加的内置函数如下:
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
func NewClass(name string) *Class {
return &Class{name: name,
vars: []string{},
funcs: map[string]*Fuction{},
}
}

func (vl *SymTable) getClass(name string) (*Class, bool) {
for _, c := range vl.Classes {
if name == c.name {
return c, true
}
}
return nil, false
}

func (vl *SymTable) addClass(class *Class) {
vl.Classes = append(vl.Classes, class)
}

func (c *Class) addVar(name string) {
c.vars = append(c.vars, name)
}

func (c *Class) initFunc(m *Jsp.ConsContext) { /* 处理构造函数 */
currentT := current
defer func() {
current = currentT
}()

name := fmt.Sprintf("%v", m.GetChild(0))
current = name

params := m.GetChild(2)
var args []string
for _, param := range params.GetChildren() {
if param.GetChild(0) != nil {
arg := fmt.Sprintf("%v", param.GetChild(0))
args = append(args, arg)
}
}
method := NewFunction(name, args, m.GetChild(4).(*Jsp.BlockContext))
c.funcs[name] = method
}

func (c *Class) addFunc(m *Jsp.MethodContext) { /* 处理内置函数 */
currentT := current
defer func() {
current = currentT
}()

name := fmt.Sprintf("%v", m.GetChild(0))
current = name

params := m.GetChild(2)
var args []string
for _, param := range params.GetChildren() {
if param.GetChild(0) != nil {
arg := fmt.Sprintf("%v", param.GetChild(0))
args = append(args, arg)
}
}
method := NewFunction(name, args, m.GetChild(4).(*Jsp.BlockContext))
c.funcs[name] = method
}

func (c *Class) getFunc(name string) (*Fuction, bool) {
if _, ok := c.funcs[name]; ok {
return c.funcs[name], true
}
return nil, false
}

在基础类型对象的处理中添加 class object:

1
2
3
4
5
type CobjObject struct {
BaseObject
ClassName string
Value map[string]BaseObject
}
  • 附加的内置函数如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func (o *CobjObject) getString() string {
str := "{"
for k, v := range o.Value {
str += fmt.Sprintf(" %s:%s,", k, v.getString())
}
str = str[:len(str)-1] + " }"

return str
}

func (o *CobjObject) addValue(name string, obj BaseObject) {
o.Value[name] = obj
}

func (o *CobjObject) setValue(name string, obj BaseObject) {
for i, _ := range o.Value {
if i == name {
o.Value[i] = obj
}
}
}

添加 class 的语法:

1
2
3
class: 'class' IDENTIFIER '{' cons? method* '}';
cons: 'constructor' '(' paramlist? ')' block;
method: IDENTIFIER '(' paramlist? ')' block;

在 listener 中添加对 class 的处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func (l *MyListener) EnterClass(ctx *Jsp.ClassContext) {
name := fmt.Sprintf("%v", ctx.GetChild(1))
class := NewClass(name)

for _, c := range ctx.GetChildren() {
if con, ok := c.(*Jsp.ConsContext); ok {
class.initFunc(con)
}
if met, ok := c.(*Jsp.MethodContext); ok {
class.addFunc(met)
}
}
vl.addClass(class)
}

在 handExpr 中添加对于 this 和 class object 的处理:

1
2
3
4
5
6
7
if _, ok := exp.GetChild(0).(*Jsp.ThisContext); ok { // this
return &ThisObjetc{}, Jsp.JavaScriptParserRULE_this
}

if cobj, ok := exp.GetChild(0).(*Jsp.CobjContext); ok { // class object
return h.handExpr_cobj(cobj) /* 核心函数 */
}

另外在 handExpr 中处理 expr '.' expr 时添加对应的处理:

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
} else if obj, ok := exp1.(*CobjObject); ok { // class object
if obj.Value[name2] != nil {
obj.setValue(name1, obj.Value[name2])
str := fmt.Sprintf("%v", obj.Value[name2].getString())
if str[0] == '"' {
return obj.Value[name2], Jsp.JavaScriptLexerSTRING
}
if renum.MatchString(str) {
return obj.Value[name2], Jsp.JavaScriptLexerNUMBER
}
return obj.Value[name2], -1
} else {
var args []Variant
cname := obj.ClassName

if call, ok := exp.GetChild(2).GetChild(0).(*Jsp.FuncallContext); ok {
for _, c := range call.GetChild(2).GetChildren() {
if c.GetChild(0) != nil {
value, typ := h.handExpr(c.(*Jsp.ExprContext))
args = append(args, *NewVariant("unknown", value, typ))
}
}
}
if class, ok := vl.getClass(cname); ok {
value, typ := h.handMethod(obj, class, name2, args)
return value, typ
}
return nil, -1
}
} else if this, ok := exp1.(*ThisObjetc); ok { // this
this.setValue(name2)
this.setObject(exp2)
return this, Jsp.JavaScriptParserRULE_this

核心函数 handExpr_cobj 的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func (h *Handler) handExpr_cobj(new *Jsp.CobjContext) (BaseObject, int) {
var args []Variant
cname := fmt.Sprintf("%s", new.GetChild(1))
cobjt := &CobjObject{Value: make(map[string]BaseObject), ClassName: cname}

if class, ok := vl.getClass(cname); ok {
for _, o := range new.GetChild(3).GetChildren() {
if o.GetChild(0) != nil {
value, typ := h.handExpr(o.(*Jsp.ExprContext))
args = append(args, Variant{"unknown", value, typ})
}
}
h.handMethod(cobjt, class, "constructor", args)
}

return cobjt, Jsp.JavaScriptParserRULE_cobj
}
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
func (h *Handler) handMethod(cobjt *CobjObject, c *Class, name string, args []Variant) (BaseObject, int) {
currentT := current
defer func() {
vl.delVarAll()
current = currentT
}()
current = name
fun, _ := c.getFunc(name)

if len(fun.args) != len(args) {
panic("The parameters do not match")
} else {
for i, param := range fun.args {
value, typ := args[i].value, args[i].typ
vl.addVar(param, value, typ)
}
}

block := fun.fctx
for _, c := range block.GetChildren() {
if h.isBreak {
break
}
if h.isContinue {
continue
}
if c.GetChild(0) != nil {
value, typ := h.handStm(c.(*Jsp.StmContext))
if this, ok := value.(*ThisObjetc); ok {
cobjt.addValue(this.Value, this.Object)
}
if h.isReturn {
return value, typ
}
}
}

return nil, -1
}