Differences From Artifact [fe545db0fb7a2428]:
- File
polemy/parse.d
- 2010-11-07 10:32:59 - part of checkin [4198578702e] on branch trunk - Changed several documentation comments into ddoc compatible ones. (user: kinaba) [annotate]
To Artifact [a819ba1b27fdc13d]:
- File
polemy/parse.d
- 2010-11-07 12:20:47 - part of checkin [5d4cb856d8] on branch trunk - Added FuncallExpression (user: kinaba) [annotate]
90 } 90 }
91 } 91 }
92 92
93 Expression parseExpression() 93 Expression parseExpression()
94 { 94 {
95 auto saved = lex.save; 95 auto saved = lex.save;
96 scope(failure) lex = saved; 96 scope(failure) lex = saved;
97 <
98 // Expr ::= E0 <
99 // E0 ::= (E1 "=")* E1 <
100 // E1 ::= (E2 "+"|"-")* E2 <
101 // E2 ::= (E3 "*"|"/")* E3 <
102 // E3 ::= int | str | id | "(" Expr ")" <
103 <
104 return parseE0(); | 97 return parseE(0);
105 } 98 }
106 99
107 Expression parseE0() | 100 // [TODO] multi-char operators are not supported by the lexer...
108 { <
109 auto lhs = parseE1(); <
> 101 static immutable string[][] operator_perferences = [
> 102 [","],
110 if( tryEat("=") ) | 103 ["="], // caution! left associative
111 lhs = new BinOpExpression(lhs.pos, "=", lhs, parseE0()); | 104 ["or"],
112 return lhs; | 105 ["and"],
113 } <
> 106 ["!="],
> 107 ["=="],
> 108 ["<","<=",">",">="],
> 109 ["|"],
> 110 ["^"],
> 111 ["&"],
> 112 ["<<", ">>"],
> 113 ["+","-"],
> 114 ["*","/","%"]
> 115 ];
114 116
115 Expression parseE1() | 117 Expression parseE(int level = 0)
116 { 118 {
117 for(auto lhs = parseE2();;) | 119 if( operator_perferences.length <= level )
> 120 return parseBaseExpression();
> 121 else
118 { 122 {
119 if( tryEat("+") ) | 123 auto ops = operator_perferences[level];
120 lhs = new BinOpExpression(lhs.pos, "+", lhs, par | 124 auto e = parseE(level+1);
> 125 seq:
> 126 while( !lex.empty )
> 127 {
> 128 auto pos = lex.front.pos;
> 129 foreach(op; ops)
121 else if( tryEat("-") ) | 130 if( tryEat(op) )
122 lhs = new BinOpExpression(lhs.pos, "-", lhs, par <
> 131 {
> 132 if( op == "=" ) // right assoc
> 133 return new AssignExpress
123 else | 134 else
> 135 e = new FuncallExpressio
> 136 continue seq;
> 137 }
> 138 break;
> 139 }
124 return lhs; | 140 return e;
125 } 141 }
126 } 142 }
127 143
128 Expression parseE2() | 144 Expression parseBaseExpression()
129 { <
130 for(auto lhs = parseE3();;) <
131 { <
132 if( tryEat("*") ) <
133 lhs = new BinOpExpression(lhs.pos, "*", lhs, par <
134 else if( tryEat("/") ) <
135 lhs = new BinOpExpression(lhs.pos, "/", lhs, par <
136 else <
137 return lhs; <
138 } <
139 } <
140 <
141 Expression parseE3() <
142 { 145 {
143 if( lex.empty ) 146 if( lex.empty )
144 throw new ParserException("EOF during parsing an express 147 throw new ParserException("EOF during parsing an express
145 auto pos = lex.front.pos; 148 auto pos = lex.front.pos;
146 149
147 if( lex.front.kind == Token.Kind.number ) 150 if( lex.front.kind == Token.Kind.number )
148 { 151 {
................................................................................................................................................................................
152 if( lex.front.kind == Token.Kind.stringLiteral ) 155 if( lex.front.kind == Token.Kind.stringLiteral )
153 { 156 {
154 scope(exit) lex.popFront; 157 scope(exit) lex.popFront;
155 return new StrLiteralExpression(pos, lex.front.str); 158 return new StrLiteralExpression(pos, lex.front.str);
156 } 159 }
157 if( tryEat("(") ) 160 if( tryEat("(") )
158 { 161 {
159 auto e = parseE0(); | 162 auto e = parseE();
160 eat(")", "after parenthesized expression"); 163 eat(")", "after parenthesized expression");
161 return e; 164 return e;
162 } 165 }
163 scope(exit) lex.popFront; 166 scope(exit) lex.popFront;
164 return new VarExpression(pos, lex.front.str); 167 return new VarExpression(pos, lex.front.str);
165 } 168 }
166 169
................................................................................................................................................................................
207 auto p = parserFromString(` 210 auto p = parserFromString(`
208 var zzz = 100; # comment 211 var zzz = 100; # comment
209 zzz = zzz + zzz * "fo\no"; # comment 212 zzz = zzz + zzz * "fo\no"; # comment
210 42; 213 42;
211 `); 214 `);
212 215
213 auto s0 = new DeclStatement(null, "zzz", new IntLiteralExpression(null, 216 auto s0 = new DeclStatement(null, "zzz", new IntLiteralExpression(null,
214 auto s1 = new ExprStatement(null, new BinOpExpression(null, "=", | 217 auto s1 = new ExprStatement(null, new AssignExpression(null,
215 new VarExpression(null, "zzz"), 218 new VarExpression(null, "zzz"),
216 new BinOpExpression(null, "+", | 219 new FuncallExpression(null, new VarExpression(null,"+"),
217 new VarExpression(null, "zzz"), 220 new VarExpression(null, "zzz"),
218 new BinOpExpression(null, "*", | 221 new FuncallExpression(null, new VarExpression(null,"*"),
219 new VarExpression(null, "zzz"), 222 new VarExpression(null, "zzz"),
220 new StrLiteralExpression(null, "fo\\no") 223 new StrLiteralExpression(null, "fo\\no")
221 )))); 224 ))));
222 auto s2 = new ExprStatement(null, new IntLiteralExpression(null, BigInt( 225 auto s2 = new ExprStatement(null, new IntLiteralExpression(null, BigInt(
223 226
224 Program prog = p.parseProgram(); 227 Program prog = p.parseProgram();
225 assert( prog.length == 3 ); 228 assert( prog.length == 3 );
226 assert( prog[0] == s0 ); 229 assert( prog[0] == s0 );
227 assert( prog[1] == s1 ); 230 assert( prog[1] == s1 );
228 assert( prog[2] == s2 ); 231 assert( prog[2] == s2 );
229 } 232 }