home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / pascal / qparser.arc / READ.ME < prev    next >
Text File  |  1985-09-30  |  53KB  |  1,454 lines

  1.  
  2.  
  3.  
  4.                         QPARSER Demonstration System
  5.  
  6.                        Version 2.3, September 3, 1985
  7.  
  8.                    Copyright (C) 1985, QCAD Systems, Inc.
  9.  
  10. Introduction
  11.  
  12. QPARSER  provides  a  strategy  and a set of software tools for compiler and
  13. translator development that we and other  professionals  have  found  to  be
  14. highly  productive.  The  strategy  is  one of writing semantic actions that
  15. respond to production rule ``triggers''. The tool set includes an LR  parser
  16. generator and several fully worked-out example programs.
  17.  
  18. QPARSER  provides  the  grammar-directed  ``front-end'',  as well as several
  19. software  tools  useful  in  developing  the  semantics  ``back-end''  of  a
  20. compiler. A comprehensive user manual is part of the full system.
  21.  
  22. The front-end is automatically generated, solving several difficult software
  23. problems. This is the half that scans and analyzes the input language forms,
  24. and  is capable of extracting meaning from them by relating them back to the
  25. rules of the defining grammar.
  26.  
  27. The back-end, which must be specially written for each application,  is  the
  28. operational  side  of the translator. It performs actions in response to the
  29. extracted meaning of input forms. Since translator actions are very  general
  30. in  nature,  it's  necessary to write these as Pascal or C program fragments
  31. for your application.
  32.  
  33. QPARSER will generate a parser automatically, but not a complete translator.
  34. The parser will contain the necessary source file access, a lexical scanner,
  35. symbol table functions, debugging tools and semantics tools.
  36.  
  37. QPARSER Features
  38.  
  39. The principal features of QPARSER are:
  40.  
  41.    * Correctness. The language accepted by the translator will be exactly
  42.    that specified by the grammar.
  43.    
  44.    * Detection of Ambiguity. If your grammar  is  ambiguous,  or  if  the
  45.    parser is unable to assure a correct translation, a diagnostic message
  46.    will be printed.
  47.  
  48.    *  Automatic generation of two key components. The lexical scanner and
  49.    the LR parser are automatically generated.
  50.    
  51.    * Efficient table-driven parser operations. For a large grammar,  most
  52.    compiler experts agree that a table-driven LR1 approach is superior in
  53.    both   performance  and  space  requirements  to  any  other.  Several
  54.    optimizations are made to minimize table size.
  55.    
  56.    * Modularity of semantic operations.  A  translator  programming  task
  57.    will become neatly partitioned into a number of relatively water-tight
  58.    compartments.
  59.    
  60.  
  61.  
  62.                                          page 1
  63.  
  64.  
  65.  
  66.  
  67.                           QPARSER Demonstration System
  68.  
  69.  
  70.    *  Efficient  lexical  scanner. The lexical scanner operates by a CASE
  71.    statement transfer on the  next  character  to  be  scanned  from  the
  72.    source. No backtracking, table searching or waste motion is involved.
  73.    
  74.    *  Efficient  and powerful symbol table mechanism. Symbol searching is
  75.    built into the lexical scanner, which is automatically generated.
  76.    
  77.    * Error recovery. A reasonable error recovery  system  is  built  into
  78.    each translator. No extra parser table space is required.
  79.    
  80.    *  Ease  of  extending  or changing the language. Once a translator is
  81.    written following the guidelines in the full  user  manual,  it'll  be
  82.    easy to extend or modify.
  83.    
  84.    *  Ease  of  extending or changing the lexical scanner. The scanner is
  85.    provided in well-documented source form.  Its  underlying  assumptions
  86.    are described in the user manual.
  87.  
  88. What's on the Demo Disk
  89.  
  90. The demo system diskette contains the following files:
  91.  
  92.    ShowQP.COM        -- a quick demo program
  93.    QPDEMO.TXT        -- needed by ShowQP
  94.    LR1.COM           -- the parser generator program
  95.    LR1P.COM          -- skeleton expander
  96.    PMACS.TXT         -- Pascal form macro file
  97.    LR1SKEL.PAS       -- a parser ``skeleton'' file
  98.    CALCDBUG.PAS, SKELRTBL.PAS, SKELNUM.PAS,
  99.    SKELSYMS.PAS, SKELDTBL.PAS  -- skeleton source files
  100.    CALC.GRM          -- grammar definition for calculator
  101.    CALCSKEL.PAS      -- skeleton file customized for calculator
  102.    CALCSEM.PAS, CALCUTIL.PAS  -- calculator-specific semantics
  103.    CALC.COM          -- executable calculator file
  104.    READ.ME           -- this text file
  105.  
  106. The Quick Demo
  107.  
  108. Select  the  floppy drive containing the demo diskette as the default drive.
  109. For example, if your floppy drive is A, then enter A: at the MS-DOS  command
  110. level.  Then  run ShowQP by typing its name. Youll be able to step through a
  111. simple demonstration of some of Qparsers features. (If you see some peculiar
  112. characters, you probably need to adjust your CONFIG.SYS  file  according  to
  113. the directions at the beginning of the demo.)
  114.  
  115. Configuration
  116.  
  117. We're  going  to  assume that your microcomputer system is an IBM PC/XT with
  118. the PC-DOS operating system, though  you  can  also  run  the  demos  on  an
  119. IBM-compatible  machine.  You'll  also  be  using  some  of the standard DOS
  120. functions in the  demonstrations.  A  Pascal  compiler  and  screen-oriented
  121. editor would make this demo system more meaningful, but aren't necessary.
  122.  
  123. The  full  QPARSER system requires a Pascal or C compiler and a text editor.
  124. We recommend a system with at least 256 Kbytes of memory and  a  hard  disk.
  125. Turbo Pascal (which includes a screen-oriented text editor) is provided with
  126.  
  127.  
  128.                                          page 2
  129.  
  130.  
  131.  
  132.  
  133.                           QPARSER Demonstration System
  134.  
  135.  
  136. the  full system, but not with the demo system. Order a copy of Turbo Pascal
  137. from QCAD Systems, and use it  for  additional  experiments  with  the  demo
  138. system.
  139.  
  140. Installation
  141.  
  142. If  your  computer  has  a  hard  disk: Copy the files from the QPARSER demo
  143. diskette to a new directory using the following commands, which assume  that
  144. the hard disk is the default drive:
  145.  
  146.         mkdir  \qparser
  147.         copy a:*.*  \qparser
  148.         cd  \qparser
  149.  
  150. You  will  now  be  able  to  run  the calculator examples from the \qparser
  151. directory.
  152.  
  153. If your computer does NOT have a hard disk: The  QPARSER  demo  diskette  is
  154. double-sided, which may not be readable from certain older PC versions. Call
  155. us if this is a problem -- we can supply the demo system on two single-sided
  156. diskettes.  In  any  case,  we  recommend copying some of the demo diskettes
  157. files -- for example, its .TXT and .PAS files -- to a  blank  diskette.  The
  158. following formats a new diskette, then copies all .PAS files from disk drive
  159. a to drive b:
  160.  
  161.         format b:
  162.         copy a:*.pas  b:
  163.  
  164. Getting Started
  165.  
  166. QPARSER  is  easy  to  try  out.  The  following operations will analyze the
  167. ``pocket calculator'' grammar and prepare a source Pascal file for a working
  168. interactive calculator.
  169.  
  170. Start by entering the two commands
  171.  
  172.    LR1  CALC
  173.    LR1P  CALC  -s  CALCSKEL
  174.  
  175. CALC.GRM contains the calculator's grammar and is read by the first  command
  176. (the  default  extension  .GRM  is  assumed).  LR1  produces a grammar table
  177. CALC.TBL. The second command reads CALC.TBL and CALCSKEL.PAS and produces  a
  178. full  Pascal  program  file CALC.PAS. A short report file will appear on the
  179. console.
  180.  
  181. Ordinarily, the CALC.PAS file would then need  to  be  compiled,  but  we've
  182. supplied  a compiled version of this file (CALC.COM) so that you can execute
  183. the calculator example and try out the parsing diagnostic  tools  without  a
  184. compiler.
  185.  
  186. If  you have a Pascal compiler, you might try compiling CALC.PAS instead. It
  187. follows Turbo Pascal conventions, and should compile without any  complaints
  188. with  that  compiler. If you are using another Pascal compiler, you may have
  189. to  edit  CALC.PAS  or  CALCSKEL.PAS  in  order  to   accommodate   compiler
  190. differences.
  191.  
  192.  
  193.  
  194.                                          page 3
  195.  
  196.  
  197.  
  198.  
  199.                           QPARSER Demonstration System
  200.  
  201.  
  202. Executing CALC.COM
  203.  
  204. When  you execute CALC.COM, you should see a prompt (>). You'll then be able
  205. to type arithmetic  expressions,  whose  values  will  be  reported  on  the
  206. console. For example,
  207.  
  208.    5 + 6.5*(9 - 3)
  209.  
  210. yields the result 44. An assignment statement, e.g.,
  211.  
  212.    x := 5 + 15
  213.  
  214. causes  variable  x  to  be  declared  and  receive  the  value  20. Then an
  215. assignment such as
  216.  
  217.    y := x + 5
  218.  
  219. can be evaluated, associating value 25 with variable y.
  220.  
  221. The point of this exercise is not to run a calculator,  but  to  demonstrate
  222. that a simple grammar and a short semantics file is sufficient to produce an
  223. interpreter  for  a simple language. We're next going to look at the grammar
  224. file (CALC.GRM) and the semantics files (CALCSEM.PAS  and  CALCUTIL.PAS)  to
  225. see what QPARSER does and what is required of you as the programmer.
  226.  
  227. The Calculator Grammar
  228.  
  229. Any  of  the  source  files  can  be examined by using a text editor of your
  230. choice, or the EDLIN or MORE command -- see the DOS  reference  manuals  for
  231. instructions.
  232.  
  233. The  calculator  grammar  file CALC.GRM is very short, so we'll reproduce it
  234. below:
  235.  
  236.       \  CALC -- A simple four-function calculator grammar
  237.       \          which allows variable assignments.
  238.    Goal     -> Stmts QUIT #quit
  239.    Stmts    -> Stmts Stmt
  240.             -> Stmt
  241.    Stmt     -> Expr <eol> #prtval
  242.             -> <identifier> := Expr <eol> #assign
  243.             -> <eol>    \ allow an empty line
  244.    Expr     -> Expr + Term #plus
  245.             -> Expr - Term #minus
  246.             -> Term
  247.    Term     -> Term * Fact #mpy
  248.             -> Term / Fact #divide
  249.             -> Fact
  250.    Fact     -> Primary
  251.             -> - Primary #uminus
  252.    Primary  -> ( Expr ) #parens
  253.             -> <identifier> #variable
  254.             -> <real> #realval
  255.             -> <integer> #intval
  256.  
  257. What does all this mean? First, anything starting with a backslash  (\)  is
  258.  
  259.  
  260.                                          page 4
  261.  
  262.  
  263.  
  264.  
  265.                           QPARSER Demonstration System
  266.  
  267.  
  268. just  a  comment.  Secondly,  a  symbol  preceded  by  a sharp sign (#) is a
  269. production rule tag, whose purpose will be explained later. What remains  is
  270. a list of production rules, whose general form is like this:
  271.  
  272.   <left-member> -> <right-member>
  273.  
  274. Whenever  a  left-member is missing, it is assumed to be the same as for the
  275. preceding rule. Thus the third rule, written
  276.  
  277.        -> Stmt
  278.  
  279. above, is actually
  280.  
  281.   Stmts -> Stmt
  282.  
  283. The primary purpose of a grammar is to define a language --  in  this  case,
  284. the algebraic formulas and assignment statements that can be legally entered
  285. when  the calculator is executed. A grammar is a set of production rules, or
  286. just rules for short. Each rule has exactly one left member element and  one
  287. or  more  right  member  elements,  each of which we shall call a token. The
  288. tokens are separated by one or more spaces.
  289.  
  290. For example,
  291.  
  292.   Term -> Term * Fact
  293.  
  294. is a rule in this grammar. Its left member token  is  Term,  and  the  three
  295. right  member  tokens  are  Term, *, and Fact. It says, in essence, that any
  296. input string form that is to be considered a Term must consist  of  a  Term,
  297. followed by an asterisk (*), followed by a Fact.
  298.  
  299. A  Term  and a Fact can each be expanded into any of a large number of token
  300. sequences, while the asterisk (*) stands for itself. Tokens  of  the  former
  301. kind  are  called  nonterminals,  while tokens of the latter kind are called
  302. terminals.
  303.  
  304. Another rule is
  305.  
  306.   Term -> Term / Fact
  307.  
  308. The left member token Term has been omitted in  the  grammar  file,  and  is
  309. therefore  inherited  from the previous rule in the grammars rule list. This
  310. rule says that a Term consists of a Term followed by a slash (/) followed by
  311. a Fact.
  312.  
  313. The first rule in the list
  314.  
  315.    Goal -> Stmts QUIT
  316.  
  317. will expand into the entire language. The left member  token  Goal  of  this
  318. rule  is not permitted anywhere else in the grammar. This rule says that any
  319. legal language form must consist of a member of Stmts followed by the  token
  320. QUIT.
  321.  
  322.  
  323.  
  324.  
  325.  
  326.                                          page 5
  327.  
  328.  
  329.  
  330.  
  331.                           QPARSER Demonstration System
  332.  
  333.  
  334. How a GOAL Symbol Expands into Forms
  335.  
  336. Lets start with the first rule:
  337.  
  338.    Goal -> Stmts QUIT
  339.  
  340. We see that Stmts appears on the left of two rules:
  341.  
  342.    Stmts -> Stmts Stmt
  343.    Stmts -> Stmt
  344.  
  345. This  means  that  we  can  choose  either  one of these two rules, and then
  346. substitute the right members for one appearance of the  left  member.  Let's
  347. choose the first rule, and make the substitution:
  348.  
  349.    Goal -> Stmts QUIT -> Stmts Stmt QUIT
  350.  
  351. Well,  we don't seem to be getting anywhere, because the token Stmts appears
  352. in our new, expanded form. However, we can close this cycle by choosing  the
  353. second Stmts rule for a substitution:
  354.  
  355.    Goal -> Stmts QUIT -> Stmts Stmt QUIT -> Stmt Stmt QUIT
  356.  
  357. It  should be clear that we can get a sequence of Stmt forms by choosing the
  358. first rule several times. Each substitution  step  is  called  a  derivation
  359. step; we are deriving a sentence in the language from the Goal token.
  360.  
  361. Now let's look at the Stmt rules. There are three of them, as follows:
  362.  
  363.    Stmt -> Expr <eol>
  364.    Stmt -> <identifier> := Expr <eol>
  365.    Stmt -> <eol>
  366.  
  367. The  special  token  <eol> is a predefined terminal token that stands for an
  368. enter. The special token <identifier> stands for any Pascal-like user  name;
  369. for example, L1, SAM_SMITH, MARY_JONES are all legal <identifier>s. The Expr
  370. is associated with some more rules, permitting more substitutions.
  371.  
  372. Let's  choose  the  first of these Stmt rules for the first substitution. We
  373. then have, starting from the Goal again:
  374.  
  375.    Goal -> Stmts QUIT -> Stmt QUIT -> Expr <eol> QUIT
  376.  
  377. More substitutions are now possible. There are  three  Expr  rules;  two  of
  378. these  include  an  Expr  and  a Term. There are also three Term rules, etc.
  379. Notice that the algebraic tokens +, -, *, / appear in these.
  380.  
  381. We'll continue the expansion by making various choices  along  the  way.  We
  382. suggest  trying one yourself on paper, to see just how many different ways a
  383. Goal can be expanded into sequences of algebraic formulas.
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.                                          page 6
  393.  
  394.  
  395.  
  396.  
  397.                           QPARSER Demonstration System
  398.  
  399.  
  400.    Goal -> Stmts QUIT
  401.         -> Stmt QUIT
  402.         -> Expr <eol> QUIT
  403.         -> Expr + Term <eol> QUIT
  404.         -> Term + Term <eol> QUIT 
  405.         -> Fact + Term <eol> QUIT
  406.         -> Primary + Term <eol> QUIT
  407.         -> <integer> + Term <eol> QUIT
  408.         -> <integer> + Fact <eol> QUIT
  409.         -> <integer> + Primary <eol> QUIT
  410.         -> <integer> + ( Expr ) <eol> QUIT
  411.         -> <integer> + ( Term - Term ) <eol> QUIT
  412.         -> <integer> + ( Term * Fact - Term ) <eol> QUIT
  413.         -> <integer> + ( Fact * Fact - Term ) <eol> QUIT
  414.         -> <integer> + ( Primary * Fact - Term ) <eol> QUIT
  415.         -> <integer> + ( <real> * Fact - Term ) <eol> QUIT
  416.         -> <integer> + ( <real> * Primary - Term ) <eol> QUIT
  417.         -> <integer> + ( <real> * <identifier> - Term ) <eol> QUIT
  418.         -> <integer> + ( <real> * <identifier> - Fact ) <eol> QUIT
  419.         -> <integer> + ( <real> * <identifier> - Primary ) <eol> QUIT
  420.         -> <integer> + ( <real> * <identifier> - <integer> ) <eol> QUIT
  421.  
  422. Whew! Fortunately, that's as far as we can go, because all  the  tokens  are
  423. terminal.  Now,  <integer>  stands for any decimal integer, and <real> for a
  424. floating-point number. So our derived sentence might look like this:
  425.  
  426.    15 + (17.65 * SAM - 45) <eol> QUIT <eol>
  427.  
  428. The <eol> will be interpreted as an `enter' when the parser is executed. The
  429. last enter will cause an exit from the calculator program.
  430.  
  431. Parsing
  432.  
  433. We've seen how a grammar can be written that  defines  some  language  we're
  434. interested  in.  At  this point, QPARSER can take over and produce a program
  435. that can invert these derivation steps. When a derivation step is  inverted,
  436. we  say  that  a  reduce step or a reduction has occurred. Such a program is
  437. called a bottom-up parser.
  438.  
  439. The program LR1 performs an analysis of the grammar and produces  a  set  of
  440. parser tables. Then program LR1P produces a parser program in Pascal source,
  441. using a Pascal-based macro file PMACS.
  442.  
  443. The actions performed by LR1 and LR1P are roughly as follows:
  444.  
  445.      1.  The nonterminal and terminal tokens are identified. The terminal
  446.    tokens are used to construct a lexical scanner,  which  when  executed
  447.    reads source strings and breaks them into the terminal token pieces.
  448.    
  449.      2. The grammar rules are then used to construct a so-called LR state
  450.    machine, which is an abstract description of a parser.
  451.  
  452.      3.  The abstract state machine description is turned into a specific
  453.    Pascal or C program. The state machine is carried in  the  program  in
  454.    tabular  form,  and  the  parser  is  a table interpreter. The lexical
  455.    scanner is expressed directly as Pascal or C statements.
  456.  
  457.  
  458.                                          page 7
  459.  
  460.  
  461.  
  462.  
  463.                           QPARSER Demonstration System
  464.  
  465.  
  466.  
  467. Following the Parser's Steps
  468.  
  469. You can follow the parsing steps of the CALC.GRM grammar by running CALC.COM
  470. again. This time, type the character ! before entering  an  expression,  for
  471. example,
  472.  
  473.    ! 15 + (17.65 * 22 - 45)
  474.  
  475. The  !  character will bring up a debugging prompt before any of the rest of
  476. the line is scanned. The debug prompt looks like this:
  477.  
  478. I(dentifier, D(ebug level, A(ll symbols, C(ontinue?
  479.  
  480. Type D, then 1 (enter), to choose debug level 1. You'll get the debug prompt
  481. again, so type C to continue. You should see a production printed:
  482.  
  483.    Primary -> <integer>
  484.  
  485. This  indicates  that  the  15  in  the  input  string has been scanned (the
  486. <integer>) and has been reduced to a Primary. The debug  prompt  will  again
  487. appear, so type C. The next production appears:
  488.  
  489.    Expr -> Term
  490.  
  491. This  indicates  that Primary has been reduced to Term and now Term is about
  492. to be reduced to Expr. The production rule Term -> Primary  will  always  be
  493. skipped over during parsing due to an optimization in the parsing tables.
  494.  
  495. Typing the next C will bring up
  496.  
  497.    Primary -> <real>
  498.  
  499. This says that the 17.65 in the input string has been scanned and reduced to
  500. a  Primary.  Keep typing C, and you'll see the rest of the productions. Here
  501. they are, as they  will  appear  during  the  parsing  process;  weve  added
  502. comments to show what's happening:
  503.  
  504.    Primary -> <integer>     \ 15
  505.    Term -> Term * Fact      \ 17.65 * 22 = 388.3
  506.    Expr -> Term
  507.    Primary -> <integer>     \ 45
  508.    Expr -> Expr - Term      \ 388.3 - 45 = 343.3
  509.    Primary -> ( Expr )
  510.    Expr -> Expr + Term      \ 15 + 343.3 = 358.3
  511.    Stmt -> Expr <eol>       \ the whole line
  512.  
  513. At this point, C will print a result and produce another prompt:
  514.  
  515.    = 358.3
  516.    >
  517.  
  518. Lets type in QUIT. We'll then see one more production:
  519.  
  520.  
  521.  
  522.  
  523.  
  524.                                          page 8
  525.  
  526.  
  527.  
  528.  
  529.                           QPARSER Demonstration System
  530.  
  531.  
  532.    > QUIT
  533.    Goal -> Stmts QUIT
  534.  
  535. One more C and the CALC program is done.
  536.  
  537. Looking at the Semantics Stack
  538.  
  539. In  the  above example, you've surely noticed that the first number (15) was
  540. scanned, then set  aside  temporarily  until  the  parenthesized  expression
  541. (17.65*22-45) could be scanned. Where was the value 15 kept while this extra
  542. work was going on?
  543.  
  544. The  answer is that it was held on a semantics stack. The semantics stack is
  545. a fundamental data structure of QPARSER. Every time a token is read from the
  546. input stream, state information is pushed on the stack associated  with  the
  547. token.  A  token  like <integer> causes the integer value to be saved on the
  548. stack. The token <real> causes a floating-point number to be saved, and  the
  549. token <identifier> causes a name to be saved.
  550.  
  551. When  a  production  rule  is  applied,  the top of the semantics stack will
  552. always carry information that  corresponds  to  the  right  members  of  the
  553. production. Let's do another trace and see how that information is carried.
  554.  
  555. Execute CALC.COM again with the same expression:
  556.  
  557.   > ! 15 + (17.65*22-45)
  558.  
  559. This  time,  choose  D(ebug level 2, then C(ontinue. Youll see the following
  560. display:
  561.  
  562.   <integer>            FIXED:  15
  563. Primary -> <integer>
  564.  
  565. This says that the semantics stack contains just one item, the first integer
  566. in the input stream. FIXED refers to its type, and the 15 is of  course  its
  567. value as held in the stack.
  568.  
  569. The next C(ontinue produces the following:
  570.  
  571.   Primary              FLOAT: 1.500E+01
  572. Expr -> Term
  573.  
  574. This  announces  that  the  fixed  point number 15 has been converted into a
  575. floating point number. That action was  caused  by  a  semantics  action  in
  576. response  to  the  production  Primary  ->  <integer>.  We'll see where that
  577. happened in the source program later.
  578.  
  579. The next C(ontinue produces the following:
  580.  
  581.   Expr                 FLOAT: 1.500E+01
  582.   +                    OTHER:
  583.   (                    OTHER:
  584.   <real>               FLOAT: 1.765E+01 \ TOS
  585. Primary -> <real>
  586.  
  587. Here we've scanned the +, the ( and the real number  17.65.  The  stack  has
  588.  
  589.  
  590.                                          page 9
  591.  
  592.  
  593.  
  594.  
  595.                           QPARSER Demonstration System
  596.  
  597.  
  598. four  items  -- its top (noted as TOS -- ``top-of-stack'' -- above) is shown
  599. at the end of the stack report. The production Primary -> <real> is about to
  600. be applied, and its right member refers to the <real>  on  the  top  of  the
  601. stack.
  602.  
  603. Now  we see where the 15 went while the remainder of the expression is being
  604. worked on -- it's held in the stack beneath the remaining material. It  will
  605. reappear later as the other material is reduced and popped from the stack.
  606.  
  607. Push  C  twice  --  well  skip  one step involving the production Primary ->
  608. <integer>. You should see the following stack:
  609.  
  610.   Expr                 FLOAT: 1.500E+01
  611.   +                    OTHER:
  612.   (                    OTHER:
  613.   Primary              FLOAT: 1.765E+01  \ TOS-2
  614.   *                    OTHER:            \ TOS-1
  615.   Primary              FLOAT: 2.200E+01  \ TOS
  616. Term -> Term * Fact
  617.  
  618. The productions right member (Term * Fact) seems not to correspond with  the
  619. three  top  stack  members,  but it does. The parser generator has optimized
  620. parsing  by  eliminating  some  unnecessary  reduction   steps.   The   Term
  621. corresponds to the Primary at TOS-2, and the Fact corresponds to the Primary
  622. at TOS.
  623.  
  624. This  production  indicates  that a multiplication is supposed to take place
  625. between the numbers in TOS and TOS-2. The product is 388.3 and  will  appear
  626. after you hit C again:
  627.  
  628.   Expr                 FLOAT: 1.500E+01
  629.   +                    OTHER:
  630.   (                    OTHER:
  631.   Primary              FLOAT: 3.883E+02   \ TOS
  632. Expr -> Term
  633.  
  634. Notice that the top three stack elements have been removed and replaced by a
  635. single  element  -- the floating point number 388.3. Hit C twice. You should
  636. get the following display:
  637.  
  638.   Expr                 FLOAT: 1.500E+01
  639.   +                    OTHER:
  640.   (                    OTHER:
  641.   Expr                 FLOAT: 3.883E+02  \ TOS-2
  642.   -                    OTHER:
  643.   Primary              FLOAT: 4.500E+01  \ TOS
  644. Expr -> Expr - Term
  645.  
  646. Here, the last number (45) has been scanned. The  stack  is  set  up  for  a
  647. subtraction.  Since the Expr in the production corresponds to TOS-2, and the
  648. Term to TOS, the calculator program is expected to subtract 45  from  388.3,
  649. yielding 343.3. That's shown in the next display, after hitting C:
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.                                          page 10
  657.  
  658.  
  659.  
  660.  
  661.                           QPARSER Demonstration System
  662.  
  663.  
  664.   Expr                 FLOAT: 1.500E+01
  665.   +                    OTHER:
  666.   (                    OTHER:
  667.   Expr                 FLOAT: 3.433E+02
  668.   )                    OTHER:
  669. Primary -> ( Expr )
  670.  
  671. This  production  won't  do any arithmetic, but must make sure that the Expr
  672. value 343.3 will appear on the stack top, associated with the  Primary.  The
  673. reduce action causes the parentheses to disappear, yielding:
  674.  
  675.   Expr                 FLOAT: 1.500E+01
  676.   +                    OTHER:
  677.   Primary              FLOAT: 3.433E+02
  678. Expr -> Expr + Term
  679.  
  680. At  last,  the  15 reappears at the right place to perform an addition. That
  681. operation yields 358.3, and the smaller stack:
  682.  
  683.   Expr                 FLOAT: 3.583E+02
  684.   <eol>                OTHER:
  685. Stmt -> Expr <eol>
  686.  
  687. This production prints the resulting Expr value on  the  console,  so  after
  688. hitting C, you should see:
  689.  
  690. = 358.3
  691. >
  692.  
  693. Type in ``QUIT'', then another C to end the program.
  694.  
  695. Some Observations
  696.  
  697. We've  run  through a complete trace for the pocket calculator example. What
  698. should be apparent is how the form  of  the  grammar  rules  determine  when
  699. operations  are  needed,  and also how the semantics stack mechanism ensures
  700. that information is available when it is needed.
  701.  
  702. The parser generator system has solved several algorithmic tasks for you:
  703.  
  704.      *  The  derivation  of  an  input  string  has  been  uncovered  and
  705.      reproduced in backward order, as a parser.
  706.        * Information is carried on the semantics stack until needed later.
  707.      *  Names and numbers are scanned and put into the stack at the right
  708.      place.
  709.      * When each production rule pops up, the top of the semantics  stack
  710.    carries just what is needed for the operation it implies.
  711.  
  712. You  can  do  any number of different things when a production rule pops up.
  713. We'll look at how that works next. We'll also take a look  at  some  of  the
  714. type declarations and procedures that implement the parser.
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.                                          page 11
  723.  
  724.  
  725.  
  726.  
  727.                           QPARSER Demonstration System
  728.  
  729.  
  730.                               Semantics Coding
  731.  
  732. Most  of  what  you've  seen in the semantics trace comes through the parser
  733. generator tools and the skeleton files. However, one  important  part  isn't
  734. automatic -- you must write a semantics procedure called APPLY.
  735.  
  736. Procedure  APPLY is the interface between the automatically generated parser
  737. and the semantics operations that you must design and write. Please look  at
  738. APPLY, founnd in file CALCSEM.PAS, while you read on.
  739.  
  740. APPLY  is  essentially a large CASE statement, whose tag names come from the
  741. tags attached to  the  production  rules  in  the  grammar.  We've  deferred
  742. discussion of these tags until now. Recall that a production rule tag is the
  743. name  following  a sharp sign in a production. For example, in CALC.GRM, the
  744. production
  745.  
  746.    Expr -> Expr + Term #plus
  747.  
  748. carries the tag plus, which you will find in  the  CALCSEM.PAS  source.  The
  749. APPLY  action  for  this  production  rule  is  essentially  to collapse the
  750. information in the top three elements  of  SEMSTACK  (corresponding  to  the
  751. right  member  Expr + Term) into a single element (corresponding to the left
  752. member Expr), as shown in figure 1.
  753.  
  754.     -----------------------------------------------------
  755.                      TOS
  756.     +---+---+---+---+---+
  757.     |   |   | E | + | T |  semstack:  BEFORE apply action
  758.     +---+---+---+---+---+          production E -> E + T
  759.               ^   ^   ^
  760.               |   |   +---- stackx
  761.               |   +-------- stackx-1
  762.               +------------ stackx-2
  763.     . . . . . . . . . . . . . . . . . . . . . . . . . . .
  764.  
  765.              TOS
  766.     +---+---+---+
  767.     |   |   | E |  semstack:  AFTER apply action
  768.     +---+---+---+
  769.               ^
  770.               +------------ stackx
  771.  
  772.   Figure 1.  Before and after APPLY operations on production
  773.                  E -> E + T
  774.   ----------------------------------------------------------
  775.  
  776. Here's what procedure APPLY looks like, with some of  the  material  removed
  777. for the sake of discussion:
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.                                          page 12
  789.  
  790.  
  791.  
  792.  
  793.                           QPARSER Demonstration System
  794.  
  795.  
  796.   procedure APPLY(PFLAG, PRODLEN: int; TSEMP: semrecp);
  797.     { Apply customized for the calculator.  All operations are kept
  798.       track of on the semantic stack. }
  799.   begin
  800.     case pflag of
  801.       { omitted material }
  802.       DIVIDE,   {Term -> Term / Fact}
  803.       MINUS,    {Expr -> Expr - Term}
  804.       MPY,      {Term -> Term * Fact}
  805.       PLUS:     {Expr -> Expr + Term}
  806.                 eval_binop(pflag, semstack[stackx-2], 
  807.                            semstack[stackx], tsemp);
  808.       { omitted material }
  809.     end { apply case }
  810.   end;
  811.  
  812. Notice  the PLUS tag. When the production Expr -> Expr + Term is ready to be
  813. applied, the parser system will call APPLY with a value of PFLAG  that  will
  814. direct  control  to  the PLUS statement. This statement happens to be shared
  815. with DIVIDE, MINUS, and MPY, but it doesn't have to be. You can  --  and  in
  816. fact  you  must -- distinguish production rules with distinct tag names. You
  817. can also omit the tag on any production that requires no special operation.
  818.  
  819. Notice that the function EVAL_BINOP passes the  flag  parameter  PFLAG,  and
  820. three  more  parameters. The second parameter, SEMSTACK[STACKX-2], refers to
  821. the  TOS-2  element  of  the   semantics   stack.   The   third   parameter,
  822. SEMSTACK[STACKX],  refers  to  the  TOS element. As we've seen in the trace,
  823. these carry information associated with the token.
  824.  
  825. The result of a stack operation is passed back through the variable TSEMP.
  826.  
  827. Procedure EVAL_BINOP
  828.  
  829. This procedure is in file CALCUTIL.PAS.  Note  that  the  two  operands  are
  830. passed  as  OPND1  and  OPND2,  respectively, and these are of type SEMRECP,
  831. which is the type of SEMSTACK[xxx].
  832.  
  833. EVAL_BINOP just sorts out which operation it is to perform, checking for the
  834. possibility that the entry might be OTHER. (OTHER will creep  in  through  a
  835. syntax error recovery patch.) The RESULT value will always be a real number,
  836. and  SEM_TYPE  will  therefore  always be FLOAT. EVAL_BINOP also attempts to
  837. produce a reasonable result, even though either of the operands might be the
  838. default type OTHER.
  839.  
  840. The procedure WRITE_VALUE, also in CALCUTIL.PAS, essentially decides how  to
  841. print  a  number.  All  numbers are stored in floating-point form, including
  842. integers, but a real number might be sufficiently close  to  an  integer  to
  843. justify  printing it that way. That's most of WRITE_VALUE. There are clearly
  844. other strategies that can be adopted.
  845.  
  846. The last two procedures, INIT_SEM and END_SEM, are called before any parsing
  847. action is taken, and after all actions are complete, respectively.  You  can
  848. use  these  for any initializations required at these times. Usually none is
  849. required.
  850.  
  851.  
  852.  
  853.  
  854.                                          page 13
  855.  
  856.  
  857.  
  858.  
  859.                           QPARSER Demonstration System
  860.  
  861.  
  862. The Types of SEMSTACK and TSEMP
  863.  
  864. You may wish to look at the Pascal type of the variables SEMSTACK and TSEMP.
  865. They are part of the global declarations in file CALCSKEL.PAS.  SEMSTACK  is
  866. an array of pointers to the record type SEMREC. Its top of stack will be the
  867. integer index STACKX.
  868.  
  869. Record  SEMREC  carries different cases for the different kinds of things to
  870. be carried in the  semantic  stack  --  IDENT  for  identifiers,  FIXED  for
  871. integers,  FLOAT  for  real numbers, etc. The record variable SEMT indicates
  872. which kind of object is in place, making it possible for a general  function
  873. like EVAL_BINOP to decide how to carry out an operation.
  874.  
  875. The  default  SEMT  type  OTHER  is  used for semantic objects that carry no
  876. special information, such as the operation tokens +, *, etc.
  877.  
  878. TSEMP is a pointer to a SEMREC record. In passing information  back  through
  879. an  APPLY  call,  the record field pointed to by TSEMP should be filled with
  880. something that will appear on the stack. You can choose to  do  nothing,  in
  881. which  case  TSEMP  will  point  to  the  default case OTHER. There's also a
  882. special case that's handy to know about: any single production with  no  tag
  883. causes  its  right  member  to  be  copied  into  its  left member. A single
  884. production is a production rule with exactly  one  right-member  token.  For
  885. example, the rule
  886.  
  887.    Fact -> Primary
  888.  
  889. qualifies  as  a  single  production.  When  its  tag is absent, the Primary
  890. information is just carried along on the stack without change.
  891.  
  892. Symbols and the Symbol Table
  893.  
  894. QPARSER provides a complete set of symbol table access  functions.  You  may
  895. wish  to look at their source, in file SKELSYMS.PAS. The global declarations
  896. associated with these functions are in CALCSKEL.PAS -- look  at  the  record
  897. SYMTABTYPE, and the other types and variables associated with it.
  898.  
  899. A  symbol  is  picked  up  by the lexical scanner whenever the grammar token
  900. <identifier> is scanned. The lexical scanner in QPARSER assumes  that  names
  901. and  other  tokens  follow Pascal rules -- but you can modify or rewrite the
  902. scanner to suit other language disciplines.
  903.  
  904. When an <identifier> is scanned, a default symbol table entry is  built  for
  905. it, and a pointer to that entry appears in the semantics stack. Symbol table
  906. entries  have  the form of the SYMTABTYPE record, and are allocated from the
  907. Pascal heap. An efficient name search algorithm is used,  based  on  a  hash
  908. table.  These  search  algorithms  are  expressed  in  the functions in file
  909. SKELSYMS.PAS.
  910.  
  911. The  skeleton  file  symbol  table  functions  are  suitable  for  flat   or
  912. block-scoped  names.  The user manual and the mini-Pascal compiler (included
  913. in the full QPARSER package) describe how they can be used  in  considerable
  914. detail  to cover a variety of special situations. Names can be unlinked from
  915. the table at the end of a block, and can also be deallocated from the heap.
  916.  
  917.  
  918.  
  919.  
  920.                                          page 14
  921.  
  922.  
  923.  
  924.  
  925.                           QPARSER Demonstration System
  926.  
  927.  
  928. Tracing Symbols
  929.  
  930. You can see how the symbol tracing system works by running  CALC.COM  again.
  931. This  time,  keep  the  debug  level  at  0, and enter each of the following
  932. formulas:
  933.  
  934.    X := 15
  935.    Y := X - 40
  936.    Z := X + Y
  937.  
  938. The calculator should report that X = 15, Y = -25, and Z = -10. Now enter  a
  939. ! character:
  940.  
  941.    !
  942.  
  943. You will get the usual debug menu:
  944.  
  945.    I(dentifier, D(ebug level, A(ll symbols, C(ontinue?
  946.  
  947. When you type A, you will be shown all the names known in the symbol table:
  948.  
  949.    Z Y X
  950.  
  951. (The  order  of these names is an accident of the hash table.) When you type
  952. I, you'll be prompted for a name, and then its attributes as  found  in  the
  953. symbol table will be reported:
  954.  
  955.    I(dentifier, D(ebug level, A(ll symbols, C(ontinue? I
  956.    What symbol? y
  957.     Y   REAL_VAR 0: -2.5000E+01
  958.  
  959. Some  of  these  attributes  will  always  be  provided. Others will require
  960. writing a short program segment to produce. In the above line,  Y,  REAL_VAR
  961. and  the  0  (scope  level)  are essentially automatic. Printing the numeric
  962. value (-2.5000E+01) requires adding a write to the standard debugging  file.
  963. To  see  what's  needed,  look at CALCDBUG.PAS, which contains the trace and
  964. interactive dump procedures. Most of this  is  generic  to  any  grammar  or
  965. language.  The  line  needed  to  support  the  calculator  may  be found in
  966. procedure DUMP_SYM, as follows:
  967.  
  968.    {---------- following line is specific to CALCDBUG -----------}
  969.         real_variable: write(rfile, rval);
  970.  
  971. Error Recovery
  972.  
  973. The  calculator  program  illustrates  the  generic  error  recovery  system
  974. provided  with  every generated translator. Error recovery operates from the
  975. parsing tables used by the parser. It attempts to find a local patch in  the
  976. vicinity  of  the  error.  The  patch  must  be  compatible with the parsing
  977. operations and is  searched  for  in  a  special  procedure  that  does  not
  978. interfere  with the mainstream of parsing operations. When a patch is found,
  979. the machine state and stack are  returned  to  the  main  parser  such  that
  980. parsing can continue as though there were no error.
  981.  
  982. The  error  recovery  system  does  not  depend  on  line endings or special
  983.  
  984.  
  985.                                          page 15
  986.  
  987.  
  988.  
  989.  
  990.                           QPARSER Demonstration System
  991.  
  992.  
  993. delimiter tokens. It will operate  as  effectively  for  a  block-structured
  994. language  as for a line-oriented language. It will usually find a reasonable
  995. patch in one step. It does not require scanning ahead through more tokens in
  996. order to find a patch, although  that  would  help  make  a  more  effective
  997. decision.
  998.  
  999. Try  running  CALC.COM with some invalid formulas. The following illustrates
  1000. two cases and the recovery report. Note that the syntax error report  points
  1001. to the position of the error in the input line:
  1002.  
  1003.    >  x y + 15
  1004.         ^
  1005.    ERROR: syntax error
  1006.    Type any character to continue:
  1007.    = 5.0000000001
  1008.  
  1009. Here  the  patch  yielded  some  new  expression;  the  program nevertheless
  1010. produced a partial result.
  1011.  
  1012.    > x := y ++ 15
  1013.              ^
  1014.    ERROR: syntax error
  1015.    Type any character to continue:
  1016.    Undefined variable ERR#AA
  1017.    X              := -10.000000001
  1018.  
  1019. Here, the patch amounted to creating and inserting a new identifier  between
  1020. the  two  +  signs,  ERR#AA.  This will be tagged as an ERRSYM in the symbol
  1021. table, but our semantics routine didn't pay attention to that and complained
  1022. about the undefined variable. It's possible to continue semantics  checking,
  1023. working around the possible error insertions, but it would be easier to just
  1024. suppress all semantics operations upon finding the first syntax error.
  1025.  
  1026. SUMMARY: What's Automatic and What Isn't
  1027.  
  1028. We  can now review what QPARSER provides automatically and whats required of
  1029. you as a programmer in order to generate a complete translator or compiler.
  1030.  
  1031. In general, you must design and  implement  the  grammar  and  the  semantic
  1032. functions.  You  will  need to expand the number of categories of the SEMREC
  1033. and SYMTABTYPE record structures, since these  contain  only  a  few  simple
  1034. types.
  1035.  
  1036. When   these   are   expanded,  some  additions  will  be  needed  (e.g.  to
  1037. SKELDBUG.PAS) to support symbolic tracing and debugging, as weve seen.
  1038.  
  1039. Designing and writing the semantic functions start with the APPLY procedure.
  1040. When you are starting from scratch with a grammar, the parser generator will
  1041. produce a dummy APPLY procedure for you automatically.  It  will  look  like
  1042. this, using the CALC.GRM grammar as an example:
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.                                          page 16
  1052.  
  1053.  
  1054.  
  1055.  
  1056.                           QPARSER Demonstration System
  1057.  
  1058.  
  1059.   procedure APPLY(PFLAG, PRODLEN: int; TSEMP: semrecp);
  1060.     begin
  1061.       case pflag of
  1062.         ASSIGN:
  1063.           begin  { Stmt -> <identifier> := Expr <eol> }
  1064.             writeln(rfile, ASSIGN applied.);
  1065.           end;
  1066.         DIVIDE:
  1067.           begin  { Term -> Term / Fact }
  1068.             writeln(rfile, DIVIDE applied.);
  1069.           end;
  1070.           { ... material omitted ... }
  1071.         UMINUS:
  1072.           begin  { Fact -> - Primary }
  1073.             writeln(rfile, UMINUS applied.);
  1074.           end;
  1075.         VARIABLE:
  1076.           begin  { Primary -> <identifier> }
  1077.             writeln(rfile, VARIABLE applied.);
  1078.           end;
  1079.       end
  1080.     end;
  1081.  
  1082. The  generator has provided a separate CASE item for each tagged production,
  1083. in alphabetic order, and has included the production for reference  purposes
  1084. as a comment. It has also provided a writeln to the report file rfile.
  1085.  
  1086. You can compile and execute a generated program based on nothing more than a
  1087. grammar. Tagged productions will announce themselves during its execution as
  1088. indicated  above.  You  can  then start to fill in the separate slots in the
  1089. APPLY case table with ``real semantics operations, testing the result as you
  1090. add various modules.
  1091.  
  1092. The generic tracing and debugging tools will also operate  with  no  special
  1093. additions,  although they cannot report your SEMREC or SYMTABTYPE extensions
  1094. without some help.
  1095.  
  1096. The Full QPARSER System
  1097.  
  1098. This demo guide is essentially the introductory chapter of the full  QPARSER
  1099. user manual. The full system contains, in addition to an unrestricted parser
  1100. generator and the calculator example discussed above, all of the following:
  1101.  
  1102.      1.  A  comprehensive  user  manual containing a language tutorial, a
  1103.    detailed discussion of the lexical scanner,  symbol  table,  semantics
  1104.    stack,   use  of  the  heap,  the  example  assembler,  simulator  and
  1105.    mini-Pascal compiler, and a technical summary. The  user  manual  also
  1106.    contains listings of all supplied source programs.
  1107.    
  1108.      2.  A  C  skeleton  and  a  companion macro file CMACS.TXT that will
  1109.    produce a complete, ready-to-compile parser in Kernighan  and  Ritchie
  1110.    C.
  1111.  
  1112.      3.  A  grammar  checking  and  analysis  program. This can produce a
  1113.    cross-reference table of the  grammar  and  report  all  terminal  and
  1114.    nonterminal  tokens.  It  looks  for  useless  nonterminals  and other
  1115.  
  1116.  
  1117.                                          page 17
  1118.  
  1119.  
  1120.  
  1121.  
  1122.                           QPARSER Demonstration System
  1123.  
  1124.  
  1125.    grammar problems, such as a single production  cycle.  It  can  report
  1126.    FIRST,   FOLLOW   and   PREDECESSOR   sets,   which  are  valuable  in
  1127.    understanding LR conflicts and in designing semantics structures.
  1128.    
  1129.      4. A simulator and assembler for a simple Pcode-style stack  machine
  1130.    is  provided, in Pascal source form. The assembler makes use of the LR
  1131.    translator system -- its grammar is also  provided.  If  you  want  to
  1132.    write  an  assembler  for any purpose or machine, this provides a good
  1133.    starting point.
  1134.  
  1135.      5. A Pascal subset compiler is provided in Pascal source form, along
  1136.    with its grammar and a detailed  discussion  of  its  internals.  This
  1137.    illustrates  the  design  of  a  user  type  declaration  scheme, full
  1138.    expression evaluation, constant folding,  several  control  structures
  1139.    with   some   optimizations,  compound  name  access  evaluation  with
  1140.    optimizations, and a procedure call/exit mechanism.  If  you  want  to
  1141.    write  a  compiler  or  interpreter for a language using any or all of
  1142.    these Pascal features, this grammar and  source  material  is  a  good
  1143.    starting point.
  1144.    
  1145.      6.  A  copy  of  Turbo  Pascal is provided. All of the Pascal source
  1146.    materials are compatible with this compiler. It contains a full screen
  1147.    editor as well. You can order this product separately from us  if  you
  1148.    wish  to  explore the demo system more fully. Turbo Pascal has certain
  1149.    limitations, as summarized below. For a large project, you will likely
  1150.    prefer a more powerful Pascal or C compiler.
  1151.  
  1152. Educational Applications
  1153.  
  1154. Are you an instructor of a  course  in  compiler  construction  or  language
  1155. theory?  If so, you will find QPARSER a valuable laboratory addition to your
  1156. course. The system has been  adopted  by  several  educational  institutions
  1157. (write  or  call  for  more information). The second edition of the textbook
  1158. written by Dr. William Barrett supplements QPARSER,  and  is  scheduled  for
  1159. release by SRA (Chicago) by December, 1985.
  1160.  
  1161. In  addition  to  the  obvious grammar and semantics experiments that can be
  1162. performed,  the  parser  generator  can  produce  detailed  item  sets  that
  1163. eventually  form  the LR state machine. The effects of various optimizations
  1164. can also be followed, and the item-sets traced through to  the  final  state
  1165. machine.
  1166.  
  1167. You  can observe the development of the item-sets by selecting a fairly high
  1168. report level when executing LR1 -- these range from 0 to 6  and  provide  an
  1169. increasingly detailed set  of reports.  For example,  here's a  command line
  1170. that will provide such a report file:
  1171.  
  1172.    LR1 CALC -l3 CALCRPT.TXT
  1173.  
  1174. There  are  no  hidden object files or undocumented features in QPARSER. LR1
  1175. produces a set of parser tables that  are  clearly  defined  by  the  source
  1176. access  procedures  and  the  parser  itself. Many of the experiments can be
  1177. performed without writing any Pascal programs.
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.                                          page 18
  1184.  
  1185.  
  1186.  
  1187.  
  1188.                           QPARSER Demonstration System
  1189.  
  1190.  
  1191. Copy Protection
  1192.  
  1193. Only one program is copy protected in the full system --  thats  the  parser
  1194. generator  LR1.  Its  provided  in  object  form  only. The IBM versions use
  1195. SoftGuard. After installing LR1 to a hard disk or floppy diskette,  you  can
  1196. then  freely execute LR1 without having the distribution diskette physically
  1197. present. You can also install a second copy for backup purposes.
  1198.  
  1199. The university editions enable multiple copies to  be  made  from  a  single
  1200. distribution  diskette.  The  instructor  must submit a signed qualification
  1201. form to us.
  1202.  
  1203. LR1 Specifications
  1204.  
  1205. The parser generator LR1 constructs an item-set state machine with an  LR(0)
  1206. construction.  Inadequate states are identified and converted into lookahead
  1207. states. The lookahead token sets for reduce  actions  are  computed  by  the
  1208. DeRemer-Penello  LALR(1)  method, as reported in ACM Transactions on Program
  1209. Languages & Systems, Vol 4, No. 4, October 1982.
  1210.  
  1211. A failure to resolve a state by LALR results in a resolution  report  and  a
  1212. default  resolution.  Special tags may be added to production rules to guide
  1213. the resolution process.
  1214.  
  1215. Resolution may result in one or more useless  lookahead  states;  these  are
  1216. removed along with any unreachable states found. If the halt state cannot be
  1217. reached from the goal state, an error report is generated.
  1218.  
  1219. Untagged single productions are bypassed if the LR state machine so permits.
  1220. The  resulting  state  tables are folded by identifying common subsequences.
  1221. These tables are of a sparse-matrix type,  resulting  in  great  economy  of
  1222. representation of the final machine, without sacrificing performance.
  1223.  
  1224. Several  tables  are  produced  to  facilitate  symbolic  debugging -- these
  1225. include production and token tables. These may easily  be  suppressed  along
  1226. with the debugging procedures for a production version of the translator.
  1227.  
  1228. The   automatically-generated  lexical  scanner  assumes  that  Pascal-style
  1229. lexical analysis is appropriate. These assumptions are explained in the user
  1230. manual and are also manifest in the  skeleton  source  files.  A  choice  of
  1231. Pascal  or C is provided for automatic generation. For other host languages,
  1232. you will have to write your own skeletons, perhaps by editing a Pascal or  C
  1233. skeleton.
  1234.  
  1235. All  the  generated  material  and  all  the  skeleton files are provided in
  1236. machine-readable source form, permitting  their  adaptation  to  other  host
  1237. languages.
  1238.  
  1239. Limitations of LR1
  1240.  
  1241. The demo version of LR1 is limited to 25 production rules.
  1242.  
  1243. The  full  system  is  limited  to  255  terminal tokens and 255 nonterminal
  1244. tokens. There are no other hard-bound limits other  than  maximum  available
  1245. heap  memory  size.  LR1s  data structures are allocated from memory in just
  1246. sufficient quantities as needed. Space  no  longer  needed  is  disposed  or
  1247.  
  1248.  
  1249.                                          page 19
  1250.  
  1251.  
  1252.  
  1253.  
  1254.                           QPARSER Demonstration System
  1255.  
  1256.  
  1257. released.  The  program  requires  about 65 Kbytes, and the stack another 65
  1258. Kbytes maximum. MS-DOS uses another 30 Kbytes. The rest  of  the  memory  is
  1259. available for heap.
  1260.  
  1261. Weve  found  that  the  mini-Pascal  grammar, with 140 productions, requires
  1262. about 200 Kbytes of heap space. LR1 completes in less than two minutes on an
  1263. IBM XT.
  1264.  
  1265. More About Turbo Pascal
  1266.  
  1267. All of the examples supplied with QPARSER will  compile  and  execute  under
  1268. Turbo  Pascal.  Turbo  has  a number of features that make it attractive for
  1269. software development. Its screen-oriented editor is nicely  integrated  with
  1270. the  compiler.  Syntax  errors are reported through the editor by the screen
  1271. cursor. Run-time errors can be traced to a single line in the program in the
  1272. editor.
  1273.  
  1274. Turbo may be ordered  separated  at  the  regular  retail  price  from  QCAD
  1275. Systems, Inc. One copy is included with the full QPARSER system.
  1276.  
  1277. However,  you will find that Turbo has a number of size limitations that may
  1278. interfere with the development of a large compiler system, as follows:
  1279.  
  1280.   * The compiled Turbo program space is limited to 64 Kilobytes. This  limit
  1281. can be exceeded somewhat by using overlays. The limit does not depend on the
  1282. total memory of your machine.
  1283.  
  1284.   * The Turbo compiler does not support independently compiled modules. Thus
  1285. the  entire  Pascal  program,  with  all  include files, must fit within the
  1286. compilers space limitations.
  1287.  
  1288.   * The Turbo editor is limited to  63  Kilobytes  of  source  data.  It  is
  1289. possible that the LR1 generator will produce a file too large to be accepted
  1290. by this editor. Note that EDLIN (on the IBM) can accept an arbitrarily large
  1291. source file.
  1292.  
  1293.   *  There  are certain other limitations explained in the Turbo manual that
  1294. may affect your development.
  1295.  
  1296. The LR1 parser generator will make full use of the maximum  memory  of  your
  1297. system, however, and can generate an arbitrarily large program file.
  1298.  
  1299. If you are impacted by the Turbo memory limitations, we recommend the use of
  1300. a  different  editor  and/or  compiler  for the compilation of the generated
  1301. translators.
  1302.  
  1303. Other Systems and Services
  1304.  
  1305. QPARSER  can  be  provided  on  the  VAX/VMS,  MacIntosh   512K,   and   the
  1306. Hewlett-Packard  series  200.  Quantity and dealer discounts available. Site
  1307. and source  licenses  available.  Consultation  with  our  expert  staff  on
  1308. specific language or translator issues can be arranged. Call for details and
  1309. prices.
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.                                          page 20
  1316.  
  1317.  
  1318.  
  1319.  
  1320.                           QPARSER Demonstration System
  1321.  
  1322.  
  1323. For Further Study
  1324.  
  1325. We  hope  weve given you some notion of whats required to make effective use
  1326. QPARSER user manual is itself a condensed course in language
  1327. theory, and is available separately. The following is a  short  bibliography
  1328. of books on compiler theory.
  1329.  
  1330. Compiler  Construction:  Theory  and  Practice,  Barrett  and Couch, Science
  1331. Research Associates, Inc, second edition, 1985.
  1332.  
  1333. Principles of Compiler Design, Aho and Ullman, Addison-Wesley, 1979.
  1334.  
  1335. The Theory of Parsing, Translation, and  Compiling,  two  volumes,  Aho  and
  1336. Ullman, Prentice-Hall, 1973.
  1337.  
  1338.  
  1339.  
  1340. Turbo Pascal is a registered trademark of Borland International.
  1341. QPARSER is a trademark of QCAD Systems, Inc.
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.                                          page 21
  1384.  
  1385.  
  1386.  
  1387.  
  1388.                           QPARSER Demonstration System
  1389.  
  1390.  
  1391.                              PRODUCT ORDER FORM
  1392.  
  1393. QCAD Systems, Inc.
  1394. 1164 Hyde Avenue, San Jose, CA  95129  (408) 727-6671
  1395. TOLL-FREE: (800) 538-9787 (outside California)
  1396.  
  1397. Quantity    Item                                     Unit Price   Total
  1398. -----------------------------------------------------------------------------
  1399.             Qparser Industrial system                 $400.00
  1400.  
  1401.             Qparser University system*                 400.00
  1402.  
  1403.             Qparser Demo Package                        10.00
  1404.  
  1405.             Qparser User Manual                         25.00
  1406.  
  1407.             Turbo Pascal 3.0                            69.95
  1408.  
  1409.             Qtools -- Unix-like tool kit                49.50
  1410.  
  1411.             Qroff -- Laserjet typesetting system        79.95
  1412.  
  1413.                                   SUB-TOTAL
  1414.                                   TAX (CA residents)
  1415.                                   SHIPPING (overseas)
  1416.                                   GRAND TOTAL
  1417.  
  1418.  * Please enclose educational agreement
  1419.  
  1420.  Name __________________________________________________________________
  1421.  
  1422.  Company _______________________________________________________________
  1423.  
  1424.  Address _______________________________________________________________
  1425.  
  1426.  City _________________________________ State ____________ ZIP _________
  1427.  
  1428.  Computer System _______________________________
  1429.  
  1430.  Method of payment:
  1431.  
  1432.     ___ check enclosed
  1433.     ___ charge card #: __________________________  Exp: ____________
  1434.  
  1435.         Name on card:  _____________________________________________
  1436.         Visa ___  Mastercard ___
  1437.  
  1438.     ___ purchase order #: _______________________
  1439.  
  1440.  (prices subject to change without notice)
  1441.  
  1442.  OVERSEAS SHIPPING:  $5.00 each for Qroff, Qtools, Qparser demo;
  1443.  $20.00 for full Qparser system; $10.00 for Qparser manual or Turbo.
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.                                          page 22
  1450.  
  1451.  
  1452.  
  1453.  
  1454.