Разбор столбца символов в Boost::Spirit
-
13-09-2019 - |
Вопрос
Я работаю над Поднимите Дух анализатор на основе 2.0 для небольшого подмножества Fortran 77.Проблема, с которой я столкнулся, заключается в том, что Fortran 77 ориентирован на столбцы, и я не смог найти в Spirit ничего, что могло бы позволить его анализаторам поддерживать работу с столбцами.Есть ли какой-нибудь способ сделать это?
На самом деле мне не обязательно поддерживать полный синтаксис arcane Fortran, но он должен иметь возможность игнорировать строки, содержащие символ в первом столбце (комментарии Fortran), и распознавать строки с символом в шестом столбце как строки продолжения.
Похоже, что у людей, имеющих дело с пакетными файлами, по крайней мере, была бы та же проблема с первым столбцом, что и у меня.Похоже, что у Spirit есть анализатор конца строки, но нет анализатора начала строки (и, безусловно, нет анализатора столбцов (x)).
Решение
Что ж, поскольку теперь у меня есть ответ на этот вопрос, я думаю, мне следует поделиться им.
Fortran 77, как, вероятно, и все другие языки, которые заботятся о столбцах, является языком, ориентированным на строку.Это означает, что ваш анализатор должен отслеживать EOL и фактически использовать его при своем синтаксическом анализе.
Другим важным фактом является то, что в моем случае я не заботился о разборе номеров строк, которые Fortran может поместить в эти ранние контрольные столбцы.Все, что мне нужно, это знать, когда он говорит мне сканировать остальную часть строки по-другому.
Учитывая эти две вещи, я мог бы полностью решить эту проблему с помощью Spirit skip parser.Я написал свое в
- пропустите всю строку, если первый столбец (комментарий) содержит буквенный символ.
- пропустите всю строку, если в ней ничего нет.
- игнорируйте предшествующий EOL и все остальное вплоть до пятой колонки, если пятая колонка содержит '.' (строка продолжения).Это привязывает его к предыдущей строке.
- пропустите все пробелы, отличные от eol (в Fortran четные пробелы не имеют значения.Да, это странный язык.)
Вот код:
skip =
// Full line comment
(spirit::eol >> spirit::ascii::alpha >> *(spirit::ascii::char_ - spirit::eol))
[boost::bind (&fortran::parse_info::skipping_line, &pi)]
|
// remaining line comment
(spirit::ascii::char_ ('!') >> *(spirit::ascii::char_ - spirit::eol)
[boost::bind (&fortran::parse_info::skipping_line_comment, &pi)])
|
// Continuation
(spirit::eol >> spirit::ascii::blank >>
spirit::qi::repeat(4)[spirit::ascii::char_ - spirit::eol] >> ".")
[boost::bind (&fortran::parse_info::skipping_continue, &pi)]
|
// empty line
(spirit::eol >>
-(spirit::ascii::blank >> spirit::qi::repeat(0, 4)[spirit::ascii::char_ - spirit::eol] >>
*(spirit::ascii::blank) ) >>
&(spirit::eol | spirit::eoi))
[boost::bind (&fortran::parse_info::skipping_empty, &pi)]
|
// whitespace (this needs to be the last alternative).
(spirit::ascii::space - spirit::eol)
[boost::bind (&fortran::parse_info::skipping_space, &pi)]
;
Я бы не советовал слепо использовать это самостоятельно для ориентированного на строки Fortran, поскольку я игнорирую номера строк, а разные компиляторы имеют разные правила для допустимых символов комментариев и продолжения.