我有一些像Foo.<Whatever>.$(Something)
这样的定义格式的字符串,我想将它们分成几部分并将每个部分自动分配给变量。
我曾经写过一些类似于bash / shell管道命令选项&#39;&lt;&#39;使用C#类和运算符重载。用法类似于
ParseExpression ex = pex("item1") > ".<" > pex("item2") > ">.$(" > pex("item3") > ")";
ParseResult r = new ParseResult(ex, "Foo.<Whatever>.$(Something)");
ParseResult
然后有一个字典,键item1到item3设置为在给定字符串中找到的字符串。方法pex
生成了一些可以与&gt;一起使用的对象。运算符,最终有一个ParseExpressionParts链,它构成ParseExpression
。
我暂时没有手头的代码,在我再次从头开始编码之前,我想我最好先问一下是否已经完成并发布了它。
答案 0 :(得分:1)
解析表达式让我想起parser combinators,如Parsec和FParsec(对于F#)。语法有多复杂?实际上,它可以由具有组的正则表达式来处理。
如果你想使用解析器组合器创建一个更复杂的语法,你可以使用FParsec,这是一个比较着名的解析器组合,以F#为目标。通常,像F#这样的函数语言在这种情况下会被大量使用。 CSharp-monad是一个针对C#的解析器组合器。该项目虽然不是很活跃。
您还可以使用像ANTLR 4这样的完整解析器生成器。 ASP.NET MVC使用ANTLR来解析Razor语法视图。 ANTLR 4创建一个解析树,允许您使用Visitor或Listener来处理它类似于DOM或SAX处理。一个元素遇到时,Listener会立即调用您的代码(例如,开头{{1} },内容等),而访问者在完成的树上工作。
ANTLR的Visual Studio扩展将生成解析器类以及语法的基本访问者和监听器类。基于NetBeans的ANTLRWorks IDE可以非常轻松地创建和测试语法。
你的例子的粗略语法是:
<
或者您可以定义像format: tag '.' '<' category '>' '.' '$' '(' value ')';
tag : ID;
category : ID;
value : ID;
ID :[A-Z0-9]+;
这样对您的语法有特殊含义的关键字。访问者或监听者可以处理标记,例如格式化字符串,对值等执行操作。
没有严格的规则。就个人而言,我使用正则表达式来处理更简单的情况,例如处理相对简单的日志文件和ANTLR以处理更复杂的情况,例如屏幕抓取大型机数据。我没有看过解析器组合器,因为我没有时间适应F#。虽然处理一些混乱的log4net日志文件,但它们真的很方便
答案 1 :(得分:1)
我从Heinzi的建议开始,最终想出了以下代码:
const string tokenPrefix = "px";
const string tokenSuffix = "sx";
const string tokenVar = "var";
string r = string.Format(@"(?<{0}>.*)\$\((?<{1}>.*)\)(?<{2}>.*)",
tokenPrefix, tokenVar, tokenSuffix);
Regex regex = new Regex(r);
Match match = regex.Match("Foo$(Something)Else");
if (match.Success)
{
string prefix = match.Groups[tokenPrefix].Value; // = "Foo"
string suffix = match.Groups[tokenSuffix].Value; // = "Something"
string variable = match.Groups[tokenVar].Value; // = "Else"
}
在与同事讨论此事后,我被告知要考虑使用名为"Sprache"的C#解析器协同库(这是正则表达式和类似ANTLR的工具集之间的东西),当我的模式使用增加并且我想要更好可维护性。