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