summaryrefslogtreecommitdiff
path: root/src/lib/go
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/go')
-rw-r--r--src/lib/go/ast/Makefile68
-rw-r--r--src/lib/go/ast/ast.go772
-rw-r--r--src/lib/go/ast/format.go123
-rw-r--r--src/lib/go/doc/Makefile68
-rw-r--r--src/lib/go/doc/comment.go310
-rw-r--r--src/lib/go/doc/doc.go486
-rw-r--r--src/lib/go/parser/Makefile60
-rw-r--r--src/lib/go/parser/parser.go1975
-rw-r--r--src/lib/go/parser/parser_test.go68
-rw-r--r--src/lib/go/scanner/Makefile60
-rw-r--r--src/lib/go/scanner/scanner.go501
-rw-r--r--src/lib/go/scanner/scanner_test.go276
-rw-r--r--src/lib/go/token/Makefile60
-rw-r--r--src/lib/go/token/token.go347
14 files changed, 0 insertions, 5174 deletions
diff --git a/src/lib/go/ast/Makefile b/src/lib/go/ast/Makefile
deleted file mode 100644
index 1fd22ae71..000000000
--- a/src/lib/go/ast/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# DO NOT EDIT. Automatically generated by gobuild.
-# gobuild -m >Makefile
-
-D=/go/
-
-include $(GOROOT)/src/Make.$(GOARCH)
-AR=gopack
-
-default: packages
-
-clean:
- rm -rf *.[$(OS)] *.a [$(OS)].out _obj
-
-test: packages
- gotest
-
-coverage: packages
- gotest
- 6cov -g `pwd` | grep -v '_test\.go:'
-
-%.$O: %.go
- $(GC) -I_obj $*.go
-
-%.$O: %.c
- $(CC) $*.c
-
-%.$O: %.s
- $(AS) $*.s
-
-O1=\
- ast.$O\
-
-O2=\
- format.$O\
-
-
-phases: a1 a2
-_obj$D/ast.a: phases
-
-a1: $(O1)
- $(AR) grc _obj$D/ast.a ast.$O
- rm -f $(O1)
-
-a2: $(O2)
- $(AR) grc _obj$D/ast.a format.$O
- rm -f $(O2)
-
-
-newpkg: clean
- mkdir -p _obj$D
- $(AR) grc _obj$D/ast.a
-
-$(O1): newpkg
-$(O2): a1
-$(O3): a2
-
-nuke: clean
- rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/ast.a
-
-packages: _obj$D/ast.a
-
-install: packages
- test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D
- cp _obj$D/ast.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/ast.a
diff --git a/src/lib/go/ast/ast.go b/src/lib/go/ast/ast.go
deleted file mode 100644
index 6cac8ea1a..000000000
--- a/src/lib/go/ast/ast.go
+++ /dev/null
@@ -1,772 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// The AST package declares the types used to represent
-// syntax trees for Go source files.
-//
-package ast
-
-import (
- "go/token";
- "unicode";
- "utf8";
-)
-
-
-// ----------------------------------------------------------------------------
-// Interfaces
-//
-// There are 3 main classes of nodes: Expressions and type nodes,
-// statement nodes, and declaration nodes. The node names usually
-// match the corresponding Go spec production names to which they
-// correspond. The node fields correspond to the individual parts
-// of the respective productions.
-//
-// All nodes contain position information marking the beginning of
-// the corresponding source text segment; it is accessible via the
-// Pos accessor method. Nodes may contain additional position info
-// for language constructs where comments may be found between parts
-// of the construct (typically any larger, parenthesized subpart).
-// That position information is needed to properly position comments
-// when printing the construct.
-
-// TODO: For comment positioning only the byte position and not
-// a complete token.Position field is needed. May be able to trim
-// node sizes a bit.
-
-
-type (
- ExprVisitor interface;
- StmtVisitor interface;
- DeclVisitor interface;
-)
-
-
-// All expression nodes implement the Expr interface.
-type Expr interface {
- // For a (dynamic) node type X, calling Visit with an expression
- // visitor v invokes the node-specific DoX function of the visitor.
- //
- Visit(v ExprVisitor);
-
- // Pos returns the (beginning) position of the expression.
- Pos() token.Position;
-}
-
-
-// All statement nodes implement the Stmt interface.
-type Stmt interface {
- // For a (dynamic) node type X, calling Visit with a statement
- // visitor v invokes the node-specific DoX function of the visitor.
- //
- Visit(v StmtVisitor);
-
- // Pos returns the (beginning) position of the statement.
- Pos() token.Position;
-}
-
-
-// All declaration nodes implement the Decl interface.
-type Decl interface {
- // For a (dynamic) node type X, calling Visit with a declaration
- // visitor v invokes the node-specific DoX function of the visitor.
- //
- Visit(v DeclVisitor);
-
- // Pos returns the (beginning) position of the declaration.
- Pos() token.Position;
-}
-
-
-// ----------------------------------------------------------------------------
-// Comments
-
-// A Comment node represents a single //-style or /*-style comment.
-type Comment struct {
- token.Position; // beginning position of the comment
- Text []byte; // the comment text (without '\n' for //-style comments)
- EndLine int; // the line where the comment ends
-}
-
-
-// A Comments node represents a sequence of single comments
-// with no other tokens and no empty lines between.
-//
-type Comments []*Comment
-
-
-// ----------------------------------------------------------------------------
-// Expressions and types
-
-// Support types.
-type (
- Ident struct;
- StringLit struct;
- FuncType struct;
- BlockStmt struct;
-
- // A Field represents a Field declaration list in a struct type,
- // a method in an interface type, or a parameter/result declaration
- // in a signature.
- Field struct {
- Doc Comments; // associated documentation; or nil
- Names []*Ident; // field/method/parameter names; nil if anonymous field
- Type Expr; // field/method/parameter type
- Tag []*StringLit; // field tag; nil if no tag
- };
-)
-
-
-// An expression is represented by a tree consisting of one
-// or more of the following concrete expression nodes.
-//
-type (
- // A BadExpr node is a placeholder for expressions containing
- // syntax errors for which no correct expression nodes can be
- // created.
- //
- BadExpr struct {
- token.Position; // beginning position of bad expression
- };
-
- // An Ident node represents an identifier.
- Ident struct {
- token.Position; // identifier position
- Value string; // identifier string (e.g. foobar)
- };
-
- // An Ellipsis node stands for the "..." type in a
- // parameter list or the "..." length in an array type.
- //
- Ellipsis struct {
- token.Position; // position of "..."
- };
-
- // An IntLit node represents an integer literal.
- IntLit struct {
- token.Position; // int literal position
- Value []byte; // literal string; e.g. 42 or 0x7f
- };
-
- // A FloatLit node represents a floating-point literal.
- FloatLit struct {
- token.Position; // float literal position
- Value []byte; // literal string; e.g. 3.14 or 1e-9
- };
-
- // A CharLit node represents a character literal.
- CharLit struct {
- token.Position; // char literal position
- Value []byte; // literal string, including quotes; e.g. 'a' or '\x7f'
- };
-
- // A StringLit node represents a string literal.
- StringLit struct {
- token.Position; // string literal position
- Value []byte; // literal string, including quotes; e.g. "foo" or `\m\n\o`
- };
-
- // A StringList node represents a sequence of adjacent string literals.
- // A single string literal (common case) is represented by a StringLit
- // node; StringList nodes are used only if there are two or more string
- // literals in a sequence.
- //
- StringList struct {
- Strings []*StringLit; // list of strings, len(Strings) > 1
- };
-
- // A FuncLit node represents a function literal.
- FuncLit struct {
- Type *FuncType; // function type
- Body *BlockStmt; // function body
- };
-
- // A CompositeLit node represents a composite literal.
- //
- CompositeLit struct {
- Type Expr; // literal type
- Lbrace token.Position; // position of "{"
- Elts []Expr; // list of composite elements
- Rbrace token.Position; // position of "}"
- };
-
- // A ParenExpr node represents a parenthesized expression.
- ParenExpr struct {
- token.Position; // position of "("
- X Expr; // parenthesized expression
- Rparen token.Position; // position of ")"
- };
-
- // A SelectorExpr node represents an expression followed by a selector.
- SelectorExpr struct {
- X Expr; // expression
- Sel *Ident; // field selector
- };
-
- // An IndexExpr node represents an expression followed by an index or slice.
- IndexExpr struct {
- X Expr; // expression
- Index Expr; // index expression or beginning of slice range
- End Expr; // end of slice range; or nil
- };
-
- // A TypeAssertExpr node represents an expression followed by a
- // type assertion.
- //
- TypeAssertExpr struct {
- X Expr; // expression
- Type Expr; // asserted type
- };
-
- // A CallExpr node represents an expression followed by an argument list.
- CallExpr struct {
- Fun Expr; // function expression
- Lparen token.Position; // position of "("
- Args []Expr; // function arguments
- Rparen token.Position; // positions of ")"
- };
-
- // A StarExpr node represents an expression of the form "*" Expression.
- // Semantically it could be a unary "*" expression, or a pointer type.
- StarExpr struct {
- token.Position; // position of "*"
- X Expr; // operand
- };
-
- // A UnaryExpr node represents a unary expression.
- // Unary "*" expressions are represented via StarExpr nodes.
- //
- UnaryExpr struct {
- token.Position; // position of Op
- Op token.Token; // operator
- X Expr; // operand
- };
-
- // A BinaryExpr node represents a binary expression.
- //
- BinaryExpr struct {
- X Expr; // left operand
- OpPos token.Position; // position of Op
- Op token.Token; // operator
- Y Expr; // right operand
- };
-
- // A KeyValueExpr node represents (key : value) pairs
- // in composite literals.
- //
- KeyValueExpr struct {
- Key Expr;
- Colon token.Position; // position of ":"
- Value Expr;
- };
-)
-
-
-// The direction of a channel type is indicated by one
-// of the following constants.
-//
-type ChanDir int
-const (
- SEND ChanDir = 1 << iota;
- RECV;
-)
-
-
-// A type is represented by a tree consisting of one
-// or more of the following type-specific expression
-// nodes.
-//
-type (
- // An ArrayType node represents an array or slice type.
- ArrayType struct {
- token.Position; // position of "["
- Len Expr; // Ellipsis node for [...]T array types, nil for slice types
- Elt Expr; // element type
- };
-
- // A StructType node represents a struct type.
- StructType struct {
- token.Position; // position of "struct" keyword
- Lbrace token.Position; // position of "{"
- Fields []*Field; // list of field declarations; nil if forward declaration
- Rbrace token.Position; // position of "}"
- };
-
- // Pointer types are represented via StarExpr nodes.
-
- // A FuncType node represents a function type.
- FuncType struct {
- token.Position; // position of "func" keyword
- Params []*Field; // (incoming) parameters
- Results []*Field; // (outgoing) results
- };
-
- // An InterfaceType node represents an interface type.
- InterfaceType struct {
- token.Position; // position of "interface" keyword
- Lbrace token.Position; // position of "{"
- Methods []*Field; // list of methods; nil if forward declaration
- Rbrace token.Position; // position of "}"
- };
-
- // A MapType node represents a map type.
- MapType struct {
- token.Position; // position of "map" keyword
- Key Expr;
- Value Expr;
- };
-
- // A ChanType node represents a channel type.
- ChanType struct {
- token.Position; // position of "chan" keyword or "<-" (whichever comes first)
- Dir ChanDir; // channel direction
- Value Expr; // value type
- };
-)
-
-
-// Pos() implementations for expression/type where the position
-// corresponds to the position of a sub-node.
-//
-func (x *StringList) Pos() token.Position { return x.Strings[0].Pos(); }
-func (x *FuncLit) Pos() token.Position { return x.Type.Pos(); }
-func (x *CompositeLit) Pos() token.Position { return x.Type.Pos(); }
-func (x *SelectorExpr) Pos() token.Position { return x.X.Pos(); }
-func (x *IndexExpr) Pos() token.Position { return x.X.Pos(); }
-func (x *TypeAssertExpr) Pos() token.Position { return x.X.Pos(); }
-func (x *CallExpr) Pos() token.Position { return x.Fun.Pos(); }
-func (x *BinaryExpr) Pos() token.Position { return x.X.Pos(); }
-func (x *KeyValueExpr) Pos() token.Position { return x.Key.Pos(); }
-
-
-// All expression/type nodes implement a Visit method which takes
-// an ExprVisitor as argument. For a given node x of type X, and
-// an implementation v of an ExprVisitor, calling x.Visit(v) will
-// result in a call of v.DoX(x) (through a double-dispatch).
-//
-type ExprVisitor interface {
- // Expressions
- DoBadExpr(x *BadExpr);
- DoIdent(x *Ident);
- DoIntLit(x *IntLit);
- DoFloatLit(x *FloatLit);
- DoCharLit(x *CharLit);
- DoStringLit(x *StringLit);
- DoStringList(x *StringList);
- DoFuncLit(x *FuncLit);
- DoCompositeLit(x *CompositeLit);
- DoParenExpr(x *ParenExpr);
- DoSelectorExpr(x *SelectorExpr);
- DoIndexExpr(x *IndexExpr);
- DoTypeAssertExpr(x *TypeAssertExpr);
- DoCallExpr(x *CallExpr);
- DoStarExpr(x *StarExpr);
- DoUnaryExpr(x *UnaryExpr);
- DoBinaryExpr(x *BinaryExpr);
- DoKeyValueExpr(x *KeyValueExpr);
-
- // Type expressions
- DoEllipsis(x *Ellipsis);
- DoArrayType(x *ArrayType);
- DoStructType(x *StructType);
- DoFuncType(x *FuncType);
- DoInterfaceType(x *InterfaceType);
- DoMapType(x *MapType);
- DoChanType(x *ChanType);
-}
-
-
-// Visit() implementations for all expression/type nodes.
-//
-func (x *BadExpr) Visit(v ExprVisitor) { v.DoBadExpr(x); }
-func (x *Ident) Visit(v ExprVisitor) { v.DoIdent(x); }
-func (x *Ellipsis) Visit(v ExprVisitor) { v.DoEllipsis(x); }
-func (x *IntLit) Visit(v ExprVisitor) { v.DoIntLit(x); }
-func (x *FloatLit) Visit(v ExprVisitor) { v.DoFloatLit(x); }
-func (x *CharLit) Visit(v ExprVisitor) { v.DoCharLit(x); }
-func (x *StringLit) Visit(v ExprVisitor) { v.DoStringLit(x); }
-func (x *StringList) Visit(v ExprVisitor) { v.DoStringList(x); }
-func (x *FuncLit) Visit(v ExprVisitor) { v.DoFuncLit(x); }
-func (x *CompositeLit) Visit(v ExprVisitor) { v.DoCompositeLit(x); }
-func (x *ParenExpr) Visit(v ExprVisitor) { v.DoParenExpr(x); }
-func (x *SelectorExpr) Visit(v ExprVisitor) { v.DoSelectorExpr(x); }
-func (x *IndexExpr) Visit(v ExprVisitor) { v.DoIndexExpr(x); }
-func (x *TypeAssertExpr) Visit(v ExprVisitor) { v.DoTypeAssertExpr(x); }
-func (x *CallExpr) Visit(v ExprVisitor) { v.DoCallExpr(x); }
-func (x *StarExpr) Visit(v ExprVisitor) { v.DoStarExpr(x); }
-func (x *UnaryExpr) Visit(v ExprVisitor) { v.DoUnaryExpr(x); }
-func (x *BinaryExpr) Visit(v ExprVisitor) { v.DoBinaryExpr(x); }
-func (x *KeyValueExpr) Visit(v ExprVisitor) { v.DoKeyValueExpr(x); }
-
-func (x *ArrayType) Visit(v ExprVisitor) { v.DoArrayType(x); }
-func (x *StructType) Visit(v ExprVisitor) { v.DoStructType(x); }
-func (x *FuncType) Visit(v ExprVisitor) { v.DoFuncType(x); }
-func (x *InterfaceType) Visit(v ExprVisitor) { v.DoInterfaceType(x); }
-func (x *MapType) Visit(v ExprVisitor) { v.DoMapType(x); }
-func (x *ChanType) Visit(v ExprVisitor) { v.DoChanType(x); }
-
-
-// IsExported returns whether name is an exported Go symbol
-// (i.e., whether it begins with an uppercase letter).
-func IsExported(name string) bool {
- ch, len := utf8.DecodeRuneInString(name);
- return unicode.IsUpper(ch);
-}
-
-// IsExported returns whether name is an exported Go symbol
-// (i.e., whether it begins with an uppercase letter).
-func (name *ast.Ident) IsExported() bool {
- return IsExported(name.Value);
-}
-
-func (name *ast.Ident) String() string {
- return name.Value;
-}
-
-
-// ----------------------------------------------------------------------------
-// Statements
-
-// A statement is represented by a tree consisting of one
-// or more of the following concrete statement nodes.
-//
-type (
- // A BadStmt node is a placeholder for statements containing
- // syntax errors for which no correct statement nodes can be
- // created.
- //
- BadStmt struct {
- token.Position; // beginning position of bad statement
- };
-
- // A DeclStmt node represents a declaration in a statement list.
- DeclStmt struct {
- Decl Decl;
- };
-
- // An EmptyStmt node represents an empty statement.
- // The "position" of the empty statement is the position
- // of the immediately preceeding semicolon.
- //
- EmptyStmt struct {
- token.Position; // position of preceeding ";"
- };
-
- // A LabeledStmt node represents a labeled statement.
- LabeledStmt struct {
- Label *Ident;
- Stmt Stmt;
- };
-
- // An ExprStmt node represents a (stand-alone) expression
- // in a statement list.
- //
- ExprStmt struct {
- X Expr; // expression
- };
-
- // An IncDecStmt node represents an increment or decrement statement.
- IncDecStmt struct {
- X Expr;
- Tok token.Token; // INC or DEC
- };
-
- // An AssignStmt node represents an assignment or
- // a short variable declaration.
- AssignStmt struct {
- Lhs []Expr;
- TokPos token.Position; // position of Tok
- Tok token.Token; // assignment token, DEFINE
- Rhs []Expr;
- };
-
- // A GoStmt node represents a go statement.
- GoStmt struct {
- token.Position; // position of "go" keyword
- Call *CallExpr;
- };
-
- // A DeferStmt node represents a defer statement.
- DeferStmt struct {
- token.Position; // position of "defer" keyword
- Call *CallExpr;
- };
-
- // A ReturnStmt node represents a return statement.
- ReturnStmt struct {
- token.Position; // position of "return" keyword
- Results []Expr;
- };
-
- // A BranchStmt node represents a break, continue, goto,
- // or fallthrough statement.
- //
- BranchStmt struct {
- token.Position; // position of Tok
- Tok token.Token; // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH)
- Label *Ident;
- };
-
- // A BlockStmt node represents a braced statement list.
- BlockStmt struct {
- token.Position; // position of "{"
- List []Stmt;
- Rbrace token.Position; // position of "}"
- };
-
- // An IfStmt node represents an if statement.
- IfStmt struct {
- token.Position; // position of "if" keyword
- Init Stmt;
- Cond Expr;
- Body *BlockStmt;
- Else Stmt;
- };
-
- // A CaseClause represents a case of an expression switch statement.
- CaseClause struct {
- token.Position; // position of "case" or "default" keyword
- Values []Expr; // nil means default case
- Colon token.Position; // position of ":"
- Body []Stmt; // statement list; or nil
- };
-
- // A SwitchStmt node represents an expression switch statement.
- SwitchStmt struct {
- token.Position; // position of "switch" keyword
- Init Stmt;
- Tag Expr;
- Body *BlockStmt; // CaseClauses only
- };
-
- // A TypeCaseClause represents a case of a type switch statement.
- TypeCaseClause struct {
- token.Position; // position of "case" or "default" keyword
- Type Expr; // nil means default case
- Colon token.Position; // position of ":"
- Body []Stmt; // statement list; or nil
- };
-
- // An TypeSwitchStmt node represents a type switch statement.
- TypeSwitchStmt struct {
- token.Position; // position of "switch" keyword
- Init Stmt;
- Assign Stmt; // x := y.(type)
- Body *BlockStmt; // TypeCaseClauses only
- };
-
- // A CommClause node represents a case of a select statement.
- CommClause struct {
- token.Position; // position of "case" or "default" keyword
- Tok token.Token; // ASSIGN or DEFINE (valid only if Lhs != nil)
- Lhs, Rhs Expr; // Rhs == nil means default case
- Colon token.Position; // position of ":"
- Body []Stmt; // statement list; or nil
- };
-
- // An SelectStmt node represents a select statement.
- SelectStmt struct {
- token.Position; // position of "select" keyword
- Body *BlockStmt; // CommClauses only
- };
-
- // A ForStmt represents a for statement.
- ForStmt struct {
- token.Position; // position of "for" keyword
- Init Stmt;
- Cond Expr;
- Post Stmt;
- Body *BlockStmt;
- };
-
- // A RangeStmt represents a for statement with a range clause.
- RangeStmt struct {
- token.Position; // position of "for" keyword
- Key, Value Expr; // Value may be nil
- TokPos token.Position; // position of Tok
- Tok token.Token; // ASSIGN, DEFINE
- X Expr; // value to range over
- Body *BlockStmt;
- };
-)
-
-
-// Pos() implementations for statement nodes where the position
-// corresponds to the position of a sub-node.
-//
-func (s *DeclStmt) Pos() token.Position { return s.Decl.Pos(); }
-func (s *LabeledStmt) Pos() token.Position { return s.Label.Pos(); }
-func (s *ExprStmt) Pos() token.Position { return s.X.Pos(); }
-func (s *IncDecStmt) Pos() token.Position { return s.X.Pos(); }
-func (s *AssignStmt) Pos() token.Position { return s.Lhs[0].Pos(); }
-
-
-// All statement nodes implement a Visit method which takes
-// a StmtVisitor as argument. For a given node x of type X, and
-// an implementation v of a StmtVisitor, calling x.Visit(v) will
-// result in a call of v.DoX(x) (through a double-dispatch).
-//
-type StmtVisitor interface {
- DoBadStmt(s *BadStmt);
- DoDeclStmt(s *DeclStmt);
- DoEmptyStmt(s *EmptyStmt);
- DoLabeledStmt(s *LabeledStmt);
- DoExprStmt(s *ExprStmt);
- DoIncDecStmt(s *IncDecStmt);
- DoAssignStmt(s *AssignStmt);
- DoGoStmt(s *GoStmt);
- DoDeferStmt(s *DeferStmt);
- DoReturnStmt(s *ReturnStmt);
- DoBranchStmt(s *BranchStmt);
- DoBlockStmt(s *BlockStmt);
- DoIfStmt(s *IfStmt);
- DoCaseClause(s *CaseClause);
- DoSwitchStmt(s *SwitchStmt);
- DoTypeCaseClause(s *TypeCaseClause);
- DoTypeSwitchStmt(s *TypeSwitchStmt);
- DoCommClause(s *CommClause);
- DoSelectStmt(s *SelectStmt);
- DoForStmt(s *ForStmt);
- DoRangeStmt(s *RangeStmt);
-}
-
-
-// Visit() implementations for all statement nodes.
-//
-func (s *BadStmt) Visit(v StmtVisitor) { v.DoBadStmt(s); }
-func (s *DeclStmt) Visit(v StmtVisitor) { v.DoDeclStmt(s); }
-func (s *EmptyStmt) Visit(v StmtVisitor) { v.DoEmptyStmt(s); }
-func (s *LabeledStmt) Visit(v StmtVisitor) { v.DoLabeledStmt(s); }
-func (s *ExprStmt) Visit(v StmtVisitor) { v.DoExprStmt(s); }
-func (s *IncDecStmt) Visit(v StmtVisitor) { v.DoIncDecStmt(s); }
-func (s *AssignStmt) Visit(v StmtVisitor) { v.DoAssignStmt(s); }
-func (s *GoStmt) Visit(v StmtVisitor) { v.DoGoStmt(s); }
-func (s *DeferStmt) Visit(v StmtVisitor) { v.DoDeferStmt(s); }
-func (s *ReturnStmt) Visit(v StmtVisitor) { v.DoReturnStmt(s); }
-func (s *BranchStmt) Visit(v StmtVisitor) { v.DoBranchStmt(s); }
-func (s *BlockStmt) Visit(v StmtVisitor) { v.DoBlockStmt(s); }
-func (s *IfStmt) Visit(v StmtVisitor) { v.DoIfStmt(s); }
-func (s *CaseClause) Visit(v StmtVisitor) { v.DoCaseClause(s); }
-func (s *SwitchStmt) Visit(v StmtVisitor) { v.DoSwitchStmt(s); }
-func (s *TypeCaseClause) Visit(v StmtVisitor) { v.DoTypeCaseClause(s); }
-func (s *TypeSwitchStmt) Visit(v StmtVisitor) { v.DoTypeSwitchStmt(s); }
-func (s *CommClause) Visit(v StmtVisitor) { v.DoCommClause(s); }
-func (s *SelectStmt) Visit(v StmtVisitor) { v.DoSelectStmt(s); }
-func (s *ForStmt) Visit(v StmtVisitor) { v.DoForStmt(s); }
-func (s *RangeStmt) Visit(v StmtVisitor) { v.DoRangeStmt(s); }
-
-
-// ----------------------------------------------------------------------------
-// Declarations
-
-// A Spec node represents a single (non-parenthesized) import,
-// constant, type, or variable declaration.
-//
-type (
- // The Spec type stands for any of *ImportSpec, *ValueSpec, and *TypeSpec.
- Spec interface {};
-
- // An ImportSpec node represents a single package import.
- ImportSpec struct {
- Doc Comments; // associated documentation; or nil
- Name *Ident; // local package name (including "."); or nil
- Path []*StringLit; // package path
- };
-
- // A ValueSpec node represents a constant or variable declaration
- // (ConstSpec or VarSpec production).
- ValueSpec struct {
- Doc Comments; // associated documentation; or nil
- Names []*Ident;
- Type Expr; // value type; or nil
- Values []Expr;
- };
-
- // A TypeSpec node represents a type declaration (TypeSpec production).
- TypeSpec struct {
- Doc Comments; // associated documentation; or nil
- Name *Ident; // type name
- Type Expr;
- };
-)
-
-
-// A declaration is represented by one of the following declaration nodes.
-//
-type (
- // A BadDecl node is a placeholder for declarations containing
- // syntax errors for which no correct declaration nodes can be
- // created.
- //
- BadDecl struct {
- token.Position; // beginning position of bad declaration
- };
-
- // A GenDecl node (generic declaration node) represents an import,
- // constant, type or variable declaration. A valid Lparen position
- // (Lparen.Line > 0) indicates a parenthesized declaration.
- //
- // Relationship between Tok value and Specs element type:
- //
- // token.IMPORT *ImportSpec
- // token.CONST *ValueSpec
- // token.TYPE *TypeSpec
- // token.VAR *ValueSpec
- //
- GenDecl struct {
- Doc Comments; // associated documentation; or nil
- token.Position; // position of Tok
- Tok token.Token; // IMPORT, CONST, TYPE, VAR
- Lparen token.Position; // position of '(', if any
- Specs []Spec;
- Rparen token.Position; // position of ')', if any
- };
-
- // A FuncDecl node represents a function declaration.
- FuncDecl struct {
- Doc Comments; // associated documentation; or nil
- Recv *Field; // receiver (methods); or nil (functions)
- Name *Ident; // function/method name
- Type *FuncType; // position of Func keyword, parameters and results
- Body *BlockStmt; // function body; or nil (forward declaration)
- };
-)
-
-
-// The position of a FuncDecl node is the position of its function type.
-func (d *FuncDecl) Pos() token.Position { return d.Type.Pos(); }
-
-
-// All declaration nodes implement a Visit method which takes
-// a DeclVisitor as argument. For a given node x of type X, and
-// an implementation v of a DeclVisitor, calling x.Visit(v) will
-// result in a call of v.DoX(x) (through a double-dispatch).
-//
-type DeclVisitor interface {
- DoBadDecl(d *BadDecl);
- DoGenDecl(d *GenDecl);
- DoFuncDecl(d *FuncDecl);
-}
-
-
-// Visit() implementations for all declaration nodes.
-//
-func (d *BadDecl) Visit(v DeclVisitor) { v.DoBadDecl(d); }
-func (d *GenDecl) Visit(v DeclVisitor) { v.DoGenDecl(d); }
-func (d *FuncDecl) Visit(v DeclVisitor) { v.DoFuncDecl(d); }
-
-
-// ----------------------------------------------------------------------------
-// Programs
-
-// A Program node represents the root node of an AST
-// for an entire source file.
-//
-type Program struct {
- Doc Comments; // associated documentation; or nil
- token.Position; // position of "package" keyword
- Name *Ident; // package name
- Decls []Decl; // top-level declarations
- Comments []*Comment; // list of unassociated comments
-}
diff --git a/src/lib/go/ast/format.go b/src/lib/go/ast/format.go
deleted file mode 100644
index caeca19aa..000000000
--- a/src/lib/go/ast/format.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ast
-
-import (
- "datafmt";
- "go/ast";
- "go/token";
- "io";
- "os";
-)
-
-
-// Format is a customized datafmt.Format for printing of ASTs.
-type Format datafmt.Format;
-
-
-// ----------------------------------------------------------------------------
-// Custom formatters
-
-// The AST-specific formatting state is maintained by a state variable.
-type state struct {
- // for now we have very little state
- // TODO maintain list of unassociated comments
- optSemi bool
-}
-
-
-func (s *state) Copy() datafmt.Environment {
- copy := *s;
- return &copy;
-}
-
-
-func isValidPos(s *datafmt.State, value interface{}, ruleName string) bool {
- pos := value.(token.Position);
- return pos.IsValid();
-}
-
-
-func isSend(s *datafmt.State, value interface{}, ruleName string) bool {
- return value.(ast.ChanDir) & ast.SEND != 0;
-}
-
-
-func isRecv(s *datafmt.State, value interface{}, ruleName string) bool {
- return value.(ast.ChanDir) & ast.RECV != 0;
-}
-
-
-func isMultiLineComment(s *datafmt.State, value interface{}, ruleName string) bool {
- return value.([]byte)[1] == '*';
-}
-
-
-func clearOptSemi(s *datafmt.State, value interface{}, ruleName string) bool {
- s.Env().(*state).optSemi = false;
- return true;
-}
-
-
-func setOptSemi(s *datafmt.State, value interface{}, ruleName string) bool {
- s.Env().(*state).optSemi = true;
- return true;
-}
-
-
-func optSemi(s *datafmt.State, value interface{}, ruleName string) bool {
- if !s.Env().(*state).optSemi {
- s.Write([]byte{';'});
- }
- return true;
-}
-
-
-var fmap = datafmt.FormatterMap {
- "isValidPos": isValidPos,
- "isSend": isSend,
- "isRecv": isRecv,
- "isMultiLineComment": isMultiLineComment,
- "/": clearOptSemi,
- "clearOptSemi": clearOptSemi,
- "setOptSemi": setOptSemi,
- "optSemi": optSemi,
-}
-
-
-// ----------------------------------------------------------------------------
-// Printing
-
-// NewFormat parses a datafmt format specification from a file
-// and adds AST-specific custom formatter rules. The result is
-// the customized format or an os.Error, if any.
-//
-func NewFormat(filename string) (Format, os.Error) {
- src, err := io.ReadFile(filename);
- if err != nil {
- return nil, err;
- }
- f, err := datafmt.Parse(src, fmap);
- return Format(f), err;
-}
-
-
-// Fprint formats each AST node provided as argument according to the
-// format f and writes to standard output. The result is the total number
-// of bytes written and an os.Error, if any.
-//
-func (f Format) Fprint(w io.Writer, nodes ...) (int, os.Error) {
- var s state;
- return datafmt.Format(f).Fprint(w, &s, nodes);
-}
-
-
-// Fprint formats each AST node provided as argument according to the
-// format f and writes to w. The result is the total number of bytes
-// written and an os.Error, if any.
-//
-func (f Format) Print(nodes ...) (int, os.Error) {
- return f.Fprint(os.Stdout, nodes);
-}
diff --git a/src/lib/go/doc/Makefile b/src/lib/go/doc/Makefile
deleted file mode 100644
index d7c6acaac..000000000
--- a/src/lib/go/doc/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# DO NOT EDIT. Automatically generated by gobuild.
-# gobuild -m >Makefile
-
-D=/go/
-
-include $(GOROOT)/src/Make.$(GOARCH)
-AR=gopack
-
-default: packages
-
-clean:
- rm -rf *.[$(OS)] *.a [$(OS)].out _obj
-
-test: packages
- gotest
-
-coverage: packages
- gotest
- 6cov -g `pwd` | grep -v '_test\.go:'
-
-%.$O: %.go
- $(GC) -I_obj $*.go
-
-%.$O: %.c
- $(CC) $*.c
-
-%.$O: %.s
- $(AS) $*.s
-
-O1=\
- comment.$O\
-
-O2=\
- doc.$O\
-
-
-phases: a1 a2
-_obj$D/doc.a: phases
-
-a1: $(O1)
- $(AR) grc _obj$D/doc.a comment.$O
- rm -f $(O1)
-
-a2: $(O2)
- $(AR) grc _obj$D/doc.a doc.$O
- rm -f $(O2)
-
-
-newpkg: clean
- mkdir -p _obj$D
- $(AR) grc _obj$D/doc.a
-
-$(O1): newpkg
-$(O2): a1
-$(O3): a2
-
-nuke: clean
- rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/doc.a
-
-packages: _obj$D/doc.a
-
-install: packages
- test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D
- cp _obj$D/doc.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/doc.a
diff --git a/src/lib/go/doc/comment.go b/src/lib/go/doc/comment.go
deleted file mode 100644
index 19a65a227..000000000
--- a/src/lib/go/doc/comment.go
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Godoc comment extraction and comment -> HTML formatting.
-
-package doc
-
-import (
- "fmt";
- "io";
- "once";
- "regexp";
- "strings";
- "template"; // for htmlEscape
-)
-
-// Comment extraction
-
-var (
- comment_markers *regexp.Regexp;
- trailing_whitespace *regexp.Regexp;
- comment_junk *regexp.Regexp;
-)
-
-func makeRex(s string) *regexp.Regexp {
- re, err := regexp.Compile(s);
- if err != nil {
- panic("MakeRegexp ", s, " ", err.String());
- }
- return re;
-}
-
-// TODO(rsc): Cannot use var initialization for regexps,
-// because Regexp constructor needs threads.
-func setupRegexps() {
- comment_markers = makeRex("^/(/|\\*) ?");
- trailing_whitespace = makeRex("[ \t\r]+$");
- comment_junk = makeRex("^[ \t]*(/\\*|\\*/)[ \t]*$");
-}
-
-// Aggregate comment text, without comment markers.
-func commentText(comments []string) string {
- once.Do(setupRegexps);
- lines := make([]string, 0, 20);
- for i, c := range comments {
- // split on newlines
- cl := strings.Split(c, "\n");
-
- // walk lines, stripping comment markers
- w := 0;
- for j, l := range cl {
- // remove /* and */ lines
- if comment_junk.Match(l) {
- continue;
- }
-
- // strip trailing white space
- m := trailing_whitespace.Execute(l);
- if len(m) > 0 {
- l = l[0 : m[1]];
- }
-
- // strip leading comment markers
- m = comment_markers.Execute(l);
- if len(m) > 0 {
- l = l[m[1] : len(l)];
- }
-
- // throw away leading blank lines
- if w == 0 && l == "" {
- continue;
- }
-
- cl[w] = l;
- w++;
- }
-
- // throw away trailing blank lines
- for w > 0 && cl[w-1] == "" {
- w--;
- }
- cl = cl[0 : w];
-
- // add this comment to total list
- // TODO: maybe separate with a single blank line
- // if there is already a comment and len(cl) > 0?
- for j, l := range cl {
- n := len(lines);
- if n+1 >= cap(lines) {
- newlines := make([]string, n, 2*cap(lines));
- for k := range newlines {
- newlines[k] = lines[k];
- }
- lines = newlines;
- }
- lines = lines[0 : n+1];
- lines[n] = l;
- }
- }
-
- // add final "" entry to get trailing newline.
- // loop always leaves room for one more.
- n := len(lines);
- lines = lines[0 : n+1];
-
- return strings.Join(lines, "\n");
-}
-
-// Split bytes into lines.
-func split(text []byte) [][]byte {
- // count lines
- n := 0;
- last := 0;
- for i, c := range text {
- if c == '\n' {
- last = i+1;
- n++;
- }
- }
- if last < len(text) {
- n++;
- }
-
- // split
- out := make([][]byte, n);
- last = 0;
- n = 0;
- for i, c := range text {
- if c == '\n' {
- out[n] = text[last : i+1];
- last = i+1;
- n++;
- }
- }
- if last < len(text) {
- out[n] = text[last : len(text)];
- }
-
- return out;
-}
-
-
-var (
- ldquo = io.StringBytes("&ldquo;");
- rdquo = io.StringBytes("&rdquo;");
-)
-
-// Escape comment text for HTML.
-// Also, turn `` into &ldquo; and '' into &rdquo;.
-func commentEscape(w io.Writer, s []byte) {
- last := 0;
- for i := 0; i < len(s)-1; i++ {
- if s[i] == s[i+1] && (s[i] == '`' || s[i] == '\'') {
- template.HtmlEscape(w, s[last : i]);
- last = i+2;
- switch s[i] {
- case '`':
- w.Write(ldquo);
- case '\'':
- w.Write(rdquo);
- }
- i++; // loop will add one more
- }
- }
- template.HtmlEscape(w, s[last : len(s)]);
-}
-
-
-var (
- html_p = io.StringBytes("<p>\n");
- html_endp = io.StringBytes("</p>\n");
- html_pre = io.StringBytes("<pre>");
- html_endpre = io.StringBytes("</pre>\n");
-)
-
-
-func indentLen(s []byte) int {
- i := 0;
- for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
- i++;
- }
- return i;
-}
-
-
-func isBlank(s []byte) bool {
- return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
-}
-
-
-func commonPrefix(a, b []byte) []byte {
- i := 0;
- for i < len(a) && i < len(b) && a[i] == b[i] {
- i++;
- }
- return a[0 : i];
-}
-
-
-func unindent(block [][]byte) {
- if len(block) == 0 {
- return;
- }
-
- // compute maximum common white prefix
- prefix := block[0][0 : indentLen(block[0])];
- for i, line := range block {
- if !isBlank(line) {
- prefix = commonPrefix(prefix, line[0 : indentLen(line)]);
- }
- }
- n := len(prefix);
-
- // remove
- for i, line := range block {
- if !isBlank(line) {
- block[i] = line[n : len(line)];
- }
- }
-}
-
-
-// Convert comment text to formatted HTML.
-// The comment was prepared by DocReader,
-// so it is known not to have leading, trailing blank lines
-// nor to have trailing spaces at the end of lines.
-// The comment markers have already been removed.
-//
-// Turn each run of multiple \n into </p><p>
-// Turn each run of indented lines into <pre> without indent.
-//
-// TODO(rsc): I'd like to pass in an array of variable names []string
-// and then italicize those strings when they appear as words.
-func ToHtml(w io.Writer, s []byte) {
- inpara := false;
-
- /* TODO(rsc): 6g cant generate code for these
- close := func() {
- if inpara {
- w.Write(html_endp);
- inpara = false;
- }
- };
- open := func() {
- if !inpara {
- w.Write(html_p);
- inpara = true;
- }
- };
- */
-
- lines := split(s);
- unindent(lines);
- for i := 0; i < len(lines); {
- line := lines[i];
- if isBlank(line) {
- // close paragraph
- if inpara {
- w.Write(html_endp);
- inpara = false;
- }
- i++;
- continue;
- }
- if indentLen(line) > 0 {
- // close paragraph
- if inpara {
- w.Write(html_endp);
- inpara = false;
- }
-
- // count indented or blank lines
- j := i+1;
- for j < len(lines) && (isBlank(lines[j]) || indentLen(lines[j]) > 0) {
- j++;
- }
- // but not trailing blank lines
- for j > i && isBlank(lines[j-1]) {
- j--;
- }
- block := lines[i : j];
- i = j;
-
- unindent(block);
-
- // put those lines in a pre block.
- // they don't get the nice text formatting,
- // just html escaping
- w.Write(html_pre);
- for k, line := range block {
- template.HtmlEscape(w, line);
- }
- w.Write(html_endpre);
- continue;
- }
- // open paragraph
- if !inpara {
- w.Write(html_p);
- inpara = true;
- }
- commentEscape(w, lines[i]);
- i++;
- }
- if inpara {
- w.Write(html_endp);
- inpara = false;
- }
-}
-
diff --git a/src/lib/go/doc/doc.go b/src/lib/go/doc/doc.go
deleted file mode 100644
index 03872fd14..000000000
--- a/src/lib/go/doc/doc.go
+++ /dev/null
@@ -1,486 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package doc
-
-import (
- "container/vector";
- "fmt";
- "go/ast";
- "go/doc";
- "go/token";
- "io";
- "regexp";
- "sort";
- "strings";
-)
-
-
-// ----------------------------------------------------------------------------
-// Elementary support
-
-func hasExportedNames(names []*ast.Ident) bool {
- for i, name := range names {
- if name.IsExported() {
- return true;
- }
- }
- return false;
-}
-
-
-func hasExportedSpecs(specs []ast.Spec) bool {
- for i, s := range specs {
- // only called for []astSpec lists of *ast.ValueSpec
- return hasExportedNames(s.(*ast.ValueSpec).Names);
- }
- return false;
-}
-
-
-// ----------------------------------------------------------------------------
-
-type typeDoc struct {
- decl *ast.GenDecl; // len(decl.Specs) == 1, and the element type is *ast.TypeSpec
- factories map[string] *ast.FuncDecl;
- methods map[string] *ast.FuncDecl;
-}
-
-
-// DocReader accumulates documentation for a single package.
-//
-type DocReader struct {
- name string; // package name
- path string; // import path
- doc ast.Comments; // package documentation, if any
- consts *vector.Vector; // list of *ast.GenDecl
- types map[string] *typeDoc;
- vars *vector.Vector; // list of *ast.GenDecl
- funcs map[string] *ast.FuncDecl;
-}
-
-
-// Init initializes a DocReader to collect package documentation
-// for the package with the given package name and import path.
-//
-func (doc *DocReader) Init(pkg, imp string) {
- doc.name = pkg;
- doc.path = imp;
- doc.consts = vector.New(0);
- doc.types = make(map[string] *typeDoc);
- doc.vars = vector.New(0);
- doc.funcs = make(map[string] *ast.FuncDecl);
-}
-
-
-func baseTypeName(typ ast.Expr) string {
- switch t := typ.(type) {
- case *ast.Ident:
- return string(t.Value);
- case *ast.StarExpr:
- return baseTypeName(t.X);
- }
- return "";
-}
-
-
-func (doc *DocReader) lookupTypeDoc(typ ast.Expr) *typeDoc {
- tdoc, found := doc.types[baseTypeName(typ)];
- if found {
- return tdoc;
- }
- return nil;
-}
-
-
-func (doc *DocReader) addType(decl *ast.GenDecl) {
- typ := decl.Specs[0].(*ast.TypeSpec);
- name := typ.Name.Value;
- tdoc := &typeDoc{decl, make(map[string] *ast.FuncDecl), make(map[string] *ast.FuncDecl)};
- doc.types[name] = tdoc;
-}
-
-
-func (doc *DocReader) addFunc(fun *ast.FuncDecl) {
- name := fun.Name.Value;
-
- // determine if it should be associated with a type
- var typ *typeDoc;
- if fun.Recv != nil {
- // method
- // (all receiver types must be declared before they are used)
- typ = doc.lookupTypeDoc(fun.Recv.Type);
- if typ != nil {
- // type found (i.e., exported)
- typ.methods[name] = fun;
- }
- // if the type wasn't found, it wasn't exported
- // TODO(gri): a non-exported type may still have exported functions
- // determine what to do in that case
- return;
- }
-
- // perhaps a factory function
- // determine result type, if any
- if len(fun.Type.Results) >= 1 {
- res := fun.Type.Results[0];
- if len(res.Names) <= 1 {
- // exactly one (named or anonymous) result type
- typ = doc.lookupTypeDoc(res.Type);
- if typ != nil {
- typ.factories[name] = fun;
- return;
- }
- }
- }
-
- // ordinary function
- doc.funcs[name] = fun;
-}
-
-
-func (doc *DocReader) addDecl(decl ast.Decl) {
- switch d := decl.(type) {
- case *ast.GenDecl:
- if len(d.Specs) > 0 {
- switch d.Tok {
- case token.IMPORT:
- // ignore
- case token.CONST:
- // constants are always handled as a group
- if hasExportedSpecs(d.Specs) {
- doc.consts.Push(d);
- }
- case token.TYPE:
- // types are handled individually
- for i, spec := range d.Specs {
- s := spec.(*ast.TypeSpec);
- if s.Name.IsExported() {
- // make a (fake) GenDecl node for this TypeSpec
- // (we need to do this here - as opposed to just
- // for printing - so we don't loose the GenDecl
- // documentation)
- var noPos token.Position;
- doc.addType(&ast.GenDecl{d.Doc, d.Pos(), token.TYPE, noPos, []ast.Spec{s}, noPos});
- }
- }
- case token.VAR:
- // variables are always handled as a group
- if hasExportedSpecs(d.Specs) {
- doc.vars.Push(d);
- }
- }
- }
- case *ast.FuncDecl:
- if d.Name.IsExported() {
- doc.addFunc(d);
- }
- }
-}
-
-
-// AddProgram adds the AST for a source file to the DocReader.
-// Adding the same AST multiple times is a no-op.
-//
-func (doc *DocReader) AddProgram(prog *ast.Program) {
- if doc.name != prog.Name.Value {
- panic("package names don't match");
- }
-
- // add package documentation
- // TODO(gri) what to do if there are multiple files?
- if prog.Doc != nil {
- doc.doc = prog.Doc
- }
-
- // add all exported declarations
- for i, decl := range prog.Decls {
- doc.addDecl(decl);
- }
-}
-
-// ----------------------------------------------------------------------------
-// Conversion to external representation
-
-func astComment(comments ast.Comments) string {
- text := make([]string, len(comments));
- for i, c := range comments {
- text[i] = string(c.Text);
- }
- return commentText(text);
-}
-
-// ValueDoc is the documentation for a group of declared
-// values, either vars or consts.
-//
-type ValueDoc struct {
- Doc string;
- Decl *ast.GenDecl;
- order int;
-}
-
-type sortValueDoc []*ValueDoc
-func (p sortValueDoc) Len() int { return len(p); }
-func (p sortValueDoc) Swap(i, j int) { p[i], p[j] = p[j], p[i]; }
-
-
-func declName(d *ast.GenDecl) string {
- if len(d.Specs) != 1 {
- return ""
- }
-
- switch v := d.Specs[0].(type) {
- case *ast.ValueSpec:
- return v.Names[0].Value;
- case *ast.TypeSpec:
- return v.Name.Value;
- }
-
- return "";
-}
-
-
-func (p sortValueDoc) Less(i, j int) bool {
- // sort by name
- // pull blocks (name = "") up to top
- // in original order
- if ni, nj := declName(p[i].Decl), declName(p[j].Decl); ni != nj {
- return ni < nj;
- }
- return p[i].order < p[j].order;
-}
-
-
-func makeValueDocs(v *vector.Vector) []*ValueDoc {
- d := make([]*ValueDoc, v.Len());
- for i := range d {
- decl := v.At(i).(*ast.GenDecl);
- d[i] = &ValueDoc{astComment(decl.Doc), decl, i};
- }
- sort.Sort(sortValueDoc(d));
- return d;
-}
-
-
-// FuncDoc is the documentation for a func declaration,
-// either a top-level function or a method function.
-//
-type FuncDoc struct {
- Doc string;
- Recv ast.Expr; // TODO(rsc): Would like string here
- Name string;
- Decl *ast.FuncDecl;
-}
-
-type sortFuncDoc []*FuncDoc
-func (p sortFuncDoc) Len() int { return len(p); }
-func (p sortFuncDoc) Swap(i, j int) { p[i], p[j] = p[j], p[i]; }
-func (p sortFuncDoc) Less(i, j int) bool { return p[i].Name < p[j].Name; }
-
-
-func makeFuncDocs(m map[string] *ast.FuncDecl) []*FuncDoc {
- d := make([]*FuncDoc, len(m));
- i := 0;
- for name, f := range m {
- doc := new(FuncDoc);
- doc.Doc = astComment(f.Doc);
- if f.Recv != nil {
- doc.Recv = f.Recv.Type;
- }
- doc.Name = f.Name.Value;
- doc.Decl = f;
- d[i] = doc;
- i++;
- }
- sort.Sort(sortFuncDoc(d));
- return d;
-}
-
-
-// TypeDoc is the documentation for a declared type.
-// Factories is a sorted list of factory functions that return that type.
-// Methods is a sorted list of method functions on that type.
-type TypeDoc struct {
- Doc string;
- Type *ast.TypeSpec;
- Factories []*FuncDoc;
- Methods []*FuncDoc;
- Decl *ast.GenDecl;
- order int;
-}
-
-type sortTypeDoc []*TypeDoc
-func (p sortTypeDoc) Len() int { return len(p); }
-func (p sortTypeDoc) Swap(i, j int) { p[i], p[j] = p[j], p[i]; }
-func (p sortTypeDoc) Less(i, j int) bool {
- // sort by name
- // pull blocks (name = "") up to top
- // in original order
- if ni, nj := p[i].Type.Name.Value, p[j].Type.Name.Value; ni != nj {
- return ni < nj;
- }
- return p[i].order < p[j].order;
-}
-
-
-// NOTE(rsc): This would appear not to be correct for type ( )
-// blocks, but the doc extractor above has split them into
-// individual statements.
-func makeTypeDocs(m map[string] *typeDoc) []*TypeDoc {
- d := make([]*TypeDoc, len(m));
- i := 0;
- for name, old := range m {
- typespec := old.decl.Specs[0].(*ast.TypeSpec);
- t := new(TypeDoc);
- t.Doc = astComment(typespec.Doc);
- t.Type = typespec;
- t.Factories = makeFuncDocs(old.factories);
- t.Methods = makeFuncDocs(old.methods);
- t.Decl = old.decl;
- t.order = i;
- d[i] = t;
- i++;
- }
- sort.Sort(sortTypeDoc(d));
- return d;
-}
-
-
-// PackageDoc is the documentation for an entire package.
-//
-type PackageDoc struct {
- PackageName string;
- ImportPath string;
- Doc string;
- Consts []*ValueDoc;
- Types []*TypeDoc;
- Vars []*ValueDoc;
- Funcs []*FuncDoc;
-}
-
-
-// Doc returns the accumulated documentation for the package.
-//
-func (doc *DocReader) Doc() *PackageDoc {
- p := new(PackageDoc);
- p.PackageName = doc.name;
- p.ImportPath = doc.path;
- p.Doc = astComment(doc.doc);
- p.Consts = makeValueDocs(doc.consts);
- p.Vars = makeValueDocs(doc.vars);
- p.Types = makeTypeDocs(doc.types);
- p.Funcs = makeFuncDocs(doc.funcs);
- return p;
-}
-
-
-// ----------------------------------------------------------------------------
-// Filtering by name
-
-// Does s look like a regular expression?
-func isRegexp(s string) bool {
- metachars := ".(|)*+?^$[]";
- for i, c := range s {
- for j, m := range metachars {
- if c == m {
- return true
- }
- }
- }
- return false
-}
-
-
-func match(s string, a []string) bool {
- for i, t := range a {
- if isRegexp(t) {
- if matched, err := regexp.Match(t, s); matched {
- return true;
- }
- }
- if s == t {
- return true;
- }
- }
- return false;
-}
-
-
-func matchDecl(d *ast.GenDecl, names []string) bool {
- for i, d := range d.Specs {
- switch v := d.(type) {
- case *ast.ValueSpec:
- for j, name := range v.Names {
- if match(name.Value, names) {
- return true;
- }
- }
- case *ast.TypeSpec:
- if match(v.Name.Value, names) {
- return true;
- }
- }
- }
- return false;
-}
-
-
-func filterValueDocs(a []*ValueDoc, names []string) []*ValueDoc {
- w := 0;
- for i, vd := range a {
- if matchDecl(vd.Decl, names) {
- a[w] = vd;
- w++;
- }
- }
- return a[0 : w];
-}
-
-
-func filterFuncDocs(a []*FuncDoc, names []string) []*FuncDoc {
- w := 0;
- for i, fd := range a {
- if match(fd.Name, names) {
- a[w] = fd;
- w++;
- }
- }
- return a[0 : w];
-}
-
-
-func filterTypeDocs(a []*TypeDoc, names []string) []*TypeDoc {
- w := 0;
- for i, td := range a {
- match := false;
- if matchDecl(td.Decl, names) {
- match = true;
- } else {
- // type name doesn't match, but we may have matching factories or methods
- td.Factories = filterFuncDocs(td.Factories, names);
- td.Methods = filterFuncDocs(td.Methods, names);
- match = len(td.Factories) > 0 || len(td.Methods) > 0;
- }
- if match {
- a[w] = td;
- w++;
- }
- }
- return a[0 : w];
-}
-
-
-// Filter eliminates information from d that is not
-// about one of the given names.
-// TODO: Recognize "Type.Method" as a name.
-// TODO(r): maybe precompile the regexps.
-//
-func (p *PackageDoc) Filter(names []string) {
- p.Consts = filterValueDocs(p.Consts, names);
- p.Vars = filterValueDocs(p.Vars, names);
- p.Types = filterTypeDocs(p.Types, names);
- p.Funcs = filterFuncDocs(p.Funcs, names);
- p.Doc = ""; // don't show top-level package doc
-}
-
diff --git a/src/lib/go/parser/Makefile b/src/lib/go/parser/Makefile
deleted file mode 100644
index 08d83646f..000000000
--- a/src/lib/go/parser/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# DO NOT EDIT. Automatically generated by gobuild.
-# gobuild -m >Makefile
-
-D=/go/
-
-include $(GOROOT)/src/Make.$(GOARCH)
-AR=gopack
-
-default: packages
-
-clean:
- rm -rf *.[$(OS)] *.a [$(OS)].out _obj
-
-test: packages
- gotest
-
-coverage: packages
- gotest
- 6cov -g `pwd` | grep -v '_test\.go:'
-
-%.$O: %.go
- $(GC) -I_obj $*.go
-
-%.$O: %.c
- $(CC) $*.c
-
-%.$O: %.s
- $(AS) $*.s
-
-O1=\
- parser.$O\
-
-
-phases: a1
-_obj$D/parser.a: phases
-
-a1: $(O1)
- $(AR) grc _obj$D/parser.a parser.$O
- rm -f $(O1)
-
-
-newpkg: clean
- mkdir -p _obj$D
- $(AR) grc _obj$D/parser.a
-
-$(O1): newpkg
-$(O2): a1
-
-nuke: clean
- rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/parser.a
-
-packages: _obj$D/parser.a
-
-install: packages
- test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D
- cp _obj$D/parser.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/parser.a
diff --git a/src/lib/go/parser/parser.go b/src/lib/go/parser/parser.go
deleted file mode 100644
index 056868695..000000000
--- a/src/lib/go/parser/parser.go
+++ /dev/null
@@ -1,1975 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// A parser for Go source text. The input is a stream of lexical tokens
-// provided via the Scanner interface. The output is an abstract syntax
-// tree (AST) representing the Go source. The parser is invoked by calling
-// Parse.
-//
-package parser
-
-import (
- "container/vector";
- "fmt";
- "go/ast";
- "go/scanner";
- "go/token";
- "io";
- "os";
-)
-
-
-// A parser error is represented by an Error node. The position Pos, if
-// valid, points to the beginning of the offending token, and the error
-// condition is described by Msg.
-//
-type Error struct {
- Pos token.Position;
- Msg string;
-}
-
-
-func (e *Error) String() string {
- pos := "";
- if e.Pos.IsValid() {
- pos = fmt.Sprintf("%d:%d: ", e.Pos.Line, e.Pos.Column);
- }
- return pos + e.Msg;
-}
-
-
-// Parser errors are returned as an ErrorList.
-type ErrorList []*Error
-
-
-// ErrorList implements the SortInterface.
-func (p ErrorList) Len() int { return len(p); }
-func (p ErrorList) Swap(i, j int) { p[i], p[j] = p[j], p[i]; }
-func (p ErrorList) Less(i, j int) bool { return p[i].Pos.Offset < p[j].Pos.Offset; }
-
-
-func (p ErrorList) String() string {
- switch len(p) {
- case 0: return "unspecified error";
- case 1: return p[0].String();
- }
- return fmt.Sprintf("%s (and %d more errors)", p[0].String(), len(p) - 1);
-}
-
-
-type interval struct {
- beg, end int;
-}
-
-
-// The parser structure holds the parser's internal state.
-type parser struct {
- errors vector.Vector;
- scanner scanner.Scanner;
-
- // Tracing/debugging
- mode uint; // parsing mode
- trace bool; // == (mode & Trace != 0)
- indent uint; // indentation used for tracing output
-
- // Comments
- comments vector.Vector; // list of collected, unassociated comments
- last_doc interval; // last comments interval of consecutive comments
-
- // The next token
- pos token.Position; // token position
- tok token.Token; // one token look-ahead
- lit []byte; // token literal
-
- // Non-syntactic parser control
- opt_semi bool; // true if semicolon separator is optional in statement list
- expr_lev int; // < 0: in control clause, >= 0: in expression
-};
-
-
-// noPos is used when there is no corresponding source position for a token
-var noPos token.Position;
-
-
-// ----------------------------------------------------------------------------
-// Parsing support
-
-func (p *parser) printTrace(a ...) {
- const dots =
- ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
- ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ";
- const n = uint(len(dots));
- fmt.Printf("%5d:%3d: ", p.pos.Line, p.pos.Column);
- i := 2*p.indent;
- for ; i > n; i -= n {
- fmt.Print(dots);
- }
- fmt.Print(dots[0 : i]);
- fmt.Println(a);
-}
-
-
-func trace(p *parser, msg string) *parser {
- p.printTrace(msg, "(");
- p.indent++;
- return p;
-}
-
-
-func un/*trace*/(p *parser) {
- p.indent--;
- p.printTrace(")");
-}
-
-
-func (p *parser) next0() {
- // Because of one-token look-ahead, print the previous token
- // when tracing as it provides a more readable output. The
- // very first token (p.pos.Line == 0) is not initialized (it
- // is token.ILLEGAL), so don't print it .
- if p.trace && p.pos.Line > 0 {
- s := p.tok.String();
- switch {
- case p.tok.IsLiteral():
- p.printTrace(s, string(p.lit));
- case p.tok.IsOperator(), p.tok.IsKeyword():
- p.printTrace("\"" + s + "\"");
- default:
- p.printTrace(s);
- }
- }
-
- p.pos, p.tok, p.lit = p.scanner.Scan();
- p.opt_semi = false;
-}
-
-
-// Collect a comment in the parser's comment list and return the line
-// on which the comment ends.
-//
-func (p *parser) collectComment() int {
- // For /*-style comments, the comment may end on a different line.
- // Scan the comment for '\n' chars and adjust the end line accordingly.
- // (Note that the position of the next token may be even further down
- // as there may be more whitespace lines after the comment.)
- endline := p.pos.Line;
- if p.lit[1] == '*' {
- for _, b := range p.lit {
- if b == '\n' {
- endline++;
- }
- }
- }
- p.comments.Push(&ast.Comment{p.pos, p.lit, endline});
- p.next0();
-
- return endline;
-}
-
-
-func (p *parser) getComments() interval {
- // group adjacent comments, an empty line terminates a group
- beg := p.comments.Len();
- endline := p.pos.Line;
- for p.tok == token.COMMENT && endline+1 >= p.pos.Line {
- endline = p.collectComment();
- }
- end := p.comments.Len();
- return interval {beg, end};
-}
-
-
-func (p *parser) getDoc() ast.Comments {
- doc := p.last_doc;
- n := doc.end - doc.beg;
-
- if n <= 0 || p.comments.At(doc.end - 1).(*ast.Comment).EndLine + 1 < p.pos.Line {
- // no comments or empty line between last comment and current token;
- // do not use as documentation
- return nil;
- }
-
- // found immediately adjacent comment interval;
- // use as documentation
- c := make(ast.Comments, n);
- for i := 0; i < n; i++ {
- c[i] = p.comments.At(doc.beg + i).(*ast.Comment);
- }
-
- // remove comments from the general list
- p.comments.Cut(doc.beg, doc.end);
-
- return c;
-}
-
-
-func (p *parser) next() {
- p.next0();
- p.last_doc = interval{0, 0};
- for p.tok == token.COMMENT {
- p.last_doc = p.getComments();
- }
-}
-
-
-// The parser implements scanner.Error.
-func (p *parser) Error(pos token.Position, msg string) {
- // Don't collect errors that are on the same line as the previous error
- // in the hope to reduce the number of spurious errors due to incorrect
- // parser synchronization.
- if p.errors.Len() == 0 || p.errors.Last().(*Error).Pos.Line != pos.Line {
- p.errors.Push(&Error{pos, msg});
- }
-}
-
-
-func (p *parser) error_expected(pos token.Position, msg string) {
- msg = "expected " + msg;
- if pos.Offset == p.pos.Offset {
- // the error happened at the current position;
- // make the error message more specific
- msg += ", found '" + p.tok.String() + "'";
- if p.tok.IsLiteral() {
- msg += " " + string(p.lit);
- }
- }
- p.Error(pos, msg);
-}
-
-
-func (p *parser) expect(tok token.Token) token.Position {
- pos := p.pos;
- if p.tok != tok {
- p.error_expected(pos, "'" + tok.String() + "'");
- }
- p.next(); // make progress in any case
- return pos;
-}
-
-
-// ----------------------------------------------------------------------------
-// Common productions
-
-func (p *parser) tryType() ast.Expr;
-func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit
-func (p *parser) parseExpression() ast.Expr;
-func (p *parser) parseStatement() ast.Stmt;
-func (p *parser) parseDeclaration() ast.Decl;
-
-
-func (p *parser) parseIdent() *ast.Ident {
- if p.tok == token.IDENT {
- x := &ast.Ident{p.pos, string(p.lit)};
- p.next();
- return x;
- }
- p.expect(token.IDENT); // use expect() error handling
- return &ast.Ident{p.pos, ""};
-}
-
-
-func (p *parser) parseIdentList(x ast.Expr) []*ast.Ident {
- if p.trace {
- defer un(trace(p, "IdentList"));
- }
-
- list := vector.New(0);
- if x == nil {
- x = p.parseIdent();
- }
- list.Push(x);
- for p.tok == token.COMMA {
- p.next();
- list.Push(p.parseIdent());
- }
-
- // convert vector
- idents := make([]*ast.Ident, list.Len());
- for i := 0; i < list.Len(); i++ {
- idents[i] = list.At(i).(*ast.Ident);
- }
-
- return idents;
-}
-
-
-func (p *parser) parseExpressionList() []ast.Expr {
- if p.trace {
- defer un(trace(p, "ExpressionList"));
- }
-
- list := vector.New(0);
- list.Push(p.parseExpression());
- for p.tok == token.COMMA {
- p.next();
- list.Push(p.parseExpression());
- }
-
- // convert list
- exprs := make([]ast.Expr, list.Len());
- for i := 0; i < list.Len(); i++ {
- exprs[i] = list.At(i).(ast.Expr);
- }
-
- return exprs;
-}
-
-
-// ----------------------------------------------------------------------------
-// Types
-
-func (p *parser) parseType() ast.Expr {
- if p.trace {
- defer un(trace(p, "Type"));
- }
-
- typ := p.tryType();
-
- if typ == nil {
- p.error_expected(p.pos, "type");
- p.next(); // make progress
- return &ast.BadExpr{p.pos};
- }
-
- return typ;
-}
-
-
-func (p *parser) parseQualifiedIdent() ast.Expr {
- if p.trace {
- defer un(trace(p, "QualifiedIdent"));
- }
-
- var x ast.Expr = p.parseIdent();
- if p.tok == token.PERIOD {
- // first identifier is a package identifier
- p.next();
- sel := p.parseIdent();
- x = &ast.SelectorExpr{x, sel};
- }
- return x;
-}
-
-
-func (p *parser) parseTypeName() ast.Expr {
- if p.trace {
- defer un(trace(p, "TypeName"));
- }
-
- return p.parseQualifiedIdent();
-}
-
-
-func (p *parser) parseArrayType(ellipsis_ok bool) ast.Expr {
- if p.trace {
- defer un(trace(p, "ArrayType"));
- }
-
- lbrack := p.expect(token.LBRACK);
- var len ast.Expr;
- if ellipsis_ok && p.tok == token.ELLIPSIS {
- len = &ast.Ellipsis{p.pos};
- p.next();
- } else if p.tok != token.RBRACK {
- len = p.parseExpression();
- }
- p.expect(token.RBRACK);
- elt := p.parseType();
-
- return &ast.ArrayType{lbrack, len, elt};
-}
-
-
-func (p *parser) makeIdentList(list *vector.Vector) []*ast.Ident {
- idents := make([]*ast.Ident, list.Len());
- for i := 0; i < list.Len(); i++ {
- ident, is_ident := list.At(i).(*ast.Ident);
- if !is_ident {
- pos := list.At(i).(ast.Expr).Pos();
- p.error_expected(pos, "identifier");
- idents[i] = &ast.Ident{pos, ""};
- }
- idents[i] = ident;
- }
- return idents;
-}
-
-
-func (p *parser) parseFieldDecl() *ast.Field {
- if p.trace {
- defer un(trace(p, "FieldDecl"));
- }
-
- doc := p.getDoc();
-
- // a list of identifiers looks like a list of type names
- list := vector.New(0);
- for {
- // TODO do not allow ()'s here
- list.Push(p.parseType());
- if p.tok == token.COMMA {
- p.next();
- } else {
- break;
- }
- }
-
- // if we had a list of identifiers, it must be followed by a type
- typ := p.tryType();
-
- // optional tag
- var tag []*ast.StringLit;
- if p.tok == token.STRING {
- tag = p.parseStringList(nil);
- }
-
- // analyze case
- var idents []*ast.Ident;
- if typ != nil {
- // IdentifierList Type
- idents = p.makeIdentList(list);
- } else {
- // Type (anonymous field)
- if list.Len() == 1 {
- // TODO check that this looks like a type
- typ = list.At(0).(ast.Expr);
- } else {
- p.error_expected(p.pos, "anonymous field");
- typ = &ast.BadExpr{p.pos};
- }
- }
-
- return &ast.Field{doc, idents, typ, tag};
-}
-
-
-func (p *parser) parseStructType() *ast.StructType {
- if p.trace {
- defer un(trace(p, "StructType"));
- }
-
- pos := p.expect(token.STRUCT);
- var lbrace, rbrace token.Position;
- var fields []*ast.Field;
- if p.tok == token.LBRACE {
- lbrace = p.pos;
- p.next();
-
- list := vector.New(0);
- for p.tok != token.RBRACE && p.tok != token.EOF {
- list.Push(p.parseFieldDecl());
- if p.tok == token.SEMICOLON {
- p.next();
- } else {
- break;
- }
- }
- if p.tok == token.SEMICOLON {
- p.next();
- }
-
- rbrace = p.expect(token.RBRACE);
- p.opt_semi = true;
-
- // convert vector
- fields = make([]*ast.Field, list.Len());
- for i := list.Len() - 1; i >= 0; i-- {
- fields[i] = list.At(i).(*ast.Field);
- }
- }
-
- return &ast.StructType{pos, lbrace, fields, rbrace};
-}
-
-
-func (p *parser) parsePointerType() *ast.StarExpr {
- if p.trace {
- defer un(trace(p, "PointerType"));
- }
-
- star := p.expect(token.MUL);
- base := p.parseType();
-
- return &ast.StarExpr{star, base};
-}
-
-
-func (p *parser) tryParameterType(ellipsis_ok bool) ast.Expr {
- if ellipsis_ok && p.tok == token.ELLIPSIS {
- pos := p.pos;
- p.next();
- if p.tok != token.RPAREN {
- // "..." always must be at the very end of a parameter list
- p.Error(pos, "expected type, found '...'");
- }
- return &ast.Ellipsis{pos};
- }
- return p.tryType();
-}
-
-
-func (p *parser) parseParameterType(ellipsis_ok bool) ast.Expr {
- typ := p.tryParameterType(ellipsis_ok);
- if typ == nil {
- p.error_expected(p.pos, "type");
- p.next(); // make progress
- typ = &ast.BadExpr{p.pos};
- }
- return typ;
-}
-
-
-func (p *parser) parseParameterDecl(ellipsis_ok bool) (*vector.Vector, ast.Expr) {
- if p.trace {
- defer un(trace(p, "ParameterDecl"));
- }
-
- // a list of identifiers looks like a list of type names
- list := vector.New(0);
- for {
- // TODO do not allow ()'s here
- list.Push(p.parseParameterType(ellipsis_ok));
- if p.tok == token.COMMA {
- p.next();
- } else {
- break;
- }
- }
-
- // if we had a list of identifiers, it must be followed by a type
- typ := p.tryParameterType(ellipsis_ok);
-
- return list, typ;
-}
-
-
-func (p *parser) parseParameterList(ellipsis_ok bool) []*ast.Field {
- if p.trace {
- defer un(trace(p, "ParameterList"));
- }
-
- list, typ := p.parseParameterDecl(ellipsis_ok);
- if typ != nil {
- // IdentifierList Type
- idents := p.makeIdentList(list);
- list.Init(0);
- list.Push(&ast.Field{nil, idents, typ, nil});
-
- for p.tok == token.COMMA {
- p.next();
- idents := p.parseIdentList(nil);
- typ := p.parseParameterType(ellipsis_ok);
- list.Push(&ast.Field{nil, idents, typ, nil});
- }
-
- } else {
- // Type { "," Type } (anonymous parameters)
- // convert list of types into list of *Param
- for i := 0; i < list.Len(); i++ {
- list.Set(i, &ast.Field{nil, nil, list.At(i).(ast.Expr), nil});
- }
- }
-
- // convert list
- params := make([]*ast.Field, list.Len());
- for i := 0; i < list.Len(); i++ {
- params[i] = list.At(i).(*ast.Field);
- }
-
- return params;
-}
-
-
-func (p *parser) parseParameters(ellipsis_ok bool) []*ast.Field {
- if p.trace {
- defer un(trace(p, "Parameters"));
- }
-
- var params []*ast.Field;
- p.expect(token.LPAREN);
- if p.tok != token.RPAREN {
- params = p.parseParameterList(ellipsis_ok);
- }
- p.expect(token.RPAREN);
-
- return params;
-}
-
-
-func (p *parser) parseResult() []*ast.Field {
- if p.trace {
- defer un(trace(p, "Result"));
- }
-
- var results []*ast.Field;
- if p.tok == token.LPAREN {
- results = p.parseParameters(false);
- } else if p.tok != token.FUNC {
- typ := p.tryType();
- if typ != nil {
- results = make([]*ast.Field, 1);
- results[0] = &ast.Field{nil, nil, typ, nil};
- }
- }
-
- return results;
-}
-
-
-func (p *parser) parseSignature() (params []*ast.Field, results []*ast.Field) {
- if p.trace {
- defer un(trace(p, "Signature"));
- }
-
- params = p.parseParameters(true);
- results = p.parseResult();
-
- return params, results;
-}
-
-
-func (p *parser) parseFuncType() *ast.FuncType {
- if p.trace {
- defer un(trace(p, "FuncType"));
- }
-
- pos := p.expect(token.FUNC);
- params, results := p.parseSignature();
-
- return &ast.FuncType{pos, params, results};
-}
-
-
-func (p *parser) parseMethodSpec() *ast.Field {
- if p.trace {
- defer un(trace(p, "MethodSpec"));
- }
-
- doc := p.getDoc();
- var idents []*ast.Ident;
- var typ ast.Expr;
- x := p.parseQualifiedIdent();
- if tmp, is_ident := x.(*ast.Ident); is_ident && (p.tok == token.COMMA || p.tok == token.LPAREN) {
- // methods
- idents = p.parseIdentList(x);
- params, results := p.parseSignature();
- typ = &ast.FuncType{noPos, params, results};
- } else {
- // embedded interface
- typ = x;
- }
-
- return &ast.Field{doc, idents, typ, nil};
-}
-
-
-func (p *parser) parseInterfaceType() *ast.InterfaceType {
- if p.trace {
- defer un(trace(p, "InterfaceType"));
- }
-
- pos := p.expect(token.INTERFACE);
- var lbrace, rbrace token.Position;
- var methods []*ast.Field;
- if p.tok == token.LBRACE {
- lbrace = p.pos;
- p.next();
-
- list := vector.New(0);
- for p.tok == token.IDENT {
- list.Push(p.parseMethodSpec());
- if p.tok != token.RBRACE {
- p.expect(token.SEMICOLON);
- }
- }
-
- rbrace = p.expect(token.RBRACE);
- p.opt_semi = true;
-
- // convert vector
- methods = make([]*ast.Field, list.Len());
- for i := list.Len() - 1; i >= 0; i-- {
- methods[i] = list.At(i).(*ast.Field);
- }
- }
-
- return &ast.InterfaceType{pos, lbrace, methods, rbrace};
-}
-
-
-func (p *parser) parseMapType() *ast.MapType {
- if p.trace {
- defer un(trace(p, "MapType"));
- }
-
- pos := p.expect(token.MAP);
- p.expect(token.LBRACK);
- key := p.parseType();
- p.expect(token.RBRACK);
- value := p.parseType();
-
- return &ast.MapType{pos, key, value};
-}
-
-
-func (p *parser) parseChanType() *ast.ChanType {
- if p.trace {
- defer un(trace(p, "ChanType"));
- }
-
- pos := p.pos;
- dir := ast.SEND | ast.RECV;
- if p.tok == token.CHAN {
- p.next();
- if p.tok == token.ARROW {
- p.next();
- dir = ast.SEND;
- }
- } else {
- p.expect(token.ARROW);
- p.expect(token.CHAN);
- dir = ast.RECV;
- }
- value := p.parseType();
-
- return &ast.ChanType{pos, dir, value};
-}
-
-
-func (p *parser) tryRawType(ellipsis_ok bool) ast.Expr {
- switch p.tok {
- case token.IDENT: return p.parseTypeName();
- case token.LBRACK: return p.parseArrayType(ellipsis_ok);
- case token.STRUCT: return p.parseStructType();
- case token.MUL: return p.parsePointerType();
- case token.FUNC: return p.parseFuncType();
- case token.INTERFACE: return p.parseInterfaceType();
- case token.MAP: return p.parseMapType();
- case token.CHAN, token.ARROW: return p.parseChanType();
- case token.LPAREN:
- lparen := p.pos;
- p.next();
- typ := p.parseType();
- rparen := p.expect(token.RPAREN);
- return &ast.ParenExpr{lparen, typ, rparen};
- }
-
- // no type found
- return nil;
-}
-
-
-func (p *parser) tryType() ast.Expr {
- return p.tryRawType(false);
-}
-
-
-// ----------------------------------------------------------------------------
-// Blocks
-
-func makeStmtList(list *vector.Vector) []ast.Stmt {
- stats := make([]ast.Stmt, list.Len());
- for i := 0; i < list.Len(); i++ {
- stats[i] = list.At(i).(ast.Stmt);
- }
- return stats;
-}
-
-
-func (p *parser) parseStatementList() []ast.Stmt {
- if p.trace {
- defer un(trace(p, "StatementList"));
- }
-
- list := vector.New(0);
- expect_semi := false;
- for p.tok != token.CASE && p.tok != token.DEFAULT && p.tok != token.RBRACE && p.tok != token.EOF {
- if expect_semi {
- p.expect(token.SEMICOLON);
- expect_semi = false;
- }
- list.Push(p.parseStatement());
- if p.tok == token.SEMICOLON {
- p.next();
- } else if p.opt_semi {
- p.opt_semi = false; // "consume" optional semicolon
- } else {
- expect_semi = true;
- }
- }
-
- return makeStmtList(list);
-}
-
-
-func (p *parser) parseBlockStmt() *ast.BlockStmt {
- if p.trace {
- defer un(trace(p, "BlockStmt"));
- }
-
- lbrace := p.expect(token.LBRACE);
- list := p.parseStatementList();
- rbrace := p.expect(token.RBRACE);
- p.opt_semi = true;
-
- return &ast.BlockStmt{lbrace, list, rbrace};
-}
-
-
-// ----------------------------------------------------------------------------
-// Expressions
-
-func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit {
- if p.trace {
- defer un(trace(p, "StringList"));
- }
-
- list := vector.New(0);
- if x != nil {
- list.Push(x);
- }
-
- for p.tok == token.STRING {
- list.Push(&ast.StringLit{p.pos, p.lit});
- p.next();
- }
-
- // convert list
- strings := make([]*ast.StringLit, list.Len());
- for i := 0; i < list.Len(); i++ {
- strings[i] = list.At(i).(*ast.StringLit);
- }
-
- return strings;
-}
-
-
-func (p *parser) parseFuncLit() ast.Expr {
- if p.trace {
- defer un(trace(p, "FuncLit"));
- }
-
- typ := p.parseFuncType();
- p.expr_lev++;
- body := p.parseBlockStmt();
- p.opt_semi = false; // function body requires separating ";"
- p.expr_lev--;
-
- return &ast.FuncLit{typ, body};
-}
-
-
-// parseOperand may return an expression or a raw type (incl. array
-// types of the form [...]T. Callers must verify the result.
-//
-func (p *parser) parseOperand() ast.Expr {
- if p.trace {
- defer un(trace(p, "Operand"));
- }
-
- switch p.tok {
- case token.IDENT:
- return p.parseIdent();
-
- case token.INT:
- x := &ast.IntLit{p.pos, p.lit};
- p.next();
- return x;
-
- case token.FLOAT:
- x := &ast.FloatLit{p.pos, p.lit};
- p.next();
- return x;
-
- case token.CHAR:
- x := &ast.CharLit{p.pos, p.lit};
- p.next();
- return x;
-
- case token.STRING:
- x := &ast.StringLit{p.pos, p.lit};
- p.next();
- if p.tok == token.STRING {
- return &ast.StringList{p.parseStringList(x)};
- }
- return x;
-
- case token.LPAREN:
- lparen := p.pos;
- p.next();
- p.expr_lev++;
- x := p.parseExpression();
- p.expr_lev--;
- rparen := p.expect(token.RPAREN);
- return &ast.ParenExpr{lparen, x, rparen};
-
- case token.FUNC:
- return p.parseFuncLit();
-
- default:
- t := p.tryRawType(true); // could be type for composite literal
- if t != nil {
- return t;
- }
- }
-
- p.error_expected(p.pos, "operand");
- p.next(); // make progress
- return &ast.BadExpr{p.pos};
-}
-
-
-func (p *parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr {
- if p.trace {
- defer un(trace(p, "SelectorOrTypeAssertion"));
- }
-
- p.expect(token.PERIOD);
- if p.tok == token.IDENT {
- // selector
- sel := p.parseIdent();
- return &ast.SelectorExpr{x, sel};
- }
-
- // type assertion
- p.expect(token.LPAREN);
- var typ ast.Expr;
- if p.tok == token.TYPE {
- // special case for type switch
- typ = &ast.Ident{p.pos, "type"};
- p.next();
- } else {
- typ = p.parseType();
- }
- p.expect(token.RPAREN);
-
- return &ast.TypeAssertExpr{x, typ};
-}
-
-
-func (p *parser) parseIndex(x ast.Expr) ast.Expr {
- if p.trace {
- defer un(trace(p, "Index"));
- }
-
- p.expect(token.LBRACK);
- p.expr_lev++;
- begin := p.parseExpression();
- var end ast.Expr;
- if p.tok == token.COLON {
- p.next();
- end = p.parseExpression();
- }
- p.expr_lev--;
- p.expect(token.RBRACK);
-
- return &ast.IndexExpr{x, begin, end};
-}
-
-
-func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
- if p.trace {
- defer un(trace(p, "CallOrConversion"));
- }
-
- lparen := p.expect(token.LPAREN);
- var args []ast.Expr;
- if p.tok != token.RPAREN {
- args = p.parseExpressionList();
- }
- rparen := p.expect(token.RPAREN);
-
- return &ast.CallExpr{fun, lparen, args, rparen};
-}
-
-
-func (p *parser) parseElement() ast.Expr {
- if p.trace {
- defer un(trace(p, "Element"));
- }
-
- x := p.parseExpression();
- if p.tok == token.COLON {
- colon := p.pos;
- p.next();
- x = &ast.KeyValueExpr{x, colon, p.parseExpression()};
- }
-
- return x;
-}
-
-
-func (p *parser) parseElementList() []ast.Expr {
- if p.trace {
- defer un(trace(p, "ElementList"));
- }
-
- list := vector.New(0);
- for p.tok != token.RBRACE && p.tok != token.EOF {
- list.Push(p.parseElement());
- if p.tok == token.COMMA {
- p.next();
- } else {
- break;
- }
- }
-
- // convert list
- elts := make([]ast.Expr, list.Len());
- for i := 0; i < list.Len(); i++ {
- elts[i] = list.At(i).(ast.Expr);
- }
-
- return elts;
-}
-
-
-func (p *parser) parseCompositeLit(typ ast.Expr) ast.Expr {
- if p.trace {
- defer un(trace(p, "CompositeLit"));
- }
-
- lbrace := p.expect(token.LBRACE);
- var elts []ast.Expr;
- if p.tok != token.RBRACE {
- elts = p.parseElementList();
- }
- rbrace := p.expect(token.RBRACE);
- return &ast.CompositeLit{typ, lbrace, elts, rbrace};
-}
-
-
-// TODO Consider different approach to checking syntax after parsing:
-// Provide a arguments (set of flags) to parsing functions
-// restricting what they are syupposed to accept depending
-// on context.
-
-// checkExpr checks that x is an expression (and not a type).
-func (p *parser) checkExpr(x ast.Expr) ast.Expr {
- // TODO should provide predicate in AST nodes
- switch t := x.(type) {
- case *ast.BadExpr:
- case *ast.Ident:
- case *ast.IntLit:
- case *ast.FloatLit:
- case *ast.CharLit:
- case *ast.StringLit:
- case *ast.StringList:
- case *ast.FuncLit:
- case *ast.CompositeLit:
- case *ast.ParenExpr:
- case *ast.SelectorExpr:
- case *ast.IndexExpr:
- case *ast.TypeAssertExpr:
- case *ast.CallExpr:
- case *ast.StarExpr:
- case *ast.UnaryExpr:
- if t.Op == token.RANGE {
- // the range operator is only allowed at the top of a for statement
- p.error_expected(x.Pos(), "expression");
- x = &ast.BadExpr{x.Pos()};
- }
- case *ast.BinaryExpr:
- default:
- // all other nodes are not proper expressions
- p.error_expected(x.Pos(), "expression");
- x = &ast.BadExpr{x.Pos()};
- }
- return x;
-}
-
-
-// isTypeName returns true iff x is type name.
-func isTypeName(x ast.Expr) bool {
- // TODO should provide predicate in AST nodes
- switch t := x.(type) {
- case *ast.BadExpr:
- case *ast.Ident:
- case *ast.ParenExpr: return isTypeName(t.X); // TODO should (TypeName) be illegal?
- case *ast.SelectorExpr: return isTypeName(t.X);
- default: return false; // all other nodes are not type names
- }
- return true;
-}
-
-
-// isCompositeLitType returns true iff x is a legal composite literal type.
-func isCompositeLitType(x ast.Expr) bool {
- // TODO should provide predicate in AST nodes
- switch t := x.(type) {
- case *ast.BadExpr:
- case *ast.Ident:
- case *ast.ParenExpr: return isCompositeLitType(t.X);
- case *ast.SelectorExpr: return isTypeName(t.X);
- case *ast.ArrayType:
- case *ast.StructType:
- case *ast.MapType:
- default: return false; // all other nodes are not legal composite literal types
- }
- return true;
-}
-
-
-// checkExprOrType checks that x is an expression or a type
-// (and not a raw type such as [...]T).
-//
-func (p *parser) checkExprOrType(x ast.Expr) ast.Expr {
- // TODO should provide predicate in AST nodes
- switch t := x.(type) {
- case *ast.UnaryExpr:
- if t.Op == token.RANGE {
- // the range operator is only allowed at the top of a for statement
- p.error_expected(x.Pos(), "expression");
- x = &ast.BadExpr{x.Pos()};
- }
- case *ast.ArrayType:
- if len, is_ellipsis := t.Len.(*ast.Ellipsis); is_ellipsis {
- p.Error(len.Pos(), "expected array length, found '...'");
- x = &ast.BadExpr{x.Pos()};
- }
- }
-
- // all other nodes are expressions or types
- return x;
-}
-
-
-func (p *parser) parsePrimaryExpr() ast.Expr {
- if p.trace {
- defer un(trace(p, "PrimaryExpr"));
- }
-
- x := p.parseOperand();
-L: for {
- switch p.tok {
- case token.PERIOD: x = p.parseSelectorOrTypeAssertion(p.checkExpr(x));
- case token.LBRACK: x = p.parseIndex(p.checkExpr(x));
- case token.LPAREN: x = p.parseCallOrConversion(p.checkExprOrType(x));
- case token.LBRACE:
- if isCompositeLitType(x) && (p.expr_lev >= 0 || !isTypeName(x)) {
- x = p.parseCompositeLit(x);
- } else {
- break L;
- }
- default:
- break L;
- }
- }
-
- return p.checkExprOrType(x);
-}
-
-
-func (p *parser) parseUnaryExpr() ast.Expr {
- if p.trace {
- defer un(trace(p, "UnaryExpr"));
- }
-
- switch p.tok {
- case token.ADD, token.SUB, token.NOT, token.XOR, token.ARROW, token.AND, token.RANGE:
- pos, op := p.pos, p.tok;
- p.next();
- x := p.parseUnaryExpr();
- return &ast.UnaryExpr{pos, op, p.checkExpr(x)};
-
- case token.MUL:
- // unary "*" expression or pointer type
- pos := p.pos;
- p.next();
- x := p.parseUnaryExpr();
- return &ast.StarExpr{pos, p.checkExprOrType(x)};
- }
-
- return p.parsePrimaryExpr();
-}
-
-
-func (p *parser) parseBinaryExpr(prec1 int) ast.Expr {
- if p.trace {
- defer un(trace(p, "BinaryExpr"));
- }
-
- x := p.parseUnaryExpr();
- for prec := p.tok.Precedence(); prec >= prec1; prec-- {
- for p.tok.Precedence() == prec {
- pos, op := p.pos, p.tok;
- p.next();
- y := p.parseBinaryExpr(prec + 1);
- x = &ast.BinaryExpr{p.checkExpr(x), pos, op, p.checkExpr(y)};
- }
- }
-
- return x;
-}
-
-
-func (p *parser) parseExpression() ast.Expr {
- if p.trace {
- defer un(trace(p, "Expression"));
- }
-
- return p.parseBinaryExpr(token.LowestPrec + 1);
-}
-
-
-// ----------------------------------------------------------------------------
-// Statements
-
-
-func (p *parser) parseSimpleStmt(label_ok bool) ast.Stmt {
- if p.trace {
- defer un(trace(p, "SimpleStmt"));
- }
-
- x := p.parseExpressionList();
-
- switch p.tok {
- case token.COLON:
- // labeled statement
- p.next();
- if label_ok && len(x) == 1 {
- if label, is_ident := x[0].(*ast.Ident); is_ident {
- return &ast.LabeledStmt{label, p.parseStatement()};
- }
- }
- p.Error(x[0].Pos(), "illegal label declaration");
- return &ast.BadStmt{x[0].Pos()};
-
- case
- token.DEFINE, token.ASSIGN, token.ADD_ASSIGN,
- token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN,
- token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN,
- token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN, token.AND_NOT_ASSIGN:
- // assignment statement
- pos, tok := p.pos, p.tok;
- p.next();
- y := p.parseExpressionList();
- if len(x) > 1 && len(y) > 1 && len(x) != len(y) {
- p.Error(x[0].Pos(), "arity of lhs doesn't match rhs");
- }
- return &ast.AssignStmt{x, pos, tok, y};
- }
-
- if len(x) > 1 {
- p.Error(x[0].Pos(), "only one expression allowed");
- // continue with first expression
- }
-
- if p.tok == token.INC || p.tok == token.DEC {
- // increment or decrement
- s := &ast.IncDecStmt{x[0], p.tok};
- p.next(); // consume "++" or "--"
- return s;
- }
-
- // expression
- return &ast.ExprStmt{x[0]};
-}
-
-
-func (p *parser) parseCallExpr() *ast.CallExpr {
- x := p.parseExpression();
- if call, is_call := x.(*ast.CallExpr); is_call {
- return call;
- }
- p.error_expected(x.Pos(), "function/method call");
- return nil;
-}
-
-
-func (p *parser) parseGoStmt() ast.Stmt {
- if p.trace {
- defer un(trace(p, "GoStmt"));
- }
-
- pos := p.expect(token.GO);
- call := p.parseCallExpr();
- if call != nil {
- return &ast.GoStmt{pos, call};
- }
- return &ast.BadStmt{pos};
-}
-
-
-func (p *parser) parseDeferStmt() ast.Stmt {
- if p.trace {
- defer un(trace(p, "DeferStmt"));
- }
-
- pos := p.expect(token.DEFER);
- call := p.parseCallExpr();
- if call != nil {
- return &ast.DeferStmt{pos, call};
- }
- return &ast.BadStmt{pos};
-}
-
-
-func (p *parser) parseReturnStmt() *ast.ReturnStmt {
- if p.trace {
- defer un(trace(p, "ReturnStmt"));
- }
-
- pos := p.pos;
- p.expect(token.RETURN);
- var x []ast.Expr;
- if p.tok != token.SEMICOLON && p.tok != token.RBRACE {
- x = p.parseExpressionList();
- }
-
- return &ast.ReturnStmt{pos, x};
-}
-
-
-func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt {
- if p.trace {
- defer un(trace(p, "BranchStmt"));
- }
-
- s := &ast.BranchStmt{p.pos, tok, nil};
- p.expect(tok);
- if tok != token.FALLTHROUGH && p.tok == token.IDENT {
- s.Label = p.parseIdent();
- }
-
- return s;
-}
-
-
-func (p *parser) isExpr(s ast.Stmt) bool {
- if s == nil {
- return true;
- }
- dummy, is_expr := s.(*ast.ExprStmt);
- return is_expr;
-}
-
-
-func (p *parser) makeExpr(s ast.Stmt) ast.Expr {
- if s == nil {
- return nil;
- }
- if es, is_expr := s.(*ast.ExprStmt); is_expr {
- return p.checkExpr(es.X);
- }
- p.Error(s.Pos(), "expected condition, found simple statement");
- return &ast.BadExpr{s.Pos()};
-}
-
-
-func (p *parser) parseControlClause(isForStmt bool) (s1, s2, s3 ast.Stmt) {
- if p.tok != token.LBRACE {
- prev_lev := p.expr_lev;
- p.expr_lev = -1;
-
- if p.tok != token.SEMICOLON {
- s1 = p.parseSimpleStmt(false);
- }
- if p.tok == token.SEMICOLON {
- p.next();
- if p.tok != token.LBRACE && p.tok != token.SEMICOLON {
- s2 = p.parseSimpleStmt(false);
- }
- if isForStmt {
- // for statements have a 3rd section
- p.expect(token.SEMICOLON);
- if p.tok != token.LBRACE {
- s3 = p.parseSimpleStmt(false);
- }
- }
- } else {
- s1, s2 = nil, s1;
- }
-
- p.expr_lev = prev_lev;
- }
-
- return s1, s2, s3;
-}
-
-
-func (p *parser) parseIfStmt() *ast.IfStmt {
- if p.trace {
- defer un(trace(p, "IfStmt"));
- }
-
- pos := p.expect(token.IF);
- s1, s2, dummy := p.parseControlClause(false);
- body := p.parseBlockStmt();
- var else_ ast.Stmt;
- if p.tok == token.ELSE {
- p.next();
- else_ = p.parseStatement();
- }
-
- return &ast.IfStmt{pos, s1, p.makeExpr(s2), body, else_};
-}
-
-
-func (p *parser) parseCaseClause() *ast.CaseClause {
- if p.trace {
- defer un(trace(p, "CaseClause"));
- }
-
- // SwitchCase
- pos := p.pos;
- var x []ast.Expr;
- if p.tok == token.CASE {
- p.next();
- x = p.parseExpressionList();
- } else {
- p.expect(token.DEFAULT);
- }
-
- colon := p.expect(token.COLON);
- body := p.parseStatementList();
-
- return &ast.CaseClause{pos, x, colon, body};
-}
-
-
-func (p *parser) parseTypeCaseClause() *ast.TypeCaseClause {
- if p.trace {
- defer un(trace(p, "CaseClause"));
- }
-
- // TypeSwitchCase
- pos := p.pos;
- var typ ast.Expr;
- if p.tok == token.CASE {
- p.next();
- typ = p.parseType();
- } else {
- p.expect(token.DEFAULT);
- }
-
- colon := p.expect(token.COLON);
- body := p.parseStatementList();
-
- return &ast.TypeCaseClause{pos, typ, colon, body};
-}
-
-
-func (p *parser) parseSwitchStmt() ast.Stmt {
- if p.trace {
- defer un(trace(p, "SwitchStmt"));
- }
-
- pos := p.expect(token.SWITCH);
- s1, s2, dummy := p.parseControlClause(false);
-
- if p.isExpr(s2) {
- // expression switch
- lbrace := p.expect(token.LBRACE);
- cases := vector.New(0);
- for p.tok == token.CASE || p.tok == token.DEFAULT {
- cases.Push(p.parseCaseClause());
- }
- rbrace := p.expect(token.RBRACE);
- p.opt_semi = true;
- body := &ast.BlockStmt{lbrace, makeStmtList(cases), rbrace};
- return &ast.SwitchStmt{pos, s1, p.makeExpr(s2), body};
- }
-
- // type switch
- // TODO do all the checks!
- lbrace := p.expect(token.LBRACE);
- cases := vector.New(0);
- for p.tok == token.CASE || p.tok == token.DEFAULT {
- cases.Push(p.parseTypeCaseClause());
- }
- rbrace := p.expect(token.RBRACE);
- p.opt_semi = true;
- body := &ast.BlockStmt{lbrace, makeStmtList(cases), rbrace};
- return &ast.TypeSwitchStmt{pos, s1, s2, body};
-}
-
-
-func (p *parser) parseCommClause() *ast.CommClause {
- if p.trace {
- defer un(trace(p, "CommClause"));
- }
-
- // CommCase
- pos := p.pos;
- var tok token.Token;
- var lhs, rhs ast.Expr;
- if p.tok == token.CASE {
- p.next();
- if p.tok == token.ARROW {
- // RecvExpr without assignment
- rhs = p.parseExpression();
- } else {
- // SendExpr or RecvExpr
- rhs = p.parseExpression();
- if p.tok == token.ASSIGN || p.tok == token.DEFINE {
- // RecvExpr with assignment
- tok = p.tok;
- p.next();
- lhs = rhs;
- if p.tok == token.ARROW {
- rhs = p.parseExpression();
- } else {
- p.expect(token.ARROW); // use expect() error handling
- }
- }
- // else SendExpr
- }
- } else {
- p.expect(token.DEFAULT);
- }
-
- colon := p.expect(token.COLON);
- body := p.parseStatementList();
-
- return &ast.CommClause{pos, tok, lhs, rhs, colon, body};
-}
-
-
-func (p *parser) parseSelectStmt() *ast.SelectStmt {
- if p.trace {
- defer un(trace(p, "SelectStmt"));
- }
-
- pos := p.expect(token.SELECT);
- lbrace := p.expect(token.LBRACE);
- cases := vector.New(0);
- for p.tok == token.CASE || p.tok == token.DEFAULT {
- cases.Push(p.parseCommClause());
- }
- rbrace := p.expect(token.RBRACE);
- p.opt_semi = true;
- body := &ast.BlockStmt{lbrace, makeStmtList(cases), rbrace};
-
- return &ast.SelectStmt{pos, body};
-}
-
-
-func (p *parser) parseForStmt() ast.Stmt {
- if p.trace {
- defer un(trace(p, "ForStmt"));
- }
-
- pos := p.expect(token.FOR);
- s1, s2, s3 := p.parseControlClause(true);
- body := p.parseBlockStmt();
-
- if as, is_as := s2.(*ast.AssignStmt); is_as {
- // possibly a for statement with a range clause; check assignment operator
- if as.Tok != token.ASSIGN && as.Tok != token.DEFINE {
- p.error_expected(as.TokPos, "'=' or ':='");
- return &ast.BadStmt{pos};
- }
- // check lhs
- var key, value ast.Expr;
- switch len(as.Lhs) {
- case 2:
- value = as.Lhs[1];
- fallthrough;
- case 1:
- key = as.Lhs[0];
- default:
- p.error_expected(as.Lhs[0].Pos(), "1 or 2 expressions");
- return &ast.BadStmt{pos};
- }
- // check rhs
- if len(as.Rhs) != 1 {
- p.error_expected(as.Rhs[0].Pos(), "1 expressions");
- return &ast.BadStmt{pos};
- }
- if rhs, is_unary := as.Rhs[0].(*ast.UnaryExpr); is_unary && rhs.Op == token.RANGE {
- // rhs is range expression; check lhs
- return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body}
- } else {
- p.error_expected(s2.Pos(), "range clause");
- return &ast.BadStmt{pos};
- }
- } else {
- // regular for statement
- return &ast.ForStmt{pos, s1, p.makeExpr(s2), s3, body};
- }
-
- panic(); // unreachable
- return nil;
-}
-
-
-func (p *parser) parseStatement() ast.Stmt {
- if p.trace {
- defer un(trace(p, "Statement"));
- }
-
- switch p.tok {
- case token.CONST, token.TYPE, token.VAR:
- return &ast.DeclStmt{p.parseDeclaration()};
- case
- // tokens that may start a top-level expression
- token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING, token.FUNC, token.LPAREN, // operand
- token.LBRACK, token.STRUCT, // composite type
- token.MUL, token.AND, token.ARROW: // unary operators
- return p.parseSimpleStmt(true);
- case token.GO:
- return p.parseGoStmt();
- case token.DEFER:
- return p.parseDeferStmt();
- case token.RETURN:
- return p.parseReturnStmt();
- case token.BREAK, token.CONTINUE, token.GOTO, token.FALLTHROUGH:
- return p.parseBranchStmt(p.tok);
- case token.LBRACE:
- return p.parseBlockStmt();
- case token.IF:
- return p.parseIfStmt();
- case token.SWITCH:
- return p.parseSwitchStmt();
- case token.SELECT:
- return p.parseSelectStmt();
- case token.FOR:
- return p.parseForStmt();
- case token.SEMICOLON, token.RBRACE:
- // don't consume the ";", it is the separator following the empty statement
- return &ast.EmptyStmt{p.pos};
- }
-
- // no statement found
- p.error_expected(p.pos, "statement");
- p.next(); // make progress
- return &ast.BadStmt{p.pos};
-}
-
-
-// ----------------------------------------------------------------------------
-// Declarations
-
-type parseSpecFunction func(p *parser, doc ast.Comments) ast.Spec
-
-func parseImportSpec(p *parser, doc ast.Comments) ast.Spec {
- if p.trace {
- defer un(trace(p, "ImportSpec"));
- }
-
- var ident *ast.Ident;
- if p.tok == token.PERIOD {
- ident = &ast.Ident{p.pos, "."};
- p.next();
- } else if p.tok == token.IDENT {
- ident = p.parseIdent();
- }
-
- var path []*ast.StringLit;
- if p.tok == token.STRING {
- path = p.parseStringList(nil);
- } else {
- p.expect(token.STRING); // use expect() error handling
- }
-
- return &ast.ImportSpec{doc, ident, path};
-}
-
-
-func parseConstSpec(p *parser, doc ast.Comments) ast.Spec {
- if p.trace {
- defer un(trace(p, "ConstSpec"));
- }
-
- idents := p.parseIdentList(nil);
- typ := p.tryType();
- var values []ast.Expr;
- if typ != nil || p.tok == token.ASSIGN {
- p.expect(token.ASSIGN);
- values = p.parseExpressionList();
- }
-
- return &ast.ValueSpec{doc, idents, typ, values};
-}
-
-
-func parseTypeSpec(p *parser, doc ast.Comments) ast.Spec {
- if p.trace {
- defer un(trace(p, "TypeSpec"));
- }
-
- ident := p.parseIdent();
- typ := p.parseType();
-
- return &ast.TypeSpec{doc, ident, typ};
-}
-
-
-func parseVarSpec(p *parser, doc ast.Comments) ast.Spec {
- if p.trace {
- defer un(trace(p, "VarSpec"));
- }
-
- idents := p.parseIdentList(nil);
- typ := p.tryType();
- var values []ast.Expr;
- if typ == nil || p.tok == token.ASSIGN {
- p.expect(token.ASSIGN);
- values = p.parseExpressionList();
- }
-
- return &ast.ValueSpec{doc, idents, typ, values};
-}
-
-
-func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl {
- if p.trace {
- defer un(trace(p, keyword.String() + "Decl"));
- }
-
- doc := p.getDoc();
- pos := p.expect(keyword);
- var lparen, rparen token.Position;
- list := vector.New(0);
- if p.tok == token.LPAREN {
- lparen = p.pos;
- p.next();
- for p.tok != token.RPAREN && p.tok != token.EOF {
- doc := p.getDoc();
- list.Push(f(p, doc));
- if p.tok == token.SEMICOLON {
- p.next();
- } else {
- break;
- }
- }
- rparen = p.expect(token.RPAREN);
- p.opt_semi = true;
- } else {
- list.Push(f(p, doc));
- }
-
- // convert vector
- specs := make([]ast.Spec, list.Len());
- for i := 0; i < list.Len(); i++ {
- specs[i] = list.At(i);
- }
- return &ast.GenDecl{doc, pos, keyword, lparen, specs, rparen};
-}
-
-
-func (p *parser) parseReceiver() *ast.Field {
- if p.trace {
- defer un(trace(p, "Receiver"));
- }
-
- pos := p.pos;
- par := p.parseParameters(false);
-
- // must have exactly one receiver
- if len(par) != 1 || len(par) == 1 && len(par[0].Names) > 1 {
- p.error_expected(pos, "exactly one receiver");
- return &ast.Field{nil, nil, &ast.BadExpr{noPos}, nil};
- }
-
- recv := par[0];
-
- // recv type must be TypeName or *TypeName
- base := recv.Type;
- if ptr, is_ptr := base.(*ast.StarExpr); is_ptr {
- base = ptr.X;
- }
- if !isTypeName(base) {
- p.error_expected(base.Pos(), "type name");
- }
-
- return recv;
-}
-
-
-func (p *parser) parseFunctionDecl() *ast.FuncDecl {
- if p.trace {
- defer un(trace(p, "FunctionDecl"));
- }
-
- doc := p.getDoc();
- pos := p.expect(token.FUNC);
-
- var recv *ast.Field;
- if p.tok == token.LPAREN {
- recv = p.parseReceiver();
- }
-
- ident := p.parseIdent();
- params, results := p.parseSignature();
-
- var body *ast.BlockStmt;
- if p.tok == token.LBRACE {
- body = p.parseBlockStmt();
- }
-
- return &ast.FuncDecl{doc, recv, ident, &ast.FuncType{pos, params, results}, body};
-}
-
-
-func (p *parser) parseDeclaration() ast.Decl {
- if p.trace {
- defer un(trace(p, "Declaration"));
- }
-
- var f parseSpecFunction;
- switch p.tok {
- case token.CONST: f = parseConstSpec;
- case token.TYPE: f = parseTypeSpec;
- case token.VAR: f = parseVarSpec;
- case token.FUNC:
- return p.parseFunctionDecl();
- default:
- pos := p.pos;
- p.error_expected(pos, "declaration");
- p.next(); // make progress
- return &ast.BadDecl{pos};
- }
-
- return p.parseGenDecl(p.tok, f);
-}
-
-
-// ----------------------------------------------------------------------------
-// Packages
-
-// The mode parameter to the Parse function is a set of flags (or 0).
-// They control the amount of source code parsed and other optional
-// parser functionality.
-//
-const (
- PackageClauseOnly uint = 1 << iota; // parsing stops after package clause
- ImportsOnly; // parsing stops after import declarations
- ParseComments; // parse comments and add them to AST
- Trace; // print a trace of parsed productions
-)
-
-
-func (p *parser) parsePackage() *ast.Program {
- if p.trace {
- defer un(trace(p, "Program"));
- }
-
- // package clause
- comment := p.getDoc();
- pos := p.expect(token.PACKAGE);
- ident := p.parseIdent();
- var decls []ast.Decl;
-
- // Don't bother parsing the rest if we had errors already.
- // Likely not a Go source file at all.
-
- if p.errors.Len() == 0 && p.mode & PackageClauseOnly == 0 {
- // import decls
- list := vector.New(0);
- for p.tok == token.IMPORT {
- list.Push(p.parseGenDecl(token.IMPORT, parseImportSpec));
- if p.tok == token.SEMICOLON {
- p.next();
- }
- }
-
- if p.mode & ImportsOnly == 0 {
- // rest of package body
- for p.tok != token.EOF {
- list.Push(p.parseDeclaration());
- if p.tok == token.SEMICOLON {
- p.next();
- }
- }
- }
-
- // convert declaration list
- decls = make([]ast.Decl, list.Len());
- for i := 0; i < list.Len(); i++ {
- decls[i] = list.At(i).(ast.Decl);
- }
- }
-
- // convert comments list
- comments := make([]*ast.Comment, p.comments.Len());
- for i := 0; i < p.comments.Len(); i++ {
- comments[i] = p.comments.At(i).(*ast.Comment);
- }
-
- return &ast.Program{comment, pos, ident, decls, comments};
-}
-
-
-// ----------------------------------------------------------------------------
-// Parsing of entire programs.
-
-func readSource(src interface{}) ([]byte, os.Error) {
- if src != nil {
- switch s := src.(type) {
- case string:
- return io.StringBytes(s), nil;
- case []byte:
- return s, nil;
- case *io.ByteBuffer:
- // is io.Read, but src is already available in []byte form
- if s != nil {
- return s.Data(), nil;
- }
- case io.Reader:
- var buf io.ByteBuffer;
- n, err := io.Copy(s, &buf);
- if err != nil {
- return nil, err;
- }
- return buf.Data(), nil;
- }
- }
- return nil, os.ErrorString("invalid source");
-}
-
-
-// scannerMode returns the scanner mode bits given the parser's mode bits.
-func scannerMode(mode uint) uint {
- if mode & ParseComments != 0 {
- return scanner.ScanComments;
- }
- return 0;
-}
-
-
-// Parse parses a Go program.
-//
-// The program source src may be provided in a variety of formats. At the
-// moment the following types are supported: string, []byte, and io.Read.
-// The mode parameter controls the amount of source text parsed and other
-// optional parser functionality.
-//
-// Parse returns a complete AST if no error occured. Otherwise, if the
-// source couldn't be read, the returned program is nil and the error
-// indicates the specific failure. If the source was read but syntax
-// errors were found, the result is a partial AST (with ast.BadX nodes
-// representing the fragments of erroneous source code) and an ErrorList
-// describing the syntax errors.
-//
-func Parse(src interface{}, mode uint) (*ast.Program, os.Error) {
- data, err := readSource(src);
- if err != nil {
- return nil, err;
- }
-
- // initialize parser state
- var p parser;
- p.errors.Init(0);
- p.scanner.Init(data, &p, scannerMode(mode));
- p.mode = mode;
- p.trace = mode & Trace != 0; // for convenience (p.trace is used frequently)
- p.comments.Init(0);
- p.next();
-
- // parse program
- prog := p.parsePackage();
-
- // convert errors list, if any
- if p.errors.Len() > 0 {
- errors := make(ErrorList, p.errors.Len());
- for i := 0; i < p.errors.Len(); i++ {
- errors[i] = p.errors.At(i).(*Error);
- }
- return prog, errors;
- }
-
- return prog, nil;
-}
diff --git a/src/lib/go/parser/parser_test.go b/src/lib/go/parser/parser_test.go
deleted file mode 100644
index 887fcf80f..000000000
--- a/src/lib/go/parser/parser_test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package parser
-
-import (
- "go/ast";
- "go/parser";
- "os";
- "testing";
-)
-
-
-var illegalInputs = []interface{} {
- nil,
- 3.14,
- []byte(nil),
- "foo!",
-}
-
-
-func TestParseIllegalInputs(t *testing.T) {
- for _, src := range illegalInputs {
- prog, err := Parse(src, 0);
- if err == nil {
- t.Errorf("Parse(%v) should have failed", src);
- }
- }
-}
-
-
-var validPrograms = []interface{} {
- `package main`,
- `package main import "fmt" func main() { fmt.Println("Hello, World!") }`,
-}
-
-
-func TestParseValidPrograms(t *testing.T) {
- for _, src := range validPrograms {
- prog, err := Parse(src, 0);
- if err != nil {
- t.Errorf("Parse(%q) failed: %v", src, err);
- }
- }
-}
-
-
-var validFiles = []string {
- "parser.go",
- "parser_test.go",
-}
-
-
-func TestParse3(t *testing.T) {
- for _, filename := range validFiles {
- src, err := os.Open(filename, os.O_RDONLY, 0);
- defer src.Close();
- if err != nil {
- t.Fatalf("os.Open(%s): %v\n", filename, err);
- }
-
- prog, err := Parse(src, 0);
- if err != nil {
- t.Errorf("Parse(%q): %v", src, err);
- }
- }
-}
diff --git a/src/lib/go/scanner/Makefile b/src/lib/go/scanner/Makefile
deleted file mode 100644
index d47fecb7c..000000000
--- a/src/lib/go/scanner/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# DO NOT EDIT. Automatically generated by gobuild.
-# gobuild -m >Makefile
-
-D=/go/
-
-include $(GOROOT)/src/Make.$(GOARCH)
-AR=gopack
-
-default: packages
-
-clean:
- rm -rf *.[$(OS)] *.a [$(OS)].out _obj
-
-test: packages
- gotest
-
-coverage: packages
- gotest
- 6cov -g `pwd` | grep -v '_test\.go:'
-
-%.$O: %.go
- $(GC) -I_obj $*.go
-
-%.$O: %.c
- $(CC) $*.c
-
-%.$O: %.s
- $(AS) $*.s
-
-O1=\
- scanner.$O\
-
-
-phases: a1
-_obj$D/scanner.a: phases
-
-a1: $(O1)
- $(AR) grc _obj$D/scanner.a scanner.$O
- rm -f $(O1)
-
-
-newpkg: clean
- mkdir -p _obj$D
- $(AR) grc _obj$D/scanner.a
-
-$(O1): newpkg
-$(O2): a1
-
-nuke: clean
- rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/scanner.a
-
-packages: _obj$D/scanner.a
-
-install: packages
- test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D
- cp _obj$D/scanner.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/scanner.a
diff --git a/src/lib/go/scanner/scanner.go b/src/lib/go/scanner/scanner.go
deleted file mode 100644
index a90e6f259..000000000
--- a/src/lib/go/scanner/scanner.go
+++ /dev/null
@@ -1,501 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// A scanner for Go source text. Takes a []byte as source which can
-// then be tokenized through repeated calls to the Scan function.
-// For a sample use of a scanner, see the implementation of Tokenize.
-//
-package scanner
-
-import (
- "go/token";
- "strconv";
- "unicode";
- "utf8";
-)
-
-
-// An implementation of an ErrorHandler may be provided to the Scanner.
-// If a syntax error is encountered and a handler was installed, Error
-// is called with a position and an error message. The position points
-// to the beginning of the offending token.
-//
-type ErrorHandler interface {
- Error(pos token.Position, msg string);
-}
-
-
-// A Scanner holds the scanner's internal state while processing
-// a given text. It can be allocated as part of another data
-// structure but must be initialized via Init before use. For
-// a sample use, see the implementation of Tokenize.
-//
-type Scanner struct {
- // immutable state
- src []byte; // source
- err ErrorHandler; // error reporting; or nil
- mode uint; // scanning mode
-
- // scanning state
- pos token.Position; // previous reading position (position before ch)
- offset int; // current reading offset (position after ch)
- ch int; // one char look-ahead
-
- // public state - ok to modify
- ErrorCount int; // number of errors encountered
-}
-
-
-// Read the next Unicode char into S.ch.
-// S.ch < 0 means end-of-file.
-//
-func (S *Scanner) next() {
- if S.offset < len(S.src) {
- S.pos.Offset = S.offset;
- S.pos.Column++;
- r, w := int(S.src[S.offset]), 1;
- switch {
- case r == '\n':
- S.pos.Line++;
- S.pos.Column = 0;
- case r >= 0x80:
- // not ASCII
- r, w = utf8.DecodeRune(S.src[S.offset : len(S.src)]);
- }
- S.offset += w;
- S.ch = r;
- } else {
- S.pos.Offset = len(S.src);
- S.ch = -1; // eof
- }
-}
-
-
-// The mode parameter to the Init function is a set of flags (or 0).
-// They control scanner behavior.
-//
-const (
- ScanComments = 1 << iota; // return comments as COMMENT tokens
- AllowIllegalChars; // do not report an error for illegal chars
-)
-
-
-// Init prepares the scanner S to tokenize the text src. Calls to Scan
-// will use the error handler err if they encounter a syntax error and
-// err is not nil. Also, for each error encountered, the Scanner field
-// ErrorCount is incremented by one. The mode parameter determines how
-// comments and illegal characters are handled.
-//
-func (S *Scanner) Init(src []byte, err ErrorHandler, mode uint) {
- // Explicitly initialize all fields since a scanner may be reused.
- S.src = src;
- S.err = err;
- S.mode = mode;
- S.pos = token.Position{0, 1, 0};
- S.offset = 0;
- S.ErrorCount = 0;
- S.next();
-}
-
-
-func charString(ch int) string {
- var s string;
- switch ch {
- case '\a': s = `\a`;
- case '\b': s = `\b`;
- case '\f': s = `\f`;
- case '\n': s = `\n`;
- case '\r': s = `\r`;
- case '\t': s = `\t`;
- case '\v': s = `\v`;
- case '\\': s = `\\`;
- case '\'': s = `\'`;
- default : s = string(ch);
- }
- return "'" + s + "' (U+" + strconv.Itob(ch, 16) + ")";
-}
-
-
-func (S *Scanner) error(pos token.Position, msg string) {
- if S.err != nil {
- S.err.Error(pos, msg);
- }
- S.ErrorCount++;
-}
-
-
-func (S *Scanner) expect(ch int) {
- if S.ch != ch {
- S.error(S.pos, "expected " + charString(ch) + ", found " + charString(S.ch));
- }
- S.next(); // always make progress
-}
-
-
-func (S *Scanner) scanComment(pos token.Position) {
- // first '/' already consumed
-
- if S.ch == '/' {
- //-style comment
- for S.ch >= 0 {
- S.next();
- if S.ch == '\n' {
- S.next(); // '\n' belongs to the comment
- return;
- }
- }
-
- } else {
- /*-style comment */
- S.expect('*');
- for S.ch >= 0 {
- ch := S.ch;
- S.next();
- if ch == '*' && S.ch == '/' {
- S.next();
- return;
- }
- }
- }
-
- S.error(pos, "comment not terminated");
-}
-
-
-func isLetter(ch int) bool {
- return
- 'a' <= ch && ch <= 'z' ||
- 'A' <= ch && ch <= 'Z' ||
- ch == '_' ||
- ch >= 0x80 && unicode.IsLetter(ch);
-}
-
-
-func isDigit(ch int) bool {
- return
- '0' <= ch && ch <= '9' ||
- ch >= 0x80 && unicode.IsDecimalDigit(ch);
-}
-
-
-func (S *Scanner) scanIdentifier() token.Token {
- pos := S.pos.Offset;
- for isLetter(S.ch) || isDigit(S.ch) {
- S.next();
- }
- return token.Lookup(S.src[pos : S.pos.Offset]);
-}
-
-
-func digitVal(ch int) int {
- switch {
- case '0' <= ch && ch <= '9': return ch - '0';
- case 'a' <= ch && ch <= 'f': return ch - 'a' + 10;
- case 'A' <= ch && ch <= 'F': return ch - 'A' + 10;
- }
- return 16; // larger than any legal digit val
-}
-
-
-func (S *Scanner) scanMantissa(base int) {
- for digitVal(S.ch) < base {
- S.next();
- }
-}
-
-
-func (S *Scanner) scanNumber(seen_decimal_point bool) token.Token {
- tok := token.INT;
-
- if seen_decimal_point {
- tok = token.FLOAT;
- S.scanMantissa(10);
- goto exponent;
- }
-
- if S.ch == '0' {
- // int or float
- S.next();
- if S.ch == 'x' || S.ch == 'X' {
- // hexadecimal int
- S.next();
- S.scanMantissa(16);
- } else {
- // octal int or float
- S.scanMantissa(8);
- if digitVal(S.ch) < 10 || S.ch == '.' || S.ch == 'e' || S.ch == 'E' {
- // float
- tok = token.FLOAT;
- goto mantissa;
- }
- // octal int
- }
- goto exit;
- }
-
-mantissa:
- // decimal int or float
- S.scanMantissa(10);
-
- if S.ch == '.' {
- // float
- tok = token.FLOAT;
- S.next();
- S.scanMantissa(10)
- }
-
-exponent:
- if S.ch == 'e' || S.ch == 'E' {
- // float
- tok = token.FLOAT;
- S.next();
- if S.ch == '-' || S.ch == '+' {
- S.next();
- }
- S.scanMantissa(10);
- }
-
-exit:
- return tok;
-}
-
-
-func (S *Scanner) scanDigits(base, length int) {
- for length > 0 && digitVal(S.ch) < base {
- S.next();
- length--;
- }
- if length > 0 {
- S.error(S.pos, "illegal char escape");
- }
-}
-
-
-func (S *Scanner) scanEscape(quote int) {
- pos := S.pos;
- ch := S.ch;
- S.next();
- switch ch {
- case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
- // nothing to do
- case '0', '1', '2', '3', '4', '5', '6', '7':
- S.scanDigits(8, 3 - 1); // 1 char read already
- case 'x':
- S.scanDigits(16, 2);
- case 'u':
- S.scanDigits(16, 4);
- case 'U':
- S.scanDigits(16, 8);
- default:
- S.error(pos, "illegal char escape");
- }
-}
-
-
-func (S *Scanner) scanChar() {
- // '\'' already consumed
-
- ch := S.ch;
- S.next();
- if ch == '\\' {
- S.scanEscape('\'');
- }
-
- S.expect('\'');
-}
-
-
-func (S *Scanner) scanString(pos token.Position) {
- // '"' already consumed
-
- for S.ch != '"' {
- ch := S.ch;
- S.next();
- if ch == '\n' || ch < 0 {
- S.error(pos, "string not terminated");
- break;
- }
- if ch == '\\' {
- S.scanEscape('"');
- }
- }
-
- S.next();
-}
-
-
-func (S *Scanner) scanRawString(pos token.Position) {
- // '`' already consumed
-
- for S.ch != '`' {
- ch := S.ch;
- S.next();
- if ch == '\n' || ch < 0 {
- S.error(pos, "string not terminated");
- break;
- }
- }
-
- S.next();
-}
-
-
-// Helper functions for scanning multi-byte tokens such as >> += >>= .
-// Different routines recognize different length tok_i based on matches
-// of ch_i. If a token ends in '=', the result is tok1 or tok3
-// respectively. Otherwise, the result is tok0 if there was no other
-// matching character, or tok2 if the matching character was ch2.
-
-func (S *Scanner) switch2(tok0, tok1 token.Token) token.Token {
- if S.ch == '=' {
- S.next();
- return tok1;
- }
- return tok0;
-}
-
-
-func (S *Scanner) switch3(tok0, tok1 token.Token, ch2 int, tok2 token.Token) token.Token {
- if S.ch == '=' {
- S.next();
- return tok1;
- }
- if S.ch == ch2 {
- S.next();
- return tok2;
- }
- return tok0;
-}
-
-
-func (S *Scanner) switch4(tok0, tok1 token.Token, ch2 int, tok2, tok3 token.Token) token.Token {
- if S.ch == '=' {
- S.next();
- return tok1;
- }
- if S.ch == ch2 {
- S.next();
- if S.ch == '=' {
- S.next();
- return tok3;
- }
- return tok2;
- }
- return tok0;
-}
-
-
-// Scan scans the next token and returns the token position pos,
-// the token tok, and the literal text lit corresponding to the
-// token. The source end is indicated by token.EOF.
-//
-// For more tolerant parsing, Scan will return a valid token if
-// possible even if a syntax error was encountered. Thus, even
-// if the resulting token sequence contains no illegal tokens,
-// a client may not assume that no error occurred. Instead it
-// must check the scanner's ErrorCount or the number of calls
-// of the error handler, if there was one installed.
-//
-func (S *Scanner) Scan() (pos token.Position, tok token.Token, lit []byte) {
-scan_again:
- // skip white space
- for S.ch == ' ' || S.ch == '\t' || S.ch == '\n' || S.ch == '\r' {
- S.next();
- }
-
- // current token start
- pos, tok = S.pos, token.ILLEGAL;
-
- // determine token value
- switch ch := S.ch; {
- case isLetter(ch):
- tok = S.scanIdentifier();
- case digitVal(ch) < 10:
- tok = S.scanNumber(false);
- default:
- S.next(); // always make progress
- switch ch {
- case -1 : tok = token.EOF;
- case '"' : tok = token.STRING; S.scanString(pos);
- case '\'': tok = token.CHAR; S.scanChar();
- case '`' : tok = token.STRING; S.scanRawString(pos);
- case ':' : tok = S.switch2(token.COLON, token.DEFINE);
- case '.' :
- if digitVal(S.ch) < 10 {
- tok = S.scanNumber(true);
- } else if S.ch == '.' {
- S.next();
- if S.ch == '.' {
- S.next();
- tok = token.ELLIPSIS;
- }
- } else {
- tok = token.PERIOD;
- }
- case ',': tok = token.COMMA;
- case ';': tok = token.SEMICOLON;
- case '(': tok = token.LPAREN;
- case ')': tok = token.RPAREN;
- case '[': tok = token.LBRACK;
- case ']': tok = token.RBRACK;
- case '{': tok = token.LBRACE;
- case '}': tok = token.RBRACE;
- case '+': tok = S.switch3(token.ADD, token.ADD_ASSIGN, '+', token.INC);
- case '-': tok = S.switch3(token.SUB, token.SUB_ASSIGN, '-', token.DEC);
- case '*': tok = S.switch2(token.MUL, token.MUL_ASSIGN);
- case '/':
- if S.ch == '/' || S.ch == '*' {
- S.scanComment(pos);
- tok = token.COMMENT;
- if S.mode & ScanComments == 0 {
- goto scan_again;
- }
- } else {
- tok = S.switch2(token.QUO, token.QUO_ASSIGN);
- }
- case '%': tok = S.switch2(token.REM, token.REM_ASSIGN);
- case '^': tok = S.switch2(token.XOR, token.XOR_ASSIGN);
- case '<':
- if S.ch == '-' {
- S.next();
- tok = token.ARROW;
- } else {
- tok = S.switch4(token.LSS, token.LEQ, '<', token.SHL, token.SHL_ASSIGN);
- }
- case '>': tok = S.switch4(token.GTR, token.GEQ, '>', token.SHR, token.SHR_ASSIGN);
- case '=': tok = S.switch2(token.ASSIGN, token.EQL);
- case '!': tok = S.switch2(token.NOT, token.NEQ);
- case '&':
- if S.ch == '^' {
- S.next();
- tok = S.switch2(token.AND_NOT, token.AND_NOT_ASSIGN);
- } else {
- tok = S.switch3(token.AND, token.AND_ASSIGN, '&', token.LAND);
- }
- case '|': tok = S.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR);
- default:
- if S.mode & AllowIllegalChars == 0 {
- S.error(pos, "illegal character " + charString(ch));
- }
- }
- }
-
- return pos, tok, S.src[pos.Offset : S.pos.Offset];
-}
-
-
-// Tokenize calls a function f with the token position, token value, and token
-// text for each token in the source src. The other parameters have the same
-// meaning as for the Init function. Tokenize keeps scanning until f returns
-// false (usually when the token value is token.EOF). The result is the number
-// of errors encountered.
-//
-func Tokenize(src []byte, err ErrorHandler, mode uint, f func (pos token.Position, tok token.Token, lit []byte) bool) int {
- var s Scanner;
- s.Init(src, err, mode);
- for f(s.Scan()) {
- // action happens in f
- }
- return s.ErrorCount;
-}
diff --git a/src/lib/go/scanner/scanner_test.go b/src/lib/go/scanner/scanner_test.go
deleted file mode 100644
index 0defece8b..000000000
--- a/src/lib/go/scanner/scanner_test.go
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package scanner
-
-import (
- "go/scanner";
- "go/token";
- "io";
- "testing";
-)
-
-
-const /* class */ (
- special = iota;
- literal;
- operator;
- keyword;
-)
-
-
-func tokenclass(tok token.Token) int {
- switch {
- case tok.IsLiteral(): return literal;
- case tok.IsOperator(): return operator;
- case tok.IsKeyword(): return keyword;
- }
- return special;
-}
-
-
-type elt struct {
- tok token.Token;
- lit string;
- class int;
-}
-
-
-var tokens = [...]elt{
- // Special tokens
- elt{ token.COMMENT, "/* a comment */", special },
- elt{ token.COMMENT, "// a comment \n", special },
-
- // Identifiers and basic type literals
- elt{ token.IDENT, "foobar", literal },
- elt{ token.IDENT, "a۰۱۸", literal },
- elt{ token.IDENT, "foo६४", literal },
- elt{ token.IDENT, "bar9876", literal },
- elt{ token.INT, "0", literal },
- elt{ token.INT, "01234567", literal },
- elt{ token.INT, "0xcafebabe", literal },
- elt{ token.FLOAT, "0.", literal },
- elt{ token.FLOAT, ".0", literal },
- elt{ token.FLOAT, "3.14159265", literal },
- elt{ token.FLOAT, "1e0", literal },
- elt{ token.FLOAT, "1e+100", literal },
- elt{ token.FLOAT, "1e-100", literal },
- elt{ token.FLOAT, "2.71828e-1000", literal },
- elt{ token.CHAR, "'a'", literal },
- elt{ token.CHAR, "'\\000'", literal },
- elt{ token.CHAR, "'\\xFF'", literal },
- elt{ token.CHAR, "'\\uff16'", literal },
- elt{ token.CHAR, "'\\U0000ff16'", literal },
- elt{ token.STRING, "`foobar`", literal },
-
- // Operators and delimitors
- elt{ token.ADD, "+", operator },
- elt{ token.SUB, "-", operator },
- elt{ token.MUL, "*", operator },
- elt{ token.QUO, "/", operator },
- elt{ token.REM, "%", operator },
-
- elt{ token.AND, "&", operator },
- elt{ token.OR, "|", operator },
- elt{ token.XOR, "^", operator },
- elt{ token.SHL, "<<", operator },
- elt{ token.SHR, ">>", operator },
- elt{ token.AND_NOT, "&^", operator },
-
- elt{ token.ADD_ASSIGN, "+=", operator },
- elt{ token.SUB_ASSIGN, "-=", operator },
- elt{ token.MUL_ASSIGN, "*=", operator },
- elt{ token.QUO_ASSIGN, "/=", operator },
- elt{ token.REM_ASSIGN, "%=", operator },
-
- elt{ token.AND_ASSIGN, "&=", operator },
- elt{ token.OR_ASSIGN, "|=", operator },
- elt{ token.XOR_ASSIGN, "^=", operator },
- elt{ token.SHL_ASSIGN, "<<=", operator },
- elt{ token.SHR_ASSIGN, ">>=", operator },
- elt{ token.AND_NOT_ASSIGN, "&^=", operator },
-
- elt{ token.LAND, "&&", operator },
- elt{ token.LOR, "||", operator },
- elt{ token.ARROW, "<-", operator },
- elt{ token.INC, "++", operator },
- elt{ token.DEC, "--", operator },
-
- elt{ token.EQL, "==", operator },
- elt{ token.LSS, "<", operator },
- elt{ token.GTR, ">", operator },
- elt{ token.ASSIGN, "=", operator },
- elt{ token.NOT, "!", operator },
-
- elt{ token.NEQ, "!=", operator },
- elt{ token.LEQ, "<=", operator },
- elt{ token.GEQ, ">=", operator },
- elt{ token.DEFINE, ":=", operator },
- elt{ token.ELLIPSIS, "...", operator },
-
- elt{ token.LPAREN, "(", operator },
- elt{ token.LBRACK, "[", operator },
- elt{ token.LBRACE, "{", operator },
- elt{ token.COMMA, ",", operator },
- elt{ token.PERIOD, ".", operator },
-
- elt{ token.RPAREN, ")", operator },
- elt{ token.RBRACK, "]", operator },
- elt{ token.RBRACE, "}", operator },
- elt{ token.SEMICOLON, ";", operator },
- elt{ token.COLON, ":", operator },
-
- // Keywords
- elt{ token.BREAK, "break", keyword },
- elt{ token.CASE, "case", keyword },
- elt{ token.CHAN, "chan", keyword },
- elt{ token.CONST, "const", keyword },
- elt{ token.CONTINUE, "continue", keyword },
-
- elt{ token.DEFAULT, "default", keyword },
- elt{ token.DEFER, "defer", keyword },
- elt{ token.ELSE, "else", keyword },
- elt{ token.FALLTHROUGH, "fallthrough", keyword },
- elt{ token.FOR, "for", keyword },
-
- elt{ token.FUNC, "func", keyword },
- elt{ token.GO, "go", keyword },
- elt{ token.GOTO, "goto", keyword },
- elt{ token.IF, "if", keyword },
- elt{ token.IMPORT, "import", keyword },
-
- elt{ token.INTERFACE, "interface", keyword },
- elt{ token.MAP, "map", keyword },
- elt{ token.PACKAGE, "package", keyword },
- elt{ token.RANGE, "range", keyword },
- elt{ token.RETURN, "return", keyword },
-
- elt{ token.SELECT, "select", keyword },
- elt{ token.STRUCT, "struct", keyword },
- elt{ token.SWITCH, "switch", keyword },
- elt{ token.TYPE, "type", keyword },
- elt{ token.VAR, "var", keyword },
-}
-
-
-const whitespace = " \t \n\n\n"; // to separate tokens
-
-type TestErrorHandler struct {
- t *testing.T
-}
-
-func (h *TestErrorHandler) Error(pos token.Position, msg string) {
- h.t.Errorf("Error() called (msg = %s)", msg);
-}
-
-
-func NewlineCount(s string) int {
- n := 0;
- for i := 0; i < len(s); i++ {
- if s[i] == '\n' {
- n++;
- }
- }
- return n;
-}
-
-
-// Verify that calling Scan() provides the correct results.
-func TestScan(t *testing.T) {
- // make source
- var src string;
- for i, e := range tokens {
- src += e.lit + whitespace;
- }
- whitespace_linecount := NewlineCount(whitespace);
-
- // verify scan
- index := 0;
- eloc := token.Position{0, 1, 1};
- nerrors := scanner.Tokenize(io.StringBytes(src), &TestErrorHandler{t}, scanner.ScanComments,
- func (pos token.Position, tok token.Token, litb []byte) bool {
- e := elt{token.EOF, "", special};
- if index < len(tokens) {
- e = tokens[index];
- }
- lit := string(litb);
- if tok == token.EOF {
- lit = "<EOF>";
- eloc.Column = 0;
- }
- if pos.Offset != eloc.Offset {
- t.Errorf("bad position for %s: got %d, expected %d", lit, pos.Offset, eloc.Offset);
- }
- if pos.Line != eloc.Line {
- t.Errorf("bad line for %s: got %d, expected %d", lit, pos.Line, eloc.Line);
- }
- if pos.Column!= eloc.Column {
- t.Errorf("bad column for %s: got %d, expected %d", lit, pos.Column, eloc.Column);
- }
- if tok != e.tok {
- t.Errorf("bad token for %s: got %s, expected %s", lit, tok.String(), e.tok.String());
- }
- if e.tok.IsLiteral() && lit != e.lit {
- t.Errorf("bad literal for %s: got %s, expected %s", lit, lit, e.lit);
- }
- if tokenclass(tok) != e.class {
- t.Errorf("bad class for %s: got %d, expected %d", lit, tokenclass(tok), e.class);
- }
- eloc.Offset += len(lit) + len(whitespace);
- eloc.Line += NewlineCount(lit) + whitespace_linecount;
- index++;
- return tok != token.EOF;
- }
- );
- if nerrors != 0 {
- t.Errorf("found %d errors", nerrors);
- }
-}
-
-
-// Verify that initializing the same scanner more then once works correctly.
-func TestInit(t *testing.T) {
- var s scanner.Scanner;
-
- // 1st init
- s.Init(io.StringBytes("if true { }"), nil, 0);
- s.Scan(); // if
- s.Scan(); // true
- pos, tok, lit := s.Scan(); // {
- if tok != token.LBRACE {
- t.Errorf("bad token: got %s, expected %s", tok.String(), token.LBRACE);
- }
-
- // 2nd init
- s.Init(io.StringBytes("go true { ]"), nil, 0);
- pos, tok, lit = s.Scan(); // go
- if tok != token.GO {
- t.Errorf("bad token: got %s, expected %s", tok.String(), token.GO);
- }
-
- if s.ErrorCount != 0 {
- t.Errorf("found %d errors", s.ErrorCount);
- }
-}
-
-
-func TestIllegalChars(t *testing.T) {
- var s scanner.Scanner;
-
- const src = "*?*$*@*";
- s.Init(io.StringBytes(src), &TestErrorHandler{t}, scanner.AllowIllegalChars);
- for offs, ch := range src {
- pos, tok, lit := s.Scan();
- if pos.Offset != offs {
- t.Errorf("bad position for %s: got %d, expected %d", string(lit), pos.Offset, offs);
- }
- if tok == token.ILLEGAL && string(lit) != string(ch) {
- t.Errorf("bad token: got %s, expected %s", string(lit), string(ch));
- }
- }
-
- if s.ErrorCount != 0 {
- t.Errorf("found %d errors", s.ErrorCount);
- }
-}
diff --git a/src/lib/go/token/Makefile b/src/lib/go/token/Makefile
deleted file mode 100644
index 12ef2a4aa..000000000
--- a/src/lib/go/token/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# DO NOT EDIT. Automatically generated by gobuild.
-# gobuild -m >Makefile
-
-D=/go/
-
-include $(GOROOT)/src/Make.$(GOARCH)
-AR=gopack
-
-default: packages
-
-clean:
- rm -rf *.[$(OS)] *.a [$(OS)].out _obj
-
-test: packages
- gotest
-
-coverage: packages
- gotest
- 6cov -g `pwd` | grep -v '_test\.go:'
-
-%.$O: %.go
- $(GC) -I_obj $*.go
-
-%.$O: %.c
- $(CC) $*.c
-
-%.$O: %.s
- $(AS) $*.s
-
-O1=\
- token.$O\
-
-
-phases: a1
-_obj$D/token.a: phases
-
-a1: $(O1)
- $(AR) grc _obj$D/token.a token.$O
- rm -f $(O1)
-
-
-newpkg: clean
- mkdir -p _obj$D
- $(AR) grc _obj$D/token.a
-
-$(O1): newpkg
-$(O2): a1
-
-nuke: clean
- rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/token.a
-
-packages: _obj$D/token.a
-
-install: packages
- test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D
- cp _obj$D/token.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/token.a
diff --git a/src/lib/go/token/token.go b/src/lib/go/token/token.go
deleted file mode 100644
index a70a75a54..000000000
--- a/src/lib/go/token/token.go
+++ /dev/null
@@ -1,347 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This package defines constants representing the lexical
-// tokens of the Go programming language and basic operations
-// on tokens (printing, predicates).
-//
-package token
-
-import "strconv"
-
-// Token is the set of lexical tokens of the Go programming language.
-type Token int
-
-// The list of tokens.
-const (
- // Special tokens
- ILLEGAL Token = iota;
- EOF;
- COMMENT;
-
- // Identifiers and basic type literals
- // (these tokens stand for classes of literals)
- literal_beg;
- IDENT;
- INT;
- FLOAT;
- CHAR;
- STRING;
- literal_end;
-
- // Operators and delimiters
- operator_beg;
- ADD;
- SUB;
- MUL;
- QUO;
- REM;
-
- AND;
- OR;
- XOR;
- SHL;
- SHR;
- AND_NOT;
-
- ADD_ASSIGN;
- SUB_ASSIGN;
- MUL_ASSIGN;
- QUO_ASSIGN;
- REM_ASSIGN;
-
- AND_ASSIGN;
- OR_ASSIGN;
- XOR_ASSIGN;
- SHL_ASSIGN;
- SHR_ASSIGN;
- AND_NOT_ASSIGN;
-
- LAND;
- LOR;
- ARROW;
- INC;
- DEC;
-
- EQL;
- LSS;
- GTR;
- ASSIGN;
- NOT;
-
- NEQ;
- LEQ;
- GEQ;
- DEFINE;
- ELLIPSIS;
-
- LPAREN;
- LBRACK;
- LBRACE;
- COMMA;
- PERIOD;
-
- RPAREN;
- RBRACK;
- RBRACE;
- SEMICOLON;
- COLON;
- operator_end;
-
- // Keywords
- keyword_beg;
- BREAK;
- CASE;
- CHAN;
- CONST;
- CONTINUE;
-
- DEFAULT;
- DEFER;
- ELSE;
- FALLTHROUGH;
- FOR;
-
- FUNC;
- GO;
- GOTO;
- IF;
- IMPORT;
-
- INTERFACE;
- MAP;
- PACKAGE;
- RANGE;
- RETURN;
-
- SELECT;
- STRUCT;
- SWITCH;
- TYPE;
- VAR;
- keyword_end;
-)
-
-
-// At the moment we have no array literal syntax that lets us describe
-// the index for each element - use a map for now to make sure they are
-// in sync.
-var tokens = map [Token] string {
- ILLEGAL : "ILLEGAL",
-
- EOF : "EOF",
- COMMENT : "COMMENT",
-
- IDENT : "IDENT",
- INT : "INT",
- FLOAT : "FLOAT",
- CHAR : "CHAR",
- STRING : "STRING",
-
- ADD : "+",
- SUB : "-",
- MUL : "*",
- QUO : "/",
- REM : "%",
-
- AND : "&",
- OR : "|",
- XOR : "^",
- SHL : "<<",
- SHR : ">>",
- AND_NOT : "&^",
-
- ADD_ASSIGN : "+=",
- SUB_ASSIGN : "-=",
- MUL_ASSIGN : "+=",
- QUO_ASSIGN : "/=",
- REM_ASSIGN : "%=",
-
- AND_ASSIGN : "&=",
- OR_ASSIGN : "|=",
- XOR_ASSIGN : "^=",
- SHL_ASSIGN : "<<=",
- SHR_ASSIGN : ">>=",
- AND_NOT_ASSIGN : "&^=",
-
- LAND : "&&",
- LOR : "||",
- ARROW : "<-",
- INC : "++",
- DEC : "--",
-
- EQL : "==",
- LSS : "<",
- GTR : ">",
- ASSIGN : "=",
- NOT : "!",
-
- NEQ : "!=",
- LEQ : "<=",
- GEQ : ">=",
- DEFINE : ":=",
- ELLIPSIS : "...",
-
- LPAREN : "(",
- LBRACK : "[",
- LBRACE : "{",
- COMMA : ",",
- PERIOD : ".",
-
- RPAREN : ")",
- RBRACK : "]",
- RBRACE : "}",
- SEMICOLON : ";",
- COLON : ":",
-
- BREAK : "break",
- CASE : "case",
- CHAN : "chan",
- CONST : "const",
- CONTINUE : "continue",
-
- DEFAULT : "default",
- DEFER : "defer",
- ELSE : "else",
- FALLTHROUGH : "fallthrough",
- FOR : "for",
-
- FUNC : "func",
- GO : "go",
- GOTO : "goto",
- IF : "if",
- IMPORT : "import",
-
- INTERFACE : "interface",
- MAP : "map",
- PACKAGE : "package",
- RANGE : "range",
- RETURN : "return",
-
- SELECT : "select",
- STRUCT : "struct",
- SWITCH : "switch",
- TYPE : "type",
- VAR : "var",
-}
-
-
-// String returns the string corresponding to the token tok.
-// For operators, delimiters, and keywords the string is the actual
-// token character sequence (e.g., for the token ADD, the string is
-// "+"). For all other tokens the string corresponds to the token
-// constant name (e.g. for the token IDENT, the string is "IDENT").
-//
-func (tok Token) String() string {
- if str, exists := tokens[tok]; exists {
- return str;
- }
- return "token(" + strconv.Itoa(int(tok)) + ")";
-}
-
-
-// A set of constants for precedence-based expression parsing.
-// Non-operators have lowest precedence, followed by operators
-// starting with precedence 1 up to unary operators. The highest
-// precedence corresponds serves as "catch-all" precedence for
-// selector, indexing, and other operator and delimiter tokens.
-//
-const (
- LowestPrec = 0; // non-operators
- UnaryPrec = 7;
- HighestPrec = 8;
-)
-
-
-// Precedence returns the operator precedence of the binary
-// operator op. If op is not a binary operator, the result
-// is LowestPrecedence.
-//
-func (op Token) Precedence() int {
- switch op {
- case LOR:
- return 1;
- case LAND:
- return 2;
- case ARROW:
- return 3;
- case EQL, NEQ, LSS, LEQ, GTR, GEQ:
- return 4;
- case ADD, SUB, OR, XOR:
- return 5;
- case MUL, QUO, REM, SHL, SHR, AND, AND_NOT:
- return 6;
- }
- return LowestPrec;
-}
-
-
-var keywords map [string] Token;
-
-func init() {
- keywords = make(map [string] Token);
- for i := keyword_beg + 1; i < keyword_end; i++ {
- keywords[tokens[i]] = i;
- }
-}
-
-
-// Lookup maps an identifier to its keyword token or IDENT (if not a keyword).
-//
-func Lookup(ident []byte) Token {
- // TODO Maps with []byte key are illegal because []byte does not
- // support == . Should find a more efficient solution eventually.
- if tok, is_keyword := keywords[string(ident)]; is_keyword {
- return tok;
- }
- return IDENT;
-}
-
-
-// Predicates
-
-// IsLiteral returns true for tokens corresponding to identifiers
-// and basic type literals; returns false otherwise.
-//
-func (tok Token) IsLiteral() bool {
- return literal_beg < tok && tok < literal_end;
-}
-
-// IsOperator returns true for tokens corresponding to operators and
-// delimiters; returns false otherwise.
-//
-func (tok Token) IsOperator() bool {
- return operator_beg < tok && tok < operator_end;
-}
-
-// IsKeyword returns true for tokens corresponding to keywords;
-// returns false otherwise.
-//
-func (tok Token) IsKeyword() bool {
- return keyword_beg < tok && tok < keyword_end;
-}
-
-
-// Token source positions are represented by a Position value.
-// A Position is valid if the line number is > 0.
-//
-type Position struct {
- Offset int; // byte offset, starting at 0
- Line int; // line number, starting at 1
- Column int; // column number, starting at 1 (character count)
-}
-
-
-// Pos is an accessor method for anonymous Position fields.
-// It returns its receiver.
-//
-func (pos *Position) Pos() Position {
- return *pos;
-}
-
-
-// IsValid returns true if the position is valid.
-func (pos *Position) IsValid() bool {
- return pos.Line > 0
-}