github.com/jmigpin/editor@v1.6.0/util/parseutil/lrparser/grammarparser.go (about) 1 package lrparser 2 3 import ( 4 "errors" 5 "fmt" 6 "strconv" 7 ) 8 9 type grammarParser struct { 10 ri *RuleIndex 11 } 12 13 func newGrammarParser(ri *RuleIndex) *grammarParser { 14 gp := &grammarParser{ri: ri} 15 return gp 16 } 17 func (gp *grammarParser) parse(fset *FileSet) error { 18 ps := NewPState(fset.Src) 19 err := gp.parse2(ps) 20 if err != nil { 21 return fset.Error2(err, ps.Pos) 22 } 23 return nil 24 } 25 func (gp *grammarParser) parse2(ps *PState) error { 26 for { 27 ok, err := gp.parse3(ps) 28 if err != nil { 29 return err 30 } 31 if !ok { 32 return nil 33 } 34 } 35 } 36 func (gp *grammarParser) parse3(ps *PState) (bool, error) { 37 gp.parseOptionalSpacesOrComments(ps) 38 if ps.M.Eof() { 39 return false, nil 40 } 41 if err := gp.parseDefRule(ps); err != nil { 42 return false, err 43 } 44 return true, nil 45 } 46 func (gp *grammarParser) parseDefRule(ps *PState) error { 47 pos0 := ps.KeepPos() 48 49 // options 50 isStart := false 51 if err := ps.M.Sequence(defRuleStartSym); err == nil { 52 isStart = true 53 } 54 isNoPrint := false 55 if err := ps.M.Sequence(defRuleNoPrintSym); err == nil { 56 isNoPrint = true 57 } 58 59 // rule name 60 name, err := gp.parseName(ps) 61 if err != nil { 62 return err 63 } 64 if gp.ri.has(name) { 65 return fmt.Errorf("rule already defined: %v", name) 66 } 67 68 gp.parseOptionalSpacesOrComments(ps) 69 70 if err := ps.M.Rune('='); err != nil { 71 return errors.New("expecting =") 72 } 73 74 gp.parseOptionalSpacesOrComments(ps) 75 76 if err := gp.parseItemRule(ps); err != nil { 77 return err 78 } 79 80 gp.parseOptionalSpacesOrComments(ps) 81 82 if err := ps.M.Rune(';'); err != nil { 83 return errors.New("expecting close rule \";\"?") 84 } 85 86 // setup 87 dr := &DefRule{name: name, isStart: isStart, isNoPrint: isNoPrint} 88 dr.setOnlyChild(ps.Node.(Rule)) 89 dr.SetPos(pos0.Pos, ps.Pos) 90 gp.ri.set(dr.name, dr) 91 ps.Node = dr 92 93 return nil 94 } 95 func (gp *grammarParser) parseName(ps *PState) (string, error) { 96 u := "[_a-zA-Z][_a-zA-Z0-9$]*" 97 pos0 := ps.KeepPos() 98 if err := ps.M.RegexpFromStartCached(u, 100); err != nil { 99 return "", err 100 } 101 name := string(pos0.Bytes()) 102 return name, nil 103 } 104 105 //---------- 106 107 func (gp *grammarParser) parseItemRule(ps *PState) error { 108 // NOTE: taking into consideration precedence tree construction 109 110 if err, ok := gp.parseIfRule(ps); ok { 111 return err 112 } 113 return gp.parseOrRule(ps) 114 } 115 116 //---------- 117 118 func (gp *grammarParser) parseIfRule(ps *PState) (error, bool) { 119 if err := ps.M.Sequence("if "); err != nil { 120 return err, false // not an ifrule 121 } 122 return gp.parseIfRule2(ps), true 123 } 124 func (gp *grammarParser) parseIfRule2(ps *PState) error { 125 i0 := ps.Pos 126 127 _, ok := gp.parseRefRule(ps) 128 if !ok { 129 return fmt.Errorf("expecting name") 130 } 131 nameRef := ps.Node.(Rule) 132 133 // then 134 gp.parseOptionalSpacesOrComments(ps) 135 if err := ps.M.Rune('?'); err != nil { 136 return fmt.Errorf("expecting '?'") 137 } 138 gp.parseOptionalSpacesOrComments(ps) 139 if err := gp.parseItemRule(ps); err != nil { 140 return err 141 } 142 thenRule := ps.Node.(Rule) 143 144 // else 145 gp.parseOptionalSpacesOrComments(ps) 146 if err := ps.M.Rune(':'); err != nil { 147 return fmt.Errorf("expecting ':'") 148 } 149 gp.parseOptionalSpacesOrComments(ps) 150 if err := gp.parseItemRule(ps); err != nil { 151 return err 152 } 153 elseRule := ps.Node.(Rule) 154 155 // setup 156 res := &IfRule{} 157 res.addChilds(nameRef) 158 res.addChilds(thenRule) 159 res.addChilds(elseRule) 160 res.SetPos(i0, ps.Pos) 161 ps.Node = res 162 163 return nil 164 } 165 166 //---------- 167 168 func (gp *grammarParser) parseOrRule(ps *PState) error { 169 pos0 := ps.KeepPos() 170 w := []Rule{} 171 for i := 0; ; i++ { 172 // handle separator 173 if i > 0 { 174 gp.parseOptionalSpacesOrComments(ps) 175 pos3 := ps.KeepPos() 176 if err := ps.M.Rune('|'); err != nil { 177 pos3.Restore() 178 if i == 1 { 179 return nil // ok, just not an OR 180 } 181 182 res := &OrRule{} 183 res.childs_ = w 184 res.SetPos(pos0.Pos, ps.Pos) 185 ps.Node = res 186 187 return nil // ok 188 } 189 190 gp.parseOptionalSpacesOrComments(ps) 191 } 192 193 // precedence tree construction ("and" is higher vs "or") 194 if err := gp.parseAndRule(ps); err != nil { 195 if i == 0 { 196 return err // fail, no rule 197 } 198 return err // fail, not expecting error after sep 199 } 200 201 resRule := ps.Node.(Rule) 202 w = append(w, resRule) 203 } 204 } 205 func (gp *grammarParser) parseAndRule(ps *PState) error { 206 pos0 := ps.KeepPos() 207 w := []Rule{} 208 for i := 0; ; i++ { 209 // handle separator 210 pos2 := ps.KeepPos() 211 if i > 0 { 212 gp.parseOptionalSpacesOrComments(ps) 213 } 214 215 if err := gp.parseBasicItemRule(ps); err != nil { 216 if i == 0 { 217 return err // fail, no rule 218 } 219 if i == 1 { 220 return nil // ok, just not an AND 221 } 222 pos2.Restore() 223 break // ok, don't include the spaces 224 } 225 226 resRule := ps.Node.(Rule) 227 w = append(w, resRule) 228 } 229 230 res := &AndRule{} 231 res.childs_ = w 232 res.SetPos(pos0.Pos, ps.Pos) 233 ps.Node = res 234 235 return nil 236 } 237 238 //---------- 239 240 func (gp *grammarParser) parseBasicItemRule(ps *PState) error { 241 if err, ok := gp.parseProcRule(ps); ok { 242 return err 243 } 244 if err, ok := gp.parseRefRule(ps); ok { 245 return err 246 } 247 if err, ok := gp.parseStringRule(ps); ok { 248 return err 249 } 250 if err, ok := gp.parseParenRule(ps); ok { 251 return err 252 } 253 return errors.New("unable to parse basic item") 254 } 255 func (gp *grammarParser) parseProcRule(ps *PState) (error, bool) { 256 i0 := ps.Pos 257 // header 258 callRuleSym := "@" 259 if err := ps.M.Sequence(callRuleSym); err != nil { 260 return err, false 261 } 262 263 // name 264 name, err := gp.parseName(ps) 265 if err != nil { 266 return err, true 267 } 268 269 // args 270 if err := ps.M.Rune('('); err != nil { 271 return err, true 272 } 273 parseProcRuleArg := func() (ProcRuleArg, error) { 274 err := gp.parseItemRule(ps) 275 if err != nil { 276 // special case: try to parse an int as a direct arg 277 if v, err, ok := gp.parseInt(ps); ok && err == nil { 278 return v, nil 279 } 280 } 281 return ps.Node, err 282 } 283 args := []ProcRuleArg{} 284 for i := 0; ; i++ { 285 arg, err := parseProcRuleArg() 286 if err != nil { 287 if i == 0 { 288 break 289 } 290 return err, true 291 } 292 args = append(args, arg) 293 gp.parseOptionalSpacesOrComments(ps) 294 if err := ps.M.Rune(','); err != nil { 295 break 296 } 297 } 298 if err := ps.M.Rune(')'); err != nil { 299 return err, true 300 } 301 302 res := &ProcRule{} 303 res.name = name 304 res.args = args 305 res.SetPos(i0, ps.Pos) 306 ps.Node = res 307 308 return nil, true 309 } 310 func (gp *grammarParser) parseRefRule(ps *PState) (error, bool) { 311 i0 := ps.Pos 312 name, err := gp.parseName(ps) 313 if err != nil { 314 return nil, false // err is lost 315 } 316 res := &RefRule{name: name} 317 res.SetPos(i0, ps.Pos) 318 ps.Node = res 319 return nil, true 320 } 321 322 func (gp *grammarParser) parseStringRule(ps *PState) (error, bool) { 323 pos0 := ps.KeepPos() 324 325 esc := '\\' // alows to escape the quote 326 if err := ps.M.StringSection("\"", esc, true, 1000, false); err != nil { 327 return nil, false 328 } 329 330 // needed: ex: transforms "\n" (2 runes) into a single '\n' 331 str := string(pos0.Bytes()) 332 u, err := strconv.Unquote(str) 333 if err != nil { 334 return err, true 335 } 336 337 sr := &StringRule{} 338 sr.runes = []rune(u) 339 sr.SetPos(pos0.Pos, ps.Pos) 340 ps.Node = sr 341 return nil, true 342 } 343 func (gp *grammarParser) parseParenRule(ps *PState) (error, bool) { 344 pos0 := ps.KeepPos() 345 if err := ps.M.Rune('('); err != nil { 346 return err, false 347 } 348 gp.parseOptionalSpacesOrComments(ps) 349 if err := gp.parseItemRule(ps); err != nil { 350 return err, true 351 } 352 gp.parseOptionalSpacesOrComments(ps) 353 ruleX := ps.Node.(Rule) 354 if err := ps.M.Rune(')'); err != nil { 355 return err, true 356 } 357 358 // option rune 359 pt := parenRTNone 360 pos2 := ps.KeepPos() 361 ru, err := ps.ReadRune() 362 if err == nil { 363 u := parenRType(ru) 364 switch u { 365 case parenRTNone, 366 parenRTOptional, 367 parenRTZeroOrMore, 368 parenRTOneOrMore, 369 parenRTStrMid, 370 parenRTStrOr, 371 parenRTStrOrRange, 372 parenRTStrOrNeg: 373 pt = u 374 default: 375 pos2.Restore() 376 } 377 } 378 379 u := &ParenRule{typ: pt} 380 u.setOnlyChild(ruleX) 381 u.SetPos(pos0.Pos, ps.Pos) 382 ps.Node = u 383 384 return nil, true 385 } 386 387 //---------- 388 389 func (gp *grammarParser) parseInt(ps *PState) (int, error, bool) { 390 pos0 := ps.KeepPos() 391 if err := ps.M.Integer(); err != nil { 392 return 0, err, false 393 } 394 395 u := string(pos0.Bytes()) 396 v, err := strconv.ParseInt(u, 10, 64) 397 if err != nil { 398 return 0, err, true 399 } 400 401 n := &BasicPNode{} 402 n.SetPos(pos0.Pos, ps.Pos) 403 ps.Node = n 404 return int(v), nil, true 405 } 406 407 //---------- 408 409 func (gp *grammarParser) parseOptionalSpacesOrComments(ps *PState) { 410 for { 411 if ps.M.SpacesIncludingNL() { 412 continue 413 } 414 if gp.parseComments(ps) { 415 continue 416 } 417 break 418 } 419 } 420 func (gp *grammarParser) parseComments(ps *PState) bool { 421 if err := ps.M.Rune('#'); err == nil { 422 _ = ps.M.ToNLIncludeOrEnd(0) 423 return true 424 } 425 if err := ps.M.Sequence("//"); err == nil { 426 _ = ps.M.ToNLIncludeOrEnd(0) 427 return true 428 } 429 return false 430 } 431 432 //func (gp *grammarParser) parseEmptyLine(ps *PState) bool { 433 // if err := ps.MatchRune('\n'); err == nil { 434 // return true 435 // } 436 // return false 437 //}