2013-05-12 6 views
0

В настоящее время я работаю над игрушечным языком, который работает следующим образом: можно встраивать блоки, написанные на этом языке, в источник C++, а перед компиляцией эти блоки переводится на C++ в дополнительном шаг предварительной обработки, создавая действительный источник C++.Экранирование блоков внешнего кода в C++

Я хочу, чтобы эти блоки всегда можно было идентифицировать в источнике однозначно, а также, когда такой блок присутствует в источнике, он не может быть действительным C++. Более того, я хочу их достичь, поставив как можно меньше ограничений на встроенный язык (сам язык по-прежнему несколько жидкий).

Очевидным способом было бы ввести пару специальных многосимвольных круглых скобок, состоящих из символов, которые не могут отображаться вместе в действительном C++-коде (или во встроенном языке). Тем не менее, я не уверен, как убедиться, что особенно последовательность символов хороша для этой цели (а не после GotW #78, в любом случае (:.)

Так что это хороший способ, чтобы избежать этих блоков

+0

Одна вещь, о которой нужно опасаться, - это [Диграфы и триграфы] (http://en.wikipedia.org/wiki/Digraphs_and_trigraphs) –

+1

Исходный строковый литерал может содержать любую последовательность символов (исключая недопустимые последовательности юникода), поэтому нет изолированных последовательностей символов, которые никогда не могут появиться в источнике C++. Вам нужно будет написать простой лексер на C++ (или использовать предварительно написанную на [Boost.Wave] (http://www.boost.org/doc/libs/1_53_0/libs/wave/), а затем просто используйте любую последовательность символов, которая не является частью литерала и которая не является идентификатором или оператором. – Mankarse

ответ

2

Если? ваш компилятор может быть сделано, чтобы принять C++11 стандарт, вы могли бы использовать сырые строковых литералов как, например:.

std::cout << R"*(<!DOCTYPE html> 
     <html> 
     <head> 
     <title>Title with a backslash \ here 
    and double " quote</title>)*"; 

Следовательно, с сырыми строковых литералов не запрещено последовательность символов в этих сырых строковых литералов Любая последовательность символов может появиться в них (но вы можете определить конечную последовательность сырой строки)


И вы могли бы использовать #{ и }# как я в MELT macro-strings; MELT - это Lisp-like domain specific language для расширения GCC, и вы можете вставлять в него код, например.

(code_chunk hellocount_chk 
      #{ /* $HELLOCOUNT_CHK chunk */ 
       static int $HELLOCOUNT_CHK#_counter; 
       $HELLOCOUNT_CHK#_counter++; 
       $HELLOCOUNT_CHK#_lab: 
       printf ("Hello World, counted %d\n", 
         $HELLOCOUNT_CHK#_counter); 
       if (random() % 4 == 0) goto $HELLOCOUNT_CHK#_lab; 
      }#) 

#{ и }# Прилагаем макро-строк (эти последовательности символов вряд ли появятся в коде C или C++, за исключением строковых литералов и комментарии), с $ начальных символов в таких макро-строк (до к символу, отличному от буквы или #).

Использование #{ и }# не дурак-доказательства (например, из-за сырые строковые литералы), но достаточно хорошо: кооперативная пользователь может управлять, чтобы избежать их.

+0

Это не то, как я хочу, чтобы это работало. Я пишу переводчик, который берет внешние блоки, выдает C++ из них и вставляет их обратно в код, прежде чем даже препроцессор увидит какой-либо источник. – xcvii

+0

MELT делает то же самое: он переводит язык MELT в C++ (до и независимо от препроцессора C++) –

+0

Достаточно честный. Я написал комментарий перед вашим редактированием, где вы добавили часть о MELT. Изменить: или, скорее всего, я просто пропустил эту часть, извините! – xcvii