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

     1  package lrparser
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  // rules first terminals
     9  type RuleFirstT struct {
    10  	ri      *RuleIndex
    11  	cache   map[Rule]RuleSet
    12  	seen    map[Rule]int
    13  	reverse bool
    14  }
    15  
    16  func newRuleFirstT(ri *RuleIndex, reverse bool) *RuleFirstT {
    17  	rf := &RuleFirstT{ri: ri, reverse: reverse}
    18  	rf.cache = map[Rule]RuleSet{}
    19  	rf.seen = map[Rule]int{}
    20  	return rf
    21  }
    22  
    23  //----------
    24  
    25  func (rf *RuleFirstT) first(r Rule) RuleSet {
    26  	rset, ok := rf.cache[r]
    27  	if ok {
    28  		return rset
    29  	}
    30  
    31  	rf.seen[r]++
    32  	defer func() { rf.seen[r]-- }()
    33  	if rf.seen[r] > 2 { // extra loop to allow proper solve
    34  		return nil
    35  	}
    36  
    37  	rset = RuleSet{}
    38  	if r.isTerminal() {
    39  		rset.set(r)
    40  	} else {
    41  		inReverse := rf.reverse && ruleProdCanReverse(r)
    42  		for _, r2 := range ruleProductions(r) { // r->a0|...|an
    43  			w2 := ruleSequence(r2, inReverse) // r->a0 ... an
    44  			rset2 := rf.sequenceFirst(w2)
    45  			rset.add(rset2)
    46  		}
    47  	}
    48  	rf.cache[r] = rset
    49  	return rset
    50  }
    51  func (rf *RuleFirstT) sequenceFirst(w []Rule) RuleSet {
    52  	rset := RuleSet{}
    53  	allHaveNil := true
    54  	for _, r := range w { // w -> r1 ... rk
    55  		rset2 := rf.first(r)
    56  		rset.add(rset2)
    57  		if !rset2.has(nilRule) {
    58  			allHaveNil = false
    59  			break
    60  		}
    61  	}
    62  	if !allHaveNil {
    63  		rset.unset(nilRule)
    64  	}
    65  	return rset
    66  }
    67  
    68  //----------
    69  
    70  func (rf *RuleFirstT) String() string {
    71  	u := []string{}
    72  	for _, r := range rf.ri.sorted() {
    73  		if r.isTerminal() { // no need to show terminals
    74  			continue
    75  		}
    76  		u = append(u, fmt.Sprintf("%v:%v", r.id(), rf.first(r)))
    77  	}
    78  	return fmt.Sprintf("rulefirst[rev=%v]{\n\t%v\n}", rf.reverse, strings.Join(u, "\n\t"))
    79  }
    80  
    81  //----------
    82  //----------
    83  //----------
    84  
    85  //type RuleFollow struct {
    86  //	ri     *RuleIndex
    87  //	rFirst *RulesFirst
    88  //	cache  map[Rule]RuleSet
    89  //}
    90  
    91  //func newRuleFollow(ri *RuleIndex, rFirst *RulesFirst, r Rule) *RuleFollow {
    92  //	rf := &RuleFollow{ri: ri, rFirst: rFirst}
    93  //	rf.cache = map[Rule]RuleSet{}
    94  //	rf.calc(r)
    95  //	return rf
    96  //}
    97  //func (rf *RuleFollow) get(r Rule) RuleSet {
    98  //	return rf.cache[r]
    99  //}
   100  //func (rf *RuleFollow) calc(r Rule) {
   101  //	AFollow := RuleSet{}
   102  //	AFollow.set(rf.ri.endRule())
   103  //	rf.cache[r] = AFollow
   104  
   105  //	seen := map[Rule]int{}
   106  //	rf.calc2(r, AFollow, seen)
   107  //}
   108  //func (rf *RuleFollow) calc2(A Rule, AFollow RuleSet, seen map[Rule]int) {
   109  //	if seen[A] >= 2 { // need to visit 2nd time to allow afollow to be used in nested rules
   110  //		return
   111  //	}
   112  //	seen[A]++
   113  //	defer func() { seen[A]-- }()
   114  
   115  //	//rset := RuleSet{}
   116  //	w, ok := ruleProductions(A)
   117  //	if !ok { // terminal
   118  //		return
   119  //	}
   120  //	nilr := rf.ri.nilRule()
   121  //	for _, r2 := range w {
   122  //		// A->r2
   123  //		w2 := ruleRhs(r2) // sequence
   124  //		for i, B := range w2 {
   125  //			// A->αBβ
   126  
   127  //			if ruleIsTerminal(B) {
   128  //				continue
   129  //			}
   130  
   131  //			BFollow, ok := rf.cache[B]
   132  //			if !ok {
   133  //				BFollow = RuleSet{}
   134  //				rf.cache[B] = BFollow
   135  //			}
   136  
   137  //			haveβ := i < len(w2)-1
   138  //			βFirstHasNil := false
   139  //			if haveβ {
   140  //				β := w2[i+1]
   141  //				βFirst := RuleSet{}
   142  //				βFirst.add(rf.rFirst.get(β))
   143  //				βFirstHasNil = βFirst.isSet(nilr)
   144  //				βFirst.unset(nilr)
   145  //				BFollow.add(βFirst)
   146  //			}
   147  //			if !haveβ || βFirstHasNil {
   148  //				BFollow.add(AFollow)
   149  //			}
   150  
   151  //			rf.calc2(B, BFollow, seen)
   152  //		}
   153  //	}
   154  //}
   155  //func (rf *RuleFollow) String() string {
   156  //	u := []string{}
   157  //	for _, r := range rf.ri.sorted() {
   158  //		u = append(u, fmt.Sprintf("%v:%v", r.id(), rf.get(r)))
   159  //	}
   160  //	return fmt.Sprintf("{\n\t%v\n}", strings.Join(u, ",\n\t"))
   161  //}