ConditionExpression: move lexing to Token class.

This commit is contained in:
atlimit8
2017-02-14 00:42:03 -06:00
parent 4537c3c7d0
commit 8e6436d71c

View File

@@ -109,8 +109,11 @@ namespace OpenRA.Support
enum TokenType
{
// varying values
Number,
Variable,
// operators
OpenParen,
CloseParen,
Not,
@@ -118,6 +121,7 @@ namespace OpenRA.Support
Or,
Equals,
NotEquals,
Invalid
}
@@ -232,6 +236,126 @@ namespace OpenRA.Support
Type = type;
Index = index;
}
public static TokenType GetNextType(string expression, ref int i)
{
var start = i;
switch (expression[i])
{
case '!':
i++;
if (i < expression.Length && expression[i] == '=')
{
i++;
return TokenType.NotEquals;
}
return TokenType.Not;
case '=':
i++;
if (i < expression.Length && expression[i] == '=')
{
i++;
return TokenType.Equals;
}
throw new InvalidDataException("Unexpected character '=' at index {0} - should it be `==`?".F(start));
case '&':
i++;
if (i < expression.Length && expression[i] == '&')
{
i++;
return TokenType.And;
}
throw new InvalidDataException("Unexpected character '&' at index {0} - should it be `&&`?".F(start));
case '|':
i++;
if (i < expression.Length && expression[i] == '|')
{
i++;
return TokenType.Or;
}
throw new InvalidDataException("Unexpected character '|' at index {0} - should it be `||`?".F(start));
case '(':
i++;
return TokenType.OpenParen;
case ')':
i++;
return TokenType.CloseParen;
}
var cc = CharClassOf(expression[start]);
// Scan forwards until we find an non-digit character
if (expression[start] == '-' || cc == CharClass.Digit)
{
i++;
for (; i < expression.Length; i++)
{
cc = CharClassOf(expression[i]);
if (cc != CharClass.Digit)
{
if (cc != CharClass.Whitespace && cc != CharClass.Operator)
throw new InvalidDataException("Number {0} and variable merged at index {1}".F(
int.Parse(expression.Substring(start, i - start)), start));
return TokenType.Number;
}
}
return TokenType.Number;
}
if (cc != CharClass.Id)
throw new InvalidDataException("Invalid character '{0}' at index {1}".F(expression[i], start));
// Scan forwards until we find an invalid name character
for (; i < expression.Length; i++)
{
cc = CharClassOf(expression[i]);
if (cc == CharClass.Whitespace || cc == CharClass.Operator)
return TokenType.Variable;
}
// Take the rest of the string
return TokenType.Variable;
}
public static Token GetNext(string expression, ref int i)
{
if (i == expression.Length)
return null;
// Ignore whitespace
while (CharClassOf(expression[i]) == CharClass.Whitespace)
{
if (++i == expression.Length)
return null;
}
var start = i;
var type = GetNextType(expression, ref i);
switch (type)
{
case TokenType.Number:
return new NumberToken(start, expression.Substring(start, i - start));
case TokenType.Variable:
return new VariableToken(start, expression.Substring(start, i - start));
default:
return new Token(type, start);
}
}
}
class VariableToken : Token
@@ -264,16 +388,12 @@ namespace OpenRA.Support
var openParens = 0;
var closeParens = 0;
var tokens = new List<Token>();
for (var i = 0; i < expression.Length;)
for (var i = 0;;)
{
// Ignore whitespace
if (CharClassOf(expression[i]) == CharClass.Whitespace)
{
i++;
continue;
}
var token = Token.GetNext(expression, ref i);
if (token == null)
break;
var token = ParseSymbol(expression, ref i);
switch (token.Type)
{
case TokenType.OpenParen:
@@ -331,111 +451,6 @@ namespace OpenRA.Support
postfix = ToPostfix(tokens).ToArray();
}
static Token ParseSymbol(string expression, ref int i)
{
var start = i;
// Parse operators
switch (expression[start])
{
case '!':
{
i++;
if (i < expression.Length && expression[start + 1] == '=')
{
i++;
return new Token(TokenType.NotEquals, start);
}
return new Token(TokenType.Not, start);
}
case '=':
{
i++;
if (i < expression.Length && expression[start + 1] == '=')
{
i++;
return new Token(TokenType.Equals, start);
}
throw new InvalidDataException("Unexpected character '=' at index {0} - should it be `==`?".F(start));
}
case '&':
{
i++;
if (i < expression.Length && expression[start + 1] == '&')
{
i++;
return new Token(TokenType.And, start);
}
throw new InvalidDataException("Unexpected character '&' at index {0} - should it be `&&`?".F(start));
}
case '|':
{
i++;
if (i < expression.Length && expression[start + 1] == '|')
{
i++;
return new Token(TokenType.Or, start);
}
throw new InvalidDataException("Unexpected character '|' at index {0} - should it be `||`?".F(start));
}
case '(':
{
i++;
return new Token(TokenType.OpenParen, start);
}
case ')':
{
i++;
return new Token(TokenType.CloseParen, start);
}
}
var cc = CharClassOf(expression[start]);
// Scan forwards until we find an non-digit character
if (expression[start] == '-' || cc == CharClass.Digit)
{
i++;
for (; i < expression.Length; i++)
{
cc = CharClassOf(expression[i]);
if (cc != CharClass.Digit)
{
if (cc != CharClass.Whitespace && cc != CharClass.Operator)
throw new InvalidDataException("Number {0} and variable merged at index {1}".F(
int.Parse(expression.Substring(start, i - start)), start));
return new NumberToken(start, expression.Substring(start, i - start));
}
}
return new NumberToken(start, expression.Substring(start));
}
if (cc != CharClass.Id)
throw new InvalidDataException("Invalid character '{0}' at index {1}".F(expression[i], start));
// Scan forwards until we find an invalid name character
for (; i < expression.Length; i++)
{
cc = CharClassOf(expression[i]);
if (cc == CharClass.Whitespace || cc == CharClass.Operator)
return new VariableToken(start, expression.Substring(start, i - start));
}
// Take the rest of the string
return new VariableToken(start, expression.Substring(start));
}
static int ParseSymbol(VariableToken t, IReadOnlyDictionary<string, int> symbols)
{
int value;