This commit is contained in:
Rohan Singh
2019-01-23 22:52:45 -05:00
parent 3f69ec7987
commit ad50a19057
103 changed files with 5734 additions and 1 deletions
@@ -0,0 +1,24 @@
using System.Collections.Generic;
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class BlockParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = false;
var statements = new List<Statement>();
while (!parser.Match(ScriptTokenType.RightBrace))
{
statements.Add(parser.ParseStatement());
}
parser.Take(ScriptTokenType.RightBrace);
return new BlockStatement(token, parser.Previous, statements);
}
}
}
@@ -0,0 +1,13 @@
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class BreakParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = true;
return new BreakStatement(token);
}
}
}
@@ -0,0 +1,29 @@
using System.Collections.Generic;
using ScriptConverter.Ast;
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class ConstVariableParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = true;
ScriptType type;
string name;
parser.ParseNamedType(out type, out name);
parser.Take(ScriptTokenType.Assign);
var value = parser.ParseExpression();
var definitions = new List<VariableStatement.Definition>()
{
new VariableStatement.Definition(type, name, value)
};
return new VariableStatement(token, parser.Previous, type, true, definitions);
}
}
}
@@ -0,0 +1,13 @@
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class ContinueParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = true;
return new ContinueStatement(token);
}
}
}
@@ -0,0 +1,23 @@
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class DoParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = true;
var block = parser.ParseBlock();
parser.Take(ScriptTokenType.While);
parser.Take(ScriptTokenType.LeftParen);
var condition = parser.ParseExpression();
parser.Take(ScriptTokenType.RightParen);
return new DoStatement(token, parser.Previous, condition, block);
}
}
}
@@ -0,0 +1,13 @@
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class EmptyParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = false;
return new EmptyStatement(token);
}
}
}
@@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.Linq;
using ScriptConverter.Ast.Expressions;
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class ForParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = false;
parser.Take(ScriptTokenType.LeftParen);
List<Statement> initializers = null;
if (!parser.Match(ScriptTokenType.Semicolon))
{
initializers = parser.ParseSeparatedBy(ScriptTokenType.Comma, (_, first) =>
{
var stmt = parser.ParseStatement(false);
if (!(stmt is VariableStatement) && !(stmt is NakedStatement))
throw new CompilerException(token, "bad for loop initializer");
return stmt;
}).ToList();
}
parser.Take(ScriptTokenType.Semicolon);
Expression condition = null;
if (!parser.Match(ScriptTokenType.Semicolon))
condition = parser.ParseExpression();
parser.Take(ScriptTokenType.Semicolon);
List<Expression> increment = null;
if (!parser.Match(ScriptTokenType.RightParen))
increment = parser.ParseSeparatedBy(ScriptTokenType.Comma, (_, first) => parser.ParseExpression()).ToList();
parser.Take(ScriptTokenType.RightParen);
var block = parser.ParseBlock();
return new ForStatement(token, parser.Previous, initializers, condition, increment, block);
}
}
}
@@ -0,0 +1,47 @@
using System.Collections.Generic;
using ScriptConverter.Ast.Expressions;
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class IfParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = false;
var first = true;
var branches = new List<IfStatement.Branch>();
IfStatement.Branch defaultBranch = null;
do
{
var isDefaultBranch = !first && !parser.MatchAndTake(ScriptTokenType.If);
first = false;
Expression condition = null;
if (!isDefaultBranch)
{
parser.Take(ScriptTokenType.LeftParen);
condition = parser.ParseExpression();
parser.Take(ScriptTokenType.RightParen);
}
var block = parser.ParseBlock();
var branch = new IfStatement.Branch(condition, block);
if (isDefaultBranch)
defaultBranch = branch;
else
branches.Add(branch);
if (isDefaultBranch)
break;
} while (parser.MatchAndTake(ScriptTokenType.Else));
return new IfStatement(token, parser.Previous, branches, defaultBranch);
}
}
}
@@ -0,0 +1,18 @@
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class ReturnParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = true;
if (parser.Match(ScriptTokenType.Semicolon))
return new ReturnStatement(token, parser.Previous, null);
var value = parser.ParseExpression();
return new ReturnStatement(token, parser.Previous, value);
}
}
}
@@ -0,0 +1,84 @@
using System.Collections.Generic;
using ScriptConverter.Ast.Expressions;
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class SwitchParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = false;
parser.Take(ScriptTokenType.LeftParen);
var expression = parser.ParseExpression();
parser.Take(ScriptTokenType.RightParen);
parser.Take(ScriptTokenType.LeftBrace);
var hasDefault = false;
var branches = new List<SwitchStatement.Branch>();
while (!parser.Match(ScriptTokenType.RightBrace))
{
var conditions = new List<Expression>();
while (true)
{
if (parser.MatchAndTake(ScriptTokenType.Case))
{
var condition = parser.ParseExpression();
conditions.Add(condition);
parser.Take(ScriptTokenType.Colon);
continue;
}
if (!parser.Match(ScriptTokenType.Default))
break;
var defaultToken = parser.Take(ScriptTokenType.Default);
if (hasDefault)
throw new CompilerException(defaultToken, "Multiple default labels");
conditions.Add(null); // special default condition
hasDefault = true;
parser.Take(ScriptTokenType.Colon);
}
if (conditions.Count > 0)
{
var block = ParseBlock(parser);
var branch = new SwitchStatement.Branch(conditions, block);
branches.Add(branch);
continue;
}
var errorToken = parser.Peek();
throw new CompilerException(errorToken, "Expected Case or Default but found {0}", errorToken);
}
parser.Take(ScriptTokenType.RightBrace);
return new SwitchStatement(token, parser.Previous, expression, branches);
}
private static BlockStatement ParseBlock(ScriptParser parser)
{
var statements = new List<Statement>();
var start = parser.Peek();
while (!parser.Match(ScriptTokenType.Case) &&
!parser.Match(ScriptTokenType.Default) &&
!parser.Match(ScriptTokenType.RightBrace))
{
statements.Add(parser.ParseStatement());
}
return new BlockStatement(start, parser.Previous, statements, true);
}
}
}
@@ -0,0 +1,15 @@
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class ThrowParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = true;
var value = parser.ParseExpression();
return new ThrowStatement(token, value);
}
}
}
@@ -0,0 +1,34 @@
using System.Collections.Generic;
using ScriptConverter.Ast;
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class TryParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = false;
var mainBlock = parser.ParseBlock(false);
var catches = new List<TryStatement.Branch>(2);
do
{
parser.Take(ScriptTokenType.Catch);
parser.Take(ScriptTokenType.LeftParen);
ScriptType type;
string name;
parser.ParseNamedType(out type, out name);
parser.Take(ScriptTokenType.RightParen);
var block = parser.ParseBlock(false);
catches.Add(new TryStatement.Branch(type, name, block));
} while (parser.Match(ScriptTokenType.Catch));
return new TryStatement(token, parser.Previous, mainBlock, catches);
}
}
}
@@ -0,0 +1,42 @@
using System.Linq;
using ScriptConverter.Ast;
using ScriptConverter.Ast.Expressions;
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class VariableParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = true;
var baseType = parser.ParseType(token);
var definitions = parser.ParseSeparatedBy(ScriptTokenType.Comma, (_, first) =>
{
var name = parser.Take(ScriptTokenType.Identifier).Contents;
var arrayDims = 0;
while (parser.MatchAndTake(ScriptTokenType.LeftSquare))
{
parser.Take(ScriptTokenType.RightSquare);
arrayDims++;
}
var type = baseType;
if (arrayDims > 0)
type = new ScriptType(baseType.Name, baseType.ArrayDimensions + arrayDims, baseType.IsResizable);
Expression value = null;
if (parser.MatchAndTake(ScriptTokenType.Assign))
value = parser.ParseExpression();
return new VariableStatement.Definition(type, name, value);
}).ToList();
return new VariableStatement(token, parser.Previous, baseType, false, definitions);
}
}
}
@@ -0,0 +1,20 @@
using ScriptConverter.Ast.Statements;
namespace ScriptConverter.Parser.Parselets.Statements
{
class WhileParselet : IStatementParselet
{
public Statement Parse(ScriptParser parser, ScriptToken token, out bool trailingSemicolon)
{
trailingSemicolon = false;
parser.Take(ScriptTokenType.LeftParen);
var condition = parser.ParseExpression();
parser.Take(ScriptTokenType.RightParen);
var block = parser.ParseBlock();
return new WhileStatement(token, parser.Previous, condition, block);
}
}
}