home *** CD-ROM | disk | FTP | other *** search
/ AI Game Programming Wisdom / AIGameProgrammingWisdom.iso / SourceCode / 10 Scripting / 02 Berger / scc / scc-parser.y < prev    next >
Encoding:
Lex Description  |  2001-10-16  |  7.2 KB  |  198 lines

  1. %{
  2. // This file contains all of the rules for GNU Bison.  This grammar defines a
  3. // very simple language that can only understand the very basic match
  4. // instructions.  Nevertheless, this still shows the basics of code generation.
  5.  
  6. #include "SCC.H"
  7. #include "PTNode.H"
  8. #include "CodeGen.H"
  9.  
  10. %}
  11.  
  12.  
  13. // Define the order of precidence for the operators.  The first line has the
  14. // lowest precidence and the last line has the highest.  Operators on the same
  15. // line have the same precidence, and these operators associate to the left.
  16. // For example, the following expressions are equivalent:
  17. //
  18. //    2 + 3 + 5 + 7
  19. //    ( (2 + 3) + 5) + 7
  20. //
  21. // This defines the operator precidence as you would expect.
  22.  
  23. // Note that these first two lines gets rid of the "dangling else" with
  24. // C-style if statements.  Since Bison only has a single token of look ahead,
  25. // it does not know if an if-statement will contain an else or not.  These two
  26. // rules help Bison get rid of this conflict.
  27. %nonassoc LESS_THAN_ELSE
  28. %nonassoc K_ELSE
  29.  
  30. %left '='
  31. %left '+' '-'
  32. %left '*' '/'
  33.  
  34.  
  35.  
  36. // Define the set of tokens that the lexer will give the parser.  The compiler
  37. // only understands numbers, basic identifiers, and a small handful of
  38. // keywords.
  39. %token NUMBER
  40. %token IDENTIFIER
  41.  
  42. %token K_ELSE
  43. %token K_FOR
  44. %token K_IF
  45.  
  46.  
  47. %%
  48.  
  49.  
  50. // This rule is where Bison starts (since this is the first rule), and it
  51. // defines what a valid source file.  For this sample, a source file is simply
  52. // a list of statements.
  53. file : stmtList
  54.          {
  55.            // This block of code will be executed once the statement list is
  56.            // "reduced" or completely matched.  Since this is the first rule
  57.            // that Bison started with, parsing of the source script has been
  58.            // completed.  We dump the parse tree that was built up, and then
  59.            // run the code generator over this parse tree.
  60.  
  61.            // Note that the $1, $2, etc match the "return results" of the of
  62.            // the rule's arguments (e.g., the right side of the colon).  $1 in
  63.            // this rule's case is the result of 'stmtList'.  Rules can set
  64.            // their return values by setting $$.
  65.  
  66.            $1->Dump();
  67.  
  68.            CodeGen cg;
  69.            cg.StartGen( $1 );
  70.          }
  71.      ;
  72.  
  73.  
  74. // This rule defines a list of one or more statements.  Notice how this rule
  75. // refers to itself recusively.  The second part of this rule (just the single
  76. // 'stmt') will always be matched first.  This little bit of code handles
  77. // creating a block parse tree node that will contain the entire list of
  78. // statements.  If there are any additional statements, they will be matched
  79. // by the first part of this rule (notice how its code adds the new statement
  80. // to the end of block node).
  81. stmtList : stmtList stmt           { $$ = $1;  $$->Add( $2 );  }
  82.          | stmt                    { $$ = new BlockNode( $1 ); }
  83.          ;
  84.  
  85.  
  86. // This rule defines what a statement is.  This rule simply passes the "what
  87. // is a statement" definition to sub-rules.
  88. stmt : block_stmt                  { $$ = $1; }
  89.      | expr_stmt                   { $$ = $1; }
  90.      | for_stmt                    { $$ = $1; }
  91.      | if_stmt                     { $$ = $1; }
  92.      ;
  93.  
  94.  
  95. // A block statement is any statement list that is surrounded by braces.  This
  96. // is commonly used in if-statements and for-loops to group a body of
  97. // statements.
  98. block_stmt : '{' stmtList '}'      { $$ = $2; }
  99.            ;
  100.  
  101.  
  102. // An expression statement is a any expression followed by a semicolon.  This
  103. // will be the most common type of statement in a script.  Since an expression
  104. // will leave its value on the stack, the code generator will generate pops to
  105. // cleanup the stack when it encounters statement nodes.
  106. expr_stmt : expr ';'               { $$ = new StatementNode( $1 ); }
  107.           ;
  108.  
  109.  
  110. // This rule defines a C-style for-loop.
  111. for_stmt : K_FOR '(' opt_expr ';' opt_expr ';' opt_expr ';' ')' stmt
  112.              {
  113.                // In order to keep the for-loop's data structure a little more
  114.                // convient, it does not expect any of its arguments to be
  115.                // NULL.  Therefore, we need to create dummy nodes where
  116.                // appropiate.  Note that when the conditional is empty, that
  117.                // means we should really push a constant 1 on the stack (ie,
  118.                // true).
  119.                PTNodePtr pre = $3;
  120.                PTNodePtr expr = $5;
  121.                PTNodePtr post = $7;
  122.                PTNodePtr body = $10;
  123.  
  124.                if ( pre == NULL )
  125.                  pre = new StatementNode( NULL );
  126.  
  127.                if ( expr == NULL )
  128.                  pre = new ConstantNode( 1 );
  129.  
  130.                if ( post == NULL )
  131.                  post = new StatementNode( NULL );
  132.  
  133.                if ( body == NULL )
  134.                  body = new StatementNode( NULL );
  135.  
  136.                $$ = new ForNode( pre, expr, post, body );
  137.              }
  138.  
  139.  
  140. // This rule defines an optional expression.  This is used by the for-loop so
  141. // its various parts can be empty.
  142. opt_expr : expr                    { $$ = $1;   }
  143.          | /* empty */             { $$ = NULL; }
  144.          ;
  145.  
  146.  
  147. // This rule defines a C-style if-statement.  Note that there are two sub
  148. // rules that actually deal with the if-statement's details (whether or not
  149. // the if statement has an else).
  150. if_stmt : if_no_else_stmt          { $$ = $1; }
  151.         | if_with_else_stmt        { $$ = $1; }
  152.         ;
  153.  
  154.  
  155. // This rule defines an C-style if-statement that does not contain an else.
  156. // Since Bison only has a single token of look-ahead, this rule conflicts with
  157. // if_with_else_stmt; therefore, we force Bison to drop the precidence of this
  158. // rule.  This effectively binds the else with the closest if (just like C).
  159. if_no_else_stmt : K_IF '(' expr ')'
  160.                     stmt     %prec LESS_THAN_ELSE
  161.                                    { $$ = new IfNode( $3, $5 ); }
  162.                 ;
  163.  
  164.  
  165. if_with_else_stmt : K_IF '(' expr ')'
  166.                       stmt
  167.                     K_ELSE
  168.                       stmt
  169.                                    { $$ = new IfNode( $3, $5, $7 ); }
  170.                   ;
  171.  
  172.  
  173. // This rule defines what an expression.  An expression can be a single number
  174. // (the last rule), or it can be any list basic math instructions.  Each of
  175. // these rules handles creating the proper parse tree node with the operands.
  176. expr : expr '+' expr               { $$ = new AddNode( $1, $3 );        }
  177.      | expr '-' expr               { $$ = new SubtractNode( $1, $3 );   }
  178.      | expr '*' expr               { $$ = new MultiplyNode( $1, $3 );   }
  179.      | expr '/' expr               { $$ = new DivideNode( $1, $3 );     }
  180.      | '(' expr ')'                { $$ = $2;                           }
  181.      | IDENTIFIER '=' expr         { $$ = new AssignmentNode( $1, $3 ); }
  182.      | NUMBER                      { $$ = $1;                           }
  183.      | IDENTIFIER                  { $$ = $1;                           }
  184.      ;
  185.  
  186.  
  187. %%
  188.  
  189.  
  190. // This function is required to be defined by Bison.  It is called whenever
  191. // any kind of error is raised while parsing the input stream.
  192. int yyerror( char *err )
  193. {
  194.   puts( err );
  195.  
  196.   return 0;
  197. }
  198.