//========================================================================================================== //========================================================================================================== void Grammar::calc_follow_table() { calc_first_table(); //------------------------------------------------------------------------------------------------------ // To handle end-of-input correctly, add the EOI (= $) symbol to the follow of the start symbol. // This is instead of add another symbol to be the new start and a production: START' -> START $ // That will have the same effect but causes some overhead of needing to deal with the new symbol and // production. //------------------------------------------------------------------------------------------------------ follow_table[START].insert(EOI); //------------------------------------------------------------------------------------------------------ // Go over the productions: // For a sequence ...NA, add First(A) to Follow(N). // For a sequence ...N, add a constraint: Follow(M) ⊆ Follow(N), where M is the LHS of the production. //------------------------------------------------------------------------------------------------------ vector<pair<Symbol, Symbol>> follow_constraints; // Pair (M,N) means Follow(M) ⊆ Follow(N) for(auto& p: productions) { Symbol M = p[0]; for(int j = 1; j < p.size(); ++j) { if(is_terminal(p[j])) continue; Symbol N = p[j]; if(j < p.size() - 1) { follow_table[N].insert(get_first_set(p[j+1])); } else if(M != N) { follow_constraints.push_back({M,N}); } } } //------------------------------------------------------------------------------------------------------ // Go over the constraints and apply them, until no more changes are made //------------------------------------------------------------------------------------------------------ bool added = true; while(added) { added = false; for(auto& c: follow_constraints) { Symbol M = c.first, N = c.second; int old_size = follow_table[N].size(); follow_table[N].insert(follow_table[M]); added = (added or follow_table[N].size() > old_size); } } } // calc_follow_table()
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, PCRE_SPTR16 *stringptr) #endif { int n = get_first_set(code, stringname, ovector); if (n <= 0) return n; #ifdef COMPILE_PCRE8 return pcre_get_substring(subject, ovector, stringcount, n, stringptr); #else return pcre16_get_substring(subject, ovector, stringcount, n, stringptr); #endif }
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_UCHAR32 *buffer, int size) #endif { int n = get_first_set(code, stringname, ovector, stringcount); if (n <= 0) return n; #if defined COMPILE_PCRE8 return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size); #elif defined COMPILE_PCRE16 return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size); #elif defined COMPILE_PCRE32 return pcre32_copy_substring(subject, ovector, stringcount, n, buffer, size); #endif }
static void first(CC_Class *cc, PT_Symbols symbols) { PT_Symbol symbol; CC_Class *set; while(!PT_isSymbolsEmpty(symbols)) { symbol = PT_getSymbolsHead(symbols); symbols = PT_getSymbolsTail(symbols); set = get_first_set(symbol, ATtrue); CC_union(cc, set, cc); if (!CC_containsChar(set, CC_EPSILON)) { CC_removeChar(cc, CC_EPSILON); return; } } CC_addChar(cc, CC_EPSILON); }
/* For each symbol on the left hand side of the given production rule, if the * symbol is a non-terminal initialise the symbol's first set to empty, * otherwise if the symbol is a terminal or the end-of-string symbol, * initialise the symbol's first set to the symbol. */ void init_prod_first(PT_Production prod) { PT_Symbols symbols; PT_Symbol symbol; CC_Class *set; CC_Class *newset; symbols = PT_getProductionLhs(prod); while(!PT_isSymbolsEmpty(symbols)) { symbol = PT_getSymbolsHead(symbols); set = get_first_set(symbol, ATtrue); newset = CC_getCharClass(symbol); /*assert(CC_isEmpty(set) || CC_isEqual(set, newset));*/ CC_copy(newset, set); symbols = PT_getSymbolsTail(symbols); } }
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_SPTR32 *stringptr) #endif { int n = get_first_set(code, stringname, ovector); if (n <= 0) return n; #if defined COMPILE_PCRE8 #if defined(ERLANG_INTEGRATION) return erts_pcre_get_substring(subject, ovector, stringcount, n, stringptr); #else return pcre_get_substring(subject, ovector, stringcount, n, stringptr); #endif #elif defined COMPILE_PCRE16 return pcre16_get_substring(subject, ovector, stringcount, n, stringptr); #elif defined COMPILE_PCRE32 return pcre32_get_substring(subject, ovector, stringcount, n, stringptr); #endif }
static void *comp_sym_follow(void *sym, void *first_set_of_following) { t_lst *first_set_of_next; t_bool sym_added; if (first_set_of_following == NULL) return (NULL); first_set_of_next = first_set_of_following; if (!is_empty_first(first_set_of_next) && !is_terminal(sym)) { if (!add_set_to_follow_set(sym, first_set_of_next, &sym_added)) return (NULL); } if (!has_symbol_in_first(sym, EMPTY_SYMBOL)) { f_lstdel(&first_set_of_next, no_destroy); if (NULL == f_lstpush(EMPTY_SYMBOL, &first_set_of_next)) return (NULL); } return (lst_add_to_filter( &first_set_of_next, get_first_set(sym), &sym_added)); }