%<$DNN GRAMMAR Condenser - Ver DN-1A(2) - [PQN-OTFA]$> % Copyright 1989--1990 by David Ness % Not to be sold, but may be used freely for any purpose or for any purposes of % Norman Ramsey \let\RA\rightarrow \def\vert{{\tt\char'174}} \def\pb{$\.|\ldots\.|$} % C brackets (|...|) \def\title{DNN GRAMMAR Condenser} \def\topofcontents{\null\vfill \titlefalse % include headline on the contents page \def\rheader{\hfil} \centerline{\titlefont The {\ttitlefont DNN GRAMMAR} Condenser} \vfill} \def\syntax##1{\leavevmode\hbox{$\langle\hbox{\sl ##1\/}\rangle$}} \def\produces{\leavevmode\hbox{${}::={}$}} \def\opt##1{$[$##1$]$} #*=The {\tt SPIDER} grammar condenser. #*Introduction. This is an \.{AWK} program designed to read a description of a grammar and to produce calls on |squash| instead of |reduce| where it can. This might not look very important, but the grammar of {\tt C} is such that MicroSoft C 5.1 can't handle the \.{WEB} for \.{WEAVE} because the |translate| function turns out to be too large. By good luck, the condensation done here manages to (just) avoid that! The philosophy here is very simple. We are only `interested' in lines which begin with |app1| or |reduce|. When they begin with |app1(pp+n...| we table |n| in the array |data| and don't generate anything. When they begin with |reduce| we check and see if the |reduce| is consistent with the |app1|s. If so then we just generate one |squash| for the whole mess. In all other cases (an inconsistent |reduce| or neither an |app1| or |reduce|) we generate all of the lines (if there were any) that got swallowed into the |data| array. #d banner = "DNN GRAMMAR.WEB Condenser -> OUT.TMP Ver DN-1A(2)" #u#1 BEGIN { # # } #@ # # #@ END { # } # #= out = "out.tmp" Base = 0 # |dumparray()| dumps any |app1(pp+...)|'s that have been accumulated so far. It is called when we get anything other than a |reduce| or |app1|, or if we get a |reduce| but it isn't {\it the right stuff!} #= function dumparray() { if (Base != 0) { for (i = 0; i < Base; ++i) print "\tapp1(pp+" data[i] ");" >out delete data Base = 0 } print $0 >out return } # If we have an |app1(pp+n)| enter |n| into the table and keep going #= #=/app1\(pp\+/#> { match($0,"app1\\(pp\\+.*\\)") val = substr($0,RSTART+8,RLENGTH-9) data[Base++] = val } # If we hit a |reduce(...)|, see if we should process it. #= #=/reduce/#> { match($0,"reduce\\(pp\\+[0-9]*\\,") val = substr($0,RSTART+10,RLENGTH-11) if (data[0] == val) #<|reduce| starts where first |app1| started#>#; else {dumparray()} } # #<|reduce| starts where first |app1| started#>= { match($0,",[0-9]+,") val = substr($0,RSTART+1,RLENGTH-2) if (val == (1+data[Base-1]-data[0])) #<|reduce| condenses right number of elements#>#; else {dumparray()} } # #<|reduce| condenses right number of elements#>= { match($0,"\\(.*\\);") print "\tsquash" substr($0,RSTART,RLENGTH) >out delete data Base = 0 } # When we encounter an `uninteresting' statement, dump anything that we might have accumulated. #= #=$0 !~ /app1|reduce/#> {dumparray()} # #=print banner # #= #*=Index.