Author: kjs
Date: Wed Apr 4 22:10:43 2007
New Revision: 17991
Modified:
trunk/compilers/pirc/src/pirparser.c
Log:
compilers/pirc:
* removed limit of 10 heredoc args (allowing for a virtual unlimited number of
heredoc arguments for function calls.
* fixed some comments.
Modified: trunk/compilers/pirc/src/pirparser.c
==============================================================================
--- trunk/compilers/pirc/src/pirparser.c (original)
+++ trunk/compilers/pirc/src/pirparser.c Wed Apr 4 22:10:43 2007
@@ -9,9 +9,6 @@
=over 4
=item *
-Remove limit of 10 heredoc arguments
-
-=item *
Add error correcting stuff, so parsing can continue after simple errors.
@@ -19,12 +16,12 @@
Maybe use #define's to implement small functions. Effectively, these routines
will be inlined in compilation_unit() or instruction(), but when using
#define's
-it's still kinda code that looks good.
+it's still code that looks good.
=item *
-Skip first token of statements if it's sure that the token has already been
checked by the caller. No need
-to match 'goto' again, if it was already checked in compilation_unit().
+Skip first token of statements if it's sure that the token has already been
checked by the caller.
+For instance, no need to match 'goto' again, if it was already checked in
compilation_unit().
=item *
@@ -33,17 +30,24 @@
=item *
Clean up grammar after discussion.
- - For instance, why have :postcomp and :immediate, having same meaning?, and
- - why ".sub" and ".pcc_sub"?
- - why "object" as type? Why custom names as type, such as '.local Array x' --
- this is not needed, and makes the code look more like a HLL. Just stick
- to 'pmc', which works fine.
- - why allow an optional comma between sub pragmas? param pragmas don't have
that
- so remove this opt. comma as well for consistency.
- - unify '.sym' and '.local'. Just allow one, and think of something else for
- local labels in macros.
- - Decide on dot-prefix: either .Integer or Integer, but not both.
- same for strings: .Integer, Integer or "Integer"?
+
+=over 4
+
+=item + For instance, why have :postcomp and :immediate, having same meaning?,
and why ".sub" and ".pcc_sub"?
+
+=item + why "object" as type? Why custom names as type, such as '.local Array
x' --
+ this is not needed, and makes the code look more like a HLL. Just
stick to 'pmc', which works fine.
+
+=item + why allow an optional comma between sub pragmas? param pragmas don't
have that
+ so remove this opt. comma as well for consistency.
+
+=item + unify '.sym' and '.local'. Just allow one, and think of something else
for local labels in macros.
+
+=item + Decide on dot-prefix: either .Integer or Integer, but not both.
+
+=item + same for strings: .Integer, Integer or "Integer"?
+
+=back
=back
@@ -54,10 +58,7 @@
#include "pirlexer.h"
#include "pirparser.h"
-
-/* output stuff */
#include "pirvtable.h" /* vtable definition */
-
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@@ -86,7 +87,8 @@
typedef struct parser_state {
struct lexer_state *lexer;
token curtoken;
- char *heredoc_ids[10];
+ char **heredoc_ids;
+ size_t heredoc_ids_size;
unsigned heredoc_index;
unsigned parse_errors;
pirvtable *vtable;
@@ -95,8 +97,9 @@
/* quit after 10 errors to prevent too many errors */
-#define MAX_ERRORS 10
+#define MAX_ERRORS 10
+#define MAX_HEREDOC_ARGS 10
/* call next() to get the next token from the lexer */
#define next(P) P->curtoken = next_token(P->lexer)
@@ -120,6 +123,8 @@
exit_parser(parser_state *p) {
emit_destroy(p); /* call destructor for emit_data */
destroy_lexer(p->lexer); /* destroy the lexer */
+ free(p->heredoc_ids);
+ p->heredoc_ids = NULL;
free(p);
p = NULL;
exit(0);
@@ -168,6 +173,9 @@
p->heredoc_index = 0;
p->vtable = vtable;
+ /* allocate array to store heredoc arguments */
+ p->heredoc_ids = (char **)calloc(MAX_HEREDOC_ARGS, sizeof(char *));
+ p->heredoc_ids_size = MAX_HEREDOC_ARGS;
return p;
}
@@ -207,6 +215,35 @@
=over 4
+=item * static void resize_heredoc_args()
+
+Reallocate memory for the array holding heredoc arguments. If needed, the
array is resized
+to twice its previous size. So, initially it's MAX_HEREDOC_ARGS, after the
first resize(),
+it's 2 times MAX_HEREDOC_ARGS, after the second time it's 2 * 2 *
MAX_HEREDOC_ARGS, etc.
+
+=cut
+
+*/
+static void
+resize_heredoc_args(parser_state *p) {
+ /* allocate a new buffer*/
+ char **newbuffer = (char **)calloc(p->heredoc_ids_size << 1, sizeof(char
**));
+ if (newbuffer == NULL) {
+ fprintf(stderr, "Failed to reallocate memory for heredoc arguments\n");
+ }
+ else {
+ unsigned i; /* copy all contents of old array into new array */
+ for (i = 0; i < p->heredoc_index; i++)
+ newbuffer[i] = p->heredoc_ids[i];
+
+ /* free old memory and store new buffer in parser_state structure */
+ free(p->heredoc_ids);
+ p->heredoc_ids = newbuffer;
+ }
+}
+
+/*
+
=item * static void syntax_error()
Handle all syntax error through this function.
@@ -520,6 +557,12 @@
argument(parser_state *p) {
/* argument -> heredoc_ident | expression */
if (p->curtoken == T_HEREDOC_ID) { /* heredoc argument */
+
+ /* check for enough space; if not, resize to make space */
+ if (p->heredoc_index == p->heredoc_ids_size) {
+ resize_heredoc_args(p);
+ }
+
p->heredoc_ids[p->heredoc_index++] =
clone_string(get_current_token(p->lexer));
next(p);
}
@@ -734,25 +777,25 @@
case T_STRING_CONSTANT: {
char *str = clone_string(get_current_token(p->lexer));
next(p);
- if (p->curtoken == T_LPAREN) { /* "foo"() */
+ if (p->curtoken == T_LPAREN) { /* is it a function call? "foo"() */
emit_invocation_start(p);
emit_invokable(p, str);
arguments(p);
emit_invocation_end(p);
}
- else { /* target '=' STRINGC */
+ else { /* no, it's a simple assignment; target '=' STRINGC */
emit_expr(p, str);
}
break;
}
- case T_IDENTIFIER:
+ case T_IDENTIFIER: /* target */
case T_PREG:
case T_PASM_PREG: {
char *obj = clone_string(get_current_token(p->lexer)); /* save it
for now */
next(p);
switch (p->curtoken) {
- case T_LPAREN: /* function call; foo() */
+ case T_LPAREN: /* target arguments; function call; foo() */
emit_invocation_start(p);
emit_invokable(p, obj);
arguments(p);
@@ -832,7 +875,7 @@
break;
default: /* '.return' target ['->' method] arguments */
target(p);
- if (p->curtoken == T_PTR) {
+ if (p->curtoken == T_PTR) { /* optional '->' method */
next(p);
method(p);
}
@@ -2038,7 +2081,7 @@
=item *
- emit_block -> '.emit' '\n' {parrot_instruction} ['\n'] '.eom'
+ emit_block -> '.emit' '\n' { parrot_instruction '\n' } '.eom'
=cut
@@ -2051,10 +2094,9 @@
while (p->curtoken == T_PARROT_OP) {
parrot_instruction(p);
+ match(p, T_NEWLINE);
}
- if (p->curtoken == T_NEWLINE) next(p);
-
match(p, T_EOM);
}
@@ -2340,6 +2382,8 @@
if (p->curtoken != T_EOF) {
syntax_error(p, 3, "end of file expected in file '",
get_current_file(p->lexer), "'\n");
}
+
+ resize_heredoc_args(p);
}