Files
Convention-CSharp/Convention/[Symbolization]/Runner/SymbolizationReader.cs

161 lines
5.1 KiB
C#
Raw Normal View History

2025-07-03 21:50:26 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Convention.Symbolization.Internal
{
public class SymbolizationReader
{
2025-07-04 21:39:02 +08:00
#region Read Script Words
2025-07-03 21:50:26 +08:00
private string buffer = "";
2025-07-04 21:39:02 +08:00
private int lineContext = 1;
2025-07-03 21:50:26 +08:00
private bool isOutOfStringline = true;
2025-07-04 23:00:41 +08:00
public Dictionary<int, Dictionary<int, Variable>> ScriptWords = new() { { 1, new() } };
2025-07-03 21:50:26 +08:00
private static HashSet<char> ControllerCharSet = new()
{
'{','}','(',')','[',']',
'+','-','*','/','%',
'=',
'!','<','>','&','|',
'^',
':',',','.','?',/*'\'','"',*/
'@','#','$',
2025-07-04 21:39:02 +08:00
';'
2025-07-03 21:50:26 +08:00
};
public void ReadChar(char ch)
{
if (isOutOfStringline)
{
if (ControllerCharSet.Contains(ch))
CompleteSingleSymbol(ch);
2025-07-04 21:39:02 +08:00
else if (ch == '\n')
CompleteLine();
else if (char.IsWhiteSpace(ch) || ch == '\r' || ch == '\t')
2025-07-03 21:50:26 +08:00
CompleteWord();
else if (buffer.Length == 0 && ch == '"')
BeginString();
else if (char.IsLetter(ch) || char.IsDigit(ch))
PushChar(ch);
else
2025-07-04 21:39:02 +08:00
throw new NotImplementedException($"{lineContext + 1} line, {buffer} + <{ch}> not implemented");
2025-07-03 21:50:26 +08:00
}
else
{
if ((buffer.Length > 0 && buffer.Last() == '\\') || ch != '"')
PushChar(ch);
else if (ch == '"')
EndString();
else
2025-07-04 21:39:02 +08:00
throw new NotImplementedException($"{lineContext + 1} line, \"{buffer}\" + \'{ch}\' not implemented");
2025-07-03 21:50:26 +08:00
}
}
void CompleteSingleSymbol(char ch)
{
CompleteWord();
buffer = ch.ToString();
CompleteWord();
}
void PushChar(char ch)
{
buffer += ch;
}
void CompleteWord()
{
if (buffer.Length > 0)
{
2025-07-04 21:39:02 +08:00
if (ScriptWords.TryGetValue(lineContext, out var line) == false)
{
ScriptWords.Add(lineContext, line = new());
}
if (Internal.Keyword.Keywords.TryGetValue(buffer, out var keyword))
{
2025-07-04 23:00:41 +08:00
line.Add(line.Count + 1, keyword.Clone() as Internal.Variable);
2025-07-04 21:39:02 +08:00
}
else
{
2025-07-04 23:00:41 +08:00
line.Add(line.Count + 1, new ScriptWordVariable(buffer));
2025-07-04 21:39:02 +08:00
}
2025-07-03 21:50:26 +08:00
buffer = "";
}
}
void CompleteLine()
{
CompleteWord();
2025-07-04 21:39:02 +08:00
lineContext++; ;
2025-07-03 21:50:26 +08:00
}
void BeginString()
{
if (buffer.Length > 0)
throw new InvalidGrammarException($"String must start with nothing: {buffer}");
isOutOfStringline = false;
}
void EndString()
{
isOutOfStringline = true;
CompleteWord();
}
2025-07-04 21:39:02 +08:00
#endregion
#region Read Scope Words
2025-07-05 16:57:59 +08:00
public class KeywordEntry
{
public int line = 1;
public int wordIndex = 1;
public Dictionary<int, Dictionary<int, Variable>> Container = new();
public KeywordEntry(int line, int wordIndex)
{
this.line = line;
this.wordIndex = wordIndex;
}
}
2025-07-04 21:39:02 +08:00
public void CompleteScopeWord(SymbolizationContext rootContext)
{
2025-07-05 16:57:59 +08:00
Dictionary<Keyword, KeywordEntry> ScopeWords = new();
Keyword currentKey = null;
bool isNextKeyword = true;
2025-07-04 21:39:02 +08:00
foreach(var line in ScriptWords)
{
int wordCounter = 1;
2025-07-04 21:39:02 +08:00
foreach (var word in line.Value)
{
if (isNextKeyword)
2025-07-04 21:39:02 +08:00
{
if (word.Value is Keyword cky)
2025-07-04 21:39:02 +08:00
{
currentKey = cky;
ScopeWords.Add(currentKey, new(line.Key, wordCounter));
isNextKeyword = false;
2025-07-04 21:39:02 +08:00
}
else
{
2025-07-05 16:57:59 +08:00
throw new InvalidGrammarException($"Line {line.Key}, Word {wordCounter}: Expected a keyword, but got {word.Value}");
2025-07-04 21:39:02 +08:00
}
}
else
{
var container = ScopeWords[currentKey].Container;
if (container.ContainsKey(line.Key) == false)
container.Add(line.Key, new() { { wordCounter, word.Value } });
else
container[line.Key][wordCounter] = word.Value;
isNextKeyword = currentKey.ControlScope(rootContext, line.Key, word.Key, word.Value) == false;
2025-07-04 21:39:02 +08:00
}
wordCounter++;
}
}
}
#endregion
2025-07-03 21:50:26 +08:00
}
}