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 //}