Differences From Artifact [fafb5e120f10db35]:
- File
polemy/parse.d
- 2010-11-09 10:28:08 - part of checkin [dc93ad8cf6] on branch trunk - layered exec expression @lay(...) added (user: kinaba) [annotate]
To Artifact [a8c1fd55863166fb]:
- File
polemy/parse.d
- 2010-11-09 14:24:09 - part of checkin [2459e9a821] on branch trunk - refactored eof-driven REPL (user: kinaba) [annotate]
9 import polemy.lex; 9 import polemy.lex;
10 import polemy.ast; 10 import polemy.ast;
11 11
12 /// Exception from this module 12 /// Exception from this module
13 13
14 class ParseException : Exception 14 class ParseException : Exception
15 { 15 {
16 const LexPosition pos; | 16 mixin ExceptionWithPosition;
17 <
18 this( const LexPosition pos, string msg, string file=null, size_t line=0 <
19 { super(sprintf!"[%s] %s"(pos, msg), file, line, next); this.pos <
20 } 17 }
21 18
22 private auto createException(Lexer)(Lexer lex, string msg) <
23 { return new ParseException(lex.empty?null:lex.front.pos, msg); } <
24 <
25 /// Entry points of this module 19 /// Entry points of this module
26 20
27 auto parseString(S, T...)(S str, T fn_ln_cn) 21 auto parseString(S, T...)(S str, T fn_ln_cn)
28 { return parserFromString(str, fn_ln_cn).parse(); } 22 { return parserFromString(str, fn_ln_cn).parse(); }
29 23
30 auto parseFile(S, T...)(S filename, T ln_cn) 24 auto parseFile(S, T...)(S filename, T ln_cn)
31 { return parserFromFile(filename, ln_cn).parse(); } 25 { return parserFromFile(filename, ln_cn).parse(); }
................................................................................................................................................................................
46 private class Parser(Lexer) 40 private class Parser(Lexer)
47 if( isForwardRange!(Lexer) && is(ElementType!(Lexer) == Token) ) 41 if( isForwardRange!(Lexer) && is(ElementType!(Lexer) == Token) )
48 { 42 {
49 AST parse() 43 AST parse()
50 { 44 {
51 auto e = Body(); 45 auto e = Body();
52 if( !lex.empty ) 46 if( !lex.empty )
53 throw createException(lex, "input is not ended but parse | 47 throw genex!ParseException(currentPosition(), "parsing e
54 return e; 48 return e;
55 } 49 }
56 50
57 AST Body() 51 AST Body()
58 { 52 {
59 if( lex.empty || !lex.front.quoted && lex.front.str=="}" ) | 53 if( lex.empty || !lex.front.quoted && ["}",")","]"].canFind(lex.
60 return doNothingExpression(); 54 return doNothingExpression();
61 55
62 auto saved = lex.save; 56 auto saved = lex.save;
63 auto pos = lex.front.pos; 57 auto pos = lex.front.pos;
64 string kwd = lex.front.str; 58 string kwd = lex.front.str;
65 if( tryEat("let") || tryEat("var") || tryEat("def") || tryEat("@ 59 if( tryEat("let") || tryEat("var") || tryEat("def") || tryEat("@
66 { 60 {
67 if( kwd == "@" ) { 61 if( kwd == "@" ) {
68 kwd ~= eatId("after @"); | 62 kwd ~= eatId("after @",true);
69 if( tryEat("(") ) { 63 if( tryEat("(") ) {
70 lex = saved; 64 lex = saved;
71 goto asExpression; 65 goto asExpression;
72 } 66 }
73 } 67 }
74 immutable LexPosition varpos = (lex.empty ? null : lex.f 68 immutable LexPosition varpos = (lex.empty ? null : lex.f
75 string var = eatId("after "~kwd); | 69 string var = eatId("after "~kwd,true);
76 eat("=", "after "~kwd); 70 eat("=", "after "~kwd);
77 kwd = (kwd[0]=='@' ? kwd : ""); // "let, var, def ==> ne 71 kwd = (kwd[0]=='@' ? kwd : ""); // "let, var, def ==> ne
78 auto e = E(0); 72 auto e = E(0);
79 if( tryEat(";") && !lex.empty && (lex.front.quoted || (l | 73 if( tryEat(";") && !lex.empty && (lex.front.quoted || ![
80 return new LetExpression(pos, var, kwd, e, Body( 74 return new LetExpression(pos, var, kwd, e, Body(
81 else 75 else
82 return new LetExpression(pos, var, kwd, e, new V 76 return new LetExpression(pos, var, kwd, e, new V
83 } 77 }
84 else 78 else
85 { 79 {
86 asExpression: 80 asExpression:
87 auto e = E(0); 81 auto e = E(0);
88 if( tryEat(";") && !lex.empty && (lex.front.quoted || (l 82 if( tryEat(";") && !lex.empty && (lex.front.quoted || (l
89 return new LetExpression(pos, "_", "@val", e, Bo | 83 return new LetExpression(pos, "_", "", e, Body()
90 else 84 else
91 return e; 85 return e;
92 } 86 }
93 } 87 }
94 88
95 // [TODO] make customizable from program 89 // [TODO] make customizable from program
96 static immutable string[][] operator_perferences = [ 90 static immutable string[][] operator_perferences = [
................................................................................................................................................................................
134 } 128 }
135 129
136 AST Funcall() 130 AST Funcall()
137 { 131 {
138 auto e = BaseExpression(); 132 auto e = BaseExpression();
139 while( tryEat("(") ) 133 while( tryEat("(") )
140 { 134 {
> 135 auto pos = currentPosition();
141 AST[] args; 136 AST[] args;
142 while( !tryEat(")") ) { 137 while( !tryEat(")") ) {
143 if( lex.empty ) 138 if( lex.empty )
144 throw createException(lex,"Unexpected EO | 139 throw genex!UnexpectedEOF(pos,"Closing '
145 args ~= E(0); 140 args ~= E(0);
146 if( !tryEat(",") ) { 141 if( !tryEat(",") ) {
147 eat(")", "after function parameters"); 142 eat(")", "after function parameters");
148 break; 143 break;
149 } 144 }
150 } 145 }
151 e = new FuncallExpression(e.pos, e, args); 146 e = new FuncallExpression(e.pos, e, args);
................................................................................................................................................................................
152 } 147 }
153 return e; 148 return e;
154 } 149 }
155 150
156 AST BaseExpression() 151 AST BaseExpression()
157 { 152 {
158 if( lex.empty ) 153 if( lex.empty )
159 throw createException(lex, "Reached EOF when tried to pa | 154 throw genex!UnexpectedEOF(currentPosition(), "Reached EO
160 155
161 auto pos = lex.front.pos; 156 auto pos = lex.front.pos;
162 if( lex.front.quoted ) 157 if( lex.front.quoted )
163 { 158 {
164 scope(exit) lex.popFront; 159 scope(exit) lex.popFront;
165 return new StrLiteral(pos, lex.front.str); 160 return new StrLiteral(pos, lex.front.str);
166 } 161 }
................................................................................................................................................................................
230 private: 225 private:
231 Lexer lex; 226 Lexer lex;
232 this(Lexer lex) { this.lex = lex; } 227 this(Lexer lex) { this.lex = lex; }
233 228
234 void eat(string kwd, lazy string msg) 229 void eat(string kwd, lazy string msg)
235 { 230 {
236 if( !tryEat(kwd) ) 231 if( !tryEat(kwd) )
237 throw createException(lex, "'"~kwd~"' is expected "~msg~ | 232 if( lex.empty )
238 ~(lex.empty ? "EOF" : lex.front.str)~"' occured" | 233 throw genex!UnexpectedEOF(
> 234 currentPosition(), sprintf!"%s is expect
> 235 else
> 236 throw genex!ParseException(
> 237 currentPosition(), sprintf!"%s is expect
239 } 238 }
240 239
241 bool tryEat(string kwd) 240 bool tryEat(string kwd)
242 { 241 {
243 if( lex.empty || lex.front.quoted || lex.front.str!=kwd ) 242 if( lex.empty || lex.front.quoted || lex.front.str!=kwd )
244 return false; 243 return false;
245 lex.popFront; 244 lex.popFront;
246 return true; 245 return true;
247 } 246 }
248 247
249 string eatId(lazy string msg) | 248 string eatId(lazy string msg, bool allowQuoted=false)
250 { 249 {
251 if( lex.empty || lex.front.quoted ) | 250 if( lex.empty )
252 throw createException(lex, "identifier is expected but n | 251 throw genex!UnexpectedEOF(currentPosition(), "identifier
253 string id = lex.front.str; | 252 if( !allowQuoted && lex.front.quoted )
> 253 throw genex!ParseException(currentPosition(), "identifie
254 lex.popFront; | 254 scope(exit) lex.popFront;
255 return id; | 255 return lex.front.str;
256 } 256 }
257 257
258 bool isNumber(string s) 258 bool isNumber(string s)
259 { 259 {
260 return find!(`a<'0'||'9'<a`)(s).empty; 260 return find!(`a<'0'||'9'<a`)(s).empty;
261 } 261 }
262 262
263 AST doNothingExpression() 263 AST doNothingExpression()
264 { 264 {
265 return new IntLiteral(lex.empty?null:lex.front.pos, BigInt(178)) | 265 return new IntLiteral(currentPosition(), BigInt(178));
> 266 }
> 267
> 268 immutable(LexPosition) currentPosition()
> 269 {
> 270 return lex.empty ? null : lex.front.pos;
266 } 271 }
267 } 272 }
268 273
269 unittest 274 unittest
270 { 275 {
271 mixin EasyAST; 276 mixin EasyAST;
272 277
273 assert_eq(parseString(`123`), intl(123)); 278 assert_eq(parseString(`123`), intl(123));
274 assert_eq(parseString(`"foo"`), strl("foo")); 279 assert_eq(parseString(`"foo"`), strl("foo"));
275 assert_eq(parseString(`fun(){1}`), fun([],intl(1))); 280 assert_eq(parseString(`fun(){1}`), fun([],intl(1)));
276 assert_eq(parseString(`fun(x){1}`), fun(["x"],intl(1))); 281 assert_eq(parseString(`fun(x){1}`), fun(["x"],intl(1)));
277 assert_eq(parseString("\u03BB(){1}"), fun([],intl(1))); 282 assert_eq(parseString("\u03BB(){1}"), fun([],intl(1)));
278 assert_eq(parseString("\u03BB(x){1}"), fun(["x"],intl(1))); 283 assert_eq(parseString("\u03BB(x){1}"), fun(["x"],intl(1)));
279 assert_eq(parseString(`1;2`), let("_","@val",intl(1),intl(2))); | 284 assert_eq(parseString(`1;2`), let("_","",intl(1),intl(2)));
280 assert_eq(parseString(`1;2;`), let("_","@val",intl(1),intl(2))); | 285 assert_eq(parseString(`1;2;`), let("_","",intl(1),intl(2)));
281 assert_eq(parseString(`let x=1;2`), let("x","",intl(1),intl(2))); 286 assert_eq(parseString(`let x=1;2`), let("x","",intl(1),intl(2)));
282 assert_eq(parseString(`var x=1;2;`), let("x","",intl(1),intl(2))); 287 assert_eq(parseString(`var x=1;2;`), let("x","",intl(1),intl(2)));
283 assert_eq(parseString(`def x=1`), let("x","",intl(1),var("x"))); 288 assert_eq(parseString(`def x=1`), let("x","",intl(1),var("x")));
284 assert_eq(parseString(`@val x=1;`), let("x","@val",intl(1),var("x"))); 289 assert_eq(parseString(`@val x=1;`), let("x","@val",intl(1),var("x")));
285 assert_eq(parseString(`@typ x="#int";`), let("x","@typ",strl("#int"),var 290 assert_eq(parseString(`@typ x="#int";`), let("x","@typ",strl("#int"),var
286 assert_eq(parseString(`f(1,2)`), call(var("f"),intl(1),intl(2))); 291 assert_eq(parseString(`f(1,2)`), call(var("f"),intl(1),intl(2)));
287 assert_eq(parseString(`if(1){2}`), call(var("if"),intl(1),fun([],intl(2) 292 assert_eq(parseString(`if(1){2}`), call(var("if"),intl(1),fun([],intl(2)
................................................................................................................................................................................
315 call(var("fac"),intl(10)) 320 call(var("fac"),intl(10))
316 ) 321 )
317 ); 322 );
318 } 323 }
319 324
320 unittest 325 unittest
321 { 326 {
322 assert_throw!ParseException(parseString(`1+`)); | 327 assert_throw!UnexpectedEOF(parseString(`1+`));
323 assert_throw!ParseException(parseString(`1+2}`)); 328 assert_throw!ParseException(parseString(`1+2}`));
324 assert_throw!ParseException(parseString(`let "x"`)); | 329 assert_throw!UnexpectedEOF(parseString(`let "x"`));
325 assert_throw!ParseException(parseString(`var`)); | 330 assert_throw!UnexpectedEOF(parseString(`var`));
326 assert_throw!ParseException(parseString(`@val x ==`)); 331 assert_throw!ParseException(parseString(`@val x ==`));
327 assert_throw!ParseException(parseString(`if(){1}`)); 332 assert_throw!ParseException(parseString(`if(){1}`));
328 assert_throw!ParseException(parseString(`f(`)); | 333 assert_throw!UnexpectedEOF(parseString(`f(`));
329 } 334 }