В
этойАвтор: Рысцов Денис
Дата: 20.04.11
теме Денис затронул тему использования PegGrammar вместо регулярных выражений.
Там жеАвтор: VladD2
Дата: 21.04.11
я высказал мысль, что в текущем виде это не вполне удобно.
Предлагаю подумать над синтаксисом и семантикой такой замены — inline PEG.
Опишу какие тут есть сложности.
1. Так как PEG поддерживает рекурсию, то подходы регекспов подходят тут плохо. Хотя конечно и не рекурсивный может быть полезен, но лучше все же чтобы inline PEG поддерживал рекурсию.
2. В отсутствии методов-орбработчиков встает вопрос именования (связывания с именами) распознанных фрагментов. Нужна какая-то иделогия именования частей грамматики, так чтобы можно было обрабатывать их результаты.
Для затравки предлагаю следующий механизм. PEG-грамматику описывать как вхождения паттернматчинга вписанные в лямбду.
Таким образом такая грамматика:
[PegGrammar(start,grammar{
any = ['\u0000'..'\uFFFF7'];
d = ['0'..'9'];
phone : string = d{3} '-' d{4,5};
start : string = phone !any;
})]
class PhoneParser
{
phone(a : NToken, _ : NToken, b : NToken) : string
{
$"+7(812) $(GetText(a))-$(GetText(b))"
}
}
может быть переписана следующим образом:
peg parser(str)
{
| <# any = ['\u0000'..'\uFFFF7'] #> => any
| <# d = ['0'..'9'] #> => d
| <# phone = b : d{3} '-' a : d{4,5} #> => $"+7(812) $a-$b"
| <# phone : phone !any #> => phone
}
В итоге parser будет указывать на функцию принимающую строку и возвращающую выведенный тип (в данном примере тоже строку).
Строки используются для того, чтобы можно было использовать паттерн любой сложности.
Для введения имен используется синтаксис имя : подправило.