Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Several improvements to the code #6

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
*.swp
*.o
lemon
lemon.exe

# Xcode
#
build/
Expand Down
4 changes: 4 additions & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ex[0-9]
example[0-9].[ch]
example[0-9].out
lexer.c
36 changes: 36 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
all: examples

EXES = \
ex1 \
ex2 \
ex3 \
ex4 \
ex5 \

ex1: example1.y exp1.c
lemon example1.y
cc -o $@ exp1.c

ex2: example2.y exp2.c
lemon example2.y
cc -o $@ exp2.c

ex3: example3.y exp3.c
lemon example3.y
cc -o $@ exp3.c

ex4: example4.y exp4.c
lemon example4.y
cc -o $@ exp4.c

ex5: example5.y exp5.c lexer.l
lemon example5.y
flex -o lexer.c lexer.l
cc -o $@ exp5.c lexer.c

examples: $(EXES)

clean:
rm -f $(EXES)
rm -f example[0-9].{c,h,out}
rm -f lexer.c
10 changes: 5 additions & 5 deletions examples/README
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ http://sourceforge.net/project/filemodule_monitor.php?filemodule_id=124528

example1.y
~~~~~~~~~~
This is a very simple calulator. To compile the
This is a very simple calculator. To compile the
example do the following:

$ make
Expand Down Expand Up @@ -79,7 +79,7 @@ example2.y

This structure supports both a value and a count.
You could add many more values, and allocate memory
to z if you wanted. One, note, you cannot put in
to z if you wanted. One note, you cannot put in
C++ strings or other STL containers directly into
this structure; instead, you would need to have pointers
to such structures. Note, if memory was allocated for z, you'd
Expand All @@ -95,7 +95,7 @@ example3.y

example4.y
~~~~~~~~~~
This is the first example that ends the grammer with
This is the first example that ends the grammar with
a newline.

In the file example4.y take a look at the following:
Expand All @@ -116,7 +116,7 @@ example4.y
example5.y
~~~~~~~~~~
This example puts everything together with flex. But,
take a peek at how lexer.l is complied in the Makefile
take a peek at how lexer.l is compiled in the Makefile
with "flex lexer.l" instead of "flex++ lexer.l". The
main_part5 for this example is in C++, so it's necessary
to add the extern "C" directives. True it could have been
Expand Down Expand Up @@ -159,7 +159,7 @@ http://www.hwaci.com/sw/lemon/
(4) Home of sqlite
http://www.sqlite.org/

(5) Glossory of paser terms
(5) Glossary of parser terms
http://www.parsifalsoft.com/gloss.html

(6) Good introduction to parsers
Expand Down
41 changes: 41 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
all: lemon

CFLAGS += -Wall
CFLAGS += -Wextra
# CFLAGS += -g
# CFLAGS += -O

C_SRCS = \
action.c \
build.c \
configlist.c \
error.c \
main.c \
msort.c \
option.c \
parse.c \
plink.c \
report.c \
set.c \
table.c \

INSTALL_DIR = /usr/local
INSTALL_DIR_BIN = $(INSTALL_DIR)/bin
INSTALL_DIR_SHARE = $(INSTALL_DIR)/share/lemon

C_OBJS = $(C_SRCS:.c=.o)

%.o: %.c
cc $(CFLAGS) -c -o $@ $^

lemon: $(C_OBJS)
cc -o $@ $^

install: lemon
mkdir -p $(INSTALL_DIR) $(INSTALL_DIR_BIN) $(INSTALL_DIR_SHARE)
cp lemon $(INSTALL_DIR_BIN)
cp ../templates/skeleton.c $(INSTALL_DIR_SHARE)

clean:
rm -f $(C_OBJS)
rm -f lemon
76 changes: 39 additions & 37 deletions src/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
#include "struct.h"
#include "table.h"

void FindRulePrecedences(struct lemon *xp)
void FindRulePrecedences(struct lemon *lemp)
{
struct rule *rp;
for(rp=xp->rule; rp; rp=rp->next){
for(rp=lemp->rule; rp; rp=rp->next){
if( rp->precsym==0 ){
int i, j;
for(i=0; i<rp->nrhs && rp->precsym==0; i++){
Expand All @@ -46,14 +46,14 @@ void FindFirstSets(struct lemon *lemp)
int i, j;
struct rule *rp;
int progress;

for(i=0; i<lemp->nsymbol; i++){
lemp->symbols[i]->lambda = LEMON_FALSE;
}
for(i=lemp->nterminal; i<lemp->nsymbol; i++){
lemp->symbols[i]->firstset = SetNew();
}

/* First compute all lambdas */
do{
progress = 0;
Expand All @@ -69,7 +69,7 @@ void FindFirstSets(struct lemon *lemp)
}
}
}while( progress );

/* Now compute all first sets */
do{
struct symbol *s1, *s2;
Expand Down Expand Up @@ -98,15 +98,15 @@ void FindFirstSets(struct lemon *lemp)
return;
}

PRIVATE struct state *getstate(/* struct lemon * */); /* forward reference */
PRIVATE struct state *getstate(struct lemon *lemp); /* forward reference */

void FindStates(struct lemon *lemp)
{
struct symbol *sp;
struct rule *rp;

Configlist_init();

/* Find the start symbol */
if( lemp->start ){
sp = Symbol_find(lemp->start);
Expand All @@ -121,7 +121,7 @@ void FindStates(struct lemon *lemp)
}else{
sp = lemp->rule->lhs;
}

/* Make sure the start symbol doesn't occur on the right-hand side of
** any rule. Report an error if it does. (YACC would generate a new
** start symbol in this case.) */
Expand All @@ -137,7 +137,7 @@ void FindStates(struct lemon *lemp)
}
}
}

/* The basis configuration set for the first state
** is all rules which have the start symbol as their
** left-hand side */
Expand All @@ -147,7 +147,7 @@ void FindStates(struct lemon *lemp)
newcfp = Configlist_addbasis(rp,0);
SetAdd(newcfp->fws,0);
}

/* Compute the first state. All other states will be
** computed automatically during the computation of the first one.
** The returned pointer to the first state is not used. */
Expand All @@ -163,12 +163,12 @@ PRIVATE struct state *getstate(struct lemon *lemp)
{
struct config *cfp, *bp;
struct state *stp;

/* Extract the sorted basis of the new state. The basis was constructed
** by prior calls to "Configlist_addbasis()". */
Configlist_sortbasis();
bp = Configlist_basis();

/* Get a state with the same basis */
stp = State_find(bp);
if( stp ){
Expand Down Expand Up @@ -203,9 +203,7 @@ PRIVATE struct state *getstate(struct lemon *lemp)
/*
** Return true if two symbols are the same.
*/
int same_symbol(a,b)
struct symbol *a;
struct symbol *b;
int same_symbol(struct symbol *a, struct symbol *b)
{
int i;
if( a==b ) return 1;
Expand All @@ -221,28 +219,28 @@ struct symbol *b;
/* Construct all successor states to the given state. A "successor"
** state is any state which can be reached by a shift action.
*/
PRIVATE void buildshifts(lemp,stp)
struct lemon *lemp;
struct state *stp; /* The state from which successors are computed */
PRIVATE void buildshifts(
struct lemon *lemp,
struct state *stp) /* The state from which successors are computed */
{
struct config *cfp; /* For looping thru the config closure of "stp" */
struct config *bcfp; /* For the inner loop on config closure of "stp" */
struct config *new; /* */
struct symbol *sp; /* Symbol following the dot in configuration "cfp" */
struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
struct state *newstp; /* A pointer to a successor state */

/* Each configuration becomes complete after it contibutes to a successor
** state. Initially, all configurations are incomplete */
for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;

/* Loop through all configurations of the state "stp" */
for(cfp=stp->cfp; cfp; cfp=cfp->next){
if( cfp->status==COMPLETE ) continue; /* Already used by inner loop */
if( cfp->dot>=cfp->rp->nrhs ) continue; /* Can't shift this config */
Configlist_reset(); /* Reset the new config set */
sp = cfp->rp->rhs[cfp->dot]; /* Symbol after the dot */

/* For every configuration in the state "stp" which has the symbol "sp"
** following its dot, add the same configuration to the basis set under
** construction but with the dot shifted one symbol to the right. */
Expand All @@ -255,11 +253,11 @@ struct state *stp; /* The state from which successors are computed */
new = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
Plink_add(&new->bplp,bcfp);
}

/* Get a pointer to the state described by the basis configuration set
** constructed in the preceding loop */
newstp = getstate(lemp);

/* The state "newstp" is reached from the state "stp" by a shift action
** on the symbol "sp" */
if( sp->type==MULTITERMINAL ){
Expand All @@ -279,7 +277,7 @@ void FindLinks(struct lemon *lemp)
struct config *cfp, *other;
struct state *stp;
struct plink *plp;

/* Housekeeping detail:
** Add to every propagate link a pointer back to the state to
** which the link is attached. */
Expand All @@ -289,7 +287,7 @@ void FindLinks(struct lemon *lemp)
cfp->stp = stp;
}
}

/* Convert all backlinks into forward links. Only the forward
** links are used in the follow-set computation. */
for(i=0; i<lemp->nstate; i++){
Expand All @@ -310,13 +308,13 @@ void FindFollowSets(struct lemon *lemp)
struct plink *plp;
int progress;
int change;

for(i=0; i<lemp->nstate; i++){
for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
cfp->status = INCOMPLETE;
}
}

do{
progress = 0;
for(i=0; i<lemp->nstate; i++){
Expand All @@ -335,7 +333,10 @@ void FindFollowSets(struct lemon *lemp)
}while( progress );
}

static int resolve_conflict();
static int resolve_conflict(
struct action *apx,
struct action *apy,
struct symbol *errsym); /* forward reference */

void FindActions(struct lemon *lemp)
{
Expand All @@ -344,7 +345,7 @@ void FindActions(struct lemon *lemp)
struct state *stp;
struct symbol *sp;
struct rule *rp;

/* Add all of the reduce actions
** A reduce action is added for each element of the followset of
** a configuration which has its dot at the extreme right.
Expand All @@ -363,7 +364,7 @@ void FindActions(struct lemon *lemp)
}
}
}

/* Add the accepting token */
if( lemp->start ){
sp = Symbol_find(lemp->start);
Expand All @@ -375,7 +376,7 @@ void FindActions(struct lemon *lemp)
** finite state machine) an action to ACCEPT if the lookahead is the
** start nonterminal. */
Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);

/* Resolve conflicts */
for(i=0; i<lemp->nstate; i++){
struct action *ap, *nap;
Expand All @@ -391,7 +392,7 @@ void FindActions(struct lemon *lemp)
}
}
}

/* Report an error for each rule that can never be reduced. */
for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE;
for(i=0; i<lemp->nstate; i++){
Expand Down Expand Up @@ -420,11 +421,12 @@ void FindActions(struct lemon *lemp)
** If either action is a SHIFT, then it must be apx. This
** function won't work if apx->type==REDUCE and apy->type==SHIFT.
*/
static int resolve_conflict(apx,apy,errsym)
struct action *apx;
struct action *apy;
struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
static int resolve_conflict(
struct action *apx,
struct action *apy,
struct symbol *errsym) /* The error symbol (NULL otherwise) */
{
UNUSED_ARG(errsym);
struct symbol *spx, *spy;
int errcnt = 0;
assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */
Expand Down
Loading