예제 #1
0
파일: lr.c 프로젝트: bsletten/hammer
// hash LR item sets (DFA states) - hash the elements and sum
HHashValue h_hash_lr_itemset(const void *p)
{
  HHashValue hash = 0;

  H_FOREACH_KEY((const HHashSet *)p, HLRItem *item)
    hash += hash_lr_item(item);
  H_END_FOREACH

  return hash;
}
예제 #2
0
파일: lalr.c 프로젝트: michiexile/hammer
int h_lalr_compile(HAllocator* mm__, HParser* parser, const void* params)
{
  // generate (augmented) CFG from parser
  // construct LR(0) DFA
  // build LR(0) table
  // if necessary, resolve conflicts "by conversion to SLR"

  if (!parser->vtable->isValidCF(parser->env)) {
    return -1;
  }
  HCFGrammar *g = h_cfgrammar_(mm__, h_desugar_augmented(mm__, parser));
  if(g == NULL)     // backend not suitable (language not context-free)
    return -1;

  HLRDFA *dfa = h_lr0_dfa(g);
  if (dfa == NULL) {     // this should normally not happen
    h_cfgrammar_free(g);
    return -1;
  }

  HLRTable *table = h_lr0_table(g, dfa);
  if (table == NULL) {   // this should normally not happen
    h_cfgrammar_free(g);
    return -1;
  }

  if(has_conflicts(table)) {
    HArena *arena = table->arena;

    HLREnhGrammar *eg = enhance_grammar(g, dfa, table);
    if(eg == NULL) {    // this should normally not happen
      h_cfgrammar_free(g);
      h_lrtable_free(table);
      return -1;
    }

    // go through the inadequate states; replace inadeq with a new list
    HSlist *inadeq = table->inadeq;
    table->inadeq = h_slist_new(arena);
    
    for(HSlistNode *x=inadeq->head; x; x=x->next) {
      size_t state = (uintptr_t)x->elem;
      bool inadeq = false;
      
      // clear old forall entry, it's being replaced by more fine-grained ones
      table->forall[state] = NULL;

      // go through each reducible item of state
      H_FOREACH_KEY(dfa->states[state], HLRItem *item)
        if(item->mark < item->len)
          continue;

        // action to place in the table cells indicated by lookahead
        HLRAction *action = h_reduce_action(arena, item);

        // find all LR(0)-enhanced productions matching item
        HHashSet *lhss = h_hashtable_get(eg->corr, item->lhs);
        assert(lhss != NULL);
        H_FOREACH_KEY(lhss, HCFChoice *lhs)
          assert(lhs->type == HCF_CHOICE);  // XXX could be CHARSET?

	  for(HCFSequence **p=lhs->seq; *p; p++) {
            HCFChoice **rhs = (*p)->items;
            if(!match_production(eg, rhs, item->rhs, state)) {
              continue;
	    }

            // the left-hand symbol's follow set is this production's
            // contribution to the lookahead
            const HStringMap *fs = h_follow(1, eg->grammar, lhs);
            assert(fs != NULL);
            assert(fs->epsilon_branch == NULL);
            assert(!h_stringmap_empty(fs));

            // for each lookahead symbol, put action into table cell
            if(terminals_put(table->tmap[state], fs, action) < 0)
              inadeq = true;
	  } H_END_FOREACH // enhanced production
      H_END_FOREACH  // reducible item

      if(inadeq) {
        h_slist_push(table->inadeq, (void *)(uintptr_t)state);
      }
    }
  }

  h_cfgrammar_free(g);
  parser->backend_data = table;
  return has_conflicts(table)? -1 : 0;
}