1

我想匹配第一个字符是字母的字符串,然后是数字或字母的多个字符,最后以字母结尾。例如a11a11a,正确但a11aa11不正确,因为它以数字而不是字母结尾。

我编写了以下代码来做到这一点:

var grammar =
    from first in Parse.Letter.Once()
    from rest in Parse.LetterOrDigit.Many()
    from end in Parse.Letter.Once()
    select new string(first.Concat(rest).Concat(end).ToArray());

var result = grammar.TryParse("a111a");

不幸的是LetterOrDigit.Many(),也消耗了最后一个字母。

有什么办法可以避免这种情况?

4

2 回答 2

1

这是一个解决方案:

Parser<IEnumerable<char>> A = null, B = null, C = null;

var letter = Parse.Letter.Once();
var digit = Parse.Digit.Once();

B =
    (
    from d in digit
    from cs in Parse.Ref(() => C)
    select d.Concat(cs)
    ).Or
    (
        from l in letter
        from bs in Parse.Ref(() => B)
        select l.Concat(bs)
    ).Or(letter);

C = (
    from d in digit
    from bs in Parse.Ref(() => B)
    select d.Concat(bs)
    ).Or(letter);

A = (
    from l in letter
    from bs in Parse.Ref(() => B)
    select l.Concat(bs)
    ).Or(letter);

var grammar =
    from _ in Parse.WhiteSpace.Many()
    from a in A
    from __ in Parse.WhiteSpace.Many()
    select a;

中的子句Or需要按正确的顺序排列。

一位评论者建议使用正则表达式。您可以在 Sprache 中使用它们:

Parse.Regex("[a-z]([a-z0-9]*[a-z])?")
于 2018-07-08T15:42:25.633 回答
0

另一种解决方案:

       var text = "a11a11a";
       var n = text.Length;
       var grammer =
           from open in Parse.Letter.Once()
           from content in Parse.LetterOrDigit.Repeat(n - 2)
           from close in Parse.Letter.Once()
           select open.Concat(content).Concat(close);       

尝试一下

于 2021-12-09T23:23:59.880 回答