github.com/cloudwego/thriftgo@v0.3.10/parser/parser.go (about)

     1  // Copyright 2021 CloudWeGo Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //   http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package parser parses a thrift IDL file with its dependencies into an abstract syntax tree.
    16  // The acceptable IDL grammar is defined in the 'thrift.peg' file.
    17  package parser
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"os"
    24  	"path/filepath"
    25  	"strconv"
    26  	"strings"
    27  )
    28  
    29  // NOTSET is a value to express 'not set'.
    30  const NOTSET = -999999
    31  
    32  type parser struct {
    33  	ThriftIDL
    34  	Thrift
    35  	IncludeDirs               []string
    36  	Annotations               *Annotations
    37  	DefinitionReservedComment string
    38  }
    39  
    40  func exists(path string) bool {
    41  	fi, err := os.Stat(path)
    42  	if err != nil {
    43  		return os.IsExist(err)
    44  	}
    45  	return !fi.IsDir()
    46  }
    47  
    48  func search(file, dir string, includeDirs []string) (string, error) {
    49  	ps := []string{file, filepath.Join(dir, file)}
    50  	for _, inc := range includeDirs {
    51  		ps = append(ps, filepath.Join(inc, file))
    52  	}
    53  	for _, p := range ps {
    54  		if exists(p) {
    55  			return normalizeFilename(p), nil
    56  		}
    57  	}
    58  	return file, &os.PathError{Op: "search", Path: file, Err: os.ErrNotExist}
    59  }
    60  
    61  // ParseFile parses a thrift file and returns an AST.
    62  // If recursive is true, then the include IDLs are parsed recursively as well.
    63  func ParseFile(path string, includeDirs []string, recursive bool) (*Thrift, error) {
    64  	if recursive {
    65  		thriftMap := make(map[string]*Thrift)
    66  		dir := filepath.Dir(normalizeFilename(path))
    67  		return parseFileRecursively(path, dir, includeDirs, thriftMap)
    68  	}
    69  	bs, err := ioutil.ReadFile(path)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	return parseString(path, string(bs), includeDirs)
    74  }
    75  
    76  func parseFileRecursively(file, dir string, includeDirs []string, thriftMap map[string]*Thrift) (*Thrift, error) {
    77  	path, err := search(file, dir, includeDirs)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	if t, ok := thriftMap[path]; ok {
    82  		return t, nil
    83  	}
    84  	bs, err := ioutil.ReadFile(path)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	t, err := parseString(path, string(bs), includeDirs)
    89  	if err != nil {
    90  		return nil, fmt.Errorf("parse %s err: %w", path, err)
    91  	}
    92  	thriftMap[path] = t
    93  	dir = filepath.Dir(path)
    94  	for _, inc := range t.Includes {
    95  		t, err := parseFileRecursively(inc.Path, dir, includeDirs, thriftMap)
    96  		if err != nil {
    97  			return nil, err
    98  		}
    99  		inc.Reference = t
   100  	}
   101  	return t, nil
   102  }
   103  
   104  // ParseString parses the thrift file path and file content then return an AST.
   105  func ParseString(path, content string) (*Thrift, error) {
   106  	return parseString(path, content, nil)
   107  }
   108  
   109  func parseString(path, content string, includeDirs []string) (*Thrift, error) {
   110  	p := &parser{
   111  		IncludeDirs: includeDirs,
   112  	}
   113  	p.Filename = path
   114  	p.Buffer = content
   115  	p.Init()
   116  	if err := p.ThriftIDL.Parse(); err != nil {
   117  		return nil, err
   118  	}
   119  	if err := p.parse(); err != nil {
   120  		return nil, err
   121  	}
   122  	return &p.Thrift, nil
   123  }
   124  
   125  func (p *parser) parse() (err error) {
   126  	root := p.AST()
   127  	if root == nil || root.pegRule != ruleDocument {
   128  		return errors.New("not document")
   129  	}
   130  	// Header* Definition* !.
   131  	for n := root.up; n != nil; n = n.next {
   132  		switch n.pegRule {
   133  		case ruleSkip, ruleSkipLine:
   134  			continue
   135  		case ruleHeader:
   136  			if err := p.parseHeader(n); err != nil {
   137  				return err
   138  			}
   139  		case ruleDefinition:
   140  			if err := p.parseDefinition(n); err != nil {
   141  				return err
   142  			}
   143  		default:
   144  			return fmt.Errorf("unknown rule: " + rul3s[n.pegRule])
   145  		}
   146  	}
   147  	return nil
   148  }
   149  
   150  func (p *parser) pegText(node *node32) string {
   151  	for n := node; n != nil; n = n.next {
   152  		if s := p.pegText(n.up); s != "" {
   153  			return s
   154  		}
   155  		if n.pegRule != rulePegText {
   156  			continue
   157  		}
   158  
   159  		quote := p.buffer[n.begin-1]
   160  		runes := make([]rune, 0, n.end-n.begin)
   161  		for i := n.begin; i < n.end-1; i++ {
   162  			r := p.buffer[i]
   163  
   164  			// unescape \' for single quoted, \" for double quoted
   165  			if r == '\\' {
   166  				switch p.buffer[i+1] {
   167  				case '\\':
   168  					i++
   169  					runes = append(runes, r)
   170  				case quote:
   171  					continue
   172  				}
   173  			}
   174  			runes = append(runes, r)
   175  		}
   176  		runes = append(runes, p.buffer[n.end-1])
   177  		return string(runes)
   178  	}
   179  	return ""
   180  }
   181  
   182  func (p *parser) parseHeader(node *node32) (err error) {
   183  	node, err = checkrule(node, ruleHeader)
   184  	if err != nil {
   185  		return err
   186  	}
   187  	// Skip (Include / CppInclude / Namespace) SkipLine
   188  	if node.pegRule == ruleSkip {
   189  		node = node.next
   190  	}
   191  	switch node.pegRule {
   192  	case ruleInclude:
   193  		if err := p.parseInclude(node); err != nil {
   194  			return err
   195  		}
   196  	case ruleNamespace:
   197  		if err := p.parseNamespace(node); err != nil {
   198  			return err
   199  		}
   200  	case ruleCppInclude:
   201  		if err := p.parseCppInclude(node); err != nil {
   202  			return err
   203  		}
   204  	default:
   205  		return fmt.Errorf("unknown rule: " + rul3s[node.pegRule])
   206  	}
   207  	return nil
   208  }
   209  
   210  func (p *parser) parseInclude(node *node32) (err error) {
   211  	node, err = checkrule(node, ruleInclude)
   212  	if err != nil {
   213  		return err
   214  	}
   215  	filename := p.pegText(node)
   216  	if filename == "" {
   217  		return
   218  	}
   219  	for _, inc := range p.Includes {
   220  		if inc.Path == filename {
   221  			return
   222  		}
   223  	}
   224  	p.Includes = append(p.Includes, &Include{Path: filename})
   225  	return nil
   226  }
   227  
   228  func (p *parser) parseCppInclude(node *node32) (err error) {
   229  	node, err = checkrule(node, ruleCppInclude)
   230  	if err != nil {
   231  		return err
   232  	}
   233  	p.CppIncludes = append(p.CppIncludes, p.pegText(node))
   234  	return nil
   235  }
   236  
   237  func (p *parser) parseNamespace(node *node32) (err error) {
   238  	ns := Namespace{}
   239  	node, err = checkrule(node, ruleNamespace)
   240  	if err != nil {
   241  		return err
   242  	}
   243  	node = node.next // ignore "namespace"
   244  	ns.Language = p.pegText(node.up)
   245  	node = node.next
   246  	ns.Name = p.pegText(node.up)
   247  	node = node.next
   248  	if node != nil && node.pegRule == ruleAnnotations { // ANNOTATIONS
   249  		ns.Annotations, err = p.parseAnnotations(node)
   250  		if err != nil {
   251  			return err
   252  		}
   253  	}
   254  	p.Namespaces = append(p.Namespaces, &ns)
   255  	return nil
   256  }
   257  
   258  func (p *parser) parseDefinition(node *node32) (err error) {
   259  	node, err = checkrule(node, ruleDefinition)
   260  	if err != nil {
   261  		return err
   262  	}
   263  	p.DefinitionReservedComment = ""
   264  	// ReservedComments Skip (Const / Typedef / Enum / Struct / Union / Service / Exception) Annotations? SkipLine
   265  	if node.pegRule == ruleReservedComments {
   266  		reservedComments, err := p.parseReservedComments(node)
   267  		if err != nil {
   268  			return err
   269  		}
   270  		p.DefinitionReservedComment = reservedComments
   271  		node = node.next
   272  	}
   273  	// skip Skip
   274  	if node.pegRule == ruleSkip {
   275  		node = node.next
   276  	}
   277  	switch node.pegRule {
   278  	case ruleConst:
   279  		if err := p.parseConst(node); err != nil {
   280  			return err
   281  		}
   282  	case ruleTypedef:
   283  		if err := p.parseTypedef(node); err != nil {
   284  			return err
   285  		}
   286  	case ruleEnum:
   287  		if err := p.parseEnum(node); err != nil {
   288  			return err
   289  		}
   290  	case ruleUnion:
   291  		if err := p.parseUnion(node); err != nil {
   292  			return err
   293  		}
   294  	case ruleStruct:
   295  		if err := p.parseStruct(node); err != nil {
   296  			return err
   297  		}
   298  	case ruleException:
   299  		if err := p.parseException(node); err != nil {
   300  			return err
   301  		}
   302  	case ruleService:
   303  		if err := p.parseService(node); err != nil {
   304  			return err
   305  		}
   306  	default:
   307  		return fmt.Errorf("unknown rule: " + rul3s[node.pegRule])
   308  	}
   309  	node = node.next
   310  	if node != nil && node.pegRule == ruleAnnotations {
   311  		ann, err := p.parseAnnotations(node)
   312  		if err != nil {
   313  			return err
   314  		}
   315  		*p.Annotations = ann
   316  	}
   317  	return nil
   318  }
   319  
   320  func (p *parser) parseConst(node *node32) (err error) {
   321  	node, err = checkrule(node, ruleConst)
   322  	if err != nil {
   323  		return err
   324  	}
   325  	// CONST FieldType Identifier EQUAL ConstValue ListSeparator?
   326  	node = node.next // ignore CONST
   327  	ft, err := p.parseFieldType(node)
   328  	if err != nil {
   329  		return err
   330  	}
   331  	node = node.next
   332  	name := p.pegText(node)
   333  	node = node.next.next // ignore EQUAL
   334  	value, err := p.parseConstValue(node)
   335  	if err != nil {
   336  		return err
   337  	}
   338  	c := &Constant{Name: name, Type: ft, Value: value}
   339  	c.ReservedComments = p.DefinitionReservedComment
   340  	p.Constants = append(p.Constants, c)
   341  	p.Annotations = &c.Annotations
   342  	return nil
   343  }
   344  
   345  func (p *parser) parseFieldType(node *node32) (typ *Type, err error) {
   346  	node, err = checkrule(node, ruleFieldType)
   347  	if err != nil {
   348  		return nil, err
   349  	}
   350  	// ContainerType / BaseType / Identifier
   351  	switch node.pegRule {
   352  	case ruleContainerType:
   353  		typ, err = p.parseContainerType(node)
   354  		if err != nil {
   355  			return typ, err
   356  		}
   357  	case ruleIdentifier, ruleBaseType:
   358  		typ = &Type{Name: p.pegText(node)}
   359  	default:
   360  		return typ, fmt.Errorf("unknown rule: " + rul3s[node.pegRule])
   361  	}
   362  	node = node.next
   363  	if node != nil && node.pegRule == ruleAnnotations {
   364  		typ.Annotations, err = p.parseAnnotations(node)
   365  		if err != nil {
   366  			return typ, err
   367  		}
   368  	}
   369  	return typ, nil
   370  }
   371  
   372  func (p *parser) parseContainerType(node *node32) (typ *Type, err error) {
   373  	node, err = checkrule(node, ruleContainerType)
   374  	if err != nil {
   375  		return &Type{}, err
   376  	}
   377  	// MapType / SetType / ListType
   378  	switch node.pegRule {
   379  	case ruleMapType: // MAP CppType? LPOINT FieldType COMMA FieldType RPOINT
   380  		node = node.up.next // ignore MAP LPOINT
   381  		var cppType string
   382  		if node.pegRule == ruleCppType {
   383  			cppType = p.pegText(node.up.next) // ignore CPPTYPE
   384  			node = node.next
   385  		}
   386  		node = node.next // ignore LPOINT
   387  		kt, err := p.parseFieldType(node)
   388  		if err != nil {
   389  			return kt, err
   390  		}
   391  		node = node.next.next // ignore COMMA
   392  		vt, err := p.parseFieldType(node)
   393  		if err != nil {
   394  			return vt, err
   395  		}
   396  		return &Type{Name: "map", KeyType: kt, ValueType: vt, CppType: cppType}, nil
   397  	case ruleSetType: // SET CppType? LPOINT FieldType RPOINT
   398  		node = node.up.next // ignore SET
   399  		var cppType string
   400  		if node.pegRule == ruleCppType {
   401  			cppType = p.pegText(node.up.next) // ignore CPPTYPE
   402  			node = node.next
   403  		}
   404  		node = node.next // ignore LPOINT
   405  		vt, err := p.parseFieldType(node)
   406  		if err != nil {
   407  			return vt, err
   408  		}
   409  		return &Type{Name: "set", ValueType: vt, CppType: cppType}, nil
   410  	case ruleListType: // LIST LPOINT FieldType RPOINT CppType?
   411  		node = node.up.next.next // ignore LIST LPOINT
   412  		vt, err := p.parseFieldType(node)
   413  		if err != nil {
   414  			return vt, err
   415  		}
   416  		node = node.next.next // ignore RPOINT
   417  		var cppType string
   418  		if node != nil && node.pegRule == ruleCppType {
   419  			cppType = p.pegText(node.up.next) // ignore CPPTYPE
   420  		}
   421  		return &Type{Name: "list", ValueType: vt, CppType: cppType}, nil
   422  	default:
   423  		return &Type{}, fmt.Errorf("unknown rule: " + rul3s[node.pegRule])
   424  	}
   425  }
   426  
   427  func (p *parser) parseConstValue(node *node32) (cv *ConstValue, err error) {
   428  	node, err = checkrule(node, ruleConstValue)
   429  	if err != nil {
   430  		return nil, err
   431  	}
   432  	// DoubleConstant / IntConstant / Literal / Identifier / ConstList / ConstMap
   433  	switch node.pegRule {
   434  	case ruleDoubleConstant:
   435  		double, _ := strconv.ParseFloat(p.pegText(node), 64)
   436  		return &ConstValue{Type: ConstType_ConstDouble, TypedValue: &ConstTypedValue{Double: &double}}, nil
   437  	case ruleIntConstant:
   438  		i, err := strconv.ParseInt(p.pegText(node), 0, 64)
   439  		if err != nil {
   440  			return nil, fmt.Errorf("parseConstValue failed at '%s': %w", p.pegText(node), err)
   441  		}
   442  		return &ConstValue{Type: ConstType_ConstInt, TypedValue: &ConstTypedValue{Int: &i}}, nil
   443  	case ruleLiteral:
   444  		literal := p.pegText(node)
   445  		return &ConstValue{Type: ConstType_ConstLiteral, TypedValue: &ConstTypedValue{Literal: &literal}}, nil
   446  	case ruleIdentifier:
   447  		identifier := p.pegText(node)
   448  		return &ConstValue{Type: ConstType_ConstIdentifier, TypedValue: &ConstTypedValue{Identifier: &identifier}}, nil
   449  	case ruleConstList:
   450  		// LBRK (ConstValue ListSeparator?)* RBRK
   451  		ret := []*ConstValue{} // important: can't not be nil
   452  		for n := node.up; n != nil; n = n.next {
   453  			if n.pegRule == ruleConstValue {
   454  				val, err := p.parseConstValue(n)
   455  				if err != nil {
   456  					return nil, err
   457  				}
   458  				ret = append(ret, val)
   459  			}
   460  		}
   461  		return &ConstValue{Type: ConstType_ConstList, TypedValue: &ConstTypedValue{List: ret}}, nil
   462  	case ruleConstMap:
   463  		node = node.up
   464  		// LWING (ConstValue COLON ConstValue ListSeparator?)* RWING
   465  		ret := []*MapConstValue{} // important: can't not be nil
   466  		for n := node.next; n != nil; n = n.next {
   467  			if n.pegRule != ruleConstValue {
   468  				continue
   469  			}
   470  			k, err := p.parseConstValue(n)
   471  			if err != nil {
   472  				return nil, err
   473  			}
   474  			n = n.next.next // ignore COLON
   475  			v, err := p.parseConstValue(n)
   476  			if err != nil {
   477  				return nil, err
   478  			}
   479  			ret = append(ret, &MapConstValue{Key: k, Value: v})
   480  		}
   481  		return &ConstValue{Type: ConstType_ConstMap, TypedValue: &ConstTypedValue{Map: ret}}, nil
   482  	default:
   483  		return nil, fmt.Errorf("unknown rule: " + rul3s[node.pegRule])
   484  	}
   485  }
   486  
   487  func (p *parser) parseTypedef(node *node32) (err error) {
   488  	node, err = checkrule(node, ruleTypedef)
   489  	if err != nil {
   490  		return err
   491  	}
   492  	// TYPEDEF FieldType Identifier
   493  	node = node.next // ignore TYPEDEF
   494  	ft, err := p.parseFieldType(node)
   495  	if err != nil {
   496  		return err
   497  	}
   498  	var typd Typedef
   499  	typd.Type = ft
   500  	node = node.next
   501  	typd.Alias = p.pegText(node)
   502  	typd.ReservedComments = p.DefinitionReservedComment
   503  	p.Typedefs = append(p.Typedefs, &typd)
   504  	p.Annotations = &typd.Annotations
   505  	return nil
   506  }
   507  
   508  func (p *parser) parseEnum(node *node32) (err error) {
   509  	node, err = checkrule(node, ruleEnum)
   510  	if err != nil {
   511  		return err
   512  	}
   513  	// ENUM Identifier LWING ( ReservedComments Identifier (EQUAL IntConstant)? Annotations? ListSeparator? ReservedEndLineComments SkipLine)* RWING
   514  	node = node.next // ignore ENUM
   515  	name := p.pegText(node)
   516  	var values []*EnumValue
   517  	for n := node.next.next; n != nil; n = n.next {
   518  		valueComments := ""
   519  		if n.pegRule == ruleReservedComments {
   520  			valueComments, err = p.parseReservedComments(n)
   521  			if err != nil {
   522  				return err
   523  			}
   524  			n = n.next
   525  		}
   526  		if n.pegRule == ruleIdentifier {
   527  			var v EnumValue
   528  			v.ReservedComments = valueComments
   529  			v.Name = p.pegText(n)
   530  			if n.next.pegRule == ruleEQUAL {
   531  				n = n.next.next
   532  				v.Value, _ = strconv.ParseInt(p.pegText(n), 0, 64)
   533  			} else {
   534  				if len(values) == 0 {
   535  					v.Value = 0
   536  				} else {
   537  					v.Value = values[len(values)-1].Value + 1
   538  				}
   539  			}
   540  
   541  			if n.next.pegRule == ruleAnnotations {
   542  				n = n.next
   543  				v.Annotations, err = p.parseAnnotations(n)
   544  				if err != nil {
   545  					return err
   546  				}
   547  			}
   548  			if n.next.pegRule == ruleListSeparator {
   549  				n = n.next
   550  			}
   551  			if n.next.pegRule == ruleReservedEndLineComments && v.ReservedComments == "" {
   552  				n = n.next
   553  				v.ReservedComments, err = p.parseReservedEndLineComments(n)
   554  				if err != nil {
   555  					return err
   556  				}
   557  			}
   558  			values = append(values, &v)
   559  		}
   560  	}
   561  	e := &Enum{Name: name, Values: values}
   562  	e.ReservedComments = p.DefinitionReservedComment
   563  	p.Enums = append(p.Enums, e)
   564  	p.Annotations = &e.Annotations
   565  	return nil
   566  }
   567  
   568  func (p *parser) parseUnion(node *node32) (err error) {
   569  	node, err = checkrule(node, ruleUnion)
   570  	if err != nil {
   571  		return err
   572  	}
   573  	// UNION Identifier LWING Field* RWING
   574  	node = node.next // ignore UNION
   575  	name := p.pegText(node)
   576  	node = node.next
   577  	var fields []*Field
   578  	for n := node.next; n != nil; n = n.next {
   579  		switch n.pegRule {
   580  		case ruleField:
   581  			field, err := p.parseField(n)
   582  			if err != nil {
   583  				return err
   584  			}
   585  			if field.ID == NOTSET {
   586  				if len(fields) > 0 {
   587  					field.ID = fields[len(fields)-1].ID + 1
   588  				} else {
   589  					field.ID = 1
   590  				}
   591  			}
   592  			fields = append(fields, field)
   593  		}
   594  	}
   595  	u := &StructLike{Category: "union", Name: name, Fields: fields}
   596  	u.ReservedComments = p.DefinitionReservedComment
   597  	p.Unions = append(p.Unions, u)
   598  	p.Annotations = &u.Annotations
   599  	return nil
   600  }
   601  
   602  func (p *parser) parseStruct(node *node32) (err error) {
   603  	node, err = checkrule(node, ruleStruct)
   604  	if err != nil {
   605  		return err
   606  	}
   607  	// STRUCT Identifier LWING Field* RWING
   608  	node = node.next // ignore STRUCT
   609  	name := p.pegText(node)
   610  	node = node.next
   611  	var fields []*Field
   612  	for n := node.next; n != nil; n = n.next {
   613  		switch n.pegRule {
   614  		case ruleField:
   615  			field, err := p.parseField(n)
   616  			if err != nil {
   617  				return err
   618  			}
   619  			if field.ID == NOTSET {
   620  				if len(fields) > 0 {
   621  					field.ID = fields[len(fields)-1].ID + 1
   622  				} else {
   623  					field.ID = 1
   624  				}
   625  			}
   626  			fields = append(fields, field)
   627  		}
   628  	}
   629  	s := &StructLike{Category: "struct", Name: name, Fields: fields}
   630  	s.ReservedComments = p.DefinitionReservedComment
   631  	p.Structs = append(p.Structs, s)
   632  	p.Annotations = &s.Annotations
   633  	return nil
   634  }
   635  
   636  func (p *parser) parseException(node *node32) (err error) {
   637  	node, err = checkrule(node, ruleException)
   638  	if err != nil {
   639  		return err
   640  	}
   641  	// EXCEPTION Identifier LWING Field* RWING
   642  	node = node.next // ignore EXCEPTION
   643  	name := p.pegText(node)
   644  	var fields []*Field
   645  	for n := node.next; n != nil; n = n.next {
   646  		if n.pegRule == ruleField {
   647  			field, err := p.parseField(n)
   648  			if err != nil {
   649  				return err
   650  			}
   651  			if field.ID == NOTSET {
   652  				if len(fields) > 0 {
   653  					field.ID = fields[len(fields)-1].ID + 1
   654  				} else {
   655  					field.ID = 1
   656  				}
   657  			}
   658  			fields = append(fields, field)
   659  		}
   660  	}
   661  	e := &StructLike{Category: "exception", Name: name, Fields: fields}
   662  	e.ReservedComments = p.DefinitionReservedComment
   663  	p.Exceptions = append(p.Exceptions, e)
   664  	p.Annotations = &e.Annotations
   665  	return nil
   666  }
   667  
   668  func (p *parser) parseField(node *node32) (field *Field, err error) {
   669  	node, err = checkrule(node, ruleField)
   670  	if err != nil {
   671  		return nil, err
   672  	}
   673  	// ReservedComments Skip FieldId? FieldReq? FieldType Identifier (EQUAL ConstValue)? Annotations? ListSeparator? ReservedEndLineComments
   674  	var f Field
   675  	f.ID = NOTSET
   676  	for ; node != nil; node = node.next {
   677  		switch node.pegRule {
   678  		case ruleSkip, ruleSkipLine:
   679  			continue
   680  		case ruleReservedComments:
   681  			reservedComments, err := p.parseReservedComments(node)
   682  			if err != nil {
   683  				return nil, err
   684  			}
   685  			f.ReservedComments = reservedComments
   686  		case ruleReservedEndLineComments:
   687  			// endline comment's priority is lower than the header comment
   688  			reservedComments, err := p.parseReservedEndLineComments(node)
   689  			if err != nil {
   690  				return nil, err
   691  			}
   692  			if f.ReservedComments == "" {
   693  				f.ReservedComments = reservedComments
   694  			}
   695  		case ruleFieldId:
   696  			i, _ := strconv.Atoi(p.pegText(node))
   697  			f.ID = int32(i)
   698  		case ruleFieldReq:
   699  			require := p.pegText(node)
   700  			f.Requiredness = FieldType_Default
   701  			if require == "required" {
   702  				f.Requiredness = FieldType_Required
   703  			} else if require == "optional" {
   704  				f.Requiredness = FieldType_Optional
   705  			}
   706  		case ruleFieldType:
   707  			f.Type, err = p.parseFieldType(node)
   708  			if err != nil {
   709  				return nil, err
   710  			}
   711  		case ruleIdentifier:
   712  			f.Name = p.pegText(node)
   713  		case ruleEQUAL:
   714  			node = node.next // ignore EQUAL
   715  			f.Default, err = p.parseConstValue(node)
   716  			if err != nil {
   717  				return nil, err
   718  			}
   719  		case ruleAnnotations:
   720  			f.Annotations, err = p.parseAnnotations(node)
   721  			if err != nil {
   722  				return nil, err
   723  			}
   724  		}
   725  	}
   726  	return &f, nil
   727  }
   728  
   729  func (p *parser) parseAnnotations(node *node32) ([]*Annotation, error) {
   730  	// LPAR Annotation+ RPAR
   731  	var err error
   732  	var ret Annotations
   733  	node, err = checkrule(node, ruleAnnotations)
   734  	if err != nil {
   735  		return nil, err
   736  	}
   737  	for node = node.next; node != nil; node = node.next {
   738  		if node.pegRule == ruleAnnotation {
   739  			k, v, err := p.parseAnnotation(node)
   740  			if err != nil {
   741  				return nil, err
   742  			}
   743  			ret.Append(k, v)
   744  		}
   745  	}
   746  	return ret, nil
   747  }
   748  
   749  func (p *parser) parseAnnotation(node *node32) (k, v string, err error) {
   750  	// Identifier EQUAL Literal ListSeparator?
   751  	node, err = checkrule(node, ruleAnnotation)
   752  	if err != nil {
   753  		return "", "", err
   754  	}
   755  
   756  	k = p.pegText(node) // Identifier
   757  	node = node.next.next
   758  	v = p.pegText(node) // Literal
   759  	return k, v, nil
   760  }
   761  
   762  func (p *parser) parseService(node *node32) (err error) {
   763  	node, err = checkrule(node, ruleService)
   764  	if err != nil {
   765  		return err
   766  	}
   767  	// SERVICE Identifier ( EXTENDS Identifier )? LWING Function* RWING
   768  	var s Service
   769  	node = node.next // ignore SERVICE
   770  	s.Name = p.pegText(node)
   771  	node = node.next
   772  	if node.pegRule == ruleEXTENDS {
   773  		s.Extends = p.pegText(node)
   774  		node = node.next
   775  	}
   776  	for node = node.next; node != nil; node = node.next {
   777  		if node.pegRule == ruleFunction {
   778  			fu, err := p.parseFunction(node)
   779  			if err != nil {
   780  				return err
   781  			}
   782  			s.Functions = append(s.Functions, fu)
   783  		}
   784  	}
   785  	s.ReservedComments = p.DefinitionReservedComment
   786  	p.Services = append(p.Services, &s)
   787  	p.Annotations = &s.Annotations
   788  	return nil
   789  }
   790  
   791  func (p *parser) parseFunction(node *node32) (fu *Function, err error) {
   792  	node, err = checkrule(node, ruleFunction)
   793  	if err != nil {
   794  		return nil, err
   795  	}
   796  	// ReservedComments ONEWAY? FunctionType Identifier LPAR Field* RPAR Throws? Annotations? ListSeparator?
   797  	var f Function
   798  	for ; node != nil; node = node.next {
   799  		switch node.pegRule {
   800  		case ruleReservedComments:
   801  			reservedComments, err := p.parseReservedComments(node)
   802  			if err != nil {
   803  				return nil, err
   804  			}
   805  			f.ReservedComments = reservedComments
   806  		case ruleONEWAY:
   807  			f.Oneway = true
   808  		case ruleFunctionType:
   809  			n := node.up
   810  			if n.pegRule == ruleFieldType {
   811  				f.FunctionType, err = p.parseFieldType(n)
   812  				if err != nil {
   813  					return nil, err
   814  				}
   815  			} else if n.pegRule == ruleVOID {
   816  				f.Void = true
   817  				f.FunctionType = &Type{Name: "void"}
   818  			}
   819  		case ruleIdentifier:
   820  			f.Name = p.pegText(node)
   821  		case ruleField:
   822  			field, err := p.parseField(node)
   823  			if err != nil {
   824  				return nil, err
   825  			}
   826  			f.Arguments = addField(f.Arguments, field)
   827  		case ruleThrows:
   828  			f.Throws, err = p.parseThrows(node)
   829  			if err != nil {
   830  				return nil, err
   831  			}
   832  		case ruleAnnotations:
   833  			f.Annotations, err = p.parseAnnotations(node)
   834  			if err != nil {
   835  				return nil, err
   836  			}
   837  		}
   838  	}
   839  	return &f, nil
   840  }
   841  
   842  func (p *parser) parseThrows(node *node32) (fs []*Field, err error) {
   843  	node, err = checkrule(node, ruleThrows)
   844  	if err != nil {
   845  		return nil, err
   846  	}
   847  	// THROWS LPAR Field* RPAR
   848  	node = node.next // ignore THROWS
   849  	var fields []*Field
   850  	for ; node != nil; node = node.next {
   851  		if node.pegRule == ruleField {
   852  			field, err := p.parseField(node)
   853  			if err != nil {
   854  				return nil, err
   855  			}
   856  			field.Requiredness = FieldType_Optional
   857  			fields = addField(fields, field)
   858  		}
   859  	}
   860  	return fields, nil
   861  }
   862  
   863  func (p *parser) parseReservedComments(node *node32) (ReservedComments string, err error) {
   864  	node, err = checkrule(node, ruleReservedComments)
   865  	if err != nil {
   866  		return "", err
   867  	}
   868  	// Skip
   869  	node = node.up
   870  	// (Space / Comment)*
   871  	var comments []string
   872  	for ; node != nil; node = node.next {
   873  		if node.pegRule == ruleComment {
   874  			comment := strings.TrimRight(string(p.buffer[int(node.up.begin):int(node.up.end)]), "\r\n")
   875  			if strings.HasPrefix(comment, "#") {
   876  				comment = strings.TrimPrefix(comment, "#")
   877  				comment = "//" + comment
   878  			}
   879  			if comment != "" {
   880  				comments = append(comments, comment)
   881  			}
   882  		}
   883  	}
   884  	return strings.Join(comments, "\n"), nil
   885  }
   886  
   887  func (p *parser) parseReservedEndLineComments(node *node32) (ReservedComments string, err error) {
   888  	node, err = checkrule(node, ruleReservedEndLineComments)
   889  	if err != nil {
   890  		return "", err
   891  	}
   892  	// Skip
   893  	node = node.up
   894  	// (Space / Comment)*
   895  	var comments []string
   896  	for ; node != nil; node = node.next {
   897  		if node.pegRule == ruleComment {
   898  			comment := strings.TrimRight(string(p.buffer[int(node.up.begin):int(node.up.end)]), "\r\n")
   899  			if strings.HasPrefix(comment, "#") {
   900  				comment = strings.TrimPrefix(comment, "#")
   901  				comment = "//" + comment
   902  			}
   903  			if comment != "" {
   904  				comments = append(comments, comment)
   905  			}
   906  		}
   907  	}
   908  	return strings.Join(comments, "\n"), nil
   909  }