|
@@ -107,107 +107,122 @@ namespace NTERA.Interpreter
|
|
|
return c == '%' || c == '{';
|
|
|
}
|
|
|
|
|
|
- public IEnumerable<Token> GetTokens()
|
|
|
+ private Token DetermineToken(char c)
|
|
|
{
|
|
|
- while (true)
|
|
|
+ if (TokenCharDictionary.TryGetValue(currentChar, out Token charToken))
|
|
|
+ return charToken;
|
|
|
+
|
|
|
+ switch (currentChar)
|
|
|
{
|
|
|
- while (IsWhitespace(GetNextChar()) && Type != LexerType.String) { }
|
|
|
+ case ';': //semicolon is comment
|
|
|
+ while (currentChar != '\n')
|
|
|
+ GetNextChar();
|
|
|
+
|
|
|
+ return Token.NewLine;
|
|
|
+ case '<':
|
|
|
+ if (!Type.HasFlag(LexerType.Real))
|
|
|
+ break;
|
|
|
+
|
|
|
+ if (GetNextChar(true) == '>')
|
|
|
+ {
|
|
|
+ GetNextChar();
|
|
|
+ return Token.NotEqual;
|
|
|
+ }
|
|
|
+ else if (GetNextChar(true) == '=')
|
|
|
+ {
|
|
|
+ GetNextChar();
|
|
|
+ return Token.LessEqual;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return Token.Less;
|
|
|
|
|
|
- TokenMarker = sourceMarker;
|
|
|
+ case '>':
|
|
|
+ if (!Type.HasFlag(LexerType.Real))
|
|
|
+ break;
|
|
|
|
|
|
- if (TokenCharDictionary.TryGetValue(currentChar, out Token charToken))
|
|
|
- {
|
|
|
- yield return charToken;
|
|
|
- continue;
|
|
|
- }
|
|
|
+ if (GetNextChar(true) == '=')
|
|
|
+ {
|
|
|
+ GetNextChar();
|
|
|
+ return Token.MoreEqual;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return Token.More;
|
|
|
+
|
|
|
+ case '+':
|
|
|
+ if (GetNextChar(true) == '=')
|
|
|
+ {
|
|
|
+ GetNextChar();
|
|
|
+ return Token.Append;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return Token.Plus;
|
|
|
|
|
|
- switch (currentChar)
|
|
|
- {
|
|
|
- case ';': //semicolon is comment
|
|
|
- while (currentChar != '\n')
|
|
|
- GetNextChar();
|
|
|
- continue;
|
|
|
- case '<':
|
|
|
- if (!Type.HasFlag(LexerType.Real))
|
|
|
- break;
|
|
|
-
|
|
|
- if (GetNextChar(true) == '>')
|
|
|
- {
|
|
|
- GetNextChar();
|
|
|
- yield return Token.NotEqual;
|
|
|
- }
|
|
|
- else if (GetNextChar(true) == '=')
|
|
|
- {
|
|
|
- GetNextChar();
|
|
|
- yield return Token.LessEqual;
|
|
|
- }
|
|
|
- else
|
|
|
- yield return Token.Less;
|
|
|
- continue;
|
|
|
- case '>':
|
|
|
- if (!Type.HasFlag(LexerType.Real))
|
|
|
- break;
|
|
|
+ case '%':
|
|
|
+
|
|
|
+ StringBuilder builder = new StringBuilder();
|
|
|
+ while (GetNextChar() != '%')
|
|
|
+ builder.Append(currentChar);
|
|
|
+
|
|
|
+ Value = $"%{builder}%";
|
|
|
+ return Token.Value;
|
|
|
|
|
|
- if (GetNextChar(true) == '=')
|
|
|
+ case '"':
|
|
|
+ string str = "";
|
|
|
+ while (GetNextChar() != '"')
|
|
|
+ {
|
|
|
+ if (currentChar == '\\')
|
|
|
{
|
|
|
- GetNextChar();
|
|
|
- yield return Token.MoreEqual;
|
|
|
+ switch (char.ToLower(GetNextChar()))
|
|
|
+ {
|
|
|
+ case 'n': str += '\n'; break;
|
|
|
+ case 't': str += '\t'; break;
|
|
|
+ case '\\': str += '\\'; break;
|
|
|
+ case '"': str += '"'; break;
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
- yield return Token.More;
|
|
|
- continue;
|
|
|
- case '+':
|
|
|
- if (GetNextChar(true) == '=')
|
|
|
{
|
|
|
- GetNextChar();
|
|
|
- yield return Token.Append;
|
|
|
+ str += currentChar;
|
|
|
}
|
|
|
- else
|
|
|
- yield return Token.Plus;
|
|
|
- continue;
|
|
|
- case '%':
|
|
|
+ }
|
|
|
+ Value = new Value(str);
|
|
|
+ return Token.Value;
|
|
|
+
|
|
|
+ case (char)0:
|
|
|
+ return Token.EOF;
|
|
|
+ }
|
|
|
|
|
|
- StringBuilder builder = new StringBuilder();
|
|
|
- while (GetNextChar() != '%')
|
|
|
- builder.Append(currentChar);
|
|
|
+ return Token.Unknown;
|
|
|
+ }
|
|
|
|
|
|
- Value = $"%{builder}%";
|
|
|
- yield return Token.Value;
|
|
|
+ public IEnumerable<Token> GetTokens()
|
|
|
+ {
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
+ while (IsWhitespace(GetNextChar()) && Type != LexerType.String || currentChar == '\r') { }
|
|
|
|
|
|
- continue;
|
|
|
- case '"':
|
|
|
- string str = "";
|
|
|
- while (GetNextChar() != '"')
|
|
|
- {
|
|
|
- if (currentChar == '\\')
|
|
|
- {
|
|
|
- switch (char.ToLower(GetNextChar()))
|
|
|
- {
|
|
|
- case 'n': str += '\n'; break;
|
|
|
- case 't': str += '\t'; break;
|
|
|
- case '\\': str += '\\'; break;
|
|
|
- case '"': str += '"'; break;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- str += currentChar;
|
|
|
- }
|
|
|
- }
|
|
|
- Value = new Value(str);
|
|
|
- yield return Token.Value;
|
|
|
- continue;
|
|
|
- case (char)0:
|
|
|
- yield return Token.EOF;
|
|
|
- yield break;
|
|
|
+ TokenMarker = sourceMarker;
|
|
|
+
|
|
|
+ Token token = DetermineToken(currentChar);
|
|
|
+
|
|
|
+ if (token == Token.EOF)
|
|
|
+ {
|
|
|
+ yield return Token.EOF;
|
|
|
+ yield break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (token != Token.Unknown)
|
|
|
+ {
|
|
|
+ yield return token;
|
|
|
+ continue;
|
|
|
}
|
|
|
|
|
|
StringBuilder bodyBuilder = new StringBuilder(currentChar.ToString());
|
|
|
|
|
|
- while (!TokenCharDictionary.ContainsKey(GetNextChar(true))
|
|
|
- && !IsEndOfLine(GetNextChar(true))
|
|
|
- && (!IsWhitespace(GetNextChar(true)) || Type == LexerType.String)
|
|
|
- && (!IsEscape(GetNextChar(true)) || Type != LexerType.String))
|
|
|
+ while ((!IsEscape(GetNextChar(true)) || Type != LexerType.String)
|
|
|
+ && DetermineToken(GetNextChar(true)) == Token.Unknown
|
|
|
+ && (!IsWhitespace(GetNextChar(true)) || Type == LexerType.String)
|
|
|
+ && GetNextChar(true) != '\r')
|
|
|
{
|
|
|
bodyBuilder.Append(GetNextChar());
|
|
|
}
|
|
@@ -230,12 +245,15 @@ namespace NTERA.Interpreter
|
|
|
|
|
|
Identifer = bodyBuilder.ToString();
|
|
|
|
|
|
- if (TokenDictionary.TryGetValue(Identifer, out Token token))
|
|
|
+ if (TokenDictionary.TryGetValue(Identifer, out token))
|
|
|
{
|
|
|
yield return token;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ if (Type == LexerType.String && char.IsWhiteSpace(Identifer[0]))
|
|
|
+ Identifer = Identifer.Substring(1);
|
|
|
+
|
|
|
if (TokenLineDictionary.TryGetValue(Identifer, out token))
|
|
|
{
|
|
|
bodyBuilder = new StringBuilder();
|
|
@@ -245,7 +263,12 @@ namespace NTERA.Interpreter
|
|
|
|
|
|
yield return token;
|
|
|
|
|
|
- Value = new Value(bodyBuilder.ToString().Substring(1));
|
|
|
+ string strValue = bodyBuilder.ToString();
|
|
|
+
|
|
|
+ if (strValue.Length > 0 && char.IsWhiteSpace(strValue[0]))
|
|
|
+ strValue = strValue.Substring(1);
|
|
|
+
|
|
|
+ Value = new Value(strValue);
|
|
|
yield return Token.Value;
|
|
|
|
|
|
yield return currentChar == '\0' ? Token.EOF : Token.NewLine;
|