Ну первый вариант однозначно плох: сложное выражение редактировать и воспринимать будет сверхнеудобно, и будет крайне легко допустить ошибку. Плюс нехороший мусор для непоименованных элементов (подчеркивания). Второй — тоже не фонтан, так как ухудшается читаемость собственно грамматики, легко запутаться в этом чередовании 'as', все сливается.
Указание имен в каком-то смысле эквивалентно введению подправил грамматики. Названия правил в описании грамматики могут говорить сами за себя (например, attrs), так что и без расшифровки понятно, что это. Если какой-то макрос упоминается только один раз (а таких случаев будет 99%), его можно явно не именовать.
macro class Xml
{
macro tagOpen : XmlAst.TagOpen
syntax: '<' identifier attrs '>'
where
attrs: attr*
{
TagOpen(identifier.Value, attrs.Map(x => x.Value :> Attr))
}
macro attr : XmlAst
syntax: identifier '=' attrValue
{
Attr(identifier, attrValue)
}
}
Я убрал из примера сохранение позиции в тексте, так как мне кажется, что этот нудный процесс обязательно должен быть как-то автоматизирован.
Здесь, кстати, есть какая-то аналогия с регэксповыми "матчами". То есть мы как бы создаем поименованное подвыражение.
Вариант синтаксиса со скобками, скобки вроде как визуально выделяют поименованный фрагмент:
macro tagOpen : XmlAst.TagOpen
syntax: '<' identifier {attrs attr*} '>'
{
TagOpen(identifier.Value, attrs.Map(x => x.Value :> Attr))
}
Можно смешать варианты:
macro tagOpen : XmlAst.TagOpen
syntax: {lt '<'} identifier attrs {gt '>'}
where
attrs: attr*
{
TagOpen(lt.StartPos, gt.EndPos, identifier.Value, attributes.Map(x => x.Value :> Attr))
}
По поводу пробелов (а точнее, разделителей, в которые входят также комментарии). Выписывать явно разделители, тем более с таким именем как "s" — явно некрасиво. Потому что в 99% случаев он будет нужен и только в 1% — не нужен. Скорее, было бы лучше, если бы макрос s вставлялся по умолчанию, если не вставлен кейворд
nospace, например:
'<' nospace identifier nospace '>'.
Еще с разделителями интересная вещь. Если я захочу добавить новый вид комментариев, значит мне как-то надо расширить макрос s? Значит, макросы можно будет определять более одного раза, расширяя их, так что ли?