static void init_symbols(void) { size_t i, j; const char *p; start_symbol = grammar[0].p_lhs; for (i = 0; i < charmap_size; i++) charmap[i] = CT_NONE; for (i = 0; i < grammar_size; i++) charmap[(uint_fast8_t)grammar[i].p_lhs] = CT_NONTERMINAL; for (i = 0; i < grammar_size; i++) for (p = grammar[i].p_rhs; *p; p++) if (charmap[(uint_fast8_t)*p] == CT_NONE) charmap[(uint_fast8_t)*p] = CT_TERMINAL; assert(charmap['$'] == CT_NONE); charmap['$'] = CT_TERMINAL; assert(charmap['-'] == CT_NONE); for (i = j = 0; i < token_pairs_size; i++, j++) { token_pair_t *tpp = &token_pairs[i]; assert(tpp->tm_ttype < token_pairs_size); uint_fast8_t *cmp = &charmap[(uint_fast8_t)tpp->tm_term]; assert(*cmp == CT_TERMINAL); *cmp |= tpp->tm_ttype; *next_symbols(1) = tpp->tm_term; } terminals_size = symbols_size; charmap['-'] = CT_TERMINAL | j++; epsilon = symbols_size; *next_symbols(1) = '-'; exterminals_size = symbols_size; for (i = 0; i < charmap_size; i++) if (charmap[i] == CT_NONTERMINAL) { charmap[i] |= j++; *next_symbols(1) = i; } nonterminals_size = symbols_size - exterminals_size; assert(symbols_size < CTMASK); #if DUMP_TABLES printf("start_symbol = '%c'\n", start_symbol); printf("terminals_size = %d\n", terminals_size); printf("exterminals_size = %d\n", exterminals_size); printf("nonterminals_size = %d\n", nonterminals_size); printf("symbols_size = %d\n", symbols_size); printf("epsilon = %d\n", epsilon); printf("charmap\n"); for (i = 0; i < charmap_size; i++) if (charmap[i]) printf(" ['%c'] = 0x%x\n", i, charmap[i]); printf("\n"); printf("symbols\n"); for (i = 0; i < symbols_size; i++) printf(" %2d: %c\n", i, symbols[i]); printf("\n"); #endif }
/* returns -1 on failure, >= 0 is an actual symbol value. String is * searched until terminating null or end. The empty string cannot * receive a symbol value. */ symbol_t getvalue_symbols(symbols_t *sb, bool_t generate, const char_t *begin, const char_t *end) { const byte_t *p; bool_t bdone, pdone; jump_t *j; if( sb && begin && *begin ) { if( !end ) { end = begin + strlen(begin); } if( (sb->bigs_len + (end - begin) + 1 + sizeof(symbol_t)) > sb->bigmax ) { if( !grow_mem(&sb->bigs, &sb->bigmax, sizeof(byte_t), 16) ) { errormsg(E_WARNING, "out of symbol memory\n"); return -1; } } if( sb->bigs_len == 0 ) { return next_symbols(sb, generate, begin, end); } p = sb->bigs; while( *begin && (begin < end) ) { /* skip common prefix */ while( (*begin == *p) && *begin && (begin < end) ) { p++; begin++; } bdone = ((begin == end) || (*begin == 0)); pdone = (*p == 0); /* either begin string is empty, or p string is empty, or both */ if( bdone && pdone ) { /* we found the string */ return *((symbol_t *)p); } else if( bdone ) { /* a longer p string was inserted first */ /* follow as many branches as possible */ j = find_in_jumptable(&sb->jt, p - sb->bigs); while( j && sb->bigs[j->pos] ) { p = sb->bigs + j->pos; j = find_in_jumptable(&sb->jt, p - sb->bigs); } if( j && (sb->bigs[j->pos] == 0) ) { /* found the string */ p = sb->bigs + j->pos; return *((symbol_t *)p); } else { /* there are no further branches at p */ insert_jumptable(&sb->jt, p - sb->bigs, sb->bigs_len); return next_symbols(sb, generate, begin, end); } } else { /* 0 != *begin != *p */ j = find_in_jumptable(&sb->jt, p - sb->bigs); if( !j ) { /* no branch at p, so we append begin */ insert_jumptable(&sb->jt, p - sb->bigs, sb->bigs_len); return next_symbols(sb, generate, begin, end); } /* in here, branch exists */ p = sb->bigs + j->pos; } /* and back to while */ } } return -1; }