1 # Copyright (C) 2005-2008, The Perl Foundation.
5 TGE::Compiler - A compiler for the grammar syntax of TGE.
11 .namespace [ 'TGE::Compiler' ]
14 load_bytecode 'TGE.pbc'
16 $P0 = get_class 'TGE::Grammar'
17 $P1 = subclass $P0, 'TGE::Compiler'
22 Take the source string for a tree grammar, and return a sensible data
27 .sub parse_grammar :method
30 # Parse the source string and build a match tree
33 start_rule = find_global "TGE::Parser", "start"
34 match = start_rule(source, 'grammar'=>'TGE::Parser')
36 unless match goto err_parse # if parse fails, stop
37 # say 'parse succeeded'
38 # say 'Match tree dump:'
39 # load_bytecode "dumper.pbc"
40 # load_bytecode "PGE/Dumper.pbc"
41 # '_dumper'(match, "match")
43 # Transform the parse tree and return the result
45 tree_match = self.apply(match)
46 $P5 = tree_match.get('result')
47 # say 'Data structure dump:'
48 # '_dumper'($P5, "syntax tree")
52 print "Unable to parse the tree grammar.\n"
57 .sub init :vtable :method
58 self.add_rule("ROOT", "result", ".", "ROOT_result")
59 self.add_rule("statements", "result", ".", "statements_result")
60 self.add_rule("statement", "result", ".", "statement_result")
61 self.add_rule("transrule", "result", ".", "transrule_result")
62 self.add_rule("grammardec", "result", ".", "grammardec_result")
63 self.add_rule("type", "value", ".", "type_value")
64 self.add_rule("inherit", "value", ".", "inherit_value")
65 self.add_rule("name", "value", ".", "name_value")
66 self.add_rule("parent", "value", ".", "parent_value")
67 self.add_rule("action", "value", ".", "action_value")
68 self.add_rule("language", "value", ".", "language_value")
71 .sub ROOT_result :method
74 $I0 = exists node["TGE::Parser::statements"]
75 unless $I0 goto err_no_tree
76 $P0 = node["TGE::Parser::statements"]
77 $P2 = tree.get('result', $P0, 'statements')
81 print "Top-level rule did not match.\n"
85 .sub statements_result :method
89 statements = new 'ResizablePMCArray'
91 # Iterate over the list of statements, and generate a processed tree for
92 # each statement. Return an array of all the processed statements.
94 iter = new 'Iterator', node # loop over the array
95 iter = 0 # start at the beginning
97 unless iter goto loop_end
99 $P2 = tree.get('result', $P1, 'statement')
106 print "This grammar contained no statements.\n"
110 .sub statement_result :method
116 iter = new 'Iterator', node # setup iterator for node
119 unless iter, iter_end # while (entries) ...
120 shift $S1, iter # get the key of the iterator
123 result = tree.get('result', $P2, $S1)
131 .sub transrule_result :method
138 iter = new 'Iterator', node # setup iterator for node
141 unless iter, iter_end # while (entries) ...
143 shift $S1, iter # get the key of the iterator
146 $P3 = tree.get('value', $P2, $S1)
152 $I0 = defined rule["parent"]
153 if $I0 goto parent_defined
156 rule["build"] = "rule"
160 print "Unable to find all the components of a rule definition\n"
165 .sub grammardec_result :method
172 iter = new 'Iterator', node # setup iterator for node
175 unless iter, iter_end # while (entries) ...
177 shift $S1, iter # get the key of the iterator
180 $P3 = tree.get('value', $P2, $S1)
185 decl["build"] = "grammar"
189 # The attribute 'value' on nodes of type 'inherit'.
190 .sub inherit_value :method
196 value = tree.get('value', $P2, 'type')
200 # The attribute 'value' on nodes of type 'type'.
201 .sub type_value :method
211 # The attribute 'value' on nodes of type 'name'.
212 .sub name_value :method
223 # The attribute 'value' on nodes of type 'parent'.
224 .sub parent_value :method
236 # The attribute 'value' on nodes of type 'action'.
237 .sub action_value :method
240 .local pmc value, infile
242 value = new 'CodeString'
243 infile = get_global '$!infile'
245 (lineno) = $P2.'line_number'()
246 value.'emit'('#line %0 %1', lineno, infile)
251 # The attribute 'value' on nodes of type 'language'.
252 # (This will be refactored out to a general syntax for modifiers.)
253 .sub language_value :method
267 Compile a grammar from a source string.
271 .sub 'precompile' :method
273 .param string infile :optional
274 .param int has_infile :opt_flag
276 .local string outstring
277 .local string header_string
279 if has_infile goto quote_infile
283 infile = concat '"', infile
288 set_global '$!infile', $P0
290 # Unnamed grammars are class 'AnonGrammar'
291 .local string grammarname
292 grammarname = 'AnonGrammar'
293 rule_data = self.'parse_grammar'(source)
295 # Construct grammar rules from the data structure of rule info
298 iter = new 'Iterator', rule_data # loop over the rule info
299 iter = 0 # start at the beginning
301 unless iter goto loop_end
302 statement = shift iter
303 $S0 = statement['build']
304 unless $S0 == 'rule' goto grammar_build
305 $S1 = self.'rule_string'(statement)
307 $S2 = self.'rule_header'(statement)
311 $S1 = self.'grammar_string'(statement)
313 grammarname = statement['type']
317 outstring .= "\n.sub init :vtable :method\n"
318 outstring .= header_string
319 outstring .= "\n.end\n"
321 .return (outstring, grammarname)
324 .sub 'compile' :method
328 compiler = compreg "PIR"
331 .local string grammarname
333 .local pmc new_grammar
335 (code, grammarname) = self.'precompile'(source)
337 unless grammarname == 'AnonGrammar' goto named_grammar
339 $P2['type'] = 'AnonGrammar'
340 $P2['inherit'] = 'TGE::Grammar'
341 $S1 = self.'grammar_string'($P2)
344 libloader = compiler(code)
347 new_grammar = new grammarname
348 .return (new_grammar)
351 .sub 'rule_header' :method
359 parent = rule["parent"]
360 output = " self.add_rule('"
374 .sub 'rule_string' :method
383 code .= "' :method\n"
384 code .= " .param pmc tree\n"
385 code .= " .param pmc node\n"
392 # NOTE - this code assumes that a type of '' is impossible
393 # (in older versions of Parrot, it was)
395 .sub 'grammar_string' :method
399 .local string inherit
400 type = grammar["type"]
401 inherit = grammar["inherit"]
402 code = "\n.namespace"
403 if type == '' goto no_type
409 code .= ".sub '__onload' :load :init\n"
410 code .= " load_bytecode 'TGE.pbc'\n"
411 code .= " push_eh class_loaded\n"
412 code .= " $P1 = subclass '"
418 code .= " class_loaded:\n"
425 Allison Randal <allison@perl.org>
433 # vim: expandtab shiftwidth=4 ft=pir: