root/trunk/enki/BaseParser.d

Revision 290, 6.9 kB (checked in by h3r3tic, 4 years ago)

incorporated bobef's Tango patch for enki.d; thanks!

Line 
1 /+
2     Copyright (c) 2006 Eric Anderton
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.BaseParser;
26 /**
27     Runtime parser engine.
28     
29     Include this with your generated enki output.
30 */
31
32 private import enki.types;
33 private import enki.IParser;
34
35 import tango.text.Util;
36 import tango.text.Unicode;
37 import tango.io.Stdout;
38 import tango.text.Regex;
39 import tango.text.convert.Format;
40
41 alias ResultT!(bool) ResultBool;
42 alias ResultT!(String) ResultString;
43
44 abstract class BaseParser: IParser{
45     struct ErrorData{
46         uint pos;
47         String text;
48     }
49    
50     protected String data;
51 //  protected uint pos;
52     protected ErrorData[] errors;
53    
54     public this(){
55     }
56    
57     //NOTE: oops. :(
58     alias initalize initialize;
59    
60     public void initalize(String input){
61         data = input;
62         pos = 0;
63     }
64     /*
65     protected uint position(){
66         return this.pos;
67     }
68     
69     protected void position(uint  newPos){
70         this.pos = newPos;
71     }*/
72    
73     uint position;
74     alias position pos;
75    
76     protected String sliceData(uint start,uint end){
77         return data[start..end];
78     }
79        
80     /** error handling **/
81     protected void setError(String text){
82         debug Stdout.formatln("[{}] Error: {}",pos,text);
83         ErrorData data;
84         data.pos = pos;
85         data.text = text;       
86         errors ~= data;
87     }
88    
89     protected void setError(String text,int pos){
90         ErrorData data;
91         data.pos = pos;
92         data.text = text;
93         errors ~= data;
94     }
95    
96     protected void clearErrors(){
97         errors = (ErrorData[]).init;
98     }
99    
100     public String getErrorReport(){
101         String result = "";
102         foreach(ErrorData err; errors){
103             uint line=1;
104             uint startOfLine = 0;
105             for(uint i=0; i<err.pos; i++){
106                 if(data[i] == '\n'){
107                     startOfLine = i;
108                     line++;
109                 }
110             }
111             result ~= transcodeToString(Format("({},{}) {}\n",line,err.pos-startOfLine+1,err.text));
112         }
113         return result;
114     }
115    
116     public bool hasErrors(){
117         return errors.length > 0;
118     }
119    
120     /** IParser hooks **/   
121    
122     public ResultString terminal(String str){
123         uint start = pos;
124         //writefln("match: %s %d (%d) %d",str,position,data[pos],data.length);
125         if(position >= data.length || str.length > data.length - pos || data[pos..pos+str.length] != str){
126             setError("Expected '" ~ str ~ "'");
127             return ResultString();
128         }
129         pos += str.length;
130         return ResultString(data[start..pos]);
131     }
132        
133     public ResultString terminal(uint ch){
134         if(pos >= data.length || data[pos] != cast(dchar)ch){
135             //TODO: find an error message for this
136             //setError("Expected char");
137             return ResultString();
138         }
139         pos++;
140         return ResultString(data[pos-1..pos]); 
141     }
142    
143     public ResultString regexp(String str){
144         assert(false,"Regular Expressions are not supported.");
145         /*
146         if (auto m = std.regexp.search(data[pos..$],str))
147         {
148             if(m.pre.length == 0){
149                 auto result = m.match(0);
150                 pos += result.length;
151                 return ResultString(result);
152             }
153         }
154         return ResultString();*/
155     }
156    
157     public ResultString range(uint start,uint end){
158         if(pos >= data.length || !(data[pos] >= cast(dchar)start && data[pos] <= cast(dchar)end)){
159             //TODO: find an error message for this
160             //setError("Expected range");
161             return ResultString();
162         }
163         pos++;
164         return ResultString(data[pos-1..pos]);     
165     }
166    
167     /** rudimentary parsers **/
168    
169     public ResultBool parse_eoi(){
170         if(pos >= data.length){
171             setError("Expected end-of-input");
172             return ResultBool(true);
173         }
174         return ResultBool();
175     }
176
177
178     public ResultString parse_letter(){
179         if(pos >= data.length ||
180             !((data[pos] >= 'a' && data[pos] <= 'z') ||
181             (data[pos] >= 'A' && data[pos] <= 'Z'))){
182             setError("Expected letter");
183             return ResultString();
184         }
185         pos++;
186         return ResultString(data[pos-1..pos]);
187     }
188    
189     public ResultString parse_digit(){
190         if(pos >= data.length || (!(data[pos] >= '0' && data[pos] <= '9'))){
191             setError("Expected digit");
192             return ResultString();
193         }
194         pos++;
195         return ResultString(data[pos-1..pos]);
196     }
197    
198     public ResultString parse_hexdigit(){
199         if(pos >= data.length ||
200             !((data[pos] >= '0' && data[pos] <= '9') ||
201             (data[pos] >= 'a' && data[pos] <= 'f') ||
202             (data[pos] >= 'A' && data[pos] <= 'F'))){           
203             setError("Expected hex digit");
204             return ResultString();
205         }
206         pos++;
207         return ResultString(data[pos-1..pos]);
208     }
209    
210     public ResultString parse_any(){
211         if(pos >= data.length){
212             setError("Unexpected end-of-input");
213             return ResultString();
214         }
215         pos++;
216         return ResultString(data[pos-1..pos]);
217     }
218    
219     public ResultString parse_newline(){
220         uint start = pos;
221         if(pos < data.length){ 
222             if(data[pos] == '\r'){
223                 pos++;
224             }
225             if(data[pos] == '\n'){
226                 pos++;
227                 return ResultString(data[start..pos]);
228             }
229         }
230         setError("Expected newline");
231         return ResultString();
232     }
233    
234     public ResultBool parse_eol(){
235         if(pos >= data.length){
236             return ResultBool(true);
237         }
238        
239         uint start = pos;
240         if(position < data.length){
241             if(data[pos] == '\r'){
242                 pos++;
243             }
244             if(data[pos] == '\n'){
245                 pos++;
246                 return ResultBool(true);
247             }
248         }
249         setError("Expected end-of-line");
250         return  ResultBool();
251     }
252    
253     public ResultString parse_ws(){
254         uint start = position;
255         while(pos < data.length){
256             switch(data[pos]){
257             case '\n':
258             case '\r':
259             case '\t':
260             case '\v':
261             case '\f':
262             case ' ':
263                 pos++;
264                 break;
265             default:
266                 goto done;
267             }           
268         }
269         done:
270         return ResultString(data[start..pos]); // always a success
271     }
272    
273     public ResultString parse_sp(){
274         uint start = position;
275         while(pos < data.length){
276             switch(data[pos]){
277             case '\n':
278             case '\r':
279             case '\t':
280             case '\v':
281             case '\f':
282             case ' ':
283                 pos++;
284                 break;
285             default:
286                 goto done;
287             }           
288         }
289     done:
290         if(start == pos) return ResultString();
291         return ResultString(data[start..pos]);
292     }
293    
294     public ResultBool parse_err(){
295         throw new Exception(.toString(getErrorReport()));
296         return ResultBool(false);
297     }
298 }
Note: See TracBrowser for help on using the browser.