home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk1.iso
/
altsrc
/
articles
/
11188
< prev
next >
Wrap
Text File
|
1994-08-27
|
27KB
|
530 lines
Newsgroups: alt.sources
Path: wupost!howland.reston.ans.net!vixen.cso.uiuc.edu!uchinews!quads!goer
From: goer@quads.uchicago.edu (Richard L. Goerwitz)
Subject: IBPAG2, part 08
Message-ID: <1994Aug28.042237.25416@midway.uchicago.edu>
Sender: news@uchinews.uchicago.edu (News System)
Reply-To: goer@midway.uchicago.edu
Organization: University of Chicago
References: <1994Aug28.041715.24693@midway.uchicago.edu>
Date: Sun, 28 Aug 1994 04:22:37 GMT
Lines: 517
#!/bin/sh
# this is part 8 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file README continued
#
CurArch=8
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> README
X
X 1) YACC's "$$ = x" constructs are replaced by "return x" (e.g.
X "$$ = $1 + $3" -> "return $1 + $3" [$1 is a synonym for
X "arg1", $3 for "arg3", etc.])
X
X 2) all variables within a given action are, by default, local
X to that action; i.e. they cannot be accessed by other
X actions unless you declare them global elsewhere (e.g. in
X the pass-through part of the declarations section %{ ...
X %})
X
X 3) the %union and %type declarations/tags are not needed by
X Ibpag2 (both for better and for worse)
X
X 4) tokens and symbols are separated from each other by a comma
X in Ibpag2 files (e.g. %token '+', '-' and S : NP, VP)
X
X 5) epsilon is indicated by the keyword "epsilon" (e.g. REL :
X epsilon), and not by an empty RHS
X
X 6) both epsilon and error *may* be declared as %tokens for
X reasons of precedence, although they retain hard-coded
X internal values (-2 and -1, respectively)
X
X 7) all actions must follow the last RHS symbol of the rule
X they apply to (preceded by an optional %prec directive); to
X achieve S : NP { action1 }, VP { action2 }, insert a dummy
X rule: S : NP, dummy, VP { action2 }; dummy : epsilon {
X action1 } ;
X
X 8) YYERROR, YYACCEPT, yyclearin, and yyerrok are the same,
X except they are written IIERROR, IIACCEPT, iiclearin, and
X iierrok (i.e. "ii" replaces "yy")
X
X 9) Ibpag2's input files are tokenized as modified Icon files,
X and, as a consequence, Icon's reserved words must not be
X used as symbols (e.g. "if : if, then" is no go)
X
XI myself find YACC to be ugly. As a result, Ibpag2 is not an exact
XYACC clone. I would like to underscore the fact that I have no
Xintention to move in this direction, either. It's as YACC-like as
Xit's going to get!
X
X Both YACC and non-YACC users should note number 9 in the above
Xlist. Don't use things like "while," "every," "do," etc. as symbols
Xin your grammar! Just use the same rules for Ibpag2 nonterminals as
Xfor Icon variables, and you'll be OK.
X
X For those that just can't bear using anything but a strictly
XYACC-conformant system, I've included a preprocessor with the Ibpag2
Xdistribution called (at one user's recommendation) "iacc." Iacc reads
X&input - assumed to be a YACCish grammar - and sends to &output an
XIbpag2-conformant file. I have not tested this file extensively, and
Xthere are likely to be bugs in the way I've handled the necessary 2
Xtoken lookaheads and value stack references. Give it a whirl, though,
Xif you are feeling adventurous. The only reason I personally use Iacc
Xis that some YACCs (e.g. BSD YACC) have particularly nice debugging
Xmessages and help. If my grammar is particularly complex, I just run
Xit through YACC without action code first, then use Iacc to convert it
Xto Ibpag2 format. Iacc's output, as I noted, is not meant to be
Xpretty, so I invariably end up doing a little editing - usually just
Xrespacing a few rules, and re-inserting any comments that I might have
Xput in the original YACC file.
X
X In general, Ibpag2 (like YACC) handles epsilon moves and
Xindirect cycles. LR-mode shift-reduce conflicts are also handled in
Xthe normal way (i.e. pick the rule with the highest priority, and, in
Xcases where the priority is the same, check the associativities). In
Xcontrast to YACC, Ibpag2 flags reduce/reduce conflicts as errors
X(since these often conceal deeper precedence problems and just plain
Xkludges). Reduce/reduce conflict errors are easily enough remedied,
Xif need be, via (dummy) precedences. One can convert these errors to
Xwarnings by specifying -y on the command line. With the -y option,
Xreduce/reduce conflicts are resolved in favor of the rule that occurs
Xfirst in the grammar. The -y switch also prevents Ibpag2 from
Xaborting on shift/reduce conflicts, telling it instead to resolve in
Xfavor of shift. Basically, -y is a partial YACC compatibility switch.
XNormally (i.e. in SLR mode) Ibpag2 is much more finicky than YACC
Xabout conflicts in its grammars.
X
X Also in contrast to YACC, Ibpag2 supports multiple
Xsimultaneous parsers. Ibpag2 normally names its main parser routine
Xiiparse(). By using the -m command-line option, however, you can
Xoverride this default behavior, and force Ibpag2 to augment this name
Xin some uniquely identifiable fashion. For example, "ibpag2 -m _1 <
Xtmp.ibp > tmp.icn" will force Ibpag2 to write a parser called
X"iiparse_1" to tmp.icn. Note that, instead of calling iilex, this
Xiiparse_1() routine will now call iilex_1, and all necessary global
Xvariables will have _1 appended to them (e.g. errors will become
Xerrors_1). I don't expect that many people will have occasion to use
Xthis feature. It is there, though, for those that want it.
X
X
X4.__Debugging
X
X Constructing and debugging LR(1) family parsers can sometimes
Xbe hair raising, even with a parser generator. Several precautions
Xcan be taken, however, to minimize the agony. The first is to declare
Xall tokens initially as part of a single %token declaration, i.e. with
Xno precedences, and with the same associativities. Also, leave out
Xaction code until the grammar seems to be working. In this stage, you
Xcan even run the grammar through (BSD)YACC or GNU Bison. All you
Xwould need to do is remove the commas between tokens and symbols, and
Xplace a semicolon at the end of every rule. During this and all
Xdebugging stages, supply Ibpag2 with a -v command-line switch. This
Xwill cause Ibpag2 to write a summary of rules, tokens, and its two
Xstate tables to "ibpag2.output" (a bit like GNU Bison, but with a
Xhard-coded name). If you get messages about conflicts in your parse
Xtables (e.g. "unresolvable reduce/reduce conflict, state 5, token
X257, rules 4,5"). This file will tell you what rules these are, and
Xwhat token number 257 is. Use precedences and associativities to
Xclear these problems up as they arise. If you are comfortable having
Xreduce/reduce errors resolved by the order in which the conflicting
Xrules occur, then use the -y command-line switch. With -y on the
Xcommand line, Ibpag2 will always resolve in favor of the earlier rule.
XThis option will also cause it to resolve all shift/reduce conflicts
Xin favor of shift.
X
X There are certain languages that are not ambiguous that SLR(1)
Xparsers like Ibpag2 will fail to produce an unambiguous parse table
Xfor. The classic example is
X
X expr : lval, '=', rval | rval
X lval : '*', rval | ID
X rval : lval
X
XC programmers will recognize this as a toy expression grammar with
Xcode for identifiers, assignments, and pointers. The problem is that
Xif we feed this grammar to Ibpag2, it will claim that there is a
Xconflict on lookahead '='. In truth, there is no ambiguity. The SLR
Xparser simply doesn't remember the pathway the parser used to get to
Xthe state it is in when it sees '=' on the input stream. Whether the
Xparser gets into this state by seeing '*' plus and ID, or by seeing
Xjust an ID, it knows to turn the ID into an lval. Then it knows to
Xturn lval into rval. At this point, though, it doesn't know whether
Xto shift the = sign via rule 1, or to turn rval and the preceding '*'
Xinto an lval. The parser has "forgotten" that the '*' is there
Xwaiting on level down on the stack!
X
X The solution to this problem is actually quite simple (at
Xleast in concept). Just provide a unique pathway in the grammar for
Xthe conflicting rules. In this case, they are rules 1 and 5 (the
Xfirst and last):
X
X expr : lval, '=', rval | rval
X lval : '*', pval | ID
X pval : lval
X rval : lval
X
XNow when the parser sees '*,' it can only have a pval after it. Never
Xmind that pval is composed of precisely the same things as rval. The
Xpoint is that the parser generator follows a different route after
Xseeing '*' than if it starts with ID and no preceding '*'. Hence it
X"remembers" that that the '*' is back on the stack, waiting for the
X"lval : '*', pval" rule to apply. There is no more conflict.
X
X Go ahead and run these grammars through Ibpag2 if you aren't
Xsure what is going on. Remember to declare ID as a token, and to
Xplace "%%" in the appropriate spot!
X
X If you get your parser up and running, but find that it is not
Xfunctioning quite the way you expect, add the following line somewhere
Xnear the start of Ibpag2's output file:
X
X $define IIDEBUG
X
XIf you like, you can add it to the beginning of your Ibpag2 input
Xfile. Place it in the declarations section (before the first double
Xpercent sign), and surround it by %{ and %}, e.g.:
X
X %{
X $define IIDEBUG
X %}
X
XThis tells Ibpag2 to send $define IIDEBUG straight through to the
Xoutput file.
X
X What defining IIDEBUG does is tell iiparse, once compiled, to
Xemit profuse debugging messages about the parser's actions, and about
Xthe state of its stacks. This display will not make a whole lot of
Xsense to anyone who doesn't understand LR-family parsers, so those who
Xwant to access this feature should perhaps go through a standard
Xreference like Aho, Sethi, and Ullman [1].
X
X If, after you are finished debugging your grammar, you find
Xthat Ibpag2's output files are rather large, you may try saving space
Xby compressing the action and goto tables. This is accomplished by
Xinvoking Ibpag2 with the -c (compress) option. Using this option
Xmakes debugging difficult, and makes the parser run a bit more slowly.
XIt also only works for rather large grammars with long nonterminal
Xsymbol names. Don't even consider it until the grammar is thoroughly
Xdebugged and you have determined that the output file's size is just
Xtoo great for practical use. Even then, compression may or may not
Xhelp, depending on how long your nonterminal names are. In general,
XIbpag2 is best as a teaching tool, or as a production system for
Xmedium or small grammars.
X
X
X5.__Using_Ibpag2_with_Non-LR_Grammars
X
X There may be times when you *want* to parse languages that no
XLR-based algorithm can handle. There may be times, that is, when the
Xgrammar you want to use contains conflicts or ambiguities that are
Xthere by design, and not by oversight. For example, you may want to
Xparse a natural language. Full-blown natural languages involve many
Xhighly ambiguous constructs, and are not LR-parsable. By invoking it
Xwith the -a option, Ibpag2 can parse or recognize certain natural
Xlanguages, or, more practically speaking, certain NL subsets. The
Xletter "a" in -a is supposed to stand for "ambiguous," although what
Xthis option really does is put Ibpag2 into a quasi-GLR mode - i.e.
Xinto a kind of "generalized" LR mode in which it can accept non-LR
Xgrammars [4,5].
X
X User-visible changes to Ibpag2's operation in quasi-GLR mode
X(i.e. with the -a option) are as follows:
X
X 1) iiparse() is now a generator
X 2) action code can use suspend as well as return
X 3) IIERROR places the current thread in an error state (i.e.
X it doesn't *necessarily* trigger error recovery; see below)
X 4) there are two new action-code directives (iiprune and
X iiisolate) and a general define (AUTO_PRUNE)
X 5) conflicts due to ambiguities in the grammar no longer
X result in aborted processing (so, e.g., if you do not
X specify the -y option on a grammar with reduce/reduce
X conflicts, Ibpag2 will simply generate a parser capable of
X producing multiple parses for the same input)
X
X In quasi-GLR mode, iiparse() should be invoked in a way that
Xwill render multiple results usable, if they are available (e.g.
X"every result := iiparse(&input) do...". Action code is also allowed
Xto produce more than one value (i.e. to use suspend). When it does
Xso, iiparse() creates separate parse threads for each value. So, for
Xinstance, if your action code for some production suspends both of the
Xfollowing lists,
X
X ["noun", "will", "gloss: desire"]
X ["noun", "will", "gloss: legal document mandating how _
X one's possessions are to be disposed _
X of after one's death"],
X
Xiiparse() would create two separate parse threads - one for each
Xresult. Note that in this case, the syntactic structure of each
Xthread is the same. It is their semantics (i.e. the stuff on the
Xvalue stack) that differs.
X
X If you use the iierrok and iiclearin macros in your action
Xcode before suspending any result, their affect persists through all
Xsubseqent suspensions and resulting parse threads. If you use these
Xmacros after suspending one or more times, however, they are valid
Xonly for the parse thread generated by the next suspension. By way of
Xcontrast, the IIERROR macro *always* flags only the next parse thread
Xas erroneous. Likewise, IIACCEPT always simulates an accept action on
Xthe next suspension only. IIERROR and IIACCEPT, in other words, never
Xhave any effect on subsequent suspensions and parse threads other than
Xthe one that immediately follows them. This is true of iierrok and
Xiiclearin only when used after the first suspension.
X
X In quasi-GLR mode, IIERROR (number three in the difference
Xlist above) becomes a mechanism for placing the current parse thread
Xin error mode. This is similar to, but not quite identical to, how
XIIERROR functions in straight LR mode. In quasi-GLR mode, if other
Xthreads can carry on the parse without error the erroneous parse
Xthread is quietly clobbered. Full-blown error recovery only occurs if
Xall of the other parsers halt as well. This makes sense if you think
Xabout it. Why keep erroneous threads around when there are threads
Xstill continuing a valid parse? For some large interactive systems,
Xit might be necessary to keep bogus threads around longer, and weed
Xthem out only after a lengthy grading process. If you are
Xconstructing a system such as this, you'll have to modify Ibpag2's
Xiiglrpar.lib file. In particular, you'll need to change the segment
Xin iiparse() that takes out the trash, so to speak, in such a way that
Xit does so only if the error count in a given parser either rises
Xabove a specific threshhold or else exceeds the number of errors in
Xthe "most correct" parser by a certain amount. This is not that hard
Xto do. I just don't expect that most parsers people generate with
XIbpag2 will use IIERROR or error recovery in general in so involved a
Xfashion.
X
X Iiprune and iiisolate (number 4 above) are used to control the
Xgrowth of the parallel parser array. In order to give straightforward
X(read "implementationally trivial") support for action code, Ibpag2
Xcannot create a parse "forest" in the sense that a standard GLR parser
Xdoes. Instead, it simply duplicates the current parser environment
Xwhenever it encounters a conflict in its action table. Even if the
Xconflict turns out to reflect only a local ambiguity, the parsers, by
Xdefault, remain separate. Put differently, Ibpag2's quasi-GLR parser,
Xby default, makes no direct effort to reduce the size of its parser
Xarrays or to alter the essentially linear structure of their value and
Xstate stacks. Size reduction, where necessary and/or desirable, is up
Xto the programmer. What the iiprune macro is there to do is to give
Xthe programmer a way of pruning a given thread out of the active
Xparser list. Iiisolate allows him or her to prune out every thread
X*but* the current one. AUTO_PRUNE makes the parser behave more like a
Xstandard GLR parser, instructing it to prune parse threads that are
Xessentially duplicating another parse thread's efforts. The parser,
Xthough, does not build a parse tree per se, the way most GLR parsers
Xtypically do, but rather manipulates its value stack like a
Xtraditional LR-family parser.
X
X Iiprune is useful when, for example, the semantics (i.e. your
X"action" code segments) determine that a given parse thread is no
Xlonger viable, and you want to signal the syntactic analyzer not to
Xcontinue pursuing it. The difference between iiprune and IIERROR is
Xthat iiprune clobbers the current parser immediately. IIERROR only
Xputs it into an error state. If all active parsers end up in an error
Xstate, and none can shift additional input symbols, then the IIERROR
Xmacro induces error recovery. Iiprune does not. NB: iiprune, if used
Xin action code that suspends multiple results, cancels the current and
Xremaining results (i.e. it does not clobber parsers already spun off
Xby previous suspensions by invocation of that same code; it merely
Xcuts the result sequence). Iiprune essentially stands in for "fail"
Xin this situation. Fail itself can be used in the code, but be warned
Xthat iiparse() will still push *at least one* value onto its value
Xstack, even if a given action code segment fails. This keeps the
Xvalue stack in sync with the syntax. To avoid confusion, I recommend
Xnot using "fail" in any action code.
X
X Iiisolate is useful if, during error recovery, you prompt the
Xuser interactively, or do something else that cannot be elegantly done
Xin parallel for two or more distinct parse threads. Iiisolate allows
Xyou to preserve only the the current parse thread, and to clobber the
Xrest. Iiisolate can also be useful as a way of making sure that only
Xone thread carries on the parse in non-error situations. Suppose that
Xwe have a series of productions:
X
X sentences : sentences sentence '\n'
X { print_parse(arg2) }
X | sentences '\n'
X | error '\n'
X | epsilon
X
XIf we get a sentence with more than one parse, all of the underlying
Xthreads that produced these parses will be active for the next
Xsentence as well. In many situations this will not be what we want.
XIf our desire it to have only one active parse thread at the start of
Xeach sentence, we simply tell our lexical analyzer to suspend two
Xnewlines every time it sees a newline on the input stream. This
Xinsures that the second rule will always apply right after the first.
XWe then insert iiisolate directives for both it and the one error
Xproduction:
X
X sentences : sentences sentence '\n'
X { print_parse(arg2) }
X | sentences '\n'
X { iiisolate }
X | error '\n'
X { iiisolate; iierrok }
X | epsilon
X
XThe effect here is to allow multiple parsers to be generated only
Xwhile parsing "sentence". The iiisolate directive, in other words,
Xsees to it that no sentence parse will ever begin with multiple active
Xparsers. As with LR mode, iierrok clears the error flag for the
X(current) parser.
X
X Note that if you use iiisolate in action code that suspends
Xmultiple results, iiisolate will clobber all parsers but the one
Xgenerated by the next suspension.
X
X If there is no need for close control over the details of the
Xparser array, and you wish only to clobber parsers that end up doing
Xthe same thing as some other parser (and hence returning identical
Xvalues), then just make sure you add "$define AUTO_PRUNE" to the
Xpass-through code section at the top of the file. Put differently,
Xdefining AUTO_PRUNE instructs the quasi-GLR parser to weed out parsers
Xthat are in the same state, and which have identical value stacks.
XAUTO_PRUNE can often be used in place of iiisolate in situations like
Xthe one discussed just above. Its only drawback is that it slows
Xthe parser a bit.
X
X Other than these deviations (action code and iiparse becoming
Xgenerators, IIERROR's altered behavior, and the addition of iiprune,
Xiiisolate, and AUTO_PRUNE), Ibpag2's quasi-GLR mode - at least on the
Xsurface - works pretty much like its straight LR mode. In fact, if
Xyou take one of your SLR(1) grammars, and run it through Ibpag2 using
Xthe -a option, you probably won't notice any difference in the
Xresulting automaton unless you do some debugging or perform some
Xtiming tests (the GLR parser is slower, though for straight SLR(1)
Xgrammars not by much). Even with non-SLR(1) grammars, the quasi-GLR
Xparser will clip along merrily, using all the same sorts of rules,
Xaction code, and macros that you would typically use in LR mode!
X
X
X6.__Installing_Ibpag
X
X If you are a UNIX user, or have a generic "make" utility, you
Xare in luck. Just edit Makefile.dist according to the directions
Xgiven in that file, rename it as "makefile," then execute "make."
XIbpag2 should be created automatically. If everything goes smoothly,
Xthen "make install" (su-ing root, if both possible and necessary for
Xcorrect installation of the iiparse.icn file). Check with your system
Xadministrator if you are on a public system, and aren't sure what to
Xdo.
X
X Please be sure to read the directions in the makefile
Xcarefully, and set DESTDIR and LIBDIR to the directory where you want
Xthe executable and parser file to reside. Also, make sure the paths
Xyou specify are correct for your Icon executables. Although Ibpag2
Xwill apparently compile using iconc, I would recommend using the
Xinterpreter, icont, first, unless you are planning on working with a
Xlarge grammar.
X
X If you are using some other system - one that lacks "make" -
Xthen shame on your manufacturer :-). You'll be a bit inconvenienced.
XTry typing:
X
X icont -o ibpag2 follow.icn ibpag2.icn ibreader.icn \
X ibtokens.icn ibutil.icn ibwriter.icn iohno.icn \
X outbits.icn slritems.icn slrtbls.icn shrnktbl.icn \
X version.icn slshupto.icn
X
XThe backslashes merely indicate that the next line is a continuation.
XThe whole thing should, in other words, be on a single line. As noted
Xabove, you may compile rather than interpret - if your OS supports the
XIcon compiler. Just replace "icont" above with "iconc." The
Xresulting executable will run considerably faster than with "icont,"
Xalthough the time required to compile it may be large, and the (still
Xsomewhat experimental) compiler may not work smoothly in all
Xenvironments.
X
X If your operating system support environment variables, and
Xyou have set up your LPATH according to the specifications in the Icon
Xdistribution (see below), then you may copy iiparse.lib and
Xiiglrpar.lib to some file in your LPATH. If you do not do this, or if
Xyour OS does not support environment variables, then you must be in
Xthe directory where you keep your Ibpag2 files when you use it, or
Xelse invoke Ibpag2 with the -p dirname option (where dirname is the
Xdirectory that holds the iiparse.lib and iiglrpar.lib files that come
Xwith the Ibpag2 distribution). The .lib files contain template
Xparsers that are critical to Ibpag2's operation. Ibpag2 will abort if
Xit cannot find them.
X
X If your operating system permits the creation of macros or
Xbatch files, it might be useful to create one that changes
Xautomatically to the Ibpag2 source directory, and runs the executable.
XThis has the side-benefit of making it easier for Ibapg2 to find the
Xparser library files, iiparse.lib and iiglrpar.lib. Under DOS, for
Xinstance, one might create a batch file that says:
X
X c:
X cd c:\ibpag2
X iconx ibpag2 %1 %2 %3 %4 %5 %6 %7 %8 %9
X
XDOS, it turns out, has to execute Icon files indirectly through iconx,
Xso this technique has yet another advantage in that it hides the
Xsecond level of indirection - although it prevents you from using
Xinput and output redirection. Naturally, the above example assumes
Xthat Ibpag2 is in c:\ibpag2.
X
X Ibpag2 assumes the existence on your system, not only of an
XIcon interpreter or compiler, but also of an up-to-date Icon Program
XLibrary. There are several routines included in the IPL that Bibleref
Xuses. Make sure you (or the local system administrators) have put the
XIPL online, and have translated the appropriate object modules. Set
Xyour IPATH environment variable to point to the place where the object
Xmodules reside. Set LPATH to point to the modules' source files.
XBoth IPATH and LPATH are documented in doc directory of the Icon
Xsource tree (ipd224.doc). If your system does not support environment
Xvariables, copy ximage.icn, options.icn, ebcdic.icn, and escape.icn
Xfrom the IPL into the Ibpag2 source directory, and compile them in
Xwith the rest of the Ibpag2 source files, either by adding them to the
XSRC variable in the makefile, or by adding them manually to the "icont
X-o ..." command line given above.
X
X If you have any problems installing or using Ibpag2, please
Xfeel free to drop me, Richard Goerwitz, an e-mail message at
Xgoer@midway.uchicago.edu, or (via the post) at:
X
X 5410 S. Ridgewood Ct., 2E
X Chicago, IL 60615
X
X
X6.__Bibliography
X
X1. Aho, Alfred V., Sethi, Ravi, and Ullman, Jeffrey D. Compilers.
X Addison-Wesley: Reading, Massachusetts, second printing, 1988.
X
X2. Griswold, Ralph E. and Griswold, Madge T. The Icon Programming
X Language. Prentice-Hall, Inc.: Englewood Cliffs, New Jersey, USA,
X second edition, 1990.
X
X3. Griswold, Ralph E., Jeffery, Clinton L., and Townsend, Gregg M.
X Version 8.10 of the Icon Programming Language. Univ. of Arizona
X Icon Project Document 212, 1993. (obtain via anonymous FTP from
X cs.arizona.edu ~ftp/icon/docs/ipd212.doc)
X
X4. Tomita, Masaru. Efficient Parsing for Natural Language. Boston:
X Kluwer Academic Publishers, c. 1985.
X
X5. Tomita, Masaru editor. Generalized LR Parsing. Boston: Kluwer
X Academic Publishers, 1991.
SHAR_EOF
chmod 0444 README || echo "restore of README fails"
rm -f s2_seq_.tmp
echo "You have unpacked the last part"
exit 0
--
-Richard L. Goerwitz goer%midway@uchicago.bitnet
goer@midway.uchicago.edu rutgers!oddjob!ellis!goer