diff --git a/Convention/[Symbolization]/Detail/Keyword.cs b/Convention/[Symbolization]/Detail/Keyword.cs index 9e086d4..4b9e6ae 100644 --- a/Convention/[Symbolization]/Detail/Keyword.cs +++ b/Convention/[Symbolization]/Detail/Keyword.cs @@ -6,104 +6,87 @@ namespace Convention.Symbolization.Internal { public abstract class Keyword : CloneableVariable { - protected Keyword(string keyword) : base(keyword) - { - Keywords.TryAdd(keyword, this); - } + protected Keyword(string keyword) : base(keyword) { } - public static readonly Dictionary Keywords = new(); + public static readonly Dictionary Keywords = new() + { + { "import", new Convention.Symbolization.Keyword.Import() }, + { "namespace", new Convention.Symbolization.Keyword.Namespace() }, + { "def", new Convention.Symbolization.Keyword.FunctionDef() }, + { "return", new Convention.Symbolization.Keyword.Return() }, + { "if", new Convention.Symbolization.Keyword.If() }, + { "elif", new Convention.Symbolization.Keyword.Elif() }, + { "else", new Convention.Symbolization.Keyword.Else() }, + { "while", new Convention.Symbolization.Keyword.While() }, + { "break", new Convention.Symbolization.Keyword.Break() }, + { "continue", new Convention.Symbolization.Keyword.Continue() }, + { "struct", new Convention.Symbolization.Keyword.Structure() } + }; public override bool Equals(Keyword other) { return this.GetType() == other.GetType(); } - public virtual Keyword ControlContext(SymbolizationContext context, int line, int wordIndex, Variable next) + public virtual bool ControlScope(SymbolizationContext context, int line, int wordIndex, Variable next) { - return ControlContext(context, next); + return ControlScope(context, next); } - protected virtual Keyword ControlContext(SymbolizationContext context, Variable next) + protected virtual bool ControlScope(SymbolizationContext context, Variable next) { - return null; + return true; } } public abstract class Keyword : Keyword where T : Keyword, new() { - private static T MyInstance = new(); - - protected Keyword(string keyword) : base(keyword) - { - } + protected Keyword(string keyword) : base(keyword) { } public override bool Equals(Variable other) { - return MyInstance == other; + return other is T; + } + + public override Keyword CloneVariable(string targetSymbolName) + { + return new T(); } } - } namespace Convention.Symbolization.Keyword { - /// - /// file - /// - public sealed class Import : Internal.Keyword + public abstract class SingleKeyword : Internal.Keyword where T : SingleKeyword, new() { - public Import() : base("import") + protected SingleKeyword(string keyword) : base(keyword) { } - - public override Internal.Keyword CloneVariable(string targetSymbolName) + protected override bool ControlScope(SymbolizationContext context, Internal.Variable next) { - return new Import(); - } - - private ToolFile ImportFile = new("./"); - private string buffer = ""; - - protected override Internal.Keyword ControlContext(SymbolizationContext context, Internal.Variable next) - { - if (next is not Internal.ScriptWordVariable swv) - { - throw new InvalidGrammarException($"Not expected a key word: {next}"); - } - if (swv.word == ";") - { - var importContext = new SymbolizationContext(context); - importContext.Compile(ImportFile); - return null; - } - else if (swv.word == ".") - { - ImportFile = ImportFile | buffer; - buffer = ""; - if (ImportFile.Exists() == false) - throw new FileNotFoundException($"File path not found: {ImportFile}", ImportFile); - } - else - { - buffer += swv.word; - } - return this; + if (next is not Internal.ScriptWordVariable swv ||swv.word!=";") + throw new InvalidGrammarException($"Expected ';' but got {next}"); + return true; } } - /// - /// name { ... } - /// - public sealed class Namespace : Internal.Keyword + public abstract class SentenceKeyword : Internal.Keyword where T : SentenceKeyword, new() { - public Namespace() : base("namespace") + protected SentenceKeyword(string keyword) : base(keyword) { } - - public override Internal.Keyword CloneVariable(string targetSymbolName) + protected override bool ControlScope(SymbolizationContext context, Internal.Variable next) { - return new Namespace(); + if (next is not Internal.ScriptWordVariable swv) + throw new InvalidGrammarException($"Not expected a key word: {next}"); + return swv.word != ";"; } + } + public abstract class NamespaceKeyword : Internal.Keyword where T : NamespaceKeyword, new() + { + protected NamespaceKeyword(string keyword) : base(keyword) + { + } private enum Pause { Name, Body @@ -111,50 +94,134 @@ namespace Convention.Symbolization.Keyword private Pause pause = Pause.Name; private int layer = 0; - private SymbolizationContext bulidingContext = null; - private Dictionary> subScriptWords = new(); - public override Internal.Keyword ControlContext(SymbolizationContext context,int line,int wordIndex, Internal.Variable next) + protected override bool ControlScope(SymbolizationContext context, Internal.Variable next) { - if (next is not Internal.ScriptWordVariable swv) - { - throw new InvalidGrammarException($"Not expected a key word: {next}"); - } if (pause == Pause.Name) { - bulidingContext = new(context, context.CurrentNamespace.CreateOrGetSubNamespace(swv.word)); - bulidingContext.CurrentNamespace.BeginUpdate(); - pause = Pause.Body; - } - else - { - if (swv.word == "{") - layer++; - else if (swv.word == "}") - layer--; - if (layer == 0) + if (next is Internal.ScriptWordVariable swv) { - bulidingContext.Compile(subScriptWords); - bulidingContext.CurrentNamespace.EndAndTryApplyUpdate(); - return null; + if (swv.word == "{") + { + pause = Pause.Body; + layer++; + } + return true; } else { - if (subScriptWords.TryGetValue(line, out var rline) == false) - { - subScriptWords.Add(line, rline = new()); - } - rline.Add(wordIndex, next); + throw new InvalidGrammarException($"Expected a script word variable for namespace name, but got {next}"); } } - return this; + else + { + if (next is Internal.ScriptWordVariable swv) + { + if (swv.word == "{") + layer++; + else if (swv.word == "}") + layer--; + if (layer == 0) + { + return false; + } + } + return true; + } + } + } + + public abstract class VerbObjectScopeKeyword : Internal.Keyword where T : VerbObjectScopeKeyword, new() + { + protected VerbObjectScopeKeyword(string keyword) : base(keyword) + { + } + + private enum Pause + { + BeforeExpression, Expression, BeforeBody, Body, SingleSentence + } + + private Pause pause = Pause.BeforeExpression; + private int layer = 0; + + protected override bool ControlScope(SymbolizationContext context, Internal.Variable next) + { + if (pause == Pause.BeforeExpression) + { + if (next is not Internal.ScriptWordVariable swv) + throw new InvalidGrammarException($"Not expected a key word: {next}"); + if (swv.word == "(") + pause = Pause.Expression; + else + throw new InvalidGrammarException($"Expected '(' symbol for expression start, but got {next}"); + } + else if (pause == Pause.Expression) + { + if (next is Internal.ScriptWordVariable swv && swv.word == ")") + { + pause = Pause.BeforeBody; + } + } + else if (pause == Pause.BeforeBody) + { + if (next is not Internal.ScriptWordVariable swv) + throw new InvalidGrammarException($"Not expected keyword for body start, but got {next}"); + if (swv.word == "{") + { + pause = Pause.Body; + layer++; + } + else + pause = Pause.SingleSentence; + } + else if (pause == Pause.Body) + { + if (next is Internal.ScriptWordVariable swv) + { + if (swv.word == "{") + layer++; + else if (swv.word == "}") + layer--; + if (layer == 0) + return false; + } + } + else if (pause == Pause.SingleSentence) + { + if (next is Internal.ScriptWordVariable swv && swv.word == ";") + { + return false; + } + } + return true; + } + } + + /// + /// file + /// + public sealed class Import : SentenceKeyword + { + public Import() : base("import") + { + } + } + + /// + /// name { ... } + /// + public sealed class Namespace : NamespaceKeyword + { + public Namespace() : base("namespace") + { } } /// /// FunctionName(parameter-list) return-type { ... return return-type-instance; } /// - public sealed class FunctionDef : Internal.Keyword + public sealed class FunctionDef : NamespaceKeyword { public FunctionDef() : base("def") { @@ -164,7 +231,7 @@ namespace Convention.Symbolization.Keyword /// /// symbol; /// - public sealed class Return : Internal.Keyword + public sealed class Return : SentenceKeyword { public Return() : base("return") { @@ -174,7 +241,7 @@ namespace Convention.Symbolization.Keyword /// /// (bool-expression) expression /// - public sealed class If : Internal.Keyword + public sealed class If : VerbObjectScopeKeyword { public If() : base("if") { @@ -182,9 +249,21 @@ namespace Convention.Symbolization.Keyword } /// - /// expression expression + /// expression expression + /// expression expression expression... /// - public sealed class Else : Internal.Keyword + public sealed class Elif : VerbObjectScopeKeyword + { + public Elif() : base("elif") + { + } + } + + /// + /// expression expression + /// expression expression... expression + /// + public sealed class Else : NamespaceKeyword { public Else() : base("else") { @@ -194,7 +273,7 @@ namespace Convention.Symbolization.Keyword /// /// (bool-expression) expression /// - public sealed class While : Internal.Keyword + public sealed class While : VerbObjectScopeKeyword { public While() : base("while") { @@ -204,7 +283,7 @@ namespace Convention.Symbolization.Keyword /// /// ; /// - public sealed class Break : Internal.Keyword + public sealed class Break : SingleKeyword { public Break() : base("break") { @@ -214,7 +293,7 @@ namespace Convention.Symbolization.Keyword /// /// ; /// - public sealed class Continue : Internal.Keyword + public sealed class Continue : SingleKeyword { public Continue() : base("continue") { @@ -224,7 +303,7 @@ namespace Convention.Symbolization.Keyword /// /// structureName { ... } /// - public sealed class Structure : Internal.Keyword + public sealed class Structure : NamespaceKeyword { public Structure() : base("struct") { diff --git a/Convention/[Symbolization]/Runner/SymbolizationContext.cs b/Convention/[Symbolization]/Runner/SymbolizationContext.cs index 4f4b204..d665dae 100644 --- a/Convention/[Symbolization]/Runner/SymbolizationContext.cs +++ b/Convention/[Symbolization]/Runner/SymbolizationContext.cs @@ -20,9 +20,9 @@ namespace Convention.Symbolization public void Compile(Dictionary> scriptWords) { + new Internal.SymbolizationReader() { ScriptWords = scriptWords }.CompleteScopeWord(this); } - public void Compile(string allText) { // Create a new reader to parse the script words @@ -31,7 +31,7 @@ namespace Convention.Symbolization reader.ReadChar(ch); var scriptWords = reader.ScriptWords; // Turn the script words into scope words - this.Compile(scriptWords); + reader.CompleteScopeWord(this); } public void Compile(ToolFile file) diff --git a/Convention/[Symbolization]/Runner/SymbolizationReader.cs b/Convention/[Symbolization]/Runner/SymbolizationReader.cs index 4eb9f57..2b6cbc4 100644 --- a/Convention/[Symbolization]/Runner/SymbolizationReader.cs +++ b/Convention/[Symbolization]/Runner/SymbolizationReader.cs @@ -106,28 +106,50 @@ namespace Convention.Symbolization.Internal #region Read Scope Words + private class KeywordEntry + { + public int line = 1; + public int wordIndex = 1; + public Dictionary> Container = new(); + public KeywordEntry(int line, int wordIndex) + { + this.line = line; + this.wordIndex = wordIndex; + } + } + + private Dictionary ScopeWords = new(); + public void CompleteScopeWord(SymbolizationContext rootContext) { - int wordCounter = 1; - Internal.Keyword currentKey = null; + Keyword currentKey = null; + bool isNextKeyword = true; foreach(var line in ScriptWords) { + int wordCounter = 1; foreach (var word in line.Value) { - if (currentKey == null) + if (isNextKeyword) { - if(currentKey is Internal.Keyword cky) + if (word.Value is Keyword cky) { currentKey = cky; + ScopeWords.Add(currentKey, new(line.Key, wordCounter)); + isNextKeyword = false; } else { - throw new InvalidGrammarException($"Line {line.Key}, word {wordCounter}: Expected a keyword, but got {word}"); + throw new InvalidGrammarException($"Line {line.Key}, word {wordCounter}: Expected a keyword, but got {word.Value}"); } } else { - currentKey = currentKey.ControlContext(rootContext, line.Key, word.Key, word.Value); + 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; } wordCounter++; }