亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Sprache 中的文本查詢解析

Sprache 中的文本查詢解析

C#
人到中年有點甜 2022-07-23 08:56:02
我正在嘗試編寫一些代碼來匹配基于模式的字符串:模式:“狗和(貓或山羊)”測試字符串:“doggoat” 結果:true測試字符串:“dogfrog” 結果:假我正在嘗試使用 Sprache 編寫解析器,其中大部分邏輯由 Corey對類似問題的出色回答提供。我快到了,但是運行代碼時出現異常:System.Func'沒有為類型2[System.String,System.Boolean]' 和 ''System.Func`2[System.String,System.Boolean]'定義二元運算符 AndAlso 。我知道這意味著我需要將表達式樹節點處的 lambda 表達式與邏輯運算符結合起來,我根據此處另一個問題的答案嘗試使用 ExpressionVisitor 。但是,程序在執行 ExpressionVisitor 之前崩潰 - 似乎首先執行 Parse 命令,但我不太明白為什么(可能是因為 Sprache.Parse.Select 語句不強制執行 lambda?) ,或者如何強制它先被執行。示例代碼如下(為了簡潔起見,我刪除了所有運算符,但“和”除外,從Corey 的模板中重新引入它們是微不足道的。必須從 NuGet 添加 Sprache 才能編譯代碼。class Program{    static void Main(string[] args)    {        var patternString = "dog and cat";        var strTest = "dog cat";        var strTest2 = "dog frog";        var conditionTest = ConditionParser.ParseCondition(patternString);        var fnTest = conditionTest.Compile();        bool res1 = fnTest(strTest); //true        bool res2 = fnTest(strTest2); //false    }}public static class ConditionParser{    static ParameterExpression Param = Expression.Parameter(typeof(string), "_");    public static Expression<Func<string, bool>> ParseCondition(string text)    {        return Lambda.Parse(text);    }    private static Parser<Expression<Func<string, bool>>> Lambda    {        get        {            var reduced = AndTerm.End().Select(delegate (Expression body)            {                var replacer = new ParameterReplacer(Param);                return Expression.Lambda<Func<string, bool>>((BinaryExpression)replacer.Visit(body), Param);            });            return reduced;        }    }    static Parser<Expression> AndTerm =>        Parse.ChainOperator(OpAnd, StringMatch, Expression.MakeBinary);    // Other operators (or, not etc.) can be chained here, between AndTerm and StringMatch    static Parser<ExpressionType> OpAnd = MakeOperator("and", ExpressionType.AndAlso);    private static Parser<Expression> StringMatch =>        Parse.Letter.AtLeastOnce()        .Text().Token()        .Select(value => StringContains(value));
查看完整描述

1 回答

?
犯罪嫌疑人X

TA貢獻2080條經驗 獲得超4個贊

您的代碼存在幾個問題,但導致異常的主要問題是StringContains返回 lambda 表達式的方法。并且Expression.AndAlso(以及大多數Expression方法)基于簡單的非 lambda 表達式(或 lambda 表達式主體)。解析代碼的整個想法是識別和組合簡單的表達式,并從結果表達式中生成單個 lambda 表達式。

要解決原始問題,該StringContains方法應直接返回MethodCall表達式而不是 lambda 表達式。

同一StringContains方法中的第二個問題是將參數反轉為string.Contains. 它基本上是這樣做token.Contains(parameter)的,而根據預期結果它應該做相反的事情。

整個方法(使用另一個方便的Expression.Call重載)可以簡化為

static Expression StringContains(string subString) =>
    Expression.Call(Param, "Contains", Type.EmptyTypes, Expression.Constant(subString));

現在一切都應該按預期工作。

但是,由于ConditionParser該類使用單個ParameterExpression實例,然后用于構建 lambda 表達式,因此不需要ParameterReplacer,因此Lambda方法(屬性)可以簡化為

private static Parser<Expression<Func<string, bool>>> Lambda =>
    AndTerm.End().Select(body => Expression.Lambda<Func<string, bool>>(body, Param));


查看完整回答
反對 回復 2022-07-23
  • 1 回答
  • 0 關注
  • 99 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號