root/lang/haxe/Tonyu2/Parser.hx @ 35690

Revision 35690, 4.9 kB (checked in by hoge1e3, 4 years ago)
Line 
1//using System;
2//using System.Collections.Generic;
3
4class ParseError  {
5    var message:String;
6        public function new(mesg:String){this.message=mesg;}
7}
8typedef Combinator = Void->Dynamic;
9//public delegate object Combinator();
10//public delegate void VoidSub();
11class Parser {
12        var input:String;
13        var context:Dynamic;
14        var p:Int;
15        var maxErrorPos:Int;
16        static var space = ~/^\s*/;
17        public function new(input:String) {
18          this.input=input;
19          p=0;
20        }
21        public var rest(getRest,null):String;
22        function getRest():String {
23                return input.substr(p);
24        }
25        public function  proceed(by:Int):Int {return p+=by;}
26        public var eos(isEOS,null):Bool;
27        function isEOS():Bool {
28           return p>=rest.length;
29        }
30        var lastError:String;
31        public function raise(message:String) {
32           if (maxErrorPos<p) {
33                   maxErrorPos=p;
34                   lastError = traceStr(message);
35                }         
36                throw new ParseError(traceStr(message));
37        }
38        public function raiseSyntaxError() {
39                throw ("���@�G���[: "+maxErrorPos+" - "+p+" - "+lastError);
40        }
41        public function traceStr(message:String):String {
42           return " at "+p+"  /  "+message ;
43        }
44        /*public void trace(string message) {
45           System.Diagnostics.Debug.WriteLine(message);
46        }*/
47        public function saveState():Int {
48           return p;
49        }
50        public function restoreState(st:Int) {
51           p=st;
52        }
53        static function startsWith(s:String,head:String):Bool {
54            return s.substr(0,head.length)==head;
55        }
56        public function parse(m:Dynamic):Dynamic {
57                return combinator(m)();
58        }
59
60        public function combinator(match:Dynamic):Combinator {
61           if (Reflect.isFunction(match) ) {
62                   //var p:Combinator=match;
63                   return match;
64           } else if (Std.is(match ,String)) {
65                  var m:String=match;
66                  return str(m);
67           } else if (Std.is(match , EReg)) {
68                  var r:EReg=match;
69                  return reg(r);
70           } else if (Std.is(match,Array)) {
71              var ary:Array<Dynamic>=match;
72              return seq(ary);
73           }
74           throw ("Invalid match: "+match);
75        }
76        public function skipSpace() {
77                if (space.match(rest)) {
78                        proceed(space.matchedPos().len);
79                }
80        }
81
82        public function combinators(seq:Array<Dynamic> ):Array<Combinator> {
83           var res:Array<Combinator>=[];
84           var s;
85           for (s in seq) {
86                  res.push(combinator(s));
87           }
88           return res;
89        }
90        public function cache(name:String, sub:Combinator ) {
91           trace("Parsing "+name);
92           return sub();
93        }
94        public function parseSeq(s:Array<Dynamic>):Array<Dynamic> {
95                return seq(s)();
96        }                       
97        //# combinator
98        public function reg(r:EReg) {
99                var t=this;
100                var message=Std.string(r)+" expected";
101                return function() {
102                        t.skipSpace();
103                        if (r.match(t.rest)) {
104                                if (r.matchedPos().pos>0) throw ("Invalid regex; it must start with ^ :"+r);
105                                t.proceed(r.matched(0).length);
106                                return r.matched(0);
107                        }
108                        t.raise(message);
109                        return null;
110                };
111        }
112        public function str(m:String) {
113                var t=this;
114                var message:String=m+" expected";
115                return function () {
116                        if (startsWith(t.rest,m)) {
117                                t.proceed(m.length);
118                                return m;
119                        }
120                        t.raise(message);
121                        return null;
122                }
123        }
124        public function seq(seq:Array<Dynamic>):Combinator {
125                var cls= combinators(seq);
126                var t:Parser=this;
127                return function() {
128                   var res=[];
129                   var r:Combinator;
130                   for (r in cls) {
131                                res.push(r());
132                   }
133                   return res;
134                };
135        }
136
137        public function either(_:Array<Dynamic>):Combinator {                   
138                var subs=combinators(_);
139                var t:Parser=this;
140                return function() {
141                        var res=null;
142                   var trID=Std.random(10000);
143                   trace("Trying "+trID);
144                   var lastError:ParseError =null;
145                   var sub:Combinator;
146                   for (sub in subs) {
147                          var st=t.saveState();
148                          lastError=null;
149                          try {
150                                 res=sub();
151                          } catch (p:ParseError) {
152                                lastError=p;
153                                t.restoreState(st);
154                          }
155                          if (lastError==null) {trace("Trial "+trID+" OK res="+res); return res;}
156                   }
157                   throw lastError;
158           };
159        }
160
161       
162        public function rept0(_:Dynamic):Combinator  {
163           return reptN(0,1000,combinator(_));
164        }
165
166        public function rept1(_:Dynamic):Combinator  {
167           return reptN(1,1000,combinator(_));
168        }
169        public function maybe(_:Dynamic):Combinator {
170            var t:Parser=this;
171                return function() {
172                 var res: Array<Dynamic> = (t.reptN(0,1,t.combinator(_)))();
173                 if (res.length==1) return res[0];
174                 return null;
175           };
176        }
177
178        public function reptN(min:Int , max:Int, sub:Combinator):Combinator  {
179           var t:Parser=this;
180                return function() {
181                 var res=[];
182                 while (res.length<max) {
183                        var suc=true;
184                        var fail=function(){suc=false;return null;};
185                        var tres=(t.either([sub, fail]))();
186                        if (suc) {
187                                res.push(tres);
188                        } else {
189                                break;
190                        }
191                 }
192                 if (res.length<min) {
193                        t.raise("only "+res.length+" time for ("+min+" - "+max+")");
194                }
195                 trace("repeated "+res.length+"("+min+" - "+max+")  OK, proceed");
196                 //#if ($cnt!=@res) {die("Why $cnt ".scalar(@res));}
197                 return res;
198           };
199        }
200       
201}
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
Note: See TracBrowser for help on using the browser.