2016-04-21 1 views
9

libclang определяет только 5 типов лексем:libclang: как получить маркер семантика

  • CXToken_Punctuation
  • CXToken_Keyword
  • CXToken_Identifier
  • CXToken_Literal
  • CXToken_Comment

Можно получить более подробную информацию о жетоны? Например, для следующего исходного кода:

struct Type; 
void foo(Type param); 

Я бы ожидать, что выход будет как:

  • структура - ключевое слово
  • Тип - имя типа
  • ; - знаки препинания
  • пустота - тип/ключевое слово
  • Foo - имя функции
  • (- пунктуация
  • Тип - тип параметра функции
  • парам - имя функции параметра
  • ) - пунктуация
  • ; - пунктуация

Мне также необходимо сопоставить эти объекты с файлами.

ответ

7

Во-первых, вам, вероятно, потребуется немного информации о том, как работает синтаксический анализ. Учебник по компиляторам будет полезным ресурсом. Во-первых, файл преобразуется в ряд токенов; который дает вам идентификаторы, знаки препинания и т. д. Код, который делает это, называется лексером. Затем выполняется синтаксический анализатор; это преобразует список токенов в AST (структурированные объявления/выражения/и т. д.).

clang отслеживает различные части деклараций и выражений, но не так, как вы описываете. Для данного объявления функции он отслеживает такие вещи, как расположение имени функции и начало списка параметров, но сохраняет их в терминах местоположений в файле, а не токенов.

A CXToken - всего лишь токен; нет дополнительной связанной семантической информации, кроме пяти перечисленных вами типов. (Вы можете получить фактический текст токена с clang_getTokenSpelling, а его местоположение - clang_getTokenExtent.) clang_annotateTokens дает вам CXCursor s, что позволит вам изучить соответствующие декларации.

Обратите внимание, что некоторые детали не отображаются API-интерфейсом libclang; если вам нужна более подробная информация, вам, возможно, придется использовать Cang API для Clang.

+0

Некоторых ссылки на которых вы основываете свои наблюдения о том, как работает Clang будет очень полезен (не претендует вы неправильно, на самом деле я видел большую часть того, что вы говорите, исследуя сам libclang, просто указывая, как образовательные будут иметь некоторые ссылки для поддержки ваших замечаний). – Yannis

+0

Я знаю, как работают парсеры, я реализовал более одного. Я добавлю более подробные сведения к моему вопросу позже. В настоящее время я использую 'clang_annotateTokens', но он возвращает курсоры с неожиданным' CXCursorKind'. – piotrekg2

+0

@ piotrekg2: Если вы действительно знаете, как работают парсеры, почему вы ожидаете, что поток токена * должен иметь не-токенную информацию, такую ​​как «имя функции» и т. Д.? Это информация, основанная на парсерах, а не на основе токенов. –

2

Вы ищете токены spelling и location атрибуты, выставленные libclang. В C++ их можно получить с помощью функций clang_getTokenLocation и clang_getTokenSpelling.Минимальное использование этих функций (используя их питон эквиваленты будет:

s = ''' 
struct Type; 
void foo(Type param); 
''' 

idx = clang.cindex.Index.create() 
tu = idx.parse('tmp.cpp', args=['-std=c++11'], unsaved_files=[('tmp.cpp', s)], options=0) 
for t in tu.get_tokens(extent=tu.cursor.extent): 
    print t.kind, t.spelling, t.location 

Дает:

TokenKind.KEYWORD struct <SourceLocation file 'tmp.cpp', line 2, column 1> 
TokenKind.IDENTIFIER Type <SourceLocation file 'tmp.cpp', line 2, column 8> 
TokenKind.PUNCTUATION ; <SourceLocation file 'tmp.cpp', line 2, column 12> 
TokenKind.KEYWORD void <SourceLocation file 'tmp.cpp', line 3, column 1> 
TokenKind.IDENTIFIER foo <SourceLocation file 'tmp.cpp', line 3, column 6> 
TokenKind.PUNCTUATION (<SourceLocation file 'tmp.cpp', line 3, column 9> 
TokenKind.IDENTIFIER Type <SourceLocation file 'tmp.cpp', line 3, column 10> 
TokenKind.IDENTIFIER param <SourceLocation file 'tmp.cpp', line 3, column 15> 
TokenKind.PUNCTUATION) <SourceLocation file 'tmp.cpp', line 3, column 20> 
TokenKind.PUNCTUATION ; <SourceLocation file 'tmp.cpp', line 3, column 21>