2013-10-01 6 views
2

Как лексер/токенизатор компилятора «имеет смысл» из: a+++b? как в:Почему и как `a +++ b` интерпретируется как` (a ++) + b`, а не `a + (++ b)`?

int a=0,b=0,x=0; 
x = a+++b; 

Я предполагаю, что он использует некоторые suffix tree, может быть generalized suffix tree, но если это так, то почему больше маркер (++) интерпретируется перед коротким (+), а не наоборот? Значение почему это интерпретируется как:

(a++) + b 

и не:

a + (++b) 

?

Мне нужно написать какой-то токенизатор самостоятельно и задавался вопросом об этом.

+0

это может также быть восприняты как 'а + + (+ б) 'с двумя одинарными плюсами до' b' и без приращений! –

+0

http://en.wikipedia.org/wiki/Maximal_munch –

+0

@BenVoigt - это точно так. Таким образом, эта проблема не может быть решена с помощью si алгоритм маркерного токенизатора, вам нужно будет подняться на один уровень выше и позволить лексеру узнать о контексте? – Tar

ответ

3

Языковые дизайнеры знают о двусмысленности, подобной этому, и вне закона «неправильный случай» в справочном руководстве.

Для лексера это довольно просто: выберите самую длинную лексическую лексему. При столкновении с «++» и «+» выберите «++». Большинство генераторов lexer реализуют эту политику напрямую, и нетрудно сделать это в ручном кодексе, потому что вы должны проверить возможность второй «+» в любом случае после того, как увидите первый.

+0

относительно «генераторов лексера», это очень проблематично, поскольку [@Ben Voigt] (http://stackoverflow.com/questions/19121048/why-and-how-ab-is-interpreted -as-ab-and-not-ab # comment28275009_19121048), прокомментированный выше: можно ли алгоритм алгоритма [maximal munch] (http://en.wikipedia.org/wiki/Maximal_munch) преодолеть? – Tar

+1

То, как Бен положил это, максимальный жест не является проблемой, его * решение * в этом случае: возьмите самый длинный токен. Если бы был вопрос: «Почему язык FOOBAR анализирует A +++ B как A + ++ B», ответ на стороне справочного руководства будет таким же: он * определен * таким образом. Но стандартный лексер, выполняющий максимальный munch, будет проблемой здесь. Рукописный лексер можно легко сгибать, если это необходимо, с помощью определений языков. Если вам нужна забавная проблема, подумайте о том, как «>>» следует лексиковать на C++: оператор сдвига или две закрывающие фигуры шаблона? Здесь максимальная метка просто не проблема. –

0

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

В этом примере лексер будет сначала соответствовать символу «a» и считать, что «идентификаторы» (или «переменная») являются потенциальным токеном (также любой другой токен, который может начинаться с буквы, например «абстрактная») или «как»), после чего лексер будет читать следующий символ («+»), а как + не может быть и идентификатор, и не «абстрактный» ни «как», он прекратит поиск кандидата для «a», и обозначить его как идентификатор.

после этого он имеет символ «+» в качестве текущего символа и думает о возможных токенах, соответствующих этому («+», «++», «+ =»), из-за «жадности» лексер пытается продолжайте со следующего символа и получите следующий «+», поэтому он приходит к выводу, что единственным токеном, который может соответствовать, является «++» (если «+++» был действительным маркером, лексер должен отказаться, если следующий символ - это +)

Следующий шаг принимает следующий символ (снова «+») и думает о возможных маркерах («+», «++», «+ =»), он примет следующий символ («b»)), а как «+ b» не является потенциальным префиксом любого токена, он определяет, что следующий токен «+».

Затем он продолжает использовать «b» (потенциальный идентификатор или любое стартовое ключевое слово b («base», «bool», «break», «byte»), но при чтении следующего символа («;») лексер определяет, что является идентификатором

поэтому лексеров произвести следующие маркеры

идентификатор ++ + идентификатор;.

Смежные вопросы