From c327cf063e8fbf804306ad906711f17049ea3b79 Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Thu, 4 Jan 2024 10:34:55 +0100 Subject: [PATCH] support for BIND/SOFT_BIND/SOFT_SPACE --- src/runtime/c/pgf/data.h | 1 + src/runtime/c/pgf/parser.cxx | 92 ++++++++++++++++++++++++++++++++++-- src/runtime/c/pgf/parser.h | 1 + 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/src/runtime/c/pgf/data.h b/src/runtime/c/pgf/data.h index 8ad6e34dd..ac1249c36 100644 --- a/src/runtime/c/pgf/data.h +++ b/src/runtime/c/pgf/data.h @@ -307,6 +307,7 @@ struct PGF_INTERNAL_DECL PgfLRReduce { struct PGF_INTERNAL_DECL PgfLRState { ref> shifts; ref> tokens; + size_t next_bind_state; ref> reductions; }; diff --git a/src/runtime/c/pgf/parser.cxx b/src/runtime/c/pgf/parser.cxx index b862f3016..5edc4314c 100644 --- a/src/runtime/c/pgf/parser.cxx +++ b/src/runtime/c/pgf/parser.cxx @@ -389,9 +389,11 @@ struct PgfLRTableMaker::State { std::map ccats1; std::map ccats2; std::map tokens; + State *bind_state; State() { this->id = 0; + this->bind_state = NULL; } ~State() { @@ -693,6 +695,36 @@ void PgfLRTableMaker::symbol(State *state, Fold fold, Item *item, PgfSymbol sym) } break; } + case PgfSymbolBIND::tag: { + if (fold != PROBE) + { + if (state->bind_state == NULL) { + state->bind_state = new State; + } + item->sym_idx++; + item->stk_size++; + state->bind_state->push_item(item); + } + break; + } + case PgfSymbolSOFTBIND::tag: + case PgfSymbolSOFTSPACE::tag: { + if (fold != PROBE) + { + // SOFT_BIND && SOFT_SPACE also allow a space + item->sym_idx++; + process(state,fold,item); + + // Now we handle the case where there is no space + if (state->bind_state == NULL) { + state->bind_state = new State; + } + item = new (item) Item(); + item->stk_size++; + state->bind_state->push_item(item); + } + break; + } default: if (item->ref_cnt == 0) delete item; @@ -956,9 +988,9 @@ ref PgfLRTableMaker::make() while (!todo.empty()) { State *state = todo.front(); todo.pop(); -//#if defined(DEBUG_AUTOMATON) || defined(DEBUG_STATE_CREATION) +#if defined(DEBUG_AUTOMATON) || defined(DEBUG_STATE_CREATION) fprintf(stderr, "--------------- state %ld ---------------\n", state->id); -//#endif +#endif while (!state->items.empty()) { Item *item = state->items.back(); state->items.pop_back(); @@ -1010,6 +1042,13 @@ ref PgfLRTableMaker::make() free(text); #endif } + if (state->bind_state != NULL) { + internalize_state(state->bind_state); +#if defined(DEBUG_AUTOMATON) + fprintf(stderr, "BIND: state %ld\n", state->bind_state->id); +#endif + } + } ref lrtable = vector_new(states.size()); @@ -1043,6 +1082,11 @@ ref PgfLRTableMaker::make() } } + size_t next_bind_state = 0; + if (state->bind_state != NULL) { + next_bind_state = state->bind_state->id; + } + auto reductions = vector_new(state->completed.size()); for (size_t i = 0; i < state->completed.size(); i++) { Item *item = state->completed[i]; @@ -1066,6 +1110,7 @@ ref PgfLRTableMaker::make() ref lrstate = vector_elem(lrtable, state->id); lrstate->shifts = shifts; lrstate->tokens = tokens; + lrstate->next_bind_state = next_bind_state; lrstate->reductions = reductions; } return lrtable; @@ -1190,8 +1235,7 @@ void PgfParser::print_transition(StackNode *source, StackNode *target, Stage *st printer.nprintf(64, "state %ld --- ", source->state_id); if (target->choice != 0) { printer.nprintf(32, "?%d", target->choice->fid); - } - if (shift != 0) { + } else if (shift != 0) { size_t sym_idx = shift->sym_idx; ref seq = shift->seq; while (sym_idx < seq->syms.len) { @@ -1201,6 +1245,8 @@ void PgfParser::print_transition(StackNode *source, StackNode *target, Stage *st printer.symbol(sym); sym_idx++; } + } else { + printer.puts("BIND"); } printer.nprintf(80, " ---> state %ld (position %zu-%zu, nodes %zu)\n", target->state_id, @@ -1315,6 +1361,32 @@ void PgfParser::shift(StackNode *parent, Stage *before) } } +void PgfParser::shift(StackNode *parent, Stage *before, Stage *after) +{ + size_t next_bind_state = vector_elem(concr->lrtable,parent->state_id)->next_bind_state; + if (next_bind_state != 0) { + StackNode *node = NULL; + for (StackNode *n : after->nodes) { + if (n->stage == before && n->state_id == next_bind_state) { + node = n; + break; + } + } + if (node == NULL) { + node = new StackNode(before, next_bind_state); + node->choice = NULL; + after->nodes.push_back(node); + } + + if (std::find(node->parents.begin(), node->parents.end(), parent) == node->parents.end()) { + node->parents.push_back(parent); +#ifdef DEBUG_PARSER + print_transition(parent,node,after,0); +#endif + } + } +} + PgfParser::Choice *PgfParser::intersect_choice(Choice *choice1, Choice *choice2, intersection_map &im) { if (choice1 == NULL) @@ -1482,6 +1554,18 @@ void PgfParser::space(PgfTextSpot *start, PgfTextSpot *end, PgfExn* err) before->end = *end; + if (before->next != NULL && before->start.pos==before->end.pos) { + after = new Stage(*end); + after->next = before; + size_t i = 0; + while (i < before->nodes.size()) { + StackNode *node = before->nodes[i++]; + reduce_all(node); + shift(node, before, after); + } + before = after; + } + size_t i = 0; while (i < before->nodes.size()) { StackNode *node = before->nodes[i++]; diff --git a/src/runtime/c/pgf/parser.h b/src/runtime/c/pgf/parser.h index 0e8654bd4..f005cc196 100644 --- a/src/runtime/c/pgf/parser.h +++ b/src/runtime/c/pgf/parser.h @@ -127,6 +127,7 @@ class PGF_INTERNAL_DECL PgfParser : public PgfPhraseScanner, public PgfExprEnum void shift(StackNode *parent, ref lincat, size_t r, Production *prod, Stage *before, Stage *after); void shift(StackNode *parent, Stage *before); + void shift(StackNode *parent, Stage *before, Stage *after); void reduce(StackNode *parent, ref lin, ref red, size_t n, std::vector &args, Stage *before, Stage *after);