github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/compiler/ast/ast.go (about)

     1  // Original: src/go/ast/ast.go
     2  //
     3  // Copyright 2009 The Go Authors. All rights reserved.
     4  // Portions Copyright 2016 Hiroshi Ioka. All rights reserved.
     5  //
     6  // Redistribution and use in source and binary forms, with or without
     7  // modification, are permitted provided that the following conditions are
     8  // met:
     9  //
    10  //    * Redistributions of source code must retain the above copyright
    11  // notice, this list of conditions and the following disclaimer.
    12  //    * Redistributions in binary form must reproduce the above
    13  // copyright notice, this list of conditions and the following disclaimer
    14  // in the documentation and/or other materials provided with the
    15  // distribution.
    16  //    * Neither the name of Google Inc. nor the names of its
    17  // contributors may be used to endorse or promote products derived from
    18  // this software without specific prior written permission.
    19  //
    20  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    24  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    25  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    26  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    27  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    28  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    29  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    30  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  
    32  package ast
    33  
    34  import (
    35  	"strings"
    36  
    37  	"github.com/hirochachacha/plua/compiler/token"
    38  	"github.com/hirochachacha/plua/position"
    39  )
    40  
    41  // ----------------------------------------------------------------------------
    42  // Interfaces
    43  //
    44  
    45  // All node types implement the Node interface.
    46  type Node interface {
    47  	Type() Type
    48  	Pos() position.Position // position of first character belonging to the node
    49  	End() position.Position // position of first character immediately after the node
    50  }
    51  
    52  // All expression nodes implement the Expr interface.
    53  type Expr interface {
    54  	Node
    55  
    56  	exprNode()
    57  }
    58  
    59  // All statement nodes implement the Stmt interface.
    60  type Stmt interface {
    61  	Node
    62  
    63  	stmtNode()
    64  }
    65  
    66  // ----------------------------------------------------------------------------
    67  // Expressions
    68  
    69  // An expression is represented by a tree consisting of one
    70  // or more of the following concrete expression nodes.
    71  //
    72  type (
    73  	// A BadExpr node is a placeholder for expressions containing
    74  	// syntax errors for which no correct expression nodes can be
    75  	// created.
    76  	//
    77  	BadExpr struct {
    78  		From, To position.Position // position range of bad expression
    79  	}
    80  
    81  	// An Name node represents an identifier.
    82  	Name struct {
    83  		NamePos position.Position // identifier position
    84  		Name    string            // identifier name
    85  	}
    86  
    87  	Vararg struct {
    88  		Ellipsis position.Position // position of "..."
    89  	}
    90  
    91  	// A BasicLit node represents a literal of basic type.
    92  	BasicLit struct {
    93  		token.Token
    94  	}
    95  
    96  	// A FuncLit node represents a function literal.
    97  	FuncLit struct {
    98  		Func   position.Position // position of "function" keyword
    99  		Body   *FuncBody         // function body
   100  		EndPos position.Position
   101  	}
   102  
   103  	// A TableLit node represents a composite literal.
   104  	TableLit struct {
   105  		Lbrace position.Position // position of "{"
   106  		Fields []Expr            // fields
   107  		Rbrace position.Position // position of "}"
   108  	}
   109  
   110  	// A ParenExpr node represents a parenthesized expression.
   111  	ParenExpr struct {
   112  		Lparen position.Position // position of "("
   113  		X      Expr              // parenthesized expression
   114  		Rparen position.Position // position of ")"
   115  	}
   116  
   117  	// A SelectorExpr node represents an expression followed by a selector.
   118  	SelectorExpr struct {
   119  		X      Expr              // expression
   120  		Period position.Position // position of "."
   121  		Sel    *Name             // field selector
   122  	}
   123  
   124  	// An IndexExpr node represents an expression followed by an index.
   125  	IndexExpr struct {
   126  		X      Expr              // expression
   127  		Lbrack position.Position // position of "["
   128  		Index  Expr              // index expression
   129  		Rbrack position.Position // position of "]"
   130  	}
   131  
   132  	// A CallExpr node represents an expression followed by an argument list.
   133  	CallExpr struct {
   134  		X      Expr              // function expression
   135  		Colon  position.Position // position of ":" or position.NoPos
   136  		Name   *Name             // method name; or nil
   137  		Lparen position.Position // position of "(" or position.NoPos
   138  		Args   []Expr            // function arguments; or nil
   139  		Rparen position.Position // position of ")" or position.NoPos
   140  	}
   141  
   142  	// A UnaryExpr node represents a unary expression.
   143  	UnaryExpr struct {
   144  		OpPos position.Position // position of Op
   145  		Op    token.Type        // operator
   146  		X     Expr              // operand
   147  	}
   148  
   149  	// A BinaryExpr node represents a binary expression.
   150  	BinaryExpr struct {
   151  		X     Expr              // left operand
   152  		OpPos position.Position // position of Op
   153  		Op    token.Type        // operator
   154  		Y     Expr              // right operand
   155  	}
   156  
   157  	// A KeyValueExpr node represents (key = value) pairs or (value)
   158  	// in table literals.
   159  	//
   160  	KeyValueExpr struct {
   161  		Lbrack position.Position // position of "["; or position.NoPos
   162  		Key    Expr              // key; or nil
   163  		Rbrack position.Position // position of "]"; or position.NoPos
   164  		Equal  position.Position // position of "="; or position.NoPos
   165  		Value  Expr
   166  	}
   167  )
   168  
   169  func (*BadExpr) Type() Type      { return BAD_EXPR }
   170  func (*Name) Type() Type         { return NAME }
   171  func (*Vararg) Type() Type       { return VARARG }
   172  func (*BasicLit) Type() Type     { return BASIC_LIT }
   173  func (*FuncLit) Type() Type      { return FUNC_LIT }
   174  func (*TableLit) Type() Type     { return TABLE_LIT }
   175  func (*ParenExpr) Type() Type    { return PAREN_EXPR }
   176  func (*SelectorExpr) Type() Type { return SELECTOR_EXPR }
   177  func (*IndexExpr) Type() Type    { return INDEX_EXPR }
   178  func (*CallExpr) Type() Type     { return CALL_EXPR }
   179  func (*UnaryExpr) Type() Type    { return UNARY_EXPR }
   180  func (*BinaryExpr) Type() Type   { return BINARY_EXPR }
   181  func (*KeyValueExpr) Type() Type { return KEY_VALUE_EXPR }
   182  
   183  // Pos and End implementations for expression/type nodes.
   184  //
   185  func (x *BadExpr) Pos() position.Position  { return x.From }
   186  func (x *Name) Pos() position.Position     { return x.NamePos }
   187  func (x *Vararg) Pos() position.Position   { return x.Ellipsis }
   188  func (x *BasicLit) Pos() position.Position { return x.Token.Pos }
   189  func (x *FuncLit) Pos() position.Position  { return x.Func }
   190  func (x *TableLit) Pos() position.Position {
   191  	return x.Lbrace
   192  }
   193  func (x *ParenExpr) Pos() position.Position    { return x.Lparen }
   194  func (x *SelectorExpr) Pos() position.Position { return x.X.Pos() }
   195  func (x *IndexExpr) Pos() position.Position    { return x.X.Pos() }
   196  func (x *CallExpr) Pos() position.Position     { return x.X.Pos() }
   197  func (x *UnaryExpr) Pos() position.Position    { return x.OpPos }
   198  func (x *BinaryExpr) Pos() position.Position   { return x.X.Pos() }
   199  func (x *KeyValueExpr) Pos() position.Position {
   200  	if x.Lbrack.IsValid() {
   201  		return x.Lbrack
   202  	}
   203  
   204  	return x.Key.Pos()
   205  }
   206  
   207  func (x *BadExpr) End() position.Position      { return x.To }
   208  func (x *Name) End() position.Position         { return x.NamePos.Offset(x.Name) }
   209  func (x *Vararg) End() position.Position       { return x.Ellipsis.OffsetColumn(3) }
   210  func (x *BasicLit) End() position.Position     { return x.Token.Pos.Offset(x.Token.Lit) }
   211  func (x *FuncLit) End() position.Position      { return x.EndPos.OffsetColumn(3) }
   212  func (x *TableLit) End() position.Position     { return x.Rbrace.OffsetColumn(1) }
   213  func (x *ParenExpr) End() position.Position    { return x.Rparen.OffsetColumn(1) }
   214  func (x *SelectorExpr) End() position.Position { return x.Sel.End() }
   215  func (x *IndexExpr) End() position.Position    { return x.Rbrack.OffsetColumn(1) }
   216  func (x *CallExpr) End() position.Position {
   217  	if x.Rparen.IsValid() {
   218  		return x.Rparen.OffsetColumn(1)
   219  	}
   220  	if len(x.Args) > 0 {
   221  		return x.Args[len(x.Args)-1].End()
   222  	}
   223  	return position.NoPos
   224  }
   225  func (x *UnaryExpr) End() position.Position    { return x.X.End() }
   226  func (x *BinaryExpr) End() position.Position   { return x.Y.End() }
   227  func (x *KeyValueExpr) End() position.Position { return x.Value.End() }
   228  
   229  // exprNode() ensures that only expression/type nodes can be
   230  // assigned to an ExprNode.
   231  //
   232  func (*BadExpr) exprNode()      {}
   233  func (*Name) exprNode()         {}
   234  func (*Vararg) exprNode()       {}
   235  func (*BasicLit) exprNode()     {}
   236  func (*FuncLit) exprNode()      {}
   237  func (*TableLit) exprNode()     {}
   238  func (*ParenExpr) exprNode()    {}
   239  func (*SelectorExpr) exprNode() {}
   240  func (*IndexExpr) exprNode()    {}
   241  func (*CallExpr) exprNode()     {}
   242  func (*UnaryExpr) exprNode()    {}
   243  func (*BinaryExpr) exprNode()   {}
   244  func (*KeyValueExpr) exprNode() {}
   245  
   246  // ----------------------------------------------------------------------------
   247  // Statements
   248  
   249  // A statement is represented by a tree consisting of one
   250  // or more of the following concrete statement nodes.
   251  //
   252  type (
   253  	// A BadStmt node is a placeholder for statements containing
   254  	// syntax errors for which no correct statement nodes can be
   255  	// created.
   256  	//
   257  	BadStmt struct {
   258  		From, To position.Position // position range of bad statement
   259  	}
   260  
   261  	// An EmptyStmt node represents an empty statement.
   262  	// The "position" of the empty statement is the position
   263  	// of the immediately preceding semicolon.
   264  	//
   265  	EmptyStmt struct {
   266  		Semicolon position.Position // position of preceding ";"
   267  	}
   268  
   269  	LocalAssignStmt struct {
   270  		Local position.Position // position of "local" keyword
   271  		LHS   []*Name
   272  		Equal position.Position // position of Tok
   273  		RHS   []Expr
   274  	}
   275  
   276  	LocalFuncStmt struct {
   277  		Local  position.Position // position of "local" keyword
   278  		Func   position.Position // position of "function" keyword
   279  		Name   *Name
   280  		Body   *FuncBody // function body
   281  		EndPos position.Position
   282  	}
   283  
   284  	// A FuncStmt node represents a function statement.
   285  	FuncStmt struct {
   286  		Func      position.Position // position of "function" keyword
   287  		PathList  []*Name
   288  		AccessTok token.Type        // "." or ":"
   289  		AccessPos position.Position // position of AccessTok
   290  		Name      *Name
   291  		Body      *FuncBody // function body
   292  		EndPos    position.Position
   293  	}
   294  
   295  	// A LabelStmt node represents a label statement.
   296  	LabelStmt struct {
   297  		Label    position.Position // position of "::"
   298  		Name     *Name
   299  		EndLabel position.Position // position of "::"
   300  	}
   301  
   302  	// An ExprStmt node represents a (stand-alone) expression
   303  	// in a statement list.
   304  	//
   305  	ExprStmt struct {
   306  		X *CallExpr // expression
   307  	}
   308  
   309  	// An AssignStmt node represents an assignment statement.
   310  	AssignStmt struct {
   311  		LHS   []Expr
   312  		Equal position.Position // position of "="
   313  		RHS   []Expr
   314  	}
   315  
   316  	// A GotoStmt node represents a goto statement.
   317  	GotoStmt struct {
   318  		Goto  position.Position
   319  		Label *Name // label name
   320  	}
   321  
   322  	// A BreakStmt represents a break statement.
   323  	BreakStmt struct {
   324  		Break position.Position // position of "break"
   325  	}
   326  
   327  	// An IfStmt node represents an if statement.
   328  	IfStmt struct {
   329  		If         position.Position // position of "if"
   330  		Cond       Expr              // condition
   331  		Then       position.Position // position of "then"
   332  		Body       *Block
   333  		ElseIfList []struct { // elseif branches; or nil
   334  			If   position.Position // position of "elseif"
   335  			Cond Expr              // condition
   336  			Then position.Position // position of "then"
   337  			Body *Block
   338  		}
   339  		Else     position.Position // position of "else" or position.NoPos
   340  		ElseBody *Block            // else branch; or nil
   341  		EndPos   position.Position
   342  	}
   343  
   344  	// A DoStmt represents a do statement.
   345  	DoStmt struct {
   346  		Do     position.Position
   347  		Body   *Block
   348  		EndPos position.Position
   349  	}
   350  
   351  	// A WhileStmt represents a while statement.
   352  	WhileStmt struct {
   353  		While  position.Position // position of "while" keyword
   354  		Cond   Expr              // condition
   355  		Do     position.Position // position of "do" keyword
   356  		Body   *Block
   357  		EndPos position.Position
   358  	}
   359  
   360  	// A RepeatStmt represents a repeat statement.
   361  	RepeatStmt struct {
   362  		Repeat position.Position // position of "repeat" keyword
   363  		Body   *Block
   364  		Until  position.Position // position of  "until" keyword
   365  		Cond   Expr              // condition
   366  	}
   367  
   368  	// A ReturnStmt represents a return statement.
   369  	ReturnStmt struct {
   370  		Return    position.Position // position of "return" keyword
   371  		Results   []Expr
   372  		Semicolon position.Position // position of ";" if exist
   373  	}
   374  
   375  	// A ForStmt represents a for statement.
   376  	ForStmt struct {
   377  		For    position.Position // position of "for" keyword
   378  		Name   *Name
   379  		Equal  position.Position // position of "="
   380  		Start  Expr
   381  		Finish Expr
   382  		Step   Expr // or nil
   383  		Do     position.Position
   384  		Body   *Block
   385  		EndPos position.Position
   386  	}
   387  
   388  	// A ForEachStmt represents a for statement with a range clause.
   389  	ForEachStmt struct {
   390  		For    position.Position // position of "for" keyword
   391  		Names  []*Name           // Key, Value may be nil
   392  		In     position.Position // position of "in" keyword
   393  		Exprs  []Expr            // value to range over
   394  		Do     position.Position
   395  		Body   *Block
   396  		EndPos position.Position
   397  	}
   398  )
   399  
   400  func (*BadStmt) Type() Type         { return BAD_STMT }
   401  func (*EmptyStmt) Type() Type       { return EMPTY_STMT }
   402  func (*LocalAssignStmt) Type() Type { return LOCAL_ASSIGN_STMT }
   403  func (*LocalFuncStmt) Type() Type   { return LOCAL_FUNC_STMT }
   404  func (*FuncStmt) Type() Type        { return FUNC_STMT }
   405  func (*LabelStmt) Type() Type       { return LABEL_STMT }
   406  func (*ExprStmt) Type() Type        { return EXPR_STMT }
   407  func (*AssignStmt) Type() Type      { return ASSIGN_STMT }
   408  func (*GotoStmt) Type() Type        { return GOTO_STMT }
   409  func (*IfStmt) Type() Type          { return IF_STMT }
   410  func (*DoStmt) Type() Type          { return DO_STMT }
   411  func (*WhileStmt) Type() Type       { return WHILE_STMT }
   412  func (*RepeatStmt) Type() Type      { return REPEAT_STMT }
   413  func (*BreakStmt) Type() Type       { return BREAK_STMT }
   414  func (*ReturnStmt) Type() Type      { return RETURN_STMT }
   415  func (*ForStmt) Type() Type         { return FOR_STMT }
   416  func (*ForEachStmt) Type() Type     { return FOR_EACH_STMT }
   417  
   418  // Pos and End implementations for statement nodes.
   419  //
   420  func (s *BadStmt) Pos() position.Position         { return s.From }
   421  func (s *EmptyStmt) Pos() position.Position       { return s.Semicolon }
   422  func (s *LocalAssignStmt) Pos() position.Position { return s.Local }
   423  func (s *LocalFuncStmt) Pos() position.Position   { return s.Local }
   424  func (s *FuncStmt) Pos() position.Position        { return s.Func }
   425  func (s *LabelStmt) Pos() position.Position       { return s.Label }
   426  func (s *ExprStmt) Pos() position.Position        { return s.X.Pos() }
   427  func (s *AssignStmt) Pos() position.Position {
   428  	if len(s.LHS) > 0 {
   429  		return s.LHS[0].Pos()
   430  	}
   431  	return position.NoPos
   432  }
   433  func (s *GotoStmt) Pos() position.Position    { return s.Goto }
   434  func (s *IfStmt) Pos() position.Position      { return s.If }
   435  func (s *DoStmt) Pos() position.Position      { return s.Do }
   436  func (s *WhileStmt) Pos() position.Position   { return s.While }
   437  func (s *RepeatStmt) Pos() position.Position  { return s.Repeat }
   438  func (s *BreakStmt) Pos() position.Position   { return s.Break }
   439  func (s *ReturnStmt) Pos() position.Position  { return s.Return }
   440  func (s *ForStmt) Pos() position.Position     { return s.For }
   441  func (s *ForEachStmt) Pos() position.Position { return s.For }
   442  
   443  func (s *BadStmt) End() position.Position   { return s.To }
   444  func (s *EmptyStmt) End() position.Position { return s.Semicolon.OffsetColumn(1) }
   445  func (s *LocalAssignStmt) End() position.Position {
   446  	if s.Equal.IsValid() {
   447  		if len(s.RHS) > 0 {
   448  			return s.RHS[len(s.RHS)-1].End()
   449  		}
   450  		return position.NoPos
   451  	}
   452  	if len(s.LHS) > 0 {
   453  		return s.LHS[len(s.LHS)-1].End()
   454  	}
   455  	return position.NoPos
   456  }
   457  func (s *LocalFuncStmt) End() position.Position { return s.EndPos.OffsetColumn(3) }
   458  func (s *FuncStmt) End() position.Position      { return s.EndPos.OffsetColumn(3) }
   459  func (s *LabelStmt) End() position.Position     { return s.EndLabel.OffsetColumn(2) }
   460  func (s *ExprStmt) End() position.Position      { return s.X.End() }
   461  func (s *AssignStmt) End() position.Position {
   462  	if len(s.RHS) > 0 {
   463  		return s.RHS[len(s.RHS)-1].End()
   464  	}
   465  	return position.NoPos
   466  }
   467  func (s *GotoStmt) End() position.Position {
   468  	return s.Label.End()
   469  }
   470  func (s *IfStmt) End() position.Position     { return s.EndPos.OffsetColumn(3) }
   471  func (s *DoStmt) End() position.Position     { return s.EndPos.OffsetColumn(3) }
   472  func (s *WhileStmt) End() position.Position  { return s.EndPos.OffsetColumn(3) }
   473  func (s *RepeatStmt) End() position.Position { return s.Cond.End() }
   474  func (s *BreakStmt) End() position.Position  { return s.Break.OffsetColumn(5) }
   475  func (s *ReturnStmt) End() position.Position {
   476  	if s.Semicolon.IsValid() {
   477  		return s.Semicolon.OffsetColumn(1)
   478  	}
   479  	if len(s.Results) > 0 {
   480  		return s.Results[len(s.Results)-1].End()
   481  	}
   482  	return s.Return.OffsetColumn(6)
   483  }
   484  func (s *ForStmt) End() position.Position     { return s.EndPos.OffsetColumn(3) }
   485  func (s *ForEachStmt) End() position.Position { return s.EndPos.OffsetColumn(3) }
   486  
   487  // stmtNode() ensures that only statement nodes can be
   488  // assigned to a StmtNode.
   489  //
   490  func (*BadStmt) stmtNode()         {}
   491  func (*EmptyStmt) stmtNode()       {}
   492  func (*LocalAssignStmt) stmtNode() {}
   493  func (*LocalFuncStmt) stmtNode()   {}
   494  func (*FuncStmt) stmtNode()        {}
   495  func (*LabelStmt) stmtNode()       {}
   496  func (*ExprStmt) stmtNode()        {}
   497  func (*AssignStmt) stmtNode()      {}
   498  func (*GotoStmt) stmtNode()        {}
   499  func (*IfStmt) stmtNode()          {}
   500  func (*DoStmt) stmtNode()          {}
   501  func (*WhileStmt) stmtNode()       {}
   502  func (*RepeatStmt) stmtNode()      {}
   503  func (*BreakStmt) stmtNode()       {}
   504  func (*ReturnStmt) stmtNode()      {}
   505  func (*ForStmt) stmtNode()         {}
   506  func (*ForEachStmt) stmtNode()     {}
   507  
   508  // ----------------------------------------------------------------------------
   509  // Other Nodes
   510  
   511  // ----------------------------------------------------------------------------
   512  // File
   513  
   514  // A File node represents a Lua source file.
   515  //
   516  // The Comments list contains all comments in the source file in order of
   517  // appearance, including the comments that are pointed to from other nodes.
   518  type File struct {
   519  	Filename string
   520  	Shebang  string
   521  	Chunk    []Stmt
   522  	Comments []*CommentGroup // list of all comments in the source file
   523  }
   524  
   525  func (f *File) Type() Type             { return FILE }
   526  func (f *File) Pos() position.Position { return position.Position{Line: 1, Column: 1} }
   527  func (f *File) End() position.Position {
   528  	var pos position.Position
   529  	if len(f.Chunk) > 0 {
   530  		pos = f.Chunk[len(f.Chunk)-1].End()
   531  	}
   532  	if len(f.Comments) > 0 {
   533  		cpos := f.Comments[len(f.Comments)-1].End()
   534  		if pos.LessThan(cpos) {
   535  			pos = cpos
   536  		}
   537  	}
   538  	return pos
   539  }
   540  
   541  // ----------------------------------------------------------------------------
   542  // Block
   543  
   544  // A Block node represents a scoped statement list.
   545  type Block struct {
   546  	Opening position.Position // end of "do", "then", "repeat", ...
   547  	List    []Stmt
   548  	Closing position.Position // start of "end", "elseif", "until", ...
   549  }
   550  
   551  func (b *Block) Type() Type { return BLOCK }
   552  
   553  func (b *Block) Pos() position.Position {
   554  	return b.Opening
   555  }
   556  
   557  func (b *Block) End() position.Position {
   558  	return b.Closing
   559  }
   560  
   561  // ----------------------------------------------------------------------------
   562  // Function Block
   563  
   564  // A Function Block node represents a function implementation.
   565  type FuncBody struct {
   566  	Params *ParamList
   567  	Body   *Block
   568  }
   569  
   570  func (f *FuncBody) Type() Type { return FUNC_BODY }
   571  
   572  func (f *FuncBody) Pos() position.Position { return f.Params.Pos() }
   573  
   574  func (f *FuncBody) End() position.Position { return f.Body.End() }
   575  
   576  // ----------------------------------------------------------------------------
   577  // Param List
   578  
   579  // A ParamList represents a list of Names, enclosed by parentheses or braces.
   580  type ParamList struct {
   581  	Lparen   position.Position // position of "("
   582  	List     []*Name           // field list; or nil
   583  	Ellipsis position.Position
   584  	Rparen   position.Position // position of ")"
   585  }
   586  
   587  func (f *ParamList) Type() Type {
   588  	return PARAM_LIST
   589  }
   590  
   591  func (f *ParamList) Pos() position.Position {
   592  	if f.Lparen.IsValid() {
   593  		return f.Lparen
   594  	}
   595  	// the list should not be empty in this case;
   596  	// be conservative and guard against bad ASTs
   597  	if len(f.List) > 0 {
   598  		return f.List[0].Pos()
   599  	}
   600  	return position.NoPos
   601  }
   602  
   603  func (f *ParamList) End() position.Position {
   604  	if f.Rparen.IsValid() {
   605  		return f.Rparen.OffsetColumn(1)
   606  	}
   607  	// the list should not be empty in this case;
   608  	// be conservative and guard against bad ASTs
   609  	if n := len(f.List); n > 0 {
   610  		return f.List[n-1].End()
   611  	}
   612  	return position.NoPos
   613  }
   614  
   615  // ----------------------------------------------------------------------------
   616  // Comments
   617  
   618  // A Comment node represents a single --style or --[[style comment.
   619  type Comment struct {
   620  	Hyphen position.Position // position of "-" starting the comment
   621  	Text   string            // comment text (excluding '\n' for --style comments)
   622  }
   623  
   624  func (c *Comment) Type() Type             { return COMMENT }
   625  func (c *Comment) Pos() position.Position { return c.Hyphen }
   626  func (c *Comment) End() position.Position { return c.Hyphen.Offset(c.Text) }
   627  
   628  // A CommentGroup represents a sequence of comments
   629  // with no other tokens and no empty lines between.
   630  //
   631  type CommentGroup struct {
   632  	List []*Comment // len(List) > 0
   633  }
   634  
   635  func (g *CommentGroup) Type() Type { return COMMENT_GROUP }
   636  func (g *CommentGroup) Pos() position.Position {
   637  	if len(g.List) > 0 {
   638  		return g.List[0].Pos()
   639  	}
   640  	return position.NoPos
   641  }
   642  func (g *CommentGroup) End() position.Position {
   643  	if len(g.List) > 0 {
   644  		return g.List[len(g.List)-1].End()
   645  	}
   646  	return position.NoPos
   647  }
   648  
   649  func isSpace(c byte) bool {
   650  	return c == ' ' || uint(c)-'\t' < 5
   651  }
   652  
   653  func stripTrailingSpace(s string) string {
   654  	i := len(s)
   655  	for i > 0 && isSpace(s[i-1]) {
   656  		i--
   657  	}
   658  	return s[0:i]
   659  }
   660  
   661  // Text returns the text of the comment.
   662  // Comment markers (//, /*, and */), the first space of a line comment, and
   663  // leading and trailing empty lines are removed. Multiple empty lines are
   664  // reduced to one, and trailing space on lines is trimmed. Unless the result
   665  // is empty, it is newline-terminated.
   666  //
   667  func (g *CommentGroup) Text() string {
   668  	if g == nil {
   669  		return ""
   670  	}
   671  
   672  	lines := make([]string, 0, len(g.List))
   673  	for _, c := range g.List {
   674  		text := c.Text
   675  		if len(text) > 0 && text[0] == ' ' {
   676  			text = text[1:]
   677  		}
   678  
   679  		// Split on newlines.
   680  		tl := strings.Split(text, "\n")
   681  
   682  		// Walk lines, stripping trailing white space and adding to list.
   683  		for _, l := range tl {
   684  			lines = append(lines, stripTrailingSpace(l))
   685  		}
   686  	}
   687  
   688  	// Remove leading blank lines; convert runs of
   689  	// interior blank lines to a single blank line.
   690  	n := 0
   691  	for _, line := range lines {
   692  		if line != "" || n > 0 && lines[n-1] != "" {
   693  			lines[n] = line
   694  			n++
   695  		}
   696  	}
   697  	lines = lines[0:n]
   698  
   699  	// Add final "" entry to get trailing newline from Join.
   700  	if n > 0 && lines[n-1] != "" {
   701  		lines = append(lines, "")
   702  	}
   703  
   704  	return strings.Join(lines, "\n")
   705  }