首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SuperPower解析器运行时异常:值不能为空。参数名称:解析器

SuperPower解析器运行时异常:值不能为空。参数名称:解析器
EN

Stack Overflow用户
提问于 2020-10-08 17:25:35
回答 1查看 62关注 0票数 0

我被要求为一个逻辑语句创建一个超级解析器,它由3种类型的操作符(和、AND_NOT、OR)、用于分组的括号和数据值组成。数据值是整数格式,但是标识符。这些更像是规则,然后是数学陈述。

样本1: 20而非(29或30)样本2: 27和(9 OR (24、25和27))

目前,我在运行时得到一个异常,其内部消息为{“值不能为空。\r\n参数名:解析器”}。堆栈跟踪表明它发生在我调用主解析器的TryParse方法的行中。有人能给我一些关于调试的提示吗?

下面是我在控制台应用程序中的内容。

Program.cs

代码语言:javascript
复制
class Program
{
    static void Main(string[] args)
    {
        //SAMPLE DATA
        string input = "20 AND 12";
        //string input = "86 AND NOT 18";
        //string input = "89 AND NOT (87 OR 88)";";
        //string input = "91 AND NOT (94 OR 98 OR 99) AND 12";            
    
        var tokenizer = new TokenizerBuilder<Tokens>()
                    .Ignore(Character.EqualTo(' '))
                    .Match(Character.EqualTo('('), Tokens.LParen)
                    .Match(Character.EqualTo(')'), Tokens.RParen)
                    .Match(Span.EqualTo("AND NOT"), Tokens.AndNot)
                    .Match(Span.EqualTo("AND"), Tokens.And)
                    .Match(Span.EqualTo("OR"), Tokens.Or)
                    .Match(Numerics.Integer, Tokens.ItemNumber)
                    .Build();
    
        var tokens = tokenizer.Tokenize(input); //.Where(x => !x.Kind.Equals(Tokens.Whitespace))
    
        var result = Parsers.Expression.TryParse(tokens);
        if (result.HasValue)
        {
            // input is valid
            var expression = (Expression)result.Value;
    
            // do what you need with it here, i.e. loop through the nodes, output the text, etc.
        }
        else
        {
            // not valid
        }
    }
}

Tokens.cs

代码语言:javascript
复制
public enum Tokens
{
    None,
    Whitespace,

    [Token(Category = "logic", Example = "AND NOT")]
    AndNot,

    [Token(Category = "logic", Example = "AND")]
    And,

    [Token(Category = "logic", Example = "OR")]
    Or,

    [Token(Category = "parenthesis", Example = "(")]
    LParen,

    [Token(Category = "parenthesis", Example = ")")]
    RParen,

    [Token(Category = "data", Example = "XX")]
    ItemNumber
}

Parsers.cs

代码语言:javascript
复制
public static class Parsers
{
    public readonly static TokenListParser<Tokens, Node> Expression =
        ItemNumber.Try().Or(ExpressionNoParens).Try().Or(ExpressionWithParens);
        
    private static readonly TokenListParser<Tokens, Node> LParen =
        Token.EqualTo(Tokens.LParen)
            .Select(i => (Node) new Parenthesis());

    private static readonly TokenListParser<Tokens, Node> RParen =
        Token.EqualTo(Tokens.RParen)
            .Select(i => (Node)new Parenthesis());

    private static readonly TokenListParser<Tokens, Node> ItemNumber =
        ItemNumberNoParens.Try().Or(ItemNumberWithParens);

    private static readonly TokenListParser<Tokens, Node> ItemNumberNoParens =
        Token.EqualTo(Tokens.ItemNumber)
            .Apply(Numerics.IntegerInt32)
            .Select(i => (Node)new ItemNumber(i));

    private static readonly TokenListParser<Tokens, Node> ItemNumberWithParens =
        Token.EqualTo(Tokens.ItemNumber)
            .Between(LParen, RParen)
            .Apply(Numerics.IntegerInt32)
            .Select(i => (Node)new ItemNumber(i));

    private static readonly TokenListParser<Tokens, Node> AndNot =
        Token.EqualTo(Tokens.AndNot)
            .Select(i => (Node)new AndNotOperator());

    private static readonly TokenListParser<Tokens, Node> And =
        Token.EqualTo(Tokens.And)
            .Select(i => (Node)new AndOperator());

    private static readonly TokenListParser<Tokens, Node> Or =
        Token.EqualTo(Tokens.Or)
            .Select(i => (Node)new OrOperator());

    private readonly static TokenListParser<Tokens, Node> Operator =
        AndNot.Try().Or(And).Try().Or(Or);

    private readonly static TokenListParser<Tokens, Node> OperatorExpression =
        from op in Operator
        from ex in Expression
        select (Node) new OperatorExpression(op as Operator, ex as Expression);

    private readonly static TokenListParser<Tokens, Node> ExpressionNoParens =
        from a in Expression
        from op in OperatorExpression.Many()
        select (Node)new ComplexExpression(a as Expression, op as OperatorExpression[]);

    private readonly static TokenListParser<Tokens, Node> ExpressionWithParens =
        from a in Expression
        from op in OperatorExpression.Between(LParen, RParen).Many()
        select (Node)new ComplexExpression(a as Expression, op as OperatorExpression[]);        
}

TokenNodes.cs

代码语言:javascript
复制
public abstract class Node
{
}

public class Parenthesis : Node
{
}

public abstract class Operator: Node
{
}

public class AndNotOperator : Operator
{
}

public class AndOperator : Operator
{
}

public class OrOperator : Operator
{
}

public abstract class Expression : Node
{
}

public class ItemNumber : Expression
{
    public ItemNumber(int value)
    {
        Value = value;
    }

    public int Value { get; set; }
}

public class ComplexExpression : Expression
{
    public ComplexExpression(Expression _exp, OperatorExpression[] _ops)
    {
        Prime = _exp;
        OperatorExpressions = _ops;
    }
    public Expression Prime { get; set; }
    public OperatorExpression[] OperatorExpressions { get; set; }
}

public class OperatorExpression : Node
{
    public OperatorExpression(Operator _op, Expression _exp)
    {
        Operator = _op;
        Expression = _exp;
    }

    public Operator Operator { get; set; }

    public Expression Expression { get; set; }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-09 21:14:40

所以我的回答是“我如何调试这个?!”,我找到了一个答案。

我注释掉了我的每个解析器类,并开始一次一个地将它们添加回一个解析器类,从最简单的、没有依赖项开始。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64267715

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档