Add "!add" bang
This commit is contained in:
parent
c93864c7e4
commit
f4a563a9d4
@ -25,5 +25,7 @@ namespace XNeedle
|
||||
|
||||
public SourceLocation WithLineNumber(int lineNumber) =>
|
||||
new SourceLocation(FilePath, Encoding, lineNumber);
|
||||
public SourceLocation AsSynthetic() =>
|
||||
new SourceLocation("<synthetic>", Encoding, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,9 @@ namespace XNeedle
|
||||
|
||||
static void RunOptions(Options opts)
|
||||
{
|
||||
// Auto-discover operations via reflection
|
||||
BangOperation.RegisterAll();
|
||||
|
||||
var masterRule = (Rule)XnParser.RuleObject.Parse(File.ReadAllText(opts.XnDefinition));
|
||||
var doc = XDocument.Load(opts.Input, LoadOptions.PreserveWhitespace);
|
||||
var encoding = XmlRoundtripWriter.DetectEncoding(File.ReadAllBytes(opts.Input));
|
||||
|
||||
31
Transformation/Bang.cs
Normal file
31
Transformation/Bang.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using XNeedle;
|
||||
using XNeedle.Parser.Elements;
|
||||
|
||||
namespace XNeedle.Transformation
|
||||
{
|
||||
public class Bang : Part
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public required IEnumerable<string> Arguments;
|
||||
public required IEnumerable<Part> Body;
|
||||
public override void Operate(Context ctx)
|
||||
{
|
||||
var bangop = BangOperation.Resolve(Name);
|
||||
if (bangop == null)
|
||||
{
|
||||
throw new ArgumentException($"!{Name} is not a valid bang.");
|
||||
}
|
||||
|
||||
var bodyctx = bangop.Execute(ctx, Arguments);
|
||||
Console.WriteLine($"Operate Bang: {Name}, {string.Join(",", Arguments)}");
|
||||
foreach (var b in Body)
|
||||
{
|
||||
b.Operate(bodyctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Transformation/BangOperation.cs
Normal file
31
Transformation/BangOperation.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using XNeedle.Parser.Elements;
|
||||
|
||||
namespace XNeedle.Transformation
|
||||
{
|
||||
public abstract class BangOperation
|
||||
{
|
||||
private static readonly Dictionary<string, BangOperation> Registry = new();
|
||||
|
||||
public abstract string Name { get; }
|
||||
|
||||
protected BangOperation()
|
||||
{
|
||||
Registry[Name] = this;
|
||||
}
|
||||
|
||||
public abstract Context Execute(Context ctx, IEnumerable<string> arguments);
|
||||
|
||||
public static BangOperation? Resolve(string name) =>
|
||||
Registry.TryGetValue(name, out var op) ? op : null;
|
||||
|
||||
public static void RegisterAll()
|
||||
{
|
||||
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
|
||||
if (!type.IsAbstract && type.IsSubclassOf(typeof(BangOperation)))
|
||||
Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Transformation/Bangs/AddBang.cs
Normal file
28
Transformation/Bangs/AddBang.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Xml.Linq;
|
||||
using XNeedle.Parser.Elements;
|
||||
|
||||
namespace XNeedle.Transformation.Bangs
|
||||
{
|
||||
public class AddBang : BangOperation
|
||||
{
|
||||
public override string Name => "add";
|
||||
|
||||
public override Context Execute(Context ctx, IEnumerable<string> arguments)
|
||||
{
|
||||
if (ctx.Node == null)
|
||||
{
|
||||
throw new ArgumentNullException("!add needs a reachable node");
|
||||
}
|
||||
if (arguments.Count() < 1)
|
||||
{
|
||||
throw new ArgumentException("!add needs at least the tag name as argument.");
|
||||
}
|
||||
|
||||
var tagname = arguments.ElementAt(0);
|
||||
var element = new XElement(tagname, "");
|
||||
ctx.Node.Add(element);
|
||||
|
||||
return new Context{ Node = element, SLoc = ctx.SLoc.AsSynthetic(), XPathSelector = tagname};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,8 @@ using Sprache;
|
||||
using XNeedle.Formats;
|
||||
using XNeedle.Parser;
|
||||
using XNeedle.Parser.Elements;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
|
||||
namespace XNeedle.Transformation
|
||||
{
|
||||
@ -19,7 +21,7 @@ namespace XNeedle.Transformation
|
||||
public static double GetLevel(Context ctx)
|
||||
{
|
||||
int level = 0;
|
||||
System.Xml.Linq.XElement? n = ctx.Node;
|
||||
XElement? n = ctx.Node;
|
||||
while (null != (n = n?.Parent))
|
||||
level++;
|
||||
return level;
|
||||
@ -106,5 +108,28 @@ namespace XNeedle.Transformation
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string swap(Context ctx, string a_select, string b_select)
|
||||
{
|
||||
if (ctx.Node == null)
|
||||
{
|
||||
throw new ArgumentNullException("!seap needs a reachable node");
|
||||
}
|
||||
|
||||
var a_node = ctx.Node.XPathSelectElement(a_select);
|
||||
var b_node = ctx.Node.XPathSelectElement(b_select);
|
||||
|
||||
if (a_node == null || b_node == null)
|
||||
{
|
||||
throw new InvalidOperationException($"!swap could not find nodes for \"{a_select}\" and/or \"{b_select}\".");
|
||||
}
|
||||
|
||||
var placeholder = new XElement("__placeholder__");
|
||||
a_node.ReplaceWith(placeholder);
|
||||
b_node.ReplaceWith(a_node);
|
||||
placeholder.ReplaceWith(b_node);
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user