Вы можете решить эту проблему, проанализировав главы в виде отдельного списка, где каждая глава заканчивается символом пробела:
public static readonly TokenListParser<PrjToken, string> Chapter =
from chapterName in Text
from wh in Whitespace
select chapterName;
public static readonly TokenListParser<PrjToken, Book> Book =
from title in Title
from chapters in Chapter.Many()
select new Book(title, chapters);
По сути, я думаю, что когда Text.ManyDelimitedBy(Whitespace)
встречает конечный пробел (новая строка)в конце Chapter 2
он ожидает другой экземпляр Имени главы, а не начало новой книги.
Анализатор не может различить разделитель между Chapters
и разделитель между Books
(обапробел (новая строка)), и поэтому он ожидает другую главу, а не начало новой Book
.
Разбив синтаксический анализатор главы на Text
с последующим токеном Whitespace
сломал эту двусмысленность.
Поскольку теперь вы проглотили Whitespace
в конце главы, каждая книга не разделена Whitespace
, и вам придется изменить работу синтаксического анализатора Book
а также:
public static readonly TokenListParser<PrjToken, Book> Book =
from title in Title
from chapters in Chapter.Many()
select new Book(title, chapters);
В дополнение к этому, если вы хотите, чтобы файл был проанализирован без перевода строки в конце файла, вы также должны сделать Whitespace
в end из Chapter
будет необязательным:
public static readonly TokenListParser<PrjToken, string> Chapter =
from chapterName in Text
from wh in Whitespace.Optional()
select chapterName;
В итоге мы получим (полный анализатор):
public class MyParsers
{
public static readonly TokenListParser<PrjToken, string> Text = from text in Token.EqualTo(PrjToken.Text)
select text.ToStringValue();
public static readonly TokenListParser<PrjToken, Superpower.Model.Token<PrjToken>> Whitespace = from text in Token.EqualTo(PrjToken.WhiteSpace)
select text;
public static readonly TokenListParser<PrjToken, string> Title =
from hash in Token.EqualTo(PrjToken.Hash)
from text in Text
from wh in Whitespace
select text;
public static readonly TokenListParser<PrjToken, string> Chapter =
from chapterName in Text
from wh in Whitespace.Optional()
select chapterName;
public static readonly TokenListParser<PrjToken, Book> Book =
from title in Title
from chapters in Chapter.Many()
select new Book(title, chapters);
public static readonly TokenListParser<PrjToken, Library> Library =
from books in Book.Many()
select new Library(books);
}