Boost Mini C Учебное пособие
Так что я работал с учебником Boost Spirit Compiler. В настоящее время он отлично работает с целыми числами. Я работаю над тем, чтобы расширить его для обработки строк. Вот ссылка на исходный код.
http://www.boost.org/doc/libs/1_57_0/libs/spirit/example/qi/compiler_tutorial/mini_c/
Для тех, кто знаком с Boost, следующее должно выглядеть знакомо - это производственное правило для основного выражения:
primary_expr =
uint_
| function_call
| identifier
| bool_
| '(' > expr > ')'
;
uint_ - это то, что позволяет primary_expr присваивать int. Обычно, мы могли бы добавить некоторые простые функции для символа или строки, создав несколько дополнительных правил работы, или просто анализатор текста, использующий регулярное выражение, которое идентифицирует кавычки или что-то в этом роде. Существует множество примеров, если вы создадите резервную копию корневой ссылки, которую я отправил.
Настоящая проблема заключается в том, что для реализации компилятора код помещает операции с байт-кодом в вектор. Здесь тривиально вставить один символ, так как все символы имеют сопровождающий код ASCII, в который он будет неявно преобразован, но это не относится к массиву символов, поскольку они потеряли бы свой контекст в процессе как часть большей строки (который формирует предложение, например).
Лучший вариант, который я могу придумать, это изменить
vector<int>
в
vector<uintptr_t>
Насколько я понимаю, этот тип указателя может указывать как на целые числа, так и на символы. Однако дело не только в том, чтобы изменить uint_ на uintptr_t в приведенном выше производственном правиле. Компилятор говорит мне, что в данном конкретном случае это незаконное использование.
Кстати, вы увидите реализацию нашего вектора, содержащего байт-код в файлах compiler.cpp /.hpp.
Буду признателен за любую помощь, и если вам нужна дополнительная информация, пожалуйста, спросите. Благодарю.
1 ответ
Как правило, мы могли бы добавить некоторые простые функции для символа или строки, создав несколько дополнительных правил работы, или просто анализатор текста с использованием регулярного выражения, определяющего кавычки, или что-то в этом роде.
Regex не поддерживается. Вы можете использовать подмножество синтаксиса регулярных выражений в шаблонах Boost Spirit Lex (которые можно использовать в token_def
) но это значительно усложнит картину.
Настоящая проблема заключается в том, что для реализации компилятора код помещает операции с байт-кодом в вектор. Здесь тривиально вставить один символ, так как все символы имеют сопровождающий код ASCII, в который он будет неявно преобразован, но это не относится к массиву символов, поскольку они потеряли бы свой контекст в процессе как часть большей строки (который формирует предложение, например).
На жаргоне: AST не поддерживает нецелые значения.
Самый простой способ - расширить AST для операнда:
typedef boost::variant<
nil
, bool
, unsigned int
, identifier
, std::string // ADDED
, boost::recursive_wrapper<unary>
, boost::recursive_wrapper<function_call>
, boost::recursive_wrapper<expression>
>
operand;
(Примечание: это также тип атрибута, предоставляемый primary_expr
а также unary_expr
)
Теперь давайте расширим правила:
quoted_string = '"' >> *('\\' >> char_ | ~char_('"')) >> '"';
primary_expr =
uint_
| function_call
| identifier
| quoted_string
| bool_
| ('(' > expr > ')')
;
Обратите внимание, что мы объявили quoted_string
без шкипера, поэтому мы не должны делать lexeme[]
заклинание ( Boost Spirit Шкипер вопросы).
Поддержка компилятора
Далее при компиляции получается compiler
посетитель пока не знает строк. Итак, добавим
op_string, // push constant string into the stack
а также
bool compiler::operator()(std::string const& x)
{
BOOST_ASSERT(current != 0);
current->op(op_string, x);
return true;
}
в соответствующих местах.
(все еще https://www.livecoding.tv/sehe/ coding, подтолкнул ответ, чтобы вы могли прочитать его заранее)