> grammar Grammars::Languages::C::Preprocessor { > rule CompilationUnit { > ( <Directive> | <UnprocessedStuff> )* > } > > rule Directive { > <Hash> ( Include > | Line > | Conditional > | Define > ) <Continuation>* > } > > rule Hash { /^\s*#\s*/ } > rule Include {...} > rule Line {...} > rule Conditional {...} > rule Define {...} > rule Continuation {...} > rule UnprocessedStuff {...} > }
We're not quite in the world of ACME::DWIM, so you can't just replace the important stuff with ... . :-) You're not outputting a parse tree, you're just outputting more text to be parsed with another, text-based, grammar. It seems to me like it's a big s//ubstitution, of sorts. Or maybe not, maybe we make an output stream which will be fed to Grammars::Languages::C. Here's an implementation a #include processor, using as little made-up syntax as possible. use Pattern::Common; grammar Preprocessor { rule include { :w(/\h*/) \# include "<Pattern::Common::filename>" $$ { $0 := (<<< open "< $filename") ~~ /<main>/ } } rule main { $0 := ( [<include> | .]* ) } } Now, to chain them, you do the (seemingly more natural): $fh ~~ /<Preprocessor>/ ~~ /<C>/ I've been trying to figure out how one would do Preprocessor lazily, such that it would not process any more text until C said it needed it. Perhaps something with ArrayString (the hypothetical class from A5)? Coroutines? Luke > Except that it would probably be even better to do this arbitrarily. > > > my $fh = open "<hello.c"; > > $fh =~ /<Grammars::Languages::C>/; > > $fh =~ /<Grammars::Languages::C(input_method = > Grammars::Languages::C::Preprocessor)>/; > > (Of course, in reality the C grammar would automatically use the > preprocessor as its input method without having to be told. But it > should be able to do so as two separate grammars.) > > Likewise: > > my $fh = open "<perl.1.gz"; > > $fh =~ /<Grammars::Languages::Runoff::Nroff(input_method > = Grammars::Languages::Runoff::tbl(input_method > = Grammars::Language::Runoff::eqn(input_method > = IO::Gunzip)))>/; > > =Austin