home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume38 / ibpag2 / part02 < prev    next >
Encoding:
Text File  |  1993-07-12  |  54.2 KB  |  1,143 lines

  1. Newsgroups: comp.sources.misc
  2. From: goer@midway.uchicago.edu (Richard L. Goerwitz)
  3. Subject: v38i046:  ibpag2 - Icon-Based Parser Generator, Part02/05
  4. Message-ID: <1993Jul13.044351.17077@sparky.sterling.com>
  5. X-Md4-Signature: ac437851616f92bab10659bfbf3f0ad5
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: University of Chicago
  8. Date: Tue, 13 Jul 1993 04:43:51 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: goer@midway.uchicago.edu (Richard L. Goerwitz)
  12. Posting-number: Volume 38, Issue 46
  13. Archive-name: ibpag2/part02
  14. Environment: Icon
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  README
  21. # Wrapped by kent@sparky on Sun Jul 11 18:51:50 1993
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 2 (of 5)."'
  25. if test -f 'README' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'README'\"
  27. else
  28.   echo shar: Extracting \"'README'\" \(52712 characters\)
  29.   sed "s/^X//" >'README' <<'END_OF_FILE'
  30. X
  31. X
  32. X
  33. X
  34. X
  35. X
  36. X               A User's Manual for Ibpag2
  37. X           (Icon-Based Parser Generation System 2)
  38. X                 Version 1.2
  39. X
  40. X                - or -
  41. X
  42. X           How to Use an LR-based Parser Generator
  43. X
  44. X
  45. X               Richard L. Goerwitz, III
  46. X            University of Chicago
  47. X
  48. X
  49. X
  50. X
  51. X
  52. X
  53. X1.__What_is_Ibpag2?
  54. X
  55. X    Ibpag2 is a so-called "parser generator," i.e. a tool for
  56. Xautomating the process of generating a recognizer and/or parser from
  57. Xabstract structural descriptions of an input language.  Put in more
  58. Xpractical terms, Ibpag2 is a piece of software that a) reads a source
  59. Xfile containing a grammar that defines an input language, and then b)
  60. Xoutputs an automaton that recognizes that language.  The user may, at
  61. Xhis or her option, specify actions this automaton should take when it
  62. Xsees various substructures within its input language.  By default,
  63. Xhowever, the parser simply recognizes a given sequence as belonging,
  64. Xor not, to that language.
  65. X
  66. X    Ibpag2 utilizes so-called "LR" table generation and parsing
  67. Xalgorithms.  These algorithms facilitate construction of reasonably
  68. Xfast deterministic pushdown automata that are powerful enough to
  69. Xhandle most commonly used programming language constructs.  LR-based
  70. Xsystems come in three main flavors: SLR(1), LALR(1), and LR(1).  The
  71. XLR(1) flavor is fairly easy to implement, but uses too many resources
  72. Xto be practical.  LALR(1) algorithms are harder to implement, but much
  73. Xfaster, and the parse tables they construct use considerably less
  74. Xmemory than do those of their LR(1) counterparts.  SLR(1) algorithms
  75. Xare the easiest to implement, compile the fastest, and use about as
  76. Xmuch memory as LALR(1)s.  SLR(1) is the least powerful of the three,
  77. Xthough, so there is a tradeoff.  Ibpag2 is an "enhanced" SLR(1) parser
  78. Xgenerator.  It is enhanced in the sense that it can operate both in
  79. Xits native SLR(1) mode, and in a more powerful "quasi-GLR" mode (on
  80. Xwhich, see section 5 below).
  81. X
  82. X    As its full title ("Icon-Based Parser Generator 2") implies,
  83. XIbpag2 is written in Icon [2,3], as are the automata it creates.
  84. XIbpag2 has been tested with Icon version 8.10.  So far I have only run
  85. Xit on an i386 box running Xenix 2.3.3, and on a Sun 4 running some
  86. Xversion of SunOS.  I have many reports, though, of it running under
  87. Xother UNIX variants.  It will probably also run under other operating
  88. Xsystems, though modifications will in some instances be required.  The
  89. XIbpag2 distribution adheres to de facto UNIX installation standards:
  90. XJust set the appropriate variables in the makefile, and then "make
  91. Xinstall."  For those who are using a non-UNIX system, or who have not
  92. Xinstalled such a package before, there is a section at the end
  93. Xentitled "Installing Ibpag2" that details the installation procedure
  94. X(section 6).
  95. X
  96. X    Aside from the above-mentioned installation section (6), the
  97. Xremainder of this document aims to provide the reader a) with a
  98. Xsimple, practical explanation of what LR-family parser generators are
  99. Xand how they work (section 2), and b) with a set of directions
  100. Xspecifically on how to use Ibpag2 (section 3).  There is also an
  101. Xadvanced section on debugging (4), and one on using Ibpag2 with non-LR
  102. Xand/or ambiguous languages (5).  The discussion is geared for those
  103. Xthat have little or no experience in parsing or automaton theory.  For
  104. Xvery advanced reading, consult the bibliography.  For a brief summary
  105. Xof Ibpag's command-line options, see the main Ibpag2 source file,
  106. Xibpag2.icn, or invoke ibpag2 with the -h (help) option.
  107. X
  108. X    In general, be warned that Ibpag2 works best with small or
  109. Xmedium-sized grammars.  Its parse tables have to be reconstructed at
  110. Xrun-time, and the code for doing this can become a bit cumbersome for
  111. Xgrammars with more than 100 rules and fifty or so terminal symbols.  I
  112. Xmyself have processed grammars with as many as 300 terminals and 400
  113. Xrules.  Although the resulting automata run well enough, the output
  114. Xfiles are over 300k, and Ibpag2 takes a long time to create them.  If
  115. Xyou must use Ibpag2 with a very large grammar symbols, try the -c
  116. Xcommand-line option (which produces compressed parse tables).  This
  117. Xoption is discussed below, in section 4.  Compiling (rather than
  118. Xinterpreting) Ibpag2 may result in much faster processing, as will
  119. Xresetting your BLOCKSIZE and STRSIZE environment variables.  See the
  120. Xinstallation section (6) below on using the Icon compiler to create
  121. Xthe Ibpag2 executable.  Good starting values for BLOCKSIZE and STRSIZE
  122. Xare triple their default values (i.e. 3 x 65000).  These variables are
  123. Xdiscussed in the Icon manual page.
  124. X
  125. X    My ultimate aim in writing this document has been to make
  126. Xaccessible to the non-CS portion of the Icon community what for them
  127. Xmight seem an inaccessible branch of applied parsing and automaton
  128. Xtheory.  I am a philologist myself, and feel that there is a great
  129. Xdeal that can and ought to be done to make advanced tools accessible
  130. Xto people with other interests than twiddling bits or pondering the
  131. Xtrue meaning of epsilon closures :-).
  132. X
  133. X    Any comments on the Ibpag2 system itself or its documentation
  134. Xwill be gratefully received.  Write to me at the address appended to
  135. Xthe final section (6).
  136. X
  137. X
  138. X2.__What_is_an_LR_Parser_Generator?
  139. X
  140. X    Back in the late 50s and 60s, linguists, mathematicians, and
  141. Xsoftware engineers all became intensely interested in the formal
  142. Xproperties of languages: Can they be described as a series of logical
  143. Xstructures and relations?  Can computers recognize and manipulate
  144. Xthese structures efficiently?  Linguists, in particular, quickly
  145. Xrealized that the amount of structural complexity, ambiguity, and pure
  146. Xnoise in natural language would render it computationally intractable,
  147. Xespecially given the limited memory/throughput of then available CPUs.
  148. XMathematicians and engineers, however, found that many of the
  149. Xformalized notations they dealt with could, in fact, be (re)designed
  150. Xin such a way that efficient computer processing could - at least in
  151. Xprinciple - be achieved.
  152. X
  153. X    Principle, in this case, did not squarely meet reality until
  154. Xviable parser generation tools came into being.  Parser generation
  155. Xtools map an abstract structural description of a formal notation or
  156. X"language" to working computer code.  Ideally, the designer simply
  157. Xmakes assertions like:
  158. X
  159. X    an expression is composed of either
  160. X        1) a term (e.g. 10), or
  161. X        2) an expression, a "+" or "-", and another expression
  162. X
  163. XParser generator systems translate these assertions (the "grammar")
  164. Xinto a machine, i.e. automaton, that can recognize and/or manipulate
  165. Xinput streams that conform to the "language" so described.
  166. X
  167. X    Let me dwell, for a moment, on the toy expression grammar
  168. Xoffered above.  Note that it describes a set of simple mathematical
  169. Xconstructs like:
  170. X
  171. X    9
  172. X    9 + 3
  173. X    9 + 3 - 8
  174. X
  175. XAccording to the specifications given above, the nine, three, and
  176. Xeight alone constitute terms - which are also expressions (via rule
  177. X1).  Because these terms are also expressions, "9 + 3" can be reduced
  178. Xto a larger expression by rule 2.  The same is true for "9 + 3 - 8,"
  179. Xexcept that there rule 2 must apply twice - once for "9 + 3," and then
  180. Xagain for that and the remainder of the line - in effect grouping the
  181. Xexpressions as ( ( (9) + (3) ) - (8) ).  It is also possible to group
  182. Xthe expression ( (9) + ( (3) - (8) ) ), although for the discussion
  183. Xthat immediately follows this second grouping will be ignored (see
  184. Xbelow on the terms "precedence" and "associativity").
  185. X
  186. X    If we add actions to the above grammar specification, we can
  187. Xcreate a calculator-like automaton.  Traditionally, LR-family automata
  188. X(like the ones Ibpag2 creates) contain a parser, one or more stacks,
  189. Xand a set of action tables.  The parser reads from an input stream
  190. Xsegmented into "tokens" (e.g. TERM, '+', '-'), and then manipulates
  191. Xits stacks according to directives contained in so-called "action" and
  192. X"goto" tables.  As it reads the input stream, the parser matches rules
  193. Xwith action code specified by the programmer, e.g. rule 2 above might
  194. Xbe matched with code that added/subtracted the expressions on either
  195. Xside of the '+'/'-' operator, and produced (in calculator style) the
  196. Xresult.  Alternatively, it might be matched with code that generated
  197. Xan equivalent construct in another language.
  198. X
  199. X    In the case of our toy expression grammar above, the
  200. Xcorresponding LR automaton operates as follows.  Omitting and/or
  201. Xsimplifying some of the inner details, it first looks at the input
  202. Xstream to see what the next token is.  If the next token is an
  203. Xoperator or end-of-input, it checks the top of its stack.  If the top
  204. Xof the stack has a term on it, that term is popped off, and pushed
  205. Xback on, this time renamed as an expression (rule 1 above).  The input
  206. Xtoken is then shifted from the input stream onto the stack, unless it
  207. Xis the end-of-input token, in which case the parser returns with a
  208. Xresult.  If the top of the stack has an expression on it (rather than
  209. Xa term), the parser pops the top three elements off of the stack, and
  210. Xthen either subtracts the third element from the first or adds the two
  211. Xtogether, depending on whether the second element down was the
  212. Xaddition or subtraction operator, and the result is pushed onto the
  213. Xstack as yet another expression.
  214. X
  215. X    Even in this much-simplified form, the automaton's structure
  216. Xis complex.  Let us look briefly, therefore, at a practical example of
  217. Xits actual workings.  If we were to feed it "9 + 3 + 8," our
  218. Xcalculator would take the following actions:
  219. X
  220. X    1) read the 9, and push it onto the stack as a term
  221. X    2) see a plus sign on the input stream
  222. X    3) pop the term (9) off of the stack and push it back on again
  223. X       (this time calling it an expression)
  224. X    4) push the plus sign onto the stack
  225. X    5) read the 3, and push it onto the stack as a term
  226. X    6) see a minus sign on the input stream
  227. X    7) pop the 3 off of the stack and push it back on again (this
  228. X       time calling it an expression)
  229. X    8) see a minus sign still waiting on the input stream
  230. X    9) pop 9, +, and 3 off of the stack, apply the plus operator
  231. X       to 9 and 3, then push the result onto the stack again a
  232. X       single expression (the stack now has 12 on top)
  233. X    10) read the minus sign, and push it onto the stack
  234. X    11) read the 8, and push it onto the stack as a term
  235. X    12) see the end of input coming up on the input stream
  236. X    13) pop the 8 off of the stack and push it back on again as an
  237. X       expression
  238. X    14) see the end-of-input token still sitting on the input
  239. X       stream 
  240. X    15) pop 12, -, and 8 off of the stack, apply the minus operator
  241. X       to 12 and 8, then push the result onto the stack again (the
  242. X       stack now has 4 on top)
  243. X    16) return the "answer" (i.e. 4)
  244. X
  245. X    This series of actions is hard to describe, and even more so
  246. Xto model as part of a hand-written computer program.  And, even if
  247. Xsuch a program were written by hand, this program would have to be
  248. Xmodified, at times radically, every time the grammar it assumes was
  249. Xaugmented or changed.  What I am leading up to is that, with a parser
  250. Xgenerator, the hand compilation stage can be eliminated by allowing
  251. Xthe programmer simply to declare his/her tokens and language specs,
  252. Xthen have the appropriate automaton constructed with little, or no,
  253. Xhuman intervention.  This is why parser generation tools were critical
  254. Xto the development of not just theoretically feasible, but truly
  255. X*practical*, LR-based computer language design systems.
  256. X
  257. X
  258. X3.__Using_Ibpag2
  259. X
  260. X    To recode the above toy expression grammar in
  261. XIbpag2-compatible format is relatively simple, especially if we omit
  262. Xthe actions initially, and concentrate on simple recognition.  We need
  263. Xonly a set of token declarations and three rules.  Certain
  264. Xmodifications will have to be made to the token declarations later on.
  265. XFor general illustration's sake, however, the following will suffice:
  266. X
  267. X    %token TERM, '+', '-'
  268. X    %%
  269. X    expression : TERM
  270. X    expression : expression, '+', expression
  271. X    expression : expression, '-', expression
  272. X
  273. XTERM, and the addition and subtraction operators, are the tokens (i.e.
  274. Xthe terminals symbols out of which the grammar is constructed - the
  275. Xthings that the input stream is segmented into).  Note the %token
  276. Xkeyword used to declare them.  The colon means "is composed of."  The
  277. Xdouble percent sign separates token declarations from the grammar
  278. Xproper.
  279. X
  280. X    Adding in our actions - which above were keyed to a complex
  281. Xset of decisions based on input tokens and stack conditions - requires
  282. Xjust a few extra lines of Ibpag2 action code, set off in curly braces:
  283. X
  284. X    %token TERM, '+', '-'
  285. X    %%
  286. X    expression : TERM { return arg1 }
  287. X    expression : expression, '+', expression { return arg1 + arg3 }
  288. X    expression : expression, '-', expression { return arg1 - arg3 }
  289. X
  290. XUsing a "|" shorthand for repeated left-hand sides of rules, we may
  291. Xreformat this as:
  292. X
  293. X    %token TERM, '+', '-'
  294. X    %%
  295. X    expression : TERM { return arg1 }
  296. X           | expression, '+', expression { return arg1 + arg3 }
  297. X           | expression, '-', expression { return arg1 - arg3 }
  298. X
  299. X    ArgX above refers to the Xth element of the right-hand side of
  300. Xthe preceding rule.  So, for example, arg1 in "{ return arg1 }" above
  301. Xrefers to TERM - the only right-hand side element of the first rule.
  302. XThe action "{ return arg1 }" means, "once you find a TERM and have
  303. Xrenamed it as an expression, use the value of TERM as the value for
  304. Xthat expression."  By way of contrast, the action "{ return arg1 +
  305. Xarg3 }" means, in conjunction with the rule it follows: "When you find
  306. Xan expression consisting of a sub-expression, a plus operator, and
  307. Xanother sub-expression, use the value of sub-expression 1 + the value
  308. Xof sub-expression 2 as the value for the expression as a whole."
  309. XTechnically, the action "{ return arg1 }" for expression : TERM is not
  310. Xnecessary, since the Ibpag2 parser, by default, pushes the value of
  311. Xthe last RHS arg onto the stack.  For epsilon productions (to be
  312. Xdiscussed below), it pushes &null.
  313. X
  314. X    One serious problem with this set of specifications is that
  315. Xthe operators '-' and '+' are left associative.  We humans take this
  316. Xfor granted, because correct algebraic grouping is something our
  317. Xhigh-school math teachers burned into us.  The computer, though, has
  318. Xto be told, pedantically, how to group addition and subtraction
  319. Xexpressions.  It has to be explicitly instructed, in other words, to
  320. Xgroup expressions like "9 + 32 - 4" as (9 + 32) - 4.  Without
  321. Xinstructions of this kind, the parser does not know, after it has read
  322. X"9 + 32" and is looking at a minus sign, whether to shift the minus
  323. Xsign onto the stack, and eventually try to group as 9 + (32 - 4), or
  324. Xto reduce "9 + 32" to an expression and group as (9 + 32) - 4.
  325. XAlthough in this case the grouping may not seem to matter, it
  326. Xsometimes does.  Some operators group right to left.  The unary minus
  327. Xsign, for example, is one such operator (--4 groups as (- (- 4))).  To
  328. Xinclude the unary minus sign in our grammar, we might append yet
  329. Xanother rule:
  330. X
  331. X    %token TERM
  332. X    %left '+', '-'
  333. X    %right '-'
  334. X    %%
  335. X    expression : TERM { return arg1 }
  336. X           | expression, '+', expression { return arg1 + arg3 }
  337. X           | expression, '-', expression { return arg1 - arg3 }
  338. X           | '-', expression { return - arg2 }
  339. X
  340. XThe trouble with this arrangement is that the minus sign was already
  341. Xdeclared as left associative.  To get around the conflict we use a
  342. X"dummy" token declaration, and a %prec declaration in the applicable
  343. Xrule:
  344. X
  345. X    %token TERM
  346. X    %left '+', '-'
  347. X    %right UMINUS
  348. X    %%
  349. X    expression : TERM { return arg1 }
  350. X           | expression, '+', expression { return arg1 + arg3 }
  351. X           | expression, '-', expression { return arg1 - arg3 }
  352. X           | '-', expression %prec UMINUS { return - arg2 }
  353. X
  354. XThe %prec declaration simply tells the parser that, even though the
  355. Xrule contains a '-' operator, the rule should be handled as if the
  356. Xoperator were UMINUS.  UMINUS is not actually used as a symbol in the
  357. Xright-hand side of any rule (hence the designation "dummy").  It is
  358. Xthere simply to make the last rule behave as if the minus sign in the
  359. Xlast rule were different than in the second-to-last rule.
  360. X
  361. X    Let us now add in multiplication and division operators to our
  362. Xcalculator specifications, and see what happens.  Let me reiterate
  363. Xhere that the action "{ return arg1 }" for rule 1 (expression : TERM)
  364. Xis not strictly necessary, since the default is to push the last RHS
  365. Xarg onto the value stack:
  366. X
  367. X    %token TERM
  368. X    %left '+', '-'
  369. X    %left '*', '/'
  370. X    %right UMINUS
  371. X    %%
  372. X    expression : TERM { return arg1 }
  373. X           | expression, '+', expression { return arg1 + arg3 }
  374. X           | expression, '-', expression { return arg1 - arg3 }
  375. X           | expression, '*', expression { return arg1 * arg3 }
  376. X           | expression, '/', expression { return arg1 / arg3 }
  377. X           | '-', expression %prec UMINUS { return - arg2 }
  378. X
  379. XNote that the multiplication and division operators were defined
  380. X*after* the addition and subtraction operators.  The reason for this
  381. Xis that, technically speaking, the grammar itself is ambiguous.  If we
  382. Xtreat all operators identically, the parser will not be able to tell
  383. Xwhether "9 + 1 * 3" should be parsed as (9 + 1) * 3 or as 9 + (1 * 3).
  384. XAs we all know from our high-school algebra, multiplication has a
  385. Xhigher precedence than addition.  You do the multiplications before
  386. Xthe additions, in other words, no matter where they occur.  To tell
  387. Xthe parser to behave in this same manner, we declare '*' after '+'.
  388. XNote that, despite their higher priority, the '*' and '/' operators
  389. Xare still left associative.  Hence, given "3 / 4 * 7," the parser will
  390. Xgroup its input as (3 / 4) * 7.  As a brain teaser, try to figure out
  391. Xhow the parser might group the input "9 + 3 / 4 * 7."  Remember that
  392. Xhigher-precedence rules get done first, but that same-precedence rules
  393. Xget done according to associativity.
  394. X
  395. X    The only fundamental problem remaining with the above grammar
  396. Xis that it assumes that the end of the input coincides with the end of
  397. Xthe line.  Is it possible to redefine the language described as
  398. Xconsisting of arbitrary many lines?  The answer to this question is
  399. X"yes."  One can simply add another set of productions to the grammar
  400. Xthat state, essentially, that the input language consists of lines
  401. Xmade up of an expression and a carriage return or of nothing.  Nothing
  402. Xis indicated by the keyword epsilon.  Note that only the first rule
  403. Xhas an action field:
  404. X
  405. X    lines    : lines, expression, '\n'    { write(arg2) }
  406. X        | lines, '\n'
  407. X        | epsilon
  408. X
  409. XThis rule-series may seem rather abstruse, but it becomes a bit
  410. Xclearer when you think about what happens on actual input.  If there
  411. Xis no input (epsilon), nothing gets printed, because lines : epsilon
  412. Xhas no action field.  If the parser sees an expression and a newline,
  413. Xthe parser takes this as an instance of epsilon, plus an expression,
  414. Xplus a newline.  This, then, becomes the first component of rule 1 if
  415. Xanother expression + newline follows, or of rule two if just a newline
  416. Xoccurs.  Every time an instance of rule 1 occurs, the action "{
  417. Xwrite(arg2) }" is executed, i.e. the value of the expression gets
  418. Xprinted.  If this still seems hard to fathom, try walking through
  419. Xstep-by-step.  Even experienced hands may find these sorts of rules
  420. Xdifficult to construct and debug.
  421. X
  422. X    Note that "lines" is now the so-called "start symbol" of our
  423. Xgrammar.  It is, in other words, the goal of every parse.  By default
  424. Xthe left-hand side symbol of the first rule is the start symbol.  This
  425. Xmay be overridden with a %start declaration in the tokens section (on
  426. Xwhich, see the sample Ibpag2 input file below).
  427. X
  428. X    With our new, multi-line start symbol in place, the only piece
  429. Xthat needs to be added, in order to make our calculator specification
  430. Xa full working input to Ibpag2, is a tokenizer.  A tokenizer is a
  431. Xroutine that reads input from a file or from some other stream (e.g.
  432. Xthe user's console), and then segments this input into tokens that its
  433. Xparser can understand.  In some cases, the tokens must be accompanied
  434. Xby a literal value.  For example, if we encounter a TERM, we return
  435. XTERM, just as it is listed in the %token declaration.  But what is the
  436. Xliteral value of a TERM token?  It could be, for example, 9, or 5, or
  437. X700.  The tokenizer returns the symbol TERM, in this case, but then
  438. Xrecords that TERM's actual value by setting some global variable.  In
  439. XIbpag2's parser, this variable is assumed to be "iilval."  In the
  440. Xtokenizer, therefore, one might write
  441. X
  442. X    iilval := (literal value)
  443. X    suspend TERM
  444. X
  445. XFor literal operators like '+' and '*', there is no need to set
  446. Xiilval, since their literal value is irrelevant.  One simply returns
  447. Xthese as integers (usually via "suspend ord(c)").
  448. X
  449. X    The tokenizer routine is normally appended to the grammar
  450. Xafter another double percent sign.  Everything after this second
  451. Xdouble percent sign is copied literally to the output file.
  452. XAlternatively, the tokenizer can be $included via Icon's preprocessor.
  453. XIbpag2 demands that the tokenizer be called iilex, and that it take a
  454. Xsingle file argument, that it be a generator, and that it fail when it
  455. Xreaches end-of-input.  Combined with our "lines" productions, the
  456. Xaddition of an iilex routine to our calculator grammar yields the
  457. Xfollowing Ibpag2 input file:
  458. X
  459. X    %token TERM
  460. X    %left '+', '-'
  461. X    %left '*', '/'
  462. X    %right UMINUS
  463. X
  464. X    %start lines
  465. X
  466. X    %%
  467. X
  468. X    expression : TERM { return arg1 }
  469. X           | expression, '+', expression { return arg1 + arg3 }
  470. X           | expression, '-', expression { return arg1 - arg3 }
  471. X           | expression, '*', expression { return arg1 * arg3 }
  472. X           | expression, '/', expression { return arg1 / arg3 }
  473. X           | '-', expression %prec UMINUS { return - arg2 }
  474. X
  475. X    lines       : lines, expression, '\n'    { write(arg2) }
  476. X           | lines, '\n'
  477. X           | epsilon
  478. X
  479. X    %%
  480. X
  481. X    procedure iilex(infile)
  482. X
  483. X        local nextchar, c, num
  484. X
  485. X        nextchar := create !(!infile || "\n" || "\n")
  486. X        c := @nextchar | fail
  487. X
  488. X        repeat {
  489. X        if any(&digits, c) then {
  490. X            if not (\num ||:= c) then
  491. X            num := c
  492. X        } else {
  493. X            if iilval := \num then {
  494. X            suspend TERM
  495. X            num := &null
  496. X            }
  497. X            if any('+-*/()\n', c) then {
  498. X            iilval := c
  499. X            suspend ord(c)
  500. X            } else {
  501. X            if not any(' \t', c) then {
  502. X                # deliberate error - will be handled later
  503. X                suspend &null
  504. X            }
  505. X            }
  506. X        }
  507. X        c := @nextchar | break
  508. X        }
  509. X        if iilval := \num then {
  510. X        return TERM
  511. X        num := &null
  512. X        }
  513. X
  514. X    end
  515. X
  516. X    procedure main()
  517. X        return iiparse(&input, 1)
  518. X    end
  519. X
  520. XAs noted above, the tokenizer (iilex) must be a generator.  It must
  521. Xsuspend integers either directly (e.g. ord(c)), or else via symbolic
  522. Xdefines like TERM, created by Ibpag2 on the basis of %token, %right,
  523. X%left, and %nonassoc declarations.  The tokenizer must fail on end of
  524. Xinput.
  525. X
  526. X    If you like, cut the above code out, place it in a temporary
  527. Xfile, tmp.ibp, and then feed this file to Ibpag2 by typing "ibpag2 -f
  528. Xtmp.ibp -o tmp.icn."  If your system supports input and output
  529. Xredirection, type: "ibpag2 < tmp.ibp > tmp.icn."  Ibpag2 will turn
  530. Xyour grammar specifications and actions into a routine called iiparse.
  531. XIf you look above, you will see that I appended a main procedure that,
  532. Xin fact, calls iiparse().  Iiparse() takes two arguments: 1) an input
  533. Xstream, and 2) a switch that, if nonnull, tells the parser to fail
  534. Xrather than abort on unrecoverable errors.  When Ibpag2 is finished
  535. Xcreating its output file (tmp.icn above), compile that file the way
  536. Xyou would compile any other Icon program (e.g. "icont tmp").  Finally,
  537. Xrun the executable.  You should be able to type in various simple
  538. Xarithmetic expressions and have the program spit back answers each
  539. Xtime you hit a return.  The only problem you might encounter is that
  540. Xthe parser aborts on erroneous input.
  541. X
  542. X    The issue of erroneous input brings up yet another point of
  543. Xgeneral Ibpag2 usage.  Normally, if one is processing input, one does
  544. Xnot want to abort on errors, but rather just emit an error message,
  545. Xand to continue processing - if this is at all possible.  To do this,
  546. XIbpag2 provides a simple but fairly effective mechanism: A reserved
  547. X"error" token.
  548. X
  549. X    When Ibpag2 encounters an error, it will remove symbols from
  550. Xits stack until it has backtracked to a point where the error token is
  551. Xlegal.  It then shifts the error token onto the stack, and tries to
  552. Xre-start the token stream at the point where it left off, discarding
  553. Xtokens if necessary in order to get itself resynchronized.  The parser
  554. Xconsiders itself resynchronized when it has successfully read and
  555. Xshifted three tokens after shifting the error token.  Until then it
  556. Xremains in an error state, and will not output additional error
  557. Xmessages as it discards tokens.
  558. X
  559. X    This explanation may sound a bit abstruse, but in practice it
  560. Xis turns out to be quite simple.  To implement error handling for our
  561. Xcalculator, we really have to add only one production to the end of
  562. Xthe "lines" section:
  563. X
  564. X    lines       : lines, expression, '\n'    { write(arg2) }
  565. X           | lines, '\n'
  566. X           | epsilon
  567. X           | error, '\n'    {
  568. X                      write("syntax error; try again:")
  569. X                      iierrok
  570. X                    }
  571. X
  572. XGiven the above grammar, the parser will handle errors as follows: If
  573. Xan error occurs (say it has an expression then an operator on its
  574. Xstack and sees a newline on the input stream) the parser will throw
  575. Xout the operator, then check if the error token would be OK in this
  576. Xstate (which it would not).  Then it would throw out the expression.
  577. XAt this point, the stack is in the ready-to-read-a-lines state - the
  578. Xstate it was in before it read the last expression.  Since "lines" may
  579. Xconsist of error and '\n,' the error token is legal here, and so the
  580. Xparser pushes error onto the stack, then looks back at the input
  581. Xstream (where a newline is still waiting).  Since the newline now
  582. Xcompletes the rule lines : error, '\n', the parser pushes the newline
  583. Xonto its stack, then executes the action associated with this
  584. Xproduction, i.e. it writes "syntax error; try again:" to the console,
  585. Xprompting the user for additional input.
  586. X
  587. X    The keyword "iierrok" in the above error production's action
  588. Xfield is there for a subtle, but important, reason: It tells the
  589. Xparser to consider itself resynchronized, even if three tokens have
  590. Xnot yet been shifted.  If iierrok were not in the action code for this
  591. Xrule, and the user were to supply more bad input after the prompt,
  592. Xthen the parser would simply discard those tokens, without emitting
  593. Xanother error message.  Why?  Because, as you will recall, the parser
  594. Xdiscards tokens after an error, in efforts to resynchronize itself.
  595. XUntil it reads and shifts three tokens successfully, it considers
  596. Xitself in an error state, and will not emit additional error messages.
  597. XThe three-token resync rule is there to prevent a cascade of
  598. Xirrelevant error messages touched off by a single error.  In our
  599. Xcalculator's case above, though, we are smarter than the parser.  We
  600. Xknow that it is resynchronized as soon as it reduces error, '\n' to
  601. Xlines.  So if a syntax error occurs on the next token, it should be
  602. Xreported.  Adding "iierrok" to the action insures that the parser will
  603. Xdo just this.
  604. X
  605. X    In addition to iierrok, there are several other directives
  606. XIbpag2 accepts as part of the action code segments.  These are as
  607. Xfollows:
  608. X
  609. X    iiclearin        clear the current input token
  610. X    IIERROR            perform error recovery
  611. X    IIACCEPT        simulate an accept action
  612. X
  613. XThere are several other directives (all implemented as macros) that
  614. XIbpag2 accepts in GLR mode.  For a discussion of GLR mode, see below,
  615. Xsection 5.  IIERROR in particular, and error recovery in general, work
  616. Xa bit differently in that mode than they do in Ibpag2's normal (i.e.
  617. XLR) mode.
  618. X
  619. X    There are admittedly many other topics that might be covered
  620. Xhere.  This treatment, however, is intended as a general nontechnical
  621. Xintroduction, and not as a complete textbook on parser generation use.
  622. XIf you want to learn more about this topic, consult the bibliography.
  623. XAlso, check the UNIX manual pages on the YACC utility (Yet Another
  624. XCompiler Compiler).  Ibpag's input format is fairly close (too close,
  625. Xperhaps) to YACC's.  In fact, most of what is said about YACC in UNIX
  626. Xdocumentation can be carried directly over to Ibpag2.  Several salient
  627. Xdifferences, though, should be kept in mind:
  628. X
  629. X        1) YACC's "$$ = x" constructs are replaced by "return x" (e.g.
  630. X           "$$ = $1 + $3" -> "return $1 + $3" [$1 is a synonym for
  631. X       "arg1", $3 for "arg3", etc.])
  632. X
  633. X        2) all variables within a given action are, by default, local
  634. X           to that action; i.e. they cannot be accessed by other
  635. X           actions unless you declare them global elsewhere (e.g. in
  636. X           the pass-through part of the declarations section %{ ...
  637. X           %})
  638. X
  639. X        3) the %union and %type declarations/tags are not needed by
  640. X       Ibpag2 (both for better and for worse)
  641. X
  642. X        4) tokens and symbols are separated from each other by a comma
  643. X           in Ibpag2 files (e.g. %token '+', '-' and S : NP, VP)
  644. X
  645. X        5) epsilon is indicated by the keyword "epsilon" (e.g. REL :
  646. X           epsilon), and not by an empty RHS
  647. X
  648. X        6) both epsilon and error *may* be declared as %tokens for
  649. X           reasons of precedence, although they retain hard-coded
  650. X           internal values (-2 and -1, respectively)
  651. X
  652. X        7) all actions must follow the last RHS symbol of the rule
  653. X           they apply to (preceded by an optional %prec directive); to
  654. X           achieve S : NP { action1 }, VP { action2 }, insert a dummy
  655. X           rule: S : NP, dummy, VP { action2 }; dummy : epsilon {
  656. X           action1 } ;
  657. X
  658. X        8) YYERROR, YYACCEPT, yyclearin, and yyerrok are the same,
  659. X           except they are written IIERROR, IIACCEPT, iiclearin, and
  660. X           iierrok (i.e. "ii" replaces "yy")
  661. X
  662. X        9) Ibpag2's input files are tokenized as modified Icon files,
  663. X           and, as a consequence, Icon's reserved words must not be
  664. X           used as symbols (e.g. "if : if, then" is no go)
  665. X
  666. XI myself find YACC to be ugly.  As a result, Ibpag2 is not an exact
  667. XYACC clone.  I would like to underscore the fact that I have no
  668. Xintention to move in this direction, either.  It's as YACC-like as
  669. Xit's going to get!
  670. X
  671. X    Both YACC and non-YACC users should note number 9 in the above
  672. Xlist.  Don't use things like "while," "every," "do," etc. as symbols
  673. Xin your grammar!  Just use the same rules for Ibpag2 nonterminals as
  674. Xfor Icon variables, and you'll be OK.
  675. X
  676. X    For those that just can't bear using anything but a strictly
  677. XYACC-conformant system, I've included a preprocessor with the Ibpag2
  678. Xdistribution called (at one user's recommendation) "iacc."  Iacc reads
  679. X&input - assumed to be a YACCish grammar - and sends to &output an
  680. XIbpag2-conformant file.  I have not tested this file extensively, and
  681. Xthere are likely to be bugs in the way I've handled the necessary 2
  682. Xtoken lookaheads and value stack references.  Give it a whirl, though,
  683. Xif you are feeling adventurous.  The only reason I personally use Iacc
  684. Xis that some YACCs (e.g. BSD YACC) have particularly nice debugging
  685. Xmessages and help.  If my grammar is particularly complex, I just run
  686. Xit through YACC without action code first, then use Iacc to convert it
  687. Xto Ibpag2 format.  Iacc's output, as I noted, is not meant to be
  688. Xpretty, so I invariably end up doing a little editing - usually just
  689. Xrespacing a few rules, and re-inserting any comments that I might have
  690. Xput in the original YACC file.
  691. X
  692. X    In general, Ibpag2 (like YACC) handles epsilon moves and
  693. Xindirect cycles.  LR-mode shift-reduce conflicts are also handled in
  694. Xthe normal way (i.e. pick the rule with the highest priority, and, in
  695. Xcases where the priority is the same, check the associativities).  In
  696. Xcontrast to YACC, Ibpag2 flags reduce/reduce conflicts as errors
  697. X(since these often conceal deeper precedence problems and just plain
  698. Xkludges).  Reduce/reduce conflict errors are easily enough remedied,
  699. Xif need be, via (dummy) precedences.  One can convert these errors to
  700. Xwarnings by specifying -y on the command line.  With the -y option,
  701. Xreduce/reduce conflicts are resolved in favor of the rule that occurs
  702. Xfirst in the grammar.  The -y switch also prevents Ibpag2 from
  703. Xaborting on shift/reduce conflicts, telling it instead to resolve in
  704. Xfavor of shift.  Basically, -y is a partial YACC compatibility switch.
  705. XNormally (i.e. in SLR mode) Ibpag2 is much more finicky than YACC
  706. Xabout conflicts in its grammars.
  707. X
  708. X    Also in contrast to YACC, Ibpag2 supports multiple
  709. Xsimultaneous parsers.  Ibpag2 normally names its main parser routine
  710. Xiiparse().  By using the -m command-line option, however, you can
  711. Xoverride this default behavior, and force Ibpag2 to augment this name
  712. Xin some uniquely identifiable fashion.  For example, "ibpag2 -m _1 <
  713. Xtmp.ibp > tmp.icn" will force Ibpag2 to write a parser called
  714. X"iiparse_1" to tmp.icn.  Note that, instead of calling iilex, this
  715. Xiiparse_1() routine will now call iilex_1, and all necessary global
  716. Xvariables will have _1 appended to them (e.g. errors will become
  717. Xerrors_1).  I don't expect that many people will have occasion to use
  718. Xthis feature.  It is there, though, for those that want it.
  719. X
  720. X
  721. X4.__Debugging
  722. X
  723. X    Constructing and debugging LR(1) family parsers can sometimes
  724. Xbe hair raising, even with a parser generator.  Several precautions
  725. Xcan be taken, however, to minimize the agony.  The first is to declare
  726. Xall tokens initially as part of a single %token declaration, i.e. with
  727. Xno precedences, and with the same associativities.  Also, leave out
  728. Xaction code until the grammar seems to be working.  In this stage, you
  729. Xcan even run the grammar through (BSD)YACC or GNU Bison.  All you
  730. Xwould need to do is remove the commas between tokens and symbols, and
  731. Xplace a semicolon at the end of every rule.  During this and all
  732. Xdebugging stages, supply Ibpag2 with a -v command-line switch.  This
  733. Xwill cause Ibpag2 to write a summary of rules, tokens, and its two
  734. Xstate tables to "ibpag2.output" (a bit like GNU Bison, but with a
  735. Xhard-coded name).  If you get messages about conflicts in your parse
  736. Xtables (e.g.  "unresolvable reduce/reduce conflict, state 5, token
  737. X257, rules 4,5").  This file will tell you what rules these are, and
  738. Xwhat token number 257 is.  Use precedences and associativities to
  739. Xclear these problems up as they arise.  If you are comfortable having
  740. Xreduce/reduce errors resolved by the order in which the conflicting
  741. Xrules occur, then use the -y command-line switch.  With -y on the
  742. Xcommand line, Ibpag2 will always resolve in favor of the earlier rule.
  743. XThis option will also cause it to resolve all shift/reduce conflicts
  744. Xin favor of shift.
  745. X
  746. X    There are certain languages that are not ambiguous that SLR(1)
  747. Xparsers like Ibpag2 will fail to produce an unambiguous parse table
  748. Xfor.  The classic example is
  749. X
  750. X    expr : lval, '=', rval | rval
  751. X    lval : '*', rval       | ID
  752. X    rval : lval
  753. X
  754. XC programmers will recognize this as a toy expression grammar with
  755. Xcode for identifiers, assignments, and pointers.  The problem is that
  756. Xif we feed this grammar to Ibpag2, it will claim that there is a
  757. Xconflict on lookahead '='.  In truth, there is no ambiguity.  The SLR
  758. Xparser simply doesn't remember the pathway the parser used to get to
  759. Xthe state it is in when it sees '=' on the input stream.  Whether the
  760. Xparser gets into this state by seeing '*' plus and ID, or by seeing
  761. Xjust an ID, it knows to turn the ID into an lval.  Then it knows to
  762. Xturn lval into rval.  At this point, though, it doesn't know whether
  763. Xto shift the = sign via rule 1, or to turn rval and the preceding '*'
  764. Xinto an lval.  The parser has "forgotten" that the '*' is there
  765. Xwaiting on level down on the stack!
  766. X
  767. X    The solution to this problem is actually quite simple (at
  768. Xleast in concept).  Just provide a unique pathway in the grammar for
  769. Xthe conflicting rules.  In this case, they are rules 1 and 5 (the
  770. Xfirst and last):
  771. X
  772. X    expr : lval, '=', rval | rval
  773. X    lval : '*', pval | ID
  774. X    pval : lval
  775. X    rval : lval
  776. X
  777. XNow when the parser sees '*,' it can only have a pval after it.  Never
  778. Xmind that pval is composed of precisely the same things as rval.  The
  779. Xpoint is that the parser generator follows a different route after
  780. Xseeing '*' than if it starts with ID and no preceding '*'.  Hence it
  781. X"remembers" that that the '*' is back on the stack, waiting for the
  782. X"lval : '*', pval" rule to apply.  There is no more conflict.
  783. X
  784. X    Go ahead and run these grammars through Ibpag2 if you aren't
  785. Xsure what is going on.  Remember to declare ID as a token, and to
  786. Xplace "%%" in the appropriate spot!
  787. X
  788. X    If you get your parser up and running, but find that it is not
  789. Xfunctioning quite the way you expect, add the following line somewhere
  790. Xnear the start of Ibpag2's output file:
  791. X
  792. X    $define IIDEBUG
  793. X
  794. XIf you like, you can add it to the beginning of your Ibpag2 input
  795. Xfile.  Place it in the declarations section (before the first double
  796. Xpercent sign), and surround it by %{ and %}, e.g.:
  797. X
  798. X    %{
  799. X    $define IIDEBUG
  800. X    %}
  801. X
  802. XThis tells Ibpag2 to send $define IIDEBUG straight through to the
  803. Xoutput file.
  804. X
  805. X    What defining IIDEBUG does is tell iiparse, once compiled, to
  806. Xemit profuse debugging messages about the parser's actions, and about
  807. Xthe state of its stacks.  This display will not make a whole lot of
  808. Xsense to anyone who doesn't understand LR-family parsers, so those who
  809. Xwant to access this feature should perhaps go through a standard
  810. Xreference like Aho, Sethi, and Ullman [1].
  811. X
  812. X    If, after you are finished debugging your grammar, you find
  813. Xthat Ibpag2's output files are rather large, you may try saving space
  814. Xby compressing the action and goto tables.  This is accomplished by
  815. Xinvoking Ibpag2 with the -c (compress) option.  Using this option
  816. Xmakes debugging difficult, and makes the parser run a bit more slowly.
  817. XIt also only works for rather large grammars with long nonterminal
  818. Xsymbol names.  Don't even consider it until the grammar is thoroughly
  819. Xdebugged and you have determined that the output file's size is just
  820. Xtoo great for practical use.  Even then, compression may or may not
  821. Xhelp, depending on how long your nonterminal names are.  In general,
  822. XIbpag2 is best as a teaching tool, or as a production system for
  823. Xmedium or small grammars.
  824. X
  825. X
  826. X5.__Using_Ibpag2_with_Non-LR_Grammars
  827. X
  828. X    There may be times when you *want* to parse languages that no
  829. XLR-based algorithm can handle.  There may be times, that is, when the
  830. Xgrammar you want to use contains conflicts or ambiguities that are
  831. Xthere by design, and not by oversight.  For example, you may want to
  832. Xparse a natural language.  Full-blown natural languages involve many
  833. Xhighly ambiguous constructs, and are not LR-parsable.  By invoking it
  834. Xwith the -a option, Ibpag2 can parse or recognize certain natural
  835. Xlanguages, or, more practically speaking, certain NL subsets.  The
  836. Xletter "a" in -a is supposed to stand for "ambiguous," although what
  837. Xthis option really does is put Ibpag2 into a quasi-GLR mode - i.e.
  838. Xinto a kind of "generalized" LR mode in which it can accept non-LR
  839. Xgrammars [4,5].
  840. X
  841. X    User-visible changes to Ibpag2's operation in quasi-GLR mode
  842. X(i.e. with the -a option) are as follows:
  843. X
  844. X    1) iiparse() is now a generator
  845. X    2) action code can use suspend as well as return
  846. X    3) IIERROR places the current thread in an error state (i.e.
  847. X       it doesn't *necessarily* trigger error recovery; see below)
  848. X    4) there are two new action-code directives (iiprune and
  849. X           iiisolate) and a general define (AUTO_PRUNE)
  850. X    5) conflicts due to ambiguities in the grammar no longer
  851. X       result in aborted processing (so, e.g., if you do not
  852. X       specify the -y option on a grammar with reduce/reduce
  853. X       conflicts, Ibpag2 will simply generate a parser capable of
  854. X       producing multiple parses for the same input)
  855. X
  856. X    In quasi-GLR mode, iiparse() should be invoked in a way that
  857. Xwill render multiple results usable, if they are available (e.g.
  858. X"every result := iiparse(&input) do...".  Action code is also allowed
  859. Xto produce more than one value (i.e. to use suspend).  When it does
  860. Xso, iiparse() creates separate parse threads for each value.  So, for
  861. Xinstance, if your action code for some production suspends both of the
  862. Xfollowing lists,
  863. X
  864. X    ["noun", "will", "gloss: desire"]
  865. X    ["noun", "will", "gloss: legal document mandating how _
  866. X                      one's possessions are to be disposed _
  867. X              of after one's death"],
  868. X
  869. Xiiparse() would create two separate parse threads - one for each
  870. Xresult.  Note that in this case, the syntactic structure of each
  871. Xthread is the same.  It is their semantics (i.e. the stuff on the
  872. Xvalue stack) that differs.
  873. X
  874. X    If you use the iierrok and iiclearin macros in your action
  875. Xcode before suspending any result, their affect persists through all
  876. Xsubseqent suspensions and resulting parse threads.  If you use these
  877. Xmacros after suspending one or more times, however, they are valid
  878. Xonly for the parse thread generated by the next suspension.  By way of
  879. Xcontrast, the IIERROR macro *always* flags only the next parse thread
  880. Xas erroneous.  Likewise, IIACCEPT always simulates an accept action on
  881. Xthe next suspension only.  IIERROR and IIACCEPT, in other words, never
  882. Xhave any effect on subsequent suspensions and parse threads other than
  883. Xthe one that immediately follows them.  This is true of iierrok and
  884. Xiiclearin only when used after the first suspension.
  885. X
  886. X    In quasi-GLR mode, IIERROR (number three in the difference
  887. Xlist above) becomes a mechanism for placing the current parse thread
  888. Xin error mode.  This is similar to, but not quite identical to, how
  889. XIIERROR functions in straight LR mode.  In quasi-GLR mode, if other
  890. Xthreads can carry on the parse without error the erroneous parse
  891. Xthread is quietly clobbered.  Full-blown error recovery only occurs if
  892. Xall of the other parsers halt as well.  This makes sense if you think
  893. Xabout it.  Why keep erroneous threads around when there are threads
  894. Xstill continuing a valid parse?  For some large interactive systems,
  895. Xit might be necessary to keep bogus threads around longer, and weed
  896. Xthem out only after a lengthy grading process.  If you are
  897. Xconstructing a system such as this, you'll have to modify Ibpag2's
  898. Xiiglrpar.lib file.  In particular, you'll need to change the segment
  899. Xin iiparse() that takes out the trash, so to speak, in such a way that
  900. Xit does so only if the error count in a given parser either rises
  901. Xabove a specific threshhold or else exceeds the number of errors in
  902. Xthe "most correct" parser by a certain amount.  This is not that hard
  903. Xto do.  I just don't expect that most parsers people generate with
  904. XIbpag2 will use IIERROR or error recovery in general in so involved a
  905. Xfashion.
  906. X
  907. X    Iiprune and iiisolate (number 4 above) are used to control the
  908. Xgrowth of the parallel parser array.  In order to give straightforward
  909. X(read "implementationally trivial") support for action code, Ibpag2
  910. Xcannot create a parse "forest" in the sense that a standard GLR parser
  911. Xdoes.  Instead, it simply duplicates the current parser environment
  912. Xwhenever it encounters a conflict in its action table.  Even if the
  913. Xconflict turns out to reflect only a local ambiguity, the parsers, by
  914. Xdefault, remain separate.  Put differently, Ibpag2's quasi-GLR parser,
  915. Xby default, makes no direct effort to reduce the size of its parser
  916. Xarrays or to alter the essentially linear structure of their value and
  917. Xstate stacks.  Size reduction, where necessary and/or desirable, is up
  918. Xto the programmer.  What the iiprune macro is there to do is to give
  919. Xthe programmer a way of pruning a given thread out of the active
  920. Xparser list.  Iiisolate allows him or her to prune out every thread
  921. X*but* the current one.  AUTO_PRUNE makes the parser behave more like a
  922. Xstandard GLR parser, instructing it to prune parse threads that are
  923. Xessentially duplicating another parse thread's efforts.  The parser,
  924. Xthough, does not build a parse tree per se, the way most GLR parsers
  925. Xtypically do, but rather manipulates its value stack like a
  926. Xtraditional LR-family parser.
  927. X
  928. X    Iiprune is useful when, for example, the semantics (i.e. your
  929. X"action" code segments) determine that a given parse thread is no
  930. Xlonger viable, and you want to signal the syntactic analyzer not to
  931. Xcontinue pursuing it.  The difference between iiprune and IIERROR is
  932. Xthat iiprune clobbers the current parser immediately.  IIERROR only
  933. Xputs it into an error state.  If all active parsers end up in an error
  934. Xstate, and none can shift additional input symbols, then the IIERROR
  935. Xmacro induces error recovery.  Iiprune does not.  NB: iiprune, if used
  936. Xin action code that suspends multiple results, cancels the current and
  937. Xremaining results (i.e. it does not clobber parsers already spun off
  938. Xby previous suspensions by invocation of that same code; it merely
  939. Xcuts the result sequence).  Iiprune essentially stands in for "fail"
  940. Xin this situation.  Fail itself can be used in the code, but be warned
  941. Xthat iiparse() will still push *at least one* value onto its value
  942. Xstack, even if a given action code segment fails.  This keeps the
  943. Xvalue stack in sync with the syntax.  To avoid confusion, I recommend
  944. Xnot using "fail" in any action code.
  945. X
  946. X    Iiisolate is useful if, during error recovery, you prompt the
  947. Xuser interactively, or do something else that cannot be elegantly done
  948. Xin parallel for two or more distinct parse threads.  Iiisolate allows
  949. Xyou to preserve only the the current parse thread, and to clobber the
  950. Xrest.  Iiisolate can also be useful as a way of making sure that only
  951. Xone thread carries on the parse in non-error situations.  Suppose that
  952. Xwe have a series of productions:
  953. X
  954. X    sentences  :  sentences sentence '\n'
  955. X            { print_parse(arg2) }
  956. X           |  sentences '\n'
  957. X           |  error '\n'
  958. X           |  epsilon
  959. X
  960. XIf we get a sentence with more than one parse, all of the underlying
  961. Xthreads that produced these parses will be active for the next
  962. Xsentence as well.  In many situations this will not be what we want.
  963. XIf our desire it to have only one active parse thread at the start of
  964. Xeach sentence, we simply tell our lexical analyzer to suspend two
  965. Xnewlines every time it sees a newline on the input stream.  This
  966. Xinsures that the second rule will always apply right after the first.
  967. XWe then insert iiisolate directives for both it and the one error
  968. Xproduction:
  969. X
  970. X    sentences  :  sentences sentence '\n'
  971. X            { print_parse(arg2) }
  972. X           |  sentences '\n'
  973. X            { iiisolate }
  974. X           |  error '\n'
  975. X            { iiisolate; iierrok }
  976. X           |  epsilon
  977. X
  978. XThe effect here is to allow multiple parsers to be generated only
  979. Xwhile parsing "sentence".  The iiisolate directive, in other words,
  980. Xsees to it that no sentence parse will ever begin with multiple active
  981. Xparsers.  As with LR mode, iierrok clears the error flag for the
  982. X(current) parser.
  983. X
  984. X    Note that if you use iiisolate in action code that suspends
  985. Xmultiple results, iiisolate will clobber all parsers but the one
  986. Xgenerated by the next suspension.
  987. X
  988. X    If there is no need for close control over the details of the
  989. Xparser array, and you wish only to clobber parsers that end up doing
  990. Xthe same thing as some other parser (and hence returning identical
  991. Xvalues), then just make sure you add "$define AUTO_PRUNE" to the
  992. Xpass-through code section at the top of the file.  Put differently,
  993. Xdefining AUTO_PRUNE instructs the quasi-GLR parser to weed out parsers
  994. Xthat are in the same state, and which have identical value stacks.
  995. XAUTO_PRUNE can often be used in place of iiisolate in situations like
  996. Xthe one discussed just above.  Its only drawback is that it slows
  997. Xthe parser a bit.
  998. X
  999. X    Other than these deviations (action code and iiparse becoming
  1000. Xgenerators, IIERROR's altered behavior, and the addition of iiprune,
  1001. Xiiisolate, and AUTO_PRUNE), Ibpag2's quasi-GLR mode - at least on the
  1002. Xsurface - works pretty much like its straight LR mode.  In fact, if
  1003. Xyou take one of your SLR(1) grammars, and run it through Ibpag2 using
  1004. Xthe -a option, you probably won't notice any difference in the
  1005. Xresulting automaton unless you do some debugging or perform some
  1006. Xtiming tests (the GLR parser is slower, though for straight SLR(1)
  1007. Xgrammars not by much).  Even with non-SLR(1) grammars, the quasi-GLR
  1008. Xparser will clip along merrily, using all the same sorts of rules,
  1009. Xaction code, and macros that you would typically use in LR mode!
  1010. X
  1011. X
  1012. X6.__Installing_Ibpag
  1013. X
  1014. X    If you are a UNIX user, or have a generic "make" utility, you
  1015. Xare in luck.  Just edit Makefile.dist according to the directions
  1016. Xgiven in that file, rename it as "makefile," then execute "make."
  1017. XIbpag2 should be created automatically.  If everything goes smoothly,
  1018. Xthen "make install" (su-ing root, if both possible and necessary for
  1019. Xcorrect installation of the iiparse.icn file).  Check with your system
  1020. Xadministrator if you are on a public system, and aren't sure what to
  1021. Xdo.
  1022. X
  1023. X    Please be sure to read the directions in the makefile
  1024. Xcarefully, and set DESTDIR and LIBDIR to the directory where you want
  1025. Xthe executable and parser file to reside.  Also, make sure the paths
  1026. Xyou specify are correct for your Icon executables.  Although Ibpag2
  1027. Xwill apparently compile using iconc, I would recommend using the
  1028. Xinterpreter, icont, first, unless you are planning on working with a
  1029. Xlarge grammar.
  1030. X
  1031. X    If you are using some other system - one that lacks "make" -
  1032. Xthen shame on your manufacturer :-).  You'll only be slightly
  1033. Xinconvenienced, though.  Type:
  1034. X
  1035. X    icont -o ibpag2 follow.icn ibpag2.icn ibreader.icn \
  1036. X         ibtokens.icn ibutil.icn ibwriter.icn iohno.icn \
  1037. X         outbits.icn slritems.icn slrtbls.icn shrnktbl.icn \
  1038. X         version.icn slshupto.icn
  1039. X
  1040. XThe backslashes merely indicate that the next line is a continuation.
  1041. XThe whole thing should, in other words, be on a single line.  As noted
  1042. Xabove, you may compile rather than interpret - if your OS supports the
  1043. XIcon compiler.  Just replace "icont" above with "iconc."  The
  1044. Xresulting executable will run considerably faster than with "icont,"
  1045. Xalthough the time required to compile it may be large, and the (still
  1046. Xsomewhat experimental) compiler may not work smoothly in all
  1047. Xenvironments.
  1048. X
  1049. X    If your operating system support environment variables, and
  1050. Xyou have set up your LPATH according to the specifications in the Icon
  1051. Xdistribution (see below), then you may copy iiparse.lib and
  1052. Xiiglrpar.lib to some file in your LPATH.  If you do not do this, or if
  1053. Xyour OS does not support environment variables, then you must be in
  1054. Xthe directory where you keep your Ibpag2 files when you use it, or
  1055. Xelse invoke Ibpag2 with the -p dirname option (where dirname is the
  1056. Xdirectory that holds the iiparse.lib and iiglrpar.lib files that come
  1057. Xwith the Ibpag2 distribution).  The .lib files contain template
  1058. Xparsers that are critical to Ibpag2's operation.  Ibpag2 will abort if
  1059. Xit cannot find them.
  1060. X
  1061. X    If your operating system permits the creation of macros or
  1062. Xbatch files, it might be useful to create one that changes
  1063. Xautomatically to the Ibpag2 source directory, and runs the executable.
  1064. XThis has the side-benefit of making it easier for Ibapg2 to find the
  1065. Xparser library files, iiparse.lib and iiglrpar.lib.  Under DOS, for
  1066. Xinstance, one might create a batch file that says:
  1067. X
  1068. X    c:
  1069. X    cd c:\ibpag2
  1070. X    iconx ibpag2 %1 %2 %3 %4 %5 %6 %7 %8 %9
  1071. X
  1072. XDOS, it turns out, has to execute Icon files indirectly through iconx,
  1073. Xso this technique has yet another advantage in that it hides the
  1074. Xsecond level of indirection - although it prevents you from using
  1075. Xinput and output redirection.  Naturally, the above example assumes
  1076. Xthat Ibpag2 is in c:\ibpag2.
  1077. X
  1078. X    Ibpag2 assumes the existence on your system, not only of an
  1079. XIcon interpreter or compiler, but also of an up-to-date Icon Program
  1080. XLibrary.  There are several routines included in the IPL that Bibleref
  1081. Xuses.  Make sure you (or the local system administrators) have put the
  1082. XIPL online, and have translated the appropriate object modules.  Set
  1083. Xyour IPATH environment variable to point to the place where the object
  1084. Xmodules reside.  Set LPATH to point to the modules' source files.
  1085. XBoth IPATH and LPATH are documented in doc directory of the Icon
  1086. Xsource tree (ipd224.doc).  If your system does not support environment
  1087. Xvariables, copy ximage.icn, options.icn, ebcdic.icn, and escape.icn
  1088. Xfrom the IPL into the Ibpag2 source directory, and compile them in
  1089. Xwith the rest of the Ibpag2 source files, either by adding them to the
  1090. XSRC variable in the makefile, or by adding them manually to the "icont
  1091. X-o ..." command line given above.
  1092. X
  1093. X    If you have any problems installing or using Ibpag2, please
  1094. Xfeel free to drop me, Richard Goerwitz, an e-mail message at
  1095. Xgoer@midway.uchicago.edu, or (via the post) at:
  1096. X
  1097. X    5410 S. Ridgewood Ct., 2E
  1098. X    Chicago, IL   60615
  1099. X
  1100. X
  1101. X6.__Bibliography
  1102. X
  1103. X1.  Aho, Alfred V., Sethi, Ravi, and Ullman, Jeffrey D.  Compilers.
  1104. X    Addison-Wesley: Reading, Massachusetts, second printing, 1988.
  1105. X
  1106. X2.  Griswold, Ralph E. and Griswold, Madge T.  The Icon Programming
  1107. X    Language. Prentice-Hall, Inc.: Englewood Cliffs, New Jersey, USA,
  1108. X    second edition, 1990.
  1109. X
  1110. X3.  Griswold, Ralph E., Jeffery, Clinton L., and Townsend, Gregg M.
  1111. X    Version 8.10 of the Icon Programming Language.  Univ. of Arizona
  1112. X    Icon Project Document 212, 1993.  (obtain via anonymous FTP from
  1113. X    cs.arizona.edu ~ftp/icon/docs/ipd212.doc)
  1114. X
  1115. X4.  Tomita, Masaru.  Efficient Parsing for Natural Language.  Boston:
  1116. X    Kluwer Academic Publishers, c. 1985.
  1117. X
  1118. X5.  Tomita, Masaru editor.  Generalized LR Parsing.  Boston:  Kluwer
  1119. X    Academic Publishers, 1991.
  1120. END_OF_FILE
  1121.   if test 52712 -ne `wc -c <'README'`; then
  1122.     echo shar: \"'README'\" unpacked with wrong size!
  1123.   fi
  1124.   # end of 'README'
  1125. fi
  1126. echo shar: End of archive 2 \(of 5\).
  1127. cp /dev/null ark2isdone
  1128. MISSING=""
  1129. for I in 1 2 3 4 5 ; do
  1130.     if test ! -f ark${I}isdone ; then
  1131.     MISSING="${MISSING} ${I}"
  1132.     fi
  1133. done
  1134. if test "${MISSING}" = "" ; then
  1135.     echo You have unpacked all 5 archives.
  1136.     rm -f ark[1-9]isdone
  1137. else
  1138.     echo You still must unpack the following archives:
  1139.     echo "        " ${MISSING}
  1140. fi
  1141. exit 0
  1142. exit 0 # Just in case...
  1143.