Parlot.NET 解析器组合器

联合创作 · 2023-10-01 08:54

Parlot 是一个快速、轻量级和简单易用的 .NET 解析器组合器。Parlot 提供了一个基于解析器组合器的 fluent API,提供了一个更可读的语法定义。


与所有其他已知的 .NET 解析器组合器相比,Parlot 速度更快,分配更少。


Fluent API 提供了简单的分析器组合器,这些组合器可以用来表达更复杂的表达式。这个API的主要目标是提供和易于阅读的语法。另一个优点是,语法是在运行时建立的,而且可以动态地扩展。


示例(源码):



public static readonly Parser<Expression> Expression;

static FluentParser()
{
/*
* Grammar:
* expression => factor ( ( "-" | "+" ) factor )* ;
* factor => unary ( ( "/" | "*" ) unary )* ;
* unary => ( "-" ) unary
* | primary ;
* primary => NUMBER
* | "(" expression ")" ;
*/

// The Deferred helper creates a parser that can be referenced by others before it is defined
var expression = Deferred<Expression>();

var number = Terms.Decimal()
.Then<Expression>(static d => new Number(d))
;

var divided = Terms.Char('/');
var times = Terms.Char('*');
var minus = Terms.Char('-');
var plus = Terms.Char('+');
var openParen = Terms.Char('(');
var closeParen = Terms.Char(')');

// "(" expression ")"
var groupExpression = Between(openParen, expression, closeParen);

// primary => NUMBER | "(" expression ")";
var primary = number.Or(groupExpression);

// The Recursive helper allows to create parsers that depend on themselves.
// ( "-" ) unary | primary;
var unary = Recursive<Expression>((u) =>
minus.And(u)
.Then<Expression>(static x => new NegateExpression(x.Item2))
.Or(primary));

// factor => unary ( ( "/" | "*" ) unary )* ;
var factor = unary.And(ZeroOrMany(divided.Or(times).And(unary)))
.Then(static x =>
{
// unary
var result = x.Item1;

// (("/" | "*") unary ) *
foreach (var op in x.Item2)
{
result = op.Item1 switch
{
'/' => new Division(result, op.Item2),
'*' => new Multiplication(result, op.Item2),
_ => null
};
}

return result;
});

// expression => factor ( ( "-" | "+" ) factor )* ;
expression.Parser = factor.And(ZeroOrMany(plus.Or(minus).And(factor)))
.Then(static x =>
{
// factor
var result = x.Item1;

// (("-" | "+") factor ) *
foreach (var op in x.Item2)
{
result = op.Item1 switch
{
'+' => new Addition(result, op.Item2),
'-' => new Subtraction(result, op.Item2),
_ => null
};
}

return result;
});

Expression = expression;
}
浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报