root/trunk/enki/Directive.d

Revision 289, 9.0 kB (checked in by h3r3tic, 4 years ago)

ported Enki to Tango; bootstraps, no other tests done yet

Line 
1 /+
2     Copyright (c) 2006 Eric Anderton, BCS
3
4     Permission is hereby granted, free of charge, to any person
5     obtaining a copy of this software and associated documentation
6     files (the "Software"), to deal in the Software without
7     restriction, including without limitation the rights to use,
8     copy, modify, merge, publish, distribute, sublicense, and/or
9     sell copies of the Software, and to permit persons to whom the
10     Software is furnished to do so, subject to the following
11     conditions:
12
13     The above copyright notice and this permission notice shall be
14     included in all copies or substantial portions of the Software.
15
16     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23     OTHER DEALINGS IN THE SOFTWARE.
24 +/
25 module enki.Directive;
26
27 private import enki.types;
28 private import enki.EnkiBackend;
29 private import enki.CodeGenerator;
30
31 debug private import tango.io.Stdout;
32
33 /*
34     RootOnly:
35         .baseclass
36         .classname
37         .module
38         .typelib
39         .parsetype
40         .utf
41         .boilerplate
42         
43     FirstPass:
44         .import
45         .define
46         .include
47         .header
48         
49     SecondPass:
50         .alias
51         .code
52 */
53
54
55 abstract class Directive : SyntaxLine, IRenderable{
56     enum: uint{
57         RootOnly,   
58         FirstPass,
59         SecondPass,
60     }       
61    
62     public uint type(){
63         return Directive.SecondPass;
64     }
65    
66     public void semanticPass(BaseEnkiParser root){
67         //do nothing
68     }
69    
70     public String toBNF(){
71         // do nothing
72         return "";
73     }
74    
75     public String toString(){
76         // do nothing
77         return "";
78     }
79
80     public void render(CodeGenerator generator,Statement passterm,Statement failterm){
81         // do nothing
82     }
83 }
84
85 class ImportDirective : Directive{
86     String imp;
87    
88     public uint type(){
89         return Directive.FirstPass;
90     }   
91        
92     public this(String imp){
93         this.imp = imp;
94     }
95    
96     public void semanticPass(BaseEnkiParser root){
97         root.setImport(imp);
98     }
99    
100     public String toBNF(){
101         return ".import(\"" ~ imp ~ "\");\n";
102     }
103    
104     public String toString(){
105         return "Import Directive";
106     }
107
108 }
109
110 class BaseClassDirective : Directive{
111     String name;
112    
113     public uint type(){
114         return Directive.RootOnly;
115     }   
116    
117     public this(String name){
118         this.name = name;
119     }
120    
121     public void semanticPass(BaseEnkiParser root){
122         root.setBaseClass(name);
123     }       
124    
125     public String toBNF(){
126         return ".baseclass(\"" ~ name ~ "\");\n";
127     }
128    
129     public String toString(){
130         return "Base Class Directive";
131     }   
132 }
133
134 class ClassnameDirective : Directive{
135     String name;
136    
137     public uint type(){
138         return Directive.RootOnly;
139     }
140    
141     public this(String name){
142         this.name = name;
143     }
144    
145     public void semanticPass(BaseEnkiParser root){
146         root.setClassname(name);
147     }
148    
149     public String toBNF(){
150         return ".classname(\"" ~ name ~ "\");\n";
151     }
152    
153     public String toString(){
154         return "Classname Directive";
155     }   
156 }
157
158 class DefineDirective : Directive{
159     String returnType;
160     String name;
161     String description;
162     bool isTerminal;
163    
164     public uint type(){
165         return Directive.FirstPass;
166     }
167    
168     public this(String returnType,String name,bool isTerminal,String description){
169         this.name = name;
170         this.returnType = returnType;
171         this.isTerminal = isTerminal;
172         this.description = description;
173     }
174    
175     public void semanticPass(BaseEnkiParser root){
176         root.defineUserProduction(returnType,name,description);
177     }
178    
179     public String toBNF(){
180         String terminalStr = isTerminal ? "true" : "false";
181         if(description){           
182             return ".define(\"" ~ returnType ~ "\",\"" ~ name ~ "\",\"" ~ terminalStr ~ "\",\"" ~ description ~ "\");\n";
183         }
184         else{
185             return ".define(\"" ~ returnType ~ "\",\"" ~ name ~ "\",\"" ~ terminalStr ~ "\");\n";
186         }
187     }
188    
189     public String toString(){
190         return "Define Directive";
191     }   
192 }
193
194
195 // cannot reference the parser duing bootstrap - it doesn't exist yet
196 version(Bootstrap){}
197 else{
198     private import enki.EnkiParser;
199     private import tango.io.FilePath;
200     private import tango.io.File;
201 }
202
203 class IncludeDirective : Directive{
204     String filename;
205    
206     public uint type(){
207         return Directive.FirstPass;
208     }
209    
210     public this(String filename){
211         this.filename = filename;
212     }
213    
214     public void semanticPass(BaseEnkiParser root){
215         // cannot reference the parser duing bootstrap - it doesn't exist yet
216         version(Bootstrap){
217             throw new Exception("Include directive is meaningless during bootstrap phase.");
218         }
219         else{
220             if(!FilePath(filename).exists){
221                 throw new Exception("Cannot include '" ~ filename ~ "'; file doesn't exist.");
222             }
223                
224             auto parser = new EnkiParser();
225             parser.initalize(cast(char[])File(filename).read());
226             auto result = parser.parse_Syntax();
227            
228             if(result.success){
229                 auto syntax = result.result;
230                 root.add(parser);
231             }
232             else{
233                 throw new Exception("In file '" ~ filename ~ "':\n" ~ parser.getErrorReport());
234             }
235         }       
236     }
237                
238     public String toBNF(){
239         return "#.include(\"" ~ filename ~ "\");\n";
240     }
241    
242     public String toString(){
243         return "Include Directive";
244     }   
245 }
246
247
248 class AliasDirective : Directive{
249     String rule;
250     String ruleAlias;
251    
252     public uint type(){
253         return Directive.SecondPass;
254     }
255    
256     public this(String rule,String ruleAlias){
257         this.rule = rule;
258         this.ruleAlias = ruleAlias;
259     }
260    
261     public void semanticPass(BaseEnkiParser root){
262         root.aliasRule(rule,ruleAlias);
263     }
264    
265     public String toBNF(){
266         return ".alias(\"" ~ rule ~ "\",\"" ~ ruleAlias ~ "\");\n";
267     }
268    
269     public String toString(){
270         return "Alias Directive";
271     }   
272    
273     public void render(CodeGenerator generator,Statement passterm,Statement failterm){
274         generator.emit("alias parse_" ~ rule ~ " parse_" ~ ruleAlias ~ ";");
275     }
276 }
277
278 class ModuleDirective : Directive{
279     String moduleName;
280    
281     public uint type(){
282         return Directive.RootOnly;
283     }
284    
285     public this(String moduleName){
286         this.moduleName = moduleName;
287     }
288    
289     public void semanticPass(BaseEnkiParser root){
290         root.setModulename(moduleName);
291     }
292    
293     public String toBNF(){
294         return ".module(\"" ~ moduleName ~ "\");\n";
295     }
296    
297     public String toString(){
298         return "Module Directive";
299     }   
300 }
301
302
303 class CodeDirective : Directive{
304     String code;
305    
306     public uint type(){
307         return Directive.SecondPass;
308     }
309        
310     public this(String code){
311         this.code = code;
312     }
313    
314     public void semanticPass(BaseEnkiParser root){
315         //do nothing
316     }
317    
318     public String toBNF(){
319         return ".code{{{" ~ code ~ "}}}\n";
320     }
321    
322     public String toString(){
323         return "Code Directive";
324     }   
325    
326     public void render(CodeGenerator generator,Statement passterm,Statement failterm){
327         generator.emit(code);
328     }   
329 }
330
331 class TypelibDirective : Directive{
332     String moduleName;
333    
334     public uint type(){
335         return Directive.RootOnly;
336     }
337    
338     public this(String moduleName){
339         this.moduleName = moduleName;
340     }
341    
342     public void semanticPass(BaseEnkiParser root){
343         root.setTypelibName(moduleName);
344     }
345    
346     public String toBNF(){
347         return ".typelib(\"" ~ moduleName ~ "\");\n";
348     }
349    
350     public String toString(){
351         return "Typelib Directive";
352     }   
353 }
354
355 class ParseTypeDirective : Directive{
356     String typeName;
357    
358     public uint type(){
359         return Directive.RootOnly;
360     }
361    
362     public this(String typeName){
363         this.typeName = typeName;
364     }
365    
366     public void semanticPass(BaseEnkiParser root){
367         root.setParseType(typeName);
368     }
369    
370     public String toBNF(){
371         return ".parsetype(\"" ~ typeName ~ "\");\n";
372     }
373    
374     public String toString(){
375         return "Parse-Type Directive";
376     }   
377 }
378
379
380 class BoilerplateDirective : Directive{
381     String code;
382    
383     public uint type(){
384         return Directive.RootOnly;
385     }
386        
387     public this(String code){
388         this.code = code;
389     }
390    
391     public void semanticPass(BaseEnkiParser root){
392         root.setBoilerplate(code);
393     }
394    
395     public String toBNF(){
396         return ".boilerplate{{{" ~ code ~ "}}}\n";
397     }
398    
399     public String toString(){
400         return "Boilerplate Directive";
401     }   
402 }
403
404 class HeaderDirective : Directive{
405     String code;
406    
407     public uint type(){
408         return Directive.FirstPass;
409     }
410        
411     public this(String code){
412         this.code = code;
413     }
414    
415     public void semanticPass(BaseEnkiParser root){
416         root.setHeader(code);
417     }
418    
419     public String toBNF(){
420         return ".header{{{" ~ code ~ "}}}\n";
421     }
422    
423     public String toString(){
424         return "Header Directive";
425     }
426 }
427
428 class UTFDirective : Directive{
429     String value;
430    
431     public uint type(){
432         return Directive.RootOnly;
433     }
434        
435     public this(String value){
436         this.value = value;
437     }
438    
439     public void semanticPass(BaseEnkiParser root){
440         switch(value){
441         case "8":
442         case "32":
443         case "16":
444             break;
445         default:
446             throw new Exception("The value '" ~ value ~ "' is not a valid UTF parameter.  Expected '8', '16' or '32'");
447         }
448         root.setUTF(value);     
449     }
450    
451     public String toBNF(){
452         return ".utf(\"" ~ value ~ "\");\n";
453     }   
454    
455     public String toString(){
456         return "UTF Directive";
457     }
458 }
Note: See TracBrowser for help on using the browser.