lemon refactor iterate

This commit is contained in:
John Kerl 2016-07-13 22:27:21 -04:00
parent 551974a000
commit 3ce14f9c2d
5 changed files with 271 additions and 234 deletions

View file

@ -3,6 +3,8 @@ AM_CFLAGS= -std=gnu99
noinst_PROGRAMS= lemon
lemon_SOURCES= lemon.c \
lemon_action.c \
lemon_action.h \
lemon_assert.c \
lemon_assert.h \
lemon_error.c \

View file

@ -105,8 +105,19 @@ ex2_lexer.c ex2_lexer.h: ex2_lexer.l ./ex_ast.h
flex --prefix=ex2_lexer_ --outfile=ex2_lexer.c --header-file=ex2_lexer.h ex2_lexer.l
# ----------------------------------------------------------------
lemon: lemon.c lemon_assert.c lemon_error.c lemon_memory.c lemon_option.c lemon_structs.h
$(DSLCC) -o lemon lemon.c lemon_assert.c lemon_error.c lemon_memory.c lemon_option.c
lemon: lemon.c \
lemon_assert.h \
lemon_assert.c \
lemon_error.h \
lemon_error.c \
lemon_memory.h \
lemon_memory.c \
lemon_option.h \
lemon_option.c \
lemon_structs.h \
lemon_action.h \
lemon_action.c
$(DSLCC) -o lemon lemon.c lemon_assert.c lemon_error.c lemon_memory.c lemon_option.c lemon_action.c
# ----------------------------------------------------------------
clean:

View file

@ -18,6 +18,7 @@
#include "lemon_memory.h"
#include "lemon_option.h"
#include "lemon_structs.h"
#include "lemon_action.h"
/* #define PRIVATE static */
#define PRIVATE
@ -31,10 +32,6 @@
char *msort();
extern void *malloc();
/******** From the file "action.h" *************************************/
struct action *Action_new();
struct action *Action_sort();
/********** From the file "build.h" ************************************/
void FindRulePrecedences();
void FindFirstSets();
@ -134,234 +131,6 @@ int Configtable_insert(/* struct config * */);
struct config *Configtable_find(/* struct config * */);
void Configtable_clear(/* int(*)(struct config *) */);
/****************** From the file "action.c" *******************************/
/*
** Routines processing parser actions in the LEMON parser generator.
*/
/* Allocate a new parser action */
struct action *Action_new() {
static struct action *freelist = 0;
struct action *new;
if (freelist==0) {
int i;
int amt = 100;
freelist = (struct action *)malloc (sizeof(struct action)*amt) ;
if (freelist==0) {
fprintf(stderr,"Unable to allocate memory for a new parser action.");
exit(1);
}
for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
freelist[amt-1].next = 0;
}
new = freelist;
freelist = freelist->next;
return new;
}
/* Compare two actions */
static int actioncmp(struct action *ap1, struct action *ap2)
{
int rc;
rc = ap1->sp->index - ap2->sp->index;
if (rc==0) rc = (int)ap1->type - (int)ap2->type;
if (rc==0) {
assert (ap1->type==REDUCE || ap1->type==RD_RESOLVED || ap1->type==CONFLICT);
assert (ap2->type==REDUCE || ap2->type==RD_RESOLVED || ap2->type==CONFLICT);
rc = ap1->x.rp->index - ap2->x.rp->index;
}
return rc;
}
/* Sort parser actions */
struct action *Action_sort(struct action *ap)
{
ap = (struct action *)msort((char *)ap,(char **)&ap->next,actioncmp);
return ap;
}
void Action_add(
struct action **app,
enum e_action type,
struct symbol *sp,
char *arg)
{
struct action *new;
new = Action_new();
new->next = *app;
*app = new;
new->type = type;
new->sp = sp;
if (type==SHIFT) {
new->x.stp = (struct state *)arg;
} else {
new->x.rp = (struct rule *)arg;
}
}
/********************** New code to implement the "acttab" module ***********/
/*
** This module implements routines use to construct the yy_action[] table.
*/
/*
** The state of the yy_action table under construction is an instance of
** the following structure
*/
typedef struct acttab acttab;
struct acttab {
int nAction; /* Number of used slots in aAction[] */
int nActionAlloc; /* Slots allocated for aAction[] */
struct {
int lookahead; /* Value of the lookahead token */
int action; /* Action to take on the given lookahead */
} *aAction, /* The yy_action[] table under construction */
*aLookahead; /* A single new transaction set */
int mnLookahead; /* Minimum aLookahead[].lookahead */
int mnAction; /* Action associated with mnLookahead */
int mxLookahead; /* Maximum aLookahead[].lookahead */
int nLookahead; /* Used slots in aLookahead[] */
int nLookaheadAlloc; /* Slots allocated in aLookahead[] */
};
/* Return the number of entries in the yy_action table */
#define acttab_size(X) ((X)->nAction)
/* The value for the N-th entry in yy_action */
#define acttab_yyaction(X,N) ((X)->aAction[N].action)
/* The value for the N-th entry in yy_lookahead */
#define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead)
/* Free all memory associated with the given acttab */
void acttab_free(acttab *p) {
free (p->aAction);
free (p->aLookahead);
free (p);
}
/* Allocate a new acttab structure */
acttab *acttab_alloc(void) {
acttab *p = malloc (sizeof(*p)) ;
if (p==0) {
fprintf(stderr,"Unable to allocate memory for a new acttab.");
exit(1);
}
memset(p, 0, sizeof(*p));
return p;
}
/* Add a new action to the current transaction set
*/
void acttab_action(acttab *p, int lookahead, int action) {
if (p->nLookahead>=p->nLookaheadAlloc) {
p->nLookaheadAlloc += 25;
p->aLookahead = realloc (p->aLookahead, sizeof(p->aLookahead[0])*p->nLookaheadAlloc) ;
if (p->aLookahead==0) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
}
if (p->nLookahead==0) {
p->mxLookahead = lookahead;
p->mnLookahead = lookahead;
p->mnAction = action;
} else {
if (p->mxLookahead<lookahead) p->mxLookahead = lookahead;
if (p->mnLookahead>lookahead) {
p->mnLookahead = lookahead;
p->mnAction = action;
}
}
p->aLookahead[p->nLookahead].lookahead = lookahead;
p->aLookahead[p->nLookahead].action = action;
p->nLookahead++;
}
/*
** Add the transaction set built up with prior calls to acttab_action()
** into the current action table. Then reset the transaction set back
** to an empty set in preparation for a new round of acttab_action() calls.
**
** Return the offset into the action table of the new transaction.
*/
int acttab_insert(acttab *p) {
int i, j, k, n;
assert (p->nLookahead>0) ;
/* Make sure we have enough space to hold the expanded action table
** in the worst case. The worst case occurs if the transaction set
** must be appended to the current action table
*/
n = p->mxLookahead + 1;
if (p->nAction + n >= p->nActionAlloc) {
int oldAlloc = p->nActionAlloc;
p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
p->aAction = realloc (p->aAction, sizeof(p->aAction[0])*p->nActionAlloc);
if (p->aAction==0) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
for(i=oldAlloc; i<p->nActionAlloc; i++){
p->aAction[i].lookahead = -1;
p->aAction[i].action = -1;
}
}
/* Scan the existing action table looking for an offset where we can
** insert the current transaction set. Fall out of the loop when that
** offset is found. In the worst case, we fall out of the loop when
** i reaches p->nAction, which means we append the new transaction set.
**
** i is the index in p->aAction[] where p->mnLookahead is inserted.
*/
for(i=0; i<p->nAction+p->mnLookahead; i++){
if (p->aAction[i].lookahead<0) {
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
if (k<0) break;
if (p->aAction[k].lookahead>=0) break;
}
if (j<p->nLookahead) continue;
for(j=0; j<p->nAction; j++){
if (p->aAction[j].lookahead==j+p->mnLookahead-i) break;
}
if (j==p->nAction) {
break; /* Fits in empty slots */
}
} else if (p->aAction[i].lookahead==p->mnLookahead) {
if (p->aAction[i].action!=p->mnAction) continue;
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
if (k<0 || k>=p->nAction) break;
if (p->aLookahead[j].lookahead!=p->aAction[k].lookahead) break;
if (p->aLookahead[j].action!=p->aAction[k].action) break;
}
if (j<p->nLookahead) continue;
n = 0;
for(j=0; j<p->nAction; j++){
if (p->aAction[j].lookahead<0) continue;
if (p->aAction[j].lookahead==j+p->mnLookahead-i) n++;
}
if (n==p->nLookahead) {
break; /* Same as a prior transaction set */
}
}
}
/* Insert transaction set at index i. */
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
p->aAction[k] = p->aLookahead[j];
if (k>=p->nAction) p->nAction = k+1;
}
p->nLookahead = 0;
/* Return the offset that is added to the lookahead in order to get the
** index into yy_action of the action */
return i - p->mnLookahead;
}
/********************** From the file "build.c" *****************************/
/*
** Routines to construction the finite state machine for the LEMON

202
c/dsls/lemon_action.c Normal file
View file

@ -0,0 +1,202 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lemon_assert.h"
#include "lemon_action.h"
// xxx move:
char *msort(char *list, char **next, int (*cmp)());
/*
** Routines processing parser actions in the LEMON parser generator.
*/
/* Allocate a new parser action */
struct action *Action_new() {
static struct action *freelist = 0;
struct action *new;
if (freelist==0) {
int i;
int amt = 100;
freelist = (struct action *)malloc (sizeof(struct action)*amt) ;
if (freelist==0) {
fprintf(stderr,"Unable to allocate memory for a new parser action.");
exit(1);
}
for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
freelist[amt-1].next = 0;
}
new = freelist;
freelist = freelist->next;
return new;
}
/* Compare two actions */
static int actioncmp(struct action *ap1, struct action *ap2)
{
int rc;
rc = ap1->sp->index - ap2->sp->index;
if (rc==0) rc = (int)ap1->type - (int)ap2->type;
if (rc==0) {
assert (ap1->type==REDUCE || ap1->type==RD_RESOLVED || ap1->type==CONFLICT);
assert (ap2->type==REDUCE || ap2->type==RD_RESOLVED || ap2->type==CONFLICT);
rc = ap1->x.rp->index - ap2->x.rp->index;
}
return rc;
}
/* Sort parser actions */
struct action *Action_sort(struct action *ap)
{
ap = (struct action *)msort((char *)ap,(char **)&ap->next,actioncmp);
return ap;
}
void Action_add(
struct action **app,
enum e_action type,
struct symbol *sp,
char *arg)
{
struct action *new;
new = Action_new();
new->next = *app;
*app = new;
new->type = type;
new->sp = sp;
if (type==SHIFT) {
new->x.stp = (struct state *)arg;
} else {
new->x.rp = (struct rule *)arg;
}
}
/* Free all memory associated with the given acttab */
void acttab_free(acttab *p) {
free (p->aAction);
free (p->aLookahead);
free (p);
}
/* Allocate a new acttab structure */
acttab *acttab_alloc(void) {
acttab *p = malloc (sizeof(*p)) ;
if (p==0) {
fprintf(stderr,"Unable to allocate memory for a new acttab.");
exit(1);
}
memset(p, 0, sizeof(*p));
return p;
}
/* Add a new action to the current transaction set
*/
void acttab_action(acttab *p, int lookahead, int action) {
if (p->nLookahead>=p->nLookaheadAlloc) {
p->nLookaheadAlloc += 25;
p->aLookahead = realloc (p->aLookahead, sizeof(p->aLookahead[0])*p->nLookaheadAlloc) ;
if (p->aLookahead==0) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
}
if (p->nLookahead==0) {
p->mxLookahead = lookahead;
p->mnLookahead = lookahead;
p->mnAction = action;
} else {
if (p->mxLookahead<lookahead) p->mxLookahead = lookahead;
if (p->mnLookahead>lookahead) {
p->mnLookahead = lookahead;
p->mnAction = action;
}
}
p->aLookahead[p->nLookahead].lookahead = lookahead;
p->aLookahead[p->nLookahead].action = action;
p->nLookahead++;
}
/*
** Add the transaction set built up with prior calls to acttab_action()
** into the current action table. Then reset the transaction set back
** to an empty set in preparation for a new round of acttab_action() calls.
**
** Return the offset into the action table of the new transaction.
*/
int acttab_insert(acttab *p) {
int i, j, k, n;
assert (p->nLookahead>0) ;
/* Make sure we have enough space to hold the expanded action table
** in the worst case. The worst case occurs if the transaction set
** must be appended to the current action table
*/
n = p->mxLookahead + 1;
if (p->nAction + n >= p->nActionAlloc) {
int oldAlloc = p->nActionAlloc;
p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
p->aAction = realloc (p->aAction, sizeof(p->aAction[0])*p->nActionAlloc);
if (p->aAction==0) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
for(i=oldAlloc; i<p->nActionAlloc; i++){
p->aAction[i].lookahead = -1;
p->aAction[i].action = -1;
}
}
/* Scan the existing action table looking for an offset where we can
** insert the current transaction set. Fall out of the loop when that
** offset is found. In the worst case, we fall out of the loop when
** i reaches p->nAction, which means we append the new transaction set.
**
** i is the index in p->aAction[] where p->mnLookahead is inserted.
*/
for(i=0; i<p->nAction+p->mnLookahead; i++){
if (p->aAction[i].lookahead<0) {
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
if (k<0) break;
if (p->aAction[k].lookahead>=0) break;
}
if (j<p->nLookahead) continue;
for(j=0; j<p->nAction; j++){
if (p->aAction[j].lookahead==j+p->mnLookahead-i) break;
}
if (j==p->nAction) {
break; /* Fits in empty slots */
}
} else if (p->aAction[i].lookahead==p->mnLookahead) {
if (p->aAction[i].action!=p->mnAction) continue;
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
if (k<0 || k>=p->nAction) break;
if (p->aLookahead[j].lookahead!=p->aAction[k].lookahead) break;
if (p->aLookahead[j].action!=p->aAction[k].action) break;
}
if (j<p->nLookahead) continue;
n = 0;
for(j=0; j<p->nAction; j++){
if (p->aAction[j].lookahead<0) continue;
if (p->aAction[j].lookahead==j+p->mnLookahead-i) n++;
}
if (n==p->nLookahead) {
break; /* Same as a prior transaction set */
}
}
}
/* Insert transaction set at index i. */
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
p->aAction[k] = p->aLookahead[j];
if (k>=p->nAction) p->nAction = k+1;
}
p->nLookahead = 0;
/* Return the offset that is added to the lookahead in order to get the
** index into yy_action of the action */
return i - p->mnLookahead;
}

53
c/dsls/lemon_action.h Normal file
View file

@ -0,0 +1,53 @@
#ifndef LEMON_ACTION_H
#define LEMON_ACTION_H
#include "lemon_structs.h"
struct action *Action_new();
struct action *Action_sort();
void Action_add(
struct action **app,
enum e_action type,
struct symbol *sp,
char *arg);
/*
** This module implements routines use to construct the yy_action[] table.
*/
/*
** The state of the yy_action table under construction is an instance of
** the following structure
*/
typedef struct acttab acttab;
struct acttab {
int nAction; /* Number of used slots in aAction[] */
int nActionAlloc; /* Slots allocated for aAction[] */
struct {
int lookahead; /* Value of the lookahead token */
int action; /* Action to take on the given lookahead */
} *aAction, /* The yy_action[] table under construction */
*aLookahead; /* A single new transaction set */
int mnLookahead; /* Minimum aLookahead[].lookahead */
int mnAction; /* Action associated with mnLookahead */
int mxLookahead; /* Maximum aLookahead[].lookahead */
int nLookahead; /* Used slots in aLookahead[] */
int nLookaheadAlloc; /* Slots allocated in aLookahead[] */
};
/* Return the number of entries in the yy_action table */
#define acttab_size(X) ((X)->nAction)
/* The value for the N-th entry in yy_action */
#define acttab_yyaction(X,N) ((X)->aAction[N].action)
/* The value for the N-th entry in yy_lookahead */
#define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead)
struct acttab *acttab_alloc(void);
void acttab_free(acttab *p);
acttab *acttab_alloc(void);
void acttab_action(acttab *p, int lookahead, int action);
int acttab_insert(acttab *p);
#endif // LEMON_ACTION_H