diff --git a/YangParser/SemanticModel/BelongsTo.cs b/YangParser/SemanticModel/BelongsTo.cs new file mode 100644 index 0000000..de285f1 --- /dev/null +++ b/YangParser/SemanticModel/BelongsTo.cs @@ -0,0 +1,24 @@ +using YangParser.Parser; + +namespace YangParser.SemanticModel; + +public class BelongsTo : Statement +{ + public BelongsTo(YangStatement statement) : base(statement) + { + if (statement.Keyword != Keyword) + throw new SemanticError($"Non-matching Keyword '{statement.Keyword}', expected {Keyword}", statement); + } + + public const string Keyword = "belongs-to"; + + public override ChildRule[] PermittedChildren { get; } = + [ + new ChildRule(Prefix.Keyword, Cardinality.Required) + ]; + + public override string ToCode() + { + return string.Empty; + } +} \ No newline at end of file diff --git a/YangParser/SemanticModel/DefaultValue.cs b/YangParser/SemanticModel/DefaultValue.cs index 482542a..816c0b6 100644 --- a/YangParser/SemanticModel/DefaultValue.cs +++ b/YangParser/SemanticModel/DefaultValue.cs @@ -24,7 +24,7 @@ public override string ToCode() return GetTypeSpecification(prefix, value, type); } - private string GetTypeSpecification(string prefix, string value, Type type) + private string GetTypeSpecification(string prefix, string value, Type type, bool chained = false) { if (string.IsNullOrEmpty(value)) { @@ -54,10 +54,10 @@ private string GetTypeSpecification(string prefix, string value, Type type) case "decimal64": return Argument; case "union": - if (onlyNumbers.Match(Argument).Success) - { - return $"new({Argument})"; - } + // if (onlyNumbers.Match(Argument).Success) + // { + // return $"new({Argument})"; + // } var enumeration = type.SearchDownwards(Argument); if (enumeration != null) @@ -73,7 +73,7 @@ private string GetTypeSpecification(string prefix, string value, Type type) foreach (var subType in type.Children.OfType()) { - var possible = GetTypeSpecification(prefix, value, subType); + var possible = GetTypeSpecification(prefix, value, subType, true); if (possible != $"new(\"{Argument}\")") { if (possible == $"\"{Argument}\"") @@ -81,7 +81,14 @@ private string GetTypeSpecification(string prefix, string value, Type type) return $"new(\"{Argument}\")"; } - return possible == Argument ? $"new({Argument})" : possible; + if (BuiltinTypeReference.IsBuiltin(subType, out var typeName, out _)) + { + return chained + ? "new(" + possible + $"/*{typeName}*/" + ")" + : possible + $"/*{typeName}*/"; + } + + return "new(new " + MakeName(subType.Argument) + "(" + possible + "))"; } } @@ -96,16 +103,16 @@ private string GetTypeSpecification(string prefix, string value, Type type) prefix = type.Argument.Prefix(out _); } - return GetTypeSpecification(prefix, value, source.GetChild()); + return GetTypeSpecification(prefix, value, source.GetChild(), true); } if (onlyNumbers.Match(Argument).Success) { - return $"new({Argument})"; + return $"new(/*{type.Argument}*/{Argument})"; } Log.Write($"Fallback for 'default {Argument}' to type {type}"); - return $"new(\"{Argument}\")"; + return $"new(/*{type.Argument}*/\"{Argument}\")"; } } diff --git a/YangParser/SemanticModel/Extension.cs b/YangParser/SemanticModel/Extension.cs index f5c37df..64ca730 100644 --- a/YangParser/SemanticModel/Extension.cs +++ b/YangParser/SemanticModel/Extension.cs @@ -25,18 +25,24 @@ public Extension(YangStatement statement) : base(statement) public override string ToCode() { var arg = Children.FirstOrDefault(child => child is Argument); - var argStr = arg is null + var vargName = arg?.Argument; + if (vargName == Argument) + { + if (Argument != "value") vargName = "value"; + else vargName = "_" + vargName; + } + + var argStr = vargName is null ? string.Empty : $$""" - public string {{MakeName(arg.Argument)}} { get; set; } - public {{MakeName(Argument)}}Attribute(string {{MakeName(arg.Argument)}}) + public string {{MakeName(vargName)}} { get; set; } + public {{MakeName(Argument)}}(string {{MakeName(vargName)}}) { - this.{{MakeName(arg.Argument)}} = {{MakeName(arg.Argument)}}; + this.{{MakeName(vargName)}} = {{MakeName(vargName)}}; } """; return $$""" - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public class {{MakeName(Argument)}}Attribute : Attribute + public class {{MakeName(Argument)}} { {{Indent(argStr)}} } diff --git a/YangParser/SemanticModel/ExtensionReference.cs b/YangParser/SemanticModel/ExtensionReference.cs new file mode 100644 index 0000000..1663bfc --- /dev/null +++ b/YangParser/SemanticModel/ExtensionReference.cs @@ -0,0 +1,59 @@ +using System.Linq; +using YangParser.Parser; + +namespace YangParser.SemanticModel; + +public class ExtensionReference : Statement +{ + public ExtensionReference(YangStatement statement) : base(statement, false) + { + SourceModulePrefix = statement.Prefix; + ExtensionName = statement.Keyword; + Argument = statement.Argument?.ToString() ?? string.Empty; + } + + public string ExtensionName { get; } + + public string SourceModulePrefix { get; } + + public override string ToCode() + { + var sourceModule = this.FindSourceFor(SourceModulePrefix); + var source = sourceModule?.Extensions.FirstOrDefault(e => e.Argument == ExtensionName); + if (source is null) + { + throw new SemanticError( + $"Could not find source extension for {SourceModulePrefix}:{ExtensionName} in module {sourceModule}", + Source); + } + + var children = Children.Select(c => c.ToCode()).ToArray(); + var inheritance = string.IsNullOrWhiteSpace(SourceModulePrefix) + ? MakeName(ExtensionName) + : SourceModulePrefix + ':' + MakeName(ExtensionName); + var classNameSource = Argument.Contains('/') ? ExtensionName + Argument.GetHashCode() : Argument; + if (source.TryGetChild(out _)) + { + return $$""" + public {{MakeName(classNameSource)}}Extension {{MakeName(classNameSource)}}ExtensionValue { get; } + {{DescriptionString}}{{AttributeString}} + public class {{MakeName(classNameSource)}}Extension : {{inheritance}} + { + public {{MakeName(classNameSource)}}Extension() : base("{{SingleLine(Argument).Replace("\n", "\\\n")}}") + { + } + {{Indent(string.Join("\n", children))}} + } + """; + } + + return $$""" + public {{MakeName(classNameSource)}}Extension {{MakeName(classNameSource)}}ExtensionValue { get; } + {{DescriptionString}}{{AttributeString}} + public class {{MakeName(classNameSource)}}Extension : {{inheritance}} + { + {{Indent(string.Join("\n", children))}} + } + """; + } +} \ No newline at end of file diff --git a/YangParser/SemanticModel/Module.cs b/YangParser/SemanticModel/Module.cs index b546573..ab9cc4f 100644 --- a/YangParser/SemanticModel/Module.cs +++ b/YangParser/SemanticModel/Module.cs @@ -55,6 +55,11 @@ public Module(YangStatement statement) : base(statement) typeDefinition.Parent?.Replace(typeDefinition, []); } } + + if (child is Extension extension) + { + Extensions.Add(extension); + } } } @@ -187,6 +192,7 @@ private void ExpandPrefixes(IStatement statement) public List Groupings { get; } = []; public List Augments { get; } = []; public List Imports { get; } = []; + public List Extensions { get; } = []; public List HiddenDefinitions { get; } = []; // public string Capability @@ -213,5 +219,6 @@ public interface ITopLevelStatement : IStatement public List Groupings { get; } public List Augments { get; } public List Imports { get; } + public List Extensions { get; } Dictionary ImportedModules { get; } } \ No newline at end of file diff --git a/YangParser/SemanticModel/Statement.cs b/YangParser/SemanticModel/Statement.cs index e319716..b458565 100644 --- a/YangParser/SemanticModel/Statement.cs +++ b/YangParser/SemanticModel/Statement.cs @@ -76,7 +76,7 @@ public static string MakeName(string argument) var prefix = argument.Prefix(out var value); var addColon = !prefix.Contains('.') && !string.IsNullOrWhiteSpace(prefix); - foreach (var section in value.Split('-', ' ', '/', '.')) + foreach (var section in value.Split('-', ' ', '/', '.','^')) { output.Append(Capitalize(section)); } diff --git a/YangParser/SemanticModel/StatementFactory.cs b/YangParser/SemanticModel/StatementFactory.cs index c5777a9..8aac08e 100644 --- a/YangParser/SemanticModel/StatementFactory.cs +++ b/YangParser/SemanticModel/StatementFactory.cs @@ -4,24 +4,13 @@ namespace YangParser.SemanticModel; -public class KeywordReference : Statement -{ - public KeywordReference(YangStatement statement) : base(statement, false) - { - ReferenceNamespace = statement.Prefix; - Argument = statement.Argument?.ToString() ?? string.Empty; - } - - public string ReferenceNamespace { get; set; } -} - public static class StatementFactory { public static IStatement Create(YangStatement source) { if (!string.IsNullOrWhiteSpace(source.Prefix)) { - return new KeywordReference(source); + return new ExtensionReference(source); } return source.Keyword switch diff --git a/YangParser/SemanticModel/Submodule.cs b/YangParser/SemanticModel/Submodule.cs index 7459fdd..c6ca0b4 100644 --- a/YangParser/SemanticModel/Submodule.cs +++ b/YangParser/SemanticModel/Submodule.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using YangParser.Generator; @@ -9,6 +8,7 @@ namespace YangParser.SemanticModel; public class Submodule : Statement, ITopLevelStatement { public Dictionary ImportedModules { get; } = []; + public Submodule(YangStatement statement) : base(statement) { if (statement.Keyword != Keyword) @@ -20,14 +20,17 @@ public Submodule(YangStatement statement) : base(statement) { Uses.Add(use); } + if (child is Grouping grouping) { Groupings.Add(grouping); } + if (child is Augment augment) { Augments.Add(augment); } + if (child is Import import) { Imports.Add(import); @@ -36,6 +39,7 @@ public Submodule(YangStatement statement) : base(statement) Usings[prefix] = reference; ImportedModules[prefix] = import.Argument; } + if (child is TypeDefinition typeDefinition) { if (typeDefinition.IsUnderGrouping()) @@ -44,11 +48,17 @@ public Submodule(YangStatement statement) : base(statement) typeDefinition.Parent?.Replace(typeDefinition, []); } } + + if (child is Extension extension) + { + Extensions.Add(extension); + } } } public List HiddenDefinitions { get; } = []; private bool IsExpanded = false; + public void Expand() { if (IsExpanded) return; @@ -56,6 +66,7 @@ public void Expand() { ExpandPrefixes(child); } + IsExpanded = true; } @@ -100,11 +111,12 @@ public override string ToCode() private void ExpandPrefixes(IStatement statement) { - if (!statement.Argument.Contains(" ")) { var argPrefix = statement.Argument.Split(':'); - if (argPrefix.Length > 1 && argPrefix.Length < 3) //ignore cases where there are multiple colons, since that's an XML-namespace reference + if (argPrefix.Length > 1 && + argPrefix.Length < + 3) //ignore cases where there are multiple colons, since that's an XML-namespace reference { if (Usings.ContainsKey(argPrefix[0])) { @@ -116,30 +128,16 @@ private void ExpandPrefixes(IStatement statement) } } } + foreach (var child in statement.Children) { ExpandPrefixes(child); } } + public List Uses { get; } = []; public List Groupings { get; } = []; public List Augments { get; } = []; + public List Extensions { get; } = []; public List Imports { get; } = []; - -} - -public class BelongsTo : Statement -{ - public BelongsTo(YangStatement statement) : base(statement) - { - if (statement.Keyword != Keyword) - throw new SemanticError($"Non-matching Keyword '{statement.Keyword}', expected {Keyword}", statement); - } - - public const string Keyword = "belongs-to"; - - public override ChildRule[] PermittedChildren { get; } = - [ - new ChildRule(Prefix.Keyword, Cardinality.Required) - ]; } \ No newline at end of file