Add "!add" bang
This commit is contained in:
parent
c93864c7e4
commit
f4a563a9d4
@ -25,5 +25,7 @@ namespace XNeedle
|
|||||||
|
|
||||||
public SourceLocation WithLineNumber(int lineNumber) =>
|
public SourceLocation WithLineNumber(int lineNumber) =>
|
||||||
new SourceLocation(FilePath, Encoding, 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)
|
static void RunOptions(Options opts)
|
||||||
{
|
{
|
||||||
|
// Auto-discover operations via reflection
|
||||||
|
BangOperation.RegisterAll();
|
||||||
|
|
||||||
var masterRule = (Rule)XnParser.RuleObject.Parse(File.ReadAllText(opts.XnDefinition));
|
var masterRule = (Rule)XnParser.RuleObject.Parse(File.ReadAllText(opts.XnDefinition));
|
||||||
var doc = XDocument.Load(opts.Input, LoadOptions.PreserveWhitespace);
|
var doc = XDocument.Load(opts.Input, LoadOptions.PreserveWhitespace);
|
||||||
var encoding = XmlRoundtripWriter.DetectEncoding(File.ReadAllBytes(opts.Input));
|
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.Formats;
|
||||||
using XNeedle.Parser;
|
using XNeedle.Parser;
|
||||||
using XNeedle.Parser.Elements;
|
using XNeedle.Parser.Elements;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using System.Xml.XPath;
|
||||||
|
|
||||||
namespace XNeedle.Transformation
|
namespace XNeedle.Transformation
|
||||||
{
|
{
|
||||||
@ -19,7 +21,7 @@ namespace XNeedle.Transformation
|
|||||||
public static double GetLevel(Context ctx)
|
public static double GetLevel(Context ctx)
|
||||||
{
|
{
|
||||||
int level = 0;
|
int level = 0;
|
||||||
System.Xml.Linq.XElement? n = ctx.Node;
|
XElement? n = ctx.Node;
|
||||||
while (null != (n = n?.Parent))
|
while (null != (n = n?.Parent))
|
||||||
level++;
|
level++;
|
||||||
return level;
|
return level;
|
||||||
@ -106,5 +108,28 @@ namespace XNeedle.Transformation
|
|||||||
}
|
}
|
||||||
return "";
|
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