if ok := p.SymTab.Push(&ast.Ident{ NamePos: tokIdent.Pos, Name: tokIdent.Literal, }, varSpec.Type); !ok { p.errorf(tokIdent.Pos, "duplicate variable declaration: %s", tokIdent.Literal) }
错误类型:使用时未定义
变量通常在表达式中使用,因此需要在 parseExpr_primary 中进行修改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
case token.IDENT: // 变量 && 数组 && 结构体 p.MustAcceptToken(token.IDENT) asti := &ast.IdentAS{ NamePos: tok.Pos, Name: tok.Literal, } if _, ok := p.AcceptToken(token.LSB); ok { asti.Offset = p.parseExpr() p.AcceptToken(token.RSB) } if _, ok := p.AcceptToken(token.DOT); ok { asti.Offset = p.parseExpr() }
if _, ok := p.SymTab.GetType(tok.Literal); !ok { p.errorf(tok.Pos, "unknown variable: %s", tok.Literal) } return asti
func(s *TypeTab)CheckType(typ string)bool { for i := s.top - 1; i >= 0; i-- { if s.elements[i] == typ { returntrue } } returnfalse }
func(s *TypeTab)ShowAll() { fmt.Println("----------TypeTab------------------------") for i, e := range s.elements { fmt.Printf("|@%d: {Type: %s}\t\t\t|\n", i+1, e) } fmt.Println("-----------------------------------------") fmt.Println("") }
func(s *TypeTab)MatchType(left string, right interface{})bool { myType := reflect.TypeOf(right) switch { case myType.String() == "*ast.Strings": if left != "string" { returnfalse } case myType.String() == "*ast.Number": if left != "int" { returnfalse } case myType.String() == "*ast.Bool": if left != "bool" { returnfalse } case myType.String() == "*ast.Char": if left != "char" { returnfalse } } returntrue }
修改 parseStmt_var,检查变量初始化的类型是否匹配:
1 2 3 4 5 6 7
if _, ok := p.AcceptToken(token.ASSIGN); ok { varSpec.Value = p.parseExpr()
if ok = p.TypeTab.MatchType(varSpec.Type.Name, varSpec.Value); !ok { p.errorf(tokIdent.Pos, "The variable:%s type:%s not match", varSpec.Name.Name, varSpec.Type.Name) } }
case token.DEFINE, token.ASSIGN: p.ReadToken() exprValueList := p.parseExprList() iflen(exprList) != len(exprValueList) { p.errorf(tok.Pos, "unknown token: %v", tok) } var assignStmt = &ast.AssignStmt{ Target: make([]*ast.IdentAS, len(exprList)), OpPos: tok.Pos, Op: tok.Type, Value: make([]ast.Expr, len(exprList)), } for i, target := range exprList { assignStmt.Target[i] = target.(*ast.IdentAS) assignStmt.Value[i] = exprValueList[i]
if ok := p.TypeTab.MatchType(assignStmt.Target[i].Name, assignStmt.Value[i]); !ok { p.errorf(tok.Pos, "The variable:%s type not match", assignStmt.Target[i].Name) } } block.List = append(block.List, assignStmt)
修改 parseExpr_binary,字符串和布尔不能参与运算:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
op := p.PeekToken() if op.Type.Precedence() < prec { return x }
myTypeX := reflect.TypeOf(x) if myTypeX.String() == "*ast.Strings" || myTypeX.String() == "*ast.Bool" { p.errorf(op.Pos, "Non-numbers cannot participate in the calculation") }
p.MustAcceptToken(op.Type) y := p.parseExpr_binary(op.Type.Precedence() + 1) x = &ast.BinaryExpr{OpPos: op.Pos, Op: op.Type, X: x, Y: y}
myTypeY := reflect.TypeOf(y) if myTypeY.String() == "*ast.Strings" || myTypeY.String() == "*ast.Bool" { p.errorf(op.Pos, "Non-numbers cannot participate in the calculation") }