Skip to content

Commit

Permalink
Disambiguating by preferring the first rule did not always work.
Browse files Browse the repository at this point in the history
  • Loading branch information
dworkin committed Dec 17, 2022
1 parent dc0d215 commit 39d1c22
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 33 deletions.
73 changes: 42 additions & 31 deletions src/parser/parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,16 @@ PNode *PNode::create(PnChunk **c, short symb, unsigned short state, char *text,
return pn;
}

struct PState{
SNode *first; /* first in list */
SNode *last; /* last in list */
};

class SNode : public ChunkAllocated {
public:
SNode *add(SnList *list, PNode *pn, SNode *slist);
void add(SnList *list, PNode *pn, PState *state);

static SNode *create(SnList *list, PNode *pn, SNode *slist);
static void create(SnList *list, PNode *pn, PState *state);
static void clear(SnList *list);

PNode *pn; /* pnode */
Expand All @@ -95,7 +100,7 @@ class SnChunk : public Chunk<SNode, SNCHUNKSZ> {
/*
* create a new snode
*/
SNode *SNode::create(SnList *list, PNode *pn, SNode *slist)
void SNode::create(SnList *list, PNode *pn, PState *state)
{
SNode *sn;

Expand All @@ -112,15 +117,19 @@ SNode *SNode::create(SnList *list, PNode *pn, SNode *slist)

sn->pn = pn;
sn->next = (SNode *) NULL;
sn->slist = slist;

return sn;
if (state->first == (SNode *) NULL) {
state->first = state->last = sn;
} else {
state->last->slist = sn;
state->last = sn;
}
sn->slist = (SNode *) NULL;
}

/*
* add an existing snode to a list
*/
SNode *SNode::add(SnList *list, PNode *pn, SNode *slist)
void SNode::add(SnList *list, PNode *pn, PState *state)
{
if (list->first == (SNode *) NULL) {
list->first = list->last = this;
Expand All @@ -131,9 +140,13 @@ SNode *SNode::add(SnList *list, PNode *pn, SNode *slist)

this->pn = pn;
next = (SNode *) NULL;
this->slist = slist;

return this;
if (state->first == (SNode *) NULL) {
state->first = state->last = this;
} else {
state->last->next = this;
state->last = this;
}
this->slist = (SNode *) NULL;
}

/*
Expand Down Expand Up @@ -318,27 +331,26 @@ void Parser::reduce(PNode *pn, char *p)
* see if this reduction can be merged with another
*/
frame->addTicks(2);
for (sn = states[n]; sn != (SNode *) NULL; sn = sn->slist) {
for (sn = states[n].first; sn != (SNode *) NULL; sn = sn->slist) {
if (sn->pn->symbol == symb && sn->pn->next == next) {
PNode **ppn;

if (sn->pn->text != (char *) NULL) {
/* first alternative */
sn->pn->list = PNode::create(&pnc, symb, n, sn->pn->text,
sn->pn->list = sn->pn->trav =
PNode::create(&pnc, symb, n, sn->pn->text,
sn->pn->len, (PNode *) NULL,
sn->pn->list);
sn->pn->text = (char *) NULL;
sn->pn->len = 1;
}

/* add alternative */
for (ppn = &sn->pn->list;
*ppn != (PNode *) NULL && (*ppn)->text < red;
ppn = &(*ppn)->next) ;
sn->pn->trav->next = pn;
sn->pn->trav = pn;
sn->pn->len++;

pn->next = *ppn;
*ppn = pn;
pn->next = (PNode *) NULL;
return;
}
frame->addTicks(1);
Expand All @@ -347,7 +359,7 @@ void Parser::reduce(PNode *pn, char *p)
/*
* new reduction
*/
states[n] = SNode::create(&list, pn, states[n]);
SNode::create(&list, pn, &states[n]);
}

/*
Expand All @@ -360,9 +372,9 @@ void Parser::shift(SNode *sn, short token, char *text, ssizet len)
n = lr->shift(sn->pn->state, token);
if (n >= 0) {
/* shift works: add new snode */
states[n] = sn->add(&list, PNode::create(&pnc, token, n, text, len,
sn->pn, (PNode *) NULL),
states[n]);
sn->add(&list, PNode::create(&pnc, token, n, text, len, sn->pn,
(PNode *) NULL),
&states[n]);
return;
}

Expand All @@ -389,15 +401,14 @@ PNode *Parser::parse(String *str, bool *toobig)
if (nstates < nprod) {
nstates = nprod;
}
states = ALLOC(SNode*, nstates);
memset(states, '\0', nstates * sizeof(SNode*));
states = ALLOC(PState, nstates);
memset(states, '\0', nstates * sizeof(PState));
list.first = (SNode *) NULL;

/* state 0 */
states[0] = SNode::create(&list, PNode::create(&pnc, 0, 0, (char *) NULL,
(ssizet) 0, (PNode *) NULL,
(PNode *) NULL),
(SNode *) NULL);
SNode::create(&list, PNode::create(&pnc, 0, 0, (char *) NULL, (ssizet) 0,
(PNode *) NULL, (PNode *) NULL),
&states[0]);

do {
/*
Expand All @@ -417,9 +428,9 @@ PNode *Parser::parse(String *str, bool *toobig)
/* grow tables */
stsize = n;
stsize <<= 1;
states = REALLOC(states, SNode*, nstates, stsize);
states = REALLOC(states, PState, nstates, stsize);
memset(states + nstates, '\0',
(stsize - nstates) * sizeof(SNode*));
(stsize - nstates) * sizeof(PState));
nstates = stsize;
}
for (n = 0; n < nred; n++) {
Expand All @@ -440,7 +451,7 @@ PNode *Parser::parse(String *str, bool *toobig)
switch (n = fa->scan(str, &size, &ttext, &tlen)) {
case DFA_EOS:
/* if end of string, return node from state 1 */
sn = states[1];
sn = states[1].first;
FREE(states);
return (sn != (SNode *) NULL) ? sn->pn : (PNode *) NULL;

Expand All @@ -457,7 +468,7 @@ PNode *Parser::parse(String *str, bool *toobig)

default:
/* shift */
memset(states, '\0', nstates * sizeof(SNode*));
memset(states, '\0', nstates * sizeof(PState));
sn = list.first;
list.first = (SNode *) NULL;
do {
Expand Down
4 changes: 2 additions & 2 deletions src/parser/parse.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* This file is part of DGD, https://github.com/dworkin/dgd
* Copyright (C) 1993-2010 Dworkin B.V.
* Copyright (C) 2010-2021 DGD Authors (see the commit log for details)
* Copyright (C) 2010-2022 DGD Authors (see the commit log for details)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
Expand Down Expand Up @@ -58,7 +58,7 @@ class Parser : public Allocated {
class PnChunk *pnc; /* pnode chunk */

unsigned short nstates; /* state table size */
SNode **states; /* state table */
struct PState *states; /* state table */
SnList list; /* snode list */

class StrPChunk *strc; /* string chunk */
Expand Down

0 comments on commit 39d1c22

Please sign in to comment.