support for BIND/SOFT_BIND/SOFT_SPACE

This commit is contained in:
Krasimir Angelov
2024-01-04 10:34:55 +01:00
parent 68da9226b1
commit c327cf063e
3 changed files with 90 additions and 4 deletions

View File

@@ -307,6 +307,7 @@ struct PGF_INTERNAL_DECL PgfLRReduce {
struct PGF_INTERNAL_DECL PgfLRState {
ref<Vector<PgfLRShift>> shifts;
ref<Vector<PgfLRShiftKS>> tokens;
size_t next_bind_state;
ref<Vector<PgfLRReduce>> reductions;
};

View File

@@ -389,9 +389,11 @@ struct PgfLRTableMaker::State {
std::map<Key1,State*,CompareKey1> ccats1;
std::map<Key2,State*,CompareKey2> ccats2;
std::map<Key3,State*,CompareKey3> 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<PgfLRTable> 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<PgfLRTable> 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<PgfLRTable> lrtable = vector_new<PgfLRState>(states.size());
@@ -1043,6 +1082,11 @@ ref<PgfLRTable> PgfLRTableMaker::make()
}
}
size_t next_bind_state = 0;
if (state->bind_state != NULL) {
next_bind_state = state->bind_state->id;
}
auto reductions = vector_new<PgfLRReduce>(state->completed.size());
for (size_t i = 0; i < state->completed.size(); i++) {
Item *item = state->completed[i];
@@ -1066,6 +1110,7 @@ ref<PgfLRTable> PgfLRTableMaker::make()
ref<PgfLRState> 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<PgfSequence> 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++];

View File

@@ -127,6 +127,7 @@ class PGF_INTERNAL_DECL PgfParser : public PgfPhraseScanner, public PgfExprEnum
void shift(StackNode *parent, ref<PgfConcrLincat> 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<PgfConcrLin> lin, ref<PgfLRReduce> red,
size_t n, std::vector<Choice*> &args,
Stage *before, Stage *after);