3 Perl6Grammar - compiler for Perl 6 grammars
9 parrot Perl6Grammar.pir [options] file ...
13 .local string grammar_source
16 pgc = compreg 'PGE::Perl6Grammar'
18 # Compile grammar_source to PIR
19 $P1 = pgc(grammar_source, 'target' => 'PIR')
21 # Compile and install grammar_source
22 $P1 = pgc(grammar_source)
26 This program takes a set of parser rules (i.e., a parser grammar)
27 specified in the input C<FILE>s, and compiles it into the PIR code
28 needed to execute the grammar. This PIR code is then suitable for
29 inclusion or compilation into other larger programs.
35 =item --output=OUTFILE
37 Send the output to OUTFILE. By default, output is directed to
40 =item --encoding=ENCODING
42 Encoding to use when reading input files. Defaults to 'ascii', but
43 can also be set to 'iso-8859-1' or 'utf8'.
51 =item C<main(PMC args)>
53 Processes command line arguments, reads input files, dispatches
54 to appropriate PIR-generating subroutines, and then sends
55 the output to the correct output file.
59 .namespace [ 'PGE::Perl6Grammar::Compiler' ]
65 pgc = compreg 'PGE::Perl6Grammar'
66 pgc.'command_line'(args, 'target'=>'PIR', 'combine'=>1)
71 .sub '__onload' :load :init
72 load_bytecode 'PGE.pbc'
73 load_bytecode 'PGE/Text.pbc'
74 load_bytecode 'PGE/Util.pbc'
75 load_bytecode 'PCT/HLLCompiler.pbc'
78 p6regex = compreg 'PGE::Perl6Regex'
80 $S0 = "<.ident> [ '::' <.ident> ]*"
81 p6regex($S0, 'grammar'=>'PGE::Perl6Grammar', 'name'=>'name')
83 $S0 = "[ '#' \\N* | \\s+ | <.pod_comment> ]* :::"
84 p6regex($S0, 'grammar'=>'PGE::Perl6Grammar', 'name'=>'ws')
86 $S0 = <<' END_POD_COMMENT_RULE'
87 ^^ '=' [ [ cut \h*: | end [\h\N*]? ]
88 | for [ \h\N+: ] \n [ \N+\n ]*:
89 | \w\N*: \n .*? \n '=' [ cut \h*: | end [\h\N*:]? ]
93 p6regex($S0, 'grammar'=>'PGE::Perl6Grammar', 'name'=>'pod_comment')
95 $S0 = <<' END_ARG_RULE'
105 p6regex($S0, 'grammar'=>'PGE::Perl6Grammar', 'name'=>'arg')
107 $S0 = <<' STMT_PARSE'
108 $<cmd>:=(grammar) <name> [ 'is' $<inherit>:=<name> ]? ';'?
109 | $<cmd>:=(regex|token|rule)
111 $<optable>:=(is optable)?
112 [ \{<regex>\} | <?PGE::Util::die: 'unable to parse regex'> ]
113 | [multi]? $<cmd>:=(proto)
115 ( is $<trait>:=[\w+]['('<arg>')']? )*
116 [ \{ <-[}]>*: \} | ';' | <?PGE::Util::die: 'missing proto/sub body'> ]
117 | [$|<PGE::Util::die: unrecognized statement>]
119 $P0 = p6regex($S0, 'grammar'=>'PGE::Perl6Grammar', 'name'=>'statement', 'w'=>1)
121 ## Add the PGE::Perl6Regex's regex method to PGE::Perl6Grammar
122 $P0 = get_hll_global ['PGE::Perl6Regex'], 'regex'
123 $P1 = get_class ['PGE::Perl6Grammar']
124 $P1.'add_method'('regex', $P0)
126 ## create the PGE::Perl6Grammar compiler object
128 $P99 = subclass 'PCT::HLLCompiler', 'PGE::Perl6Grammar::Compiler'
129 pgc = new [ 'PGE::Perl6Grammar::Compiler' ]
130 pgc.'language'('PGE::Perl6Grammar')
134 .sub 'compile' :method
136 .param pmc adverbs :slurpy :named
138 .local pmc nstable, namespace
140 namespace = new 'String'
142 $P1 = new 'CodeString'
144 $P1 = new 'CodeString'
148 # get our initial match object
150 $P0 = get_hll_global ['PGE'], 'Match'
151 match = $P0.'new'(source, 'grammar'=>'PGE::Perl6Grammar')
154 stmtrule = get_hll_global ['PGE::Perl6Grammar'], 'statement'
157 match = stmtrule(match)
158 unless match goto stmt_end
159 unless match > '' goto stmt_end
163 $P0(match, namespace, nstable)
167 .local pmc initpir, rulepir, iter, ns
168 .local string namespace
169 initpir = new 'CodeString'
170 rulepir = new 'CodeString'
171 iter = new 'Iterator', nstable
173 unless iter goto iter_end
174 namespace = shift iter
178 if namespace == 'PGE::Grammar' goto ns_optable
179 if namespace == '' goto ns_optable
180 .local string inherit
181 inherit = ns['inherit']
182 $S0 = initpir.unique('onload_')
183 initpir.emit(<<' CODE', namespace, inherit, $S0)
187 p6meta = get_hll_global 'P6metaclass'
188 p6meta.'new_class'('%0', 'parent'=>'%1')
194 if $P0 == '' goto iter_loop
195 initpir.emit(" optable = new 'PGE::OPTable'")
196 initpir.emit(" set_hll_global ['%0'], '$optable', optable", namespace)
202 out = new 'CodeString'
203 if initpir == '' goto out_rule
204 out.emit(" .sub '__onload' :load :init")
205 out.emit(" .local pmc optable")
207 out.emit(" .return ()")
213 target = adverbs['target']
214 target = downcase target
215 if target != 'pir' goto compile_pir
229 ## get the grammar name
230 .local string name, inherit
232 inherit = 'PGE::Grammar'
233 $P0 = stmt['inherit']
234 if null $P0 goto have_inherit
238 ## set the new namespace, and create any nstable entries
240 assign namespace, name
242 $I0 = exists nstable[name]
246 ns['inherit'] = inherit
247 $P1 = new 'CodeString'
249 $P1 = new 'CodeString'
262 ## get the regex name
265 $S0 = $P0['category']
267 name = concat $S0, $S1
269 ## set compile adverbs
272 adverbs['grammar'] = namespace
273 adverbs['name'] = name
275 ## handle options for 'token' and 'rule' commands
277 if $S0 == 'regex' goto with_adverbs
278 adverbs['ratchet'] = 1
279 if $S0 == 'token' goto with_adverbs
283 $I0 = exists stmt['optable']
284 if $I0 goto rulepir_optable
285 ## compile the rule to pir
286 .local pmc p6regex, regex, rulepir
287 p6regex = compreg 'PGE::Perl6Regex'
288 regex = stmt['regex']
289 rulepir = p6regex(regex, 'target'=>'PIR', adverbs :flat :named)
292 ## this is a special rule generated via the 'is optable' trait
293 rulepir = new 'CodeString'
294 rulepir.emit(<<' END', namespace, name)
298 .param pmc adverbs :named :slurpy
299 $P0 = get_hll_global ["%0"], "$optable"
300 .return $P0.'parse'(mob, 'rulename'=>"%1", adverbs :named :flat)
305 ## add to set of rules
307 $P0 = nstable[namespace]
309 code.emit("\n## <%0::%1>\n", namespace, name)
318 .return 'regex_stmt'(stmt, namespace, nstable)
325 .return 'regex_stmt'(stmt, namespace, nstable)
336 $S0 = $P0['category']
338 name = concat $S0, $S1
341 $P0 = nstable[namespace]
342 optable = $P0['optable']
344 ## build the list of traits
346 .local string traitlist
348 iter = new 'Iterator', $P0
351 unless iter goto trait_end
354 .local string trait, arg
357 if null $P0 goto trait_arg_null
358 ## convert parsed arg to single string
360 $S0 = $P0['category']
362 arg = concat $S0, $S1
363 if arg == '' goto trait_arg_null
364 ## args starting with & are symbol lookups
365 $S0 = substr arg, 0, 1
366 if $S0 != '&' goto trait_arg
370 if trait == 'parsed' goto trait_sub
371 arg = optable.'escape'(arg)
374 optable.emit(" $P0 = get_hll_global ['%0'], '%1'", namespace, arg)
380 concat traitlist, ", '"
381 concat traitlist, trait
382 concat traitlist, "'=>"
383 concat traitlist, arg
386 name = optable.'escape'(name)
387 optable.emit(" optable.newtok(%0%1)", name, traitlist)
395 # vim: expandtab shiftwidth=4 ft=pir: