root/trunk/enki/Rule.d

Revision 289, 13.2 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.Rule;
26
27 private import enki.types;
28 private import enki.EnkiBackend;
29 private import enki.Expression;
30 private import enki.CodeGenerator;
31
32 private import tango.io.Stdout;
33
34 class Rule : SyntaxLine, IRenderable{
35     String name;
36     RulePredicate pred;
37     Expression expr;
38     RuleDecl decl;
39     String lhs;
40     String type;
41     bool semanticDone;
42     Param[String] params;
43    
44     protected this(){
45     }
46        
47     public this(String name,RulePredicate pred,Expression expr,RuleDecl decl=null){
48         this.name = name;
49         this.pred = pred;
50         this.expr = expr;
51         this.decl = decl;
52        
53         if(!pred){
54             this.pred = new DefaultPredicate();
55         }
56         if(!decl){
57             this.decl = new RuleDecl();
58         }
59     }
60    
61     public void semanticPass(BaseEnkiParser root){
62         try{
63             if(semanticDone) return;
64             semanticDone = true;
65            
66             expr.semanticPass(this,root);
67             pred.semanticPass(this,root);
68             decl.semanticPass(this,root);
69            
70             foreach(param; params){
71                 param.semanticPass(this,root);
72             }
73            
74             type = pred.getType(this,root);
75         }
76         catch(Exception e){
77             throw new Exception("during semantic pass of Rule '" ~ name ~ "'\n" ~ e.toString());           
78         }
79     }
80        
81     public String getType(BaseEnkiParser root){
82         if(!semanticDone) semanticPass(root);
83         if(type) return type;
84        
85         type = pred.getType(this,root);
86        
87         return type;
88     }
89    
90     public String resolveBindingType(String name,BaseEnkiParser root){
91         debug writefln("%s Rule.resolveBindingType %s",this.name,name);
92         String type = decl.resolveBindingType(name);
93         if(!type) type = pred.resolveBindingType(name);
94         if(!type) type = expr.resolveBindingType(name,root);
95        
96         //resolve using params
97         if(!type) foreach(param; params){
98             if(param.name == name && param.realType != null){
99                 type = param.realType;
100                 break;
101             }
102         }
103
104        
105         return type;
106     }
107        
108     public void resolveBinding(String name){
109         if(pred.resolveBinding(name)) return;
110         if(decl.resolveBinding(name)) return;
111        
112         this.params[name] = new Param(name);
113        
114         //throw new Exception("Binding '" ~ name ~ "' is not declared.");
115     }   
116            
117     public void render(CodeGenerator generator,Statement pass,Statement fail){
118         auto matchLabel = new Label("match");
119         auto gotoMatch = new Goto(matchLabel);
120         auto mismatchLabel = new Label("mismatch");
121         auto gotoMismatch = new Goto(mismatchLabel);
122        
123         with(generator){
124             auto startLabel = getUniqueLabel("start");
125             indent();
126                 emit("/*");
127                 emit(this.toBNF());
128                 emit("*/");
129                
130                 emit("public ResultT!(" ~ type ~ ") parse_" ~ name ~ "(" ~ decl.renderDeclaration() ~ "){");
131                 indent();
132                     emit("debug Stdout.formatln(\"parse_" ~ name ~ "()\");");
133                     emit("uint " ~ startLabel ~ " = position;");
134                     pred.renderDeclarations(generator,decl.paramXRef);
135                     emit("");
136                     foreach(param; params){
137                         emit(param.toString() ~ ";");
138                     }
139                     emit("");
140                     render(expr,gotoMatch,gotoMismatch);
141                    
142                     render(matchLabel);
143                     emit("debug Stdout.formatln(\"parse_" ~ name ~ "() PASS\");");
144                     pred.renderPass(generator,startLabel);
145                    
146                     render(mismatchLabel);
147                     emit("position = " ~ startLabel ~ ";");
148                     pred.renderFail(generator,startLabel);
149                                
150                 unindent();
151                 emit("}");
152             unindent();
153             emit("");
154         }
155     }
156    
157     public String toBNF(){     
158         String result = "\n" ~ name ~ decl.toBNF() ~ "\n";
159         if(!(cast(DefaultPredicate)pred)) result ~= "\t= " ~ pred.toBNF() ~ "\n";
160         result ~= "\t::=" ~ expr.toBNF() ~ ";\n";
161         return result;
162     }
163    
164 }
165
166 class RuleDecl{
167     Param[String] paramXRef;
168     Param[] params;
169    
170     public this(Param[] params...){
171         foreach(param; params){
172             this.params ~= param;
173             this.paramXRef[param.name] = param;
174         }
175     }
176    
177     public String renderDeclaration(){
178         String result = "";
179         bool first = true;
180         foreach(param; params){
181             if(first){
182                 result ~= "inout " ~ param.toString();
183                 first = false;
184             }
185             else{
186                 result ~= ",inout " ~ param.toString();
187             }
188         }
189         return result;
190     }
191    
192     public void semanticPass(Rule thisRule,BaseEnkiParser root){
193         foreach(param; params){
194             param.semanticPass(thisRule,root);
195         }
196     }       
197    
198     public bool resolveBinding(String name){
199         foreach(param; params){
200             if(param.name == name) return true;
201         }
202         return false;
203     }
204    
205     public String resolveBindingType(String name){
206         if(name in paramXRef){
207             return paramXRef[name].realType;
208         }
209         return null;
210     }   
211    
212     public String toBNF(){
213         if(params.length == 0) return "";
214         String result = "(";
215         bool first = true;
216         foreach(param; params){
217             if(first){
218                 result ~= param.toBNF();
219                 first = false;
220             }
221             else{
222                 result ~= "," ~ param.toBNF();
223             }
224         }
225         result ~= ")";
226         return result;
227     }
228 }
229
230 abstract class RulePredicate{
231     public void renderDeclarations(CodeGenerator generator,Param[String] ruleParams);
232     public void renderPass(CodeGenerator generator,String startLabel);
233     public void renderFail(CodeGenerator generator,String startLabel);
234     public void semanticPass(Rule thisRule,BaseEnkiParser root);
235     public bool resolveBinding(String name);
236     public String resolveBindingType(String name);
237     public String getType(Rule thisRule,BaseEnkiParser root);
238     public String toBNF();
239 }
240
241 class DefaultPredicate : RulePredicate{
242     public this(){
243     }
244    
245     public void renderDeclarations(CodeGenerator generator,Param[String] ruleParams){
246         generator.emit("//no declarations");
247     }
248    
249     public void renderPass(CodeGenerator generator,String startLabel){
250         generator.emit("return ResultT!(bool)(true);");
251     }
252    
253     public void renderFail(CodeGenerator generator,String startLabel){
254         generator.emit("return ResultT!(bool)();");
255     }
256    
257     public void semanticPass(Rule thisRule,BaseEnkiParser root){
258         //do nothing
259     }
260    
261     public bool resolveBinding(String name){
262         return false;
263     }
264    
265     public String resolveBindingType(String name){
266         return null;
267     }
268    
269     public String getType(Rule thisRule,BaseEnkiParser root){
270         return "bool";
271     }
272    
273     public String toBNF(){
274         return "";
275     }
276 }
277
278 class ClassPredicate : RulePredicate{
279     Param[] params;
280     String type;
281    
282     public this(String type,Param[] params...){
283         this.type = type;
284         this.params = params.dup;
285     }
286    
287     public void renderDeclarations(CodeGenerator generator,Param[String] ruleParams){
288         foreach(uint i,param; params){
289             if(param.name in ruleParams) continue;
290             generator.emit(param.toString() ~ ";");
291         }
292     }
293    
294     public void renderPass(CodeGenerator generator,String startLabel){
295         String args = "";
296         foreach(uint i,param; params){
297             if(i==0){
298                 args ~= param.getName();
299             }
300             else{
301                 args ~= "," ~ param.getName();
302             }
303         }
304         generator.emit("ResultT!(" ~ type ~ ") passed = ResultT!(" ~ type ~ ")(new " ~ type ~ "(" ~ args ~ "));");
305         generator.emit("return passed;");
306     }
307    
308     public void renderFail(CodeGenerator generator,String startLabel){
309         generator.emit("ResultT!(" ~ type ~ ") failed = ResultT!(" ~ type ~ ")();");
310         generator.emit("return failed;");
311     }
312    
313     public void semanticPass(Rule thisRule,BaseEnkiParser root){
314         foreach(param; params){
315             param.semanticPass(thisRule,root);
316         }
317     }       
318    
319     public bool resolveBinding(String name){
320         foreach(param; params){
321             if(param.name == name) return true;
322         }
323         return false;
324     }
325    
326     public String resolveBindingType(String name){
327         foreach(param; params){
328             if(param.name == name) return param.realType;
329         }
330         return null;
331     }   
332    
333     public String getType(Rule thisRule,BaseEnkiParser root){
334         return type;
335     }
336    
337     public String toBNF(){
338         String result = "new " ~ type ~ "(";
339         foreach(uint i,param; params){
340             if(i==0){
341                 result ~= param.toBNF();
342             }
343             else{
344                 result ~= "," ~ param.toBNF();
345             }
346         }
347         result ~= ")";
348         return result;
349     }
350 }
351    
352 class FunctionPredicate : RulePredicate{
353     Param[] params;
354     Param decl;
355    
356     public this(Param decl,Param[] params...){
357         this.decl = decl;
358         this.params = params.dup;
359     }
360    
361     public void renderDeclarations(CodeGenerator generator,Param[String] ruleParams){
362         foreach(uint i,param; params){
363             if(!(param.name in ruleParams)){
364                 generator.emit(param.toString() ~ ";");
365             }
366         }
367     }
368    
369     public void renderPass(CodeGenerator generator,String startLabel){
370         String args = "";
371         foreach(uint i,param; params){
372             if(i==0){
373                 args ~= param.getName();
374             }
375             else{
376                 args ~= "," ~ param.getName();
377             }
378         }
379         if(decl.type == "void"){
380             generator.emit(decl.name ~ "(" ~ args ~ ");");
381             generator.emit("return ResultT!(String)(sliceData(" ~ startLabel ~ ",position));");
382         }
383         else{
384             generator.emit("auto value = " ~ decl.name ~ "(" ~ args ~ ");");
385             generator.emit("return ResultT!(" ~ decl.realType ~ ")(value);");
386         }
387     }
388    
389     public void renderFail(CodeGenerator generator,String startLabel){
390         if(decl.type == "void"){
391             generator.emit("return ResultT!(String)();");
392         }
393         else{
394             generator.emit("return ResultT!(" ~ decl.realType ~ ")();");
395         }
396     }   
397    
398     public void semanticPass(Rule thisRule,BaseEnkiParser root){
399         //decl.semanticPass(thisRule,root); // not needed
400        
401         foreach(param; params){
402             param.semanticPass(thisRule,root);
403         }
404     }   
405        
406     public bool resolveBinding(String name){
407         foreach(param; params){
408             if(param.name == name) return true;
409         }
410         return false;
411     }
412        
413     public String resolveBindingType(String name){
414         foreach(param; params){
415             if(param.name == name){
416                 return param.realType;
417             }
418         }
419         return null;
420     }       
421    
422     public String getType(Rule thisRule,BaseEnkiParser root){
423         if(decl.type == "void"){
424             return root.getParseType();
425         }
426         else{
427             return decl.getType(thisRule,root);
428         }
429     }
430    
431     public String toBNF(){
432         String result = decl.toBNF() ~ "(";
433         foreach(uint i,param; params){
434             if(i==0){
435                 result ~= param.toBNF();
436             }
437             else{
438                 result ~= "," ~ param.toBNF();
439             }
440         }
441         result ~= ")";
442         return result;
443     }   
444 }
445
446 class BindingPredicate : RulePredicate{
447     Param decl;
448    
449     public this(Param decl){
450         this.decl = decl;
451     }
452    
453     public void renderDeclarations(CodeGenerator generator,Param[String] ruleParams){
454         if(!(decl.name in ruleParams)){
455             generator.emit(decl.toString() ~ ";");
456         }
457     }
458    
459     public void renderPass(CodeGenerator generator,String startLabel){
460         generator.emit("return ResultT!(" ~ decl.realType ~ ")(" ~ decl.getName() ~ ");");
461     }
462    
463     public void renderFail(CodeGenerator generator,String startLabel){
464         generator.emit("return ResultT!(" ~ decl.realType ~ ")();");
465     }
466    
467     public void semanticPass(Rule thisRule,BaseEnkiParser root){
468         decl.semanticPass(thisRule,root);
469     }   
470    
471     public bool resolveBinding(String name){
472         return decl.name == name;
473     }
474    
475     public String resolveBindingType(String name){
476         if(decl.name == name) return decl.realType;
477         return null;
478     }       
479    
480     public String getType(Rule thisRule,BaseEnkiParser root){
481         return decl.getType(thisRule,root);
482     }
483    
484     public String toBNF(){
485         return decl.toBNF();
486     }       
487 }
488
489 class Param{
490     public bool isArray;
491     public String type;
492     public String name;
493     public String realType;
494    
495     public this(bool isArray,String type,String name){
496         this.isArray = isArray;
497         this.type = type;
498         this.name = name;
499         this.realType = type;
500         if(this.isArray) this.realType ~= "[]";
501     }
502    
503     public this(String name){
504         this.name = name;
505         this.type = null;
506     }
507    
508     public String getName(){
509         return "bind_" ~ name;
510     }
511    
512     public void semanticPass(Rule thisRule,BaseEnkiParser root){
513         getType(thisRule,root);
514     }
515    
516     public String getType(Rule thisRule,BaseEnkiParser root){
517         if(realType) return realType;
518        
519         debug writefln("resolve type");
520         type = thisRule.resolveBindingType(name,root);
521         //if(!type) throw new Exception("Cannot resolve type of binding '" ~ this.name ~ "'");
522         if(!type){
523              type = root.parseType;
524              debug writefln("resolving " ~ name ~ " to " ~ root.parseType);
525          }
526         realType = type;
527        
528         //debug writefln("param: %s resolved to %s",this.name,realType);
529         return realType;
530     }
531    
532     public String toString(){
533         String result = "";
534         result ~= type;
535         if(isArray) result ~= "[]";
536         result ~= " bind_" ~ name;
537        
538         return result;
539     }
540    
541     public String toBNF(){
542         String result = "";
543         result ~= type;
544         if(isArray) result ~= "[]";
545         result ~= " " ~ name;
546        
547         return result;
548     }       
549 }
Note: See TracBrowser for help on using the browser.