> 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