Мне нужно разобрать строку вроде func1(arg1, arg2); func2(arg3, arg4);
. Это не очень сложная проблема с синтаксическим анализом, поэтому я бы предпочел не использовать flex / bison или аналогичные утилиты.
Моим первым подходом было попытаться использовать POSIX C regcomp/regexec
или Boost реализацию C ++ std::regex
. Я написал следующее регулярное выражение, которое не работает (я объясню почему в дальнейшем).
"^"
"[ ;\t\n]*"
"(" // (1) identifier
"[a-zA-Z_][a-zA-Z0-9_]*"
")"
"[ \t\n]*"
"(" // (2) non-marking
"\["
"(" // (3) non-marking
"[ \t]*"
"(" // (4..n-1) argument
"[a-zA-Z0-9_]+"
")"
"[ \t\n]*"
","
")*"
"[ \t\n]*"
"(" // (n) last argument
"[a-zA-Z0-9_]+"
")"
"]"
")?"
"[ \t\n]*"
";"
Обратите внимание, что группа 1
захватывает идентификатор, а группы 4..n-1
предназначены для захвата аргументов, кроме последнего, который захватывается группой n
.
Когда я применяю это регулярное выражение, скажем func(arg1, arg2, arg3)
, я получаю массив {func, arg2, arg3}
. Это неправильно, потому что arg1
не в этом!
Проблема заключается в том, что в стандартных библиотеках регулярных выражений подмаркировка фиксирует только последнее совпадение. Другими словами, если вы, например, применили регулярное выражение "((a*|b*))*"
к "babb"
, результаты внутреннего совпадения будут bb
, а все предыдущие захваты будут забыты.
Еще одна вещь, которая меня раздражает, это то, что в случае ошибки нет способа узнать, какой символ не был распознан, поскольку эти функции предоставляют очень мало информации о состоянии синтаксического анализатора при отклонении ввода.
Так что я не знаю, упускаю ли я что-то здесь ... В этом случае я должен использовать sscanf
или подобное?
Обратите внимание, что я предпочитаю использовать стандартные библиотеки C / C ++ (и, возможно, boost).