home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pccts1.zip / BEGTUT.TXT < prev    next >
Text File  |  1993-09-07  |  36KB  |  1,489 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.                         Introductory Tutorial
  9.  
  10.  
  11.                               PCCTS 1.xx
  12.  
  13.  
  14.                Terence Parr, Will Cohen, and Hank Dietz
  15.  
  16.                    School of Electrical Engineering
  17.                           Purdue University
  18.                       West Lafayette, IN  47907
  19.                               Fall 1993
  20.  
  21.                             parrt@acm.org
  22.                         cohenw@ecn.purdue.edu
  23.                          hankd@ecn.purdue.edu
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.      The Purdue Compiler-Construction Tool Set (PCCTS) is  a  set
  32.      of  public  domain software tools designed to facilitate the
  33.      implementation of compilers and other  translation  systems.
  34.      In  many  ways, PCCTS is similar to a highly integrated ver-
  35.      sion of YACC and LEX; where ANTLR (ANother Tool for Language
  36.      Recognition)  corresponds to YACC and DLG (DFA-based Lexical
  37.      analyzer Generator) functions like LEX.  However, PCCTS  has
  38.      many  additional  features which make it easier to use for a
  39.      wide range of translation problems.
  40.  
  41.      This document introduces the basic functionality of PCCTS by
  42.      example.   The user need not be familiar with parsing theory
  43.      or other compiler tools, but  any  familiarity  reduces  the
  44.      learning curve substantially.  The PCCTS reference manual is
  45.      a necessary supplement to this tutorial as information  here
  46.      regarding PCCTS structures and operation is incomplete.
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.                                                                 Page 1
  63.  
  64. PCCTS Introductory Tutorial 1.xx
  65.  
  66.  
  67. 1.  Introduction
  68.  
  69.      PCCTS allows the user to  describe  languages  (e.g.  programming
  70. language,  OS  shell, game, editor); from such a description, a C pro-
  71. gram is generated that recognizes and, optionally, translates  phrases
  72. in that language.  The user must specify the following:
  73.  
  74. (i)  How the input stream is to be broken  up  into  lexemes  (tokens)
  75.      which comprise the vocabulary of the language.
  76.  
  77. (ii) How the tokens are to be grouped; i.e. what structure/grammar  is
  78.      to be applied to the token stream.
  79.  
  80. (iii)C actions which perform a user-specified translation.  Along with
  81.      this   specification,   the   user   must   also  describe  token
  82.      attributes-objects that actions use to communicate with the lexi-
  83.      cal analysis phase of translation.
  84.  
  85. Similarly, this  tutorial  is  broken  up  into  sections  on  lexical
  86. analysis, syntactic analysis, and actions/translation.
  87.  
  88. 2.  Lexical Analysis
  89.  
  90.      Before understanding a phrase in English, one must  separate  the
  91. stream  of  characters  into  a  stream  of  words;  e.g.  the phrase:
  92. "thisisveryhardtoread" accentuates this fact-recognition cannot easily
  93. be done from a character stream, only from word/token streams.
  94.  
  95.      Compilers and  other  translators  are  very  strict  about  this
  96. "tokenization"  and generally describe tokens via regular expressions-
  97. expressions that describe sets of character  sequences.   The  regular
  98. expressions are, in fact, language descriptions as well.  For example,
  99. hello is a regular expression that recognizes a sequence of five char-
  100. acters; namely, the word: "hello".  To inform PCCTS that "hello" is to
  101. be a word in the vocabulary of your language, simply use the  word  in
  102. your grammar or place the following description in your grammar file.
  103.  
  104.  
  105. #token LABEL "hello"
  106.  
  107.  
  108.  
  109. where LABEL is some label (C #define) that you  want  associated  with
  110. that  token.  To test regular expressions in PCCTS, let us form a sim-
  111. ple, complete description which recognizes "hello" (we will  use  this
  112. description as a base for all examples in this section):
  113.  
  114.  
  115. #header <<#include "charbuf.h">>
  116.  
  117. <<main() { ANTLR(a(), stdin); }>>
  118.  
  119. a : "hello" ;
  120.  
  121.  
  122.  
  123.  
  124.                                                                 Page 2
  125.  
  126. PCCTS Introductory Tutorial 1.xx
  127.  
  128.  
  129. This is a minimal description in that it  contains  everything  needed
  130. for PCCTS to generate an executable (actually, to generate all C files
  131. needed for the C compiler to generate  an  executable).   The  #header
  132. <<...>>  instruction  informs PCCTS that the C code inside the <<...>>
  133. action is necessary to define attributes and to  compile  the  actions
  134. found  elsewhere;  for  this section, we will ignore its significance.
  135. The second action gives a main program that specifies where  C  is  to
  136. begin  execution.  It contains one statement which asks ANTLR to begin
  137. parsing at rule a.  The third component of this description is a  rule
  138. definition.  Rules definitions have the form:
  139.  
  140.  
  141. rule: alternative  | alternative  | ... | alternative  ;
  142.                  1              2                    n
  143.  
  144.  
  145. where each alternative is a sequence of  grammatical  structures  that
  146. are  to be matched-one of possible structures is a simple token refer-
  147. ence ("hello", in our case).  Therefore, rule a says, "match the token
  148. identified  as "hello" on the input stream".  The C function generated
  149. for rule a asks the lexical analyzer, generated by PCCTS,  to  collect
  150. characters  until it sees a complete token.  Each token in the vocabu-
  151. lary is given a unique number which the lexical  analyzer  returns  to
  152. indicate what token was just matched.  Function a() then verifies that
  153. the number associated with "hello" is indeed returned by  the  lexical
  154. analyzer.
  155.  
  156.      The above example can be tested via  the  following  sequence  of
  157. commands:
  158.  
  159.  
  160. antlr -gk t.g
  161. dlg -i parser.dlg scan.c
  162. cc -I../h -o t t.c scan.c err.c
  163.  
  164.  
  165. The first command generates the parser, t.c, the lexical  description,
  166. parser.dlg,  and  a  support file, err.c.  The second command converts
  167. the lexical description to a C file that constitutes our scanner (lex-
  168. ical analyzer).  The third command compiles all C files needed to gen-
  169. erate the executable (the -I../h option tells the C compiler where  to
  170. look  for  the  standard  PCCTS include files; you will have to change
  171. this to where the PCCTS include files are located).  The output on our
  172. UNIX system looks like this (assuming the example is in file t.g):
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.                                                                 Page 3
  187.  
  188. PCCTS Introductory Tutorial 1.xx
  189.  
  190.  
  191.  
  192. % antlr -gk t.g
  193. Antlr parser generator   Version 1.10   1989-1993
  194. % dlg -i parser.dlg scan.c
  195. dlg  Version 1.10   1989-1993
  196. % cc -I../h -o t t.c scan.c err.c
  197. t.c:
  198. scan.c:
  199. err.c:
  200. Linking:
  201.  
  202.  
  203.  
  204. To test the grammar file, run the executable:
  205.  
  206.  
  207. % t
  208. hello
  209. %
  210.  
  211.  
  212.  
  213. No error message is generated and t  terminates  successfully.   If  a
  214. token not in the vocabulary of our language is typed, an error message
  215. appears.  We have only one word in our vocabulary, and hence, anything
  216. other than "hello" generates an error.
  217.  
  218.  
  219. % t
  220. bob
  221. invalid token near line 1 (text was 'b')
  222. invalid token near line 1 (text was 'o')
  223. invalid token near line 1 (text was 'b')
  224. invalid token near line 1 (text was '
  225. ')
  226. ^Dline 1: syntax error at "EOF" missing WORD
  227. %
  228.  
  229.  
  230.  
  231. The first "invalid token" errors are from the scanner, the  last  mes-
  232. sage is from the parser (function a()) indicating that end-of-file was
  233. found when a WORD was expected.   EOF  was  returned  by  the  scanner
  234. because  bob  was  ignored and end-of-file appeared immediately after-
  235. wards; EOF is a predefined token in any PCCTS vocabulary and is  iden-
  236. tified by the regular expression "@".
  237.  
  238.      Adding more tokens to your language's vocabulary  is  easy-simply
  239. reference  more  regular  expressions in your rules or add more #token
  240. definitions.  Consider this new example:
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.                                                                 Page 4
  249.  
  250. PCCTS Introductory Tutorial 1.xx
  251.  
  252.  
  253.  
  254. #token    "\ "     <<zzskip();>>            /* ignore blanks */
  255. #token    "\t"     <<zzskip();>>            /* ignore tabs */
  256. #token    "\n"     <<zzline++; zzskip();>>  /* ignore newlines */
  257. #token A  "apple"
  258. #token P  "pear"
  259.  
  260.  
  261.  
  262. This example introduces lexical actions-actions that are executed upon
  263. recognition  of  a  particular  regular expression.  For most language
  264. descriptions, lexical actions are not used except to tell the  scanner
  265. to  skip a token or continue looking for more characters.  zzskip() is
  266. a      standard      PCCTS      function       (generally,       PCCTS
  267. variables/functions/defines  are prefixed with zz to avoid name colli-
  268. sions with user variables) which forces  the  scanner  to  ignore  the
  269. currently  matched token and to try to find another.  Essentially, the
  270. first three token definitions here tell the  scanner  that  it  is  to
  271. ignore  white  space, but to increment the current line number when it
  272. sees a newline.  The fourth and fifth definitions introduce two  words
  273. into  our vocabulary.  Notice that only the last two have labels asso-
  274. ciated with them.  Any #token instruction may give a label,  but  they
  275. are  not necessary.  Labels are handy when you want an action to refer
  276. to the value (token number) of a particular token; also, when a  regu-
  277. lar  expression is complicated or confusing, often it is better to use
  278. a label throughout your grammar  rather  than  repeating  the  regular
  279. expression.   To  illustrate  this,  we  present  the  following  four
  280. equivalent partial PCCTS descriptions:
  281.  
  282. (i)  Repeated use of labels.
  283.  
  284.  
  285. #token A "apple"
  286. #token P "pear"
  287.  
  288. a : A P
  289.   | P A
  290.   ;
  291.  
  292.  
  293.  
  294. (ii) Repeated use of expressions.
  295.  
  296.  
  297. #token "apple"
  298. #token "pear"
  299.  
  300. a : "apple" "pear"
  301.   | "pear" "apple"
  302.   ;
  303.  
  304.  
  305.  
  306. (iii)Repeated use of implicitly-defined expressions.
  307.  
  308.  
  309.  
  310.                                                                 Page 5
  311.  
  312. PCCTS Introductory Tutorial 1.xx
  313.  
  314.  
  315.  
  316. a : "apple" "pear"
  317.   | "pear" "apple"
  318.   ;
  319.  
  320.  
  321.  
  322. (iv) Mixed use of labels and expressions.
  323.  
  324.  
  325. #token A  "apple"
  326. #token P  "pear"
  327.  
  328. a : "apple" P
  329.   | "pear" A
  330.   ;
  331.  
  332.  
  333.  
  334. Each unique token regular-expression string  in  PCCTS  gets  its  own
  335. token  number.   Token  labels  are  words that begin with a uppercase
  336. letter whereas rules begin with lowercase letters.  Repeating the same
  337. token string in a grammar merely refers to the same token; strings can
  338. only appear once in #token definitions, however, as  this  instruction
  339. attempts  to  define  a new token.  An implicitly-defined token is one
  340. that is referenced but that has  no  formal  #token  instruction.   In
  341. fact, we use the #token only when the expression is long, when a lexi-
  342. cal action must be attached, or when a label is required (so that a  C
  343. action  can refer to it).  For completeness, we mention that each rule
  344. a above indicates that either apple followed by pear is to be  matched
  345. or pear followed by apple is to be matched.
  346.  
  347.      Once again, let's test this vocabulary description  with  a  com-
  348. plete, executable example:
  349.  
  350.  
  351. #header <<#include "charbuf.h">>
  352.  
  353. <<main() { ANTLR(a(), stdin); }>>
  354.  
  355. #token    "\ "     <<zzskip();>>            /* ignore blanks */
  356. #token    "\t"     <<zzskip();>>            /* ignore tabs */
  357. #token    "\n"     <<zzline++; zzskip();>>  /* ignore newlines */
  358.  
  359. a : "apple" "pear"
  360.   | "pear" "apple"
  361.   ;
  362.  
  363.  
  364.  
  365. To build the executable, we proceed as before:
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  
  372.                                                                 Page 6
  373.  
  374. PCCTS Introductory Tutorial 1.xx
  375.  
  376.  
  377.  
  378. % antlr -gk t.g
  379. Antlr parser generator   Version 1.10   1989-1993
  380. % dlg -i parser.dlg scan.c
  381. dlg  Version 1.10   1989-1993
  382. % cc -I../h -o t t.c scan.c err.c
  383. t.c:
  384. scan.c:
  385. err.c:
  386. Linking:
  387.  
  388.  
  389.  
  390. To test the example, type:
  391.  
  392.  
  393. % t
  394. apple
  395.      pear
  396. %
  397.  
  398.  
  399. No error is reported due to the validity of the input.  Note that  the
  400. newline  and  the  spaces were ignored because of the zzskip() actions
  401. associated with our token definitions for white space.  To ensure that
  402. t is actually doing something useful, try:
  403.  
  404.  
  405. % t
  406. apple apple
  407. line 1: syntax error at "apple" missing pear
  408. ^D%
  409.  
  410.  
  411.  
  412. PCCTS generates parsers that automatically report errors  and  try  to
  413. resynchronize  the  parser;  hence,  in this case, a control-D (^D) is
  414. necessary to terminate the program because t is  looking  for  another
  415. token with which to resynchronize.
  416.  
  417.      The regular expressions used in the above examples are simple and
  418. do not use any of the meta-characters or regular expression operators.
  419. Before presenting a more realistic example, we illustrate the  use  of
  420. some   useful  regular  expression  meta-characters  (for  a  complete
  421. description see PCCTS documentation):
  422.  
  423. @    EOF character
  424.  
  425. \t   tab character
  426.  
  427. \n   newline character
  428.  
  429. \c   character escape; used  to  obtain  actual  character  for  meta-
  430.      characters
  431.  
  432.  
  433.  
  434.                                                                 Page 7
  435.  
  436. PCCTS Introductory Tutorial 1.xx
  437.  
  438.  
  439. (e)  keep expression e as an indivisible group
  440.  
  441. [c]  match one character from list c
  442.  
  443. [x-y]match one character from range x to y
  444.  
  445.  
  446. {e}  expression e is optional
  447.  
  448. e*   match zero or more of e
  449.  
  450. e+   match one or more of e
  451.  
  452. e|f  match either expression e or f
  453.  
  454. Naturally, the above operators and meta-characters can be used in many
  455. combinations  to  produce very complicated expressions.  To illustrate
  456. more complex expressions, we define the  vocabulary  of  a  calculator
  457. (ignoring white space for the moment).
  458.  
  459.  
  460. #token NUM "[0-9]+"
  461. #token VAR "[a-zA-Z][a-zA-Z0-9]*"
  462. #token     "\("
  463. #token     "\)"
  464. #token     "\+"
  465. #token     "\-"
  466. #token     "\*"
  467. #token     "/"
  468.  
  469.  
  470.  
  471. A number is defined as a sequence  of  one  or  more  decimal  digits.
  472. Variables  begin  with an upper or lowercase letter, but can otherwise
  473. contain digits as well; note that * is used rather than  +  for  vari-
  474. ables  because + would force VAR to recognize at least two characters.
  475. This calculator has some tokens in its vocabulary that  are  identical
  476. to  those of the regular expressions, so these must be escaped to tell
  477. the scanner to look for those actual characters.  To create an execut-
  478. able, we form a grammar which accepts any sequence of the words in the
  479. vocabulary:
  480.  
  481.  
  482. #header <<#include "charbuf.h">>
  483.  
  484. <<main() { ANTLR(a(), stdin); }>>
  485.  
  486. #token     "\ "     <<zzskip();>>            /* ignore blanks */
  487. #token     "\t"     <<zzskip();>>            /* ignore tabs */
  488. #token     "\n"     <<zzline++; zzskip();>>  /* ignore newlines */
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.                                                                 Page 8
  496.  
  497. PCCTS Introductory Tutorial 1.xx
  498.  
  499.  
  500.  
  501. #token NUM "[0-9]+"
  502. #token VAR "[a-zA-Z][a-zA-Z0-9]*"
  503. #token     "\("
  504. #token     "\)"
  505. #token     "\+"
  506. #token     "\-"
  507. #token     "\*"
  508. #token     "/"
  509.  
  510. a : ( NUM | VAR | "\(" | "\)" | "\+" | "\-" | "\*" | "/" )+ ;
  511.  
  512.  
  513.  
  514. As before, we create the executable with (assuming the example  is  in
  515. t.g):
  516.  
  517.  
  518. antlr -gk t.g
  519. dlg -i parser.dlg scan.c
  520. cc -g -I../h -o t t.c scan.c err.c
  521.  
  522.  
  523.  
  524. The executable, t, will recognize any sentence compsed of tokens  from
  525. our  vocabulary.   The next section discusses how one employs rules to
  526. specify valid, structured sequences; i.e. how one defines  the  syntax
  527. of a language.
  528.  
  529. 3.  Syntactic Analysis
  530.  
  531.      The syntax of a language is the grammatical structure which  sum-
  532. marizes the set of valid phrases in that language.  Because one cannot
  533. normally delineate all possible sentences, languages are described via
  534. a  set  of  rules  which  obey  the  laws of a meta-language, which is
  535. literally a "language to describe languages" just  as  the  syntax  of
  536. regular expressions represents a language.  This section describes the
  537. format of a PCCTS language description-the syntax of PCCTS  rules  and
  538. how  they  may  be  used  to impose a structure upon a stream of input
  539. tokens.
  540.  
  541.      The basic template used to build a grammar is:
  542.  
  543.         #header action
  544.         action(s) and/or #token definition(s)
  545.         rule(s)
  546.         action(s) and/or #token definition(s)
  547.  
  548. To compile, all grammars must define a number  of  things  inside  the
  549. #header action; this instruction is not optional and must appear first
  550. in your file.  The rest of the file is basically a  sequence  of  user
  551. actions, token and rule definitions-except that actions, not contained
  552. within rules, must be placed before or after the rule definitions.
  553.  
  554.  
  555.  
  556.  
  557.                                                                 Page 9
  558.  
  559. PCCTS Introductory Tutorial 1.xx
  560.  
  561.  
  562.      Rules have the basic form:
  563.  
  564.  
  565. rule: alternative  | alternative  | ... | alternative  ;
  566.                  1              2                    n
  567.  
  568.  
  569. where alternative  is a sequence of the following elements:
  570.                  i
  571. token
  572.      Match token on the input stream.
  573.  
  574. rule  Visit rule and match whatever is specified.
  575.  
  576. action
  577.      Execute C action.
  578.  
  579. (a  | a  | ... | a )
  580.   1  Introduce a subrule-match one a .
  581.                                     i
  582. {a  | a  | ... | a }
  583.   1  Introduce an optional subrule; match one a  or none.
  584.                                                i
  585. (a  | a  | ... | a )*
  586.   1  Conditionallynmatch any sequence of a 's.
  587.                                           i
  588. (a  | a  | ... | a )+
  589.   1  Match any sequence of a 's.
  590.                             i
  591. Examples of rule definitions are:
  592.  
  593.  
  594. w   :   WORD ("," WORD)*
  595.     ;
  596.  
  597.  
  598.  
  599. where rule w matches a  list  of  comma-separated  WORD's.   The  (","
  600. WORD)*  construction says match zero or more "," WORD sequences.  Con-
  601. sider,
  602.  
  603.  
  604. st  :   "if" expr "then" st {"else" st} ";"
  605.     |   WORD ":=" expr
  606.     |   "begin" ( st ";" )+ "end"
  607.         ;
  608.  
  609.  
  610.  
  611. where expr is some rule that matches an arithmetic  expression.   Rule
  612. st matches statements such as:
  613.  
  614.  
  615.  
  616.  
  617.  
  618.  
  619.                                                                Page 10
  620.  
  621. PCCTS Introductory Tutorial 1.xx
  622.  
  623.  
  624.  
  625. if expr  then begin
  626.   i := expr ;
  627.   j := expr2;
  628. end        3
  629. else
  630.   k := expr ;
  631.            4
  632.  
  633.  
  634. The first alternative has an optional subrule that  matches  an  else-
  635. clause  if  it  exists.   The  third  alternative  matches one or more
  636. semicolon-delimited statements, which are enclosed in begin  and  end.
  637. Let's examine the description of a simple expression.
  638.  
  639.  
  640. e   :   e1 ( ("\+" | "\-") e1 )*
  641.     ;
  642.  
  643. e1  :   WORD
  644.     |   INT
  645.     ;
  646.  
  647.  
  648.  
  649. Rule e matches simple expressions with only plus and minus  as  opera-
  650. tors;  e.g.  a+3-b  or  a.  Note that we have nested the ("\+" | "\-")
  651. subrule within the (...)* subrule.
  652.  
  653.      Let's build a complete PCCTS language  description  by  extending
  654. the  expression  example.  Rules to handle multiplication and division
  655. will be added as well as  token  definitions  to  ignore  white  space
  656. etc...:
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.                                                                Page 11
  682.  
  683. PCCTS Introductory Tutorial 1.xx
  684.  
  685.  
  686.  
  687. #header <<#include "charbuf.h">>
  688.  
  689. <<main() { ANTLR(calc(), stdin); }>>
  690.  
  691. #token     "[\ \t]"  <<zzskip();>>           /* ignore blanks, tabs */
  692. #token     "\n"      <<zzline++;>>           /* ignore newlines */
  693. #token INT "[0-9]+"
  694. #token FLOAT "[0-9]+ {. [0-9]+}"
  695.  
  696. calc:   ( e "\n" )* "@"
  697.     ;
  698.  
  699. e   :   e1 ( ("\+" | "\-") e1 )*
  700.     ;
  701.  
  702. e1  :   e2 ( ("\*" | "/") e2 )*
  703.     ;
  704.  
  705. e2  :   INT
  706.         |       FLOAT
  707.     ;
  708.  
  709.  
  710.  
  711. Note that newlines are no longer to be ignored,  hence,  the  zzskip()
  712. function  call has been removed from its lexical action.  Our language
  713. is a set of expressions terminated by newlines followed by end-of-file
  714. (@  is  a  predefined  lexical  meta-symbol referring to end-of-file).
  715. Without actions, testing this grammar is uninteresting because no out-
  716. put  is generated (unless, of course, an invalid expression is given).
  717. Therefore, let us place an action among the rule elements to  generate
  718. some output.  Augment rule calc as follows:
  719.  
  720.  
  721. calc:   ( e "\n" <<printf("found expression\n");>> )* "@"
  722.     ;
  723.  
  724.  
  725.  
  726. Essentially, we have added C code to print out a brief  message  after
  727. an  expression-newline  pair has been encountered.  Create the execut-
  728. able, t, as before with:
  729.  
  730.  
  731. antlr -gk t.g
  732. dlg -i parser.dlg scan.c
  733. cc -I../h -o t t.c scan.c err.c
  734.  
  735.  
  736.  
  737.  
  738. Test the program via a few simple expressions:
  739.  
  740.  
  741.  
  742.  
  743.                                                                Page 12
  744.  
  745. PCCTS Introductory Tutorial 1.xx
  746.  
  747.  
  748.  
  749. % t
  750. 3+4*5
  751. found expression
  752. 3.15 / 6 - 2.1
  753. found expression
  754. ^D%
  755.  
  756.  
  757.  
  758. This example grammar is not recursive; i.e. no rule references another
  759. rule that directly or indirectly returns to itself.  But, recursion is
  760. a very powerful tool.  It allows the concept of  self-similarity.   In
  761. other words, structures in which some subcomponents are similar to the
  762. outer structure.  Pascal has several self-similar  constructs:  record
  763. field definitions, procedure definitions, expressions, and type defin-
  764. itions to name a few.
  765.  
  766.      To illustrate recursive grammars, we extend the above  expression
  767. example to allow parenthesized subexpressions such as (3+4)*7.  Change
  768. rule e2 to:
  769.  
  770.  
  771. e2  :   INT
  772.         |       FLOAT
  773.     |   "\(" e "\)"
  774.     ;
  775.  
  776.  
  777.  
  778. Placing the subexpression construct  at  the  lowest  recursion  level
  779. makes  it  have  the  highest precedence because of the nature of top-
  780. down, depth-first parsing.  To see this, consider the parse  tree  for
  781. (3+4)*5 (beginning at rule e):
  782.  
  783. [Figure omitted]
  784.  
  785. Clearly, 3+4 must be evaluated before the * for a valid  result;  this
  786. is  precisely  a depth-first evaluation of the parse tree (which PCCTS
  787. parsers do naturally).  The deeper the recursive nesting,  the  higher
  788. the precedence.  Extending the input expression to (3+4)*(5-6) yields:
  789.  
  790. [Figure omitted]
  791.  
  792. Again, both operands of the * must be evaluated before it can proceed.
  793.  
  794.      As another example of recursive definitions, consider type defin-
  795. itions for a Pascal-like language.  Types look like:
  796.  
  797.  
  798. char
  799. integer
  800. array [5] of char
  801. array [100] of array [20] of integer
  802.  
  803.  
  804.  
  805.                                                                Page 13
  806.  
  807. PCCTS Introductory Tutorial 1.xx
  808.  
  809.  
  810. A grammar similar to the following could be used:
  811.  
  812.  
  813. type:   "char"
  814.     |   "integer"
  815.     |   "array" "\[" INT "\]" "of" type
  816.     ;
  817.  
  818.  
  819. The recursive invocation of type by the array alternative  effectively
  820. allows chains of array specifications.  The parse tree for
  821.  
  822.  
  823. array [100] of array [20] of integer
  824.  
  825.  
  826.  
  827. looks like:
  828.  
  829. [Figure omitted]
  830.  
  831. In this case, we are less interested in precedence and more interested
  832. in allowing chains of array specifications.
  833.  
  834.      In general, recursion and repetition constructs  such  as  (...)+
  835. are  needed  to  avoid delineating all possible phrases in a language.
  836. Grammars are descriptions of the patterns found among the phrases of a
  837. particular language just as R notation summarizes an infinite series.
  838.  
  839.      The recognition of input languages, via the use of grammars, per-
  840. forms two tasks: it ensures phrase validity and directs translation to
  841. an output language.  The next section demonstrates how actions, embed-
  842. ded among the grammar elements, can be used to effect a translation.
  843.  
  844. 4.  Translation
  845.  
  846.      Given a grammar, PCCTS constructs a  recognizer  for  phrases  in
  847. that  input  language.   No  translation  from input to output is per-
  848. formed.  User actions must be supplied in  the  correct  positions  to
  849. generate  output.   Translation  occurs when an action produces output
  850. which is a function of the input phrase.  Actions have access to input
  851. phrase token values through an abstraction called an attribute.  These
  852. attributes are user-defined types and can be as  simple  as  the  text
  853. associated with a token.
  854.  
  855.      This section introduces the notion of an attribute as a means  of
  856. communicating with the lexical analyzer and presents a number of exam-
  857. ples that explain how and where actions can be used to  generate  out-
  858. put.
  859.  
  860. 4.1.  Attributes
  861.  
  862.      Attributes are objects associated with all rules  and  rule  ele-
  863. ments,  but  we  will  only  concern  ourselves  here  with attributes
  864.  
  865.  
  866.  
  867.                                                                Page 14
  868.  
  869. PCCTS Introductory Tutorial 1.xx
  870.  
  871.  
  872. associated with token and rule references.  Attributes are  referenced
  873. in  actions  with the notation $i where i indicates that the attribute
  874. for the ith token in that production is desired.  Attributes are  run-
  875. time  objects  and  have  no value until run-time.  They are generally
  876. used to access the actual text (or a function  of  the  text)  of  the
  877. tokens matched on the input stream.  The set of all tokens defines the
  878. vocabulary of the  input  language.   The  term  "token"  collectively
  879. refers to the token type (an integer that identifies it as part of the
  880. vocabulary) and the token text (the actual  string  that  matched  the
  881. regular expression for the token type).
  882.  
  883.      Before illustrating attributes, we begin with  an  example.   The
  884. vocabulary  of  an  input  language  (known a priori) may be the set {
  885. WORD, "begin", INT },  which  is  the  set  of  token  types  (set  of
  886. integers).   The  text  associated  with a token type is only known at
  887. parser run-time because it depends on the input  characters.   Let  us
  888. say  that the grammatical structure of the language is any sequence of
  889. tokens in the vocabulary (ignoring white space); then,  a  valid  sen-
  890. tence could be:
  891.  
  892.  
  893. begin hello 34 13 bob
  894.  
  895.  
  896.  
  897. The parser would see a token stream of tuples of the form (token type,
  898. token text):
  899.  
  900.  
  901. (begin, begin)
  902. (WORD, hello)
  903. (INT, 34)
  904. (INT, 13)
  905. (WORD, bob)
  906.  
  907.  
  908.  
  909. A different input sentence, with the same sequence of token types, is:
  910.  
  911.  
  912. begin hi 2 99 ptr
  913.  
  914.  
  915.  
  916. which would yield the same sequence of token types,  but  a  different
  917. set of token text:
  918.  
  919.  
  920. (begin, begin)
  921. (WORD, hi)
  922. (INT, 2)
  923. (INT, 99)
  924. (WORD, ptr)
  925.  
  926.  
  927.  
  928.  
  929.                                                                Page 15
  930.  
  931. PCCTS Introductory Tutorial 1.xx
  932.  
  933.  
  934. The grammar might look like:
  935.  
  936.  
  937. a : ( WORD | "begin" | INT )+
  938.   ;
  939.  
  940.  
  941.  
  942. Only the token types are referenced in the grammar  as  they  describe
  943. the structure of the language and are a shorthand notation for the set
  944. of valid input sentences.  Obviously, one could not delineate all pos-
  945. sible sentences as there are infinitely many.  For a PCCTS description
  946. to perform a translation that is specific  to  the  particular  input,
  947. actions  must  access the text of the input tokens, not just the token
  948. type.  Attributes are provided to access the text  (or  some  function
  949. thereof)  of  an  input token.  To illustrate this, we give a complete
  950. example and then, later, describe the particulars:
  951.  
  952.  
  953. #header <<#include "charbuf.h">>
  954.  
  955. <<main() { ANTLR(a(), stdin); }>>
  956.  
  957. #token "[\ \t]"        <<zzskip();>>
  958. #token "\n"            <<zzline++; zzskip();>>
  959.  
  960. a : ( WORD    <<printf(" %s", $1.text);>>
  961.     | "begin" <<printf(" begin");>>
  962.     | INT     <<printf(" %s", $1.text);>>
  963.     )+
  964.   ;
  965.  
  966. #token WORD "[a-z]+"
  967. #token INT  "[0-9]+"
  968.  
  969.  
  970.  
  971. This example defines attributes to be strings  representing  what  was
  972. found  on  the  input stream and prints the stream of tokens back out.
  973. In other words, attributes are merely a copy of the words  found;  the
  974. mapping  from  token/lexeme  to  attribute  is an identity mapping (do
  975. nothing but copy).  For the moment, concentrate on  the  actions.   $1
  976. refers  to  the attribute of the first item in the production in which
  977. the action occurs; in this case, only one item appears per production.
  978. $1.text refers to the text of that token (the file "charbuf.h" defines
  979. an attribute to be a structure with one field - an  array  of  charac-
  980. ters).   Note  that  the action for the "begin" token does not need to
  981. refer to its attribute as it will always be begin.  The rest  of  this
  982. section describes the particulars needed to understand everything else
  983. in the example.
  984.  
  985.      PCCTS requires that the user define the data type or structure of
  986. the attributes as well as specify how to convert from tokens to attri-
  987. butes.  The type is always defined by a C  typedef  named  Attrib  and
  988.  
  989.  
  990.  
  991.                                                                Page 16
  992.  
  993. PCCTS Introductory Tutorial 1.xx
  994.  
  995.  
  996. must be defined in the action associated with the #header instruction.
  997. For example, if one wishes the attribute for  a  token  to  be  simple
  998. integers, the following is a sufficient type definition:
  999.  
  1000.  
  1001. #header <<typedef int Attrib;>>
  1002.  
  1003.  
  1004.  
  1005. However, this does not tell PCCTS how to convert a token to an  attri-
  1006. bute.   This  is accomplished with a function called zzcr_attr() which
  1007. defines the value of an attribute given complete information  about  a
  1008. lexeme (token number and associated text).  It has the general form:
  1009.  
  1010.  
  1011. void
  1012. zzcr_attr(a,token,text)
  1013. Attrib *a;
  1014. int token;
  1015. char *text;
  1016. {
  1017.     /* *a = function(token, text); */
  1018. }
  1019.  
  1020.  
  1021. where a points to an attribute created by PCCTS at run-time.  The user
  1022. simply  has to assign a value to *a.  In our case, we will use a macro
  1023. version to set our attributes to the integer value of the input:
  1024.  
  1025.  
  1026. #define zzcr_attr(a,tok,txt) {*(a) = atoi(txt);}
  1027.  
  1028.  
  1029.  
  1030. This specifies that whenever a token is matched on the input stream by
  1031. the parser, an attribute of type int is to be created and assigned the
  1032. result of atoi(text) where text is the character  string  matched  for
  1033. the  token.   The attribute is then made available as $i to actions in
  1034. the production that matched the token.  For example,
  1035.  
  1036.  
  1037. #header <<
  1038.     typedef int Attrib;
  1039.     #define zzcr_attr(a,tok,txt) {*(a) = atoi(txt);}
  1040. >>
  1041.  
  1042. <<main() { ANTLR(a(), stdin); }>>
  1043.  
  1044. #token "[\ \t]"        <<zzskip();>>
  1045. #token "\n"            <<zzline++; zzskip();>>
  1046.  
  1047. a   :   "hi" "[0-9]+" <<printf("$1, $2 are %d, %d\n", $1, $2);>>
  1048.     ;
  1049.  
  1050.  
  1051.  
  1052.  
  1053.                                                                Page 17
  1054.  
  1055. PCCTS Introductory Tutorial 1.xx
  1056.  
  1057.  
  1058. $1 refers to the first token in the alternative, "hi";  similarly,  $2
  1059. refers  to the the second token, "[0-9]+".  When executed, the execut-
  1060. able t (created as before) yields:
  1061.  
  1062.  
  1063. % t
  1064. hi 34
  1065. $1, $2 are 0, 34
  1066. %
  1067.  
  1068.  
  1069.  
  1070. where atoi() of a non-numeric string is 0, but the text 34  gets  con-
  1071. verted  to an integer (binary word) version of 34 and printed back out
  1072. as a number.
  1073.  
  1074.      The token type can be tested to ensure  that  it  is  an  integer
  1075. before applying the atoi() function via:
  1076.  
  1077.  
  1078. #header <<
  1079.     typedef int Attrib;
  1080.     #define zzcr_attr(a,tok,txt) {if ( tok==INT ) *(a) = atoi(txt);}
  1081. >>
  1082.  
  1083.  
  1084.  
  1085. where INT is defined to be "[0-9]+".  This defines  an  attribute  for
  1086. all INT tokens found on the input stream.  Other tokens have undefined
  1087. attributes.
  1088.  
  1089.      Attributes can have multiple  elements  or  assume  one  of  many
  1090. values.   For example, we can extend the above example to handle FLOAT
  1091. tokens as well:
  1092.  
  1093.  
  1094. #header <<typedef union { int ival; float fval; } Attrib;>>
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.                                                                Page 18
  1116.  
  1117. PCCTS Introductory Tutorial 1.xx
  1118.  
  1119.  
  1120.  
  1121. <<
  1122. void
  1123. zzcr_attr(a,token,text)
  1124. Attrib *a;
  1125. int token;
  1126. char *text;
  1127. {
  1128.     switch ( token )
  1129.     {
  1130.         case INT   : (a)->ival = atoi(text); break;
  1131.         case FLOAT : (a)->fval = atof(text); break;
  1132.     }
  1133. }
  1134. >>
  1135.  
  1136.  
  1137.  
  1138. The typedef specifies that attributes are integer  or  floating  point
  1139. values.   When  the  regular  expression  for  a floating point number
  1140. (integer number) is matched on the input stream, zzcr_attr()  converts
  1141. the string of characters representing that number to a C float (int).
  1142.  
  1143.      Attributes can  become  even  more  complicated,  but  typically,
  1144. attributes are merely a copy of the text found on the input stream.  A
  1145. standard PCCTS attribute definition is available as charbuf.h  and  is
  1146. defined as follows:
  1147.  
  1148.  
  1149. /* PCCTS attribute -- constant width text */
  1150. #ifndef D_TextSize
  1151. #define D_TextSize      30
  1152. #endif
  1153.  
  1154. typedef struct { char text[D_TextSize]; } Attrib;
  1155.  
  1156. #define zzcr_attr(a,tok,t)      strncpy((a)->text, t, D_TextSize-1);
  1157.  
  1158.  
  1159.  
  1160. These attributes are referred to by $i.text in actions.
  1161.  
  1162.      Each alternative begins a  new  sequence  of  $i's  and  from  an
  1163. enclosing  scope/level,  entire subules are counted as one unit.  This
  1164. is best explained with an example:
  1165.  
  1166.  
  1167. a   :   A B ( C D )+ E
  1168.     |   F G
  1169.     ;
  1170.  
  1171.  
  1172.  
  1173. >From an action after token E, A is $1, B is $2, the entire subrule ( C
  1174.  
  1175.  
  1176.  
  1177.                                                                Page 19
  1178.  
  1179. PCCTS Introductory Tutorial 1.xx
  1180.  
  1181.  
  1182. D  )  is  $3,  and  E is $4; C and D are inaccessible from outside the
  1183. scope of the subrule.  From an action inside the  subrule  just  after
  1184. the  token  D, C is $1 and D is $2.  In alternative two from an action
  1185. after G, F is $1 and G is $2.  Attributes have  a  scoping  just  like
  1186. variables in a programming langauage.
  1187.  
  1188.      Attributes  are  a  means  of  communicating  with  the   lexical
  1189. analyzer.   Actions may use these attributes to provide a translation.
  1190. The next section utilizes the concepts presented here to build  trans-
  1191. lators.
  1192.  
  1193. 4.2.  Actions
  1194.  
  1195.      Actions are rule elements just like token references, but perform
  1196. a  different  function.   Token  references indicate that a particular
  1197. token is to be matched on the input stream at that point in the parse.
  1198. Actions  indicate that this action is to be performed at that point in
  1199. the parse, immediately following the preceding token match.  For exam-
  1200. ple,
  1201.  
  1202.  
  1203. a   :   A <<action >> B ;
  1204.     |  ( C )+ <<action >>
  1205.     ;                 2
  1206.  
  1207.  
  1208.  
  1209. action  is executed after the parser has found an A, but before it has
  1210. found 1a  B.  action  is executed only after a sequence of one or more
  1211. C's has been found. 2
  1212.  
  1213.      As a more concrete example, we augment the above calc example  to
  1214. print something more useful than found expression:
  1215.  
  1216.  
  1217. calc:   ( e "\n" <<printf("\n");>> )* "@"
  1218.     ;
  1219.  
  1220. e   :   e1
  1221.         (   (  "\+" <<printf(" add");>>
  1222.             |  "\-" <<printf(" sub");>>
  1223.             )
  1224.             e1
  1225.         )*
  1226.     ;
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.                                                                Page 20
  1240.  
  1241. PCCTS Introductory Tutorial 1.xx
  1242.  
  1243.  
  1244.  
  1245. e1  :   e2
  1246.         (   (  "\*" <<printf(" mult");>>
  1247.             |  "/"   <<printf(" div");>>
  1248.             )
  1249.             e2
  1250.         )*
  1251.     ;
  1252.  
  1253. e2  :   INT     <<printf(" INT");>>
  1254.         |       FLOAT   <<printf(" FLOAT");>>
  1255.     ;
  1256.  
  1257.  
  1258.  
  1259. Essentially, we have added C code to print out the operand  types  and
  1260. operators.  Create the executable, t, as before with
  1261.  
  1262.  
  1263. antlr -gk t.g
  1264. dlg -i parser.dlg scan.c
  1265. cc -I../h -o t t.c scan.c err.c
  1266.  
  1267.  
  1268.  
  1269. Test the program via a few simple expressions:
  1270.  
  1271.  
  1272. % t
  1273. 3+4*5
  1274.  INT add INT mult INT
  1275. 3.15 / 6 - 2.1
  1276.  FLOAT div INT sub FLOAT
  1277. ^D%
  1278.  
  1279.  
  1280.  
  1281. 4.3.  Stack Machine
  1282.  
  1283. Now, let's use the attributes to generate code for a  simple  reverse-
  1284. polish stack machine whose operations are defined as follows:
  1285.  
  1286. push opnd
  1287.      Push opnd onto the stack.
  1288.  
  1289. printPrint the value of the top of stack; POP the value off the stack.
  1290.  
  1291. add   PUSH(POP + POP)
  1292.  
  1293. sub   a := POP
  1294.      b := POP
  1295.      PUSH(b - a)
  1296.  
  1297. mult
  1298.  
  1299.  
  1300.  
  1301.                                                                Page 21
  1302.  
  1303. PCCTS Introductory Tutorial 1.xx
  1304.  
  1305.  
  1306.      PUSH(POP * POP)
  1307.  
  1308. div   a := POP
  1309.      b := POP
  1310.      PUSH(b / a)
  1311.  
  1312. Modify the rules as follows:
  1313.  
  1314.  
  1315. #header <<#include "charbuf.h">>
  1316.  
  1317. <<main() { ANTLR(calc(), stdin); }>>
  1318.  
  1319. #token     "[\ \t]"  <<zzskip();>>           /* ignore blanks, tabs */
  1320. #token     "\n"      <<zzline++;>>           /* ignore newlines */
  1321. #token INT "[0-9]+"
  1322. #token FLOAT "[0-9]+ {. [0-9]+}"
  1323.  
  1324.  
  1325.  
  1326.  
  1327. calc:   ( e "\n" <<printf("\tprint\n");>> )* "@"
  1328.     ;
  1329.  
  1330. e   :   <<char *op;>>
  1331.         e1
  1332.         (   (  "\+" <<op="\tadd\n";>>
  1333.             |  "\-" <<op="\tsub\n";>>
  1334.             )
  1335.             e1
  1336.                         <<printf("%s", op);>>
  1337.         )*
  1338.     ;
  1339.  
  1340.  
  1341.  
  1342.  
  1343. e1  :   <<char *op;>>
  1344.         e2
  1345.         (   (  "\*"  <<op="\tmult\n";>>
  1346.             |  "/"   <<op="\tdiv\n";>>
  1347.             )
  1348.             e2
  1349.                         <<printf("%s", op);>>
  1350.         )*
  1351.     ;
  1352.  
  1353. e2  :   INT     <<printf("\tpush %s\n", $1.text);>>
  1354.         |       FLOAT   <<printf("\tpush %s\n", $1.text);>>
  1355.     ;
  1356.  
  1357.  
  1358.  
  1359. Running the program yields:
  1360.  
  1361.  
  1362.  
  1363.                                                                Page 22
  1364.  
  1365. PCCTS Introductory Tutorial 1.xx
  1366.  
  1367.  
  1368.  
  1369. % t
  1370. 3+4*5
  1371.         push 3
  1372.         push 4
  1373.         push 5
  1374.         mult
  1375.         add
  1376.         print
  1377. ^D
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.  
  1391.  
  1392.  
  1393.  
  1394.  
  1395.  
  1396.  
  1397.  
  1398.  
  1399.  
  1400.  
  1401.  
  1402.  
  1403.  
  1404.  
  1405.  
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411.  
  1412.  
  1413.  
  1414.  
  1415.  
  1416.  
  1417.  
  1418.  
  1419.  
  1420.  
  1421.  
  1422.  
  1423.  
  1424.  
  1425.                                                                Page 23
  1426.  
  1427. PCCTS Introductory Tutorial 1.xx
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.                           Table of Contents
  1434.  
  1435.  
  1436.  
  1437.  
  1438. 1. Introduction .................................................    2
  1439.  
  1440. 2. Lexical Analysis .............................................    2
  1441.  
  1442. 3. Syntactic Analysis ...........................................    9
  1443.  
  1444. 4. Translation ..................................................   14
  1445.  
  1446.          4.1. Attributes ........................................   14
  1447.  
  1448.          4.2. Actions ...........................................   20
  1449.  
  1450.          4.3. Stack Machine .....................................   21
  1451.  
  1452.  
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458.  
  1459.  
  1460.  
  1461.  
  1462.  
  1463.  
  1464.  
  1465.  
  1466.  
  1467.  
  1468.  
  1469.  
  1470.  
  1471.  
  1472.  
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479.  
  1480.  
  1481.  
  1482.  
  1483.  
  1484.  
  1485.  
  1486.  
  1487.  
  1488.  
  1489.