/****************************************************************************
 * File: hq9+.l
 * Author: Keith Schwarz (htiek@cs.stanford.edu)
 * 
 * An interpreter for the esorteric programming language HQ9+.  Each HQ9+
 * program is a string of H's, Q's, 9's, and +'s that is executed from left-
 * to-right.  The operators have the following meaning:
 *
 *   H: Print "Hello, World!"
 *   Q: Print the program's source code (the Quine operator)
 *   9: Print the lyrics to "99 Bottles of Beer on the Wall"
 *   +: Increment the accumulator, which cannot otherwise be accessed.
 */
%{
  #include <string.h>

  /* The accumulator. */
  int accumulator = 0;

  /* The program's source code. */
  char* source;
%}

/* A state that represents that the interpreter should run. */
%x RUN

%%
 /* First, match the entire program so that we can store its source code in
  * the 'source' variable for later use.
  */
.*      { 
          source = strdup(yytext); /* Store the program text. */
          yyless(0);               /* Hand back this token so it can be 
                                    * interpreted later.
                                    */
          BEGIN(RUN);              /* Enter the "run" state to begin
                                    * interpreting.
                                    */
        }
<RUN>"H"     printf("Hello, world!\n"); /* Interpret "H" */
<RUN>"Q"     printf("%s\n", source);    /* Interpret "Q" */
<RUN>"9"     {                          /* Interpret "9" */
  int i;
  for (i = 99; i > 0;) {
    printf("%d bottle%s of beer on the wall,\n", i, i == 1? "" : "s");
    printf("%d bottle%s of beer!\n", i, i == 1? "" : "s");
    printf("Take one down, pass it around\n");
    --i;
    printf("%d bottle%s of beer on the wall!\n\n", i, i == 1? "" : "s");
  }
 } 
<RUN>"+"     ++accumulator;             /* Interpret "+" */
<RUN>\n      exit(0);                   /* Exit on a newline. */
<RUN>.       { fprintf(stderr, "Unknown character: %c\n", yytext[0]); exit(-1); } /* Other characters are errors. */
