Вы думали о правильной вещи (разбивая материал на композиционную грамматику), но так, как вы это делали, есть проблемы.
Важнейшей проблемой является то, что многие ваши обратные косые черты будут игнорироваться. "url\(.+\)" eq "url(.+)"
, "... \. ..."
не помещает обратную косую черту перед периодом. Чтобы избежать различных правил синтаксического анализа для строк и регулярных выражений, я настоятельно рекомендую использовать котировки регулярных выражений: qr//
. Это имеет побочный эффект компиляции все эти регулярные выражений (которые вы на самом деле не хотите), но, по крайней мере, вам не придется делать двойное вытекание:
my $w = qr/\s*/;
...
my $paint = qr/fill|stroke/; # enclosing group added automatically
Однако каждый из этих моделей должны иметь смысл, как регулярное выражение само по себе. Поэтому вам нужно временные переменные для
my $color_names = join ...
my $color = qr/...|...|$color_names/;
При соединении не-строки регулярных выражений вместе, вы должны как привычка бежать все метасимволы:
join '|', map quotemeta, keys %{ ... };
Вместо составления регулярных выражений через переменные интерполяции, вы можете использовать (?(DEFINE) ...)
:
qr/
(?(DEFINE)
(?<ws> \s*)
(?<comma> \s*[,]\s*)
(?<integer> [+-]?[0-9]+)
(?<percent> (?&integer)[%])
(?<number> (?&integer)(?: [.][0-9]+ (?: [eE](?&integer))?)?)
...
)
/x
Внутри DEFINE
среды, вы можете объявить шаблоны, как называли захватами (но они не захватывают, а у ou не может захватить внутри таких шаблонов). Вы можете вызвать такой шаблон, как (?&pattern)
.
Если вы не хотите просто соответствовать данных, но и проанализировать его, то регулярные выражения могут оказаться непригодными. Я рекомендую парсер Marpa :: R2. Это немного более низкого уровня, и менее выразительный, но имеет хороший BNF синтаксис:
:start ::= NumberList
:default ::= action => ::array bless => ::lhs
:discard ~ ws
NumberList ::= number+ separator => comma
ws ~ [\s]+
comma ~ ','
digits ~ [0-9]+
sign ~ [+-]
integer ~ sign digits | digits
number ~ integer
| integer '.' digits
| integer '.' digits [eE] integer
...
Прочитайте Marpa documentation, чтобы увидеть, если это libary может быть полезным. В противном случае Parse::RecDescent и Regexp::Grammars являются хорошими альтернативами простым регулярным выражениям. Если вы выберете парсер, основанный на регулярном выражении, вы можете повторно использовать общие шаблоны от Regexp::Common.
Как представляется, нет конкретной проблемы, которую вам необходимо решить, вы можете попросить об этом на http://codereview.stackexchange.com. –
Хорошо - сделаем - спасибо. –