-
Notifications
You must be signed in to change notification settings - Fork 138
/
TGE.pir
123 lines (91 loc) · 3.35 KB
/
TGE.pir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Copyright (C) 2005-2007, The Perl Foundation.
=head1 NAME
TGE - A tree grammar engine.
=head1 SYNOPSIS
# define a grammar leaf.tg
transform min (Leaf) :language('PIR') {
$P1 = getattribute node, "value"
.return ($P1)
}
...
# and elsewhere...
.sub _main :main
load_bytecode 'TGE.pir'
# Compile a grammar from the source grammar file
.local pmc compiler
compiler = new 'TGE::Compiler'
.local pmc grammar
grammar = compiler.'compile'(source)
.local pmc tree
# ... the tree to be manipulated
# Apply the grammar to the tree
.local pmc TGI
TGI = grammar.apply(tree)
# Return the result of a particular rule on a particular tree
.local pmc result
result = TGI.get('min')
# ...
.end
=head1 DESCRIPTION
TGE is a tool for transforming trees. Think of it as a good
old-fashioned substitution, but instead of taking and returning strings,
it takes and returns trees.
TGE is most heavily used in the compiler tools suite, where it
transforms the trees output by PGE into abstract syntax trees.
TGE has both a procedural interface and a syntax interface. The syntax
interface is easiest for humans to use when constructing grammars by
hand. The procedural interface is preferable for computer generated
grammars.
This is the syntax for tree grammar rules:
transform name (pattern) {
# action
}
The I<name> is the name of the transform rule. The I<pattern> is the type of
node this particular transform applies to. You can have multiple transforms
with the same name, as long as they match different patterns. The I<action> is
a block of code that executes the transform. You can specify what language the
action code is written in with the C<:language> modifier. At the moment, the
only valid language is PIR. Within the block, two parameters are supplied for
you: C<node> is the current node considered, and C<tree> is the top-level node
for the entire tree.
The C<:applyto> modifier says which node the transform applies to.
transform name (pattern) :applyto('childname') {
# action
}
By default the transform applies to the current node (generally synthesized
attributes), but you can specify the name of a child node if the transform
applies to a child of the current node (generally inherited attributes).
=cut
.namespace [ 'TGE' ]
.sub '__onload' :load
# make sure we execute this sub only once
$P0 = get_global '$!tge_loaded'
unless null $P0 goto end
$P0 = new 'Integer'
assign $P0, 1
set_global '$!tge_loaded', $P0
# use other modules
load_bytecode 'PGE.pbc'
load_bytecode 'PGE/Util.pbc'
load_bytecode 'compilers/tge/TGE/Rule.pbc'
load_bytecode 'compilers/tge/TGE/Tree.pbc'
load_bytecode 'compilers/tge/TGE/Parser.pbc'
load_bytecode 'compilers/tge/TGE/Grammar.pbc'
load_bytecode 'compilers/tge/TGE/Compiler.pbc'
# import <die> and <line_number> rules from PGE::Util
$P0 = get_class ['TGE::Parser']
$P1 = get_hll_global ['PGE::Util'], 'die'
$P0.'add_method'('die', $P1)
$P1 = get_hll_global ['PGE::Util'], 'line_number'
$P0.'add_method'('line_number', $P1)
end:
.return ()
.end
=head1 AUTHOR
Allison Randal <allison@perl.org>
=cut
# Local Variables:
# mode: pir
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4: