public static IExpression BuildExpression(TokenList tokens, Stack<int?> precedenceStack) { if (tokens.Current == null) throw new TokenParserException("The script seems to have ended prematurely. Shouldn't there be something here?", tokens.Peek(-2)); Token token = tokens.Current; IExpression expr = null; bool endGroupedExpression = false; switch (token.TokenType) { case TokenType.Number: expr = new NumericExpression(tokens, precedenceStack); break; case TokenType.QuotedString: expr = new StringExpression(tokens, precedenceStack); break; case TokenType.FreeText: expr = new StringExpression(tokens, precedenceStack); return expr; case TokenType.Word: if (expressionCreators.ContainsKey(token.Value)) { // find the appropriate handler for this keyword expr = expressionCreators[token.Value].Create(); } else // we don't recognise the word, so we can assume it's a variable and validate it at run-time { // don't allow instruction keywords to be used as variable names if (instructionCreators.ContainsKey(token.Value)) throw new TokenParserException("This word is the name of an instruction. You can't use it here in this context.", token); else expr = new VariableExpression(); } // if applicable, have the expression prepare itself according to its own rules if (expr is IFlexibleSyntaxExpression) ((IFlexibleSyntaxExpression)expr).PrepareExpression(tokens, precedenceStack); else // otherwise just advance to the next token tokens.Advance(); // chain together any properties and argument lists expr = BuildDeepExpression(expr, tokens); break; case TokenType.PropertyDesignator: // property designators are handled elsewhere. if we found one here, it's a parsing error. if (tokens.Previous.TokenType == TokenType.Word) throw new TokenParserException("This type of expression doesn't allow you to specify a property.", tokens.Next); throw new TokenParserException("You've got a property designator in a spot where it doesn't belong.", tokens.Next); case TokenType.GroupStart: expr = BuildGroupedExpression(tokens); break; case TokenType.GroupEnd: endGroupedExpression = true; break; default: throw new TokenParserException("This part of the script should equate to a value but instead I got \"" + token.Value + "\", which doesn't really mean anything in this context.", token); } if (!endGroupedExpression) { int? precedence = precedenceStack.Peek(); while (NextHasGreaterPrecedence(precedence, tokens)) expr = BuildBinaryExpression(tokens, expr, precedenceStack); } return expr; }
public static IExpression BuildExpression(TokenList tokens, Stack <int?> precedenceStack) { if (tokens.Current == null) { throw new TokenParserException("The script seems to have ended prematurely. Shouldn't there be something here?", tokens.Peek(-2)); } Token token = tokens.Current; IExpression expr = null; bool endGroupedExpression = false; switch (token.TokenType) { case TokenType.Number: expr = new NumericExpression(tokens, precedenceStack); break; case TokenType.QuotedString: expr = new StringExpression(tokens, precedenceStack); break; case TokenType.FreeText: expr = new StringExpression(tokens, precedenceStack); return(expr); case TokenType.Word: if (expressionCreators.ContainsKey(token.Value)) { // find the appropriate handler for this keyword expr = expressionCreators[token.Value].Create(); } else // we don't recognise the word, so we can assume it's a variable and validate it at run-time { // don't allow instruction keywords to be used as variable names if (instructionCreators.ContainsKey(token.Value)) { throw new TokenParserException("This word is the name of an instruction. You can't use it here in this context.", token); } else { expr = new VariableExpression(); } } // if applicable, have the expression prepare itself according to its own rules if (expr is IFlexibleSyntaxExpression) { ((IFlexibleSyntaxExpression)expr).PrepareExpression(tokens, precedenceStack); } else // otherwise just advance to the next token { tokens.Advance(); } // chain together any properties and argument lists expr = BuildDeepExpression(expr, tokens); break; case TokenType.PropertyDesignator: // property designators are handled elsewhere. if we found one here, it's a parsing error. if (tokens.Previous.TokenType == TokenType.Word) { throw new TokenParserException("This type of expression doesn't allow you to specify a property.", tokens.Next); } throw new TokenParserException("You've got a property designator in a spot where it doesn't belong.", tokens.Next); case TokenType.GroupStart: expr = BuildGroupedExpression(tokens); break; case TokenType.GroupEnd: endGroupedExpression = true; break; default: throw new TokenParserException("This part of the script should equate to a value but instead I got \"" + token.Value + "\", which doesn't really mean anything in this context.", token); } if (!endGroupedExpression) { int?precedence = precedenceStack.Peek(); while (NextHasGreaterPrecedence(precedence, tokens)) { expr = BuildBinaryExpression(tokens, expr, precedenceStack); } } return(expr); }