nacc was a program I worked on in my spare time, many years ago (early 1980's?); I never completed it. The name is a take-off on yacc(1) (Yet Another Compiler-Compiler). An article, "A LALR(1) Grammar For '82 Ada" by Philippe Charles and Gerald Fisher (ACM Ada Letters, Volume II, Number 2, Sept-Oct 1982), was the inspiration for nacc: I wanted to build an Ada syntax checker. If memory serves, nacc was intended to generate LALR parse tables which I would feed into a yet-to-be-written parser.
nacc (what there was of it) was written in FORTRAN. Before you roll on the floor laughing, remember that this was the early or mid 1980's. We were a VMS shop (an excellent one, by the way) - no Ada, no UNIX, no C, no YACC, no Internet, etc. And, face it, FORTRAN 77 blows C away in the string handling department. From the looks of the output, it looks like I got as far as generating the LR(0) sets of items; I remember studying the dragon book trying to figure out the algorithm for going from LR(0) to LALR. (The meanings of these compiler terms are pretty hazy now!)
The structure chart for the program, as built:
NOT_ANOTHER_COMPILER_COMPILER
NCDISPLAY
CURSOR_EDIT
READ_GRAMMAR
ADD_SYMBOL *
NCERROR
GETSTRING
ADD_RIGHT_SIDE
ADD_ACTION
ADD_RIGHT_SIDE_SYMBOL
ADD_SYMBOL *
OUTPUT_GRAMMAR_FILE
WRITEVBLK *
PRINT_GRAMMAR
GENERATE_LR0_SETS_OF_ITEMS
INPUT_GRAMMAR_FILE
READVBLK
ADD_ITEM *
COMPUTE_CLOSURE *
ADD_ITEM *
ADD_STATE
SETS_EQUAL
MAKE_LIST
COMPUTE_GOTO
ADD_ITEM *
COMPUTE_CLOSURE *
ADD_GOTO
OUTPUT_LR0_FILE
WRITEVBLK *
PRINT_LR0_SETS_OF_ITEMS
BUILD_PRODUCTION
GENERATE_LALR_SETS_OF_ITEMS
GENERATE_PARSE_TABLE
My test grammar (the input is free format):
%START %IS E
%SYMBOL E %IS
E + T
%OR
T
%SYMBOL T %IS
T * F
%OR
F
%SYMBOL F %IS
( E )
%OR
id
And the LR(0) sets of items:
** State 1 **
Set of Items (Left, Right, Dot):
%START => E
Dot = 0
E => E + T
Dot = 0
E => T
Dot = 0
T => T * F
Dot = 0
T => F
Dot = 0
F => ( E )
Dot = 0
F => ID
Dot = 0
Goto Transitions (Symbol, State):
E => 2
T => 3
F => 4
( => 5
ID => 6
** State 2 **
Set of Items (Left, Right, Dot):
%START => E
Dot = 1
E => E + T
Dot = 1
Goto Transitions (Symbol, State):
+ => 7
** State 3 **
Set of Items (Left, Right, Dot):
E => T
Dot = 1
T => T * F
Dot = 1
Goto Transitions (Symbol, State):
* => 8
** State 4 **
Set of Items (Left, Right, Dot):
T => F
Dot = 1
** State 5 **
Set of Items (Left, Right, Dot):
E => E + T
Dot = 0
E => T
Dot = 0
T => T * F
Dot = 0
T => F
Dot = 0
F => ( E )
Dot = 0
F => ID
Dot = 0
F => ( E )
Dot = 1
Goto Transitions (Symbol, State):
E => 9
T => 3
F => 4
( => 5
ID => 6
** State 6 **
Set of Items (Left, Right, Dot):
F => ID
Dot = 1
** State 7 **
Set of Items (Left, Right, Dot):
T => T * F
Dot = 0
T => F
Dot = 0
F => ( E )
Dot = 0
F => ID
Dot = 0
E => E + T
Dot = 2
Goto Transitions (Symbol, State):
T => 10
F => 4
( => 5
ID => 6
** State 8 **
Set of Items (Left, Right, Dot):
F => ( E )
Dot = 0
F => ID
Dot = 0
T => T * F
Dot = 2
Goto Transitions (Symbol, State):
( => 5
ID => 6
F => 11
** State 9 **
Set of Items (Left, Right, Dot):
E => E + T
Dot = 1
F => ( E )
Dot = 2
Goto Transitions (Symbol, State):
+ => 7
) => 12
** State 10 **
Set of Items (Left, Right, Dot):
T => T * F
Dot = 1
E => E + T
Dot = 3
Goto Transitions (Symbol, State):
* => 8
** State 11 **
Set of Items (Left, Right, Dot):
T => T * F
Dot = 3
** State 12 **
Set of Items (Left, Right, Dot):
F => ( E )
Dot = 3
Pretty cool stuff, huh?!