cfad47cfa3/t3compiler/tads3/samples/gramdisp.t

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
#charset "us-ascii"
2
3
/*
4
 *   Grammar displayer.  This demonstrates how to use
5
 *   GrammarProd.getGrammarInfo() by displaying the information on a given
6
 *   production object in human-readable format.
7
 *   
8
 *   You can add this into any adv3-based game (make sure you have the
9
 *   basic library's reflection module - reflect.t - included in the
10
 *   build).  We'll add a new verb to the game - "gramprod <name>" - that
11
 *   lets you display a grammar production's internal information
12
 *   interactively.
13
 */
14
15
#include <gramprod.h>
16
#include <reflect.h>
17
#include "adv3.h"
18
#include "en_us.h"
19
20
21
/*
22
 *   display the grammar tree 
23
 */
24
DefineLiteralAction(GramProd) 
25
    execAction()
26
    {
27
        /* look up the production by name */
28
        local prod = reflectionServices.symtab_[getLiteral()];
29
30
        /* check to see if we found it */
31
        if (prod != nil && prod.ofKind(GrammarProd))
32
        {
33
            /* found it - display the given production */
34
            displayProd(prod);
35
        }
36
        else
37
        {
38
            /* didn't find it */
39
            "Sorry, there's no such production as <q><<getLiteral>></q>. ";
40
        }
41
    }
42
43
    /*
44
     *   Display the given production in human-readable format.  This
45
     *   contains the same information as a 'grammar' statement, but adds
46
     *   some annotations to indicate the types of the symbols displayed.  
47
     */
48
    displayProd(prod)
49
    {
50
        local lastSubName;
51
        
52
        /* show the name of the overall production */
53
        "<<reflectionServices.valToSymbol(prod)>>:\n";
54
55
        /* get the grammar info - this is a list of GrammarAltInfo objects */
56
        local alts = prod.getGrammarInfo();
57
58
        /* we don't have a last-sub-name yet */
59
        lastSubName = nil;
60
61
        /* display each alternative */
62
        foreach (local alt in alts)
63
        {
64
            /* 
65
             *   parse the sub-name out of the match object - the name will
66
             *   be in the format prod(subname), so pull out the part in
67
             *   the parentheses 
68
             */
69
            rexMatch('.+<lparen>(.+)<rparen>',
70
                     reflectionServices.valToSymbol(alt.gramMatchObj));
71
            local subName = rexGroup(1)[3];
72
73
            /* 
74
             *   if this matches the previous rule's sub-name, just show it
75
             *   as another alternative for the same named rule; otherwise,
76
             *   show the new named rule 
77
             */
78
            if (subName == lastSubName)
79
                "\t\t| ";
80
            else
81
                "\t(<<subName>>):\n\t\t";
82
83
            /* remember the sub-name for next time */
84
            lastSubName = subName;
85
86
            /* check for badness */
87
            if (alt.gramBadness != 0)
88
                "[badness <<alt.gramBadness>>] ";
89
90
            /* show the token list */
91
            foreach (local tok in alt.gramTokens)
92
            {
93
                local nm = reflectionServices.valToSymbol(tok.gramTokenInfo);
94
                
95
                /* show the token information */
96
                switch (tok.gramTokenType)
97
                {
98
                case GramTokTypeProd:
99
                    "(prod:<<nm>>)";
100
                    break;
101
102
                case GramTokTypeSpeech:
103
                    "(pos:<<nm>>)";
104
                    break;
105
106
                case GramTokTypeNSpeech:
107
                    "(pos:";
108
                    for (local i = 1 ; i <= tok.gramTokenInfo.length() ; ++i)
109
                    {
110
                        if (i != 1)
111
                            ",";
112
                        say(reflectionServices.valToSymbol(
113
                            tok.gramTokenInfo[i]));
114
                    }
115
                    ")";
116
                    break;
117
118
                case GramTokTypeLiteral:
119
                    "'<<tok.gramTokenInfo>>'";
120
                    break;
121
122
                case GramTokTypeTokEnum:
123
                    "(tok:<<nm>>)";
124
                    break;
125
126
                case GramTokTypeStar:
127
                    "*";
128
                    break;
129
130
                default:
131
                    "(unknown)";
132
                    break;
133
                }
134
135
                /* add the target property, if present */
136
                if (tok.gramTargetProp != nil)
137
                    "-&gt;<<
138
                      reflectionServices.valToSymbol(tok.gramTargetProp)>>";
139
140
                /* add a space before the next one */
141
                " ";
142
            }
143
144
            /* finish the line */
145
            "\n";
146
        }
147
    }
148
149
    /*
150
     *   Display the given production as a 'grammar' statement or
151
     *   statements.  This will generate 'grammar' syntax that could be
152
     *   used in source code.  Note that this won't necessarily generate
153
     *   the identical syntax as the original 'grammar' statement that was
154
     *   used to create the GrammarProd object; there are many ways to
155
     *   write the same production, and the compiler doesn't keep
156
     *   information on superficial variations in syntax.  The syntax we
157
     *   generate will have the identical meaning to the original, though.
158
     *   Note also that we don't (and can't) display the source code of any
159
     *   methods defined with the match object, nor do we show any
160
     *   additional properties of the object; we only show the grammar
161
     *   definitions.  
162
     */
163
    displayProdGrammar(prod)
164
    {
165
        local lastMatchObj = nil;
166
        
167
        /* get the grammar info - this is a list of GrammarAltInfo objects */
168
        local alts = prod.getGrammarInfo();
169
170
        /* display each alternative */
171
        for (local ai = 1 ; ai <= alts.length() ; ++ai)
172
        {
173
            local alt = alts[ai];
174
            
175
            /* 
176
             *   if this matches the previous rule's full name, just show
177
             *   it as another alternative for the same named rule;
178
             *   otherwise, show the new named rule 
179
             */
180
            if (lastMatchObj == alt.gramMatchObj)
181
                "\t| ";
182
            else
183
                "grammar <<reflectionServices.valToSymbol(alt.gramMatchObj)
184
                  >>:\n\t";
185
            
186
            /* check for badness */
187
            if (alt.gramBadness != 0)
188
                "[badness <<alt.gramBadness>>] ";
189
190
            /* show the token list */
191
            foreach (local tok in alt.gramTokens)
192
            {
193
                local nm = reflectionServices.valToSymbol(tok.gramTokenInfo);
194
                
195
                /* show the token information */
196
                switch (tok.gramTokenType)
197
                {
198
                case GramTokTypeProd:
199
                case GramTokTypeSpeech:
200
                case GramTokTypeTokEnum:
201
                    say(nm);
202
                    break;
203
204
                case GramTokTypeNSpeech:
205
                    "&lt;";
206
                    for (local i = 1 ; i <= tok.gramTokenInfo.length() ; ++i)
207
                    {
208
                        if (i != 1)
209
                            " ";
210
                        say(reflectionServices.valToSymbol(
211
                            tok.gramTokenInfo[i]));
212
                    }
213
                    "&gt;";
214
                    break;
215
216
                case GramTokTypeLiteral:
217
                    "'<<tok.gramTokenInfo>>'";
218
                    break;
219
220
                case GramTokTypeStar:
221
                    "*";
222
                    break;
223
224
                default:
225
                    "(???)";
226
                    break;
227
                }
228
229
                /* add the target property, if present */
230
                if (tok.gramTargetProp != nil)
231
                    "-&gt;<<
232
                      reflectionServices.valToSymbol(tok.gramTargetProp)>>";
233
234
                /* add a space before the next one */
235
                " ";
236
            }
237
238
            /* finish the line */
239
            "\n";
240
241
            /* 
242
             *   if this is the last one with this match object, add the
243
             *   superclass specifier 
244
             */
245
            if (ai == alts.length()
246
                || alt.gramMatchObj != alts[ai+1].gramMatchObj)
247
            {
248
                /* add the superclass list */
249
                "\t: ";
250
                for (local scLst = alt.gramMatchObj.getSuperclassList(),
251
                     local i = 1 ; i <= scLst.length() ; ++i)
252
                {
253
                    if (i != 1)
254
                        ", ";
255
                    say(reflectionServices.valToSymbol(scLst[i]));
256
                }
257
258
                /* end the grammar definition */
259
                "\n;\n";
260
            }
261
262
            /* remember the match object for next time */
263
            lastMatchObj = alt.gramMatchObj;
264
        }
265
    }
266
;
267
268
VerbRule(GramProd)
269
    'gramprod' singleLiteral
270
    : GramProdAction
271
    verbPhrase = 'show/showing the grammar for (what)'
272
;