Есть ли какая-то разница между токенами или строками в построении компилятора? - PullRequest
1 голос
/ 21 февраля 2020

Я пытался оптимизировать компилятор в JavaCC, но потом наткнулся на то, чего я никогда не обнаруживал при работе с компиляторами в прошлом, потому что меня учили использовать токены для любого терминала.

Этот компилятор иногда использует строки в регулярных выражениях анализа syntacti c вместо токенов, например:

<TK_IF> "(" log_expr ")" body

вместо:

<TK_IF> <TK_LPAREN> log_expr <TK_RPAREN> body

Это просто пример, в других в частях кода используются строки в таких операторах, как (+, -,! =, ==,>, <). </p>

Я хочу знать, есть ли какая-то разница между токенами использования или строками в компилятор, в основном о производительности, и это моя цель - оптимизировать его.

Ответы [ 2 ]

4 голосов
/ 22 февраля 2020

В прошлом было принято реализовывать лексеры / токенизаторы так, чтобы они возвращали значения «маленького целого» для каждого типа токена: например,

IF the next token is the word "def" THEN RETURN 257 FI

. Объединяя это с использованием 7 или 8-битных наборов символов, мы сразу видим, что все 256 возможных значений символов доступны в качестве значений токенов. Таким образом, «(» может быть просто токеном номер 40 (см. Любую таблицу ASCII).

Вы часто можете сказать, использует ли кто-то такую ​​запись, потому что односимвольные операторы, такие как +, будут кодироваться таким образом. (+ = 43), но двухсимвольный оператор, такой как +=, будет иметь именованный токен. Другая дешевая распродажа происходит, когда код, который генерирует код поиска токена, генерирует таблицу токенов, и первое имя цифра токена c чуть выше 255, максимальное 8-битное значение.

В конце концов, это не очень важно: это просто изюминка реализации. Если вы напишите свой собственный сканер и парсер, вы сделаете все возможное, чтобы вернуть соответствующий токен-код вашему парсеру. Как превратить некоторый входной синтаксис в соответствующий код зависит от вас.

2 голосов
/ 23 февраля 2020

Ответ в FAQ .

Скажите, что у меня есть два определения (или лексические произведения в терминологии JavaCC)

TOKEN : { <ID : (["a"-"z","A"-Z"])+ > 
      |   <BECOMES : ":=" >}

Это определяет вид токена с именем ID. Это соответствует бесконечному числу строк, которые могут появиться во входном файле: apple, pear, fruitBasket. Он также определяет вид токена BECOMES, который может отображаться только в виде строки :=.

В ваших продуктах BNF вам необходимо ссылаться на виды токенов. Таким образом, производство BNF может быть

void assignment() : {} { <ID> <BECOMES> expression() }

Но --- , как объяснено в FAQ ---, поскольку вид токена BECOMES может ссылаться только на строку := - - и, по-видимому, единственный такой тип токенов, JavaCC позволяет записать эту продукцию BNF как

void assignment() : {} { <ID> ":=" expression() }

Два способа написания продукции идентичны.

В в вашем случае строки "(" и ")" в нетерминальных продуктах просто сокращаются <TK_LPAREN> и <TK_RPAREN> соответственно.

Эта аббревиатура может использоваться только в продуктах BNF .

...