3

I am having some trouble with my Sprache based parser. I am trying to parse a string in which there are two possible things to parse. One option is a regular variable name like x or a more complex version x[1]. The first references a simple variable the second an aggregate variable made up of many variables, x[1] references the first variable in the aggregate.

This is what I have so far.

    private static readonly Parser<VariableModel> SingletonVariableName =
        from leading in Sprache.Parse.WhiteSpace.Many()
        from variable in Identifier
        from trailing in Sprache.Parse.WhiteSpace.Many()
        select variable;

    private static readonly Parser<VariableModel> Identifier =
        from first in Sprache.Parse.Letter.Once().Text()
        from rest in Sprache.Parse.LetterOrDigit.Many().Text()
        select new VariableModel(string.Concat(first, rest));

   private static readonly Parser<AggregateVariableReference> AggregateVariableReference =
        from variableName in Identifier
        from openingSubscript in Sprache.Parse.Char('[').Once()
        from subscriptStatement in Sprache.Parse.Number.Text()
        from closingSubscript in Sprache.Parse.Char(']').Once()
        select new AggregateVariableReference(variableName.Name,
                                              Convert.ToInt32(subscriptStatement));
private static readonly Parser<Expression> LeftHandSide =
    SingletonVariableName.Select(Models.Expression.CreateIdentifier)
       .Or(AggregateVariableReference.Select(Models.Expression.CreateAggregateReference));

I read somewhere that the Or method only works if the first character will decide which expression wins. In my case that isn't the case. Both start with a variable name. What does XOr do? Will that help in this case?

I get the following exception: Sprache.ParseException : Parsing failure: unexpected '['; expected = or != or >= or <= or > or < (Line 1, Column 3); recently consumed: xx

Jack Hughes
  • 5,514
  • 4
  • 27
  • 32

1 Answers1

2

The way to do this is to order the arguments to the Or() combinator so that the one consuming the most input is first:

static readonly Parser<Expression> LeftHandSide =
    AggregateVariableReference
        .Select(Models.Expression.CreateAggregateReference)
   .Or(SingletonVariableName
        .Select(Models.Expression.CreateIdentifier));
Nicholas Blumhardt
  • 30,271
  • 4
  • 90
  • 101