using System; using System.IO; using System.Collections.Generic; namespace Convention.Symbolization.Internal { public abstract class Keyword : CloneableVariable { protected Keyword(string keyword) : base(keyword) { } 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 bool ControlScope(SymbolizationContext context, int line, int wordIndex, Variable next) { return ControlScope(context, next); } protected virtual bool ControlScope(SymbolizationContext context, Variable next) { return true; } } public abstract class Keyword : Keyword where T : Keyword, new() { protected Keyword(string keyword) : base(keyword) { } public override bool Equals(Variable other) { return other is T; } public override Keyword CloneVariable(string targetSymbolName) { return new T(); } } } namespace Convention.Symbolization.Keyword { public abstract class SingleKeyword : Internal.Keyword where T : SingleKeyword, new() { protected SingleKeyword(string keyword) : base(keyword) { } protected override bool ControlScope(SymbolizationContext context, Internal.Variable next) { if (next is not Internal.ScriptWordVariable swv ||swv.word!=";") throw new InvalidGrammarException($"Expected ';' but got {next}"); return true; } } public abstract class SentenceKeyword : Internal.Keyword where T : SentenceKeyword, new() { protected SentenceKeyword(string keyword) : base(keyword) { } 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}"); return swv.word != ";"; } } public abstract class NamespaceKeyword : Internal.Keyword where T : NamespaceKeyword, new() { protected NamespaceKeyword(string keyword) : base(keyword) { } private enum Pause { Name, Body } private Pause pause = Pause.Name; private int layer = 0; protected override bool ControlScope(SymbolizationContext context, Internal.Variable next) { if (pause == Pause.Name) { if (next is Internal.ScriptWordVariable swv) { if (swv.word == "{") { pause = Pause.Body; layer++; } return true; } else { throw new InvalidGrammarException($"Expected a script word variable for namespace name, but got {next}"); } } 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 : NamespaceKeyword { public FunctionDef() : base("def") { } } /// /// symbol; /// public sealed class Return : SentenceKeyword { public Return() : base("return") { } } /// /// (bool-expression) expression /// public sealed class If : VerbObjectScopeKeyword { public If() : base("if") { } } /// /// expression expression /// expression expression expression... /// public sealed class Elif : VerbObjectScopeKeyword { public Elif() : base("elif") { } } /// /// expression expression /// expression expression... expression /// public sealed class Else : NamespaceKeyword { public Else() : base("else") { } } /// /// (bool-expression) expression /// public sealed class While : VerbObjectScopeKeyword { public While() : base("while") { } } /// /// ; /// public sealed class Break : SingleKeyword { public Break() : base("break") { } } /// /// ; /// public sealed class Continue : SingleKeyword { public Continue() : base("continue") { } } /// /// structureName { ... } /// public sealed class Structure : NamespaceKeyword { public Structure() : base("struct") { } } }