File Annotation
Not logged in
5081139836 2010-11-09        kinaba: /**
4198578702 2010-11-07        kinaba:  * Authors: k.inaba
4198578702 2010-11-07        kinaba:  * License: NYSL 0.9982 http://www.kmonos.net/nysl/
4198578702 2010-11-07        kinaba:  *
4198578702 2010-11-07        kinaba:  * Parser for Polemy programming language
423f308350 2010-11-07        kinaba:  */
4198578702 2010-11-07        kinaba: module polemy.parse;
4198578702 2010-11-07        kinaba: import polemy._common;
3464a035ec 2010-11-20        kinaba: import polemy.failure;
423f308350 2010-11-07        kinaba: import polemy.lex;
423f308350 2010-11-07        kinaba: import polemy.ast;
435fa085ec 2010-11-21        kinaba: import polemy.layer;
3995a5eb6a 2010-11-21        kinaba: import polemy.fresh;
423f308350 2010-11-07        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: /// Parse a string and return its AST
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: AST parseString(S, T...)(S str, T fn_ln_cn)
38fcc662be 2010-11-10        kinaba: {
a7b5d1d95a 2010-11-12        kinaba: 	return parserFromString(str, fn_ln_cn).parse();
38fcc662be 2010-11-10        kinaba: }
38fcc662be 2010-11-10        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: /// Parse the content of a file and return its AST
38fcc662be 2010-11-10        kinaba: 
38fcc662be 2010-11-10        kinaba: AST parseFile(S, T...)(S filename, T ln_cn)
a7b5d1d95a 2010-11-12        kinaba: {
a7b5d1d95a 2010-11-12        kinaba: 	return parserFromFile(filename, ln_cn).parse();
a7b5d1d95a 2010-11-12        kinaba: }
423f308350 2010-11-07        kinaba: 
38fcc662be 2010-11-10        kinaba: // Named Constructors of Parser
423f308350 2010-11-07        kinaba: 
b985f3bf91 2010-11-08        kinaba: private auto parserFromLexer(Lexer)(Lexer lex)
b985f3bf91 2010-11-08        kinaba: 	{ return new Parser!Lexer(lex); }
423f308350 2010-11-07        kinaba: 
b985f3bf91 2010-11-08        kinaba: private auto parserFromString(T...)(T params)
a7b5d1d95a 2010-11-12        kinaba: 	{ return parserFromLexer(lexerFromString(params)); }
423f308350 2010-11-07        kinaba: 
b985f3bf91 2010-11-08        kinaba: private auto parserFromFile(T...)(T params)
a7b5d1d95a 2010-11-12        kinaba: 	{ return parserFromLexer(lexerFromFile(params)); }
423f308350 2010-11-07        kinaba: 
38fcc662be 2010-11-10        kinaba: // Parser
423f308350 2010-11-07        kinaba: 
b985f3bf91 2010-11-08        kinaba: private class Parser(Lexer)
b985f3bf91 2010-11-08        kinaba: 	if( isForwardRange!(Lexer) && is(ElementType!(Lexer) == Token) )
423f308350 2010-11-07        kinaba: {
b985f3bf91 2010-11-08        kinaba: 	AST parse()
b985f3bf91 2010-11-08        kinaba: 	{
b985f3bf91 2010-11-08        kinaba: 		auto e = Body();
b985f3bf91 2010-11-08        kinaba: 		if( !lex.empty )
2459e9a821 2010-11-09        kinaba: 			throw genex!ParseException(currentPosition(), "parsing ended but some tokens left");
b985f3bf91 2010-11-08        kinaba: 		return e;
b985f3bf91 2010-11-08        kinaba: 	}
b985f3bf91 2010-11-08        kinaba: 
b985f3bf91 2010-11-08        kinaba: 	AST Body()
b985f3bf91 2010-11-08        kinaba: 	{
a7b5d1d95a 2010-11-12        kinaba: 		/// Body ::= Declaration
a7b5d1d95a 2010-11-12        kinaba: 		///        | TopLevelExpression
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 		if( closingBracket() )
dc93ad8cf6 2010-11-09        kinaba: 			return doNothingExpression();
dc93ad8cf6 2010-11-09        kinaba: 
dc93ad8cf6 2010-11-09        kinaba: 		auto saved = lex.save;
a7b5d1d95a 2010-11-12        kinaba: 		if( auto e = Declaration() )
a7b5d1d95a 2010-11-12        kinaba: 			return e;
a7b5d1d95a 2010-11-12        kinaba: 		lex = saved;
a7b5d1d95a 2010-11-12        kinaba: 		return TopLevelExpression();
a7b5d1d95a 2010-11-12        kinaba: 	}
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	AST Declaration() // returns null if it is not a declaration
a7b5d1d95a 2010-11-12        kinaba: 	{
a7b5d1d95a 2010-11-12        kinaba: 		/// Declaration ::=
a7b5d1d95a 2010-11-12        kinaba: 		///    ["@" Layer|"let"|"var"|"def"] Var "=" Expression ([";"|"in"] Body?)?
a7b5d1d95a 2010-11-12        kinaba: 		///  | ["@" Layer|"let"|"var"|"def"] Var "(" Param%"," ")" "{" Body "}" ([";"|"in"] Body?)?
c368edbcb1 2010-11-13        kinaba: 		///  | ["@" "@" Layer "=" Expression ([";"|"in"] Body?)?
c368edbcb1 2010-11-13        kinaba: 		///  | ["@" "@" Layer "(" Param%"," ")" "{" Body "}" ([";"|"in"] Body?)?
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 		auto pos = currentPosition();
2bdfb8a182 2010-11-21        kinaba: 		Layer layer = "";
2bdfb8a182 2010-11-21        kinaba: 		bool layerLiftDecl = false;
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 		if( tryEat("@") )
dc93ad8cf6 2010-11-09        kinaba: 		{
a7b5d1d95a 2010-11-12        kinaba: 			layer = "@" ~ eatId("after @", AllowQuoted);
c368edbcb1 2010-11-13        kinaba: 			if( layer == "@@" )
c368edbcb1 2010-11-13        kinaba: 			{
c368edbcb1 2010-11-13        kinaba: 				layer = "@" ~ eatId("after @@", AllowQuoted);
2bdfb8a182 2010-11-21        kinaba: 				layerLiftDecl = true;
c368edbcb1 2010-11-13        kinaba: 			}
c368edbcb1 2010-11-13        kinaba: 			else
c368edbcb1 2010-11-13        kinaba: 			{
c368edbcb1 2010-11-13        kinaba: 				if( tryEat("(") )
c368edbcb1 2010-11-13        kinaba: 					return null; // @lay(...) expression, not a declaration
c368edbcb1 2010-11-13        kinaba: 			}
c368edbcb1 2010-11-13        kinaba: 		}
c368edbcb1 2010-11-13        kinaba: 
c368edbcb1 2010-11-13        kinaba: 		// [TODO] Refactor
2bdfb8a182 2010-11-21        kinaba: 		if( layerLiftDecl )
c368edbcb1 2010-11-13        kinaba: 		{
c368edbcb1 2010-11-13        kinaba: 			string kwd = "@" ~ layer;
c368edbcb1 2010-11-13        kinaba: 			string var = layer;
c368edbcb1 2010-11-13        kinaba: 
c368edbcb1 2010-11-13        kinaba: 			auto e = tryEat("(")
c368edbcb1 2010-11-13        kinaba: 				? parseLambdaAfterOpenParen(pos)  // let var ( ...
c368edbcb1 2010-11-13        kinaba: 				: (eat("=", "after "~kwd), E(0)); // let var = ...
c368edbcb1 2010-11-13        kinaba: 			if( moreDeclarationExists() )
207cea338a 2010-11-26        kinaba: 				return new Let(pos, var, LiftLayer, e, Body());
c368edbcb1 2010-11-13        kinaba: 			else
207cea338a 2010-11-26        kinaba: 				return new Let(pos, var, LiftLayer, e,
207cea338a 2010-11-26        kinaba: 					new Lay(pos, LiftLayer, new Var(pos, var))
2bdfb8a182 2010-11-21        kinaba: 				);
c368edbcb1 2010-11-13        kinaba: 		}
a7b5d1d95a 2010-11-12        kinaba: 		else
c368edbcb1 2010-11-13        kinaba: 		{
c368edbcb1 2010-11-13        kinaba: 			string kwd = layer;
c368edbcb1 2010-11-13        kinaba: 			if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="var") && !tryEat(kwd="def") )
c368edbcb1 2010-11-13        kinaba: 				return null; // none of {@lay, let, var, def} occurred, it's not a declaration
c368edbcb1 2010-11-13        kinaba: 
c368edbcb1 2010-11-13        kinaba: 			auto varpos = currentPosition();
c368edbcb1 2010-11-13        kinaba: 			string var = eatId("after "~kwd, AllowQuoted); // name of the declared variable
c368edbcb1 2010-11-13        kinaba: 
c368edbcb1 2010-11-13        kinaba: 			auto e = tryEat("(")
ba11f1d551 2010-11-23        kinaba: 				? parseLambdaAfterOpenParen(pos)  // let var ( ...
ba11f1d551 2010-11-23        kinaba: 				: (eat("=", "after "~kwd), E(0)); // let var = ...
c368edbcb1 2010-11-13        kinaba: 			if( moreDeclarationExists() )
6ac127ddd0 2010-11-23        kinaba: 				return new Let(pos, var, layer, e, Body());
f8684f4d69 2010-11-26        kinaba: 			else {
f8684f4d69 2010-11-26        kinaba: 				if( layer.empty )
f8684f4d69 2010-11-26        kinaba: 					return new Let(pos, var, layer, e, new Var(varpos, var));
f8684f4d69 2010-11-26        kinaba: 				else if( isMacroLayer(layer) )
f8684f4d69 2010-11-26        kinaba: 					return new Let(pos, var, layer, e, new Str(varpos, "(macro definition)"));
f8684f4d69 2010-11-26        kinaba: 				else
f8684f4d69 2010-11-26        kinaba: 					return new Let(pos, var, layer, e, new Lay(varpos, layer, new Var(varpos, var)));
f8684f4d69 2010-11-26        kinaba: 			}
c368edbcb1 2010-11-13        kinaba: 		}
68546f3e9f 2010-11-09        kinaba: 	}
68546f3e9f 2010-11-09        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	AST TopLevelExpression()
a7b5d1d95a 2010-11-12        kinaba: 	{
a7b5d1d95a 2010-11-12        kinaba: 		/// TopLevelExpression ::= Expression ([";"|"in"] Body?)?
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 		auto pos = currentPosition();
a7b5d1d95a 2010-11-12        kinaba: 		auto e = E(0);
a7b5d1d95a 2010-11-12        kinaba: 		if( moreDeclarationExists() )
6ac127ddd0 2010-11-23        kinaba: 			return new Let(pos, "_", "", e, Body());
a7b5d1d95a 2010-11-12        kinaba: 		else
a7b5d1d95a 2010-11-12        kinaba: 			return e;
a7b5d1d95a 2010-11-12        kinaba: 	}
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	private bool moreDeclarationExists()
a7b5d1d95a 2010-11-12        kinaba: 	{
a7b5d1d95a 2010-11-12        kinaba: 		return (tryEat(";") || tryEat("in")) && !closingBracket();
a7b5d1d95a 2010-11-12        kinaba: 	}
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	private bool closingBracket()
a7b5d1d95a 2010-11-12        kinaba: 	{
3995a5eb6a 2010-11-21        kinaba: 		return lex.empty || !lex.front.quoted && ["}",")","]",","].canFind(lex.front.str);
a7b5d1d95a 2010-11-12        kinaba: 	}
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	// [TODO] make this customizable from program
a7b5d1d95a 2010-11-12        kinaba: 	private static string[][] operator_perferences = [
b985f3bf91 2010-11-08        kinaba: 		["||"],
b985f3bf91 2010-11-08        kinaba: 		["&&"],
5d4cb856d8 2010-11-07        kinaba: 		["!="],
5d4cb856d8 2010-11-07        kinaba: 		["=="],
5d4cb856d8 2010-11-07        kinaba: 		["<","<=",">",">="],
2134cd44cc 2010-11-23        kinaba: 		["|"],
2134cd44cc 2010-11-23        kinaba: 		["^"],
2134cd44cc 2010-11-23        kinaba: 		["&"],
2134cd44cc 2010-11-23        kinaba: 		["<<", ">>", "<<<", ">>>"],
5d4cb856d8 2010-11-07        kinaba: 		["+","-"],
b985f3bf91 2010-11-08        kinaba: 		["~"],
b985f3bf91 2010-11-08        kinaba: 		["*","/","%"],
2134cd44cc 2010-11-23        kinaba: 		["^^","**"],
515502e8d1 2010-11-20        kinaba: 		[".",".?"]
5d4cb856d8 2010-11-07        kinaba: 	];
5d4cb856d8 2010-11-07        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	AST E(size_t level)
5d4cb856d8 2010-11-07        kinaba: 	{
a7b5d1d95a 2010-11-12        kinaba: 		/// Expression ::= (Binary left-associative operators over) Funcall
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 		AST rec(AST lhs)
a7b5d1d95a 2010-11-12        kinaba: 		{
a7b5d1d95a 2010-11-12        kinaba: 			if( closingBracket() )
a7b5d1d95a 2010-11-12        kinaba: 				return lhs;
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 			auto pos = currentPosition();
a7b5d1d95a 2010-11-12        kinaba: 			foreach(op; operator_perferences[level])
a7b5d1d95a 2010-11-12        kinaba: 				if( tryEat(op) )
515502e8d1 2010-11-20        kinaba: 					if( op[0]=='.' )
515502e8d1 2010-11-20        kinaba: 						return rec(
6ac127ddd0 2010-11-23        kinaba: 							new App(lhs.pos, new Var(pos, op), lhs, parseId()));
515502e8d1 2010-11-20        kinaba: 					else
6ac127ddd0 2010-11-23        kinaba: 						return rec(
6ac127ddd0 2010-11-23        kinaba: 							new App(lhs.pos, new Var(pos, op), lhs, E(level+1)));
a7b5d1d95a 2010-11-12        kinaba: 			return lhs;
a7b5d1d95a 2010-11-12        kinaba: 		}
a7b5d1d95a 2010-11-12        kinaba: 
5d4cb856d8 2010-11-07        kinaba: 		if( operator_perferences.length <= level )
b985f3bf91 2010-11-08        kinaba: 			return Funcall();
5d4cb856d8 2010-11-07        kinaba: 		else
a7b5d1d95a 2010-11-12        kinaba: 			return rec(E(level+1));
b985f3bf91 2010-11-08        kinaba: 	}
b985f3bf91 2010-11-08        kinaba: 
b985f3bf91 2010-11-08        kinaba: 	AST Funcall()
b985f3bf91 2010-11-08        kinaba: 	{
5e924caac9 2010-11-23        kinaba: 		/// Funcall ::= BaseExpression ["(" Expression%"," ")" | "{" ENTRIES "}"]*
a7b5d1d95a 2010-11-12        kinaba: 
b985f3bf91 2010-11-08        kinaba: 		auto e = BaseExpression();
6ecc7046fc 2010-11-21        kinaba: 		for(;;)
6ecc7046fc 2010-11-21        kinaba: 			if( tryEat("(") )
6ecc7046fc 2010-11-21        kinaba: 			{
6ecc7046fc 2010-11-21        kinaba: 				auto pos = currentPosition();
6ecc7046fc 2010-11-21        kinaba: 				AST[] args;
6ecc7046fc 2010-11-21        kinaba: 				while( !tryEat(")") ) {
6ecc7046fc 2010-11-21        kinaba: 					if( lex.empty )
6ecc7046fc 2010-11-21        kinaba: 						throw genex!UnexpectedEOF(pos, "closing ')' for arguments not found");
6ecc7046fc 2010-11-21        kinaba: 					args ~= E(0);
6ecc7046fc 2010-11-21        kinaba: 					if( !tryEat(",") ) {
6ecc7046fc 2010-11-21        kinaba: 						eat(")", "after function parameters");
6ecc7046fc 2010-11-21        kinaba: 						break;
6ecc7046fc 2010-11-21        kinaba: 					}
3f5dc76a75 2010-11-07        kinaba: 				}
6ac127ddd0 2010-11-23        kinaba: 				e = new App(e.pos, e, args);
6ecc7046fc 2010-11-21        kinaba: 			}
6ecc7046fc 2010-11-21        kinaba: 			else if( tryEat("{") )
6ecc7046fc 2010-11-21        kinaba: 			{
6ecc7046fc 2010-11-21        kinaba: 				e = parseTableSetAfterBrace(e);
3f5dc76a75 2010-11-07        kinaba: 			}
6ecc7046fc 2010-11-21        kinaba: 			else
6ecc7046fc 2010-11-21        kinaba: 				break;
6ecc7046fc 2010-11-21        kinaba: 		return e;
6ecc7046fc 2010-11-21        kinaba: 	}
6ecc7046fc 2010-11-21        kinaba: 
6ecc7046fc 2010-11-21        kinaba: 	AST parseTableSetAfterBrace(AST e)
6ecc7046fc 2010-11-21        kinaba: 	{
5e924caac9 2010-11-23        kinaba: 		/// TableSet ::= "{" (ID ":" E) % "," "}"
5e924caac9 2010-11-23        kinaba: 
6ecc7046fc 2010-11-21        kinaba: 		if( tryEat("}") )
6ecc7046fc 2010-11-21        kinaba: 			return e;
6ecc7046fc 2010-11-21        kinaba: 		auto pos = currentPosition();
6ecc7046fc 2010-11-21        kinaba: 		for(;;)
6ecc7046fc 2010-11-21        kinaba: 		{
6ecc7046fc 2010-11-21        kinaba: 			string key = eatId("for table key", AllowQuoted);
6ecc7046fc 2010-11-21        kinaba: 			eat(":", "after table key");
6ecc7046fc 2010-11-21        kinaba: 			AST val = E(0);
6ac127ddd0 2010-11-23        kinaba: 			e = new App(pos, new Var(pos,".="),
6ac127ddd0 2010-11-23        kinaba: 					e, new Str(pos,key), val);
6ecc7046fc 2010-11-21        kinaba: 			if( !tryEat(",") )
6ecc7046fc 2010-11-21        kinaba: 			{
6ecc7046fc 2010-11-21        kinaba: 				eat("}", "for the end of table literal");
6ecc7046fc 2010-11-21        kinaba: 				break;
6ecc7046fc 2010-11-21        kinaba: 			}
5d4cb856d8 2010-11-07        kinaba: 		}
3f5dc76a75 2010-11-07        kinaba: 		return e;
5d4cb856d8 2010-11-07        kinaba: 	}
5d4cb856d8 2010-11-07        kinaba: 
b985f3bf91 2010-11-08        kinaba: 	AST BaseExpression()
423f308350 2010-11-07        kinaba: 	{
423f308350 2010-11-07        kinaba: 		if( lex.empty )
2459e9a821 2010-11-09        kinaba: 			throw genex!UnexpectedEOF(currentPosition(), "Reached EOF when tried to parse an expression");
423f308350 2010-11-07        kinaba: 
f9c31f3cd8 2010-11-24        kinaba: 		auto pos = currentPosition();
8d297342aa 2010-11-08        kinaba: 		if( lex.front.quoted )
423f308350 2010-11-07        kinaba: 		{
423f308350 2010-11-07        kinaba: 			scope(exit) lex.popFront;
6ac127ddd0 2010-11-23        kinaba: 			return new Str(pos, lex.front.str);
423f308350 2010-11-07        kinaba: 		}
b985f3bf91 2010-11-08        kinaba: 		if( isNumber(lex.front.str) )
423f308350 2010-11-07        kinaba: 		{
423f308350 2010-11-07        kinaba: 			scope(exit) lex.popFront;
6ac127ddd0 2010-11-23        kinaba: 			return new Int(pos, BigInt(cast(string)lex.front.str));
f9c31f3cd8 2010-11-24        kinaba: 		}
f7e9e77316 2010-11-26        kinaba: 		if( tryEat("...") )
f7e9e77316 2010-11-26        kinaba: 		{
f7e9e77316 2010-11-26        kinaba: 			return new Die(pos);
f7e9e77316 2010-11-26        kinaba: 		}
dc93ad8cf6 2010-11-09        kinaba: 		if( tryEat("@") )
dc93ad8cf6 2010-11-09        kinaba: 		{
dc93ad8cf6 2010-11-09        kinaba: 			auto lay = "@"~eatId("for layer ID");
dc93ad8cf6 2010-11-09        kinaba: 			eat("(", "for layered execution");
a5d10ace51 2010-11-09        kinaba: 			auto e = Body();
dc93ad8cf6 2010-11-09        kinaba: 			eat(")", "after "~lay~"(...");
6ac127ddd0 2010-11-23        kinaba: 			return new Lay(pos, lay, e);
423f308350 2010-11-07        kinaba: 		}
423f308350 2010-11-07        kinaba: 		if( tryEat("(") )
423f308350 2010-11-07        kinaba: 		{
b985f3bf91 2010-11-08        kinaba: 			auto e = Body();
423f308350 2010-11-07        kinaba: 			eat(")", "after parenthesized expression");
423f308350 2010-11-07        kinaba: 			return e;
423f308350 2010-11-07        kinaba: 		}
515502e8d1 2010-11-20        kinaba: 		if( tryEat("{") )
515502e8d1 2010-11-20        kinaba: 		{
6ac127ddd0 2010-11-23        kinaba: 			AST e = new App(pos, new Var(pos,"{}"));
6ecc7046fc 2010-11-21        kinaba: 			return parseTableSetAfterBrace(e);
515502e8d1 2010-11-20        kinaba: 		}
633e700889 2010-11-07        kinaba: 		if( tryEat("if") )
633e700889 2010-11-07        kinaba: 		{
153a14cec0 2010-11-24        kinaba: 			return parseIfAfterIf(pos);
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 		if( tryEat("case") )
3995a5eb6a 2010-11-21        kinaba: 		{
3995a5eb6a 2010-11-21        kinaba: 			return parsePatternMatch(pos);
a7b5d1d95a 2010-11-12        kinaba: 		}
a7b5d1d95a 2010-11-12        kinaba: 		if( tryEat("fun") || tryEat("\u03BB") ) // lambda!!
3f5dc76a75 2010-11-07        kinaba: 		{
3f5dc76a75 2010-11-07        kinaba: 			eat("(", "after fun");
68546f3e9f 2010-11-09        kinaba: 			return parseLambdaAfterOpenParen(pos);
68546f3e9f 2010-11-09        kinaba: 		}
68546f3e9f 2010-11-09        kinaba: 		scope(exit) lex.popFront;
6ac127ddd0 2010-11-23        kinaba: 		return new Var(pos, lex.front.str);
6ac127ddd0 2010-11-23        kinaba: 	}
6ac127ddd0 2010-11-23        kinaba: 
153a14cec0 2010-11-24        kinaba: 	AST parseIfAfterIf(LexPosition pos)
153a14cec0 2010-11-24        kinaba: 	{
153a14cec0 2010-11-24        kinaba: 		auto cond = E(0);
3ae09b8cbf 2010-11-24        kinaba: 		auto thenPos = currentPosition();
3ae09b8cbf 2010-11-24        kinaba: 		if(!tryEat(":")) {
3ae09b8cbf 2010-11-24        kinaba: 			eat("then", "after if condition");
3ae09b8cbf 2010-11-24        kinaba: 			tryEat(":");
153a14cec0 2010-11-24        kinaba: 		}
576c494e53 2010-11-27        kinaba: 		AST th = Body();
153a14cec0 2010-11-24        kinaba: 		auto el = doNothingExpression();
3ae09b8cbf 2010-11-24        kinaba: 		auto elsePos = currentPosition();
3ae09b8cbf 2010-11-24        kinaba: 		if( tryEat("else") ) {
3ae09b8cbf 2010-11-24        kinaba: 			tryEat(":");
576c494e53 2010-11-27        kinaba: 			el = Body();
3ae09b8cbf 2010-11-24        kinaba: 		}
153a14cec0 2010-11-24        kinaba: 		return new App(pos, new Var(pos,"if"), cond, new Fun(thenPos,[],th), new Fun(elsePos,[],el));
153a14cec0 2010-11-24        kinaba: 	}
153a14cec0 2010-11-24        kinaba: 
3995a5eb6a 2010-11-21        kinaba: 	AST parsePatternMatch(LexPosition pos)
3995a5eb6a 2010-11-21        kinaba: 	{
adacc96a55 2010-11-24        kinaba: 		//   case pmExpr CASES
3995a5eb6a 2010-11-21        kinaba: 		//==>
3995a5eb6a 2010-11-21        kinaba: 		//   let pmVar = pmExpr in (... let pmTryFirst = ... in pmTryFirst())
3995a5eb6a 2010-11-21        kinaba: 		AST   pmExpr = E(0);
3995a5eb6a 2010-11-21        kinaba: 		string pmVar = freshVarName();
3995a5eb6a 2010-11-21        kinaba: 		string pmTryFirst = freshVarName();
f9c31f3cd8 2010-11-24        kinaba: 		AST   pmBody = parsePatternMatchCases(pos, pmVar, pmTryFirst,
6ac127ddd0 2010-11-23        kinaba: 			new App(pos, new Var(pos, pmTryFirst)));
6ac127ddd0 2010-11-23        kinaba: 		return new Let(pos, pmVar, [], pmExpr, pmBody);
3995a5eb6a 2010-11-21        kinaba: 	}
3995a5eb6a 2010-11-21        kinaba: 
f9c31f3cd8 2010-11-24        kinaba: 	AST parsePatternMatchCases(LexPosition casePos, string pmVar, string tryThisBranchVar, AST thenDoThis)
3995a5eb6a 2010-11-21        kinaba: 	{
adacc96a55 2010-11-24        kinaba: 		//    when pat: cBody
3995a5eb6a 2010-11-21        kinaba: 		//==>
3995a5eb6a 2010-11-21        kinaba: 		//    ... let failBranchVar = ... in
3995a5eb6a 2010-11-21        kinaba: 		//    let tryThisBranchVar = fun(){ if(test){cBody}else{failBranchVar()} } in thenDoThis
3995a5eb6a 2010-11-21        kinaba: 		if( tryEat("when") )
3995a5eb6a 2010-11-21        kinaba: 		{
3995a5eb6a 2010-11-21        kinaba: 			auto pos = currentPosition();
3995a5eb6a 2010-11-21        kinaba: 			string failBranchVar = freshVarName();
3995a5eb6a 2010-11-21        kinaba: 
3995a5eb6a 2010-11-21        kinaba: 			auto pr = parsePattern();
adacc96a55 2010-11-24        kinaba: 			eat(":", "after when pattern");
576c494e53 2010-11-27        kinaba: 			AST cBody = Body();
6ac127ddd0 2010-11-23        kinaba: 			AST judgement = new App(pos, new Var(pos, "if"),
6ac127ddd0 2010-11-23        kinaba: 				ppTest(pmVar, pr), new Fun(pos,[],ppBind(pmVar, pr, cBody)),
6ac127ddd0 2010-11-23        kinaba: 				new Var(pos, failBranchVar));
f9c31f3cd8 2010-11-24        kinaba: 			return parsePatternMatchCases(casePos, pmVar, failBranchVar,
6ac127ddd0 2010-11-23        kinaba: 				new Let(pos, tryThisBranchVar, [],
6ac127ddd0 2010-11-23        kinaba: 					new Fun(pos,[],judgement), thenDoThis)
3995a5eb6a 2010-11-21        kinaba: 			);
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 		else
3995a5eb6a 2010-11-21        kinaba: 		{
f7e9e77316 2010-11-26        kinaba: 			AST doNothing = new Fun(casePos,[], new Die(casePos));
f9c31f3cd8 2010-11-24        kinaba: 			return new Let(casePos, tryThisBranchVar, [], doNothing, thenDoThis);
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 	}
3995a5eb6a 2010-11-21        kinaba: 
3995a5eb6a 2010-11-21        kinaba: // hageshiku tenuki
3995a5eb6a 2010-11-21        kinaba: 	abstract class SinglePattern
3995a5eb6a 2010-11-21        kinaba: 	{
3995a5eb6a 2010-11-21        kinaba: 		string[] path;
3995a5eb6a 2010-11-21        kinaba: 		mixin SimpleClass;
3995a5eb6a 2010-11-21        kinaba: 		private AST access(string pmVar, string[] path) {
3995a5eb6a 2010-11-21        kinaba: 			auto pos = currentPosition();
6ac127ddd0 2010-11-23        kinaba: 			AST e = new Var(pos, pmVar);
3995a5eb6a 2010-11-21        kinaba: 			foreach(p; path)
6ac127ddd0 2010-11-23        kinaba: 				e = new App(pos, new Var(pos, "."), e, new Str(pos, p));
3995a5eb6a 2010-11-21        kinaba: 			return e;
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 		private AST has(AST e, string k) {
3995a5eb6a 2010-11-21        kinaba: 			auto pos = currentPosition();
3995a5eb6a 2010-11-21        kinaba: 			return opAndAnd(
005474ba5b 2010-11-27        kinaba: 				new App(pos, new Var(pos, "_istbl"), e),
6ac127ddd0 2010-11-23        kinaba: 				new App(pos, new Var(pos, ".?"), e, new Str(pos, k))
3995a5eb6a 2010-11-21        kinaba: 			);
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 		private AST opAndAnd(AST a, AST b) {
3995a5eb6a 2010-11-21        kinaba: 			if( a is null ) return b;
3995a5eb6a 2010-11-21        kinaba: 			if( b is null ) return a;
3995a5eb6a 2010-11-21        kinaba: 			auto pos = currentPosition();
6ac127ddd0 2010-11-23        kinaba: 			return new App(pos,
6ac127ddd0 2010-11-23        kinaba: 				new Var(pos, "if"),
3995a5eb6a 2010-11-21        kinaba: 				a,
6ac127ddd0 2010-11-23        kinaba: 				new Fun(pos, [], b),
6ac127ddd0 2010-11-23        kinaba: 				new Fun(pos, [], new Int(pos, 0))
3995a5eb6a 2010-11-21        kinaba: 			);
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 		AST ppTest(string pmVar) {
3995a5eb6a 2010-11-21        kinaba: 			AST c = null;
3995a5eb6a 2010-11-21        kinaba: 			for(int i=0; i<path.length; ++i)
3995a5eb6a 2010-11-21        kinaba: 				c = opAndAnd(c, has(access(pmVar,path[0..i]), path[i]));
3995a5eb6a 2010-11-21        kinaba: 			return c;
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 		AST ppBind(string pmVar, AST thenDoThis) { return thenDoThis; }
3995a5eb6a 2010-11-21        kinaba: 	}
3995a5eb6a 2010-11-21        kinaba: 	class WildPattern : SinglePattern
3995a5eb6a 2010-11-21        kinaba: 	{
3995a5eb6a 2010-11-21        kinaba: 		mixin SimpleClass;
3995a5eb6a 2010-11-21        kinaba: 	}
3995a5eb6a 2010-11-21        kinaba: 	class VarPattern : SinglePattern
3995a5eb6a 2010-11-21        kinaba: 	{
3995a5eb6a 2010-11-21        kinaba: 		string name;
3995a5eb6a 2010-11-21        kinaba: 		mixin SimpleClass;
3995a5eb6a 2010-11-21        kinaba: 		AST ppBind(string pmVar, AST thenDoThis) {
3995a5eb6a 2010-11-21        kinaba: 			auto pos = currentPosition();
6ac127ddd0 2010-11-23        kinaba: 			return new Let(pos, name, [], access(pmVar,path), thenDoThis);
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 	}
3995a5eb6a 2010-11-21        kinaba: 	class ConstantPattern : SinglePattern
3995a5eb6a 2010-11-21        kinaba: 	{
3995a5eb6a 2010-11-21        kinaba: 		AST e;
3995a5eb6a 2010-11-21        kinaba: 		mixin SimpleClass;
3995a5eb6a 2010-11-21        kinaba: 		AST ppTest(string pmVar) {
3995a5eb6a 2010-11-21        kinaba: 			auto pos = currentPosition();
3995a5eb6a 2010-11-21        kinaba: 			return opAndAnd( super.ppTest(pmVar),
6ac127ddd0 2010-11-23        kinaba: 				new App(pos, new Var(pos,"=="), access(pmVar,path), e)
3995a5eb6a 2010-11-21        kinaba: 			);
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 	}
3995a5eb6a 2010-11-21        kinaba: 
3995a5eb6a 2010-11-21        kinaba: 	SinglePattern[] parsePattern(string[] path = null)
3995a5eb6a 2010-11-21        kinaba: 	{
3995a5eb6a 2010-11-21        kinaba: 		SinglePattern[] result;
3995a5eb6a 2010-11-21        kinaba: 		if( tryEat("{") )
3995a5eb6a 2010-11-21        kinaba: 		{
3995a5eb6a 2010-11-21        kinaba: 			if( !tryEat("}") ) {
3995a5eb6a 2010-11-21        kinaba: 				do {
20be503cae 2010-11-24        kinaba: 					string key = eatId("in table pattern", AllowQuoted);
3995a5eb6a 2010-11-21        kinaba: 					eat(":", "after field-id in table pattern");
3995a5eb6a 2010-11-21        kinaba: 					result ~= parsePattern(path ~ key);
3995a5eb6a 2010-11-21        kinaba: 				} while( tryEat(",") );
3995a5eb6a 2010-11-21        kinaba: 				eat("}", "at the end of table pattern");
3995a5eb6a 2010-11-21        kinaba: 			}
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 		else
3995a5eb6a 2010-11-21        kinaba: 		{
3995a5eb6a 2010-11-21        kinaba: 			AST e = E(0);
6ac127ddd0 2010-11-23        kinaba: 			if(auto ev = cast(Var)e)
3995a5eb6a 2010-11-21        kinaba: 				if(ev.name == "_")
3995a5eb6a 2010-11-21        kinaba: 					result ~= new WildPattern(path);
3995a5eb6a 2010-11-21        kinaba: 				else
3995a5eb6a 2010-11-21        kinaba: 					result ~= new VarPattern(path, ev.name);
3995a5eb6a 2010-11-21        kinaba: 			else
3995a5eb6a 2010-11-21        kinaba: 				result ~= new ConstantPattern(path, e);
3995a5eb6a 2010-11-21        kinaba: 		}
3995a5eb6a 2010-11-21        kinaba: 		return result;
3995a5eb6a 2010-11-21        kinaba: 	}
3995a5eb6a 2010-11-21        kinaba: 
3995a5eb6a 2010-11-21        kinaba: 	AST ppTest(string pmVar, SinglePattern[] pats)
3995a5eb6a 2010-11-21        kinaba: 	{
3995a5eb6a 2010-11-21        kinaba: 		auto pos = currentPosition();
3995a5eb6a 2010-11-21        kinaba: 		AST cond = null;
3995a5eb6a 2010-11-21        kinaba: 		foreach(p; pats) {
3995a5eb6a 2010-11-21        kinaba: 			AST c2 = p.ppTest(pmVar);
3995a5eb6a 2010-11-21        kinaba: 			if( c2 !is null )
3995a5eb6a 2010-11-21        kinaba: 				cond = cond is null ? c2
6ac127ddd0 2010-11-23        kinaba: 				    : new App(pos, new Var(pos,"&&"), cond, c2);
3995a5eb6a 2010-11-21        kinaba: 		}
6ac127ddd0 2010-11-23        kinaba: 		return cond is null ? new Int(currentPosition(), 1) : cond;
3995a5eb6a 2010-11-21        kinaba: 	}
3995a5eb6a 2010-11-21        kinaba: 
3995a5eb6a 2010-11-21        kinaba: 	AST ppBind(string pmVar, SinglePattern[] pats, AST thenDoThis)
3995a5eb6a 2010-11-21        kinaba: 	{
3995a5eb6a 2010-11-21        kinaba: 		foreach(p; pats)
3995a5eb6a 2010-11-21        kinaba: 			thenDoThis = p.ppBind(pmVar, thenDoThis);
3995a5eb6a 2010-11-21        kinaba: 		return thenDoThis;
515502e8d1 2010-11-20        kinaba: 	}
515502e8d1 2010-11-20        kinaba: 
515502e8d1 2010-11-20        kinaba: 	AST parseId()
515502e8d1 2010-11-20        kinaba: 	{
515502e8d1 2010-11-20        kinaba: 		scope(exit) lex.popFront;
6ac127ddd0 2010-11-23        kinaba: 		return new Str(currentPosition(), lex.front.str);
68546f3e9f 2010-11-09        kinaba: 	}
68546f3e9f 2010-11-09        kinaba: 
ba11f1d551 2010-11-23        kinaba: 	AST parseLambdaAfterOpenParen(LexPosition pos)
68546f3e9f 2010-11-09        kinaba: 	{
8e6fa743ee 2010-11-11        kinaba: 		Parameter[] params;
68546f3e9f 2010-11-09        kinaba: 		while( !tryEat(")") )
68546f3e9f 2010-11-09        kinaba: 		{
a7b5d1d95a 2010-11-12        kinaba: 			params ~= parseParam();
68546f3e9f 2010-11-09        kinaba: 			if( !tryEat(",") ) {
68546f3e9f 2010-11-09        kinaba: 				eat(")", "after function parameters");
68546f3e9f 2010-11-09        kinaba: 				break;
68546f3e9f 2010-11-09        kinaba: 			}
68546f3e9f 2010-11-09        kinaba: 		}
68546f3e9f 2010-11-09        kinaba: 		eat("{", "after function parameters");
68546f3e9f 2010-11-09        kinaba: 		auto funbody = Body();
68546f3e9f 2010-11-09        kinaba: 		eat("}", "after function body");
6ac127ddd0 2010-11-23        kinaba: 		return new Fun(pos, params, funbody);
a7b5d1d95a 2010-11-12        kinaba: 	}
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	Parameter parseParam()
a7b5d1d95a 2010-11-12        kinaba: 	{
a7b5d1d95a 2010-11-12        kinaba: 		string var;
a7b5d1d95a 2010-11-12        kinaba: 		string[] lay;
a7b5d1d95a 2010-11-12        kinaba: 		while( !closingBracket() && !lex.empty && lex.front.str!="," )
a7b5d1d95a 2010-11-12        kinaba: 		{
a7b5d1d95a 2010-11-12        kinaba: 			auto pos = currentPosition();
a7b5d1d95a 2010-11-12        kinaba: 			string p = eatId("for function parameter", AllowQuoted);
a7b5d1d95a 2010-11-12        kinaba: 			if( p == "@" )
a7b5d1d95a 2010-11-12        kinaba: 				lay ~= "@" ~ eatId("after @", AllowQuoted);
a7b5d1d95a 2010-11-12        kinaba: 			else if( var.empty )
a7b5d1d95a 2010-11-12        kinaba: 				var = p;
a7b5d1d95a 2010-11-12        kinaba: 			else
a7b5d1d95a 2010-11-12        kinaba: 				throw genex!ParseException(pos, "one parameter has two names");
a7b5d1d95a 2010-11-12        kinaba: 		}
a7b5d1d95a 2010-11-12        kinaba: 		return new Parameter(var, lay);
423f308350 2010-11-07        kinaba: 	}
423f308350 2010-11-07        kinaba: 
423f308350 2010-11-07        kinaba: private:
423f308350 2010-11-07        kinaba: 	Lexer lex;
b985f3bf91 2010-11-08        kinaba: 	this(Lexer lex) { this.lex = lex; }
a7b5d1d95a 2010-11-12        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	bool isNumber(string s)
a7b5d1d95a 2010-11-12        kinaba: 	{
a7b5d1d95a 2010-11-12        kinaba: 		return find!(`a<'0' || '9'<a`)(s).empty;
a7b5d1d95a 2010-11-12        kinaba: 	}
6f0ec5b7c9 2010-11-11        kinaba: 
423f308350 2010-11-07        kinaba: 	void eat(string kwd, lazy string msg)
423f308350 2010-11-07        kinaba: 	{
423f308350 2010-11-07        kinaba: 		if( !tryEat(kwd) )
2459e9a821 2010-11-09        kinaba: 			if( lex.empty )
2459e9a821 2010-11-09        kinaba: 				throw genex!UnexpectedEOF(
6f0ec5b7c9 2010-11-11        kinaba: 					currentPosition(), sprintf!"%s is expected %s but not found"(kwd,msg));
2459e9a821 2010-11-09        kinaba: 			else
2459e9a821 2010-11-09        kinaba: 				throw genex!ParseException(
2459e9a821 2010-11-09        kinaba: 					currentPosition(), sprintf!"%s is expected for %s but not found"(kwd,msg));
423f308350 2010-11-07        kinaba: 	}
423f308350 2010-11-07        kinaba: 
423f308350 2010-11-07        kinaba: 	bool tryEat(string kwd)
423f308350 2010-11-07        kinaba: 	{
8d297342aa 2010-11-08        kinaba: 		if( lex.empty || lex.front.quoted || lex.front.str!=kwd )
423f308350 2010-11-07        kinaba: 			return false;
423f308350 2010-11-07        kinaba: 		lex.popFront;
423f308350 2010-11-07        kinaba: 		return true;
8d297342aa 2010-11-08        kinaba: 	}
8d297342aa 2010-11-08        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	enum {AllowQuoted=true, DisallowQuoted=false};
a7b5d1d95a 2010-11-12        kinaba: 	string eatId(lazy string msg, bool aq=DisallowQuoted)
b985f3bf91 2010-11-08        kinaba: 	{
2459e9a821 2010-11-09        kinaba: 		if( lex.empty )
2459e9a821 2010-11-09        kinaba: 			throw genex!UnexpectedEOF(currentPosition(), "identifier is expected but not found "~msg);
a7b5d1d95a 2010-11-12        kinaba: 		if( !aq && lex.front.quoted )
2459e9a821 2010-11-09        kinaba: 			throw genex!ParseException(currentPosition(), "identifier is expected but not found "~msg);
2459e9a821 2010-11-09        kinaba: 		scope(exit) lex.popFront;
2459e9a821 2010-11-09        kinaba: 		return lex.front.str;
b985f3bf91 2010-11-08        kinaba: 	}
b985f3bf91 2010-11-08        kinaba: 
a7b5d1d95a 2010-11-12        kinaba: 	AST doNothingExpression()
b985f3bf91 2010-11-08        kinaba: 	{
6ac127ddd0 2010-11-23        kinaba: 		return new Str(currentPosition(), "(empty function body)");
2459e9a821 2010-11-09        kinaba: 	}
2459e9a821 2010-11-09        kinaba: 
ba11f1d551 2010-11-23        kinaba: 	LexPosition currentPosition()
2459e9a821 2010-11-09        kinaba: 	{
f9c31f3cd8 2010-11-24        kinaba: 		return lex.empty ? new LexPosition("EOF",0,0) : lex.front.pos;
423f308350 2010-11-07        kinaba: 	}
423f308350 2010-11-07        kinaba: }
423f308350 2010-11-07        kinaba: 
423f308350 2010-11-07        kinaba: unittest
423f308350 2010-11-07        kinaba: {
b985f3bf91 2010-11-08        kinaba: 	mixin EasyAST;
b985f3bf91 2010-11-08        kinaba: 
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`123`), intl(123));
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`"foo"`), strl("foo"));
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`fun(){1}`), fun([],intl(1)));
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`fun(x){1}`), fun(["x"],intl(1)));
77abaf5f42 2010-11-09        kinaba: 	assert_eq(parseString("\u03BB(){1}"), fun([],intl(1)));
f8684f4d69 2010-11-26        kinaba: 	assert_eq(parseString("\u03BB(x,y){1}"), fun(["x","y"],intl(1)));
2459e9a821 2010-11-09        kinaba: 	assert_eq(parseString(`1;2`), let("_","",intl(1),intl(2)));
2459e9a821 2010-11-09        kinaba: 	assert_eq(parseString(`1;2;`), let("_","",intl(1),intl(2)));
a7b5d1d95a 2010-11-12        kinaba: 	assert_eq(parseString(`let x=1 in 2`), let("x","",intl(1),intl(2)));
0f02103885 2010-11-09        kinaba: 	assert_eq(parseString(`var x=1;2;`), let("x","",intl(1),intl(2)));
0f02103885 2010-11-09        kinaba: 	assert_eq(parseString(`def x=1`), let("x","",intl(1),var("x")));
f8684f4d69 2010-11-26        kinaba: 	assert_eq(parseString(`@val x=1;`), let("x","@val",intl(1),lay("@val",var("x"))));
f8684f4d69 2010-11-26        kinaba: 	assert_eq(parseString(`@typ x="#int";`), let("x","@typ",strl("#int"),lay("@typ",var("x"))));
f8684f4d69 2010-11-26        kinaba: 	assert_eq(parseString(`@macro x=1`), let("x","@macro",intl(1),strl("(macro definition)")));
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`f(1,2)`), call(var("f"),intl(1),intl(2)));
3ae09b8cbf 2010-11-24        kinaba: 	assert_eq(parseString(`if 1 then 2`), call(var("if"),intl(1),fun([],intl(2)),fun([],strl("(empty function body)"))));
3ae09b8cbf 2010-11-24        kinaba: 	assert_eq(parseString(`if 1 then: 2 else(3)`), call(var("if"),intl(1),fun([],intl(2)),fun([],intl(3))));
3ae09b8cbf 2010-11-24        kinaba: 	assert_eq(parseString(`(if 1 then () else 3)()()`),
2bdfb8a182 2010-11-21        kinaba: 		call(call(call(var("if"),intl(1),fun([],strl("(empty function body)")),fun([],intl(3))))));
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`1+2*3`), call(var("+"),intl(1),call(var("*"),intl(2),intl(3))));
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`(1+2)*3`), call(var("*"),call(var("+"),intl(1),intl(2)),intl(3)));
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`1*(2+3)`), call(var("*"),intl(1),call(var("+"),intl(2),intl(3))));
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`1*2+3`), call(var("+"),call(var("*"),intl(1),intl(2)),intl(3)));
dc93ad8cf6 2010-11-09        kinaba: 	assert_eq(parseString(`@x(1)`), lay("@x", intl(1)));
a7b5d1d95a 2010-11-12        kinaba: 	assert_eq(parseString(`fun(x @v @t, y, z @t){}`),
2bdfb8a182 2010-11-21        kinaba: 		funp([param("x",["@v","@t"]), param("y",[]), param("z",["@t"])], strl("(empty function body)")));
b985f3bf91 2010-11-08        kinaba: 
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`
aa770610d3 2010-11-08        kinaba: 		let x = 100; #comment
aa770610d3 2010-11-08        kinaba: 		let y = 200; #comment!!!!!
b985f3bf91 2010-11-08        kinaba: 			x+y
b985f3bf91 2010-11-08        kinaba: 	`),
0f02103885 2010-11-09        kinaba: 		let("x", "", intl(100), let("y", "", intl(200), call(var("+"), var("x"), var("y"))))
b985f3bf91 2010-11-08        kinaba: 	);
b985f3bf91 2010-11-08        kinaba: 
b985f3bf91 2010-11-08        kinaba: 	assert_eq(parseString(`
3ae09b8cbf 2010-11-24        kinaba: 		var fac = fun(x){ if(x <= 1) then 1 else x*fac(x-1) };
b985f3bf91 2010-11-08        kinaba: 		fac(10)
b985f3bf91 2010-11-08        kinaba: 	`),
0f02103885 2010-11-09        kinaba: 		let("fac", "", fun(["x"],
b985f3bf91 2010-11-08        kinaba: 			call(var("if"),
b985f3bf91 2010-11-08        kinaba: 				call(var("<="), var("x"), intl(1)),
b985f3bf91 2010-11-08        kinaba: 				fun([], intl(1)),
b985f3bf91 2010-11-08        kinaba: 				fun([], call(var("*"), var("x"), call(var("fac"),call(var("-"),var("x"),intl(1)))))
b985f3bf91 2010-11-08        kinaba: 			)),
b985f3bf91 2010-11-08        kinaba: 			call(var("fac"),intl(10))
b985f3bf91 2010-11-08        kinaba: 		)
b985f3bf91 2010-11-08        kinaba: 	);
b985f3bf91 2010-11-08        kinaba: }
b985f3bf91 2010-11-08        kinaba: 
b985f3bf91 2010-11-08        kinaba: unittest
b985f3bf91 2010-11-08        kinaba: {
2459e9a821 2010-11-09        kinaba: 	assert_throw!UnexpectedEOF(parseString(`1+`));
b985f3bf91 2010-11-08        kinaba: 	assert_throw!ParseException(parseString(`1+2}`));
2459e9a821 2010-11-09        kinaba: 	assert_throw!UnexpectedEOF(parseString(`let "x"`));
2459e9a821 2010-11-09        kinaba: 	assert_throw!UnexpectedEOF(parseString(`var`));
aa770610d3 2010-11-08        kinaba: 	assert_throw!ParseException(parseString(`@val x ==`));
b985f3bf91 2010-11-08        kinaba: 	assert_throw!ParseException(parseString(`if(){1}`));
2459e9a821 2010-11-09        kinaba: 	assert_throw!UnexpectedEOF(parseString(`f(`));
23fb1b4a0e 2010-11-26        kinaba: 	assert_throw!ParseException(parseString(`fun(x y){}`));
68546f3e9f 2010-11-09        kinaba: }
68546f3e9f 2010-11-09        kinaba: 
68546f3e9f 2010-11-09        kinaba: unittest
68546f3e9f 2010-11-09        kinaba: {
68546f3e9f 2010-11-09        kinaba: 	mixin EasyAST;
68546f3e9f 2010-11-09        kinaba: 	assert_eq(parseString(`def foo(x) { x+1 }; foo`),
68546f3e9f 2010-11-09        kinaba: 		let("foo", "",
68546f3e9f 2010-11-09        kinaba: 			fun(["x"], call(var("+"), var("x"), intl(1))),
68546f3e9f 2010-11-09        kinaba: 			var("foo"))
68546f3e9f 2010-11-09        kinaba: 	);
c368edbcb1 2010-11-13        kinaba: 
c368edbcb1 2010-11-13        kinaba: 	assert_eq(parseString(`@@type ( x ) { x }`),
207cea338a 2010-11-26        kinaba: 		let("@type", LiftLayer, fun(["x"], var("x")), lay(LiftLayer, var("@type"))) );
515502e8d1 2010-11-20        kinaba: 
515502e8d1 2010-11-20        kinaba: 	assert_eq(parseString(`{}`), call(var("{}")));
515502e8d1 2010-11-20        kinaba: 	assert_eq(parseString(`{foo:1,"bar":2}`),
515502e8d1 2010-11-20        kinaba: 		call(var(".="), call(var(".="), call(var("{}")), strl("foo"), intl(1)), strl("bar"), intl(2)));
515502e8d1 2010-11-20        kinaba: 	assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo")));
515502e8d1 2010-11-20        kinaba: 	assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("foo")));
6ecc7046fc 2010-11-21        kinaba: 	assert_eq(parseString(`x{y:1}`), call(var(".="),var("x"),strl("y"),intl(1)));
3995a5eb6a 2010-11-21        kinaba: }
3995a5eb6a 2010-11-21        kinaba: 
3995a5eb6a 2010-11-21        kinaba: unittest
3995a5eb6a 2010-11-21        kinaba: {
3995a5eb6a 2010-11-21        kinaba: 	assert_nothrow(parseString(`
3995a5eb6a 2010-11-21        kinaba: 		case( 1 )
adacc96a55 2010-11-24        kinaba: 			when(x): 1
5e924caac9 2010-11-23        kinaba: 	`));
5e924caac9 2010-11-23        kinaba: 	assert_nothrow(parseString(`
adacc96a55 2010-11-24        kinaba: 		case 1
adacc96a55 2010-11-24        kinaba: 			when {aaaa:_}: 1
3995a5eb6a 2010-11-21        kinaba: 	`));
3995a5eb6a 2010-11-21        kinaba: 	assert_nothrow(parseString(`
adacc96a55 2010-11-24        kinaba: 		case 1
adacc96a55 2010-11-24        kinaba: 			when {aaaa:@value(x)}: 1
adacc96a55 2010-11-24        kinaba: 			when {aaaa:{bbb:_}, ccc:123}: 1
3995a5eb6a 2010-11-21        kinaba: 	`));
423f308350 2010-11-07        kinaba: }