home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / ipl / packs / ibpag2 / sample.ibp < prev    next >
Text File  |  2000-07-29  |  2KB  |  112 lines

  1. #
  2. # Sample Ibpag2 grammar file.
  3. #
  4.  
  5. #
  6. # The code between %{ and %} gets copied directly.  Note the Iconish
  7. # comment syntax.
  8. #
  9. %{
  10.  
  11. # Note:  If IIDEBUG is defined in the output file, debugging messages
  12. # about the stacks and actions get displayed.
  13. #
  14. $define IIDEBUG 1
  15.  
  16. %}
  17.  
  18. #
  19. # Here we declare the tokens returned by the lexical analyzer.
  20. # Precedences increase as we go on.  Note how (unlike YACC), tokens
  21. # are separated by commas.  Note also how UMINUS is used only for its
  22. # %prec later.
  23. #
  24. %token NUMBER
  25. %left '+', '-'
  26. %left '*', '/'
  27. %right UMINUS
  28.  
  29. %%
  30.  
  31. #
  32. # After this point, and up to the next %%, we have the grammar itself.
  33. # By default, the start symbol is the left-hand side of the first
  34. # rule. 
  35. #
  36.  
  37. lines    :    lines, expr, '\n'    { write($2) }
  38.     |    lines, '\n'
  39.     |    epsilon     # Note use of epsilon/error tokens.
  40.     |    error, '\n'        {
  41.                       write("syntax error; try again:")
  42.                       # like YACC's yyerrok macro
  43.                       iierrok
  44.                     }
  45.     ;
  46.  
  47. expr    :    expr, '+', expr    { return $1 + $3 }
  48.     |    expr, '-', expr    { return $1 - $3 }
  49.     |    expr, '*', expr    { return $1 * $3 }
  50.     |    expr, '/', expr    { return $1 / $3 }
  51.     |    '(', expr, ')'    { return $2 }
  52.     |    '-', expr %prec UMINUS    { return -$2 }
  53.     |    NUMBER        { return $1 }
  54.     ;
  55.  
  56. %%
  57.  
  58. #
  59. # From here on, code gets copied directly to the output file.  We are
  60. # no longer in the grammar proper.
  61. #
  62.  
  63. #
  64. # The lexical analyzer must be called iilex, with the module name
  65. # appended (if there is one).  It must take one argument, infile (an
  66. # input stream).  It must be a generator, and fail on EOF (not return
  67. # something <= 0, as is the case for YACC + Lex).  Iilval holds the
  68. # literal string value of the token just suspended by iilex().
  69. #
  70. procedure iilex(infile)
  71.  
  72.     local nextchar, c, num
  73.     initial {
  74.     # Here's where you'd initialize any %{ globals %} declared
  75.     # above.
  76.     }
  77.  
  78.     nextchar := create !(!infile || "\n" || "\n")
  79.  
  80.     c := @nextchar | fail
  81.     repeat {
  82.     if any(&digits, c) then {
  83.         if not (\num ||:= c) then
  84.         num := c
  85.     } else {
  86.         if iilval := \num then {
  87.         suspend NUMBER
  88.         num := &null
  89.         }
  90.         if any('+-*/()\n', c) then {
  91.         iilval := c
  92.         suspend ord(c)
  93.         } else {
  94.         if not any(' \t', c) then {
  95.             # deliberate error - will be handled later
  96.             suspend &null
  97.         }
  98.         }
  99.     }
  100.     c := @nextchar | break
  101.     }
  102.     if iilval := \num then {
  103.     return NUMBER
  104.     num := &null
  105.     }
  106.  
  107. end
  108.  
  109. procedure main()
  110.     return iiparse(&input, 1)
  111. end
  112.