[svn:languages] r20 - in c99: . branches tags trunk trunk/config trunk/config/makefiles trunk/lib trunk/lib/Parrot trunk/lib/Parrot/Test trunk/src trunk/src/builtins trunk/src/cpp trunk/src/cpp/src trunk/src/cpp/src/builtins trunk/src/cpp/src/parser trunk/src/cpp/t trunk/src/parser trunk/t

allison at svn.parrot.org allison at svn.parrot.org
Tue Mar 10 23:43:33 UTC 2009


Author: allison
Date: Tue Mar 10 23:43:32 2009
New Revision: 20
URL: https://trac.parrot.org/languages/changeset/20

Log:
[c99] Relocating c99 language to languages repository from
https://svn.parrot.org/parrot/trunk/languages/c99/.

Added:
   c99/
   c99/branches/
   c99/tags/
   c99/trunk/
   c99/trunk/MAINTAINER
   c99/trunk/c99.pir
   c99/trunk/config/
   c99/trunk/config/makefiles/
   c99/trunk/config/makefiles/cpp.in
   c99/trunk/config/makefiles/root.in
   c99/trunk/lib/
   c99/trunk/lib/Parrot/
   c99/trunk/lib/Parrot/Test/
   c99/trunk/lib/Parrot/Test/C99.pm
   c99/trunk/src/
   c99/trunk/src/CPP_AST2Constants.tg
   c99/trunk/src/CPP_ASTGrammar.tg
   c99/trunk/src/CPP_PASTNodes.pir
   c99/trunk/src/CPP_PGE2AST.pir
   c99/trunk/src/builtins/
   c99/trunk/src/builtins/say.pir
   c99/trunk/src/c99.pg
   c99/trunk/src/c99_PGE.pir
   c99/trunk/src/cpp/
   c99/trunk/src/cpp/Makefile
   c99/trunk/src/cpp/cpp.pir
   c99/trunk/src/cpp/src/
   c99/trunk/src/cpp/src/builtins/
   c99/trunk/src/cpp/src/builtins/say.pir
   c99/trunk/src/cpp/src/parser/
   c99/trunk/src/cpp/src/parser/actions.pm
   c99/trunk/src/cpp/src/parser/grammar.pg
   c99/trunk/src/cpp/t/
   c99/trunk/src/cpp/t/comment_01.t
   c99/trunk/src/cpp/t/cpp_0.t
   c99/trunk/src/cpp/t/harness   (contents, props changed)
   c99/trunk/src/cpp/t/spi.t
   c99/trunk/src/parser/
   c99/trunk/src/parser/actions.pm
   c99/trunk/src/parser/grammar.pg
   c99/trunk/src/preamble
   c99/trunk/t/
   c99/trunk/t/harness   (contents, props changed)
   c99/trunk/t/spi.t

Added: c99/trunk/MAINTAINER
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/MAINTAINER	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,7 @@
+# $Id: MAINTAINER 25984 2008-02-22 12:18:20Z kjs $
+
+N: Kevin Tew
+E: kevintew at tewk.com
+
+N: Klaas-Jan Stol (kjs)
+E: parrotcode at gmail.com

Added: c99/trunk/c99.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/c99.pir	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,80 @@
+# $Id: c99.pir 36833 2009-02-17 20:09:26Z allison $
+# Copyright (C) 2008, Parrot Foundation.
+
+=head1 TITLE
+
+c99.pir - A C99 compiler.
+
+=head2 Description
+
+This is the base file for the C99 compiler.
+
+This file includes the parsing and grammar rules from
+the src/ directory, loads the relevant PGE libraries,
+and registers the compiler under the name 'C99'.
+
+=head2 Functions
+
+=over 4
+
+=item onload()
+
+Creates the C compiler using a C<PCT::HLLCompiler>
+object.
+
+=cut
+
+.namespace [ 'C99';'Compiler' ]
+
+.loadlib 'c99_group'
+
+.sub 'onload' :anon :load :init
+    load_bytecode 'PCT.pbc'
+
+    $P0 = get_hll_global ['PCT'], 'HLLCompiler'
+    $P1 = $P0.'new'()
+    $P1.'language'('C99')
+    $P1.'parsegrammar'('C99::Grammar')
+    $P1.'parseactions'('C99::Grammar::Actions')
+.end
+
+=item main(args :slurpy)  :main
+
+Start compilation by passing any command line C<args>
+to the C compiler.
+
+=cut
+
+.sub 'main' :main
+    .param pmc args
+
+    $P0 = compreg 'C99'
+    $P1 = $P0.'command_line'(args)
+.end
+
+
+.include 'src/gen_builtins.pir'
+.include 'src/gen_grammar.pir'
+.include 'src/gen_actions.pir'
+
+
+.namespace [ 'C99';'Grammar' ]
+
+.sub 'debug'
+    .param pmc match
+    .param pmc arg
+    .param pmc attrs :slurpy
+    printerr arg
+    printerr "\n"
+.end
+
+=back
+
+=cut
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+

Added: c99/trunk/config/makefiles/cpp.in
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/config/makefiles/cpp.in	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,102 @@
+# Copyright (C) 2008-2009, Parrot Foundation.
+## $Id: cpp.in 36833 2009-02-17 20:09:26Z allison $
+
+## arguments we want to run parrot with
+PARROT_ARGS   =
+
+## configuration settings
+BUILD_DIR     = @build_dir@
+LOAD_EXT      = @load_ext@
+O             = @o@
+
+## Setup some commands
+PERL          = @perl@
+RM_F          = @rm_f@
+CP            = @cp@
+CAT           = @cat@
+PARROT        = ../../../../parrot at exe@
+BUILD_DYNPMC  = $(PERL) $(BUILD_DIR)/tools/build/dynpmc.pl
+RECONFIGURE   = $(PERL) $(BUILD_DIR)/tools/dev/reconfigure.pl
+
+## places to look for things
+PARROT_DYNEXT = $(BUILD_DIR)/runtime/parrot/dynext
+PGE_LIBRARY   = $(BUILD_DIR)/runtime/parrot/library/PGE
+PERL6GRAMMAR  = $(PGE_LIBRARY)/Perl6Grammar.pbc
+NQP           = $(BUILD_DIR)/compilers/nqp/nqp.pbc
+PCT           = $(BUILD_DIR)/runtime/parrot/library/PCT.pbc
+
+PMC_DIR       = src/pmc
+
+all: cpp.pbc
+
+SOURCES = cpp.pir \
+  src/gen_grammar.pir \
+  src/gen_actions.pir \
+  src/gen_builtins.pir
+
+BUILTINS_PIR = \
+  src/builtins/say.pir
+
+# the default target
+cpp.pbc: $(PARROT) $(SOURCES)
+	$(PARROT) $(PARROT_ARGS) -o cpp.pbc cpp.pir
+	$(CP) cpp.pbc ../../cpp.pbc
+
+src/gen_grammar.pir: $(PERL6GRAMMAR) src/parser/grammar.pg
+	$(PARROT) $(PARROT_ARGS) $(PERL6GRAMMAR) \
+	    --output=src/gen_grammar.pir \
+	    src/parser/grammar.pg
+
+src/gen_actions.pir: $(NQP) $(PCT) src/parser/actions.pm
+	$(PARROT) $(PARROT_ARGS) $(NQP) --output=src/gen_actions.pir \
+	    --target=pir src/parser/actions.pm
+
+src/gen_builtins.pir: $(BUILTINS_PIR)
+	$(CAT) $(BUILTINS_PIR) >src/gen_builtins.pir
+
+# regenerate the Makefile
+Makefile: ../../config/makefiles/cpp.in
+	cd $(BUILD_DIR) && $(RECONFIGURE) --step=gen::languages --languages=c99
+
+# 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:               c.pbc"
+	@echo "                     This is the default."
+	@echo "Testing:"
+	@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 ""
+	@echo "Misc:"
+	@echo "  help:              Print this help message."
+	@echo ""
+
+test: all
+	$(PERL) t/harness
+
+# this target has nothing to do
+testclean:
+
+CLEANUPS = \
+  cpp.pbc \
+  "src/gen_*.pir"
+
+clean:
+	$(RM_F) $(CLEANUPS)
+
+realclean: clean
+	$(RM_F) Makefile
+
+distclean: realclean
+
+# Local variables:
+#   mode: makefile
+# End:
+# vim: ft=make:

Added: c99/trunk/config/makefiles/root.in
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/config/makefiles/root.in	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,113 @@
+# Copyright (C) 2006-2009, Parrot Foundation.
+## $Id: root.in 36833 2009-02-17 20:09:26Z allison $
+
+## arguments we want to run parrot with
+PARROT_ARGS   =
+
+## configuration settings
+BUILD_DIR     = @build_dir@
+LOAD_EXT      = @load_ext@
+O             = @o@
+
+## Setup some commands
+PERL          = @perl@
+RM_RF         = @rm_rf@
+CP            = @cp@
+CAT           = @cat@
+MAKE          = @make_c@
+PARROT        = ../../parrot at exe@
+BUILD_DYNPMC  = $(PERL) $(BUILD_DIR)/tools/build/dynpmc.pl
+RECONFIGURE   = $(PERL) $(BUILD_DIR)/tools/dev/reconfigure.pl
+#IF(darwin):
+#IF(darwin):# MACOSX_DEPLOYMENT_TARGET must be defined for OS X compilation/linking
+#IF(darwin):export MACOSX_DEPLOYMENT_TARGET := @osx_version@
+
+## places to look for things
+PARROT_DYNEXT = $(BUILD_DIR)/runtime/parrot/dynext
+PGE_LIBRARY   = $(BUILD_DIR)/runtime/parrot/library/PGE
+PERL6GRAMMAR  = $(PGE_LIBRARY)/Perl6Grammar.pbc
+NQP           = $(BUILD_DIR)/compilers/nqp/nqp.pbc
+PCT           = $(BUILD_DIR)/runtime/parrot/library/PCT.pbc
+
+PMC_DIR       = src/pmc
+
+all: c99.pbc cpp
+
+C_GROUP = $(PMC_DIR)/c_group$(LOAD_EXT)
+
+SOURCES = c99.pir \
+  src/gen_grammar.pir \
+  src/gen_actions.pir \
+  src/gen_builtins.pir
+
+BUILTINS_PIR = \
+  src/builtins/say.pir
+
+c99.pbc: $(PARROT) $(SOURCES)
+	$(PARROT) $(PARROT_ARGS) -o c99.pbc c99.pir
+
+src/gen_grammar.pir: $(PERL6GRAMMAR) src/parser/grammar.pg
+	$(PARROT) $(PARROT_ARGS) $(PERL6GRAMMAR) \
+	    --output=src/gen_grammar.pir \
+	    src/parser/grammar.pg
+
+src/gen_actions.pir: $(NQP) $(PCT) src/parser/actions.pm
+	$(PARROT) $(PARROT_ARGS) $(NQP) --output=src/gen_actions.pir \
+	    --target=pir src/parser/actions.pm
+
+src/gen_builtins.pir: $(BUILTINS_PIR)
+	$(CAT) $(BUILTINS_PIR) >src/gen_builtins.pir
+
+cpp:
+	$(MAKE) src/cpp
+
+# regenerate the Makefile
+Makefile: config/makefiles/root.in
+	cd $(BUILD_DIR) && $(RECONFIGURE) --step=gen::languages --languages=c99
+
+# 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:               c.pbc"
+	@echo "                     This is the default."
+	@echo "Testing:"
+	@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 ""
+	@echo "Misc:"
+	@echo "  help:              Print this help message."
+	@echo ""
+
+test: all
+	$(PERL) t/harness
+	$(MAKE) src/cpp test
+
+# this target has nothing to do
+testclean:
+
+CLEANUPS = \
+  c99.pbc \
+  "src/gen_*.pir"
+
+clean:
+	$(RM_RF) $(CLEANUPS)
+	$(MAKE) src/cpp clean
+
+realclean: clean
+	$(RM_RF) Makefile
+	$(MAKE) src/cpp realclean
+
+distclean: realclean
+	$(MAKE) src/cpp distclean
+
+# Local variables:
+#   mode: makefile
+# End:
+# vim: ft=make:

Added: c99/trunk/lib/Parrot/Test/C99.pm
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/lib/Parrot/Test/C99.pm	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,90 @@
+# $Id: C99.pm 36833 2009-02-17 20:09:26Z allison $
+# Copyright (C) 2006, Parrot Foundation.
+
+
+package Parrot::Test::C99;
+
+use strict;
+use warnings;
+
+use File::Basename;
+
+=head1 Parrot::Test::C99
+
+Provide language specific testing routines here...
+
+This is currently alarmingly similar to the generated subs in Parrot::Test.
+Perhaps someone can do a better job of delegation here.
+
+=cut
+
+sub new {
+    return bless {};
+}
+
+sub output_is() {
+    my ( $self, $code, $output, $desc ) = @_;
+
+    #print "@_\n";
+
+    my $count = $self->{builder}->current_test + 1;
+    $desc = 'C99 Test' unless $desc;
+
+    my $lang_f          = File::Spec->rel2abs( Parrot::Test::per_test( '.c',             $count ) );
+    my $out_f           = File::Spec->rel2abs( Parrot::Test::per_test( '.out',           $count ) );
+    my $c99_out_f       = File::Spec->rel2abs( Parrot::Test::per_test( '.c99.out',       $count ) );
+    my $c99_out_debug_f = File::Spec->rel2abs( Parrot::Test::per_test( '.c99.debug.out', $count ) );
+    my $parrotdir       = dirname $self->{parrot};
+
+    Parrot::Test::write_code_to_file( $code, $lang_f );
+
+    my $args = $ENV{TEST_PROG_ARGS} || '';
+
+#my $gcc_cmd = "gcc $lang_f";
+#my $gcc_exit_code = Parrot::Test::run_command($gcc_cmd, CD => $self->{relpath}, STDOUT => $out_f, STDERR => $out_f );
+#my $gcc_output = Parrot::Test::slurp_file($out_f);
+
+    my $c99_cmd       = "$self->{parrot} $args languages/c99/c99.pbc $lang_f";
+    my $c99_exit_code = Parrot::Test::run_command(
+        $c99_cmd,
+        CD     => $self->{relpath},
+        STDOUT => $c99_out_f,
+        STDERR => $c99_out_f
+    );
+    my $c99_output = Parrot::Test::slurp_file($c99_out_f);
+
+    my $pass = $self->{builder}->is_eq( $c99_output, "1" );
+
+#my $pass = $self->{builder}->is_eq( $c99_output, $gcc_output, $desc );
+#$self->{builder}->diag("'$gcc_cmd' failed with exit code $gcc_exit_code") if $gcc_exit_code and not $pass;
+    $self->{builder}->diag("'$c99_cmd' failed with exit code $c99_exit_code")
+        if $c99_exit_code and not $pass;
+
+    if ( not $pass ) {
+        my $c99_debug_cmd       = "$self->{parrot} $args languages/c99/c99.pbc -d $lang_f";
+        my $c99_debug_exit_code = Parrot::Test::run_command(
+            $c99_debug_cmd,
+            CD     => $self->{relpath},
+            STDOUT => $c99_out_debug_f,
+            STDERR => $c99_out_debug_f
+        );
+        my $c99_debug_output = Parrot::Test::slurp_file($c99_out_debug_f);
+    }
+
+    unless ( $ENV{POSTMORTEM} ) {
+
+        #unlink $lang_f;
+        unlink $out_f;
+        unlink $c99_out_f;
+    }
+    return $pass;
+}
+
+1;
+
+# Local Variables:
+#   mode: cperl
+#   cperl-indent-level: 4
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:

Added: c99/trunk/src/CPP_AST2Constants.tg
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/CPP_AST2Constants.tg	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,190 @@
+=head1 NAME
+
+C99::CPPConstants Grammar -- A grammar for transforming an CPP AST to a Parrot constants file
+
+=head1 SYNOPSYS
+
+=head1 DESCRIPTION
+
+=cut
+
+#code = new 'CodeString'
+#code.'emit'("    %0 = find_name '%1'", value, name)
+
+grammar C99::CPP::Constants::ConstantsGrammar is TGE::Grammar;
+
+transform root (C99::CPP::PAST::Node) :language('PIR') {
+    .local pmc code
+    code = new 'CodeString'
+    code .= "# DO NOT EDIT THIS FILE.\n"
+    code .= "#\n"
+    code .= "# This file is generated automatically from\n"
+    code .= "# ?? by c99 --constants \n"
+    code .= "#\n"
+    code .= "# Any changes made here will be lost.\n"
+    code .= "#\n"
+    $P0 = tree.get('pir', node)
+    $S0 = $P0
+    code .= $S0
+    .return (code)
+}
+
+transform pir (C99::CPP::PAST::Node) :language('PIR') {
+    .local pmc code
+    .local pmc iter
+    code = new 'CodeString'
+    iter = node.'child_iter'()
+  iter_loop:
+    unless iter, iter_end
+    $P0 = shift iter
+    $P1 = tree.get('pir', $P0)
+    code .= $P1
+    goto iter_loop
+  iter_end:
+    .return (code)
+}
+
+transform pir (C99::CPP::PAST::IF_SECTION) :language('PIR') {
+    .local pmc code
+    .local pmc iter
+    code = new 'CodeString'
+    iter = node.'child_iter'()
+  iter_loop:
+    unless iter, iter_end
+    $P0 = shift iter
+    $P1 = tree.get('pir', $P0)
+    code .= $P1
+    goto iter_loop
+  iter_end:
+    .return (code)
+}
+
+transform pir(C99::CPP::PAST::IFNDEF) :language('PIR') {
+    .local pmc code
+    .local pmc iter
+    code = new 'CodeString'
+    iter = node.'child_iter'()
+  iter_loop:
+    unless iter, iter_end
+    $P0 = shift iter
+    $P1 = tree.get('pir', $P0)
+    code .= $P1
+    goto iter_loop
+  iter_end:
+    .return (code)
+}
+
+transform pir(C99::CPP::PAST::IFDEF) :language('PIR') {
+    .local pmc code
+    .local pmc iter
+    code = new 'CodeString'
+    iter = node.'child_iter'()
+  iter_loop:
+    unless iter, iter_end
+    $P0 = shift iter
+    $P1 = tree.get('pir', $P0)
+    code .= $P1
+    goto iter_loop
+  iter_end:
+    .return (code)
+}
+
+transform pir(C99::CPP::PAST::IF) :language('PIR') {
+    .local pmc code
+    .local pmc iter
+    code = new 'CodeString'
+    iter = node.'child_iter'()
+  iter_loop:
+    unless iter, iter_end
+    $P0 = shift iter
+    $P1 = tree.get('pir', $P0)
+    code .= $P1
+    goto iter_loop
+  iter_end:
+    .return (code)
+}
+
+transform pir(C99::CPP::PAST::ELIF) :language('PIR') {
+    .local pmc code
+    .local pmc iter
+    code = new 'CodeString'
+    iter = node.'child_iter'()
+  iter_loop:
+    unless iter, iter_end
+    $P0 = shift iter
+    $P1 = tree.get('pir', $P0)
+    code .= $P1
+    goto iter_loop
+  iter_end:
+    .return (code)
+}
+
+transform pir(C99::CPP::PAST::ELSE) :language('PIR') {
+    .local pmc code
+    .local pmc iter
+    code = new 'CodeString'
+    iter = node.'child_iter'()
+  iter_loop:
+    unless iter, iter_end
+    $P0 = shift iter
+    $P1 = tree.get('pir', $P0)
+    code .= $P1
+    goto iter_loop
+  iter_end:
+    .return (code)
+}
+
+
+transform pir(C99::CPP::PAST::DEFINE) :language('PIR') {
+    .local pmc code
+    code = new 'CodeString'
+    $S0 = node.'name'()
+    $S1 = node.'line'()
+    code.'emit'("    .macro_const %0 %1", $S0, $S1)
+    .return (code)
+}
+transform pir(C99::CPP::PAST::DEFINE_FUNCTION) :language('PIR') {
+    .local pmc code
+    code = new 'CodeString'
+    $S0 = node.'name'()
+    $S1 = node.'line'()
+    code.'emit'("    .macro_const %0 = %1", $S0, $S1)
+    .return (code)
+}
+transform pir(C99::CPP::PAST::INCLUDE) :language('PIR') {
+    .local pmc code
+    .return ("")
+}
+transform pir(C99::CPP::PAST::ERROR) :language('PIR') {
+    .local pmc code
+    .return ("")
+}
+transform pir(C99::CPP::PAST::LINE) :language('PIR') {
+    .local pmc code
+    .return ("")
+}
+transform pir(C99::CPP::PAST::PRAGMA) :language('PIR') {
+    .local pmc code
+    .return ("")
+}
+transform pir(C99::CPP::PAST::SOURCE_LINE) :language('PIR') {
+    .local pmc code
+    .return ("")
+}
+transform pir(C99::CPP::PAST::WSNWS) :language('PIR') {
+    .local pmc code
+    .return ("")
+}
+
+=head1 LICENSE
+
+Copyright (C) 2006, Parrot Foundation.
+
+This is free software; you may redistribute it and/or modify
+it under the same terms as Parrot.
+
+=head1 AUTHOR
+
+Kevin Tew <tewk at tewk.com>
+
+=cut

Added: c99/trunk/src/CPP_ASTGrammar.tg
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/CPP_ASTGrammar.tg	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,336 @@
+grammar C99::CPP::ASTGrammar is TGE::Grammar;
+
+transform result (ROOT) :language('PIR') {
+    debug_init
+    
+    .local pmc child
+    $I0 = defined node['group']
+    unless $I0 goto err_no_tree
+    $P0 = node['group']
+    child = tree.get('result', $P0, 'C99::CPP::ASTGrammar::group')
+    .return (child)
+
+  err_no_tree:
+    print "The top-level node doesn't contain an 'group' match.\n"
+    end
+}
+
+transform result (C99::CPP::ASTGrammar::group) :language('PIR') {
+    .local pmc child
+    .local pmc result
+    result = new 'C99::CPP::PAST::Node'
+    result.'init'()
+
+    $I0 = defined node['group_line']
+    unless $I0 goto err_no_tree
+    $P0 = node['group_line']
+
+    .local pmc iter
+    iter = new Iterator, $P0
+  iter_loop:
+    unless iter, iter_end
+    $P1 = shift iter
+    child = tree.get('result', $P1, 'C99::CPP::ASTGrammar::group_line')
+    result.add_child(child)
+    goto iter_loop
+ iter_end:
+    .return (result)
+
+  err_no_tree:
+    $S0 = "The group node doesn't contain an 'group_line' match.\n"
+    print $S0
+    .kdump(node)
+    print $S0
+    end
+}
+
+transform result (C99::CPP::ASTGrammar::group_line) :language('PIR') {
+    .local pmc child
+
+    $I0 = defined node['if_section']
+    unless $I0 goto control_line
+    $P1 = node['if_section']
+    child = tree.get('result', $P1, 'C99::CPP::ASTGrammar::if_section')
+    .return (child)
+
+   control_line:
+     $I0 = defined node['control_line']
+    unless $I0 goto source_line
+    $P1 = node['control_line']
+    child = tree.get('result', $P1, 'C99::CPP::ASTGrammar::control_line')
+    .return (child)
+
+  source_line:
+    $I0 = defined node['source_line']
+    unless $I0 goto wsnws
+    $S0 = node
+    child = new 'C99::CPP::PAST::SOURCE_LINE'
+    child .'init'('line'=>$S0)
+    .return (child)
+
+  wsnws:
+    $I0 = defined node['wsnws']
+    unless $I0 goto err_no_tree
+    $S0 = node
+    child = new 'C99::CPP::PAST::WSNWS'
+    child .'init'('line'=>$S0)
+    .return (child)
+
+   err_no_tree:
+    $S0 = "The group_line node doesn't contain an 'if_section' match.\n"
+    print $S0
+    .kdump(node)
+    print $S0
+    end
+}
+
+transform result (C99::CPP::ASTGrammar::if_section) :language('PIR') {
+    .local pmc child
+    .local pmc result
+    result = new 'C99::CPP::PAST::IF_SECTION'
+    result.'init'('node'=>node)
+
+    $I0 = defined node['if_group']
+    unless $I0 goto err_no_tree
+    $P0 = node['if_group']
+    child = tree.get('result', $P0, 'C99::CPP::ASTGrammar::if_group')
+    result.add_child(child)
+    
+    .local pmc iter
+    $I0 = defined node['elif_group']
+    unless $I0 goto else_group
+    $P0 = node['elif_group']
+    iter = new Iterator, $P0
+  iter_loop:
+    unless iter, iter_end
+    $P1 = shift iter
+    child = tree.get('result', $P1, 'C99::CPP::ASTGrammar::elif_group')
+    result.add_child(child)
+    goto iter_loop
+
+  else_group:
+    $I0 = defined node['else_group']
+    unless $I0 goto return
+    $P0 = node['else_group']
+    child = tree.get('result', $P0, 'C99::CPP::ASTGrammar::else_group')
+    result.add_child(child)
+  iter_end:
+
+  return:
+    .return (result)
+
+  err_no_tree:
+    $S0 = "The if_section node doesn't contain an 'if*_group' match.\n"
+    print $S0 
+    .kdump(node)
+    print $S0
+    end
+}
+
+transform result (C99::CPP::ASTGrammar::if_group) :language('PIR') {
+    .local pmc result
+
+    $I0 = defined node['ifndef']
+    unless $I0 goto ifdef_lbl
+    result = new 'C99::CPP::PAST::IFNDEF'
+    result.'init'('node'=>node)
+    goto parts
+
+  ifdef_lbl:
+    $I0 = defined node['ifdef']
+    unless $I0 goto if_lbl
+    $P0 = node['ifdef']
+    result = new 'C99::CPP::PAST::IFDEF'
+    result.'init'('node'=>node)
+    goto parts
+
+  if_lbl:
+    $I0 = defined node['if']
+    unless $I0 goto err_no_tree
+    $P0 = node['if']
+    result = new 'C99::CPP::PAST::IF'
+    result.'init'('node'=>node)
+    goto parts
+
+  parts:
+    $I0 = defined node['identifier']
+    unless $I0 goto constant_expression
+    $P0 = node['identifier']
+    $S0 = $P0
+    result.'line'($S0)
+  constant_expression:
+    $I0 = defined node['constant_expression']
+    unless $I0 goto group
+    $P0 = node['constant_expression']
+    $S0 = $P0
+    result.'line'($S0)
+  group:
+    $I0 = defined node['group']
+    unless $I0 goto err_no_tree
+    $P0 = node['group' ; 0]
+    $P1= tree.get('result', $P0, 'C99::CPP::ASTGrammar::group')
+    $P2 = $P1.'children'()
+    result.'append_children'($P2)
+    .return (result)
+
+
+  err_no_tree:
+    $S0 = "The if_group node doesn't contain an 'if*' match.\n"
+    print $S0
+    .kdump(node)
+    print $S0
+    end
+}
+
+transform result (C99::CPP::ASTGrammar::elif_group) :language('PIR') {
+    .local pmc result
+
+    $I0 = defined node['elif']
+    unless $I0 goto err_no_tree
+    result = new 'C99::CPP::PAST::ELIF'
+    result.'init'('node'=>node)
+
+    $I0 = defined node['constant_expression']
+    unless $I0 goto err_no_tree
+    $P0 = node['constant_expression']
+    $S0 = $P0
+    result.'line'($S0)
+  group:
+    $I0 = defined node['group']
+    unless $I0 goto err_no_tree
+    $P0 = node['group' ; 0]
+    $P1= tree.get('result', $P0, 'C99::CPP::ASTGrammar::group')
+    $P2 = $P1.'children'()
+    result.'append_children'($P2)
+    .return (result)
+
+
+  err_no_tree:
+    $S0 = "The elif_group node doesn't contain an 'if*' match.\n"
+    print $S0
+    .kdump(node)
+    print $S0
+    end
+}
+
+transform result (C99::CPP::ASTGrammar::elif_group) :language('PIR') {
+    .local pmc result
+
+    $I0 = defined node['elif']
+    unless $I0 goto err_no_tree
+    result = new 'C99::CPP::PAST::ELIF'
+    result.'init'('node'=>node)
+
+    $I0 = defined node['group']
+    unless $I0 goto err_no_tree
+    $P0 = node['group' ; 0]
+    $P1= tree.get('result', $P0, 'C99::CPP::ASTGrammar::group')
+    $P2 = $P1.'children'()
+    result.'append_children'($P2)
+    .return (result)
+
+
+  err_no_tree:
+    $S0 = "The elif_group node doesn't contain an 'if*' match.\n"
+    print $S0
+    .kdump(node)
+    print $S0
+    end
+}
+
+transform result (C99::CPP::ASTGrammar::control_line) :language('PIR') {
+    .local pmc child
+    .local pmc result
+
+    $I0 = defined node['include']
+    unless $I0 goto define_function_lbl
+    result = new 'C99::CPP::PAST::INCLUDE'
+    result.'init'('node'=>node)
+    bsr pp_tokens
+    .return (result)
+
+  define_function_lbl:
+    $I0 = defined node['define_function']
+    unless $I0 goto define_lbl
+    result = new 'C99::CPP::PAST::DEFINE_FUNCTION'
+    result.'init'('node'=>node)
+    $P0 = node['define_function']
+    $S0 = $P0
+    result.'name'($S0)
+    bsr pp_tokens
+    .return (result)
+
+  define_lbl:
+    $I0 = defined node['define']
+    unless $I0 goto undefine_lbl
+    result = new 'C99::CPP::PAST::DEFINE'
+    result.'init'('node'=>node)
+    $I0 = defined node['define_name']
+    unless $I0 goto no_id
+    $P0 = node['define_name']
+    $S0 = $P0
+    result.'name'($S0)
+  no_id:
+    bsr pp_tokens
+    .return (result)
+
+  undefine_lbl:
+    $I0 = defined node['undefine']
+    unless $I0 goto line_lbl
+    result = new 'C99::CPP::PAST::UNDEFINE'
+    bsr pp_tokens
+    .return (result)
+
+  line_lbl:
+    $I0 = defined node['line']
+    unless $I0 goto error_lbl
+    result = new 'C99::CPP::PAST::LINE'
+    result.'init'('node'=>node)
+    bsr pp_tokens
+    .return (result)
+
+  error_lbl:
+    $I0 = defined node['error']
+    unless $I0 goto pragma_lbl
+    result = new 'C99::CPP::PAST::ERROR'
+    result.'init'('node'=>node)
+    bsr pp_tokens
+    .return (result)
+
+  pragma_lbl:
+    $I0 = defined node['pragma']
+    unless $I0 goto err_no_tree
+    result = new 'C99::CPP::PAST::PRAGMA'
+    result.'init'('node'=>node)
+    bsr pp_tokens
+    .return (result)
+
+  pp_tokens:
+    $I0 = defined node['value']
+    unless $I0 goto notoks1
+    $P0 = node['value']
+    $S0 = $P0
+    result.'line'($S0)
+    notoks1:
+    ret
+
+  err_no_tree:
+    print "The control_line node doesn't contain an appropriate match.\n"
+    print $S0
+    .kdump(node)
+    print $S0
+    end
+}
+
+=head1 LICENSE
+
+Copyright (C) 2006, Parrot Foundation.
+
+This is free software; you may redistribute it and/or modify
+it under the same terms as Parrot.
+
+=head1 AUTHOR
+
+Kevin Tew <tewk at tewk.com>
+
+=cut

Added: c99/trunk/src/CPP_PASTNodes.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/CPP_PASTNodes.pir	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,300 @@
+## $Id: CPP_PASTNodes.pir 31862 2008-10-10 18:23:45Z tene $
+
+=head1 NAME
+
+C99::CPP::PAST - Abstract syntax tree nodes for C99
+
+=head1 DESCRIPTION
+
+This file implements the various abstract syntax tree nodes
+needed for C99.  The currently defined ast nodes:
+
+    C99::CPP::PAST::Node       - base class for all ast nodes
+
+=head1 METHODS
+
+=over 4
+
+=cut
+
+.include 'languages/c99/src/preamble'
+
+.HLL 'C99', 'c99_group'
+.namespace [ 'C99';'CPP';'PAST' ]
+
+.sub '__onload' :load
+    .local pmc base, p6meta
+    p6meta = get_hll_global 'P6metaclass'
+    base = p6meta.'new_class'('C99::CPP::PAST::Node','attr'=>'children source pos name line')
+
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::IF_SECTION','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::IFNDEF','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::IFDEF','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::IF','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::ELIF','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::ELSE','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::DEFINE','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::DEFINE_FUNCTION','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::INCLUDE','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::ERROR','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::LINE','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::PRAGMA','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::SOURCE_LINE','parent'=>'C99::CPP::PAST::Node')
+    $P0 = p6meta.'new_class'('C99::CPP::PAST::WSNWS','parent'=>'C99::CPP::PAST::Node')
+
+
+    $P0 = new 'Integer'
+    $P0 = 10
+    set_hll_global ['C99';'CPP';'PAST'], 'serial_number', $P0
+    .return ()
+.end
+
+
+.namespace [ 'C99';'CPP';'PAST';'Node' ]
+
+.sub 'attr' :method
+    .param string attrname
+    .param pmc value
+    .param int setvalue
+    if setvalue goto set
+    value = getattribute self, attrname
+    unless null value goto end
+    value = new .Undef
+  set:
+    setattribute self, attrname, value
+  end:
+    .return (value)
+.end
+
+
+.sub 'init' :method
+    .param pmc children        :slurpy
+    .param pmc adverbs         :slurpy :named
+
+    unless null children goto set_children
+    children = new .ResizablePMCArray
+  set_children:
+    setattribute self, 'children', children
+
+    if null adverbs goto end
+    .local pmc iter
+    iter = new .Iterator, adverbs
+  iter_loop:
+    unless iter goto iter_end
+    $S0 = shift iter
+    if $S0 == 'XXX' goto iter_loop
+    $P0 = iter[$S0]
+    $P1 = find_method self, $S0
+    self.$P1($P0)
+    goto iter_loop
+  iter_end:
+  end:
+    .return ()
+.end
+
+
+.sub 'new' :method
+    .param string class
+    .param pmc children        :slurpy
+    .param pmc adverbs         :slurpy :named
+
+    $P0 = new class
+    $P0.'init'(children :flat, 'node'=>self, 'XXX'=>1, adverbs :flat :named)
+    .return ($P0)
+.end
+
+
+.sub 'add_child' :method
+    .param pmc child
+    .local pmc array
+    array = getattribute self, 'children'
+    push array, child
+    .return ()
+  .end
+
+.sub 'append_children' :method
+    .param pmc children
+    .local pmc array
+    array = getattribute self, 'children'
+    array.'append'(children)
+    .return ()
+.end
+
+
+.sub 'add_child_new' :method
+    .param string class
+    .param pmc children        :slurpy
+    .param pmc adverbs         :slurpy :named
+    $P0 = self.'new'(class, children :flat, 'XXX'=>0, adverbs :flat :named)
+    self.'add_child'($P0)
+    .return ($P0)
+.end
+
+.gen_accessor('source')
+.gen_accessor('pos')
+.gen_accessor('name')
+.gen_accessor('line')
+.gen_get_accessor('children')
+
+.sub 'children' :method
+#    .param pmc value :optional
+#    .param int has_value        :opt_flag
+    null $P0
+    .return self.'attr'('children', $P0, 0)
+.end
+
+.sub 'node' :method
+    .param pmc node
+    $I0 = isa node, ['C99';'CPP';'PAST';'Node']
+    if $I0 goto clone_past
+  clone_pge:
+    $S0 = node
+    self.'source'($S0)
+    $I0 = node.'from'()
+    self.'pos'($I0)
+    .return ()
+  clone_past:
+    $S0 = node.'source'()
+    self.'source'($S0)
+    $I0 = node.'pos'()
+    self.'pos'($I0)
+    .return ()
+.end
+
+
+.sub 'child_iter' :method
+    $P0 = getattribute self, 'children'
+    $P1 = new .Iterator, $P0
+    $P1 = 0
+    .return ($P1)
+.end
+
+
+=item C<C99::CPP::PAST::Node::unique([string fmt])>
+
+Each call to C<unique> returns a unique number, or if a C<fmt>
+parameter is given it returns a unique string beginning with
+C<fmt>.  (This may eventually be generalized to allow
+uniqueness anywhere in the string.)  The function starts
+counting at 10 (so that the values 0..9 can be considered "safe").
+
+=cut
+
+.sub 'unique' :method
+    .param string fmt          :optional
+    .param int has_fmt         :opt_flag
+
+    if has_fmt goto unique_1
+    fmt = ''
+  unique_1:
+    $P0 = get_hll_global ['C99';'CPP';'PAST'], 'serial_number'
+    $S0 = $P0
+    $S0 = concat fmt, $S0
+    inc $P0
+    .return ($S0)
+.end
+
+
+.sub '__elements' :method
+    $P0 = getattribute self, 'children'
+    $I0 = elements $P0
+    .return ($I0)
+.end
+
+
+.sub '__get_pmc_keyed_int' :method
+    .param int key
+    $P0 = getattribute self, 'children'
+    $P0 = $P0[key]
+    .return ($P0)
+.end
+
+
+.sub '__set_pmc_keyed_int' :method
+    .param int key
+    .param pmc val
+    $P0 = getattribute self, 'children'
+    $P0[key] = val
+    .return ()
+.end
+
+.sub '__get_string' :method
+    $P0 = getattribute self, 'name'
+    $S0 = $P0
+    .return ($S0)
+.end
+
+
+.sub '__dumplist' :method
+    .return ('pos name children')
+.end
+
+
+.sub '__dump' :method
+    .param pmc dumper
+    .param string label
+    .local string indent, subindent
+
+    (subindent, indent) = dumper.'newIndent'()
+    print '=> { '
+.local pmc attrlist, iter
+    $S0 = self.'__dumplist'()
+    attrlist = split ' ', $S0
+    iter = new .Iterator, attrlist
+  iter_loop:
+    unless iter goto iter_end
+    .local string attrname
+    .local pmc val
+    attrname = shift iter
+    val = getattribute self, attrname
+    print "\n"
+    print subindent
+    print attrname
+    print ' => '
+    dumper.'dump'(label, val)
+    goto iter_loop
+  iter_end:
+    print "\n"
+    print indent
+    print '}'
+    dumper.'deleteIndent'()
+    .return ()
+.end
+
+
+.namespace [ 'C99';'CPP';'PAST';'Node' ]
+.gen_dumplist('children')
+.namespace [ 'C99';'CPP';'PAST';'IF_SECTION' ]
+.gen_dumplist('children')
+.namespace [ 'C99';'CPP';'PAST';'IFNDEF' ]
+.gen_dumplist('line children')
+.namespace [ 'C99';'CPP';'PAST';'IFDEF' ]
+.gen_dumplist('line children')
+.namespace [ 'C99';'CPP';'PAST';'IF' ]
+.gen_dumplist('line children')
+.namespace [ 'C99';'CPP';'PAST';'ELIF' ]
+.gen_dumplist('line children')
+.namespace [ 'C99';'CPP';'PAST';'ELSE' ]
+.gen_dumplist('children')
+.namespace [ 'C99';'CPP';'PAST';'DEFINE' ]
+.gen_dumplist('name line')
+.namespace [ 'C99';'CPP';'PAST';'DEFINE_FUNCTION' ]
+.gen_dumplist('name line')
+.namespace [ 'C99';'CPP';'PAST';'INCLUDE' ]
+.gen_dumplist('line')
+.namespace [ 'C99';'CPP';'PAST';'ERROR' ]
+.gen_dumplist('line')
+.namespace [ 'C99';'CPP';'PAST';'LINE' ]
+.gen_dumplist('line')
+.namespace [ 'C99';'CPP';'PAST';'PRAGMA' ]
+.gen_dumplist('line')
+.namespace [ 'C99';'CPP';'PAST';'SOURCE_LINE' ]
+.gen_dumplist('line')
+.namespace [ 'C99';'CPP';'PAST';'WSNWS' ]
+.gen_dumplist('line')
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:

Added: c99/trunk/src/CPP_PGE2AST.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/CPP_PGE2AST.pir	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,92 @@
+.namespace [ 'C99';'CPP';'ASTGrammar' ]
+
+.include 'languages/c99/src/preamble'
+.include 'languages/c99/src/CPP_ASTGrammar.pir'
+.include "iterator.pasm"
+
+.sub '__onload' :load
+    $P0 = get_class ['C99';'CPP';'ASTGrammar']
+    if null $P0 goto error
+    addattribute $P0, 'scope_stack'
+    .return ()
+error:
+    print "C99::CPP::ASTGrammar class not found\n"
+    end
+.end
+
+.sub 'attr' :method
+    .param string attrname
+    .param pmc value
+    .param int setvalue
+    if setvalue goto set
+    value = getattribute self, attrname
+    unless null value goto end
+    value = new .Undef
+  set:
+    setattribute self, attrname, value
+  end:
+    .return (value)
+.end
+
+.sub 'scope_stack' :method
+    .param pmc attr           :optional
+    .param int has_attr       :opt_flag
+    .local pmc value
+    value = self.'attr'('scope_stack', attr, has_attr)
+    $I0 = defined value
+    if $I0 goto end
+    value = new .ResizablePMCArray
+    value = self.'attr'('scope_stack', value, 1)
+  end:
+    .return (value)
+.end
+
+.sub 'push_scope_stack' :method
+    .param pmc value
+    .local pmc stack
+    stack = self.'scope_stack'()
+    push stack, value
+    .return (value)
+.end
+
+.sub 'pop_scope_stack' :method
+    .local pmc value
+    .local pmc stack
+    stack = self.'scope_stack'()
+    value = pop stack
+    .return (value)
+.end
+
+.sub 'top_scope_stack' :method
+    .local pmc value
+    .local pmc stack
+    stack = self.'scope_stack'()
+    $I0 = elements stack
+    unless $I0 goto end
+    $I0 -= 1
+    value = stack[$I0]
+    .return (value)
+  end:
+    print "Error: top_scope_stack is empty"
+    end
+.end
+
+.sub 'add_to_current_block' :method
+    .param string key
+    .param pmc value
+    .local pmc scope
+    scope = self.'top_scope_stack'()
+    $I0 = isa scope, ['Cardinal';'PAST';'Block']
+    unless $I0 goto end
+    scope.'vardecl'(key, value)
+    .return ()
+  end:
+    print "Error: top_scope_stack is empty"
+    end
+.end
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:

Added: c99/trunk/src/builtins/say.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/builtins/say.pir	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,82 @@
+# $Id: say.pir 27878 2008-05-28 14:44:03Z Whiteknight $
+
+=head1
+
+say.pir -- simple implementation of a say function
+
+=cut
+
+.namespace []
+
+.sub 'say'
+    .param pmc args            :slurpy
+    .local pmc iter
+    iter = new 'Iterator', args
+  iter_loop:
+    unless iter goto iter_end
+    $P0 = shift iter
+    print $P0
+    goto iter_loop
+  iter_end:
+    print "\n"
+    .return ()
+.end
+
+.sub 'printf'
+    .param pmc format
+    .param pmc args   :slurpy
+    .local pmc iter
+    iter = new 'Iterator', args
+  iter_loop:
+    unless iter goto iter_end
+    goto iter_loop
+  iter_end:
+.end
+
+.sub 'puts'
+    .param pmc str
+    print str
+    print "\n"
+.end
+
+.sub 'infix:<'
+    .param pmc a
+    .param pmc b
+    islt $I0, a, b
+    .return ($I0)
+.end
+
+.sub 'postfix:++'
+    .param pmc arg
+    $P0 = clone arg
+    inc $P0
+    .return (arg)
+.end
+
+.sub 'postfix:--'
+    .param pmc arg
+    $P0 = clone arg
+    dec $P0
+    .return (arg)
+.end
+
+.sub 'prefix:++'
+    .param pmc arg
+    inc arg
+    .return (arg)
+.end
+
+.sub 'prefix:--'
+    .param pmc arg
+    dec arg
+    .return (arg)
+.end
+
+
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+

Added: c99/trunk/src/c99.pg
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/c99.pg	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,581 @@
+#taken from n869.pdf
+#google for n869.pdf
+
+## A.1 Lexical grammar
+grammar C99::Grammar;
+
+## A.1.1 Lexical elements
+token ws {
+  [
+  | <'//'> \N* \n
+  | <'/*'> .*? <'*/'>
+  | \s+
+  ]*
+}
+
+rule c99_token {
+  | <keyword>
+  | <identifier>
+  | <constant>
+  | <string_literal>
+  | <punctuator>
+}
+
+token pound { <'\#'> }
+
+regex preprocessing_token {
+  | <header_name>
+  | <identifier>
+  | <pp_number>
+  | <character_constant>
+  | <string_literal>
+  | <!pound> <punctuator>
+  | <universal_character_name>
+  | <-[# \r\n\t]>\S* ## <-[#]-\S>\S* ##non-whitespace
+}
+
+## A.1.2 Keywords
+token keyword {
+  | auto      | enum      | restrict  | unsigned
+  | break     | extern    | return    | void
+  | case      | float     | short     | volatile
+  | char      | for       | signed    | while
+  | const     | goto      | sizeof    | _Bool
+  | continue  | if        | static    | _Complex
+  | default   | inline    | struct    | _Imaginary
+  | do        | int       | switch
+  | double    | long      | typedef
+  | else      | register  | union
+
+}
+
+## A.1.3 Identifiers
+#token identifier { <identifier_nondigit> [ <identifier_nondigit> | \d ]* }
+token identifier { <?identifier_nondigit> [ <?identifier_nondigit> | <?digit> ]* }
+
+token identifier_nondigit { <alpha> | <[_]> | <universal_character_name> }
+
+## A.1.4 Universal character names
+token universal_character_name {
+  | <'\u'> <xdigit>**{4}
+  | <'\U'> <xdigit>**{8}
+}
+
+## A.1.5 Constants
+token constant {
+  | <integer_constant>
+  | <floating_constant>
+  | <enumeration_constant>
+  | <character_constant>
+}
+
+token integer_constant {
+  [ <decimal_constant>
+  | <octal_constant>
+  | <hexadecimal_constant>
+  ] <integer_sufffix>?
+}
+
+token decimal_constant     { <[1..9]> <digit>   }
+#token decimal_constant     { <[1..9]> \d*       }
+token octal_constant       { 0 <[0..7]>+        }
+token hexadecimal_constant { 0 <[xX]> <xdigit>+ }
+
+token integer_suffix {
+  | <[uU]> [ll?|LL?]?
+  | [ll?|LL?] <[uU]>?
+}
+
+token floating_constant {
+  | <decimal_floating_constant>
+  | <hexadecimal_floating_constant>
+}
+
+token decimal_floating_constant {
+  [ <fractional_constant> <exponent_part>?
+  | <digit_sequence> <exponent_part> 
+  ] <floating_suffix>?
+}
+
+token hexadecimal_prefix
+{
+  0 <[xX]>
+}
+
+token hexadecimal_floating_constant {
+  <hexadecimal_prefix> 
+  [ <hexadecimal_fractional_constant>
+  | <hexadecimal_digit_constant>
+  ] <binary_exponent_part> <floating_suffix>?
+}
+
+token fractional_constant {
+  | <digit_sequence>? \. <digit_sequence>
+  | <digit_sequence> \.
+}
+
+token exponent_part {
+  <[eE]> <[\+\-]>? <digit_sequence>
+}
+
+#token digit_sequence { \d+ }
+token digit_sequence { <digit>+ }
+
+token hexadecimal_fractional_constant {
+  | <hexadecimal_digit_sequence>? \. <hexadecimal_digit_sequence>
+  | <hexadecimal_digit_sequence> \.
+}
+
+token binary_exponent_part {
+  <[pP]> <[\+\-]>? <digit_sequence>
+}
+
+token hexadecimal_digit_sequence { <xdigit>+ }
+
+token floating_suffix { <[fFlL]> }
+
+token enumeration_constant { <identifier> }
+
+token character_constant { <[L]>? \' <c_char>+ \' }
+
+token <c_char> { <-['\\\n]> | <escape_sequence> }
+
+token escape_sequence {
+  \\
+  [ <['"?\\abfnrtv]>
+  | <octal_digit>**{1..3}
+  | x <xdigit>+
+  | <universal_character_name>
+  ]
+}
+
+## A.1.6 String literals
+token string_literal { <[L]>? " <s_char>* " }
+
+token s_char { <-["\\\n]> | <escape_sequence> }
+
+## A.1.7 Punctuators
+token punctuator {
+  | \[        | \]        | <[(){}.]>   | <'->'>
+  | <'++'>    | <'--'>    | <[&*+\-~!/%]>
+  | <'<<'>    | <'>>'>    | <[<>]>
+  | <'<='>    | <'>='>    | <'=='>   | <'!='>
+  | <[^|]>    | <'&&'>    | <'||'>
+  | <[?:;]>   | <'...'>
+  | [ <[*/%+\-&^|]> | <'<<'> | <'>>'> ] <'='>
+  | <[,#]>    | <'##'>
+  | <'<:'>    | <':>'>    | <'<%'>   | <'%>'>   | <'%:'>   | <'%:%:'>
+}
+
+## A.1.8 Header names
+token header_name {
+  | \< $<name:>=<?h_char>+ \>
+  | " $<name>:=<?q_char>+ "
+}
+
+token h_char { <-[\n>]> }
+token q_char { <-[\n"]> }
+
+## A.1.9 Preprocessing numbers
+token pp_number { \.? \d [ \d | <identifier_nondigit> | <[eEpP]> <[\+\-]> | \. ]* }
+
+## A.2 Phrase structure grammar
+## XXX: see below
+
+## A.2.2 Declarations
+rule declaration { <declaration_specifier>+ <init_declarator_list>? ; }
+
+rule declaration_specifier {
+  | <storage_class_specifier>
+  | <type_specifier>
+  | <type_qualifier>
+  | <function_specifier>
+}
+
+rule init_declarator_list { init_declarator [ , <init_declarator> ]* }
+
+rule init_declarator { <declarator> [ = <initializer> ]? }
+
+token storage_class_specifier { typedef | extern | static | auto | register }
+
+rule type_specifier {
+  | void      | char    | short     | int
+  | long      | float   | double    | signed
+  | unsigned  | _Bool   | _Complex  | _Imaginary
+  | <struct_or_union_specifier>
+  | <enum_specifier>
+  | <typedef_name>
+}
+
+rule struct_or_union_specifier {
+  [ $<struct>:=<'struct'> | $<union>:=<'union'> ] [ <identifier> | <identifier>? \{ <struct_declaration>+ \} ]
+}
+
+rule struct_declaration { [<type_specifier>|<type_qualifier>]+ <struct_declarator>+ ; }
+
+rule struct_declarator { <declarator> | <declarator>? : <constant_expression> }
+
+rule enum_specifier { enum [ <identifier>? \{ <enumerator> [ , <enumerator> ]+ [,]? \}| <identifier> ] }
+
+rule enumerator { <enumeration_constant> [ = <constant_expression> ]? }
+
+token type_qualifier { const | restrict  | volatile }
+
+token function_specifier { inline }
+
+rule declarator { <pointer>? <direct_declarator> }
+
+rule direct_declarator {
+  [ <identifier> | \( <declarator> \) ]
+  [
+    | \[ <assignment_expression>? \]
+    | \[ \* \]
+    | \( <parameter_type_list> \)
+    | \( <identifier_list>? \)
+  ]*
+}
+
+rule pointer { [\* <type_qualifier>* ]+ }
+
+rule parameter_type_list { <parameter_declaration> [ , <parameter_declaration> ]* [ , <'...'>]? }
+
+rule parameter_declaration { <declaration_specifier>+ [ <declarator> | <abstract_declatator> ]? }
+
+rule identifier_list { <identifier> [ , <identifier> ]* }
+
+rule type_name { <specifier_qualifier_list> <abstract_declatator>? }
+
+rule abstract_declatator {
+  <pointer>? <direct_abstract_declarator>
+  |<pointer>
+}
+
+rule direct_abstract_declarator {
+  [
+    | \( <abstract_declatator> \) 
+    | \[ <assignment_expression>? \]
+    | \( <parameter_type_list> \) 
+  ] 
+  <direct_abstract_declarator_1>*
+}
+
+rule direct_abstract_declarator_1 {
+  | \[ <assignment_expression>? \]
+  | \[ * \]
+  | \( <parameter_type_list> \)
+}
+
+rule typedef_name { <identifier> }
+
+rule initializer { <assignment_expression> | \{ <initializer_list> [,]? \} }
+
+rule initializer_list { <designation>? <initializer> [, <designation>? <initializer> ]* }
+
+rule designation { <designator>+ = }
+
+rule designator { 
+  | \[ <constant_expression> \]
+  | \. <identifier>
+}
+
+## A.2.3 Statements
+rule statement {
+  | <labeled_statement>
+  | <compound_statement>
+  | <expression_statement>
+  | <selection_statement>
+  | <iteration_statement>
+  | <jump_statement>
+}
+
+rule labeled_statement {
+  [ <identifier> \:
+  | case <constant_expression> \:
+  | default \:
+  ] <statement>
+}
+
+rule compound_statement { \{ [ <declaration> | <statement> ]* \} }
+
+rule expression_statement { <expression>? ; }
+
+rule selection_statement {
+  | if \( <expresssion> \) <statement> [else <statement>]?
+  | switch \( <expression> \) <statement>
+}
+
+rule iteration_statement {
+  | while \( <expression> \) <statement>
+  | do <statement> while \( <expression> \) ;
+  | for \( [ <expression>? ; <expression>? ; <expression>? | <declaration> <expression>? ; <expression>? ] \) <statement>
+}
+
+rule jump_statement {
+  | goto <identifier> ;
+  | continue ;
+  | break ;
+  | return <expression>? ;
+}
+
+
+## A.2.4 External definitions
+rule translation_unit { [ <function_definition> | <declaration> ]+ }
+
+rule function_definition { <declaration_specifier>+ <declarator> <declaration>* <compound_statement> }
+
+
+## A.3 preprocessing directives
+token wsnws {
+  <?ws_minus_n>? \n <?ws>?
+}
+
+regex prereprocessing_file { <group> }
+
+regex group { <group_line>+ }
+
+regex group_line {
+  | <if_section>
+  | <control_line>
+  | <source_line>? $<wsnws>:=<?wsnws>
+}
+
+regex source_line {
+  <?pp_tokens>
+}
+
+
+rule if_section { <if_group> <elif_group>* <else_group>? <endif_line> }
+
+token ws_minus_n
+{
+  [
+  | <'//'> \N* \n
+  | <'/*'> .*? <'*/'>
+  | \t 
+  | <' '>
+  ## | <\s-<[\n]>
+  ]*
+}
+
+regex if_group {
+  [ 
+  | \# <?ws>? $<ifndef>:=<'ifndef'> <?ws> <identifier>
+  | \# <?ws>? $<ifdef>:=<'ifdef'> <?ws> <identifier>
+  | \# <?ws>? $<if>:=<'if'> <?ws> <constant_expression>
+  ] <?wsnws> <group>?
+}
+
+regex elif_group { \# <?ws> $<elif>:=<'elif'> <?ws> <constant_expression> <?wsnws> <group>? }
+regex else_group { \# <?ws> $<else>:=<'else'> <?wsnws> <group>? }
+regex endif_line { \# <?ws> $<endif>:=<'endif'> <?wsnws> }
+regex control_line {
+  | \# <?ws>? $<include>:=<'include'> <?ws_minus_n> $<value>:=<pp_tokens> <?wsnws>
+  | \# <?ws>? $<define>:=<'define'> <?ws>
+    [ 
+      | $<define_name>:=<identifier>
+      | $<define_function>:=(<identifier_p> [ <identifier_list> [, \.\.\.]? | [ \.\.\.] ]? \)) 
+    ] <?ws_minus_n>? $<value>:=<pp_tokens>?
+  | \# ?<ws>? $<undefine>:=<'undefine'> <?ws_minus_n> <identifier> <?wsnws>
+  | \# ?<ws>? $<line>:=<'line'> <?ws_minus_n> $<value>:=<pp_tokens> <?wsnws>
+  | \# ?<ws>? $<error>:=<'error'> <?ws_minus_n> $<value>:=<pp_tokens>? <?wsnws>
+  | \# ?<ws>? $<pragma>:=<'pragma'> <?ws_minus_n> $<value>:=<pp_tokens>? <?wsnws>
+  | \# <?wsnws>
+
+}
+
+token identifier_p { <identifier> \( }
+regex pp_tokens { <preprocessing_token> [<?ws_minus_n> <preprocessing_token>]* }
+
+
+## A.2.1 Expressions
+rule primary_expression {
+  | <identifier>
+  | <constant>
+  | <string_literal>
+  | \( <expression> \)
+}
+
+rule postfix_expression {
+  [ <primary_expression> 
+  | \( <type_name> \) \{ <initializer_list> [\,]? \} ]
+
+  [ <'++'>
+  | <'--'>
+  | \[ <expression> \]
+  | \( [ <assignment_expression> [ \, <assignment_expression> ]* ]? \)
+  | \. <identifier>
+  | <'->'> <identifier>
+  | \( <type_name> \) \{ <initializer_list> [\,]? \}
+  ]*
+}
+
+rule unary_expression {
+  [<'++'>|<'--'>|<'sizeof'>]? 
+
+  [ <postfix_expression>
+  | $<unary_op>:=<[&*+\-~!]> <cast_expression>
+  | <'sizeof'> \( <type_name> \)
+  ]
+}
+
+rule cast_expression {  [ \( <type_name> \) ]* <unary_expression> }
+
+#proto 'term:' is precedence('22=')
+#    is parsed(primary_expression)
+#    is pastrule('past_term') { ... }
+
+## postfix expressions
+#proto 'postfix:++' is precedence('20=') { ... }
+#proto 'postcircumfix:[]' is equiv('postfix:++') { ... }
+#rule postfix_expression { <postfix_expression> \[ <expression> \] }
+#proto 'postcircumfix:()' is equiv('postfix:++') { ... }
+#rule postfix_expression { <postfix_expression> \( [ <assignment_expression> [\, <assignment_expression>]* ]? \) }
+#proto 'infix:.' is equiv('postfix:++') { ... }
+#rule postfix_expression { <postfix_expression> . <identifier> }
+#proto 'infix:->' is equiv('postfix:++') { ... }
+#rule postfix_expression { <postfix_expression> \-\> <identifier> }
+#proto 'postfix:--' is equiv('postfix:++') { ... }
+#rule postfix_expression { \( <type_name> \) \{ <initializer_list> [,]? \} }
+
+## unary-expression
+#proto 'prefix:++' is precedenc('18=') { ... }
+#proto 'prefix:--' is equiv('prefix:++') { ... }
+#proto 'prefix:&' is equiv('prefix:++') { ... }
+#proto 'prefix:*' is equiv('prefix:++') { ... }
+#proto 'prefix:+' is equiv('prefix:++') { ... }
+#proto 'prefix:-' is equiv('prefix:++') { ... }
+#proto 'prefix:~' is equiv('prefix:++') { ... }
+#proto 'prefix:!' is equiv('prefix:++') { ... }
+#proto 'prefix:sizeof' is equiv('prefix:++') { ... }
+#proto 'prefix:sizeof' is equiv('prefix:++') { ... }
+#rule unary_expression { sizeof  <unary_expression> }
+#rule unary_expression { sizeof [\( <type_name> \) ] }
+
+## cast-expression
+## XXX: PGE doesn't have a precircumfix:() function (yet?)
+#proto 'precircumfix:()' is precedence('17=') {...}
+#rule cast_expression { [\( <type_name> \) ]* <unary_expression> }
+
+proto 'term:' is precedence('22=')
+    is parsed(cast_expression)
+    is pastrule('cast_expression') { ... }
+
+## multiplicative
+proto 'infix:*' is precedence('16=')
+    is post('mul')
+    { ... }
+
+proto 'infix:/' is equiv('infix:*')
+    is post('div')
+    { ... }
+
+proto 'infix:%' is equiv('infix:*')
+    is post('mod')
+    { ... }
+
+## additive
+proto 'infix:+' is precedence('16=')
+    is post('add')
+    { ... }
+
+proto 'infix:-' is equiv('infix:+')
+    is post('sub')
+    { ... }
+
+
+## shift-expression
+proto 'infix:<<' is precedence('15=') { ... }
+proto 'infix:>>' is precedence('15=') { ... }
+
+
+## relational-expression
+## chaining binary
+proto 'infix:<' is equiv('14=') is assoc('chain')
+    is pasttype('chain')
+    { ... }
+
+proto 'infix:<=' is equiv('infix:<')
+    is pasttype('chain')
+    { ... }
+
+proto 'infix:>' is equiv('infix:<')
+    is pasttype('chain')
+    { ... }
+
+proto 'infix:>=' is equiv('infix:<')
+    is pasttype('chain')
+    { ... }
+
+# equality-expression
+proto 'infix:==' is precedence('13=') is assoc('chain')
+    is pasttype('chain')
+    { ... }
+
+proto 'infix:!=' is equiv('infix:==')
+    is pasttype('chain')
+    { ... }
+
+
+proto 'infix:&' is precedence('12=') { ... }
+proto 'infix:^' is precedence('11=') { ... }
+proto 'infix:|' is precedence('10=') { ... }
+
+proto 'infix:&&' is precedence('09=')
+    is pasttype('cond') 
+    { ... }
+
+proto 'infix:||' is precedence('08=')
+    is pasttype('cond') 
+    { ... }
+
+## ternary
+#proto 'ternary:? :' is precedence('07=') is assoc('right')
+#    is pasttype('cond') 
+#    is parsed('conditional_expression')
+#    { ... }
+
+rule operator_precedence_parser { {{ 
+  .local pmc optable
+  .local pmc match_result
+  #optable = get_hll_namespace ['Cardinal'; 'Grammar']
+  optable = get_root_global [ 'parrot'; 'C99'], '$optable'
+  match_result = optable."parse"(match)
+  .return (match_result)
+}} }
+
+rule conditional_expression { <operator_precedence_parser> [ \? <expression> : <operator_precedence_parser> ]* }
+
+rule assignment_expression { [ <unary_expression> <assignment_operator> ]* <constant_expression> }
+
+token assignment_operator {
+  | <'*='>
+  | <'/='>
+  | <'%='>
+  | <'+='>
+  | <'-='>
+  | <'<<='>
+  | <'>>='>
+  | <'&='>
+  | <'^='>
+  | <'|='>
+}
+
+rule expression { <assignment_expression> [, <assignment_expression> ] }
+rule constant_expression { <conditional_expression> }
+
+## assignment
+#proto 'infix:=' is precedence('06=') is assoc('right')
+#    is parsed('assignment_expression')
+#    is pasttype('assign') 
+#    { ... }
+
+#proto 'infix:*=' is equiv('infix:=') is parsed('assignment_expression') { ... }
+#proto 'infix:/=' is equiv('infix:=') is parsed('assignment_expression') { ... }
+#proto 'infix:%=' is equiv('infix:=') is parsed('assignment_expression') { ... }
+#proto 'infix:+=' is equiv('infix:=') is parsed('assignment_expression') { ... }
+#proto 'infix:-=' is equiv('infix:=') is parsed('assignment_expression') { ... }
+#proto 'infix:<<=' is equiv('infix:=') is parsed('assignment_expression') { ... }
+#proto 'infix:>>=' is equiv('infix:=') is parsed('assignment_expression') { ... }
+#proto 'infix:&=' is equiv('infix:=') is parsed('assignment_expression') { ... }
+#proto 'infix:^=' is equiv('infix:=') is parsed('assignment_expression') { ... }
+#proto 'infix:|=' is equiv('infix:=') is parsed('assignment_expression') { ... }

Added: c99/trunk/src/c99_PGE.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/c99_PGE.pir	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,60 @@
+=head1 NAME
+
+C99::Grammar -- A grammar for parsing C99
+
+=head1 SYNOPSYS
+
+=head1 DESCRIPTION
+
+This is a grammar to parse c99 programs. It inherits the behavior
+of the PGE::Grammar class. It parses a string of source code according to
+its hierarchy of rules and returns a PGE::Match object (a parse tree).
+
+=cut
+
+#.HLL 'C99', 'c99y_group'
+#.namespace [ 'C99'; 'Grammar' ]
+.namespace [ 'C99';'Grammar' ]
+
+.sub _load :load
+    load_bytecode 'PGE.pbc'
+    load_bytecode 'PGE/Text.pbc'
+.end
+
+# Pull in the compiled grammar
+.include "languages/c99/src/c99_grammar_gen.pir"
+.sub '__onload' :load
+    $P0 = get_hll_global ['C99';'Grammar'], '$optable'
+    $P1 = get_hll_global ['C99';'Grammar'], 'ws'
+    setattribute $P0, '&!ws', $P1
+    $P0 = new .Hash
+.end
+
+# Operator precedence parsing rule
+.sub "operator_precedence_parser"
+  .param pmc match_object
+  .local pmc optable
+  #optable = get_hll_namespace ['C99'; 'Grammar']
+  optable = get_root_global [ 'parrot'; 'C99';'Grammar'], '$optable'
+  $P0 = optable."parse"(match_object)
+  .return ($P0)
+.end
+
+=head1 LICENSE
+
+Copyright (C) 2005-2008, Parrot Foundation.
+
+This is free software; you may redistribute it and/or modify
+it under the same terms as Parrot.
+
+=head1 AUTHOR
+
+Kevin Tew <kevintew at tewk.com>
+
+=cut
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:

Added: c99/trunk/src/cpp/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/cpp/Makefile	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,106 @@
+# ex: set ro:
+# DO NOT EDIT THIS FILE
+# Generated by Parrot::Configure::Compiler from languages/c99/config/makefiles/cpp.in
+
+# Copyright (C) 2008-2009, Parrot Foundation.
+## $Id: cpp.in 36833 2009-02-17 20:09:26Z allison $
+
+## arguments we want to run parrot with
+PARROT_ARGS   =
+
+## configuration settings
+BUILD_DIR     = /home/allison/projects/svn/parrot
+LOAD_EXT      = .so
+O             = .o
+
+## Setup some commands
+PERL          = /usr/bin/perl
+RM_F          = $(PERL) -MExtUtils::Command -e rm_f
+CP            = $(PERL) -MExtUtils::Command -e cp
+CAT           = $(PERL) -MExtUtils::Command -e cat
+PARROT        = ../../../../parrot
+BUILD_DYNPMC  = $(PERL) $(BUILD_DIR)/tools/build/dynpmc.pl
+RECONFIGURE   = $(PERL) $(BUILD_DIR)/tools/dev/reconfigure.pl
+
+## places to look for things
+PARROT_DYNEXT = $(BUILD_DIR)/runtime/parrot/dynext
+PGE_LIBRARY   = $(BUILD_DIR)/runtime/parrot/library/PGE
+PERL6GRAMMAR  = $(PGE_LIBRARY)/Perl6Grammar.pbc
+NQP           = $(BUILD_DIR)/compilers/nqp/nqp.pbc
+PCT           = $(BUILD_DIR)/runtime/parrot/library/PCT.pbc
+
+PMC_DIR       = src/pmc
+
+all: cpp.pbc
+
+SOURCES = cpp.pir \
+  src/gen_grammar.pir \
+  src/gen_actions.pir \
+  src/gen_builtins.pir
+
+BUILTINS_PIR = \
+  src/builtins/say.pir
+
+# the default target
+cpp.pbc: $(PARROT) $(SOURCES)
+	$(PARROT) $(PARROT_ARGS) -o cpp.pbc cpp.pir
+	$(CP) cpp.pbc ../../cpp.pbc
+
+src/gen_grammar.pir: $(PERL6GRAMMAR) src/parser/grammar.pg
+	$(PARROT) $(PARROT_ARGS) $(PERL6GRAMMAR) \
+	    --output=src/gen_grammar.pir \
+	    src/parser/grammar.pg
+
+src/gen_actions.pir: $(NQP) $(PCT) src/parser/actions.pm
+	$(PARROT) $(PARROT_ARGS) $(NQP) --output=src/gen_actions.pir \
+	    --target=pir src/parser/actions.pm
+
+src/gen_builtins.pir: $(BUILTINS_PIR)
+	$(CAT) $(BUILTINS_PIR) >src/gen_builtins.pir
+
+# regenerate the Makefile
+Makefile: ../../config/makefiles/cpp.in
+	cd $(BUILD_DIR) && $(RECONFIGURE) --step=gen::languages --languages=c99
+
+# 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:               c.pbc"
+	@echo "                     This is the default."
+	@echo "Testing:"
+	@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 ""
+	@echo "Misc:"
+	@echo "  help:              Print this help message."
+	@echo ""
+
+test: all
+	$(PERL) t/harness
+
+# this target has nothing to do
+testclean:
+
+CLEANUPS = \
+  cpp.pbc \
+  "src/gen_*.pir"
+
+clean:
+	$(RM_F) $(CLEANUPS)
+
+realclean: clean
+	$(RM_F) Makefile
+
+distclean: realclean
+
+# Local variables:
+#   mode: makefile
+# End:
+# vim: ft=make:

Added: c99/trunk/src/cpp/cpp.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/cpp/cpp.pir	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,80 @@
+# $Id: cpp.pir 36833 2009-02-17 20:09:26Z allison $
+# Copyright (C) 2008, Parrot Foundation.
+
+=head1 TITLE
+
+cpp.pir - A C pre processor.
+
+=head2 Description
+
+This is the base file for the C99 C pre processor.
+
+This file includes the parsing and grammar rules from
+the src/ directory, loads the relevant PGE libraries,
+and registers the compiler under the name 'C99::CPP'.
+
+=head2 Functions
+
+=over 4
+
+=item onload()
+
+Creates the C compiler using a C<PCT::HLLCompiler>
+object.
+
+=cut
+
+.namespace [ 'C99';'CPP';'Compiler' ]
+
+.loadlib 'c99_group'
+
+.sub 'onload' :anon :load :init
+    load_bytecode 'PCT.pbc'
+
+    $P0 = get_hll_global ['PCT'], 'HLLCompiler'
+    $P1 = $P0.'new'()
+    $P1.'language'('C99::CPP')
+    $P1.'parsegrammar'('C99::CPP::Grammar')
+    $P1.'parseactions'('C99::CPP::Grammar::Actions')
+.end
+
+=item main(args :slurpy)  :main
+
+Start compilation by passing any command line C<args>
+to the C compiler.
+
+=cut
+
+.sub 'main' :main
+    .param pmc args
+
+    $P0 = compreg 'C99::CPP'
+    $P1 = $P0.'command_line'(args)
+.end
+
+
+.include 'src/gen_builtins.pir'
+.include 'src/gen_grammar.pir'
+.include 'src/gen_actions.pir'
+
+
+.namespace [ 'C99';'CPP';'Grammar' ]
+
+.sub 'debug'
+    .param pmc match
+    .param pmc arg
+    .param pmc attrs :slurpy
+    printerr arg
+    printerr "\n"
+.end
+
+=back
+
+=cut
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+

Added: c99/trunk/src/cpp/src/builtins/say.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/cpp/src/builtins/say.pir	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,82 @@
+# $Id: say.pir 27878 2008-05-28 14:44:03Z Whiteknight $
+
+=head1
+
+say.pir -- simple implementation of a say function
+
+=cut
+
+.namespace []
+
+.sub 'say'
+    .param pmc args            :slurpy
+    .local pmc iter
+    iter = new 'Iterator', args
+  iter_loop:
+    unless iter goto iter_end
+    $P0 = shift iter
+    print $P0
+    goto iter_loop
+  iter_end:
+    print "\n"
+    .return ()
+.end
+
+.sub 'printf'
+    .param pmc format
+    .param pmc args   :slurpy
+    .local pmc iter
+    iter = new 'Iterator', args
+  iter_loop:
+    unless iter goto iter_end
+    goto iter_loop
+  iter_end:
+.end
+
+.sub 'puts'
+    .param pmc str
+    print str
+    print "\n"
+.end
+
+.sub 'infix:<'
+    .param pmc a
+    .param pmc b
+    islt $I0, a, b
+    .return ($I0)
+.end
+
+.sub 'postfix:++'
+    .param pmc arg
+    $P0 = clone arg
+    inc $P0
+    .return (arg)
+.end
+
+.sub 'postfix:--'
+    .param pmc arg
+    $P0 = clone arg
+    dec $P0
+    .return (arg)
+.end
+
+.sub 'prefix:++'
+    .param pmc arg
+    inc arg
+    .return (arg)
+.end
+
+.sub 'prefix:--'
+    .param pmc arg
+    dec arg
+    .return (arg)
+.end
+
+
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+

Added: c99/trunk/src/cpp/src/parser/actions.pm
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/cpp/src/parser/actions.pm	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,31 @@
+# $Id: actions.pm 36833 2009-02-17 20:09:26Z allison $
+# Copyright (C) 2008, Parrot Foundation.
+
+=begin comments
+
+C99::Grammar::Actions - ast transformations for C99
+
+This file contains the methods that are used by the parse grammar
+to build the PAST representation of an C program.
+Each method below corresponds to a rule in F<src/parser/grammar.pg>,
+and is invoked at the point where C<{*}> appears in the rule,
+with the current match object as the first argument.  If the
+line containing C<{*}> also has a C<#= key> comment, then the
+value of the comment is passed as the second argument to the method.
+
+=end comments
+
+class C99::CPP::Grammar::Actions;
+
+method TOP($/) {
+}
+
+
+
+# Local Variables:
+#   mode: cperl
+#   cperl-indent-level: 4
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
+

Added: c99/trunk/src/cpp/src/parser/grammar.pg
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/cpp/src/parser/grammar.pg	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,431 @@
+# $Id: grammar.pg 36833 2009-02-17 20:09:26Z allison $
+# Copyright (C) 2008, Parrot Foundation.
+
+=begin overview
+
+This is the grammar for C99 written as a sequence of Perl 6 rules.
+
+
+taken from n869.pdf
+google for n869.pdf
+
+=end overview
+
+grammar C99::CPP::Grammar is PCT::Grammar;
+
+token ws { 
+    | \h* 
+    | <multilinecomment>
+}
+
+token TOP {
+    ^
+    <pre_processing_file>
+    [ $ || <.panic: Syntax error> ]
+    {*}
+}
+
+## A.1.5 Constants
+##
+token constant {
+    | <floating_constant> {*}       #= floating_constant
+    | <integer_constant> {*}        #= integer_constant
+    | <enumeration_constant> {*}    #= enumeration_constant
+    | <character_constant> {*}      #= character_constant
+}
+
+token integer_constant {
+    [ <decimal_constant>
+    | <octal_constant>
+    | <hexadecimal_constant>
+    ]
+    <integer_suffix>?
+    {*}
+}
+
+token decimal_constant {
+    <[1..9]> <digit>*
+}
+
+token octal_constant {
+    0 <[0..7]>*
+}
+
+token hexadecimal_constant {
+    0 <[xX]> <xdigit>+
+}
+
+token integer_suffix {
+    | <[uU]> [ll?|LL?]?
+    | [ll?|LL?] <[uU]>?
+}
+
+token floating_constant {
+    [
+    | <decimal_floating_constant>
+    | <hexadecimal_floating_constant>
+    ]
+    {*}
+}
+
+token decimal_floating_constant {
+    [
+    | <fractional_constant> <exponent_part>?
+    | <digit_sequence> <exponent_part>
+    ]
+    <floating_suffix>?
+}
+
+token hexadecimal_prefix {
+  0 <[xX]>
+}
+
+token hexadecimal_floating_constant {
+  <hexadecimal_prefix>
+  [
+  | <hexadecimal_fractional_constant>
+  | <hexadecimal_digit_constant>
+  ]
+  <binary_exponent_part> <floating_suffix>?
+}
+
+token fractional_constant {
+  | <digit_sequence>? \. <digit_sequence>
+  | <digit_sequence> \.
+}
+
+token exponent_part {
+  <[eE]> ['+'|'-']? <digit_sequence>
+}
+
+token digit_sequence { <digit>+ }
+
+token hexadecimal_fractional_constant {
+  | <hexadecimal_digit_sequence>? \. <hexadecimal_digit_sequence>
+  | <hexadecimal_digit_sequence> \.
+}
+
+token binary_exponent_part {
+  <[pP]> ['+'|'-']? <digit_sequence>
+}
+
+token hexadecimal_digit_sequence { <xdigit>+ }
+
+token floating_suffix { <[fFlL]> }
+
+token enumeration_constant { <identifier> }
+
+token character_constant { [L]? \' <c_char>+ \' }
+
+token <c_char> { <-['\\\n]> | <escape_sequence> }
+
+token escape_sequence {
+  \\
+  [ <['"?\\abfnrtv]>
+  | <octal_digit>**{1..3}
+  | x <xdigit>+
+  | <universal_character_name>
+  ]
+}
+
+## A.1.6 String literals
+token c_string_literal {
+    [L]? <string_literal: '"'>
+    {*}
+}
+
+##\" <s_char>* \"
+
+token s_char { <-["\\\n]> | <escape_sequence> }
+
+
+## A.2 Phrase structure grammar
+##
+
+## A.2.1 Expressions
+##
+
+rule expression {
+    <constant_expression>
+    {*}
+}
+
+rule constant_expression {
+    <conditional_expression>
+    {*}
+}
+
+rule assign_op { '='|'*='|'/='|'%='|'+='|'-='|'<<='|'>>='|'&='|'^='|'|=' }
+
+rule conditional_expression {
+    <logical_expression> ['?' <conditional_expression> ':' <conditional_expression>]?
+    {*}
+}
+
+rule logical_expression is optable { ... }
+
+proto 'infix:||' is precedence('1') { ... }
+
+proto 'infix:&&' is tighter('infix:||') { ... }
+
+proto 'infix:|' is tighter('infix:&&') { ... }
+
+proto 'infix:^' is tighter('infix:|') { ... }
+
+proto 'infix:&' is tighter('infix:^') { ... }
+
+proto 'infix:==' is tighter('infix:&') { ... }
+proto 'infix:!=' is equal('infix:==') { ... }
+
+proto 'infix:<' is tighter('infix:==') { ... }
+proto 'infix:>' is equal('infix:<') { ... }
+proto 'infix:>=' is equal('infix:<') { ... }
+proto 'infix:<=' is equal('infix:<') { ... }
+
+proto 'infix:<<' is tighter('infix:==') { ... }
+proto 'infix:>>' is equal('infix:<<') { ... }
+
+proto 'infix:+' is tighter('infix:<<') is pirop('n_add') { ... }
+proto 'infix:-' is equal('infix:+') is pirop('n_sub') { ... }
+
+proto 'infix:*' is tighter('infix:+') is pirop('n_mul') { ... }
+proto 'infix:/' is equal('infix:*') is pirop('n_div') { ... }
+proto 'infix:%' is equal('infix:*') is pirop('n_mod') { ... }
+
+proto 'term:' is tighter('infix:*')
+              is parsed(&cast_expression) { ... }
+
+
+rule postfix_expression_prefix {
+    | <primary_expression> {*}                                  #= primary_expression
+    | '(' <type_name> ')' '{' <initializer_list> [',']? '}' {*} #= type_name
+}
+
+rule postfix_expression {
+    <postfix_expression_prefix>
+    <postfix_expression_suffix>*
+    {*}
+}
+
+rule postfix_expression_suffix {
+    | <index> {*}                           #= index
+    | <arguments>  {*}                      #= arguments
+    | <direct_field> {*}                    #= direct_field
+    | <indirect_field> {*}                  #= indirect_field
+    | <inc_or_dec> {*}                      #= inc_or_dec
+}
+
+rule inc_or_dec {
+    $<op>=['++'|'--']
+    {*}
+}
+
+rule index {
+    '[' <expression> ']'
+    {*}
+}
+
+rule direct_field {
+    '.' <identifier>
+    {*}
+}
+
+rule indirect_field {
+    '->' <identifier>
+    {*}
+}
+
+rule arguments {
+    '(' <argument_expression_list>? ')'
+    {*}
+}
+
+rule argument_expression_list {
+    <assignment_expression> [',' <assignment_expression>]*
+    {*}
+}
+
+rule unary_expression {
+    | <postfix_expression> {*}              #= postfix_expression
+    | <prefix_expression> {*}               #= prefix_expression
+    | <unary_operator> <cast_expression>
+    | 'sizeof' <unary_expression>
+    | 'sizeof' '(' <type_name> ')'
+}
+
+rule prefix_expression {
+    $<op>=['++'|'--'] <unary_expression>
+    {*}
+}
+
+rule unary_operator {
+    '&' | '*' | '+' | '-' | '~' | '!'
+}
+
+rule cast_expression {
+    ['(' <type_name> ')']* <unary_expression>
+    {*}
+}
+
+rule primary_expression {
+    | <identifier> {*}             #= identifier
+    | <constant> {*}               #= constant
+    | <c_string_literal> {*}       #= c_string_literal
+    | '(' <expression> ')' {*}     #= expression
+}
+
+token pound { '#' }
+token begincomment { '/*' }
+
+token multilinecomment { '/*' .*? '*/' }
+
+
+regex preprocessing_token {
+#  | <multilinecomment>
+  | <header_name>
+  | <identifier>
+  | <pp_number>
+  | <character_constant>
+  | '"' <string_literal: '"'> '"'
+  | <!pound> <!begincomment> <punctuator>
+  | <universal_character_name>
+  | <!begincomment><-[# \t\r\n]>\S* ## <-[#]-\S>\S* ##non-whitespace
+}
+
+## A.1.2 Keywords
+##
+token keyword {
+  [ auto      | enum      | restrict  | unsigned
+  | break     | extern    | return    | void
+  | case      | float     | short     | volatile
+  | char      | for       | signed    | while
+  | const     | goto      | sizeof    | _Bool
+  | continue  | if        | static    | _Complex
+  | default   | inline    | struct    | _Imaginary
+  | do        | int       | switch
+  | double    | long      | typedef
+  | else      | register  | union     ]>>
+}
+
+token reserved_word {
+    <keyword>
+}
+
+token identifier {
+    <!reserved_word>
+    <identifier_nondigit> [ <identifier_nondigit> | <digit> ]*
+    {*}
+}
+
+token identifier_nondigit {
+    <alpha> | <[_]> | <universal_character_name>
+}
+
+token character_constant { [L]? \' <c_char>+ \' }
+
+token <c_char> { <-['\\\n]> | <escape_sequence> }
+
+## A.1.4 Universal character names
+##
+token universal_character_name {
+  | '\u' <xdigit>**{4}
+  | '\U' <xdigit>**{8}
+}
+
+
+## A.1.7 Punctuators
+##
+
+token punctuator {
+  | \[        | \]      | <[(){}.]>     | '->'
+  | '++'      | '--'    | <[&*+\-~!/%]>
+  | '<<'      | '>>'    | '<'    | '>'
+  | '<='      | '>='    | '=='          | '!='
+  | <[^|]>    | '&&'    | '||'
+  | <[?:;]>   | '...'
+  | <[*/%+\-&^|]>       | '<<'   | '>>' | '='
+  | <[,#]>    | '##'
+  | '<:'      | ':>'    | '<%'   | '%>' | '%:' | '%:%:'
+}
+
+## A.3 Preprocessing directives
+##
+
+rule pre_processing_file {
+    <group>?
+}
+
+rule group {
+    <group_part>+
+}
+
+rule group_part {
+    | <pp_tokens>? <newline>
+    | <if_section>
+    | <control_line>
+}
+
+rule if_section {
+    <if_group> <elif_group>* <else_group>? <endif_line>
+}
+
+rule if_group {
+    | '#' 'if' <constant_expression> <newline> <group>?
+    | '#' 'ifdef' <identifier> <newline> <group>?
+    | '#' 'ifndef' <identifier> <newline> <group>?
+}
+
+rule elif_group {
+    '#' 'elif' <constant_expression> <newline> <group>?
+}
+
+rule else_group {
+    '#' 'else' <newline> <group>?
+}
+
+rule endif_line {
+    '#' 'endif' <newline>
+}
+
+rule control_line {
+    | '#' 'include' <pp_tokens> <newline>
+    | '#' 'define' <identifier> <replacement_list> <newline>
+    | '#' 'define' <identifier> <lparen> <identifier_list>? ')' <replacement_list> <newline>
+    | '#' 'define' <identifier> <lparen> '...' ')' <replacement_list> <newline>
+    | '#' 'define' <identifier> <lparen> <identifier_list> ',' '...' ')' <replacement_list> <newline>
+    | '#' 'undef' <identifier> <newline>
+    | '#' 'line' <pp_tokens> <newline>
+    | '#' 'error' <pp_tokens>? <newline>
+    | '#' 'pragma' <pp_tokens>? <newline>
+    | '#' <newline>
+}
+
+rule pp_tokens { [ <preprocessing_token> ]+ }
+
+token pp_number {
+    ['.']? <digit> <pp_number_suffix>*
+}
+
+token pp_number_suffix {
+    | '.'
+    | <identifier_nondigit>
+    | <digit>
+    | <[eEpP]> ['+'|'-']
+}
+
+rule replacement_list {
+  <pp_tokens>?
+}
+
+token lparen { '(' }
+
+token newline { \n }
+
+## A.1.8 Header names
+token header_name {
+  | \< <h_char>+ \>
+  | \" <q_char>+ \"
+}
+
+token h_char { <-[\n>]> }
+token q_char { <-[\n"]> }

Added: c99/trunk/src/cpp/t/comment_01.t
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/cpp/t/comment_01.t	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1 @@
+/*hello */

Added: c99/trunk/src/cpp/t/cpp_0.t
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/cpp/t/cpp_0.t	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1 @@
+#define L1 1

Added: c99/trunk/src/cpp/t/harness
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/cpp/t/harness	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,7 @@
+#!/usr/bin/perl
+
+# $Id: harness 26906 2008-04-10 19:45:40Z bernhard $
+
+use FindBin;
+use lib qw( . lib ../lib ../../lib ../../lib ../../../../lib );
+use Parrot::Test::Harness language => 'c99', exec => [ '../../../../parrot', './', 'cpp.pbc' ] ;

Added: c99/trunk/src/cpp/t/spi.t
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/cpp/t/spi.t	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,158 @@
+/*-------------------------------------------------------------------------
+ *
+ * spi.h
+ *				Server Programming Interface public declarations
+ *
+ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL$
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPI_H
+#define SPI_H
+
+/*
+ * This file may be used by client modules that haven't already
+ * included postgres.h
+ */
+#include "postgres.h"
+
+/*
+ *	Most of these are not needed by this file, but may be used by
+ *	user-written code that uses SPI
+ */
+#include "access/heapam.h"
+#include "access/xact.h"
+#include "catalog/pg_language.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "executor/execdefs.h"
+#include "executor/executor.h"
+#include "nodes/execnodes.h"
+#include "nodes/params.h"
+#include "nodes/parsenodes.h"
+#include "nodes/plannodes.h"
+#include "nodes/primnodes.h"
+#include "nodes/relation.h"
+#include "tcop/dest.h"
+#include "tcop/pquery.h"
+#include "tcop/tcopprot.h"
+#include "tcop/utility.h"
+#include "utils/builtins.h"
+#include "utils/datum.h"
+#include "utils/portal.h"
+#include "utils/syscache.h"
+
+
+typedef struct SPITupleTable
+{
+	MemoryContext tuptabcxt;	/* memory context of result table */
+	uint32		alloced;		/* # of alloced vals */
+	uint32		free;			/* # of free vals */
+	TupleDesc	tupdesc;		/* tuple descriptor */
+	HeapTuple  *vals;			/* tuples */
+} SPITupleTable;
+
+/* Plans are opaque structs for standard users of SPI */
+typedef struct _SPI_plan *SPIPlanPtr;
+
+#define SPI_ERROR_CONNECT		(-1)
+#define SPI_ERROR_COPY			(-2)
+#define SPI_ERROR_OPUNKNOWN		(-3)
+#define SPI_ERROR_UNCONNECTED	(-4)
+#define SPI_ERROR_CURSOR		(-5)	/* not used anymore */
+#define SPI_ERROR_ARGUMENT		(-6)
+#define SPI_ERROR_PARAM			(-7)
+#define SPI_ERROR_TRANSACTION	(-8)
+#define SPI_ERROR_NOATTRIBUTE	(-9)
+#define SPI_ERROR_NOOUTFUNC		(-10)
+#define SPI_ERROR_TYPUNKNOWN	(-11)
+
+#define SPI_OK_CONNECT			1
+#define SPI_OK_FINISH			2
+#define SPI_OK_FETCH			3
+#define SPI_OK_UTILITY			4
+#define SPI_OK_SELECT			5
+#define SPI_OK_SELINTO			6
+#define SPI_OK_INSERT			7
+#define SPI_OK_DELETE			8
+#define SPI_OK_UPDATE			9
+#define SPI_OK_CURSOR			10
+#define SPI_OK_INSERT_RETURNING 11
+#define SPI_OK_DELETE_RETURNING 12
+#define SPI_OK_UPDATE_RETURNING 13
+
+extern PGDLLIMPORT uint32 SPI_processed;
+extern PGDLLIMPORT Oid SPI_lastoid;
+extern PGDLLIMPORT SPITupleTable *SPI_tuptable;
+extern PGDLLIMPORT int SPI_result;
+
+extern int	SPI_connect(void);
+extern int	SPI_finish(void);
+extern void SPI_push(void);
+extern void SPI_pop(void);
+extern void SPI_restore_connection(void);
+extern int	SPI_execute(const char *src, bool read_only, long tcount);
+extern int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
+				 bool read_only, long tcount);
+extern int	SPI_exec(const char *src, long tcount);
+extern int SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls,
+		  long tcount);
+extern int SPI_execute_snapshot(SPIPlanPtr plan,
+					 Datum *Values, const char *Nulls,
+					 Snapshot snapshot,
+					 Snapshot crosscheck_snapshot,
+					 bool read_only, bool fire_triggers, long tcount);
+extern int	SPI_execute_with_args(const char *src,
+								  int nargs, Oid *argtypes,
+								  Datum *Values, const char *Nulls,
+								  bool read_only, long tcount);
+extern SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes);
+extern SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
+				   int cursorOptions);
+extern SPIPlanPtr SPI_saveplan(SPIPlanPtr plan);
+extern int	SPI_freeplan(SPIPlanPtr plan);
+
+extern Oid	SPI_getargtypeid(SPIPlanPtr plan, int argIndex);
+extern int	SPI_getargcount(SPIPlanPtr plan);
+extern bool SPI_is_cursor_plan(SPIPlanPtr plan);
+extern const char *SPI_result_code_string(int code);
+
+extern HeapTuple SPI_copytuple(HeapTuple tuple);
+extern HeapTupleHeader SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc);
+extern HeapTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts,
+				int *attnum, Datum *Values, const char *Nulls);
+extern int	SPI_fnumber(TupleDesc tupdesc, const char *fname);
+extern char *SPI_fname(TupleDesc tupdesc, int fnumber);
+extern char *SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber);
+extern Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull);
+extern char *SPI_gettype(TupleDesc tupdesc, int fnumber);
+extern Oid	SPI_gettypeid(TupleDesc tupdesc, int fnumber);
+extern char *SPI_getrelname(Relation rel);
+extern char *SPI_getnspname(Relation rel);
+extern void *SPI_palloc(Size size);
+extern void *SPI_repalloc(void *pointer, Size size);
+extern void SPI_pfree(void *pointer);
+extern void SPI_freetuple(HeapTuple pointer);
+extern void SPI_freetuptable(SPITupleTable *tuptable);
+
+extern Portal SPI_cursor_open(const char *name, SPIPlanPtr plan,
+				Datum *Values, const char *Nulls, bool read_only);
+extern Portal SPI_cursor_open_with_args(const char *name,
+										const char *src,
+										int nargs, Oid *argtypes,
+										Datum *Values, const char *Nulls,
+										bool read_only, int cursorOptions);
+extern Portal SPI_cursor_find(const char *name);
+extern void SPI_cursor_fetch(Portal portal, bool forward, long count);
+extern void SPI_cursor_move(Portal portal, bool forward, long count);
+extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, long count);
+extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, long count);
+extern void SPI_cursor_close(Portal portal);
+
+extern void AtEOXact_SPI(bool isCommit);
+extern void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid);
+
+#endif   /* SPI_H */

Added: c99/trunk/src/parser/actions.pm
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/parser/actions.pm	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,378 @@
+# $Id: actions.pm 36833 2009-02-17 20:09:26Z allison $
+# Copyright (C) 2008, Parrot Foundation.
+
+=begin comments
+
+C99::Grammar::Actions - ast transformations for C99
+
+This file contains the methods that are used by the parse grammar
+to build the PAST representation of an C program.
+Each method below corresponds to a rule in F<src/parser/grammar.pg>,
+and is invoked at the point where C<{*}> appears in the rule,
+with the current match object as the first argument.  If the
+line containing C<{*}> also has a C<#= key> comment, then the
+value of the comment is passed as the second argument to the method.
+
+=end comments
+
+class C99::Grammar::Actions;
+
+method TOP($/) {
+    for $<external_declaration> {
+        my $fun := $( $_ );
+
+        ## Look for the "main" function, and set that as the result
+        ## object.
+        if $fun.name() eq 'main' {
+             make $fun;
+        }
+    }
+}
+
+method external_declaration($/, $key) {
+    make $( $/{$key} );
+}
+
+method declaration($/) {
+    my $past := PAST::Stmts.new( :node($/) );
+
+    for $<init_declarator> {
+           $past.push( $( $_ ) );
+    }
+    make $past;
+}
+
+method init_declarator($/) {
+    make $( $<declarator> );
+}
+
+method function_definition($/) {
+    my $past := PAST::Block.new( :blocktype('declaration'), :node($/) );
+    my $decl := $( $<declarator> );
+    $past.name( $decl.name() );
+
+    my $body := $( $<compound_statement> );
+    $past.push($body);
+    make $past;
+}
+
+method declaration($/) {
+
+}
+
+method declarator($/) {
+    make $( $<direct_declarator> );
+}
+
+method direct_declarator($/) {
+    my $past := $( $<declarator_prefix> );
+    #my $past := $( $<declarator_suffix>[0] );
+    #$past.name($pref.name());
+    make $past;
+}
+
+method declarator_prefix($/, $key) {
+    make $( $/{$key} );
+}
+
+method declarator_suffix($/, $key) {
+    make $( $/{$key} );
+}
+
+method parameter_type_list($/) {
+    my $past := $( $<parameter_list> );
+    if $<vararg> {
+        $past.push( PAST::Var.new( :name('@vararg'), :slurpy(1), :scope('parameter'), :node($/) ) );
+    }
+    make $past;
+}
+
+method parameter_list($/) {
+    ## create the function block here already; it's needed to store the parameters
+    my $past := PAST::Block.new( :blocktype('declaration'), :node($/) );
+    for $<parameter_declaration> {
+        $past.push( $( $_ ) );
+    }
+    make $past;
+}
+
+method parameter_declaration($/, $key) {
+    make $( $/{$key} );
+}
+
+method statement($/, $key) {
+    make $( $/{$key} );
+}
+
+method jump_statement($/, $key) {
+    if $key eq 'return' {
+        my $past := PAST::Op.new( :pirop('return'), :node($/) );
+        if $<expression> {
+            $past.push( $( $<expression>[0] ) );
+        }
+        make $past;
+    }
+    else {
+        $/.panic("$key is not implemented!");
+    }
+}
+
+method for1_statement($/) {
+    my $past := PAST::Stmts.new( :node($/) );
+    my $body := $( $<statement> );
+    my $cond;
+    if $<cond> {
+        $cond := $( $<cond>[0] );
+    }
+    else { # a missing condition is true
+        $cond := PAST::Val.new( :returns('Integer'), :value('1'), :node($/) );
+    }
+
+
+
+    if $<init> {
+        my $init := $( $<init>[0] );
+        $past.unshift($init);
+    }
+
+
+    if $<step> {
+        my $step := $( $<step>[0] );
+        $body := PAST::Stmts.new( $body, $step, :node($/) );
+    }
+    my $loop := PAST::Op.new( $cond, $body, :pasttype('while'), :node($/) );
+    $past.push($loop);
+
+    make $past;
+}
+
+method for2_statement($/) {
+    my $past := PAST::Block.new( :blocktype('immediate'), :node($/) );
+    my $loop := PAST::Op.new( :pasttype('while'), :node($/) );
+
+    $past.push( $( $<declaration> ) );
+    my $body := $( $<statement> );
+
+    if $<step> {
+        my $step := $( $<step>[0] );
+    }
+    my $cond;
+    if $<cond> {
+        $cond := $( $<cond>[0] );
+    }
+    else {
+        $cond := PAST::Val.new( :returns('Integer'), :value('1'), :node($/) );
+    }
+    $loop.push($cond);
+    $loop.push($body);
+
+    $past.push($loop);
+    make $past;
+}
+
+method expression($/) {
+    if +$<assignment_expression> != 1 {
+        my $past := PAST::Stmts.new( :node($/) );
+        for $<assignment_expression> {
+            $past.push( $( $_ ) );
+        }
+        make $past;
+    }
+    else {
+        make $( $<assignment_expression>[0] );
+    }
+}
+
+method expression_statement($/) {
+    if $<expression> {
+        make $( $<expression>[0] );
+    }
+    else {
+        make PAST::Op.new( :inline('    # empty statement'), :node($/) );
+    }
+}
+
+method compound_statement($/) {
+    my $past := PAST::Block.new( :blocktype('immediate'), :node($/) );
+    #my $past := PAST::Stmts.new( :node($/) );
+    for $<block_item> {
+        $past.push( $($_) );
+    }
+    make $past;
+}
+
+method if_statement($/) {
+    my $cond := $( $<expression> );
+    my $then := $( $<statement> );
+    my $past := PAST::Op.new( $cond, $then, :pasttype('if'), :node($/) );
+    if $<else> {
+        $past.push( $( $<else>[0] ) );
+    }
+    make $past;
+}
+
+method do_while_statement($/) {
+    my $cond := $( $<expression> );
+    my $body := $( $<statement> );
+    make PAST::Op.new( $cond, $body, :pasttype('repeat_while'), :node($/) );
+}
+
+method while_statement($/) {
+    my $cond := $( $<expression> );
+    my $body := $( $<statement> );
+    make PAST::Op.new( $cond, $body, :pasttype('while'), :node($/) );
+}
+
+method block_item($/, $key) {
+    make $( $/{$key} );
+}
+
+method constant($/, $key) {
+    make $( $/{$key} );
+}
+
+method constant_expression($/) {
+    make $( $<conditional_expression> );
+}
+
+method assignment_expression($/) {
+    make $( $<conditional_expression> );
+}
+
+method conditional_expression($/) {
+    my $cond := $( $<logical_expression> );
+    if $<expression> {
+        my $then := $( $<expression>[0] );
+        my $else := $( $<conditional_expression>[0] );
+        make PAST::Op.new( $cond, $then, $else, :pasttype('if'), :node($/) );
+    }
+    else {
+        make $cond;
+    }
+}
+
+method postfix_expression_prefix($/, $key) {
+    make $( $/{$key} );
+}
+
+method postfix_expression_suffix($/, $key) {
+    make $( $/{$key} );
+}
+
+method index($/) {
+    my $expr := $( $<expression> );
+    ## XXX
+    make PAST::Op.new( $expr, :name('xxx_index'), :pasttype('call'), :node($/) );
+}
+
+method direct_field($/) {
+    my $field := $( $<identifier> );
+    ## XXX
+    make PAST::Op.new( $field, :name('xxx_get_field'), :pasttype('call'), :node($/) );
+}
+
+method indirect_field($/) {
+    my $field := $( $<identifier> );
+    ## XXX
+    make PAST::Op.new( $field, :name('xxx_get_indirect'), :pasttype('call'), :node($/) );
+}
+
+method inc_or_dec($/) {
+    my $opname := 'postfix:' ~ ~$<op>;
+    my $past := PAST::Op.new( :name($opname), :pasttype('call'), :node($/) );
+    make $past;
+}
+
+method arguments($/) {
+    if $<argument_expression_list> {
+        make $( $<argument_expression_list>[0] );
+    }
+    else {
+        make PAST::Op.new( :pasttype('call'), :node($/) );
+    }
+}
+
+method argument_expression_list($/) {
+    my $past := PAST::Op.new( :pasttype('call'), :node($/) );
+    for $<assignment_expression> {
+        $past.push( $( $_ ) );
+    }
+    make $past;
+}
+
+method postfix_expression($/) {
+    my $past := $( $<postfix_expression_prefix> );
+    for $<postfix_expression_suffix> {
+        ## XXX
+        my $args := $( $_ );
+        $args.unshift($past);
+        $past := $args;
+    }
+    make $past;
+}
+
+method prefix_expression($/) {
+    my $opname := 'prefix:' ~ ~$<op>;
+    my $expr   := $( $<unary_expression> );
+    make PAST::Op.new( $expr, :name($opname), :pasttype('call'), :node($/) );
+}
+
+method primary_expression($/, $key) {
+    make $( $/{$key} );
+}
+
+method unary_expression($/, $key) {
+    make $( $/{$key} );
+}
+
+method integer_constant($/) {
+    make PAST::Val.new( :value( ~$/ ), :returns('Integer'), :node($/) );
+}
+
+method floating_constant($/) {
+    make PAST::Val.new( :value( ~$/ ), :returns('Float'), :node($/) );
+}
+
+
+method c_string_literal($/) {
+    make PAST::Val.new( :value( ~$<string_literal> ), :node($/) );
+    #make PAST::Val.new( :value( ~$/ ), :node($/) );
+}
+
+method identifier($/) {
+    ## XXX fix scopes
+    ## XXX fix declarations so that :viviself can be removed
+    make PAST::Var.new( :name( ~$/ ), :scope('package'), :viviself('Integer'), :node($/) );
+}
+
+method cast_expression($/) {
+    make $( $<unary_expression> );
+}
+
+method logical_expression($/, $key) {
+    if ($key eq 'end') {
+        make $($<expr>);
+    }
+    else {
+        my $past := PAST::Op.new( :name($<type>),
+                                  :pasttype($<top><pasttype>),
+                                  :pirop($<top><pirop>),
+                                  :lvalue($<top><lvalue>),
+                                  :node($/)
+                                );
+        for @($/) {
+            $past.push( $($_) );
+        }
+        make $past;
+    }
+
+}
+
+
+# Local Variables:
+#   mode: cperl
+#   cperl-indent-level: 4
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
+

Added: c99/trunk/src/parser/grammar.pg
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/parser/grammar.pg	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,769 @@
+# $Id: grammar.pg 36833 2009-02-17 20:09:26Z allison $
+# Copyright (C) 2008, Parrot Foundation.
+
+=begin overview
+
+This is the grammar for C99 written as a sequence of Perl 6 rules.
+
+
+taken from n869.pdf
+google for n869.pdf
+
+=end overview
+
+grammar C99::Grammar is PCT::Grammar;
+
+## A.2.4 External definitions
+##
+
+token TOP {
+    ^
+    <external_declaration>+
+    [ $ || <.panic: Syntax error> ]
+    {*}
+}
+
+rule external_declaration {
+    | <declaration> {*}          #= declaration
+    | <function_definition> {*}  #= function_definition
+}
+
+rule function_definition {
+    <declaration_specifiers>
+    <declarator>
+    <declaration>*
+    <compound_statement>
+    {*}
+}
+
+
+## A.2.2
+##
+
+rule declaration {
+    <declaration_specifiers>
+    [ <init_declarator> [',' <init_declarator>]* ]?
+    ';'
+    {*}
+}
+
+rule declaration_specifiers {
+    [ <type_specifier>
+    | <storage_class_specifier>
+    | <type_qualifier>
+    | <function_specifier>
+    ]+
+}
+
+rule function_specifier {
+    'inline'
+}
+
+rule init_declarator {
+    <declarator> ['=' <initializer>]?
+    {*}
+}
+
+rule storage_class_specifier {
+    | 'typedef'
+    | 'extern'
+    | 'static'
+    | 'auto'
+    | 'register'
+}
+
+rule type_specifier {
+    | <builtin_type>
+    | <struct_or_union_specifier>
+    | <enum_specifier>
+    | <typedef_name>
+}
+
+token builtin_type {
+    | 'void'
+    | 'char'
+    | 'short'
+    | 'int'
+    | 'long'
+    | 'float'
+    | 'double'
+    | 'signed'
+    | 'unsigned'
+    | '_Bool'
+    | '_Complex'
+    | '_Imaginary'
+}
+
+rule struct_or_union_specifier {
+    $<type>=['struct'|'union']
+    [
+    | <struct_or_union_definition>
+    | <pre_declaration>
+    ]
+}
+
+rule struct_or_union_definition {
+    <identifier>? '{' <struct_declaration>+ '}'
+}
+
+rule pre_declaration {
+    <identifier>
+}
+
+rule struct_declaration {
+    <specifier_qualifier_list> <struct_declarator_list>* ';'
+}
+
+rule specifier_qualifier_list {
+    [
+    | <type_specifier>
+    | <type_qualifier>
+    ]+
+}
+
+rule struct_declarator_list {
+    <struct_declarator> [',' <struct_declarator>]*
+}
+
+rule struct_declarator {
+    | <declarator>? ':' <constant_expression>
+    | <declarator>
+}
+
+rule enum_specifier {
+    | 'enum' <identifier>? '{' <enumerator_list> [',']? '}'
+    | 'enum' <identifier>
+}
+
+rule enumerator_list {
+    <enumerator> [',' <enumerator>]*
+}
+
+rule enumerator {
+    <enumeration_constant> ['=' <constant_expression>]?
+}
+
+rule type_qualifier {
+    $<qualifier>=['const'|'restrict'|'volatile']
+}
+
+rule declarator {
+    <pointer>?
+    <direct_declarator>
+    {*}
+}
+
+rule direct_declarator {
+    <declarator_prefix>
+    <declarator_suffix>*
+    {*}
+}
+
+rule declarator_prefix {
+    | '(' <declarator> ')' {*}       #= declarator
+    | <identifier> {*}               #= identifier
+}
+
+rule declarator_suffix {
+    | '(' <parameter_type_list> ')' {*}    #= parameter_type_list
+    ## old-style C parameter declarations
+    | '(' <identifier_list>? ')' {*}       #= identifier_list
+    | '[' <assignment_expression>? ']'
+    | '[' '*' ']'
+}
+
+rule pointer {
+    '*' <type_qualifier>* ['*']?
+}
+
+rule parameter_type_list {
+    <parameter_list>  [$<vararg>=[',' '...']]?
+    {*}
+}
+
+rule parameter_list {
+    <parameter_declaration> [',' <parameter_declaration>]*
+    {*}
+}
+
+rule parameter_declaration {
+    <declaration_specifiers>
+    [
+    | <declarator> {*}               #= declarator
+    | <abstract_declarator>? {*}     #= abstract_declarator
+    ]
+}
+
+rule identifier_list {
+    <identifier> [',' <identifier>]*
+}
+
+rule type_name {
+    <specifier_qualifier_list> <abstract_declarator>?
+}
+
+rule abstract_declarator {
+    | '*'
+    | ['*']? <direct_abstract_declarator>
+}
+
+rule direct_abstract_declarator {
+    [
+    | '(' <abstract_declatator> ')'
+    | '[' <assignment_expression>? ']'
+    | '(' <parameter_type_list> ')'
+    ]
+    <direct_abstract_declarator_1>*
+}
+
+rule direct_abstract_declarator_1 {
+    | '[' <assignment_expression>? ']'
+    | '[' '*' ']'
+    | '(' <parameter_type_list> ')'
+}
+
+rule typedef_name {
+
+## a typedef name can be a return type specifier. This is ambiguous, because
+## the parser doesn't know if it's a return type thingie or the name of the
+## function. Therefore, typedef'd names must be stored in a %hash, so that
+## this rule is not calling <identifier>, but inspecting the registered
+## typedef'd names. For now, specify 'SOME_TYPEDEF_NAME' as the only typedef'd name.
+##
+    #<identifier>
+    'SOME_TYPEDEF_NAME'
+}
+
+rule initializer {
+    | <assignment_expression>
+    | '{' <initializer_list> [',']? '}'
+}
+
+rule initializer_list {
+    <initializer_item> [',' <initializer_item>]*
+}
+
+rule initializer_item {
+    <designation>? <initializer>
+}
+
+rule designation {
+    <designator>+ '='
+}
+
+rule designator {
+    | '[' <constant_expression> ']'
+    | '.' <identifier>
+}
+
+
+## A.2.3 Statements
+##
+
+rule statement {
+    | <labeled_statement>
+    | <compound_statement> {*}        #= compound_statement
+    | <expression_statement> {*}      #= expression_statement
+    | <if_statement> {*}              #= if_statement
+    | <switch_statement>
+    | <while_statement> {*}           #= while_statement
+    | <do_while_statement> {*}        #= do_while_statement
+    | <for1_statement> {*}            #= for1_statement
+    | <for2_statement> {*}            #= for2_statement
+    | <jump_statement> {*}            #= jump_statement
+}
+
+rule labeled_statement {
+    | <identifier> ':' <statement>
+    | 'case' <constant_expression> ':' <statement>
+    | 'default' ':' <statement>
+}
+
+rule compound_statement {
+    '{' <block_item>* '}'
+    {*}
+}
+
+rule block_item {
+    | <declaration> {*}    #= declaration
+    | <statement> {*}      #= statement
+}
+
+rule expression_statement {
+    <expression>? ';'
+    {*}
+}
+
+rule if_statement {
+    'if' '(' <expression> ')' <statement> ['else' $<else>=<statement>]?
+    {*}
+}
+
+rule switch_statement {
+    'switch' '(' <expression> ')' <statement>
+}
+
+rule while_statement {
+    'while' '(' <expression> ')' <statement>
+    {*}
+}
+
+rule do_while_statement {
+    'do' <statement> 'while' '(' <expression> ')' ';'
+    {*}
+}
+
+rule for1_statement {
+    'for' '(' [$<init>=<expression>]? ';' [$<cond>=<expression>]? ';' [$<step>=<expression>]? ')'
+    <statement>
+    {*}
+}
+
+rule for2_statement {
+    'for' '(' <declaration> [$<cond>=<expression>]? ';' [$<step>=<expression>]? ')' <statement>
+    {*}
+}
+
+rule jump_statement {
+    | 'goto' <identifier> ';' {*}         #= goto
+    | 'continue' ';' {*}                  #= continue
+    | 'break' ';' {*}                     #= break
+    | 'return' <expression>? ';' {*}      #= return
+}
+
+
+## A.1.1 Lexical elements
+##
+##rule token {
+##  | <keyword>
+##  | <identifier>
+##  | <constant>
+##  | <c_string_literal>
+##  | <punctuator>
+##}
+
+regex preprocessing_token {
+  | <header_name>
+  | <identifier>
+  | <pp_number>
+  | <character_constant>
+  | <string_literal>
+  | <!pound> <punctuator>
+  | <universal_character_name>
+  | <-[# \r\n\t]>\S* ## <-[#]-\S>\S* ##non-whitespace
+}
+
+## A.1.2 Keywords
+##
+token keyword {
+  [ auto      | enum      | restrict  | unsigned
+  | break     | extern    | return    | void
+  | case      | float     | short     | volatile
+  | char      | for       | signed    | while
+  | const     | goto      | sizeof    | _Bool
+  | continue  | if        | static    | _Complex
+  | default   | inline    | struct    | _Imaginary
+  | do        | int       | switch
+  | double    | long      | typedef
+  | else      | register  | union     ]>>
+
+}
+
+token reserved_word {
+    <keyword>
+}
+
+
+token identifier {
+    <!reserved_word>
+    <identifier_nondigit> [ <identifier_nondigit> | <digit> ]*
+    {*}
+}
+
+token identifier_nondigit {
+    <alpha> | <[_]> | <universal_character_name>
+}
+
+## A.1.4 Universal character names
+##
+token universal_character_name {
+  | '\u' <xdigit>**{4}
+  | '\U' <xdigit>**{8}
+}
+
+
+## A.1.5 Constants
+##
+token constant {
+    | <floating_constant> {*}       #= floating_constant
+    | <integer_constant> {*}        #= integer_constant
+    | <enumeration_constant> {*}    #= enumeration_constant
+    | <character_constant> {*}      #= character_constant
+}
+
+token integer_constant {
+    [ <decimal_constant>
+    | <octal_constant>
+    | <hexadecimal_constant>
+    ]
+    <integer_suffix>?
+    {*}
+}
+
+token decimal_constant {
+    <[1..9]> <digit>*
+}
+
+token octal_constant {
+    0 <[0..7]>*
+}
+
+token hexadecimal_constant {
+    0 <[xX]> <xdigit>+
+}
+
+token integer_suffix {
+    | <[uU]> [ll?|LL?]?
+    | [ll?|LL?] <[uU]>?
+}
+
+token floating_constant {
+    [
+    | <decimal_floating_constant>
+    | <hexadecimal_floating_constant>
+    ]
+    {*}
+}
+
+token decimal_floating_constant {
+    [
+    | <fractional_constant> <exponent_part>?
+    | <digit_sequence> <exponent_part>
+    ]
+    <floating_suffix>?
+}
+
+token hexadecimal_prefix {
+  0 <[xX]>
+}
+
+token hexadecimal_floating_constant {
+  <hexadecimal_prefix>
+  [
+  | <hexadecimal_fractional_constant>
+  | <hexadecimal_digit_constant>
+  ]
+  <binary_exponent_part> <floating_suffix>?
+}
+
+token fractional_constant {
+  | <digit_sequence>? \. <digit_sequence>
+  | <digit_sequence> \.
+}
+
+token exponent_part {
+  <[eE]> ['+'|'-']? <digit_sequence>
+}
+
+token digit_sequence { <digit>+ }
+
+token hexadecimal_fractional_constant {
+  | <hexadecimal_digit_sequence>? \. <hexadecimal_digit_sequence>
+  | <hexadecimal_digit_sequence> \.
+}
+
+token binary_exponent_part {
+  <[pP]> ['+'|'-']? <digit_sequence>
+}
+
+token hexadecimal_digit_sequence { <xdigit>+ }
+
+token floating_suffix { <[fFlL]> }
+
+token enumeration_constant { <identifier> }
+
+token character_constant { [L]? \' <c_char>+ \' }
+
+token <c_char> { <-['\\\n]> | <escape_sequence> }
+
+token escape_sequence {
+  \\
+  [ <['"?\\abfnrtv]>
+  | <octal_digit>**{1..3}
+  | x <xdigit>+
+  | <universal_character_name>
+  ]
+}
+
+## A.1.6 String literals
+token c_string_literal {
+    [L]? <string_literal: '"'>
+    {*}
+}
+
+##\" <s_char>* \"
+
+token s_char { <-["\\\n]> | <escape_sequence> }
+
+
+## A.2 Phrase structure grammar
+##
+
+## A.2.1 Expressions
+##
+
+rule constant_expression {
+    <conditional_expression>
+    {*}
+}
+
+rule expression {
+    <assignment_expression> [',' <assignment_expression>]*
+    {*}
+}
+
+rule assignment_expression {
+    [<unary_expression> <assign_op>]* <conditional_expression>
+    {*}
+}
+
+rule assign_op { '='|'*='|'/='|'%='|'+='|'-='|'<<='|'>>='|'&='|'^='|'|=' }
+
+rule conditional_expression {
+    <logical_expression> ['?' <expression> ':' <conditional_expression>]?
+    {*}
+}
+
+rule logical_expression is optable { ... }
+
+proto 'infix:||' is precedence('1') { ... }
+
+proto 'infix:&&' is tighter('infix:||') { ... }
+
+proto 'infix:|' is tighter('infix:&&') { ... }
+
+proto 'infix:^' is tighter('infix:|') { ... }
+
+proto 'infix:&' is tighter('infix:^') { ... }
+
+proto 'infix:==' is tighter('infix:&') { ... }
+proto 'infix:!=' is equal('infix:==') { ... }
+
+proto 'infix:<' is tighter('infix:==') { ... }
+proto 'infix:>' is equal('infix:<') { ... }
+proto 'infix:>=' is equal('infix:<') { ... }
+proto 'infix:<=' is equal('infix:<') { ... }
+
+proto 'infix:<<' is tighter('infix:==') { ... }
+proto 'infix:>>' is equal('infix:<<') { ... }
+
+proto 'infix:+' is tighter('infix:<<') is pirop('n_add') { ... }
+proto 'infix:-' is equal('infix:+') is pirop('n_sub') { ... }
+
+proto 'infix:*' is tighter('infix:+') is pirop('n_mul') { ... }
+proto 'infix:/' is equal('infix:*') is pirop('n_div') { ... }
+proto 'infix:%' is equal('infix:*') is pirop('n_mod') { ... }
+
+proto 'term:' is tighter('infix:*')
+              is parsed(&cast_expression) { ... }
+
+
+rule postfix_expression_prefix {
+    | <primary_expression> {*}                                  #= primary_expression
+    | '(' <type_name> ')' '{' <initializer_list> [',']? '}' {*} #= type_name
+}
+
+rule postfix_expression {
+    <postfix_expression_prefix>
+    <postfix_expression_suffix>*
+    {*}
+}
+
+rule postfix_expression_suffix {
+    | <index> {*}                           #= index
+    | <arguments>  {*}                      #= arguments
+    | <direct_field> {*}                    #= direct_field
+    | <indirect_field> {*}                  #= indirect_field
+    | <inc_or_dec> {*}                      #= inc_or_dec
+}
+
+rule inc_or_dec {
+    $<op>=['++'|'--']
+    {*}
+}
+
+rule index {
+    '[' <expression> ']'
+    {*}
+}
+
+rule direct_field {
+    '.' <identifier>
+    {*}
+}
+
+rule indirect_field {
+    '->' <identifier>
+    {*}
+}
+
+rule arguments {
+    '(' <argument_expression_list>? ')'
+    {*}
+}
+
+rule argument_expression_list {
+    <assignment_expression> [',' <assignment_expression>]*
+    {*}
+}
+
+rule unary_expression {
+    | <postfix_expression> {*}              #= postfix_expression
+    | <prefix_expression> {*}               #= prefix_expression
+    | <unary_operator> <cast_expression>
+    | 'sizeof' <unary_expression>
+    | 'sizeof' '(' <type_name> ')'
+}
+
+rule prefix_expression {
+    $<op>=['++'|'--'] <unary_expression>
+    {*}
+}
+
+rule unary_operator {
+    '&' | '*' | '+' | '-' | '~' | '!'
+}
+
+rule cast_expression {
+    ['(' <type_name> ')']* <unary_expression>
+    {*}
+}
+
+rule primary_expression {
+    | <identifier> {*}             #= identifier
+    | <constant> {*}               #= constant
+    | <c_string_literal> {*}       #= c_string_literal
+    | '(' <expression> ')' {*}     #= expression
+}
+
+token ws {
+  [
+  | '//' \N* \n
+  | '/*' .*? '*/'
+  | \s+
+  | '#' \N* \n
+  ]*
+}
+
+## A.1.7 Punctuators
+##
+
+token punctuator {
+  | \[        | \]      | <[(){}.]>     | '->'
+  | '++'      | '--'    | <[&*+\-~!/%]>
+  | '<<'      | '>>'    | '<'    | '>'
+  | '<='      | '>='    | '=='          | '!='
+  | <[^|]>    | '&&'    | '||'
+  | <[?:;]>   | '...'
+  | <[*/%+\-&^|]>       | '<<'   | '>>' | '='
+  | <[,#]>    | '##'
+  | '<:'      | ':>'    | '<%'   | '%>' | '%:' | '%:%:'
+}
+
+
+## A.3 Preprocessing directives
+##
+
+rule pre_processing_file {
+    <group>?
+}
+
+rule group {
+    <group_part>+
+}
+
+rule group_part {
+    | <pp_tokens>? <newline>
+    | <if_section>
+    | <control_line>
+}
+
+rule if_section {
+    <if_group> <elif_group>* <else_group>? <endif_line>
+}
+
+rule if_group {
+    | '#' 'if' <constant_expression> <newline> <group>?
+    | '#' 'ifdef' <identifier> <newline> <group>?
+    | '#' 'ifndef' <identifier> <newline> <group>?
+}
+
+rule elif_group {
+    '#' 'elif' <constant_expression> <newline> <group>?
+}
+
+rule else_group {
+    '#' 'else' <newline> <group>?
+}
+
+rule endif_line {
+    '#' 'endif' <newline>
+}
+
+rule control_line {
+    | '#' 'include' <pp_tokens> <newline>
+    | '#' 'define' <identifier> <replacement_list> <newline>
+    | '#' 'define' <identifier> <lparen> <identifier_list>? ')' <replacement_list> <newline>
+    | '#' 'define' <identifier> <lparen> '...' ')' <replacement_list> <newline>
+    | '#' 'define' <identifier> <lparen> <identifier_list> ',' '...' ')' <replacement_list> <newline>
+    | '#' 'undef' <identifier> <newline>
+    | '#' 'line' <pp_tokens> <newline>
+    | '#' 'error' <pp_tokens>? <newline>
+    | '#' 'pragma' <pp_tokens>? <newline>
+    | '#' <newline>
+}
+
+rule pp_tokens {
+    <preprocessing_token>+
+}
+
+rule preprocessing_token {
+    | <header_name>
+    | <identifier>
+    | <pp_number>
+    | <character_constant>
+    | <c_string_literal>
+    | <punctuator>
+}
+
+rule pp_number {
+    ['.']? <digit> <pp_number_suffix>*
+}
+
+rule pp_number_suffix {
+    | '.'
+    | <identifier_nondigit>
+    | <digit>
+    | <[eEpP]> ['+'|'-']
+}
+
+rule replacement_list {
+    <pp_tokens>?
+}
+
+token lparen {
+    '('
+}
+
+token newline {
+     \n
+}
+
+## A.1.8 Header names
+token header_name {
+    | \< <h_char>+ \>
+    | \" <q_char>+ \"
+}
+
+token h_char { <-[\n>]> }
+token q_char { <-[\n"]> }

Added: c99/trunk/src/preamble
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/src/preamble	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,96 @@
+.macro kdump ( x )
+    .local pmc it
+    it = get_root_global ['parrot'], '_dumper'
+    it(.x)
+.endm
+
+.macro kdump2 ( x, d)
+    .local pmc it
+    it = get_root_global ['parrot'], '_dumper'
+    it(.x, .d)
+.endm
+
+.macro dump_root
+    .local string it
+    .local pmc ns
+    ns = get_root_namespace [ 'parrot'; 'Cardinal::Grammar' ]
+    .local pmc iter
+    iter = new 'Iterator', ns
+    set iter, 0
+    .label $iter_loop:
+    unless iter, .$iter_end
+    shift it, iter
+    print it
+    print "\n"
+    goto .$iter_loop
+    .label $iter_end:
+.endm
+
+.macro dump_hll
+    .local string it
+    .local pmc ns
+    ns = get_hll_namespace
+    .local pmc iter
+    iter = new 'Iterator', ns
+    set iter, 0
+    .label $iter_loop:
+    unless iter, .$iter_end
+    shift it, iter
+    print it
+    print "\n"
+    goto .$iter_loop
+    .label $iter_end:
+.endm
+
+.macro dump_hll2
+    .local string it
+    .local pmc ns
+    ns = get_hll_namespace
+    .local pmc iter
+    iter = new 'Iterator', ns
+    set iter, 0
+    .label $iter_loop:
+    unless iter, .$iter_end
+    shift it, iter
+    print it
+    print "\n"
+    goto .$iter_loop
+    .label $iter_end:
+.endm
+
+.macro dump_current
+    .local string it
+    .local pmc ns
+    ns = get_namespace
+    .local pmc iter
+    iter = new 'Iterator', ns
+    set iter, 0
+    .label $iter_loop:
+    unless iter, .$iter_end
+    shift it, iter
+    print it
+    print "\n"
+    goto .$iter_loop
+    .label $iter_end:
+.endm
+
+.macro gen_accessor(x)
+.sub .x :method
+  .param pmc value           :optional
+  .param int has_value       :opt_flag
+  .return self.'attr'(.x, value, has_value)
+.end
+.endm
+
+.macro gen_get_accessor(x)
+.sub .x :method
+    null $P0
+    .return self.'attr'(.x, $P0, 0)
+.end
+.endm
+
+.macro gen_dumplist(x)
+.sub '__dumplist' :method
+    .return (.x)
+.end
+.endm

Added: c99/trunk/t/harness
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/t/harness	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,7 @@
+#!/usr/bin/perl
+
+# $Id: harness 25985 2008-02-22 12:22:13Z kjs $
+
+use FindBin;
+use lib qw( . lib ../lib ../../lib ../../lib );
+use Parrot::Test::Harness language => 'c99', compiler => 'c99.pbc';

Added: c99/trunk/t/spi.t
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ c99/trunk/t/spi.t	Tue Mar 10 23:43:32 2009	(r20)
@@ -0,0 +1,33 @@
+
+
+
+void main() {
+    puts("1..6");
+    puts("ok 1");
+
+    if (0)
+        puts("nok 2");
+    else {
+        puts("ok 2");
+    }
+
+
+    if (1) {
+        puts("ok 3");
+    }
+    else
+        puts("nok 3");
+
+    do {
+        puts("ok 4");
+    }
+    while(0);
+
+    while(0) {
+        puts("nok 5");
+    }
+    puts("ok 5");
+
+    1 ? puts("ok 6") : puts("nok 6");
+}
+


More information about the parrot-commits mailing list