github.com/jhump/protocompile@v0.0.0-20221021153901-4f6f732835e8/parser/ast.go (about)

     1  package parser
     2  
     3  import "github.com/jhump/protocompile/ast"
     4  
     5  // the types below are accumulator types: linked lists that are
     6  // constructed during parsing and then converted to slices of AST nodes
     7  // once the whole list has been parsed
     8  // TODO: change grammer to use slices of nodes instead of these constructions
     9  
    10  type compactOptionList struct {
    11  	option *ast.OptionNode
    12  	comma  *ast.RuneNode
    13  	next   *compactOptionList
    14  }
    15  
    16  func (list *compactOptionList) toNodes() ([]*ast.OptionNode, []*ast.RuneNode) {
    17  	l := 0
    18  	for cur := list; cur != nil; cur = cur.next {
    19  		l++
    20  	}
    21  	opts := make([]*ast.OptionNode, l)
    22  	commas := make([]*ast.RuneNode, l-1)
    23  	for cur, i := list, 0; cur != nil; cur, i = cur.next, i+1 {
    24  		opts[i] = cur.option
    25  		if cur.comma != nil {
    26  			commas[i] = cur.comma
    27  		}
    28  	}
    29  	return opts, commas
    30  }
    31  
    32  type stringList struct {
    33  	str  *ast.StringLiteralNode
    34  	next *stringList
    35  }
    36  
    37  func (list *stringList) toStringValueNode() ast.StringValueNode {
    38  	if list.next == nil {
    39  		// single name
    40  		return list.str
    41  	}
    42  
    43  	l := 0
    44  	for cur := list; cur != nil; cur = cur.next {
    45  		l++
    46  	}
    47  	strs := make([]*ast.StringLiteralNode, l)
    48  	for cur, i := list, 0; cur != nil; cur, i = cur.next, i+1 {
    49  		strs[i] = cur.str
    50  	}
    51  	return ast.NewCompoundLiteralStringNode(strs...)
    52  }
    53  
    54  type nameList struct {
    55  	name  ast.StringValueNode
    56  	comma *ast.RuneNode
    57  	next  *nameList
    58  }
    59  
    60  func (list *nameList) toNodes() ([]ast.StringValueNode, []*ast.RuneNode) {
    61  	l := 0
    62  	for cur := list; cur != nil; cur = cur.next {
    63  		l++
    64  	}
    65  	names := make([]ast.StringValueNode, l)
    66  	commas := make([]*ast.RuneNode, l-1)
    67  	for cur, i := list, 0; cur != nil; cur, i = cur.next, i+1 {
    68  		names[i] = cur.name
    69  		if cur.comma != nil {
    70  			commas[i] = cur.comma
    71  		}
    72  	}
    73  	return names, commas
    74  }
    75  
    76  type rangeList struct {
    77  	rng   *ast.RangeNode
    78  	comma *ast.RuneNode
    79  	next  *rangeList
    80  }
    81  
    82  func (list *rangeList) toNodes() ([]*ast.RangeNode, []*ast.RuneNode) {
    83  	l := 0
    84  	for cur := list; cur != nil; cur = cur.next {
    85  		l++
    86  	}
    87  	ranges := make([]*ast.RangeNode, l)
    88  	commas := make([]*ast.RuneNode, l-1)
    89  	for cur, i := list, 0; cur != nil; cur, i = cur.next, i+1 {
    90  		ranges[i] = cur.rng
    91  		if cur.comma != nil {
    92  			commas[i] = cur.comma
    93  		}
    94  	}
    95  	return ranges, commas
    96  }
    97  
    98  type valueList struct {
    99  	val   ast.ValueNode
   100  	comma *ast.RuneNode
   101  	next  *valueList
   102  }
   103  
   104  func (list *valueList) toNodes() ([]ast.ValueNode, []*ast.RuneNode) {
   105  	if list == nil {
   106  		return nil, nil
   107  	}
   108  	l := 0
   109  	for cur := list; cur != nil; cur = cur.next {
   110  		l++
   111  	}
   112  	vals := make([]ast.ValueNode, l)
   113  	commas := make([]*ast.RuneNode, l-1)
   114  	for cur, i := list, 0; cur != nil; cur, i = cur.next, i+1 {
   115  		vals[i] = cur.val
   116  		if cur.comma != nil {
   117  			commas[i] = cur.comma
   118  		}
   119  	}
   120  	return vals, commas
   121  }
   122  
   123  type fieldRefList struct {
   124  	ref  *ast.FieldReferenceNode
   125  	dot  *ast.RuneNode
   126  	next *fieldRefList
   127  }
   128  
   129  func (list *fieldRefList) toNodes() ([]*ast.FieldReferenceNode, []*ast.RuneNode) {
   130  	l := 0
   131  	for cur := list; cur != nil; cur = cur.next {
   132  		l++
   133  	}
   134  	refs := make([]*ast.FieldReferenceNode, l)
   135  	dots := make([]*ast.RuneNode, l-1)
   136  	for cur, i := list, 0; cur != nil; cur, i = cur.next, i+1 {
   137  		refs[i] = cur.ref
   138  		if cur.dot != nil {
   139  			dots[i] = cur.dot
   140  		}
   141  	}
   142  
   143  	return refs, dots
   144  }
   145  
   146  type identList struct {
   147  	ident *ast.IdentNode
   148  	dot   *ast.RuneNode
   149  	next  *identList
   150  }
   151  
   152  func (list *identList) toIdentValueNode(leadingDot *ast.RuneNode) ast.IdentValueNode {
   153  	if list.next == nil && leadingDot == nil {
   154  		// single name
   155  		return list.ident
   156  	}
   157  
   158  	l := 0
   159  	for cur := list; cur != nil; cur = cur.next {
   160  		l++
   161  	}
   162  	idents := make([]*ast.IdentNode, l)
   163  	dots := make([]*ast.RuneNode, l-1)
   164  	for cur, i := list, 0; cur != nil; cur, i = cur.next, i+1 {
   165  		idents[i] = cur.ident
   166  		if cur.dot != nil {
   167  			dots[i] = cur.dot
   168  		}
   169  	}
   170  
   171  	return ast.NewCompoundIdentNode(leadingDot, idents, dots)
   172  }
   173  
   174  type messageFieldEntry struct {
   175  	field     *ast.MessageFieldNode
   176  	delimiter *ast.RuneNode
   177  }
   178  
   179  type messageFieldList struct {
   180  	field *messageFieldEntry
   181  	next  *messageFieldList
   182  }
   183  
   184  func (list *messageFieldList) toNodes() ([]*ast.MessageFieldNode, []*ast.RuneNode) {
   185  	if list == nil {
   186  		return nil, nil
   187  	}
   188  	l := 0
   189  	for cur := list; cur != nil; cur = cur.next {
   190  		l++
   191  	}
   192  	fields := make([]*ast.MessageFieldNode, l)
   193  	delimiters := make([]*ast.RuneNode, l)
   194  	for cur, i := list, 0; cur != nil; cur, i = cur.next, i+1 {
   195  		fields[i] = cur.field.field
   196  		if cur.field.delimiter != nil {
   197  			delimiters[i] = cur.field.delimiter
   198  		}
   199  	}
   200  
   201  	return fields, delimiters
   202  }