我正在使用Sprache monadic解析器来解析DSL.
这是我的语法片段:
public static readonly Parser<IExpression> TerminatedStatement =
from exp in Parse.Ref(() => Expression)
from _ in Parse.Char(';').Token()
select exp;
public static readonly Parser<IExpression> Statement =
Parse.Ref(() => TerminatedStatement)
.Or(Parse.Ref(() => InvocationStatement));
public static readonly Parser<Statements> Statements =
from statements in Statement.Many()
select new Statements(statements);
Run Code Online (Sandbox Code Playgroud)
如果我然后使用它,Statements.Parse(" ")我得到一个例外,说输入意外结束.
如何Statements使用Many运算符,AFAIK产生0-n结果.
" "应该返回一个Statements包含0个语句的实例.
那么解析器如何抱怨意外结束输入呢?难道它只是得出结论,那里没有陈述?(不管构成语句的不同表达方式有什么时髦的东西)
我正在为类似于SQL的语言开发解析器,我遇到了创建一些语言规则的问题,例如:expression IS NULL和expression IN (expression1, expression2, ...)逻辑和数学运算符之间的优先级.
我上传了一个GitHub测试项目https://github.com/anpv/SpracheTest/,但这个变种并不好.
我试图使用以下规则:
private static readonly Parser<AstNode> InOperator =
from expr in Parse.Ref(() => Expression)
from inKeyword in Parse.IgnoreCase("in").Token()
from values in Parse
.Ref(() => Expression)
.DelimitedBy(Comma)
.Contained(OpenParenthesis, CloseParenthesis)
select new InOperator(expr, values);
private static readonly Parser<AstNode> IsNullOperator =
from expr in Parse.Ref(() => Expression)
from isNullKeyword in Parse
.IgnoreCase("is")
.Then(_ => Parse.WhiteSpace.AtLeastOnce())
.Then(_ => Parse.IgnoreCase("null"))
select new IsNullOperator(expr);
private static readonly Parser<AstNode> Equality =
Parse
.ChainOperator(Eq, IsNullOperator.Or(InOperator).Or(Additive), …Run Code Online (Sandbox Code Playgroud) 我还没有找到一个例子 - 如何处理字符转义。我找到了一个代码示例:
static void Main(string[] args)
{
string text = "'test \\\' text'";
var result = Grammar.QuotedText.End().Parse(text);
}
public static class Grammar
{
private static readonly Parser<char> QuoteEscape = Parse.Char('\\');
private static Parser<T> Escaped<T>(Parser<T> following)
{
return from escape in QuoteEscape
from f in following
select f;
}
private static readonly Parser<char> QuotedTextDelimiter = Parse.Char('\'');
private static readonly Parser<char> QuotedContent =
Parse.AnyChar.Except(QuotedTextDelimiter).Or(Escaped(QuotedTextDelimiter));
public static Parser<string> QuotedText = (
from lquot in QuotedTextDelimiter
from content in QuotedContent.Many().Text()
from rquot in …Run Code Online (Sandbox Code Playgroud) 我正在使用 Sprache 构建一个简单的命令式语法。我试图找出是否有办法在缺少结束字符(例如]、)、} 时获得更好的错误报告。
如果缺少结束字符,我的语法会正确报告错误。然而,消息传递导致难以理解真正的问题。给定以下要解析的字符串:
sum 10 [multiply 5 4
sprache 报如下错误:
Sprache.ParseException : Parsing failure: unexpected '['; expected newline or end of input (Line 1, Column 8); recently consumed: sum 10
似乎正在发生的事情是解析器试图匹配 myCommandSubstitution并且未能找到结束的']'. 这会导致解析器回退并尝试替代。由于它无法再匹配Things命令,它会尝试匹配CommandTerminator. 因为它不能匹配 a'['它报告错误抱怨预期newline或end of input而不是说,“嘿,伙计,你没有匹配你的括号!”
是否有任何解决方法或建议可以说明如何使用像 Sprache 这样的解析库改进语法以更好地报告?
public static readonly Parser<Word> Word = Parse.Char(IsWordChar, "word character").AtLeastOnce().Text()
.Select(str => new Word(str));
public static readonly Parser<CommandSubstitution> CommandSubstitution = from open in Parse.Char('[').Once()
from …Run Code Online (Sandbox Code Playgroud) 我正在构建一个 Sprache 解析器来解析类似于 SQL 搜索条件的表达式。例如Property = 123或Property > AnotherProperty
到目前为止,这两个示例都有效,但是我正在努力弄清楚我需要做什么才能允许 ANDing/ORing 条件和括号。
到目前为止,基本上我有这个:
private static readonly Parser<string> Operators =
Parse.String("+").Or(Parse.String("-")).Or(Parse.String("="))
.Or(Parse.String("<")).Or(Parse.String(">"))
.Or(Parse.String("<=")).Or(Parse.String(">=")).Or(Parse.String("<>"))
.Text();
private static readonly Parser<IdentifierExpression> Identifier =
from first in Parse.Letter.Once()
from rest in Parse.LetterOrDigit.Many()
select new IdentifierExpression(first.Concat(rest).ToArray());
public static readonly Parser<Expression> Integer =
Parse.Number.Select(n => new IntegerExpression {Value = int.Parse(n)});
public static readonly Parser<SearchCondition> SearchCondition =
from left in Identifier.Or(Number)
from op in Operators.Token()
from right in Identifier.Or(Number)
select new SearchCondition { Left = …Run Code Online (Sandbox Code Playgroud) 我有一个报表服务器需要解析一个字符串,其中一些参数控制报表中的内容.
我正在使用解析器库sprache来帮助解决这个问题.一切都很好,除了我坚持的一件事.
我有一个时间过滤器,可以是以下值之一:今天,昨天,上周,上个月,无或自定义.
这是习惯,给我一些悲伤.所有其他只是简单的字符串.之后,Custom还有一个from和to属性.
private static readonly Parser<DataFilterEntity> TimeFilter =
from filter in Parse.String("today").Return(DataFilterEntity.Today)
.Or(Parse.String("yesterday").Return(DataFilterEntity.Yesterday)
.Or(Parse.String("last week").Return(DataFilterEntity.LastWeek)
.Or(Parse.String("last month").Return(DataFilterEntity.LastMonth)
.Or(Parse.String("none").Return(DataFilterEntity.None))
.Or(Parse.String("custom").Return(DataFilterEntity.Custom())))))
select filter;
Run Code Online (Sandbox Code Playgroud)
自定义行是问题所在.我需要解析"自定义"字符串,然后解析from和to DateTime字段,并将它们传递给DataFilterEntity.Custom(from,to)
任何想法都非常感激.
我想知道是否有更好的方法使用Sprache解析器框架解析有符号整数。
对于没有符号的整数,有一个众所周知的解析器定义
Parse.Number.Select(int.Parse)
但是我也想解析带有-前缀的整数。
我现在得到的是Parse.Regex(@"\-?\d+").Select(int.Parse)。
没有使用正则表达式的更好方法吗?
例如,使用Parse.Char('-').Optional()然后解析以下数字。
谢谢