...

Source file src/github.com/gobwas/glob/syntax/ast/parser.go

Documentation: github.com/gobwas/glob/syntax/ast

     1  package ast
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/gobwas/glob/syntax/lexer"
     7  	"unicode/utf8"
     8  )
     9  
    10  type Lexer interface {
    11  	Next() lexer.Token
    12  }
    13  
    14  type parseFn func(*Node, Lexer) (parseFn, *Node, error)
    15  
    16  func Parse(lexer Lexer) (*Node, error) {
    17  	var parser parseFn
    18  
    19  	root := NewNode(KindPattern, nil)
    20  
    21  	var (
    22  		tree *Node
    23  		err  error
    24  	)
    25  	for parser, tree = parserMain, root; parser != nil; {
    26  		parser, tree, err = parser(tree, lexer)
    27  		if err != nil {
    28  			return nil, err
    29  		}
    30  	}
    31  
    32  	return root, nil
    33  }
    34  
    35  func parserMain(tree *Node, lex Lexer) (parseFn, *Node, error) {
    36  	for {
    37  		token := lex.Next()
    38  		switch token.Type {
    39  		case lexer.EOF:
    40  			return nil, tree, nil
    41  
    42  		case lexer.Error:
    43  			return nil, tree, errors.New(token.Raw)
    44  
    45  		case lexer.Text:
    46  			Insert(tree, NewNode(KindText, Text{token.Raw}))
    47  			return parserMain, tree, nil
    48  
    49  		case lexer.Any:
    50  			Insert(tree, NewNode(KindAny, nil))
    51  			return parserMain, tree, nil
    52  
    53  		case lexer.Super:
    54  			Insert(tree, NewNode(KindSuper, nil))
    55  			return parserMain, tree, nil
    56  
    57  		case lexer.Single:
    58  			Insert(tree, NewNode(KindSingle, nil))
    59  			return parserMain, tree, nil
    60  
    61  		case lexer.RangeOpen:
    62  			return parserRange, tree, nil
    63  
    64  		case lexer.TermsOpen:
    65  			a := NewNode(KindAnyOf, nil)
    66  			Insert(tree, a)
    67  
    68  			p := NewNode(KindPattern, nil)
    69  			Insert(a, p)
    70  
    71  			return parserMain, p, nil
    72  
    73  		case lexer.Separator:
    74  			p := NewNode(KindPattern, nil)
    75  			Insert(tree.Parent, p)
    76  
    77  			return parserMain, p, nil
    78  
    79  		case lexer.TermsClose:
    80  			return parserMain, tree.Parent.Parent, nil
    81  
    82  		default:
    83  			return nil, tree, fmt.Errorf("unexpected token: %s", token)
    84  		}
    85  	}
    86  	return nil, tree, fmt.Errorf("unknown error")
    87  }
    88  
    89  func parserRange(tree *Node, lex Lexer) (parseFn, *Node, error) {
    90  	var (
    91  		not   bool
    92  		lo    rune
    93  		hi    rune
    94  		chars string
    95  	)
    96  	for {
    97  		token := lex.Next()
    98  		switch token.Type {
    99  		case lexer.EOF:
   100  			return nil, tree, errors.New("unexpected end")
   101  
   102  		case lexer.Error:
   103  			return nil, tree, errors.New(token.Raw)
   104  
   105  		case lexer.Not:
   106  			not = true
   107  
   108  		case lexer.RangeLo:
   109  			r, w := utf8.DecodeRuneInString(token.Raw)
   110  			if len(token.Raw) > w {
   111  				return nil, tree, fmt.Errorf("unexpected length of lo character")
   112  			}
   113  			lo = r
   114  
   115  		case lexer.RangeBetween:
   116  			//
   117  
   118  		case lexer.RangeHi:
   119  			r, w := utf8.DecodeRuneInString(token.Raw)
   120  			if len(token.Raw) > w {
   121  				return nil, tree, fmt.Errorf("unexpected length of lo character")
   122  			}
   123  
   124  			hi = r
   125  
   126  			if hi < lo {
   127  				return nil, tree, fmt.Errorf("hi character '%s' should be greater than lo '%s'", string(hi), string(lo))
   128  			}
   129  
   130  		case lexer.Text:
   131  			chars = token.Raw
   132  
   133  		case lexer.RangeClose:
   134  			isRange := lo != 0 && hi != 0
   135  			isChars := chars != ""
   136  
   137  			if isChars == isRange {
   138  				return nil, tree, fmt.Errorf("could not parse range")
   139  			}
   140  
   141  			if isRange {
   142  				Insert(tree, NewNode(KindRange, Range{
   143  					Lo:  lo,
   144  					Hi:  hi,
   145  					Not: not,
   146  				}))
   147  			} else {
   148  				Insert(tree, NewNode(KindList, List{
   149  					Chars: chars,
   150  					Not:   not,
   151  				}))
   152  			}
   153  
   154  			return parserMain, tree, nil
   155  		}
   156  	}
   157  }
   158  

View as plain text