Fix Parser Whitespace.

Fix Parser Whitespace.

--- PineTree.Language/Parser/PineTreeParser.cs
+++ PineTree.Language/Parser/PineTreeParser.cs
@@ -8,1446 +8,1446 @@

 namespace PineTree.Language.Parser
 {
-	public class PineTreeParser
-	{
-		private Token _current;
-		private bool _enforceSemi;
-		private Token _last;
-		private PineTreeLexer _lexer;
-
-		private Token _next;
-
-		/// <summary>
-		/// Initializes a new instance of the <see cref="PineTreeParser"/> class.
-		/// </summary>
-		public PineTreeParser()
-			: this(new PineTreeLexer())
-		{
-		}
-
-		/// <summary>
-		/// Initializes a new instance of the <see cref="PineTreeParser"/> class with a given <see cref="PineTreeLexer"/>.
-		/// </summary>
-		/// <param name="lexer"></param>
-		public PineTreeParser(PineTreeLexer lexer)
-		{
-			_lexer = lexer;
-			_enforceSemi = true;
-		}
-
-		/// <summary>
-		/// Parses all of the given source code and returns a <see cref="SourceDocument"/> containing the created Abstract Syntax Tree.
-		/// Root members of the file must be classes or methods and semicolons are enforced.
-		/// </summary>
-		/// <seealso cref="Parse(string)"/>
-		/// <returns></returns>
-		public SourceDocument Parse()
-		{
-			InitializeTokens(true);
-			List<SyntaxNode> nodes = new List<SyntaxNode>();
-
-			try
-			{
-				while (_current != TokenType.EOF)
-				{
-					nodes.Add(ParseClassOrMethod());
-				}
-			}
-			catch (SyntaxException)
-			{
-				_lexer.Clear();
-				throw;
-			}
-
-			return new SourceDocument(nodes);
-		}
-
-		/// <summary>
-		/// Parses all of the given source code and returns a <see cref="SourceDocument"/> containing the created Abstract Syntax Tree.
-		/// Root members of the file must be classes or methods and semicolons are enforced.
-		/// </summary>
-		/// <param name="source">The file to parse.</param>
-		/// <seealso cref="Parse"/>
-		/// <returns></returns>
-		public SourceDocument Parse(string source)
-		{
-			_lexer.Feed(source);
-			try
-			{
-				return Parse();
-			}
-			catch (SyntaxException)
-			{
-				_lexer.Clear();
-				throw;
-			}
-		}
-
-		/// <summary>
-		/// Parses an <see cref="Expression"/> and returns an AST object containing the contents.
-		/// Semicolons are not enforced.
-		/// </summary>
-		/// <param name="source">The expression to parse.</param>
-		/// <returns></returns>
-		public Expression ParseExpression(string source)
-		{
-			_lexer.Feed(source);
-			InitializeTokens(false);
-			try
-			{
-				return ParseExpression();
-			}
-			catch (SyntaxException)
-			{
-				_lexer.Clear();
-				throw;
-			}
-		}
-
-		/// <summary>
-		/// Parses all of the given source code and returns a <see cref="SourceDocument"/> containing the created Abstract Syntax Tree.
-		/// Root members of the file may be classes, methods, or statements.  Semicolons are not enforced.
-		/// </summary>
-		/// <param name="source">The source code to parse.</param>
-		/// <returns></returns>
-		public SourceDocument ParseScript(string source)
-		{
-			_lexer.Feed(source);
-			InitializeTokens(false);
-			List<SyntaxNode> nodes = new List<SyntaxNode>();
-			try
-			{
-				while (_current != TokenType.EOF)
-				{
-					if (_current == "import")
-					{
-						nodes.Add(ParseImportStatement());
-					}
-					else if (_current == "public" || _current == "private" || _current == "protected" || _current == "class")
-					{
-						nodes.Add(ParseClassOrMethod());
-					}
-					else
-					{
-						nodes.Add(ParseStatement());
-					}
-				}
-			}
-			catch (SyntaxException)
-			{
-				_lexer.Clear();
-				throw;
-			}
-
-			return new SourceDocument(nodes);
-		}
-
-		/// <summary>
-		/// Parses a single statement and returns the created Abstract Syntax Tree.
-		/// Semicolons are not enforced.
-		/// </summary>
-		/// <param name="source">The source code to parse.</param>
-		/// <returns></returns>
-		public SyntaxNode ParseStatement(string source)
-		{
-			_lexer.Feed(source);
-			InitializeTokens(false);
-
-			try
-			{
-				return ParseStatement();
-			}
-			catch (SyntaxException)
-			{
-				_lexer.Clear();
-				throw;
-			}
-		}
-
-		private void AcceptToken()
-		{
-			_last = _current;
-			_current = _next;
-			_next = _lexer.LexToken(g => !g.IsTrivia());
-		}
-
-		private void InitializeTokens(bool enforceSemi)
-		{
-			_enforceSemi = enforceSemi;
-			AcceptToken();
-			AcceptToken();
-			_last = null;
-		}
-
-		private IEnumerable<VariableDeclaration> ParseArgumentList()
-		{
-			Take(TokenType.OpenPara);
-
-			List<VariableDeclaration> arguments = new List<VariableDeclaration>();
-
-			while (_current != TokenType.ClosePara)
-			{
-				VariableDeclaration variable = ParseVariableDeclaration();
-				if (variable != null)
-				{
-					arguments.Add(variable);
-				}
-
-				if (_current == TokenType.Comma && _current != TokenType.ClosePara)
-				{
-					Take(TokenType.Comma);
-				}
-			}
-
-			Take(TokenType.ClosePara);
-
-			return arguments;
-		}
-
-		private AssignmentType ParseAssignmentType()
-		{
-			if (_current.Catagory != TokenCatagory.Assignment)
-			{
-				throw UnexpectedToken("assignment operator");
-			}
-
-			var op = _current.Type;
-			AcceptToken();
-
-			switch (op)
-			{
-				case TokenType.Assignment:
-					return AssignmentType.Regular;
-
-				case TokenType.AssignmentAdd:
-					return AssignmentType.AddTo;
-
-				case TokenType.AssignmentSubtract:
-					return AssignmentType.SubractFrom;
-
-				case TokenType.AssignmentMultiply:
-					return AssignmentType.MultiplyBy;
-
-				case TokenType.AssignmentDivide:
-					return AssignmentType.DivideBy;
-
-				default:
-					return AssignmentType.Regular;
-			}
-		}
-
-		private CatchStatement ParseCatchStatement()
-		{
-			TakeKeyword("catch");
-			VariableDeclaration variable = null;
-			if (_current == TokenType.OpenPara)
-			{
-				Take(TokenType.OpenPara);
-				variable = ParseVariableDeclaration(false);
-				Take(TokenType.ClosePara);
-			}
-			SyntaxNode body = ParseLexicalScopeOrStatement();
-			return new CatchStatement(body, variable);
-		}
-
-		private ClassDeclaration ParseClass(Visibility visibility)
-		{
-			TakeKeyword("class");
-			var name = Take(TokenType.Identifier).Value;
-			string supertype = "object";
-			if (_current == "extends")
-			{
-				AcceptToken();
-				supertype = Take(TokenType.Identifier).Value;
-			}
-
-			Take(TokenType.OpenBracket);
-
-			List<FieldDeclaration> fields = new List<FieldDeclaration>();
-			List<MethodDeclaration> methods = new List<MethodDeclaration>();
-			List<PropertyDeclaration> properties = new List<PropertyDeclaration>();
-			List<ConstructorDeclaration> constructors = new List<ConstructorDeclaration>();
-
-			while (_current != TokenType.CloseBracket)
-			{
-				var node = ParseClassMember(name);
-
-				switch (node.SyntaxType)
-				{
-					case SyntaxTypes.FieldDeclaration:
-						fields.Add((FieldDeclaration)node);
-						break;
-
-					case SyntaxTypes.PropertyDeclaration:
-						properties.Add((PropertyDeclaration)node);
-						break;
-
-					case SyntaxTypes.MethodDeclaration:
-						methods.Add((MethodDeclaration)node);
-						break;
-
-					case SyntaxTypes.ConstructorDeclaration:
-						constructors.Add((ConstructorDeclaration)node);
-						break;
-				}
-			}
-			Take(TokenType.CloseBracket);
-
-			return new ClassDeclaration(name, supertype, fields, properties, methods, constructors);
-		}
-
-		private SyntaxNode ParseClassMember(string type)
-		{
-			var visibility = ParseVisibility(true);
-
-			if (_next == TokenType.OpenPara && _current == type)
-			{
-				return ParseConstructor(visibility);
-			}
-			else
-			{
-				bool isStatic = false;
-				if (_current == "static")
-				{
-					isStatic = true;
-					AcceptToken();
-				}
-				string name;
-				string returnType;
-
-				ParseTypeAndName(out returnType, out name, "void");
-
-				if (_current == TokenType.OpenBracket)
-				{
-					if (returnType == "void")
-					{
-						throw UnexpectedToken("type");
-					}
-					return ParseProperty(visibility, name, returnType);
-				}
-				else if (_current == TokenType.OpenPara)
-				{
-					return ParseMethod(visibility, name, returnType, isStatic);
-				}
-				else if (_current == TokenType.Assignment || _current == TokenType.Semicolon)
-				{
-					if (_current == TokenType.Semicolon)
-					{
-						Take(TokenType.Semicolon);
-						return new FieldDeclaration(name, type, null);
-					}
-
-					var expression = ParseExpression();
-					if (_current == TokenType.Semicolon || _enforceSemi)
-					{
-						Take(TokenType.Semicolon);
-					}
-					return new FieldDeclaration(name, type, expression);
-				}
-			}
-			return null;
-		}
-
-		private SyntaxNode ParseClassOrMethod()
-		{
-			Visibility visibility = ParseVisibility(true);
-
-			SyntaxNode node;
-
-			if (_current == "class")
-			{
-				node = ParseClass(visibility);
-			}
-			else
-			{
-				string type, name;
-				ParseTypeAndName(out type, out name, "void");
-
-				node = ParseMethod(visibility, name, type, false);
-			}
-
-			return node;
-		}
-
-		private ConstructorDeclaration ParseConstructor(Visibility visibility)
-		{
-			string name = Take(TokenType.Identifier).Value;
-			var args = ParseArgumentList();
-			var body = ParseLexicalScope();
-
-			return new ConstructorDeclaration(name, visibility, args, body);
-		}
-
-		private ElseStatement ParseElseStatement()
-		{
-			TakeKeyword("else");
-			var body = ParseLexicalScopeOrStatement();
-
-			return new ElseStatement(body);
-		}
-
-		private ForStatement ParseForStatement()
-		{
-			TakeKeyword("for");
-			Take(TokenType.OpenPara);
-
-			SyntaxNode variable = null;
-
-			if (_current != TokenType.Semicolon)
-			{
-				variable = ParseVariableDeclaration();
-			}
-			else
-			{
-				variable = new EmptyStatement();
-			}
-			Take(TokenType.Semicolon);
-
-			Expression predicate = ParseLevel2Expression();
-			Take(TokenType.Semicolon);
-
-			Expression increment = ParseExpression();
-			Take(TokenType.ClosePara);
-
-			SyntaxNode body = ParseLexicalScopeOrStatement();
-
-			return new ForStatement(variable, predicate, increment, body);
-		}
-
-		private IfStatement ParseIfStatement()
-		{
-			TakeKeyword("if");
-			var predicate = ParsePredicate();
-			var body = ParseLexicalScopeOrStatement();
-			ElseStatement elseStatement = null;
-			if (_current == "else")
-			{
-				elseStatement = ParseElseStatement();
-			}
-
-			return new IfStatement(predicate, body, elseStatement);
-		}
-
-		private SyntaxNode ParseImportStatement()
-		{
-			StringBuilder value = new StringBuilder();
-
-			TakeKeyword("import");
-
-			while (_current == TokenType.Identifier || _current == TokenType.Dot)
-			{
-				value.Append(_current.Value);
-				AcceptToken();
-			}
-
-			if (_current == TokenType.Semicolon || _enforceSemi)
-			{
-				Take(TokenType.Semicolon);
-			}
-
-			return new ImportStatement(value.ToString());
-		}
-
-		private LambdaExpression ParseLambdaExpression(IEnumerable<VariableDeclaration> arguments)
-		{
-			Take(TokenType.FatArrow);
-
-			SyntaxNode body;
-
-			if (_current == TokenType.OpenBracket)
-			{
-				body = ParseLexicalScope();
-			}
-			else
-			{
-				body = new ReturnStatement(ParseExpression());
-			}
-
-			return new LambdaExpression(arguments, body);
-		}
-
-		private LexicalScope ParseLexicalScope()
-		{
-			Take(TokenType.OpenBracket);
-
-			List<SyntaxNode> statements = new List<SyntaxNode>();
-
-			while (_current != TokenType.CloseBracket)
-			{
-				statements.Add(ParseStatement());
-			}
-
-			Take(TokenType.CloseBracket);
-
-			return new LexicalScope(statements);
-		}
-
-		private SyntaxNode ParseLexicalScopeOrExpression()
-		{
-			if (_current == TokenType.OpenBracket)
-			{
-				return ParseLexicalScope();
-			}
-			else
-			{
-				return ParseExpression();
-			}
-		}
-
-		private SyntaxNode ParseLexicalScopeOrStatement()
-		{
-			if (_current == TokenType.OpenBracket)
-			{
-				return ParseLexicalScope();
-			}
-			else
-			{
-				return ParseStatement();
-			}
-		}
-
-		private SyntaxNode ParseMethod(Visibility visibility, string name, string type, bool isStatic)
-		{
-			if (type == "var")
-			{
-				throw UnexpectedToken("Type");
-			}
-			IEnumerable<VariableDeclaration> arguments = ParseArgumentList();
-
-			List<PreconditionStatement> preconditions = new List<PreconditionStatement>();
-
-			if (_current == "requires")
-			{
-				do
-				{
-					AcceptToken();
-					SyntaxNode precondition = ParseLexicalScopeOrExpression();
-					string message = "Failed Precondition";
-					if (_current == "error")
-					{
-						AcceptToken();
-						Take(TokenType.Colon);
-						message = Take(TokenType.StringLiteral).Value;
-					}
-
-					preconditions.Add(new PreconditionStatement(precondition, message));
-				}
-				while (_current == "and");
-			}
-
-			LexicalScope body = ParseLexicalScope();
-
-			return new MethodDeclaration(name, type, isStatic, visibility, arguments, body, preconditions);
-		}
-
-		private Expression ParsePredicate()
-		{
-			Take(TokenType.OpenPara);
-			var expression = ParseLevel2Expression();
-			Take(TokenType.ClosePara);
-			return expression;
-		}
-
-		private PropertyDeclaration ParseProperty(Visibility visibility, string name, string type)
-		{
-			Take(TokenType.OpenBracket);
-
-			bool hasGet = false;
-			bool hasSet = false;
-
-			MethodDeclaration getMethod = null;
-			MethodDeclaration setMethod = null;
-
-			while (_current != TokenType.CloseBracket)
-			{
-				if (_current == "get" && !hasGet)
-				{
-					Take(_current.Type);
-					var body = ParseLexicalScope();
-					getMethod = new MethodDeclaration($"get_{name}", type, false, visibility, new VariableDeclaration[0], body);
-					hasGet = true;
-				}
-				else if (_current == "set" && !hasSet)
-				{
-					Take(_current.Type);
-					var body = ParseLexicalScope();
-					setMethod = new MethodDeclaration($"set_{name}", type, false, visibility, new[] { new VariableDeclaration("value", type, null) }, body);
-					hasSet = true;
-				}
-				else
-				{
-					StringBuilder message = new StringBuilder();
-					if (!hasGet)
-					{
-						message.Append("get");
-					}
-					if (!hasGet && !hasSet)
-					{
-						message.Append(" or ");
-					}
-					if (!hasSet)
-					{
-						message.Append("set");
-					}
-					throw UnexpectedToken(message.ToString());
-				}
-			}
-			Take(TokenType.CloseBracket);
-			if (!hasGet)
-			{
-				throw UnexpectedToken("'get'");
-			}
-
-			return new PropertyDeclaration(name, type, visibility, getMethod, setMethod);
-		}
-
-		private RaiseStatement ParseRaiseStatement()
-		{
-			TakeKeyword("raise");
-
-			Expression expression = ParseExpression();
-
-			return new RaiseStatement(expression);
-		}
-
-		private ReturnStatement ParseReturnStatement()
-		{
-			AcceptToken();
-
-			var expression = ParseExpression();
-
-			return new ReturnStatement(expression);
-		}
-
-		private SyntaxNode ParseStatement()
-		{
-			SyntaxNode node;
-			if (_current == TokenType.Keyword)
-			{
-				switch (_current.Value)
-				{
-					case "if":
-						node = ParseIfStatement();
-						break;
-
-					case "var":
-						node = ParseVariableDeclaration();
-						break;
-
-					case "new":
-						node = ParseNewExpression();
-						break;
-
-					case "return":
-						node = ParseReturnStatement();
-						break;
-
-					case "for":
-						node = ParseForStatement();
-						break;
-
-					case "while":
-						node = ParseWhileStatement();
-						break;
-
-					case "try":
-						node = ParseTryStatement();
-						break;
-
-					case "raise":
-						node = ParseRaiseStatement();
-						break;
-
-					default:
-						node = ParseExpressionTerminal();
-						break;
-				}
-			}
-			else if (_current == TokenType.OpenBracket)
-			{
-				node = ParseLexicalScope();
-			}
-			else if (_current == TokenType.Semicolon)
-			{
-				AcceptToken();
-				return new EmptyStatement();
-			}
-			else
-			{
-				if (_next == TokenType.Identifier && _current.Catagory == TokenCatagory.Identifier)
-				{
-					node = ParseVariableDeclaration();
-				}
-				else
-				{
-					node = ParseExpression();
-				}
-			}
-			if (node == null)
-			{
-				throw UnexpectedToken("statement");
-			}
-			if ((_enforceSemi && _last != TokenType.CloseBracket) || _current == TokenType.Semicolon)
-			{
-				Take(TokenType.Semicolon);
-			}
-
-			return node;
-		}
-
-		private TryStatement ParseTryStatement()
-		{
-			TakeKeyword("try");
-
-			SyntaxNode body = ParseLexicalScopeOrStatement();
-			CatchStatement catchStatement = ParseCatchStatement();
-
-			return new TryStatement(body, catchStatement);
-		}
-
-		private void ParseTypeAndName(out string type, out string name, params string[] specialWords)
-		{
-			if (specialWords.Contains(_current.Value))
-			{
-				type = Take(TokenType.Keyword).Value;
-			}
-			else
-			{
-				type = Take(TokenType.Identifier).Value;
-			}
-
-			name = Take(TokenType.Identifier).Value;
-		}
-
-		private VariableDeclaration ParseVariableDeclaration(bool allowDefault = true)
-		{
-			string type;
-			string name;
-			SyntaxNode value = null;
-
-			ParseTypeAndName(out type, out name, "var");
-
-			if (allowDefault && _current == TokenType.Assignment)
-			{
-				AcceptToken();
-				value = ParseExpression();
-			}
-
-			return new VariableDeclaration(name, type, value);
-		}
-
-		private Visibility ParseVisibility(bool optional)
-		{
-			if (_current != TokenType.Keyword)
-			{
-				if (optional)
-				{
-					return Visibility.Private;
-				}
-				else
-				{
-					throw UnexpectedToken("'public', 'private', or 'protected'");
-				}
-			}
-			if (_current == "public")
-			{
-				AcceptToken();
-				return Visibility.Public;
-			}
-			else if (_current == "protected")
-			{
-				AcceptToken();
-				return Visibility.Protected;
-			}
-			else if (_current == "private")
-			{
-				AcceptToken();
-				return Visibility.Private;
-			}
-			else
-			{
-				if (!optional)
-				{
-					throw UnexpectedToken("'public', 'private', or 'protected'");
-				}
-			}
-			return Visibility.Private;
-		}
-
-		private WhileStatement ParseWhileStatement()
-		{
-			TakeKeyword("while");
-			Expression predicate = ParsePredicate();
-
-			SyntaxNode body = ParseLexicalScopeOrStatement();
-
-			return new WhileStatement(predicate, body);
-		}
-
-		private Token PeekToken(int ahead)
-		{
-			return _lexer.PeekToken(ahead, g => !g.IsTrivia());
-		}
-
-		private SyntaxException SyntaxError(string message)
-		{
-			return new SyntaxException($"{{_current.Start}} {{_current.Span}} {{message}}");
-		}
-
-		#region Parse Expression
-
-		private bool IsUnaryOperator()
-		{
-			switch (_current.Type)
-			{
-				case TokenType.PlusPlus:
-				case TokenType.MinusMinus:
-				case TokenType.LogicalNot:
-					return true;
-			}
-			switch (_next.Type)
-			{
-				case TokenType.PlusPlus:
-				case TokenType.MinusMinus:
-					return true;
-			}
-			return false;
-		}
-
-		private ArithmeticOperator ParseArithmeticOperator()
-		{
-			if (_current.Catagory != TokenCatagory.Arithmetic)
-			{
-				throw UnexpectedToken("Arithmetic operator");
-			}
-			var last = _last;
-			var op = _current.Type;
-			AcceptToken();
-
-			switch (op)
-			{
-				case TokenType.Addition:
-					return ArithmeticOperator.Add;
-
-				case TokenType.Divide:
-					return ArithmeticOperator.Divide;
-
-				case TokenType.Multiply:
-					return ArithmeticOperator.Multiply;
-
-				case TokenType.Subtract:
-					return ArithmeticOperator.Subtract;
-
-				case TokenType.Modulo:
-					return ArithmeticOperator.Modulo;
-
-				// Unreachable
-				default:
-					return ArithmeticOperator.Add;
-			}
-		}
-
-		private Expression ParseArrayAccess(bool inObjectRef = false)
-		{
-			string target = Take(TokenType.Identifier).Value;
-
-			Take(TokenType.OpenArrayAccessor);
-
-			Expression index = ParseExpression();
-
-			Take(TokenType.CloseArrayAccessor);
-
-			var expression = new ArrayAccessExpression(target, index);
-			if (_current == TokenType.Dot && !inObjectRef)
-			{
-				return ParseObjectReferenceExpression(expression);
-			}
-			return expression;
-		}
-
-		private Expression ParseArrayDeclaration(string identifier)
-		{
-			Take(TokenType.OpenArrayAccessor);
-
-			if (_current == TokenType.CloseArrayAccessor)
-			{
-				Take(TokenType.CloseArrayAccessor);
-				return new ArrayDeclarationExpression(identifier, null);
-			}
-			var expression = ParseExpression();
-
-			Take(TokenType.CloseArrayAccessor);
-
-			return new ArrayDeclarationExpression(identifier, expression);
-		}
-
-		private Expression ParseBasicOperation()
-		{
-			Take(TokenType.OpenPara);
-
-			// Explicit lambda declaration
-			if (_next.Catagory == TokenCatagory.Identifier)
-			{
-				List<VariableDeclaration> args = new List<VariableDeclaration>();
-				while (_current != TokenType.ClosePara)
-				{
-					string type = Take(TokenType.Identifier).Value;
-					string name = Take(TokenType.Identifier).Value;
-
-					args.Add(new VariableDeclaration(name, type, null));
-
-					if (_current != TokenType.ClosePara)
-					{
-						Take(TokenType.Comma);
-					}
-				}
-
-				Take(TokenType.ClosePara);
-
-				return ParseLambdaExpression(args);
-			}
-			else if (_current == TokenType.ClosePara && _next == TokenType.FatArrow)
-			{
-				Take(_current.Type);
-				return ParseLambdaExpression(new VariableDeclaration[0]);
-			}
-
-			var expression = ParseExpression();
-
-			// Implicit Lambda
-			if (_current == TokenType.Comma)
-			{
-				Take(TokenType.Comma);
-				if (expression.SyntaxType != SyntaxTypes.IdentifierExpression)
-				{
-					throw SyntaxError("Implicit lambda parameters must be identifiers.");
-				}
-				List<IdentifierExpression> expressions = new List<IdentifierExpression>() { (IdentifierExpression)expression };
-				while (_current != TokenType.ClosePara)
-				{
-					string name = Take(TokenType.Identifier).Value;
-
-					expressions.Add(new IdentifierExpression(name));
-
-					if (_current != TokenType.ClosePara)
-					{
-						Take(TokenType.Comma);
-					}
-				}
-
-				Take(TokenType.ClosePara);
-
-				return ParseLambdaExpression(expressions.Select(g => new VariableDeclaration(g.Identifier, "var", null)));
-			}
-			else if (_current == TokenType.Semicolon)
-			{
-				return ParseCompoundExpression(expression);
-			}
-			Take(TokenType.ClosePara);
-
-			if (_current == TokenType.FatArrow)
-			{
-				if (expression.SyntaxType != SyntaxTypes.IdentifierExpression)
-				{
-					throw SyntaxError("Implicit lambda parameters must be identifiers.");
-				}
-
-				return ParseLambdaExpression(new List<VariableDeclaration>() { new VariableDeclaration(((IdentifierExpression)expression).Identifier, "var", null) });
-			}
-			else if (_current == TokenType.Dot)
-			{
-				return ParseObjectReferenceExpression(expression);
-			}
-
-			return expression;
-		}
-
-		private BitwiseOperator ParseBitwiseOperator()
-		{
-			if (_current.Catagory != TokenCatagory.Bitwise)
-			{
-				throw UnexpectedToken("Bitwise operator");
-			}
-			var op = _current.Type;
-			AcceptToken();
-
-			switch (op)
-			{
-				case TokenType.BitwiseAnd:
-					return BitwiseOperator.And;
-
-				case TokenType.BitwiseOr:
-					return BitwiseOperator.Or;
-
-				case TokenType.BitwiseXOR:
-					return BitwiseOperator.Xor;
-
-				default: return BitwiseOperator.And;
-			}
-		}
-
-		private Expression ParseCompoundExpression(Expression first)
-		{
-			List<Expression> expressions = new List<Expression>();
-			expressions.Add(first);
-
-			while (_current != TokenType.ClosePara)
-			{
-				Take(TokenType.Semicolon);
-
-				var expression = ParseExpression();
-
-				expressions.Add(expression);
-			}
-
-			Take(TokenType.ClosePara);
-
-			return new CompoundExpression(expressions);
-		}
-
-		private Expression ParseExpression()
-		{
-			Expression left = ParseLevel1Expression();
-
-			return left;
-		}
-
-		private Expression ParseExpressionTerminal()
-		{
-			if (_current == TokenType.Identifier)
-			{
-				if (_next == TokenType.OpenPara)
-				{
-					return ParseMethodCall();
-				}
-				else if (_next == TokenType.OpenArrayAccessor)
-				{
-					return ParseArrayAccess();
-				}
-				else if (_next == TokenType.FatArrow)
-				{
-					return ParseLambdaExpression(new List<VariableDeclaration>() { new VariableDeclaration(Take(TokenType.Identifier).Value, "var", null) });
-				}
-				else if (_next == TokenType.Dot)
-				{
-					return ParseObjectReferenceExpression(new IdentifierExpression(Take(TokenType.Identifier).Value));
-				}
-				else
-				{
-					return new IdentifierExpression(Take(TokenType.Identifier).Value);
-				}
-			}
-			else if (_current == TokenType.Keyword)
-			{
-				if (_current == "true")
-				{
-					return new ConstantExpression(Take(_current.Type).Value, ConstantType.Boolean);
-				}
-				else if (_current == "false")
-				{
-					return new ConstantExpression(Take(_current.Type).Value, ConstantType.Boolean);
-				}
-				else if (_current == "null")
-				{
-					return new ConstantExpression(Take(_current.Type).Value, ConstantType.Null);
-				}
-				else if (_current == "new")
-				{
-					return ParseNewExpression();
-				}
-			}
-			else if (_current.Catagory == TokenCatagory.Arithmetic)
-			{
-				if (_current == TokenType.Addition)
-				{
-					AcceptToken();
-					return ParseExpression();
-				}
-				else if (_current == TokenType.Subtract)
-				{
-					Take(TokenType.Subtract);
-					Expression parameter = ParseLevel8Expression();
-					return new UnaryExpression(parameter, UnaryOperator.Negation, true);
-				}
-			}
-			else if (_current.Catagory == TokenCatagory.Literal)
-			{
-				if (_current == TokenType.StringLiteral)
-				{
-					return new ConstantExpression(Take(_current.Type).Value, ConstantType.String);
-				}
-				else
-				{
-					return ParseNumberLiteral();
-				}
-			}
-			throw UnexpectedToken("expression terminal");
-		}
-
-		private Expression ParseLevel1Expression()
-		{
-			Expression left = ParseLevel2Expression();
-			if (_current.Catagory == TokenCatagory.Assignment)
-			{
-				var op = ParseAssignmentType();
-				Expression right = ParseLevel1Expression();
-
-				return new AssignmentExpression(left, right, op);
-			}
-			return left;
-		}
-
-		private Expression ParseLevel2Expression()
-		{
-			Expression left = ParseLevel3Expression();
-
-			if (_current == TokenType.LogicalAnd || _current == TokenType.LogicalOr)
-			{
-				var op = ParseLogicalOperator();
-				Expression right = ParseLevel2Expression();
-
-				return new LogicalExpression(left, right, op);
-			}
-
-			return left;
-		}
-
-		private Expression ParseLevel3Expression()
-		{
-			Expression left = ParseLevel4Expression();
-
-			if (_current.Catagory == TokenCatagory.Logical && _current != "!")
-			{
-				var op = ParseLogicalOperator();
-				Expression right = ParseLevel3Expression();
-
-				return new LogicalExpression(left, right, op);
-			}
-
-			return left;
-		}
-
-		private Expression ParseLevel4Expression()
-		{
-			Expression left = ParseLevel5Expression();
-
-			// 10 - 3 + 2 should be parsed as ((10 - 3) + 2)
-			while (_current == TokenType.Addition || _current == TokenType.Subtract)
-			{
-				var op = ParseArithmeticOperator();
-				left = new ArithmeticExpression(left, ParseLevel5Expression(), op);
-			}
-			return left;
-		}
-
-		private Expression ParseLevel5Expression()
-		{
-			Expression left = ParseLevel6Expression();
-
-			while (_current == TokenType.Multiply || _current == TokenType.Divide)
-			{
-				var op = ParseArithmeticOperator();
-				left = new ArithmeticExpression(left, ParseLevel6Expression(), op);
-			}
-
-			return left;
-		}
-
-		private Expression ParseLevel6Expression()
-		{
-			Expression left = ParseLevel7Expression();
-			if (_current == TokenType.Modulo)
-			{
-				var op = ParseArithmeticOperator();
-				Expression right = ParseLevel6Expression();
-
-				return new ArithmeticExpression(left, right, op);
-			}
-			return left;
-		}
-
-		private Expression ParseLevel7Expression()
-		{
-			Expression left = ParseLevel8Expression();
-
-			if (_current.Catagory == TokenCatagory.Bitwise)
-			{
-				var op = ParseBitwiseOperator();
-				Expression right = ParseLevel7Expression();
-
-				return new BitwiseExpression(left, right, op);
-			}
-
-			return left;
-		}
-
-		private Expression ParseLevel8Expression()
-		{
-			if (_current == TokenType.OpenPara)
-			{
-				return ParseBasicOperation();
-			}
-			else if (IsUnaryOperator() || _next == TokenType.PlusPlus || _next == TokenType.PlusPlus)
-			{
-				return ParseUnaryExpression();
-			}
-			else
-			{
-				return ParseExpressionTerminal();
-			}
-		}
-
-		private LogicOperation ParseLogicalOperator()
-		{
-			if (_current.Catagory != TokenCatagory.Logical)
-			{
-				throw UnexpectedToken("logical operator");
-			}
-			var op = _current.Type;
-			AcceptToken();
-
-			switch (op)
-			{
-				case TokenType.LogicalAnd:
-					return LogicOperation.And;
-
-				case TokenType.LogicalEquals:
-					return LogicOperation.Equals;
-
-				case TokenType.LogicalGreater:
-					return LogicOperation.GreaterThan;
-
-				case TokenType.LogicalGreaterOrEqual:
-					return LogicOperation.GreaterThanOrEqual;
-
-				case TokenType.LogicalLess:
-					return LogicOperation.LessThan;
-
-				case TokenType.LogicalLessOrEqual:
-					return LogicOperation.LessThanOrEqual;
-
-				case TokenType.LogicalNot:
-					return LogicOperation.Not;
-
-				case TokenType.LogicalNotEquals:
-					return LogicOperation.NotEquals;
-
-				case TokenType.LogicalOr:
-					return LogicOperation.Or;
-
-				default: return LogicOperation.Not;
-			}
-		}
-
-		private Expression ParseMethodCall(bool inObjectRef = false)
-		{
-			string identifier = Take(TokenType.Identifier).Value;
-			Take(TokenType.OpenPara);
-
-			List<Expression> arguments = new List<Expression>();
-
-			while (_current != TokenType.ClosePara)
-			{
-				if (_current == TokenType.Comma)
-				{
-					Take(TokenType.Comma);
-				}
-
-				var expression = ParseExpression();
-
-				arguments.Add(expression);
-			}
-
-			Take(TokenType.ClosePara);
-
-			var call = new MethodCallExpression(identifier, arguments);
-			if (_current == TokenType.Dot && !inObjectRef)
-			{
-				return ParseObjectReferenceExpression(call);
-			}
-
-			return call;
-		}
-
-		private Expression ParseNewExpression()
-		{
-			TakeKeyword("new");
-			string identifier = Take(TokenType.Identifier).Value;
-			if (_current == TokenType.OpenArrayAccessor)
-			{
-				return ParseArrayDeclaration(identifier);
-			}
-			Take(TokenType.OpenPara);
-
-			List<Expression> arguments = new List<Expression>();
-
-			while (_current != TokenType.ClosePara)
-			{
-				if (_current == TokenType.Comma && arguments.Count > 0)
-				{
-					Take(TokenType.Comma);
-				}
-
-				var expression = ParseExpression();
-
-				arguments.Add(expression);
-			}
-
-			Take(TokenType.ClosePara);
-
-			var call = new NewExpression(identifier, arguments);
-			if (_current == TokenType.Dot)
-			{
-				return ParseObjectReferenceExpression(call);
-			}
-
-			return call;
-		}
-
-		private ConstantExpression ParseNumberLiteral()
-		{
-			switch (_current.Type)
-			{
-				case TokenType.Number:
-					return new ConstantExpression(Take(TokenType.Number).Value, ConstantType.Int);
-
-				case TokenType.HexNumber:
-					{
-						string value = Take(TokenType.HexNumber).Value.Substring(2);
-						long number = Convert.ToInt64(value, 16);
-						return new ConstantExpression(number.ToString(), ConstantType.Int);
-					}
-				case TokenType.OctalNumber:
-					{
-						string value = Take(TokenType.OctalNumber).Value.Substring(2);
-						long number = Convert.ToInt64(value, 8);
-						return new ConstantExpression(number.ToString(), ConstantType.Int);
-					}
-				case TokenType.FloatingPointNumber:
-					return new ConstantExpression(Take(TokenType.FloatingPointNumber).Value, ConstantType.Float);
-
-				default:
-					throw UnexpectedToken("number constant");
-			}
-		}
-
-		private Expression ParseObjectReferenceExpression(Expression root)
-		{
-			List<Expression> references = new List<Expression>();
-			while (_current == TokenType.Dot)
-			{
-				Take(TokenType.Dot);
-
-				Expression expression;
-
-				if (_next == TokenType.OpenPara)
-				{
-					expression = ParseMethodCall(true);
-				}
-				else if (_next == TokenType.OpenArrayAccessor)
-				{
-					expression = ParseArrayAccess(true);
-				}
-				else
-				{
-					expression = new IdentifierExpression(Take(TokenType.Identifier).Value);
-				}
-
-				references.Add(expression);
-			}
-
-			return new ObjectReferenceExpression(root, references);
-		}
-
-		private Expression ParseUnaryExpression()
-		{
-			Expression expression;
-			if (_current == "!")
-			{
-				var op = ParseUnaryOperator();
-
-				if (_current == TokenType.OpenPara)
-				{
-					expression = ParseBasicOperation();
-				}
-				else
-				{
-					expression = ParseExpression();
-				}
-				return new UnaryExpression(expression, op, true);
-			}
-			else if (_current == "++" || _current == "--")
-			{
-				var op = ParseUnaryOperator();
-				string identifier = Take(TokenType.Identifier).Value;
-				return new UnaryExpression(new IdentifierExpression(identifier), op, true);
-			}
-			else
-			{
-				string identifier = Take(TokenType.Identifier).Value;
-				var op = ParseUnaryOperator();
-
-				return new UnaryExpression(new IdentifierExpression(identifier), op, false);
-			}
-		}
-
-		private UnaryOperator ParseUnaryOperator()
-		{
-			var op = _current.Type;
-			AcceptToken();
-			switch (op)
-			{
-				case TokenType.PlusPlus:
-					return UnaryOperator.Increment;
-
-				case TokenType.MinusMinus:
-					return UnaryOperator.Decrement;
-
-				case TokenType.LogicalNot:
-					return UnaryOperator.LogicalNot;
-
-				default:
-					return UnaryOperator.None;
-			}
-		}
-
-		#endregion Parse Expression
-
-		private Token Take(TokenType type)
-		{
-			if (_current != type)
-			{
-				throw UnexpectedToken(type.ToString().ToLower());
-			}
-			AcceptToken();
-			return _last;
-		}
-
-		private Token Take(TokenType type, string value)
-		{
-			if (_current != type || _current != value)
-			{
-				throw UnexpectedToken($"'{{value}}'");
-			}
-			AcceptToken();
-			return _last;
-		}
-
-		private Token TakeKeyword(string keyword)
-		{
-			return Take(TokenType.Keyword, keyword);
-		}
-
-		private SyntaxException UnexpectedToken(string expected)
-		{
-			string message = $"{_current.Start} {_current.Span} Unexpected Token '{_current.Value}'.  Expected {expected}";
-			return new SyntaxException(message);
-		}
-
-		private SyntaxException UnexpectedToken(Token value, string expected)
-		{
-			string message = $"{value.Start} {value.Span} Unexpected Token '{value.Value}'.  Expected {expected}";
-			return new SyntaxException(message);
-		}
-	}
+    public class PineTreeParser
+    {
+        private Token _current;
+        private bool _enforceSemi;
+        private Token _last;
+        private PineTreeLexer _lexer;
+
+        private Token _next;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PineTreeParser"/> class.
+        /// </summary>
+        public PineTreeParser()
+            : this(new PineTreeLexer())
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PineTreeParser"/> class with a given <see cref="PineTreeLexer"/>.
+        /// </summary>
+        /// <param name="lexer"></param>
+        public PineTreeParser(PineTreeLexer lexer)
+        {
+            _lexer = lexer;
+            _enforceSemi = true;
+        }
+
+        /// <summary>
+        /// Parses all of the given source code and returns a <see cref="SourceDocument"/> containing the created Abstract Syntax Tree.
+        /// Root members of the file must be classes or methods and semicolons are enforced.
+        /// </summary>
+        /// <seealso cref="Parse(string)"/>
+        /// <returns></returns>
+        public SourceDocument Parse()
+        {
+            InitializeTokens(true);
+            List<SyntaxNode> nodes = new List<SyntaxNode>();
+
+            try
+            {
+                while (_current != TokenType.EOF)
+                {
+                    nodes.Add(ParseClassOrMethod());
+                }
+            }
+            catch (SyntaxException)
+            {
+                _lexer.Clear();
+                throw;
+            }
+
+            return new SourceDocument(nodes);
+        }
+
+        /// <summary>
+        /// Parses all of the given source code and returns a <see cref="SourceDocument"/> containing the created Abstract Syntax Tree.
+        /// Root members of the file must be classes or methods and semicolons are enforced.
+        /// </summary>
+        /// <param name="source">The file to parse.</param>
+        /// <seealso cref="Parse"/>
+        /// <returns></returns>
+        public SourceDocument Parse(string source)
+        {
+            _lexer.Feed(source);
+            try
+            {
+                return Parse();
+            }
+            catch (SyntaxException)
+            {
+                _lexer.Clear();
+                throw;
+            }
+        }
+
+        /// <summary>
+        /// Parses an <see cref="Expression"/> and returns an AST object containing the contents.
+        /// Semicolons are not enforced.
+        /// </summary>
+        /// <param name="source">The expression to parse.</param>
+        /// <returns></returns>
+        public Expression ParseExpression(string source)
+        {
+            _lexer.Feed(source);
+            InitializeTokens(false);
+            try
+            {
+                return ParseExpression();
+            }
+            catch (SyntaxException)
+            {
+                _lexer.Clear();
+                throw;
+            }
+        }
+
+        /// <summary>
+        /// Parses all of the given source code and returns a <see cref="SourceDocument"/> containing the created Abstract Syntax Tree.
+        /// Root members of the file may be classes, methods, or statements.  Semicolons are not enforced.
+        /// </summary>
+        /// <param name="source">The source code to parse.</param>
+        /// <returns></returns>
+        public SourceDocument ParseScript(string source)
+        {
+            _lexer.Feed(source);
+            InitializeTokens(false);
+            List<SyntaxNode> nodes = new List<SyntaxNode>();
+            try
+            {
+                while (_current != TokenType.EOF)
+                {
+                    if (_current == "import")
+                    {
+                        nodes.Add(ParseImportStatement());
+                    }
+                    else if (_current == "public" || _current == "private" || _current == "protected" || _current == "class")
+                    {
+                        nodes.Add(ParseClassOrMethod());
+                    }
+                    else
+                    {
+                        nodes.Add(ParseStatement());
+                    }
+                }
+            }
+            catch (SyntaxException)
+            {
+                _lexer.Clear();
+                throw;
+            }
+
+            return new SourceDocument(nodes);
+        }
+
+        /// <summary>
+        /// Parses a single statement and returns the created Abstract Syntax Tree.
+        /// Semicolons are not enforced.
+        /// </summary>
+        /// <param name="source">The source code to parse.</param>
+        /// <returns></returns>
+        public SyntaxNode ParseStatement(string source)
+        {
+            _lexer.Feed(source);
+            InitializeTokens(false);
+
+            try
+            {
+                return ParseStatement();
+            }
+            catch (SyntaxException)
+            {
+                _lexer.Clear();
+                throw;
+            }
+        }
+
+        private void AcceptToken()
+        {
+            _last = _current;
+            _current = _next;
+            _next = _lexer.LexToken(g => !g.IsTrivia());
+        }
+
+        private void InitializeTokens(bool enforceSemi)
+        {
+            _enforceSemi = enforceSemi;
+            AcceptToken();
+            AcceptToken();
+            _last = null;
+        }
+
+        private IEnumerable<VariableDeclaration> ParseArgumentList()
+        {
+            Take(TokenType.OpenPara);
+
+            List<VariableDeclaration> arguments = new List<VariableDeclaration>();
+
+            while (_current != TokenType.ClosePara)
+            {
+                VariableDeclaration variable = ParseVariableDeclaration();
+                if (variable != null)
+                {
+                    arguments.Add(variable);
+                }
+
+                if (_current == TokenType.Comma && _current != TokenType.ClosePara)
+                {
+                    Take(TokenType.Comma);
+                }
+            }
+
+            Take(TokenType.ClosePara);
+
+            return arguments;
+        }
+
+        private AssignmentType ParseAssignmentType()
+        {
+            if (_current.Catagory != TokenCatagory.Assignment)
+            {
+                throw UnexpectedToken("assignment operator");
+            }
+
+            var op = _current.Type;
+            AcceptToken();
+
+            switch (op)
+            {
+                case TokenType.Assignment:
+                    return AssignmentType.Regular;
+
+                case TokenType.AssignmentAdd:
+                    return AssignmentType.AddTo;
+
+                case TokenType.AssignmentSubtract:
+                    return AssignmentType.SubractFrom;
+
+                case TokenType.AssignmentMultiply:
+                    return AssignmentType.MultiplyBy;
+
+                case TokenType.AssignmentDivide:
+                    return AssignmentType.DivideBy;
+
+                default:
+                    return AssignmentType.Regular;
+            }
+        }
+
+        private CatchStatement ParseCatchStatement()
+        {
+            TakeKeyword("catch");
+            VariableDeclaration variable = null;
+            if (_current == TokenType.OpenPara)
+            {
+                Take(TokenType.OpenPara);
+                variable = ParseVariableDeclaration(false);
+                Take(TokenType.ClosePara);
+            }
+            SyntaxNode body = ParseLexicalScopeOrStatement();
+            return new CatchStatement(body, variable);
+        }
+
+        private ClassDeclaration ParseClass(Visibility visibility)
+        {
+            TakeKeyword("class");
+            var name = Take(TokenType.Identifier).Value;
+            string supertype = "object";
+            if (_current == "extends")
+            {
+                AcceptToken();
+                supertype = Take(TokenType.Identifier).Value;
+            }
+
+            Take(TokenType.OpenBracket);
+
+            List<FieldDeclaration> fields = new List<FieldDeclaration>();
+            List<MethodDeclaration> methods = new List<MethodDeclaration>();
+            List<PropertyDeclaration> properties = new List<PropertyDeclaration>();
+            List<ConstructorDeclaration> constructors = new List<ConstructorDeclaration>();
+
+            while (_current != TokenType.CloseBracket)
+            {
+                var node = ParseClassMember(name);
+
+                switch (node.SyntaxType)
+                {
+                    case SyntaxTypes.FieldDeclaration:
+                        fields.Add((FieldDeclaration)node);
+                        break;
+
+                    case SyntaxTypes.PropertyDeclaration:
+                        properties.Add((PropertyDeclaration)node);
+                        break;
+
+                    case SyntaxTypes.MethodDeclaration:
+                        methods.Add((MethodDeclaration)node);
+                        break;
+
+                    case SyntaxTypes.ConstructorDeclaration:
+                        constructors.Add((ConstructorDeclaration)node);
+                        break;
+                }
+            }
+            Take(TokenType.CloseBracket);
+
+            return new ClassDeclaration(name, supertype, fields, properties, methods, constructors);
+        }
+
+        private SyntaxNode ParseClassMember(string type)
+        {
+            var visibility = ParseVisibility(true);
+
+            if (_next == TokenType.OpenPara && _current == type)
+            {
+                return ParseConstructor(visibility);
+            }
+            else
+            {
+                bool isStatic = false;
+                if (_current == "static")
+                {
+                    isStatic = true;
+                    AcceptToken();
+                }
+                string name;
+                string returnType;
+
+                ParseTypeAndName(out returnType, out name, "void");
+
+                if (_current == TokenType.OpenBracket)
+                {
+                    if (returnType == "void")
+                    {
+                        throw UnexpectedToken("type");
+                    }
+                    return ParseProperty(visibility, name, returnType);
+                }
+                else if (_current == TokenType.OpenPara)
+                {
+                    return ParseMethod(visibility, name, returnType, isStatic);
+                }
+                else if (_current == TokenType.Assignment || _current == TokenType.Semicolon)
+                {
+                    if (_current == TokenType.Semicolon)
+                    {
+                        Take(TokenType.Semicolon);
+                        return new FieldDeclaration(name, type, null);
+                    }
+
+                    var expression = ParseExpression();
+                    if (_current == TokenType.Semicolon || _enforceSemi)
+                    {
+                        Take(TokenType.Semicolon);
+                    }
+                    return new FieldDeclaration(name, type, expression);
+                }
+            }
+            return null;
+        }
+
+        private SyntaxNode ParseClassOrMethod()
+        {
+            Visibility visibility = ParseVisibility(true);
+
+            SyntaxNode node;
+
+            if (_current == "class")
+            {
+                node = ParseClass(visibility);
+            }
+            else
+            {
+                string type, name;
+                ParseTypeAndName(out type, out name, "void");
+
+                node = ParseMethod(visibility, name, type, false);
+            }
+
+            return node;
+        }
+
+        private ConstructorDeclaration ParseConstructor(Visibility visibility)
+        {
+            string name = Take(TokenType.Identifier).Value;
+            var args = ParseArgumentList();
+            var body = ParseLexicalScope();
+
+            return new ConstructorDeclaration(name, visibility, args, body);
+        }
+
+        private ElseStatement ParseElseStatement()
+        {
+            TakeKeyword("else");
+            var body = ParseLexicalScopeOrStatement();
+
+            return new ElseStatement(body);
+        }
+
+        private ForStatement ParseForStatement()
+        {
+            TakeKeyword("for");
+            Take(TokenType.OpenPara);
+
+            SyntaxNode variable = null;
+
+            if (_current != TokenType.Semicolon)
+            {
+                variable = ParseVariableDeclaration();
+            }
+            else
+            {
+                variable = new EmptyStatement();
+            }
+            Take(TokenType.Semicolon);
+
+            Expression predicate = ParseLevel2Expression();
+            Take(TokenType.Semicolon);
+
+            Expression increment = ParseExpression();
+            Take(TokenType.ClosePara);
+
+            SyntaxNode body = ParseLexicalScopeOrStatement();
+
+            return new ForStatement(variable, predicate, increment, body);
+        }
+
+        private IfStatement ParseIfStatement()
+        {
+            TakeKeyword("if");
+            var predicate = ParsePredicate();
+            var body = ParseLexicalScopeOrStatement();
+            ElseStatement elseStatement = null;
+            if (_current == "else")
+            {
+                elseStatement = ParseElseStatement();
+            }
+
+            return new IfStatement(predicate, body, elseStatement);
+        }
+
+        private SyntaxNode ParseImportStatement()
+        {
+            StringBuilder value = new StringBuilder();
+
+            TakeKeyword("import");
+
+            while (_current == TokenType.Identifier || _current == TokenType.Dot)
+            {
+                value.Append(_current.Value);
+                AcceptToken();
+            }
+
+            if (_current == TokenType.Semicolon || _enforceSemi)
+            {
+                Take(TokenType.Semicolon);
+            }
+
+            return new ImportStatement(value.ToString());
+        }
+
+        private LambdaExpression ParseLambdaExpression(IEnumerable<VariableDeclaration> arguments)
+        {
+            Take(TokenType.FatArrow);
+
+            SyntaxNode body;
+
+            if (_current == TokenType.OpenBracket)
+            {
+                body = ParseLexicalScope();
+            }
+            else
+            {
+                body = new ReturnStatement(ParseExpression());
+            }
+
+            return new LambdaExpression(arguments, body);
+        }
+
+        private LexicalScope ParseLexicalScope()
+        {
+            Take(TokenType.OpenBracket);
+
+            List<SyntaxNode> statements = new List<SyntaxNode>();
+
+            while (_current != TokenType.CloseBracket)
+            {
+                statements.Add(ParseStatement());
+            }
+
+            Take(TokenType.CloseBracket);
+
+            return new LexicalScope(statements);
+        }
+
+        private SyntaxNode ParseLexicalScopeOrExpression()
+        {
+            if (_current == TokenType.OpenBracket)
+            {
+                return ParseLexicalScope();
+            }
+            else
+            {
+                return ParseExpression();
+            }
+        }
+
+        private SyntaxNode ParseLexicalScopeOrStatement()
+        {
+            if (_current == TokenType.OpenBracket)
+            {
+                return ParseLexicalScope();
+            }
+            else
+            {
+                return ParseStatement();
+            }
+        }
+
+        private SyntaxNode ParseMethod(Visibility visibility, string name, string type, bool isStatic)
+        {
+            if (type == "var")
+            {
+                throw UnexpectedToken("Type");
+            }
+            IEnumerable<VariableDeclaration> arguments = ParseArgumentList();
+
+            List<PreconditionStatement> preconditions = new List<PreconditionStatement>();
+
+            if (_current == "requires")
+            {
+                do
+                {
+                    AcceptToken();
+                    SyntaxNode precondition = ParseLexicalScopeOrExpression();
+                    string message = "Failed Precondition";
+                    if (_current == "error")
+                    {
+                        AcceptToken();
+                        Take(TokenType.Colon);
+                        message = Take(TokenType.StringLiteral).Value;
+                    }
+
+                    preconditions.Add(new PreconditionStatement(precondition, message));
+                }
+                while (_current == "and");
+            }
+
+            LexicalScope body = ParseLexicalScope();
+
+            return new MethodDeclaration(name, type, isStatic, visibility, arguments, body, preconditions);
+        }
+
+        private Expression ParsePredicate()
+        {
+            Take(TokenType.OpenPara);
+            var expression = ParseLevel2Expression();
+            Take(TokenType.ClosePara);
+            return expression;
+        }
+
+        private PropertyDeclaration ParseProperty(Visibility visibility, string name, string type)
+        {
+            Take(TokenType.OpenBracket);
+
+            bool hasGet = false;
+            bool hasSet = false;
+
+            MethodDeclaration getMethod = null;
+            MethodDeclaration setMethod = null;
+
+            while (_current != TokenType.CloseBracket)
+            {
+                if (_current == "get" && !hasGet)
+                {
+                    Take(_current.Type);
+                    var body = ParseLexicalScope();
+                    getMethod = new MethodDeclaration($"get_{name}", type, false, visibility, new VariableDeclaration[0], body);
+                    hasGet = true;
+                }
+                else if (_current == "set" && !hasSet)
+                {
+                    Take(_current.Type);
+                    var body = ParseLexicalScope();
+                    setMethod = new MethodDeclaration($"set_{name}", type, false, visibility, new[] { new VariableDeclaration("value", type, null) }, body);
+                    hasSet = true;
+                }
+                else
+                {
+                    StringBuilder message = new StringBuilder();
+                    if (!hasGet)
+                    {
+                        message.Append("get");
+                    }
+                    if (!hasGet && !hasSet)
+                    {
+                        message.Append(" or ");
+                    }
+                    if (!hasSet)
+                    {
+                        message.Append("set");
+                    }
+                    throw UnexpectedToken(message.ToString());
+                }
+            }
+            Take(TokenType.CloseBracket);
+            if (!hasGet)
+            {
+                throw UnexpectedToken("'get'");
+            }
+
+            return new PropertyDeclaration(name, type, visibility, getMethod, setMethod);
+        }
+
+        private RaiseStatement ParseRaiseStatement()
+        {
+            TakeKeyword("raise");
+
+            Expression expression = ParseExpression();
+
+            return new RaiseStatement(expression);
+        }
+
+        private ReturnStatement ParseReturnStatement()
+        {
+            AcceptToken();
+
+            var expression = ParseExpression();
+
+            return new ReturnStatement(expression);
+        }
+
+        private SyntaxNode ParseStatement()
+        {
+            SyntaxNode node;
+            if (_current == TokenType.Keyword)
+            {
+                switch (_current.Value)
+                {
+                    case "if":
+                        node = ParseIfStatement();
+                        break;
+
+                    case "var":
+                        node = ParseVariableDeclaration();
+                        break;
+
+                    case "new":
+                        node = ParseNewExpression();
+                        break;
+
+                    case "return":
+                        node = ParseReturnStatement();
+                        break;
+
+                    case "for":
+                        node = ParseForStatement();
+                        break;
+
+                    case "while":
+                        node = ParseWhileStatement();
+                        break;
+
+                    case "try":
+                        node = ParseTryStatement();
+                        break;
+
+                    case "raise":
+                        node = ParseRaiseStatement();
+                        break;
+
+                    default:
+                        node = ParseExpressionTerminal();
+                        break;
+                }
+            }
+            else if (_current == TokenType.OpenBracket)
+            {
+                node = ParseLexicalScope();
+            }
+            else if (_current == TokenType.Semicolon)
+            {
+                AcceptToken();
+                return new EmptyStatement();
+            }
+            else
+            {
+                if (_next == TokenType.Identifier && _current.Catagory == TokenCatagory.Identifier)
+                {
+                    node = ParseVariableDeclaration();
+                }
+                else
+                {
+                    node = ParseExpression();
+                }
+            }
+            if (node == null)
+            {
+                throw UnexpectedToken("statement");
+            }
+            if ((_enforceSemi && _last != TokenType.CloseBracket) || _current == TokenType.Semicolon)
+            {
+                Take(TokenType.Semicolon);
+            }
+
+            return node;
+        }
+
+        private TryStatement ParseTryStatement()
+        {
+            TakeKeyword("try");
+
+            SyntaxNode body = ParseLexicalScopeOrStatement();
+            CatchStatement catchStatement = ParseCatchStatement();
+
+            return new TryStatement(body, catchStatement);
+        }
+
+        private void ParseTypeAndName(out string type, out string name, params string[] specialWords)
+        {
+            if (specialWords.Contains(_current.Value))
+            {
+                type = Take(TokenType.Keyword).Value;
+            }
+            else
+            {
+                type = Take(TokenType.Identifier).Value;
+            }
+
+            name = Take(TokenType.Identifier).Value;
+        }
+
+        private VariableDeclaration ParseVariableDeclaration(bool allowDefault = true)
+        {
+            string type;
+            string name;
+            SyntaxNode value = null;
+
+            ParseTypeAndName(out type, out name, "var");
+
+            if (allowDefault && _current == TokenType.Assignment)
+            {
+                AcceptToken();
+                value = ParseExpression();
+            }
+
+            return new VariableDeclaration(name, type, value);
+        }
+
+        private Visibility ParseVisibility(bool optional)
+        {
+            if (_current != TokenType.Keyword)
+            {
+                if (optional)
+                {
+                    return Visibility.Private;
+                }
+                else
+                {
+                    throw UnexpectedToken("'public', 'private', or 'protected'");
+                }
+            }
+            if (_current == "public")
+            {
+                AcceptToken();
+                return Visibility.Public;
+            }
+            else if (_current == "protected")
+            {
+                AcceptToken();
+                return Visibility.Protected;
+            }
+            else if (_current == "private")
+            {
+                AcceptToken();
+                return Visibility.Private;
+            }
+            else
+            {
+                if (!optional)
+                {
+                    throw UnexpectedToken("'public', 'private', or 'protected'");
+                }
+            }
+            return Visibility.Private;
+        }
+
+        private WhileStatement ParseWhileStatement()
+        {
+            TakeKeyword("while");
+            Expression predicate = ParsePredicate();
+
+            SyntaxNode body = ParseLexicalScopeOrStatement();
+
+            return new WhileStatement(predicate, body);
+        }
+
+        private Token PeekToken(int ahead)
+        {
+            return _lexer.PeekToken(ahead, g => !g.IsTrivia());
+        }
+
+        private SyntaxException SyntaxError(string message)
+        {
+            return new SyntaxException($"{{_current.Start}} {{_current.Span}} {{message}}");
+        }
+
+        #region Parse Expression
+
+        private bool IsUnaryOperator()
+        {
+            switch (_current.Type)
+            {
+                case TokenType.PlusPlus:
+                case TokenType.MinusMinus:
+                case TokenType.LogicalNot:
+                    return true;
+            }
+            switch (_next.Type)
+            {
+                case TokenType.PlusPlus:
+                case TokenType.MinusMinus:
+                    return true;
+            }
+            return false;
+        }
+
+        private ArithmeticOperator ParseArithmeticOperator()
+        {
+            if (_current.Catagory != TokenCatagory.Arithmetic)
+            {
+                throw UnexpectedToken("Arithmetic operator");
+            }
+            var last = _last;
+            var op = _current.Type;
+            AcceptToken();
+
+            switch (op)
+            {
+                case TokenType.Addition:
+                    return ArithmeticOperator.Add;
+
+                case TokenType.Divide:
+                    return ArithmeticOperator.Divide;
+
+                case TokenType.Multiply:
+                    return ArithmeticOperator.Multiply;
+
+                case TokenType.Subtract:
+                    return ArithmeticOperator.Subtract;
+
+                case TokenType.Modulo:
+                    return ArithmeticOperator.Modulo;
+
+                // Unreachable
+                default:
+                    return ArithmeticOperator.Add;
+            }
+        }
+
+        private Expression ParseArrayAccess(bool inObjectRef = false)
+        {
+            string target = Take(TokenType.Identifier).Value;
+
+            Take(TokenType.OpenArrayAccessor);
+
+            Expression index = ParseExpression();
+
+            Take(TokenType.CloseArrayAccessor);
+
+            var expression = new ArrayAccessExpression(target, index);
+            if (_current == TokenType.Dot && !inObjectRef)
+            {
+                return ParseObjectReferenceExpression(expression);
+            }
+            return expression;
+        }
+
+        private Expression ParseArrayDeclaration(string identifier)
+        {
+            Take(TokenType.OpenArrayAccessor);
+
+            if (_current == TokenType.CloseArrayAccessor)
+            {
+                Take(TokenType.CloseArrayAccessor);
+                return new ArrayDeclarationExpression(identifier, null);
+            }
+            var expression = ParseExpression();
+
+            Take(TokenType.CloseArrayAccessor);
+
+            return new ArrayDeclarationExpression(identifier, expression);
+        }
+
+        private Expression ParseBasicOperation()
+        {
+            Take(TokenType.OpenPara);
+
+            // Explicit lambda declaration
+            if (_next.Catagory == TokenCatagory.Identifier)
+            {
+                List<VariableDeclaration> args = new List<VariableDeclaration>();
+                while (_current != TokenType.ClosePara)
+                {
+                    string type = Take(TokenType.Identifier).Value;
+                    string name = Take(TokenType.Identifier).Value;
+
+                    args.Add(new VariableDeclaration(name, type, null));
+
+                    if (_current != TokenType.ClosePara)
+                    {
+                        Take(TokenType.Comma);
+                    }
+                }
+
+                Take(TokenType.ClosePara);
+
+                return ParseLambdaExpression(args);
+            }
+            else if (_current == TokenType.ClosePara && _next == TokenType.FatArrow)
+            {
+                Take(_current.Type);
+                return ParseLambdaExpression(new VariableDeclaration[0]);
+            }
+
+            var expression = ParseExpression();
+
+            // Implicit Lambda
+            if (_current == TokenType.Comma)
+            {
+                Take(TokenType.Comma);
+                if (expression.SyntaxType != SyntaxTypes.IdentifierExpression)
+                {
+                    throw SyntaxError("Implicit lambda parameters must be identifiers.");
+                }
+                List<IdentifierExpression> expressions = new List<IdentifierExpression>() { (IdentifierExpression)expression };
+                while (_current != TokenType.ClosePara)
+                {
+                    string name = Take(TokenType.Identifier).Value;
+
+                    expressions.Add(new IdentifierExpression(name));
+
+                    if (_current != TokenType.ClosePara)
+                    {
+                        Take(TokenType.Comma);
+                    }
+                }
+
+                Take(TokenType.ClosePara);
+
+                return ParseLambdaExpression(expressions.Select(g => new VariableDeclaration(g.Identifier, "var", null)));
+            }
+            else if (_current == TokenType.Semicolon)
+            {
+                return ParseCompoundExpression(expression);
+            }
+            Take(TokenType.ClosePara);
+
+            if (_current == TokenType.FatArrow)
+            {
+                if (expression.SyntaxType != SyntaxTypes.IdentifierExpression)
+                {
+                    throw SyntaxError("Implicit lambda parameters must be identifiers.");
+                }
+
+                return ParseLambdaExpression(new List<VariableDeclaration>() { new VariableDeclaration(((IdentifierExpression)expression).Identifier, "var", null) });
+            }
+            else if (_current == TokenType.Dot)
+            {
+                return ParseObjectReferenceExpression(expression);
+            }
+
+            return expression;
+        }
+
+        private BitwiseOperator ParseBitwiseOperator()
+        {
+            if (_current.Catagory != TokenCatagory.Bitwise)
+            {
+                throw UnexpectedToken("Bitwise operator");
+            }
+            var op = _current.Type;
+            AcceptToken();
+
+            switch (op)
+            {
+                case TokenType.BitwiseAnd:
+                    return BitwiseOperator.And;
+
+                case TokenType.BitwiseOr:
+                    return BitwiseOperator.Or;
+
+                case TokenType.BitwiseXOR:
+                    return BitwiseOperator.Xor;
+
+                default: return BitwiseOperator.And;
+            }
+        }
+
+        private Expression ParseCompoundExpression(Expression first)
+        {
+            List<Expression> expressions = new List<Expression>();
+            expressions.Add(first);
+
+            while (_current != TokenType.ClosePara)
+            {
+                Take(TokenType.Semicolon);
+
+                var expression = ParseExpression();
+
+                expressions.Add(expression);
+            }
+
+            Take(TokenType.ClosePara);
+
+            return new CompoundExpression(expressions);
+        }
+
+        private Expression ParseExpression()
+        {
+            Expression left = ParseLevel1Expression();
+
+            return left;
+        }
+
+        private Expression ParseExpressionTerminal()
+        {
+            if (_current == TokenType.Identifier)
+            {
+                if (_next == TokenType.OpenPara)
+                {
+                    return ParseMethodCall();
+                }
+                else if (_next == TokenType.OpenArrayAccessor)
+                {
+                    return ParseArrayAccess();
+                }
+                else if (_next == TokenType.FatArrow)
+                {
+                    return ParseLambdaExpression(new List<VariableDeclaration>() { new VariableDeclaration(Take(TokenType.Identifier).Value, "var", null) });
+                }
+                else if (_next == TokenType.Dot)
+                {
+                    return ParseObjectReferenceExpression(new IdentifierExpression(Take(TokenType.Identifier).Value));
+                }
+                else
+                {
+                    return new IdentifierExpression(Take(TokenType.Identifier).Value);
+                }
+            }
+            else if (_current == TokenType.Keyword)
+            {
+                if (_current == "true")
+                {
+                    return new ConstantExpression(Take(_current.Type).Value, ConstantType.Boolean);
+                }
+                else if (_current == "false")
+                {
+                    return new ConstantExpression(Take(_current.Type).Value, ConstantType.Boolean);
+                }
+                else if (_current == "null")
+                {
+                    return new ConstantExpression(Take(_current.Type).Value, ConstantType.Null);
+                }
+                else if (_current == "new")
+                {
+                    return ParseNewExpression();
+                }
+            }
+            else if (_current.Catagory == TokenCatagory.Arithmetic)
+            {
+                if (_current == TokenType.Addition)
+                {
+                    AcceptToken();
+                    return ParseExpression();
+                }
+                else if (_current == TokenType.Subtract)
+                {
+                    Take(TokenType.Subtract);
+                    Expression parameter = ParseLevel8Expression();
+                    return new UnaryExpression(parameter, UnaryOperator.Negation, true);
+                }
+            }
+            else if (_current.Catagory == TokenCatagory.Literal)
+            {
+                if (_current == TokenType.StringLiteral)
+                {
+                    return new ConstantExpression(Take(_current.Type).Value, ConstantType.String);
+                }
+                else
+                {
+                    return ParseNumberLiteral();
+                }
+            }
+            throw UnexpectedToken("expression terminal");
+        }
+
+        private Expression ParseLevel1Expression()
+        {
+            Expression left = ParseLevel2Expression();
+            if (_current.Catagory == TokenCatagory.Assignment)
+            {
+                var op = ParseAssignmentType();
+                Expression right = ParseLevel1Expression();
+
+                return new AssignmentExpression(left, right, op);
+            }
+            return left;
+        }
+
+        private Expression ParseLevel2Expression()
+        {
+            Expression left = ParseLevel3Expression();
+
+            if (_current == TokenType.LogicalAnd || _current == TokenType.LogicalOr)
+            {
+                var op = ParseLogicalOperator();
+                Expression right = ParseLevel2Expression();
+
+                return new LogicalExpression(left, right, op);
+            }
+
+            return left;
+        }
+
+        private Expression ParseLevel3Expression()
+        {
+            Expression left = ParseLevel4Expression();
+
+            if (_current.Catagory == TokenCatagory.Logical && _current != "!")
+            {
+                var op = ParseLogicalOperator();
+                Expression right = ParseLevel3Expression();
+
+                return new LogicalExpression(left, right, op);
+            }
+
+            return left;
+        }
+
+        private Expression ParseLevel4Expression()
+        {
+            Expression left = ParseLevel5Expression();
+
+            // 10 - 3 + 2 should be parsed as ((10 - 3) + 2)
+            while (_current == TokenType.Addition || _current == TokenType.Subtract)
+            {
+                var op = ParseArithmeticOperator();
+                left = new ArithmeticExpression(left, ParseLevel5Expression(), op);
+            }
+            return left;
+        }
+
+        private Expression ParseLevel5Expression()
+        {
+            Expression left = ParseLevel6Expression();
+
+            while (_current == TokenType.Multiply || _current == TokenType.Divide)
+            {
+                var op = ParseArithmeticOperator();
+                left = new ArithmeticExpression(left, ParseLevel6Expression(), op);
+            }
+
+            return left;
+        }
+
+        private Expression ParseLevel6Expression()
+        {
+            Expression left = ParseLevel7Expression();
+            if (_current == TokenType.Modulo)
+            {
+                var op = ParseArithmeticOperator();
+                Expression right = ParseLevel6Expression();
+
+                return new ArithmeticExpression(left, right, op);
+            }
+            return left;
+        }
+
+        private Expression ParseLevel7Expression()
+        {
+            Expression left = ParseLevel8Expression();
+
+            if (_current.Catagory == TokenCatagory.Bitwise)
+            {
+                var op = ParseBitwiseOperator();
+                Expression right = ParseLevel7Expression();
+
+                return new BitwiseExpression(left, right, op);
+            }
+
+            return left;
+        }
+
+        private Expression ParseLevel8Expression()
+        {
+            if (_current == TokenType.OpenPara)
+            {
+                return ParseBasicOperation();
+            }
+            else if (IsUnaryOperator() || _next == TokenType.PlusPlus || _next == TokenType.PlusPlus)
+            {
+                return ParseUnaryExpression();
+            }
+            else
+            {
+                return ParseExpressionTerminal();
+            }
+        }
+
+        private LogicOperation ParseLogicalOperator()
+        {
+            if (_current.Catagory != TokenCatagory.Logical)
+            {
+                throw UnexpectedToken("logical operator");
+            }
+            var op = _current.Type;
+            AcceptToken();
+
+            switch (op)
+            {
+                case TokenType.LogicalAnd:
+                    return LogicOperation.And;
+
+                case TokenType.LogicalEquals:
+                    return LogicOperation.Equals;
+
+                case TokenType.LogicalGreater:
+                    return LogicOperation.GreaterThan;
+
+                case TokenType.LogicalGreaterOrEqual:
+                    return LogicOperation.GreaterThanOrEqual;
+
+                case TokenType.LogicalLess:
+                    return LogicOperation.LessThan;
+
+                case TokenType.LogicalLessOrEqual:
+                    return LogicOperation.LessThanOrEqual;
+
+                case TokenType.LogicalNot:
+                    return LogicOperation.Not;
+
+                case TokenType.LogicalNotEquals:
+                    return LogicOperation.NotEquals;
+
+                case TokenType.LogicalOr:
+                    return LogicOperation.Or;
+
+                default: return LogicOperation.Not;
+            }
+        }
+
+        private Expression ParseMethodCall(bool inObjectRef = false)
+        {
+            string identifier = Take(TokenType.Identifier).Value;
+            Take(TokenType.OpenPara);
+
+            List<Expression> arguments = new List<Expression>();
+
+            while (_current != TokenType.ClosePara)
+            {
+                if (_current == TokenType.Comma)
+                {
+                    Take(TokenType.Comma);
+                }
+
+                var expression = ParseExpression();
+
+                arguments.Add(expression);
+            }
+
+            Take(TokenType.ClosePara);
+
+            var call = new MethodCallExpression(identifier, arguments);
+            if (_current == TokenType.Dot && !inObjectRef)
+            {
+                return ParseObjectReferenceExpression(call);
+            }
+
+            return call;
+        }
+
+        private Expression ParseNewExpression()
+        {
+            TakeKeyword("new");
+            string identifier = Take(TokenType.Identifier).Value;
+            if (_current == TokenType.OpenArrayAccessor)
+            {
+                return ParseArrayDeclaration(identifier);
+            }
+            Take(TokenType.OpenPara);
+
+            List<Expression> arguments = new List<Expression>();
+
+            while (_current != TokenType.ClosePara)
+            {
+                if (_current == TokenType.Comma && arguments.Count > 0)
+                {
+                    Take(TokenType.Comma);
+                }
+
+                var expression = ParseExpression();
+
+                arguments.Add(expression);
+            }
+
+            Take(TokenType.ClosePara);
+
+            var call = new NewExpression(identifier, arguments);
+            if (_current == TokenType.Dot)
+            {
+                return ParseObjectReferenceExpression(call);
+            }
+
+            return call;
+        }
+
+        private ConstantExpression ParseNumberLiteral()
+        {
+            switch (_current.Type)
+            {
+                case TokenType.Number:
+                    return new ConstantExpression(Take(TokenType.Number).Value, ConstantType.Int);
+
+                case TokenType.HexNumber:
+                    {
+                        string value = Take(TokenType.HexNumber).Value.Substring(2);
+                        long number = Convert.ToInt64(value, 16);
+                        return new ConstantExpression(number.ToString(), ConstantType.Int);
+                    }
+                case TokenType.OctalNumber:
+                    {
+                        string value = Take(TokenType.OctalNumber).Value.Substring(2);
+                        long number = Convert.ToInt64(value, 8);
+                        return new ConstantExpression(number.ToString(), ConstantType.Int);
+                    }
+                case TokenType.FloatingPointNumber:
+                    return new ConstantExpression(Take(TokenType.FloatingPointNumber).Value, ConstantType.Float);
+
+                default:
+                    throw UnexpectedToken("number constant");
+            }
+        }
+
+        private Expression ParseObjectReferenceExpression(Expression root)
+        {
+            List<Expression> references = new List<Expression>();
+            while (_current == TokenType.Dot)
+            {
+                Take(TokenType.Dot);
+
+                Expression expression;
+
+                if (_next == TokenType.OpenPara)
+                {
+                    expression = ParseMethodCall(true);
+                }
+                else if (_next == TokenType.OpenArrayAccessor)
+                {
+                    expression = ParseArrayAccess(true);
+                }
+                else
+                {
+                    expression = new IdentifierExpression(Take(TokenType.Identifier).Value);
+                }
+
+                references.Add(expression);
+            }
+
+            return new ObjectReferenceExpression(root, references);
+        }
+
+        private Expression ParseUnaryExpression()
+        {
+            Expression expression;
+            if (_current == "!")
+            {
+                var op = ParseUnaryOperator();
+
+                if (_current == TokenType.OpenPara)
+                {
+                    expression = ParseBasicOperation();
+                }
+                else
+                {
+                    expression = ParseExpression();
+                }
+                return new UnaryExpression(expression, op, true);
+            }
+            else if (_current == "++" || _current == "--")
+            {
+                var op = ParseUnaryOperator();
+                string identifier = Take(TokenType.Identifier).Value;
+                return new UnaryExpression(new IdentifierExpression(identifier), op, true);
+            }
+            else
+            {
+                string identifier = Take(TokenType.Identifier).Value;
+                var op = ParseUnaryOperator();
+
+                return new UnaryExpression(new IdentifierExpression(identifier), op, false);
+            }
+        }
+
+        private UnaryOperator ParseUnaryOperator()
+        {
+            var op = _current.Type;
+            AcceptToken();
+            switch (op)
+            {
+                case TokenType.PlusPlus:
+                    return UnaryOperator.Increment;
+
+                case TokenType.MinusMinus:
+                    return UnaryOperator.Decrement;
+
+                case TokenType.LogicalNot:
+                    return UnaryOperator.LogicalNot;
+
+                default:
+                    return UnaryOperator.None;
+            }
+        }
+
+        #endregion Parse Expression
+
+        private Token Take(TokenType type)
+        {
+            if (_current != type)
+            {
+                throw UnexpectedToken(type.ToString().ToLower());
+            }
+            AcceptToken();
+            return _last;
+        }
+
+        private Token Take(TokenType type, string value)
+        {
+            if (_current != type || _current != value)
+            {
+                throw UnexpectedToken($"'{{value}}'");
+            }
+            AcceptToken();
+            return _last;
+        }
+
+        private Token TakeKeyword(string keyword)
+        {
+            return Take(TokenType.Keyword, keyword);
+        }
+
+        private SyntaxException UnexpectedToken(string expected)
+        {
+            string message = $"{_current.Start} {_current.Span} Unexpected Token '{_current.Value}'.  Expected {expected}";
+            return new SyntaxException(message);
+        }
+
+        private SyntaxException UnexpectedToken(Token value, string expected)
+        {
+            string message = $"{value.Start} {value.Span} Unexpected Token '{value.Value}'.  Expected {expected}";
+            return new SyntaxException(message);
+        }
+    }
 }


Order of rendering changed

Order of rendering changed

--- ReferenceCore/ExtenderDoc.cs
+++ ReferenceCore/ExtenderDoc.cs
@@ -31,9 +31,10 @@
             RenderTypeDescription(typeDoc.Summary);
             RenderTypeRemarks(typeDoc.Remarks);

+            RenderProperties(typeDoc.Properties.OrderBy(p => p.Name));
             RenderMethods(typeDoc.Methods.OrderBy(m => m.Name), "Methods");
             RenderEvents(typeDoc.Events.OrderBy(e => e.Name));
-            RenderProperties(typeDoc.Properties.OrderBy(p => p.Name));
+
             RenderClientProperties(typeDoc.ClientProperties.OrderBy(p => p.Name));
             RenderMethods(typeDoc.ClientMethods.OrderBy(m => m.Name), "Client methods");
             RenderClientEvents(typeDoc.ClientEvents.OrderBy(p => p.Name));


Improve UWP indexing #954

Improve UWP indexing #954

1. enable WinJS based UWP
2. ms bug of InstalledLocation:
https://connect.microsoft.com/VisualStudio/feedback/details/1690879/vs2015-cannot-auto-uninstall-universal-windows-appss-debug-item

--- Plugins/Wox.Plugin.Program/Programs/UWP.cs
+++ Plugins/Wox.Plugin.Program/Programs/UWP.cs
@@ -47,8 +47,7 @@
             InitializeAppInfo();
             Apps = Apps.Where(a =>
             {
-                var valid = !string.IsNullOrEmpty(a.Executable) &&
-                            !string.IsNullOrEmpty(a.UserModelId) &&
+                var valid = !string.IsNullOrEmpty(a.UserModelId) &&
                             !string.IsNullOrEmpty(a.DisplayName);
                 return valid;
             }).ToArray();
@@ -81,7 +80,6 @@
                     if (appListEntry != "nonoe")
                     {
                         Apps[i].UserModelId = currentApp.GetAppUserModelId();
-                        Apps[i].Executable = currentApp.GetStringValue("Executable") ?? string.Empty;
                         Apps[i].BackgroundColor = currentApp.GetStringValue("BackgroundColor") ?? string.Empty;
                         Apps[i].LogoPath = Path.Combine(Location, currentApp.GetStringValue("Square44x44Logo"));
                         Apps[i].Location = Location;
@@ -157,7 +155,7 @@
                 var userSecurityId = user.Value;
                 var packageManager = new PackageManager();
                 var packages = packageManager.FindPackagesForUser(userSecurityId);
-                packages = packages.Where(p => !p.IsFramework && !string.IsNullOrEmpty(p.InstalledLocation.Path));
+                packages = packages.Where(p => !p.IsFramework && !p.IsDevelopmentMode && !string.IsNullOrEmpty(p.InstalledLocation.Path));
                 return packages;
             }
             else
@@ -196,7 +194,6 @@
             public string Description { get; set; }
             public RandomAccessStreamReference LogoStream { get; set; }
             public string UserModelId { get; set; }
-            public string Executable { get; set; }
             public string PublisherDisplayName { get; set; }
             public string BackgroundColor { get; set; }
             public string LogoPath { get; set; }


Nullability

Nullability

--- Rdr/Gui/Converters/BooleanConverterBase.cs
+++ Rdr/Gui/Converters/BooleanConverterBase.cs
@@ -37,6 +37,6 @@
 			=> (bool)value ? True : False;

 		public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
-			=> throw new NotImplementedException($"converting from {value.GetType().ToString()} to {targetType.ToString()} is not implemented!");
+			=> throw new NotImplementedException($"converting from {value?.GetType().ToString() ?? "value is null"} to {targetType?.ToString() ?? "targetType is null"} is not implemented!");
 	}
 }


Update Box.cs

Update Box.cs

--- Runtime/LibProcessors/Box.cs
+++ Runtime/LibProcessors/Box.cs
@@ -38,7 +38,10 @@
 		{
 			return Resources.Load<T>(id);
 		}
-
+		public static T[] LoadAll<T>(string id) where T : Object
+		{
+			return Resources.LoadAll<T>(id);
+		}
 		public static T Get<T>(string id) where T : Object
 		{
 			Object obj;


Update

Update

--- Runtime/LibProcessors/ProcessorObserver.cs
+++ Runtime/LibProcessors/ProcessorObserver.cs
@@ -13,12 +13,12 @@

 		public ProcessorObserver()
 		{
-			groupObservers.onAdd += (in ent entity) =>
-			{
-				var cObserver = entity.ComponentObserver();
-				for (int j = 0; j < cObserver.length; j++)
-					cObserver.wrappers[j].FirstTime();
-			};
+			// groupObservers.onAdd += (in ent entity) =>
+			// {
+			// 	var cObserver = entity.ComponentObserver();
+			// 	for (int j = 0; j < cObserver.length; j++)
+			// 		cObserver.wrappers[j].FirstTime();
+			// };
 		}

 		public void Tick(float delta)


Update stockMarketScreen.cs

Update stockMarketScreen.cs

--- SMG/SMG/stockMarketScreen.cs
+++ SMG/SMG/stockMarketScreen.cs
@@ -10,7 +10,7 @@

 namespace SMG
 {
-
+
     public partial class stockMarketScreen : Form
     {
         //Global Variables
@@ -30,11 +30,19 @@
         private void stockMarketScreen_Load(object sender, EventArgs e)
         {
             //load stocks
-            //adds a row
-            dgvStockList.Rows.Add();
-            dgvStockList.Rows[dgvStockList.RowCount - 1].Cells[0].Value = "Google";
-            dgvStockList.Rows[dgvStockList.RowCount - 1].Cells[1].Value = 99.98;
-            dgvStockList.Rows[dgvStockList.RowCount - 1].Cells[2].Value = bmpUp;
+            stocks.Add(new Stock("Guugle"));
+            stocks.Add(new Stock("Pear"));
+            stocks.Add(new Stock("Skybucks"));
+            //adds rows
+            int currentRow = 0;
+            foreach (Stock s in stocks)
+            {
+                dgvStockList.Rows.Add();
+                dgvStockList.Rows[currentRow].Cells[0].Value = s.StockName;
+                dgvStockList.Rows[currentRow].Cells[1].Value = s.StockReturn;
+                dgvStockList.Rows[currentRow].Cells[2].Value = bmpUp;
+                currentRow++;
+            }
         }

         /// <summary>
@@ -45,7 +53,7 @@
         private void dgvStockList_CellContentClick(object sender, DataGridViewCellEventArgs e)
         {
             //is a row clicked?
-            if (e.RowIndex >= 0 && e.RowIndex < dgvStockList.RowCount)
+            if (e.RowIndex >= 0 && e.RowIndex < dgvStockList.RowCount)
             {
                 MessageBox.Show("You clicked " +
                     dgvStockList.Rows[e.RowIndex].Cells[0].Value);


Added function to clear the task batching window when tasks are added to weekly to do

--- Saveyour/TaskBatch/TaskBatchWindow.xaml.cs
+++ Saveyour/TaskBatch/TaskBatchWindow.xaml.cs
@@ -121,6 +121,7 @@
             bool? result = confirm.ShowDialog();
             if (result == true)
             {
+                AvailableDates.Children.Clear();
                 // ADD THE TASKS AT THE DATE
             }
         }


ScadaData: remove obsolete methos from CommSettings

--- ScadaData/ScadaData/Client/CommSettings.cs
+++ ScadaData/ScadaData/Client/CommSettings.cs
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Mikhail Shiryaev
+ * Copyright 2017 Mikhail Shiryaev
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
  *
  * Author   : Mikhail Shiryaev
  * Created  : 2005
- * Modified : 2016
+ * Modified : 2017
  */

 using System;
@@ -203,22 +203,6 @@
         }

         /// <summary>
-        /// Загрузить настройки из файла
-        /// </summary>
-        [Obsolete]
-        public void LoadFromFile(string fileName, Log log)
-        {
-            if (log == null)
-                throw new ArgumentNullException("log");
-
-            log.WriteAction(Localization.UseRussian ? "Загрузка настроек соединения с сервером" :
-                "Load server connection settings", Log.ActTypes.Action);
-            string errMsg;
-            if (!LoadFromFile(fileName, out errMsg))
-                log.WriteAction(errMsg, Log.ActTypes.Exception);
-        }
-
-        /// <summary>
         /// Сохранить настройки в заданный XML-элемент
         /// </summary>
         public void SaveToXml(XmlElement commSettingsElem)


fix of PanelChanged arguments

fix of PanelChanged arguments

--- ScnSideMenu/ScnSideMenu/Src/SideBarPage.cs
+++ ScnSideMenu/ScnSideMenu/Src/SideBarPage.cs
@@ -338,7 +338,7 @@
                     else
                         HideRightPanel();

-                    OnPanelChanged(new SideBarEventArgs(value, PanelAlignEnum.paLeft));
+                    OnPanelChanged(new SideBarEventArgs(value, PanelAlignEnum.paRight));
                 }
             }
         }


fix: clarify language

fix: clarify language

PiperOrigin-RevId: 428802866

Source-Link: https://github.com/googleapis/googleapis/commit/8cb469950ab01d1377f8b90212a65e35c5408723

Source-Link: https://github.com/googleapis/googleapis-gen/commit/b15d56f575356c9c3ef1eb2076ee209e5b48bc41
Copy-Tag: eyJwIjoiYXBpcy9Hb29nbGUuQ2xvdWQuQ2hhbm5lbC5WMS8uT3dsQm90LnlhbWwiLCJoIjoiYjE1ZDU2ZjU3NTM1NmM5YzNlZjFlYjIwNzZlZTIwOWU1YjQ4YmM0MSJ9

--- apis/Google.Cloud.Channel.V1/Google.Cloud.Channel.V1/Entitlements.g.cs
+++ apis/Google.Cloud.Channel.V1/Google.Cloud.Channel.V1/Entitlements.g.cs
@@ -1380,8 +1380,8 @@
     public const int ProvisioningIdFieldNumber = 1;
     private string provisioningId_ = "";
     /// <summary>
-    /// Output only. Provisioning ID of the entitlement. For Google Workspace, this would be the
-    /// underlying Subscription ID. For Google Cloud Platform, this would be the
+    /// Output only. Provisioning ID of the entitlement. For Google Workspace, this is the
+    /// underlying Subscription ID. For Google Cloud Platform, this is the
     /// Billing Account ID of the billing subaccount."
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]


Added throwIfOutOfRange() method.

Added throwIfOutOfRange() method.

--- Sandra.UI.WF/PlayingBoard.cs
+++ Sandra.UI.WF/PlayingBoard.cs
@@ -867,10 +867,15 @@
             if (squareLocation == null) throw new ArgumentNullException(nameof(squareLocation));
         }

-        private int getIndex(int x, int y)
+        private void throwIfOutOfRange(int x, int y)
         {
             if (x < 0 || x >= BoardWidth) throw new IndexOutOfRangeException(nameof(x));
             if (y < 0 || y >= BoardHeight) throw new IndexOutOfRangeException(nameof(y));
+        }
+
+        private int getIndex(int x, int y)
+        {
+            throwIfOutOfRange(x, y);
             return y * BoardWidth + x;
         }


minor fixes

minor fixes

--- SelfHosting.Nancy/Program.cs
+++ SelfHosting.Nancy/Program.cs
@@ -8,22 +8,21 @@
     {
         static void Main(string[] args)
         {
-            string url =@"http://localhost:12345";
+            const string url = @"http://localhost:12345";
             using (var host = new NancyHost(new Uri(url)))
             {
                 host.Start();

-                Process.Start(@"chrome.exe", string.Format("--incognito {0}", url));
+                Process.Start(@"chrome.exe", $"--incognito {url}");
                 Console.WriteLine("press any key to stop");
                 Console.ReadLine();
                 host.Stop();
             }
-
         }

         private static void OpenUrl(string askedServer, int port)
         {
-            var url = string.Format(@"http://{0}:{1}", askedServer, port);
+            var url = $@"http://{askedServer}:{port}";

         }
     }


removed bogus unit test used to demonstrate moq

--- SendGrid/Tests/TestHeader.cs
+++ SendGrid/Tests/TestHeader.cs
@@ -14,12 +14,7 @@
         [Test]
         public void TestAddTo()
         {
-            var foo = new Mock<IHeader>();
-            foo.Setup(m => m.Enable("foo"));
-
-            var bar = new SendGrid(foo.Object);
-            Assert.AreEqual(1, 2, "I suck");
-
+
         }
     }
 }


use ulong instead of uint in responses

use ulong instead of uint in responses

--- b2-csharp-client/B2.Client/Apis/ListBucketsV1/ListBucketsV1Response.cs
+++ b2-csharp-client/B2.Client/Apis/ListBucketsV1/ListBucketsV1Response.cs
@@ -72,7 +72,7 @@
             /// The revision number of the bucket, which increments every time it is changed.
             /// </summary>
             [DataMember(Name = "revision", IsRequired = true)]
-            public uint Revision { get; }
+            public ulong Revision { get; }

             /// <summary>
@@ -86,7 +86,7 @@
             /// <param name="Revision">The revision number of the bucket, which increments every time it is changed.</param>
             [SuppressMessage("ReSharper", "InconsistentNaming")]
             public B2Bucket(string AccountId, string BucketId, string BucketName, BucketType BucketType,
-                            List<B2LifecycleRule> LifecycleRules, uint Revision)
+                            List<B2LifecycleRule> LifecycleRules, ulong Revision)
             {
                 this.AccountId = AccountId;
                 this.BucketId = BucketId;


Renamed some of the parameters in the constructor for the StumpsServer to be more intuitive.

--- src/main/dot-net/Stumps.Base/StumpsServer.cs
+++ src/main/dot-net/Stumps.Base/StumpsServer.cs
@@ -14,7 +14,7 @@

         private readonly object _syncRoot;
         private readonly IStumpsManager _stumpsManager;
-        private readonly Uri _externalHost;
+        private readonly Uri _proxyHost;
         private readonly ServerDefaultResponse _defaultResponse;

         private readonly int _port;
@@ -30,10 +30,10 @@
         /// <summary>
         /// Initializes a new instance of the <see cref="T:Stumps.StumpsServer" /> class.
         /// </summary>
-        /// <param name="port">The port the HTTP server is using to listen for traffic.</param>
+        /// <param name="listeningPort">The port the HTTP server is using to listen for traffic.</param>
         /// <param name="defaultResponse">The default response returned to a client when a matching <see cref="T:Stumps.Stump"/> is not found.</param>
-        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="port" /> exceeds the allowed TCP port range.</exception>
-        public StumpsServer(int port, ServerDefaultResponse defaultResponse) : this(port, null)
+        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="listeningPort" /> exceeds the allowed TCP port range.</exception>
+        public StumpsServer(int listeningPort, ServerDefaultResponse defaultResponse) : this(listeningPort, null)
         {
             _defaultResponse = defaultResponse;
         }
@@ -41,22 +41,22 @@
         /// <summary>
         ///     Initializes a new instance of the <see cref="T:Stumps.StumpsServer" /> class.
         /// </summary>
-        /// <param name="port">The port the HTTP server is using to listen for traffic.</param>
-        /// <param name="externalHostUri">The external host that is contacted when a <see cref="T:Stumps.Stump"/> is unavailable to handle the incomming request.</param>
-        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="port" /> exceeds the allowed TCP port range.</exception>
-        public StumpsServer(int port, Uri externalHostUri)
-        {
-            if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)
-            {
-                throw new ArgumentOutOfRangeException("port");
+        /// <param name="listeningPort">The port the HTTP server is using to listen for traffic.</param>
+        /// <param name="proxyHostUri">The external host that is contacted when a <see cref="T:Stumps.Stump"/> is unavailable to handle the incomming request.</param>
+        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="listeningPort" /> exceeds the allowed TCP port range.</exception>
+        public StumpsServer(int listeningPort, Uri proxyHostUri)
+        {
+            if (listeningPort < IPEndPoint.MinPort || listeningPort > IPEndPoint.MaxPort)
+            {
+                throw new ArgumentOutOfRangeException("listeningPort");
             }

             _syncRoot = new object();
             _stumpsManager = new StumpsManager();

-            _port = port;
-
-            _externalHost = externalHostUri;
+            _port = listeningPort;
+
+            _proxyHost = proxyHostUri;
         }

         /// <summary>
@@ -87,6 +87,17 @@
         public int ListeningPort
         {
             get { return _port; }
+        }
+
+        /// <summary>
+        ///     Gets the external host that is contacted when a <see cref="T:Stumps.Stump"/> is unavailable to handle the incomming request.
+        /// </summary>
+        /// <value>
+        ///     The external host that is contacted when a <see cref="T:Stumps.Stump"/> is unavailable to handle the incomming request.
+        /// </value>
+        public Uri ProxyHostUri
+        {
+            get { return _proxyHost; }
         }

         /// <summary>
@@ -219,9 +230,9 @@
                 pipeline.Add(stumpsHandler);

                 // Setup the Proxy HTTP handler
-                if (_externalHost != null)
-                {
-                    var proxyHandler = new ProxyHandler(_externalHost);
+                if (_proxyHost != null)
+                {
+                    var proxyHandler = new ProxyHandler(_proxyHost);
                     proxyHandler.ContextProcessed += (o, e) => Interlocked.Increment(ref _proxyCounter);
                     pipeline.Add(proxyHandler);
                 }


Fixed dispose issue in Stumps server.

Fixed dispose issue in Stumps server.

--- src/main/dot-net/Stumps.Base/StumpsServer.cs
+++ src/main/dot-net/Stumps.Base/StumpsServer.cs
@@ -127,6 +127,10 @@
                     this.Stop();
                 }

+                if (_stumpsManager != null)
+                {
+                    _stumpsManager.Dispose();
+                }
             }

             GC.SuppressFinalize(this);