Overview
SHA1 Hash: | 3f5dc76a75ae8b8ecbee3c1b287f449cf312e595 |
---|---|
Date: | 2010-11-07 21:46:23 |
User: | kinaba |
Comment: | Added funcall expression parser and function literal parser. |
Timelines: | family | ancestors | descendants | both | trunk |
Downloads: | Tarball | ZIP archive |
Other Links: | files | file ages | manifest |
Tags And Properties
- branch=trunk inherited from [f65680e1d2]
- sym-trunk inherited from [f65680e1d2]
Changes
Modified polemy/ast.d from [e79569cb2ae94b8c] to [a264a204623245e6].
62 62 class AssignExpression : Expression 63 63 { 64 64 Expression lhs; 65 65 Expression rhs; 66 66 mixin SimpleConstructor; 67 67 mixin SimpleCompare; // do not take "pos" into account 68 68 } 69 + 69 70 class FuncallExpression : Expression 70 71 { 71 72 Expression fun; 72 73 Expression[] args; 73 74 this(immutable LexPosition pos, Expression fun, Expression[] args...) 74 75 { super(pos); this.fun=fun; this.args=args.dup; } 75 76 mixin SimpleCompare; // do not take "pos" into account 76 77 } 78 + 79 +class FunLiteralExpression : Expression 80 +{ 81 + string[] params; 82 + Program funbody; 83 + mixin SimpleConstructor; 84 + mixin SimpleCompare; // do not take "pos" into account 85 +}
Modified polemy/eval.d from [0a7ac481ec249b42] to [c5ee9ab6830c78bd].
3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Evaluator for Polemy programming language. 6 6 */ 7 7 module polemy.eval; 8 8 import polemy._common; 9 9 import polemy.ast; 10 +import polemy.parse; 10 11 import polemy.runtime; 11 12 12 13 Context createGlobalContext() 13 14 { 14 15 auto ctx = new Context; 15 16 ctx.add("+", new PrimitiveFunction(delegate Value(Value[] args){ 16 17 if( args.length != 2 ) ................................................................................ 42 43 if( auto x = cast(IntValue)args[0] ) 43 44 if( auto y = cast(IntValue)args[1] ) 44 45 return new IntValue(x.data/y.data); 45 46 throw new PolemyRuntimeException("cannot add non-integers"); // TODO improve this message 46 47 })); 47 48 return ctx; 48 49 } 50 + 51 +Context evalString(T...)(T params) 52 +{ 53 + return eval( parserFromString(params).parseProgram() ); 54 +} 55 + 56 +Context evalFile(T...)(T params) 57 +{ 58 + return eval( parserFromFile(params).parseProgram() ); 59 +} 49 60 50 61 Context eval(Program prog) 51 62 { 52 63 return eval(prog, createGlobalContext()); 53 64 } 54 65 55 66 Context eval(Program prog, Context ctx) ................................................................................ 120 131 121 132 122 133 version(unittest) import polemy.parse; 123 134 version(unittest) import std.stdio; 124 135 version(unittest) import std.exception; 125 136 unittest 126 137 { 127 - auto parser = parserFromString(`var x = 21; x = x + x*x;`); 128 - auto prog = parser.parseProgram(); 129 - auto ctx = eval(prog); 138 + auto ctx = evalString(`var x = 21; x = x + x*x;`); 130 139 assert( ctx["x"] == new IntValue(BigInt(21+21*21)) ); 131 140 assert( !collectException(ctx["x"]) ); 132 141 assert( collectException(ctx["y"]) ); 133 142 } 134 143 unittest 135 144 { 136 - auto parser = parserFromString(`var x = 21; x = x + x*y;`); 137 - auto prog = parser.parseProgram(); 138 - assert( collectException(eval(prog)) ); 145 + assert( collectException(evalString(`var x = 21; x = x + x*y;`)) ); 139 146 } 140 147 unittest 141 148 { 142 - auto parser = parserFromString(`var x = 21; y = x + x*x;`); 143 - auto prog = parser.parseProgram(); 144 - assert( collectException(eval(prog)) ); 149 + assert( collectException(evalString(`var x = 21; y = x + x*x;`)) ); 145 150 }
Modified polemy/parse.d from [a819ba1b27fdc13d] to [4856c979362ef435].
95 95 auto saved = lex.save; 96 96 scope(failure) lex = saved; 97 97 return parseE(0); 98 98 } 99 99 100 100 // [TODO] multi-char operators are not supported by the lexer... 101 101 static immutable string[][] operator_perferences = [ 102 - [","], 103 - ["="], // caution! left associative 102 + ["="], 104 103 ["or"], 105 104 ["and"], 106 105 ["!="], 107 106 ["=="], 108 107 ["<","<=",">",">="], 109 108 ["|"], 110 109 ["^"], ................................................................................ 142 141 } 143 142 144 143 Expression parseBaseExpression() 145 144 { 146 145 if( lex.empty ) 147 146 throw new ParserException("EOF during parsing an expression"); 148 147 auto pos = lex.front.pos; 148 + Expression e = parseBaseBaseExpression(); 149 + while( tryEat("(") ) // funcall 150 + { 151 + Expression[] args; 152 + while( !tryEat(")") ) { 153 + if( lex.empty ) { 154 + auto ex = ParserException.create(lex,"Unexpected EOF"); 155 + throw ex; 156 + } 157 + args ~= parseE(); 158 + if( !tryEat(",") ) { 159 + eat(")", "after function parameters"); 160 + break; 161 + } 162 + } 163 + e = new FuncallExpression(pos, e, args); 164 + } 165 + return e; 166 + } 167 + 168 + Expression parseBaseBaseExpression() 169 + { 170 + if( lex.empty ) 171 + throw new ParserException("EOF during parsing an expression"); 172 + auto pos = lex.front.pos; 149 173 150 174 if( lex.front.kind == Token.Kind.number ) 151 175 { 152 176 scope(exit) lex.popFront; 153 177 return new IntLiteralExpression(pos, BigInt(cast(string)lex.front.str)); 154 178 } 155 179 if( lex.front.kind == Token.Kind.stringLiteral ) ................................................................................ 159 183 } 160 184 if( tryEat("(") ) 161 185 { 162 186 auto e = parseE(); 163 187 eat(")", "after parenthesized expression"); 164 188 return e; 165 189 } 190 + 191 + if( tryEat("fun") ) 192 + { 193 + eat("(", "after fun"); 194 + string[] params; 195 + for(;;) 196 + { 197 + if( lex.empty ) { 198 + auto e = ParserException.create(lex,"Unexpected EOF"); 199 + throw e; 200 + } 201 + if( lex.front.kind != Token.Kind.identifier ) { 202 + auto e = ParserException.create(lex,"Identifier Expected for parameters"); 203 + throw e; 204 + } 205 + params ~= lex.front.str; 206 + lex.popFront; 207 + if( !tryEat(",") ) { 208 + eat(")", "after function parameters"); 209 + break; 210 + } 211 + } 212 + eat("{", "after function parameters"); 213 + Statement[] funbody; 214 + while(!tryEat("}")) { 215 + if( lex.empty ) { 216 + auto e = ParserException.create(lex,"Unexpected EOF"); 217 + throw e; 218 + } 219 + funbody ~= parseStatement(); 220 + } 221 + return new FunLiteralExpression(pos, params, funbody); 222 + } 166 223 scope(exit) lex.popFront; 167 224 return new VarExpression(pos, lex.front.str); 168 225 } 169 226 170 227 private: 171 228 Lexer lex; 172 229 ................................................................................ 226 283 227 284 Program prog = p.parseProgram(); 228 285 assert( prog.length == 3 ); 229 286 assert( prog[0] == s0 ); 230 287 assert( prog[1] == s1 ); 231 288 assert( prog[2] == s2 ); 232 289 } 290 + 291 +unittest 292 +{ 293 + auto p = parserFromString(` 294 + var f = fun(x,y){x+y;}; 295 + f(1,fun(abc){}(4)); 296 + `); 297 + Program prog = p.parseProgram(); 298 + assert( prog.length == 2 ); 299 + assert( prog[0] == new DeclStatement(null, "f", new FunLiteralExpression(null, 300 + ["x","y"], [new ExprStatement(null, 301 + new FuncallExpression(null, new VarExpression(null, "+"), 302 + new VarExpression(null, "x"), new VarExpression(null, "y")))] 303 + ))); 304 + assert( prog[1] == new ExprStatement(null, new FuncallExpression(null, 305 + new VarExpression(null, "f"), 306 + new IntLiteralExpression(null, BigInt(1)), 307 + new FuncallExpression(null, 308 + new FunLiteralExpression(null, ["abc"], [ 309 + ]), 310 + new IntLiteralExpression(null, BigInt(4)) 311 + )))); 312 +}