Author: kjs
Date: Sat Mar 31 02:47:12 2007
New Revision: 17875
Added:
trunk/compilers/pirc/src/pirvtable.c (contents, props changed)
Modified:
trunk/compilers/pirc/src/pirlexer.c
trunk/compilers/pirc/src/pirlexer.h
trunk/compilers/pirc/src/pirmain.c
trunk/compilers/pirc/src/pirout.c
trunk/compilers/pirc/src/pirparser.c
trunk/compilers/pirc/src/pirparser.h
trunk/compilers/pirc/src/pirvtable.h
trunk/config/gen/makefiles/pirc.in
Log:
compilers/pirc:
* added vtable entries
* remove no_output.{c,h} files
* clean up here and there
* better PIR output
* better PAST output
* not finished :-) but working nicely
Modified: trunk/compilers/pirc/src/pirlexer.c
==============================================================================
--- trunk/compilers/pirc/src/pirlexer.c (original)
+++ trunk/compilers/pirc/src/pirlexer.c Sat Mar 31 02:47:12 2007
@@ -368,6 +368,34 @@
return s->curfile->line;
}
+/*
+
+=item get_current_linepos()
+
+Returns the current line position (i.o.w., how many characters
+have been read on the current line?)
+
+=cut
+
+*/
+unsigned short
+get_current_linepos(struct lexer_state *s) {
+ return s->curfile->linepos;
+}
+
+/*
+
+=item get_current_filepos()
+
+Returns the number of charactars read in the current file so far.
+
+=cut
+
+*/
+long
+get_current_filepos(struct lexer_state *s) {
+ return (s->curfile->curchar - s->curfile->buffer);
+}
/*
Modified: trunk/compilers/pirc/src/pirlexer.h
==============================================================================
--- trunk/compilers/pirc/src/pirlexer.h (original)
+++ trunk/compilers/pirc/src/pirlexer.h Sat Mar 31 02:47:12 2007
@@ -181,6 +181,12 @@
/* get the current line number */
extern long get_current_line(struct lexer_state *s);
+/* get the current line position */
+extern unsigned short get_current_linepos(struct lexer_state *s);
+
+/* get current file position */
+extern long get_current_filepos(struct lexer_state *s);
+
/* get the name of the current file being scanned */
extern char * const get_current_file(struct lexer_state *s);
Modified: trunk/compilers/pirc/src/pirmain.c
==============================================================================
--- trunk/compilers/pirc/src/pirmain.c (original)
+++ trunk/compilers/pirc/src/pirmain.c Sat Mar 31 02:47:12 2007
@@ -1,6 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
#include "pirparser.h"
+#include "pirout.h" /* for PIR output */
+#include "pastout.h" /* for PAST output */
+
+
+/* define output type: what kind of semantic routines
+ * should be called in the parser?
+ */
+typedef enum outputtypes {
+ OUTPUT_NONE, /* do nothing */
+ OUTPUT_PIR, /* output PIR */
+ OUTPUT_PAST /* output PAST */
+
+} outputtype;
+
+
+
/* main()
*
@@ -11,24 +27,51 @@
main(int argc, char **argv) {
struct parser_state *p = NULL;
-
+ pirvtable *vtable = NULL;
+
+ /* make this a commandline switch */
+ int output;
+
+ //output = OUTPUT_PAST;
+ output = OUTPUT_PIR;
+
+
if (argc < 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
exit(1);
}
-
- /* create a new parser, specifying the file name */
- p = new_parser(argv[1], OUTPUT_PAST);
+
+ switch (output) {
+ case OUTPUT_NONE:
+ /* just create an empty vtable, the default implementation does
nothing */
+ vtable = new_pirvtable();
+ break;
+ case OUTPUT_PIR:
+ vtable = init_pir_vtable();
+ break;
+ case OUTPUT_PAST:
+ vtable = init_past_vtable();
+ break;
+ default:
+ fprintf(stderr, "Unknown output type specified\n");
+ exit(1);
+ }
+
+
+ /* create a new parser, specifying the file name and the vtable */
+ p = new_parser(argv[1], vtable);
/* start parsing */
TOP(p);
/* check for errors */
- if (get_parse_errors(p))
+ if (get_parse_errors(p)) {
fprintf(stderr, "\nThere were %d errors.\n", get_parse_errors(p));
- else
+ }
+ else {
fprintf(stderr, "\nparsed successfully.\n");
+ }
/* clean up and exit */
exit_parser(p);
Modified: trunk/compilers/pirc/src/pirout.c
==============================================================================
--- trunk/compilers/pirc/src/pirout.c (original)
+++ trunk/compilers/pirc/src/pirout.c Sat Mar 31 02:47:12 2007
@@ -4,6 +4,9 @@
#include <stdio.h>
#include <malloc.h>
+
+#define OUT stderr
+
/*
=head1 API
@@ -57,9 +60,24 @@
static void
pir_name(struct parser_state *p, char *name) {
- fprintf(stderr, " %s ", name);
+ fprintf(OUT, " %s ", name);
+}
+
+static void
+pir_sub(struct parser_state *p, char *source, int pos) {
+ fprintf(OUT, "#character position %d\n", pos);
+ fprintf(OUT, ".sub");
}
+static void
+pir_end(struct parser_state *p) {
+ fprintf(OUT, ".end\n");
+}
+
+static void
+pir_newline(struct parser_state *p, ...) {
+ fprintf(OUT, "\n");
+}
/*
@@ -73,11 +91,13 @@
*/
pirvtable *
init_pir_vtable(void) {
- pirvtable *vtable = (pirvtable *)malloc(sizeof(pirvtable));
+ pirvtable *vtable = new_pirvtable();
- vtable->sub_start = pirout;
- vtable->sub_end = pirout;
- vtable->name = pir_name;
+ /* override the methods that are needed for PIR output */
+ vtable->sub_start = pir_sub;
+ vtable->sub_end = pir_end;
+ vtable->name = pir_name;
+ vtable->stmts_start = pir_newline;
return vtable;
}
Modified: trunk/compilers/pirc/src/pirparser.c
==============================================================================
--- trunk/compilers/pirc/src/pirparser.c (original)
+++ trunk/compilers/pirc/src/pirparser.c Sat Mar 31 02:47:12 2007
@@ -57,10 +57,7 @@
#include "pirparser.h"
/* output stuff */
-#include "pirvtable.h"
-#include "pirout.h" /* for PIR output */
-#include "pastout.h" /* for PAST output */
-#include "no_output.h" /* guess what... */
+#include "pirvtable.h" /* vtable definition */
#include <stdio.h>
#include <stdlib.h>
@@ -80,7 +77,7 @@
char *heredoc_ids[10]; -- array for holding heredoc arguments.
XXX Limited to 10 currently XXX
unsigned heredoc_index; -- index to keep track of heredoc ids
in the array
unsigned parse_errors; -- counter for parse_errors
- pirvtable *vtable; -- vtable holding pointers for output
+ pirvtable *vtable; -- vtable holding pointers for output
routines
}
=cut
@@ -102,13 +99,9 @@
#define MAX_ERRORS 10
-/* call next() to get the next token from the lexer */ /* NOTE: it's calling
pirout() */
-
+/* call next() to get the next token from the lexer */
#define next(P) P->curtoken = next_token(P->lexer)
-/*
-#define next(P) do { pirout(P); P->curtoken = next_token(P->lexer); } while(0)
-*/
/*
@@ -153,13 +146,17 @@
=item new_parser()
-constructor for a parser_state object.
+constructor for a parser_state object. The specified filename
+is parsed. The semantic actions in vtable are called at certain
+points in the code. The vtable is constructed in the parser's
+client code.
=cut
*/
parser_state *
-new_parser(char const * filename, outputtype output) {
+new_parser(char const * filename, pirvtable *vtable) {
+
parser_state *p = (parser_state *)malloc(sizeof(parser_state));
if (p == NULL) {
@@ -170,22 +167,7 @@
p->curtoken = next_token(p->lexer);
p->parse_errors = 0;
p->heredoc_index = 0;
-
- /* based on the output type, create the appropiate vtable */
- switch (output) {
- case OUTPUT_NONE:
- p->vtable = init_none_vtable();
- break;
- case OUTPUT_PIR:
- p->vtable = init_pir_vtable();
- break;
- case OUTPUT_PAST:
- p->vtable = init_past_vtable();
- break;
- default:
- fprintf(stderr, "Unknown output type specified\n");
- exit(1);
- }
+ p->vtable = vtable;
return p;
}
@@ -1807,31 +1789,32 @@
*/
static void
sub_definition(parser_state *p) {
- /* either '.sub' or '.pcc_sub'. This kind of optimization (just skipping)
- * can be done more often, if we're sure the token has already been
checked for.
- */
-
/* call emit method */
- emit_sub_start(p);
-
- next(p);
+ emit_sub_start(p, "", get_current_filepos(p->lexer));
+ next(p); /* skip '.sub' or '.pcc_sub' */
- if (p->curtoken == T_IDENTIFIER) {
- emit_name(p, get_current_token(p->lexer));
- match(p, T_IDENTIFIER);
- }
- else {
- emit_name(p, get_current_token(p->lexer));
- stringconstant(p);
+ switch (p->curtoken) {
+ case T_IDENTIFIER:
+ case T_DOUBLE_QUOTED_STRING:
+ case T_SINGLE_QUOTED_STRING:
+ emit_name(p, get_current_token(p->lexer)); /* emit the name */
+ next(p); /* and get next token */
+ break;
+ default:
+ syntax_error(p, 1, "sub identifier expected");
+ break;
}
sub_flags(p);
match(p, T_NEWLINE);
+
parameters(p);
+ emit_stmts_start(p); /* open stmts block */
instructions(p);
+ emit_stmts_end(p); /* close stmts block */
match(p, T_END);
- /* call emit method */
+ /* call emit method to close sub*/
emit_sub_end(p);
}
@@ -2114,12 +2097,16 @@
/* the file may have some initial newlines; eat them */
if (p->curtoken == T_NEWLINE) next(p);
+ emit_init(p); /* initialize emitter */
+
compilation_unit(p);
while (p->curtoken != T_EOF ) {
match(p, T_NEWLINE);
compilation_unit(p);
}
+
+ emit_end(p); /* close down emitter */
}
/*
Modified: trunk/compilers/pirc/src/pirparser.h
==============================================================================
--- trunk/compilers/pirc/src/pirparser.h (original)
+++ trunk/compilers/pirc/src/pirparser.h Sat Mar 31 02:47:12 2007
@@ -7,17 +7,9 @@
/* hide internals; definition in pirparser.c */
struct parser_state;
-/* define output type: what kind of semantic routines
- * should be called in the parser?
- */
-typedef enum outputtypes {
- OUTPUT_NONE, /* do nothing */
- OUTPUT_PIR, /* output PIR */
- OUTPUT_PAST /* output PAST */
-} outputtype;
/* parser constructor */
-extern struct parser_state *new_parser(char const * filename, outputtype type);
+extern struct parser_state *new_parser(char const * filename, pirvtable
*vtable);
/* entry function for the parser */
extern void TOP(struct parser_state *p);
Added: trunk/compilers/pirc/src/pirvtable.c
==============================================================================
--- (empty file)
+++ trunk/compilers/pirc/src/pirvtable.c Sat Mar 31 02:47:12 2007
@@ -0,0 +1,96 @@
+/*
+
+=head1 NAME
+
+pirvtable.c - implementation of a vtable, that is used by the parser for its
semantic actions.
+
+=head1 DESCRIPTION
+
+Using a vtable makes changing the behaviour of the parser easy. The parser
calls vtable methods
+at certain points, for instance at the start of a subroutine and at the end.
Depending on the
+type of output that is expected, the appropiate function is invoked. Any
output type should
+implement all vtable methods for correct behaviour.
+
+=cut
+
+*/
+#include "pirvtable.h"
+#include "pirparser.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+
+
+/*
+
+=head1 HELPER METHODS
+
+=over 4
+
+=item not_implemented()
+
+Default entry that is set to all vtable entries. If a particular vtable entry
is invoked,
+but was never implemented, this method is called. This is usefule, because not
all output
+type need all vtable methods. The variable arguments are necessary, you never
know how
+many args a method has.
+
+=cut
+
+*/
+static void
+not_implemented(struct parser_state *p, ...) {
+ /* do nothing */
+}
+
+/*
+
+=back
+
+=head1 PIRVTABLE API
+
+=over 4
+
+=item new_pirvtable()
+
+Constructor for a pir vtable. All entries are set to "not_implemented"
function.
+
+=cut
+
+*/
+pirvtable *
+new_pirvtable(void) {
+ pirvtable *vtable = (pirvtable *)malloc(sizeof(pirvtable));
+
+ if (vtable == NULL) {
+ fprintf(stderr, "Failed to allocate memory for vtable!\n");
+ exit(1);
+ }
+
+ /* set all entries to 'default' by default */
+ vtable->initialize = not_implemented;
+ vtable->name = not_implemented;
+ vtable->sub_start = not_implemented;
+ vtable->sub_end = not_implemented;
+ vtable->stmts_start = not_implemented;
+ vtable->stmts_end = not_implemented;
+ vtable->end = not_implemented;
+
+ return vtable;
+}
+
+/*
+
+=back
+
+=cut
+
+*/
+
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
+
Modified: trunk/compilers/pirc/src/pirvtable.h
==============================================================================
--- trunk/compilers/pirc/src/pirvtable.h (original)
+++ trunk/compilers/pirc/src/pirvtable.h Sat Mar 31 02:47:12 2007
@@ -8,20 +8,28 @@
*/
typedef struct pirvtable {
- void (* sub_start)(struct parser_state *p);
- void (* sub_end) (struct parser_state *p);
- void (* name) (struct parser_state *p, char *name);
+ void (* initialize) (struct parser_state *p);
+ void (* sub_start) (struct parser_state *p, char *source, int pos);
+ void (* sub_end) (struct parser_state *p);
+ void (* name) (struct parser_state *p, char *name);
+ void (* stmts_start) (struct parser_state *p);
+ void (* stmts_end) (struct parser_state *p);
+ void (* end) (struct parser_state *p);
} pirvtable;
/* #defines for cleaner invocation syntax */
-# define emit_sub_start(P) (*P->vtable->sub_start)(P)
-# define emit_sub_end(P) (*P->vtable->sub_end) (P)
-# define emit_name(P,N) (*P->vtable->name) (P,N)
-
+# define emit_init(P) (*P->vtable->initialize) (P)
+# define emit_sub_start(P,S,L) (*P->vtable->sub_start) (P,S,L)
+# define emit_sub_end(P) (*P->vtable->sub_end) (P)
+# define emit_name(P,N) (*P->vtable->name) (P,N)
+# define emit_stmts_start(P) (*P->vtable->stmts_start)(P)
+# define emit_stmts_end(P) (*P->vtable->stmts_end) (P)
+# define emit_end(P) (*P->vtable->end) (P)
+extern pirvtable *new_pirvtable(void);
#endif
Modified: trunk/config/gen/makefiles/pirc.in
==============================================================================
--- trunk/config/gen/makefiles/pirc.in (original)
+++ trunk/config/gen/makefiles/pirc.in Sat Mar 31 02:47:12 2007
@@ -1,26 +1,26 @@
-# Setup some commands
-LN_S = @lns@
-PERL = @perl@
-RM_RF = @rm_rf@
-PARROT = ../../[EMAIL PROTECTED]@
+# Setup some commands
+LN_S = @lns@
+PERL = @perl@
+RM_RF = @rm_rf@
+PARROT = ../../[EMAIL PROTECTED]@
TOOL_DIR = ../..
-CC = @cc@
-CP = @cp@
-BUILD = $(PERL) @build_dir@/tools/build/dynpmc.pl
-O = @o@
-EXE = @exe@
+CC = @cc@
+CP = @cp@
+BUILD = $(PERL) @build_dir@/tools/build/dynpmc.pl
+O = @o@
+EXE = @exe@
-CC_INC = @cc_inc@
-C_LIBS = @libs@
+CC_INC = @cc_inc@
+C_LIBS = @libs@
CC_SHARED = @cc_shared@
-CFLAGS = $(CC_INC) @ccflags@ @cc_debug@ @ccwarn@ @cc_hasjit@ @cg_flag@
@gc_flag@ $(CC_SHARED)
-LINK_DYNAMIC = @link_dynamic@
-LINK = @link@
+CFLAGS = $(CC_INC) @ccflags@ @cc_debug@ @ccwarn@ @cc_hasjit@ @cg_flag@
@gc_flag@ $(CC_SHARED)
+LINK_DYNAMIC = @link_dynamic@
+LINK = @link@
LINKFLAGS = @linkflags@ @link_debug@ @ld_debug@
-LD = @ld@
-LDFLAGS = @ldflags@ @ld_debug@
+LD = @ld@
+LDFLAGS = @ldflags@ @ld_debug@
@@ -28,71 +28,71 @@
all: pirc
-SOURCES = src/pirmain.c \
+SOURCES = src/pirmain.c \
src/pirparser.c \
src/pirparser.h \
src/pirlexer.c \
src/pirlexer.h \
src/pirout.c \
src/pirout.h \
- src/pastout.c \
- src/pastout.h \
- src/no_output.c \
- src/no_output.h \
- src/pirvtable.h
+ src/pastout.c \
+ src/pastout.h \
+ src/pirvtable.c \
+ src/pirvtable.h
-pirc: pirmain$(O) pirparser$(O) pirlexer$(O) pirout$(O) pastout$(O)
no_output$(O)
- $(CC) -o pirc$(EXE) pirmain$(O) pirparser$(O) pirlexer$(O) pirout$(O)
pastout$(O) \
- no_output$(O)
+pirc: pirmain$(O) pirparser$(O) pirlexer$(O) pirout$(O) pastout$(O)
pirvtable$(O)
+ $(CC) -o pirc$(EXE) pirmain$(O) pirparser$(O) pirlexer$(O)
pirout$(O) pastout$(O) pirvtable$(O)
pirmain$(O): src/pirmain.c src/pirparser.h
- $(CC) $(CFLAGS) -c src/pirmain.c
+ $(CC) $(CFLAGS) -c src/pirmain.c
pirparser$(O): src/pirparser.c src/pirparser.h src/pirlexer.h
- $(CC) $(CFLAGS) -c src/pirparser.c
-
+ $(CC) $(CFLAGS) -c src/pirparser.c
+
pirlexer$(O): src/pirlexer.c src/pirlexer.h
- $(CC) $(CFLAGS) -c src/pirlexer.c
-
-pirout$(O): src/pirout.c src/pirout.h
- $(CC) $(CFLAGS) -c src/pirout.c
+ $(CC) $(CFLAGS) -c src/pirlexer.c
+
+pirout$(O): src/pirout.c src/pirout.h
+ $(CC) $(CFLAGS) -c src/pirout.c
pastout$(O): src/pastout.c src/pastout.h
- $(CC) $(CFLAGS) -c src/pastout.c
+ $(CC) $(CFLAGS) -c src/pastout.c
+
+pirvtable$(O): src/pirvtable.c src/pirvtable.h
+ $(CC) $(CFLAGS) -c src/pirvtable.c
-no_output$(O): src/no_output.c src/no_output.h
- $(CC) $(CFLAGS) -c src/no_output.c
-# This is a listing of all targets, that are meant to be called by users
+
+# This is a listing of all targets, that are meant to be called by users
help:
@echo ""
@echo "Following targets are available for the user:"
@echo ""
- @echo " all: pirc"
- @echo " This is the default."
+ @echo " all: pirc"
+ @echo " This is the
default."
# @echo "Testing:"
-# @echo " test: Run the test suite."
-# @echo " testclean: Clean up test results."
+# @echo " test: Run the test suite."
+# @echo " testclean: Clean up test results."
# @echo ""
@echo "Cleaning:"
- @echo " clean: Basic cleaning up."
- @echo " realclean: Removes also files generated by
'Configure.pl'"
- @echo " distclean: Removes also anything built, in theory"
+ @echo " clean: Basic cleaning up."
+ @echo " realclean: Removes also files generated by
'Configure.pl'"
+ @echo " distclean: Removes also anything built, in
theory"
@echo ""
@echo "Misc:"
- @echo " help: Print this help message."
+ @echo " help: Print this help message."
@echo ""
-clean:
- $(RM_RF) *$(O)
-
+clean:
+ $(RM_RF) *$(O)
+
realclean: clean
$(RM_RF) \
- $(STICKY_FILES) \
- pirc$(EXE)
+ $(STICKY_FILES) \
+ pirc$(EXE)
distclean: realclean