github.com/jmigpin/editor@v1.6.0/util/parseutil/lrparser/predefineds.go (about)

     1  package lrparser
     2  
     3  import (
     4  	"fmt"
     5  )
     6  
     7  func setupPredefineds(ri *RuleIndex) error {
     8  	if err := ri.setSingletonRule(nilRule); err != nil {
     9  		return err
    10  	}
    11  	if err := ri.setSingletonRule(endRule); err != nil {
    12  		return nil
    13  	}
    14  
    15  	if err := setupAnyRuneFn(ri); err != nil {
    16  		return err
    17  	}
    18  	if err := setupQuotedStringFn(ri); err != nil {
    19  		return err
    20  	}
    21  	if err := setupDropRunesFn(ri); err != nil {
    22  		return err
    23  	}
    24  	if err := setupEscapeAnyFn(ri); err != nil {
    25  		return err
    26  	}
    27  
    28  	// also add these rules to the ruleindex
    29  	gram := `
    30  		// § = don't print child rules when printing the ruleindex (helpful for tests)
    31  		§digit = ("09")-;
    32  		§digits = (digit)+;
    33  		§letter = ("az")- | ("AZ")-;
    34  		§anyRuneFirst = @anyRune(-10000);
    35  		§anyRuneLast = @anyRune(10000);
    36  	`
    37  	gp0 := newGrammarParser(ri)
    38  	fset0 := NewFileSetFromBytes([]byte(gram))
    39  	if err := gp0.parse(fset0); err != nil {
    40  		return err
    41  	}
    42  
    43  	return nil
    44  }
    45  
    46  //----------
    47  
    48  func setupAnyRuneFn(ri *RuleIndex) error {
    49  	name := "anyRune"
    50  	fn := func(args ProcRuleArgs) (Rule, error) {
    51  		parseOrder, err := args.Int(0)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  		fr := &FuncRule{name: name, parseOrder: parseOrder}
    56  		fr.fn = func(ps *PState) error {
    57  			if _, err := ps.ReadRune(); err != nil {
    58  				return err // fails at eof
    59  			}
    60  			return nil
    61  		}
    62  		return fr, nil
    63  	}
    64  	return ri.setProcRuleFn(name, fn) // grammar call name
    65  }
    66  
    67  func setupQuotedStringFn(ri *RuleIndex) error {
    68  	fn := func(args ProcRuleArgs) (Rule, error) {
    69  		// arg: parse order
    70  		parseOrder, err := args.Int(0)
    71  		if err != nil {
    72  			return nil, err
    73  		}
    74  		// arg: escape rune
    75  		sr, err := args.MergedStringRule(1)
    76  		if err != nil {
    77  			return nil, err
    78  		}
    79  		if len(sr.runes) != 1 {
    80  			return nil, fmt.Errorf("expecting escape to be 1 rune only")
    81  		}
    82  		esc := sr.runes[0]
    83  		// arg
    84  		maxLen1, err := args.Int(2)
    85  		if err != nil {
    86  			return nil, err
    87  		}
    88  		// arg
    89  		maxLen2, err := args.Int(3)
    90  		if err != nil {
    91  			return nil, err
    92  		}
    93  
    94  		name := fmt.Sprintf("quotedString(%q,%v,%v)", esc, maxLen1, maxLen2)
    95  		fr := &FuncRule{name: name, parseOrder: parseOrder}
    96  		fr.fn = func(ps *PState) error {
    97  			return ps.M.QuotedString2(esc, int(maxLen1), int(maxLen2))
    98  		}
    99  		return fr, nil
   100  	}
   101  	return ri.setProcRuleFn("quotedString", fn) // grammar call name
   102  }
   103  
   104  func setupDropRunesFn(ri *RuleIndex) error {
   105  	fn := func(args ProcRuleArgs) (Rule, error) {
   106  		if len(args) < 2 {
   107  			return nil, fmt.Errorf("expecting at least 2 args")
   108  		}
   109  		srs := []*StringRule{}
   110  		for i, _ := range args {
   111  			sr, err := args.MergedStringRule(i)
   112  			if err != nil {
   113  				return nil, err
   114  			}
   115  			if sr.typ != stringRTOr {
   116  				return nil, fmt.Errorf("expecting type %q: %v", stringRTOr, sr)
   117  			}
   118  			if len(sr.rranges) != 0 {
   119  				return nil, fmt.Errorf("not expecting ranges: %v", sr)
   120  			}
   121  			srs = append(srs, sr)
   122  		}
   123  		// join rules to remove
   124  		m2 := map[rune]bool{}
   125  		for i := 1; i < len(srs); i++ {
   126  			for _, ru := range srs[i].runes {
   127  				m2[ru] = true
   128  			}
   129  		}
   130  		// remove from first rule
   131  		rs := []rune{}
   132  		for _, ru := range srs[0].runes {
   133  			if m2[ru] {
   134  				continue
   135  			}
   136  			rs = append(rs, ru)
   137  		}
   138  		sr3 := *srs[0] // copy
   139  		sr3.runes = rs
   140  		return &sr3, nil
   141  	}
   142  	return ri.setProcRuleFn("dropRunes", fn) // grammar call name
   143  }
   144  
   145  func setupEscapeAnyFn(ri *RuleIndex) error {
   146  	// allows to rewind in case of failure
   147  	fn := func(args ProcRuleArgs) (Rule, error) {
   148  		// arg
   149  		parseOrder, err := args.Int(0)
   150  		if err != nil {
   151  			return nil, err
   152  		}
   153  		// arg
   154  		sr, err := args.MergedStringRule(1)
   155  		if err != nil {
   156  			return nil, err
   157  		}
   158  		if len(sr.runes) != 1 {
   159  			return nil, fmt.Errorf("expecting rule with one rune")
   160  		}
   161  		esc := sr.runes[0]
   162  
   163  		name := fmt.Sprintf("escapeAny(%q)", esc)
   164  		fr := &FuncRule{name: name, parseOrder: parseOrder}
   165  		fr.fn = func(ps *PState) error {
   166  			return ps.M.EscapeAny(esc)
   167  		}
   168  		return fr, nil
   169  	}
   170  	return ri.setProcRuleFn("escapeAny", fn) // grammar call name
   171  }
   172  
   173  //----------
   174  //----------
   175  //----------
   176  
   177  //// commented: using grammar definition
   178  //func parseLetter(ps *PState) error {
   179  //	ps2 := ps.Copy()
   180  //	ru, err := ps2.ReadRune()
   181  //	if err != nil {
   182  //		return err
   183  //	}
   184  //	if !unicode.IsLetter(ru) {
   185  //		return errors.New("not a letter")
   186  //	}
   187  //	ps.Set(ps2)
   188  //	return nil
   189  //}
   190  
   191  //// commented: using grammar definition
   192  //func parseDigit(ps *PState) error {
   193  //	ps2 := ps.Copy()
   194  //	ru, err := ps2.ReadRune()
   195  //	if err != nil {
   196  //		return err
   197  //	}
   198  //	if !unicode.IsDigit(ru) {
   199  //		return errors.New("not a digit")
   200  //	}
   201  //	ps.Set(ps2)
   202  //	return nil
   203  //}
   204  
   205  // commented: using this won't recognize "digit" in "digits", which won't allow to parse correctly in some cases
   206  //func parseDigits(ps *PState) error {
   207  //	for i := 0; ; i++ {
   208  //		ps2 := ps.copy()
   209  //		ru, err := ps2.readRune()
   210  //		if err != nil {
   211  //			if i > 0 {
   212  //				return nil
   213  //			}
   214  //			return err
   215  //		}
   216  //		if !unicode.IsDigit(ru) {
   217  //			if i == 0 {
   218  //				return errors.New("not a digit")
   219  //			}
   220  //			return nil
   221  //		}
   222  //		ps.set(ps2)
   223  //	}
   224  //}