home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / ibpag2 / part04 / sample.ibp < prev    next >
Encoding:
Text File  |  1994-09-25  |  2.4 KB  |  113 lines

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