if typ, ok := p.AcceptToken(token.IDENT); ok { varSpec.Type = &ast.Ident{ NamePos: typ.Pos, Name: typ.Literal, } }
if _, ok := p.AcceptToken(token.ASSIGN); ok { varSpec.Value = p.parseExpr() } p.AcceptToken(token.SEMICOLON) return varSpec }
利用之前实现的 API 获取 AST 结点的关键信息,最后生成并返回该 AST 结点
if分支和for循环
在 token 类型和注册的关键字中添加 if for,以保证词法分析可以顺利匹配
if 语句结点和 for 语句结点的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// 表示一个 if 语句节点 type IfStmt struct { If int// if 关键字的位置 Init Stmt // 初始化语句 Cond Expr // if 条件, *BinaryExpr Body *BlockStmt // if 为真时对应的语句列表 Else Stmt // else 对应的语句 }
// 表示一个 for 语句节点 type ForStmt struct { For int// for 关键字的位置 Init Stmt // 初始化语句 Cond Expr // 条件表达式 Post Stmt // 迭代语句 Body *BlockStmt // 循环对应的语句列表 }
在语法分析中与 if for 语句只能在语句块中,因此需要添加入 parseStmt_block:
1 2 3 4
case token.IF: block.List = append(block.List, p.parseStmt_if()) case token.FOR: block.List = append(block.List, p.parseStmt_for())
对于 if 语句而言,有如下几种情况:
1 2 3 4
if x > 0 {} if x := 1; x > 0 {} if x > 0 {} else {} if x := 1; x > 0 {} else {}
if _, ok := p.AcceptToken(token.ELSE); ok { switch p.PeekToken().Type { case token.IF: // else if ifStmt.Else = p.parseStmt_if() default: ifStmt.Else = p.parseStmt_block() } }
return ifStmt }
对于 for 语句而言,有如下几种情况:
1 2 3
for {} for x > 10 {} for x := 0; x < 10; x = x+1 {}
// for {} if _, ok := p.AcceptToken(token.LBRACE); ok { p.UnreadToken() forStmt.Body = p.parseStmt_block() return forStmt }
// for Cond {} // for Init?; Cond?; Post? {}
// for ; ... if _, ok := p.AcceptToken(token.SEMICOLON); ok { forStmt.Init = nil
// for ;; ... if _, ok := p.AcceptToken(token.SEMICOLON); ok { if _, ok := p.AcceptToken(token.LBRACE); ok { // for ;; {} p.UnreadToken() forStmt.Body = p.parseStmt_block() return forStmt } else { // for ; ; postStmt {} forStmt.Post = p.parseStmt() forStmt.Body = p.parseStmt_block() return forStmt } } else { // for ; cond ; ... {} forStmt.Cond = p.parseExpr() p.MustAcceptToken(token.SEMICOLON) if _, ok := p.AcceptToken(token.LBRACE); ok { // for ; cond ; {} p.UnreadToken() forStmt.Body = p.parseStmt_block() return forStmt } else { // for ; cond ; postStmt {} forStmt.Post = p.parseStmt() forStmt.Body = p.parseStmt_block() return forStmt } } } else { stmt := p.parseStmt()
if _, ok := p.AcceptToken(token.LBRACE); ok { // for cond {} p.UnreadToken() if expr, ok := stmt.(ast.Expr); ok { forStmt.Cond = expr } forStmt.Body = p.parseStmt_block() return forStmt } else { // for init; p.MustAcceptToken(token.SEMICOLON) forStmt.Init = stmt
// for ;; ... if _, ok := p.AcceptToken(token.SEMICOLON); ok { if _, ok := p.AcceptToken(token.LBRACE); ok { // for ;; {} p.UnreadToken() forStmt.Body = p.parseStmt_block() return forStmt } else { // for ; ; postStmt {} forStmt.Post = p.parseStmt() forStmt.Body = p.parseStmt_block() return forStmt } } else { // for ; cond ; ... {} forStmt.Cond = p.parseExpr() p.MustAcceptToken(token.SEMICOLON) if _, ok := p.AcceptToken(token.LBRACE); ok { // for ; cond ; {} p.UnreadToken() forStmt.Body = p.parseStmt_block() return forStmt } else { // for ; cond ; postStmt {} forStmt.Post = p.parseStmt() forStmt.Body = p.parseStmt_block() return forStmt } } } } }