Author: kjs
Date: Sat Mar 24 09:53:14 2007
New Revision: 17713

Modified:
   trunk/compilers/pirc/src/pirparser.c

Log:
compilers/pirc:
* converted comments to perldoc, resulting in grammar overview using perldoc.

Modified: trunk/compilers/pirc/src/pirparser.c
==============================================================================
--- trunk/compilers/pirc/src/pirparser.c        (original)
+++ trunk/compilers/pirc/src/pirparser.c        Sat Mar 24 09:53:14 2007
@@ -1,22 +1,29 @@
+/*
+
+=head1 NAME
+
+pirparser.c - parser for Parrot Intermediate Representation 
+
+=cut
+
+*/
+
 #include "pirlexer.h"
 #include "pirparser.h"
-
 #include "pirout.h" /* for test output */
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
 #include <stdarg.h>
 #include <string.h>
 
+/* 
 
-#define MAX_ERRORS  10  /* quit after 10 errors to prevent too many errors */
+parser_state structure holds the current token, a pointer to the lexer, 
+and keeps track of the number of errors.
+
+*/
 
-/* parser_state structure
- * holds the current token, a pointer to the lexer,
- * and keeps track of the number of errors.
- *
- */
 typedef struct parser_state {
     struct lexer_state *lexer;      /* the lexer */
     token curtoken;                 /* the current token as returned by the 
lexer */
@@ -24,24 +31,30 @@
     int heredoc_index;              /* index to keep track of heredoc ids in 
the array */
     unsigned parse_errors;          /* parse_errors */
 
-
 } parser_state;
 
 
+/* quit after 10 errors to prevent too many errors */
+#define MAX_ERRORS  10  
+
 
 /* call next() to get the next token from the lexer */ /* NOTE: it's calling 
pirout() */
 #define next(P) do { pirout(P); P->curtoken = next_token(P->lexer); } while(0)
 
-/* prototypes */
-static void target(parser_state *p);
-static void type(parser_state *p);
 
+/* 
+
+=head1 HELPER FUNCTIONS
 
+=over 4
 
-/* exit_parser()
- *
- * Clean up and exit the program normally.
- */
+=item void exit_parser()
+
+Clean up and exit the program normally.
+
+=cut
+
+*/
 void
 exit_parser(parser_state *p) {
     destroy_lexer(p->lexer);
@@ -49,12 +62,55 @@
     exit(0);
 }
 
-/* syntax_error()
- *
- * Handle all syntax error through this function.
- * numargs is the number of variable arguments.
- * All arguments should be of type "char *" !!!
- */
+/* 
+
+=item get_parse_errors()
+
+return the number of parse errors.
+
+=cut
+
+*/
+int
+get_parse_errors(parser_state *p) {
+    return p->parse_errors;
+}
+
+/* 
+
+=item new_parser()
+
+constructor for a parser_state object.
+
+=cut
+*/
+parser_state *
+new_parser(char const * filename) {
+    parser_state *p = (parser_state *)malloc(sizeof(parser_state));
+
+    if (p == NULL) {
+        fprintf(stderr, "no parser");
+        exit(1);
+    }
+    p->lexer         = new_lexer(filename);
+    p->curtoken      = next_token(p->lexer);
+    p->parse_errors  = 0;
+    p->heredoc_index = 0;
+    return p;
+}
+
+
+/* 
+
+=item static void syntax_error()
+
+Handle all syntax error through this function.
+numargs is the number of variable arguments.
+All arguments should be of type "char *" !!!
+
+=cut
+
+*/
 static void
 syntax_error(parser_state *p, int numargs, ...) {
     va_list arg_ptr;
@@ -85,13 +141,18 @@
     }
 }
 
-/* match()
- *
- * checks whether the current token is the same
- * as the expected token. If so, all is ok, and the
- * next token is fetched. If not, an appropiate syntax error
- * is reported.
- */
+/* 
+
+=item static void match()
+
+checks whether the current token is the same
+as the expected token. If so, all is ok, and the
+next token is fetched. If not, an appropiate syntax error
+is reported.
+
+=cut
+
+*/
 static void
 match(parser_state *p, token expected) {
     if (p->curtoken == expected) { /* if all is fine, get next token */        
               
@@ -121,27 +182,54 @@
     }
 }
 
+/* 
 
+=item struct lexer_state const *get_lexer()
+
+returns the specified parser's lexer
+
+=cut
+
+*/
 struct lexer_state const *
 get_lexer(parser_state *p) {
     return p->lexer;
 }
 
+/* 
+
+=item token get_token()
+
+returns the specified parser's current token
+
+=cut
+
+*/
 token get_token(parser_state *p) {
     return p->curtoken;   
 }
 
 
 
-/* grammar rules */
+/* 
+
+=back
+
+=head1 GRAMMAR RULES
+
+=over 4
+
+=item expression()
 
-/* simple_expression()
- *
- * Parse a simple expression. Returns the type of the expression.
- */
+Parse a simple expression. Returns the type of the expression.
+
+  expression -> IDENT | INTC | NUMC | STRINGC | REG
+
+=cut
+
+*/
 static token
-simple_expression(parser_state *p) {
-    /* simple_expression -> IDENT | INTC | NUMC | STRINGC | REG */
+expression(parser_state *p) {   
     token exprtok = T_ERROR;
     switch(p->curtoken) {
         case T_IDENTIFIER:
@@ -163,24 +251,89 @@
     return exprtok;
 }
 
+/*
+
+=item target()
+
+  target -> REGISTER | IDENTIFIER
+
+=cut 
+    
+*/
+static void
+target(parser_state *p) {
+    switch(p->curtoken) {
+        case T_PASM_PREG: case T_PREG: case T_PASM_IREG: case T_IREG:
+        case T_PASM_NREG: case T_NREG: case T_PASM_SREG: case T_SREG:
+        case T_IDENTIFIER:
+            next(p);
+            break;
+        default:
+            syntax_error(p, 1, "register or identifier expected");
+            break;
+    }
+}
+
+/* 
+
+=item type()
+
+  type -> 'int' | 'num' | 'pmc' | 'string'
+
+=cut
+
+*/
+static void
+type(parser_state *p) {    
+    switch(p->curtoken) {
+        case T_INT:
+        case T_NUM:
+        case T_PMC:
+        case T_STRING:
+            next(p);
+            break;
+        default:
+            syntax_error(p, 1, "type expected");
+            break;
+    }
+}
+
+/*
+
+=item key()
+
+  key -> '..' expr 
+  key -> expr [ '..' [ expr ] ] 
 
+=cut
+
+*/
 static void
 key(parser_state *p) {
     if (p->curtoken == T_DOTDOT) { /* key -> '..' expr */
         next(p);
-        simple_expression(p);
+        expression(p);
     }
     else { /* key -> expr [ '..' [ expr ] ] */
-        simple_expression(p);
+        expression(p);
         if (p->curtoken == T_DOTDOT) {
             next(p);
             if (p->curtoken == T_RBRACKET) return;
-            else simple_expression(p);
+            else expression(p);
         }
     }
 }
 
 
+/* 
+
+=item keylist()
+
+  keylist -> '[' key { (';'|',') key } ']'
+  
+=cut
+
+*/
 static void
 keylist(parser_state *p) {
     /* keylist -> '[' key { (';'|',') key} ']' */
@@ -193,6 +346,15 @@
     match(p, T_RBRACKET); /* match closing ']' */
 }
 
+/*
+
+=item argument()
+
+  argument -> HEREDOCID | expr | STRINGC '='> expr
+    
+=cut
+
+*/
 static void
 argument(parser_state *p) {
     /* argument -> heredoc_ident | simple_expr */
@@ -201,17 +363,26 @@
         next(p);
     }
     else {
-        token exprtok = simple_expression(p);
+        token exprtok = expression(p);
         /* allow for "stringc '=>' expr" */
         if (exprtok == T_SINGLE_QUOTED_STRING || exprtok == 
T_DOUBLE_QUOTED_STRING) {
             if (p->curtoken == T_ARROW) {
                 next(p);
-                simple_expression(p);
+                expression(p);
             }
         }
     }
 }
 
+/*
+
+=item argument_list()
+
+  argument_list -> argument { ',' argument }
+  
+=cut
+
+*/
 static void
 argument_list(parser_state *p) {
     /* argument_list -> argument { ',' argument } */
@@ -223,7 +394,15 @@
 
 }
 
+/*
+
+=item global_definition()
+
+  global_definition -> '.global' IDENT 
+  
+=cut
 
+*/
 static void
 global_definition(parser_state *p) {
     /* global_definition -> '.global' IDENT */
@@ -231,9 +410,18 @@
     match(p, T_IDENTIFIER);
 }
 
+
+/* 
+
+=item arguments()
+
+  arguments -> '(' [argument_list] ')' { HEREDOC_STRING HEREDOC_DELIM }
+
+=cut
+
+*/
 static void
-arguments(parser_state *p) {
-    /* arguments -> '(' [argument_list] ')' { heredocstring heredoc_delimiter 
} */
+arguments(parser_state *p) {    
     match(p, T_LPAREN);
     if (p->curtoken != T_RPAREN) argument_list(p);
     match(p, T_RPAREN);
@@ -259,15 +447,21 @@
     }
 }
 
-/* arith_expression()
- *
- * If the current token is a binary operator, then this operator
- * together with its right operand is parsed. If no operator,
- * just return.
- */
+/* 
+
+=item arith_expression()
+
+If the current token is a binary operator, then this operator
+together with its right operand is parsed. If no operator,
+just return.
+
+  arith_expr -> [binop expr]
+
+=cut
+
+*/
 static void
-arith_expression(parser_state *p) {
-    /* arith_expr -> [binop simple_expr] */
+arith_expression(parser_state *p) {    
     switch(p->curtoken) {
         case T_PLUS:
         case T_MINUS:
@@ -280,16 +474,25 @@
         case T_BAND:
         case T_CONCAT: /* yeah I know, it's not arithmatic */
             next(p);
-            simple_expression(p);
+            expression(p);
             break;
         default:
             break;
     }
 }
 
+
+/*
+
+=item assignment()
+
+  assignment -> '=' (expr [binop expr] | target (keylist|arguments) | 
heredocstring ) '\n'
+  
+=cut
+
+*/
 static void
-assignment(parser_state *p) {
-    /* assignment -> '=' (expr [binop expr] | target (keylist|arguments) | 
heredocstring ) '\n' */
+assignment(parser_state *p) {    
     match(p, T_ASSIGN);
 
     switch(p->curtoken) {
@@ -308,8 +511,7 @@
                 default: /* expression with a PMC target/id as first operand */
                     arith_expression(p);
                     break;
-            }
-            match(p, T_NEWLINE);
+            }            
             break;
 
         case T_HEREDOC_ID: { /* parse heredoc string */
@@ -317,31 +519,44 @@
             /* read_heredoc() returns a special token */
             p->curtoken = read_heredoc(p->lexer, heredocid);
             match(p, T_HEREDOC_STRING);
-            free(heredocid); /* clean up */
-            match(p, T_NEWLINE);
+            free(heredocid); /* clean up */            
             break;
         }
-
         default: /* general case for 'expr binop expr' */
-            simple_expression(p);
-            arith_expression(p);
-            match(p, T_NEWLINE);
+            expression(p);
+            arith_expression(p);            
             break;
     }
-
+    match(p, T_NEWLINE);
 }
 
+/*
+
+=item goto_statement()
+
+  goto_statement -> 'goto' IDENT '\n'
+
+=cut
+
+*/
 static void
-goto_statement(parser_state *p) {
-    /* goto_statement -> 'goto' IDENT '\n' */
+goto_statement(parser_state *p) {    
     match(p, T_GOTO);
     match(p, T_IDENTIFIER);
     match(p, T_NEWLINE);
 }
 
+/*
+
+=item return_statement()
+
+  return_statement -> '.return' (arguments|tailcall) '\n'
+  
+=cut
+
+*/
 static void
-return_statement(parser_state *p) {
-    /* return_statement -> '.return' ( [arguments] | tailcall ) '\n' */
+return_statement(parser_state *p) {    
     match(p, T_RETURN);
     if (p->curtoken == T_LPAREN) { /* arguments */
         arguments(p);
@@ -353,33 +568,65 @@
     match(p, T_NEWLINE);
 }
 
+/*
+
+=item yield_statement()
+
+  yield_statement -> '.yield' arguments '\n'
+  
+=cut
+
+*/
 static void
-yield_statement(parser_state *p) {
-    /* yield_statement -> '.yield' arguments '\n' */
+yield_statement(parser_state *p) {    
     match(p, T_YIELD);
     arguments(p);
     match(p, T_NEWLINE);
 }
 
+/*
+
+=item close_ns()
+
+  close_ns -> '.endnamespace' IDENT '\n'
+
+=cut
+  
+*/
 static void
-close_ns(parser_state *p) {
-    /* close_ns -> '.endnamespace' IDENT '\n' */
+close_ns(parser_state *p) {   
     match(p, T_ENDNAMESPACE);
     match(p, T_IDENTIFIER);
     match(p, T_NEWLINE);
 }
 
+/*
+
+=item open_ns()
+
+  open_ns -> '.namespace' IDENT '\n'
+  
+=cut
+
+*/
 static void
-open_ns(parser_state *p) {
-    /* open_ns -> '.namespace' IDENT '\n' */
+open_ns(parser_state *p) {    
     match(p, T_NAMESPACE);
     match(p, T_IDENTIFIER);
     match(p, T_NEWLINE);
 }
 
+/*
+
+=item local_id_list()
+
+  local_id_list -> IDENT [flag] { ',' IDENT [flag] }
+
+=cut
+
+*/
 static void
-local_id_list(parser_state *p) {
-    /* local_id_list -> IDENT [flag] { ',' IDENT [flag] } */
+local_id_list(parser_state *p) {   
     match(p, T_IDENTIFIER);
     if (p->curtoken == T_UNIQUE_REG_FLAG) next(p);
 
@@ -391,31 +638,67 @@
     }
 }
 
+/*
+
+=item declaration_list()
+
+ declaration_list -> type local_id_list '\n' 
+ 
+=cut
+
+*/
+
 static void
-declaration_list(parser_state *p) {
-    /* declaration_list -> type local_id_list '\n' */
+declaration_list(parser_state *p) {    
     type(p);
     local_id_list(p);
     match(p, T_NEWLINE);
 }
 
+/*
+
+=item sym_declaration()
+
+  sym_declaration -> '.sym' declaration_list
+ 
+=cut
+
+*/
 static void
 sym_declaration(parser_state *p) {
-    /* sym_declaration -> '.sym' declaration_list */
+    
     match(p, T_SYM);
     declaration_list(p);
 }
 
+/*
+
+=item local_declaration()
+
+  local_declaration -> '.local' declaration_list
+  
+=cut
+
+*/
 static void
-local_declaration(parser_state *p) {
-    /* sym_declaration -> '.local' declaration_list */
+local_declaration(parser_state *p) {    
     match(p, T_LOCAL);
     declaration_list(p);
 }
 
+
+/*
+
+=item stringconstant()
+
+  strinconstant -> DOUBLE_QUOTED_STRING | SINGLE_QUOTED_STRING
+  
+=cut
+
+*/
 static void
 stringconstant(parser_state *p) {
-    /* strinconstant -> double-quoted_string | single-quoted-string */
+    
     if (p->curtoken == T_DOUBLE_QUOTED_STRING
         || p->curtoken == T_SINGLE_QUOTED_STRING) {
         next(p);
@@ -425,9 +708,17 @@
     }
 }
 
+/*
+
+=item lex_declaration()
+
+  lex_declaration -> '.lex' STRINGC ',' target '\n' 
+
+=cut
+
+*/
 static void
-lex_declaration(parser_state *p) {
-    /* sym_declaration -> '.lex' STRINGC ',' target '\n' */
+lex_declaration(parser_state *p) {    
     match(p, T_LEX);
     stringconstant(p);
     match(p, T_COMMA);
@@ -437,30 +728,46 @@
 
 
 
+/*
+
+=item condition_expression()
+
+  conditional_expression -> expression [ ('>'|'>='|'<'|'<='|'=='|'!=') 
expression] 
+
+=cut
+
+*/
 static void
-conditional_expression(parser_state *p) {
-    /* conditional_expression -> simple_expr [ ['>'|'>='|'<'|'<='|'=='|'!='] 
simple_expr] */
-    simple_expression(p);
+conditional_expression(parser_state *p) {    
+    expression(p);
 
     switch(p->curtoken) { /* optional */
-        case T_GE: case T_GT: case T_EQ: case T_NE: case T_LT: case T_LE:
+        case T_GE: case T_GT: case T_EQ: 
+        case T_NE: case T_LT: case T_LE:
             next(p); /* skip comparison op */
-            simple_expression(p);
+            expression(p);
             break;
-        default:
+        default: /* cond-expr -> expr */
             break;
     }
 }
 
+/*
+
+=item unless_statement()
 
+  unless_statement -> 'unless' (null expression|conditional_epxression) 'goto' 
IDENT '\n' 
+
+=cut
+
+*/
 static void
 unless_statement(parser_state *p) {
-    /* unless_statement -> 'unless' expression 'goto' IDENT '\n' */
     match(p, T_UNLESS);
 
     if (p->curtoken == T_NULL) { /* 'unless' 'null' expr 'goto' IDENT */
         next(p);
-        simple_expression(p);
+        expression(p);
     }
     else { /* 'unless' cond_expr 'goto' IDENT */
         conditional_expression(p);
@@ -470,13 +777,21 @@
     match(p, T_NEWLINE);
 }
 
+/*
+
+=item if_statement()
+
+  if_statement -> 'if' (null expression|conditional_epxression) 'goto' IDENT 
'\n'
+
+=cut
+
+*/
 static void
-if_statement(parser_state *p) {
-    /* if_statement -> 'if' expression 'goto' IDENT '\n' */
+if_statement(parser_state *p) {    
     match(p, T_IF);
     if (p->curtoken == T_NULL) { /* if null expr goto LABEL */
         next(p);
-        simple_expression(p);
+        expression(p);
     }
     else { /* if x [op y] goto LABEL */
         conditional_expression(p);
@@ -486,54 +801,36 @@
     match(p, T_NEWLINE);
 }
 
-static void
-int_const_definition(parser_state *p) {
-    match(p, T_IDENTIFIER);
-    match(p, T_ASSIGN);
-    match(p, T_INTEGER_CONSTANT);
-}
-
-static void
-string_const_definition(parser_state *p) {
-    match(p, T_IDENTIFIER);
-    match(p, T_ASSIGN);
-    stringconstant(p);
-}
+/*
 
-static void
-num_const_definition(parser_state *p) {
-    match(p, T_IDENTIFIER);
-    match(p, T_ASSIGN);
-    match(p, T_NUMBER_CONSTANT);
-}
+=item const_definition()
 
-static void
-pmc_const_definition(parser_state *p) {
-    match(p, T_IDENTIFIER);
-    match(p, T_ASSIGN);
-    stringconstant(p);
-}
+  const_definition -> type IDENT '=' constant
 
+=cut
 
+*/
 static void
-const_definition(parser_state *p) {
-    /* const_definition -> type IDENT '=' LITERAL */
+const_definition(parser_state *p) {    
     switch(p->curtoken) {
         case T_INT:
             next(p);
-            int_const_definition(p);
+            match(p, T_IDENTIFIER);
+            match(p, T_ASSIGN);
+            match(p, T_INTEGER_CONSTANT);
             break;
         case T_NUM:
             next(p);
-            num_const_definition(p);
-            break;
-        case T_PMC:
-            next(p);
-            pmc_const_definition(p);
+            match(p, T_IDENTIFIER);
+            match(p, T_ASSIGN);
+            match(p, T_NUMBER_CONSTANT);
             break;
-        case T_STRING:
+        case T_STRING: /* both string and PMC have strings as constants */
+        case T_PMC:                    
             next(p);
-            string_const_definition(p);
+            match(p, T_IDENTIFIER);
+            match(p, T_ASSIGN);
+            stringconstant(p);
             break;
         default:
             syntax_error(p, 1, "type expected");
@@ -543,55 +840,62 @@
 }
 
 
+/*
+
+=item methodcall()
+
+  methodcall -> INVOCANT_IDENT (IDENT|stringconstant) arguments '\n'
+
+=cut
+
+*/
 static void
-methodcall(parser_state *p) {
-    /* methodcall -> IDENT'.' (IDENT|STRINGC) arguments '\n' */
+methodcall(parser_state *p) {    
     match(p, T_INVOCANT_IDENT);
-
     if (p->curtoken == T_IDENTIFIER) next(p);
     else stringconstant(p);
-
     arguments(p);
     match(p, T_NEWLINE);
 }
 
 
-static void
-target(parser_state *p) {
-    /* target -> register | identifier */
-    switch(p->curtoken) {
-        case T_PASM_PREG: case T_PREG: case T_PASM_IREG: case T_IREG:
-        case T_PASM_NREG: case T_NREG: case T_PASM_SREG: case T_SREG:
-        case T_IDENTIFIER:
-            next(p);
-            break;
-        default:
-            syntax_error(p, 1, "register or identifier expected");
-            break;
-    }
-}
-
 
+/*
 
+=item long_return_statement()
 
+  long_return_statement -> '.pcc_begin_return' '\n' 
+                           { '.return' expression '\n' }
+                           '.pcc_end_return' '\n'
+  
+=cut
 
+*/
 static void
-long_return_statement(parser_state *p) {
-    /* long_return_statement -> '.pcc_begin_return' '\n' ... */
+long_return_statement(parser_state *p) {    
     match(p, T_PCC_BEGIN_RETURN);
     match(p, T_NEWLINE);
 
     while (p->curtoken == T_RETURN) { /* ... { '.return' simple_expr '\n' } 
...*/
         next(p); /* skip .return */
-        simple_expression(p);
+        expression(p);
         match(p, T_NEWLINE);
     }
     match(p, T_PCC_END_RETURN); /* ... '.pcc_end_return' '\n' */
     match(p, T_NEWLINE);
 }
 
+/*
+
+=item arg_flags()
+
+  arg_flags -> ':flat' | ':named' [ '(' stringconstant ')' ]
+
+=cut
+
+*/
 static void
-arg_flag(parser_state *p) {
+arg_flags(parser_state *p) {
     while (p->curtoken != T_NEWLINE) {
         switch (p->curtoken) {
             case T_FLAT_FLAG:
@@ -612,17 +916,73 @@
     }
 }
 
+/*
+
+=item param_flag()
+
+  param_flag -> ':slurpy' 
+              | ':named'['(' string ')'] 
+              | ':unique_reg'
+              | ':optional' 
+              | ':opt_flag' 
+              
+=cut
+
+*/
+static void
+param_flags(parser_state *p) {    
+    int ok = 1;
+    while (ok) {
+        switch(p->curtoken) {
+            case T_SLURPY_FLAG:
+            case T_UNIQUE_REG_FLAG:
+            case T_OPTIONAL_FLAG:
+            case T_OPT_FLAG_FLAG:
+                next(p);
+                break;
+            case T_NAMED_FLAG: /* param_flag -> ':named' [ '(' string ')' ] */
+                next(p);
+                if (p->curtoken == T_LPAREN) {
+                    next(p); /* skip '(' */
+                    stringconstant(p);
+                    match(p, T_RPAREN);
+                }
+                break;
+            case T_NEWLINE:
+                ok = 0; /* stop loop */
+                break;
+            default:
+                syntax_error(p, 1, "syntax error: parameter flag or newline 
expected");
+                ok = 0; /* stop loop */
+                break;
+        }
+    }
+}
+
+/*
+
+=item long_invocation()
+
+  long-invocation -> '.pcc_begin' '\n'
+                     { '.arg' expression arg_flags }
+                     ('.pcc_call'|'.nci_call'|'.meth_call')
+                     { (local_declaration| '.result' target '\n') } 
+                     '.pcc_end' '\n'
+
+=cut
+
+*/
 static void
 long_invocation(parser_state *p) {
-    int results = 1;
+    int results = 1; /* flag for while loop */
 
     match(p, T_PCC_BEGIN);  /* '.pcc_begin '\n' ... */
     match(p, T_NEWLINE);
 
     while (p->curtoken == T_ARG) { /* ... { '.arg' expr [flag] '\n' } ... */
         next(p);
-        simple_expression(p);
-        arg_flag(p);
+        expression(p);
+        arg_flags(p);
         match(p, T_NEWLINE);
     }
 
@@ -674,21 +1034,43 @@
 }
 
 
+/*
+
+=item long_yield_statement()
+
+  long_yield_statement -> '.pcc_begin_yield' '\n' 
+                          { '.yield' expr '\n' }
+                          '.pcc_end_yield' '\n' 
+
+=cut
+
+*/
 static void
-long_yield_statement(parser_state *p) {
-    /* long_yield_statement -> '.pcc_begin_yield' '\n' ... */
+long_yield_statement(parser_state *p) {   
     match(p, T_PCC_BEGIN_YIELD);
     match(p, T_NEWLINE);
 
-    while (p->curtoken == T_YIELD) { /* { '.yield' simple_expr '\n' } */
+    while (p->curtoken == T_YIELD) { /* { '.yield' expr '\n' } */
         match(p, T_YIELD);
-        simple_expression(p);
+        expression(p);
         match(p, T_NEWLINE);
     }
     match(p, T_PCC_END_YIELD); /* '.pcc_end_yield' '\n' */
     match(p, T_NEWLINE);
 }
 
+/*
+
+=item target_statement()
+
+  target_statement -> target '=' assignment
+                    | target ('+='|'-='|etc.) expression
+                    | target keylist '=' expression
+                    |
+
+=cut
+
+*/
 static void
 target_statement(parser_state *p) {
     target(p);
@@ -704,13 +1086,13 @@
         case T_POWER_ASSIGN:
         case T_MULTIPLY_ASSIGN:
             next(p);
-            simple_expression(p);
+            expression(p);
             match(p, T_NEWLINE);
             break;
-        case T_LBRACKET: /* target '[' keylist ']' '=' simple_expression */
+        case T_LBRACKET: /* target '[' keylist ']' '=' expression */
             keylist(p);
             match(p, T_ASSIGN);
-            simple_expression(p);
+            expression(p);
             match(p, T_NEWLINE);
             break;
         case T_PTR:  /* target '->' (stringc|identifier) arguments '\n' */
@@ -730,22 +1112,39 @@
     }
 }
 
+/*
+
+=item target_list
+
+  target_list -> '(' target {',' target } ')'
+
+=cut
+
+*/
 static void
-target_list(parser_state *p) {
-    /* target_list -> '(' target {',' target } ')' */
+target_list(parser_state *p) {    
     match(p, T_LPAREN);
-    match(p, T_IDENTIFIER);
+    target(p);
     while(p->curtoken == T_COMMA) {
         next(p);
-        match(p, T_IDENTIFIER);
+        target(p);
         /* add flags like slurpy */
+        param_flags(p);
     }
     match(p, T_RPAREN);
 }
 
+/*
+
+=item multi_result_invocation()
+
+  multi-result-invocation -> target_list '=' (subcall | methodcall) 
+
+=cut
+
+*/
 static void
-multi_result_invocation(parser_state *p) {
-    /* multi-result-invocation -> target_list '=' (subcall | methodcall) */
+multi_result_invocation(parser_state *p) {    
     target_list(p);
     match(p, T_ASSIGN);
 
@@ -767,9 +1166,17 @@
 }
 
 /*
- TODO: create a parse tree for each macro definition, then on macro expansion
- the parse tree can be populated with the actual values (macro parameters).
- */
+
+=item macro_expansion()
+
+  macro_expansion -> ??
+  
+TODO: create a parse tree for each macro definition, then on macro expansion
+the parse tree can be populated with the actual values (macro parameters).
+ 
+=cut
+
+*/
 static void
 macro_expansion(parser_state *p) {
     while (p->curtoken != T_NEWLINE)
@@ -777,7 +1184,15 @@
     match(p, T_NEWLINE);
 }
 
+/*
 
+=item var()
+
+  var -> IDENT | REGISTER
+
+=cut
+
+*/
 static void
 var(parser_state *p) {
     switch (p->curtoken) {
@@ -794,15 +1209,54 @@
     }
 }
 
+/*
+
+=item get_results_instruction()
+
+  get_results_instr -> '.get_results' '(' target_list ')' '\n'
+
+=cut
+
+*/
 static void
 get_results_instruction(parser_state *p) {
-    /* get_results_instr -> '.get_results' '(' target_list ')' '\n' */
+    
     match(p, T_GET_RESULTS);
     target_list(p);
     match(p, T_NEWLINE);
 }
 
 
+/*
+
+=item instructions()
+
+  instruction -> {LABEL '\n'} instr
+  
+  instr -> if_statement
+         | unless_statement
+         | local_declaration
+         | sym_declaration
+         | lex_declaration
+         | globalconst_definition
+         | const_definition
+         | open_ns
+         | close_ns
+         | return_statement
+         | yield_statement
+         | macro_expansion
+         | target_statement
+         | methodcall
+         | long_invocation
+         | long_return_statement
+         | long_yield_statement
+         | NULL var
+         | get_results_instruction
+         | '\n'
+
+=cut
+
+*/
 static void
 instructions(parser_state *p) {
     int ok = 1;
@@ -905,29 +1359,21 @@
     }
 }
 
-static void
-type(parser_state *p) {
-    /* type -> INT | NUM | PMC | STRING */
-    switch(p->curtoken) {
-        case T_INT:
-        case T_NUM:
-        case T_PMC:
-        case T_STRING:
-            next(p);
-            break;
-        default:
-            syntax_error(p, 1, "type expected");
-            break;
-    }
-}
 
+/*
+
+=item multi_type_list()
+
+  multi_type_list -> '(' [multi-type {',' multi_type } ] ')'
+
+=cut
+
+*/
 static void
-multi_type_list(parser_state *p) {
-    /* multi_type_list -> '(' [multi-type {',' multi-type}] ')' */
+multi_type_list(parser_state *p) {    
     int wantmore = 1;
 
     match(p, T_LPAREN);
-
     while (wantmore) {
         /* multi-type -> IDENT | stringc | '[' keylist ']' | type */
         switch (p->curtoken) {
@@ -960,6 +1406,26 @@
     match(p, T_RPAREN);
 }
 
+/*
+
+=item sub_flags()
+
+  sub_flags -> [sub_flag { [','] sub_flag } ]
+  
+  sub_flag  -> ':anon'
+             | ':init'
+             | ':load'
+             | ':main'
+             | ':lex'
+             | ':outer' '(' stringconstant ')'
+             | ':vtable' '(' stringconstant ')'
+             | ':multi' multi-type-list
+             | ':postcomp'
+             | ':immediate'             
+
+=cut
+
+*/
 static void
 sub_flags(parser_state *p) {
     /* sub_flags -> flag { [','] flag } */
@@ -1021,42 +1487,20 @@
     }
 }
 
-static void
-param_flags(parser_state *p) {
-    /* param_flag -> ':slurpy' | ':named'['(' string ')'] | ':unique_reg'
-                               | ':optional' | ':opt_flag' */
-    int ok = 1;
-    while (ok) {
-        switch(p->curtoken) {
-            case T_SLURPY_FLAG:
-            case T_UNIQUE_REG_FLAG:
-            case T_OPTIONAL_FLAG:
-            case T_OPT_FLAG_FLAG:
-                next(p);
-                break;
-            case T_NAMED_FLAG: /* param_flag -> ':named' [ '(' string ')' ] */
-                next(p);
-                if (p->curtoken == T_LPAREN) {
-                    next(p); /* skip '(' */
-                    stringconstant(p);
-                    match(p, T_RPAREN);
-                }
-                break;
-            case T_NEWLINE:
-                ok = 0; /* stop loop */
-                break;
-            default:
-                syntax_error(p, 1, "syntax error: parameter flag or newline 
expected");
-                ok = 0; /* stop loop */
-                break;
-        }
-    }
-}
 
 
+
+/*
+
+=item parameters()
+
+  parameters -> { '.param (register | type IDENT) [param_flag] '\n' }
+
+=cut
+
+*/
 static void
-parameters(parser_state *p) {
-    /* parameters -> { '.param' (register | type IDENT) [param_flag] '\n' */
+parameters(parser_state *p) {    
     while (p->curtoken == T_PARAM) {
         next(p); /* skip '.param */
         if (p->curtoken == T_REGISTER) { /* parameter -> '.param' register */
@@ -1071,9 +1515,17 @@
     }
 }
 
+/*
+
+=item sub_definition()
+
+  sub_definition -> '.sub' (IDENT | stringc) '\n' parameters body '.end'
+
+=cut
+
+*/
 static void
-sub_definition(parser_state *p) {
-    /* sub_definition -> '.sub' (IDENT | stringc) '\n' parameters body '.end' 
*/
+sub_definition(parser_state *p) {    
     match(p, T_SUB);
 
     if (p->curtoken == T_IDENTIFIER) match(p, T_IDENTIFIER);
@@ -1087,9 +1539,17 @@
     match(p, T_END);
 }
 
+/*
+
+=item emit_block()
+
+  emit_block -> '.emit' '\n' {pasm_instruction} '.eom'
+
+=cut
+
+*/
 static void
-emit_block(parser_state *p) {
-    /* emit_block -> '.emit' '\n' {pasm_instruction} '.eom' */
+emit_block(parser_state *p) {    
     match(p, T_EMIT);
     match(p, T_NEWLINE);
     
@@ -1107,9 +1567,17 @@
     match(p, T_EOM);
 }
 
+/*
+
+=item macro_parameters()
+
+  macro_parameters -> [ '(' [ id {',' id} ] ')' ]
+
+=cut
+
+*/
 static void
-macro_parameters(parser_state *p) {
-    /* macro_params -> [ '(' [ id {',' id} ] ')' ] */
+macro_parameters(parser_state *p) {    
     if (p->curtoken == T_LPAREN) next(p);
     else return; /* no parameters apparently */
 
@@ -1123,9 +1591,17 @@
 
 
 
+/*
+
+=item macro_definition()
+
+  '.macro' IDENT parameters '\n' macro_body '.endm'
+
+=cut
+
+*/
 static void
-macro_definition(parser_state *p) {
-    /* macro_definition -> '.macro' ident parameters '\n' macro_body '.endm' */
+macro_definition(parser_state *p) {    
     match(p, T_MACRO);
     match(p, T_IDENTIFIER);
     macro_parameters(p);
@@ -1141,68 +1617,103 @@
     match(p, T_ENDM);
 }
 
-/* include()
- *
- * calls include_file() in the lexer. Then, the first token is initialized
- * by calling next(); then the TOP() routine is invoked to start parsing
- * the included file. After having parsed that file, continue the current file
- * by calling the next token.
- */
+/*
+
+=item include()
+
+calls include_file() in the lexer. Then, the first token is initialized
+by calling next(); then the TOP() routine is invoked to start parsing
+the included file. After having parsed that file, continue the current file
+by calling the next token.
+
+  include -> '.include' stringconstant
+ 
+=cut
+ 
+*/
 static void
 include(parser_state *p) {
     next(p); /* skip '.include '*/
 
     /* only check, don't skip filename */
-    if (p->curtoken != T_DOUBLE_QUOTED_STRING
-        && p->curtoken != T_SINGLE_QUOTED_STRING) {
+    if (p->curtoken != T_DOUBLE_QUOTED_STRING && p->curtoken != 
T_SINGLE_QUOTED_STRING) {
             syntax_error(p, 1, "string constant expected");
     }
     else {
         /* read the file to be included and get first token of the included 
file */
         open_include_file(p->lexer);
         next(p);
-
-        /* go parse it */
-        TOP(p);
-
+                
+        TOP(p); /* go parse it */
         /* switch back to other file that included the one above */
-        close_include_file(p->lexer);
-
-        /* get next token from this file */
-        next(p);
+        close_include_file(p->lexer);       
+        next(p); /* get next token from this file */
     }
 
 }
 
+/*
+
+=item pragma()
+
+  pragma -> '.pragma' 'n_operators' INTC
+
+=cut
+
+*/
+
 static void
-pragma(parser_state *p) {
-    /* pragma -> '.pragma' 'n_operators' intc */
+pragma(parser_state *p) {    
     match(p, T_PRAGMA);
     match(p, T_N_OPERATORS);
     match(p, T_INTEGER_CONSTANT);
 }
 
+/*
+
+=item hll_specifier()
+
+  hll_specifier -> '.HLL' stringconstant ',' stringconstant
+  
+=cut
+
+*/
 static void
-hll_specifier(parser_state *p) {
-    /* hll_spec -> '.HLL' stringc ',' stringc */
+hll_specifier(parser_state *p) {    
     match(p, T_HLL);
     stringconstant(p);
     match(p, T_COMMA);
     stringconstant(p);
 }
 
+/*
+
+=item hll_mapping()
+
+  hll_mapping -> '.HLL_map' INTC ',' INTC
+  
+=cut
+
+*/
 static void
-hll_mapping(parser_state *p) {
-    /* hll_mapping -> '.HLL_map' intc ',' intc */
+hll_mapping(parser_state *p) {    
     match(p, T_HLL_MAP);
     match(p, T_INTEGER_CONSTANT);
     match(p, T_COMMA);
     match(p, T_INTEGER_CONSTANT);
 }
 
+/*
+
+=item namespace_declaration()
+
+  namespace_declaration -> '.namespace' [ '[' stringc { (','|';') stringc ']' ]
+
+=cut
+
+*/
 static void
-namespace_declaration(parser_state *p) {
-    /* namespace_decl -> '.namespace' [ '[' stringc { (','|';') stringc ']' ] 
*/
+namespace_declaration(parser_state *p) {    
     match(p, T_NAMESPACE);
     if (p->curtoken == T_LBRACKET) {
         next(p); /* skip '[' */
@@ -1216,13 +1727,40 @@
     }
 }
 
+/*
+
+=item loadlib()
+
+  loadlib -> '.loadlib' stringconstant
+
+=cut
+
+*/
 static void
-loadlib(parser_state *p) {
-    /* loadlib -> '.loadlib' stringconstant */
+loadlib(parser_state *p) {    
     match(p, T_LOADLIB);
     stringconstant(p);
 }
 
+/*
+
+=item compilation_unit()
+
+  compilation_unit -> global_definition
+                    | sub_definition
+                    | const_definition
+                    | emit_block
+                    | include
+                    | macro_definition
+                    | pragma
+                    | loadlib
+                    | namespace_declaration
+                    | hll_specifier
+                    | hll_mapping
+
+=cut
+
+*/
 static void
 compilation_unit(parser_state *p) {
     switch (p->curtoken) {
@@ -1267,10 +1805,17 @@
 }
 
 
-static void
-program(parser_state *p) {
-    /* program -> {'\n'} compilation_unit { '\n' compilation_unit } */
+/*
+
+=item program()
 
+  program -> {'\n'} compilation_unit { '\n' compilation_unit }
+
+=cut
+
+*/
+static void
+program(parser_state *p) {    
     /* the file may have some initial newlines; eat them */
     if (p->curtoken == T_NEWLINE) next(p);
 
@@ -1282,55 +1827,28 @@
     }
 }
 
-/* TOP()
- *
- * Entry point of the parser
- */
+/*
+
+=item TOP()
+
+Entry point of the parser
+
+  TOP -> program EOF
+  
+=cut
+
+*/
 void
 TOP(parser_state *p) {
     /* file -> program EOF */
     program(p);
 
-    /* do NOT match T_EOF; match() tries to read the next token
-     * instead, do a manual check.
-     */
+    /* do NOT match T_EOF; match() tries to read the next token instead, do a 
manual check. */
     if (p->curtoken != T_EOF) {
-        syntax_error(p, 3, "end of file expected in file '", 
get_current_file(p->lexer), "'\n");
-
-    }
-    //else {
-    //    fprintf(stderr, "TOP: end of file '%s'\n", 
get_current_file(p->lexer));
-    //}
-
+        syntax_error(p, 3, "end of file expected in file '", 
get_current_file(p->lexer), "'\n");    
+    }    
 }
 
 
-/* get_parse_errors()
- *
- * return the number of parse errors.
- */
-int
-get_parse_errors(parser_state *p) {
-    return p->parse_errors;
-}
-
-/* new_parser()
- *
- * constructor for a parser_state object.
- */
-parser_state *
-new_parser(char const * filename) {
-    parser_state *p = (parser_state *)malloc(sizeof(parser_state));
-
-    if (p == NULL) {
-        fprintf(stderr, "no parser");
-        exit(1);
-    }
-    p->lexer         = new_lexer(filename);
-    p->curtoken      = next_token(p->lexer);
-    p->parse_errors  = 0;
-    p->heredoc_index = 0;
-    return p;
-}
 
 

Reply via email to