def compute_firsts(): from Skoarcery.terminals import Empty, tokens as T from Skoarcery.nonterminals import nonterminals as N global FIRST # do terminals first for X in T.values(): FIRST(X).add(X) last = 0 first_len = len(FIRST) while first_len > last: last = first_len for X in N.values(): if X.derives_empty: FIRST(X).add(Empty) for R in X.production_rules: i = -1 n = len(R.production) # figure out FIRST(X) first for Yi in R.production: i += 1 Yi_to_end = R.production[i:] if len(Yi_to_end) > 0: S = FIRST(Yi_to_end) S.update( everything_but_e(FIRST(Yi)) ) FIRST(X).update(S) FIRST(Yi_to_end).update(S) if not Yi.derives_empty: break # if we got to the end of the loop without breaking, add Empty else: FIRST(X).add(Empty) first_len = len(FIRST)
def compute_firsts(): from Skoarcery.terminals import Empty, tokens as T from Skoarcery.nonterminals import nonterminals as N global FIRST # do terminals first for X in T.values(): FIRST(X).add(X) last = 0 first_len = len(FIRST) while first_len > last: last = first_len for X in N.values(): if X.derives_empty: FIRST(X).add(Empty) for R in X.production_rules: i = -1 n = len(R.production) # figure out FIRST(X) first for Yi in R.production: i += 1 Yi_to_end = R.production[i:] if len(Yi_to_end) > 0: S = FIRST(Yi_to_end) S.update(everything_but_e(FIRST(Yi))) FIRST(X).update(S) FIRST(Yi_to_end).update(S) if not Yi.derives_empty: break # if we got to the end of the loop without breaking, add Empty else: FIRST(X).add(Empty) first_len = len(FIRST)
def compute_follows(): from Skoarcery.terminals import EOF, Empty from Skoarcery.nonterminals import nonterminals as N, SKOAR global FIRST, FOLLOW # start symbol gets end symbol FOLLOW(SKOAR).add(EOF) # repeat until nothing can be added to any follow set last = 0 follow_len = len(FOLLOW) while follow_len > last: last = follow_len for X in N.values(): for R in X.production_rules: A = R.production # If there is a production [ A -> alpha B beta]: # everything except <e> in FIRST(beta) is in FOLLOW(B) # examine each suffix (except last) n = len(A) for i in range(0, n - 1): B = A[i] if not isinstance(B, Nonterminal): continue beta = A[i + 1:] #print("n: " + str(n) + " i: " + str(i) + " A: " + repr(A) + " beta: " + repr(beta)) S = FIRST(beta) FOLLOW(B).update(everything_but_e(S)) for i in reversed(range(0, n)): B = A[i] if not isinstance(B, Nonterminal): continue # we are at the end of the list if i == n - 1: FOLLOW(B).update(FOLLOW(X)) continue beta = A[i + 1:] S = FIRST(beta) #print(": FIRST(" + repr(beta) + ") = " + repr(S)) if Empty in S: FOLLOW(B).update(FOLLOW(X)) else: break follow_len = len(FOLLOW)