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 93 Expression parseExpression()
94 94 {
95 95 auto saved = lex.save;
96 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()
108 - {
109 - auto lhs = parseE1();
110 - if( tryEat("=") )
111 - lhs = new BinOpExpression(lhs.pos, "=", lhs, parseE0());
112 - return lhs;
113 - }
100 + // [TODO] multi-char operators are not supported by the lexer...
101 + static immutable string[][] operator_perferences = [
102 + [","],
103 + ["="], // caution! left associative
104 + ["or"],
105 + ["and"],
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("+") )
120 - lhs = new BinOpExpression(lhs.pos, "+", lhs, parseE2());
121 - else if( tryEat("-") )
122 - lhs = new BinOpExpression(lhs.pos, "-", lhs, parseE2());
123 - else
124 - return lhs;
123 + auto ops = operator_perferences[level];
124 + auto e = parseE(level+1);
125 + seq:
126 + while( !lex.empty )
127 + {
128 + auto pos = lex.front.pos;
129 + foreach(op; ops)
130 + if( tryEat(op) )
131 + {
132 + if( op == "=" ) // right assoc
133 + return new AssignExpression(e.pos, e, parseE(level));
134 + else
135 + e = new FuncallExpression(e.pos, new VarExpression(pos, op), e, parseE(level+1));
136 + continue seq;
137 + }
138 + break;
139 + }
140 + return e;
125 141 }
126 142 }
127 143
128 - Expression parseE2()
129 - {
130 - for(auto lhs = parseE3();;)
131 - {
132 - if( tryEat("*") )
133 - lhs = new BinOpExpression(lhs.pos, "*", lhs, parseE3());
134 - else if( tryEat("/") )
135 - lhs = new BinOpExpression(lhs.pos, "/", lhs, parseE3());
136 - else
137 - return lhs;
138 - }
139 - }
140 -
141 - Expression parseE3()
144 + Expression parseBaseExpression()
142 145 {
143 146 if( lex.empty )
144 147 throw new ParserException("EOF during parsing an expression");
145 148 auto pos = lex.front.pos;
146 149
147 150 if( lex.front.kind == Token.Kind.number )
148 151 {
................................................................................
152 155 if( lex.front.kind == Token.Kind.stringLiteral )
153 156 {
154 157 scope(exit) lex.popFront;
155 158 return new StrLiteralExpression(pos, lex.front.str);
156 159 }
157 160 if( tryEat("(") )
158 161 {
159 - auto e = parseE0();
162 + auto e = parseE();
160 163 eat(")", "after parenthesized expression");
161 164 return e;
162 165 }
163 166 scope(exit) lex.popFront;
164 167 return new VarExpression(pos, lex.front.str);
165 168 }
166 169
................................................................................
207 210 auto p = parserFromString(`
208 211 var zzz = 100; # comment
209 212 zzz = zzz + zzz * "fo\no"; # comment
210 213 42;
211 214 `);
212 215
213 216 auto s0 = new DeclStatement(null, "zzz", new IntLiteralExpression(null, BigInt(100)));
214 - auto s1 = new ExprStatement(null, new BinOpExpression(null, "=",
217 + auto s1 = new ExprStatement(null, new AssignExpression(null,
215 218 new VarExpression(null, "zzz"),
216 - new BinOpExpression(null, "+",
219 + new FuncallExpression(null, new VarExpression(null,"+"),
217 220 new VarExpression(null, "zzz"),
218 - new BinOpExpression(null, "*",
221 + new FuncallExpression(null, new VarExpression(null,"*"),
219 222 new VarExpression(null, "zzz"),
220 223 new StrLiteralExpression(null, "fo\\no")
221 224 ))));
222 225 auto s2 = new ExprStatement(null, new IntLiteralExpression(null, BigInt(42)));
223 226
224 227 Program prog = p.parseProgram();
225 228 assert( prog.length == 3 );
226 229 assert( prog[0] == s0 );
227 230 assert( prog[1] == s1 );
228 231 assert( prog[2] == s2 );
229 232 }