2016-04-21 14 views
9

libclang określa jedynie 5 rodzaje tokenów:libclang: jak zdobyć żeton semantyka

  • CXToken_Punctuation
  • CXToken_Keyword
  • CXToken_Identifier
  • CXToken_Literal
  • CXToken_Comment

Czy to możliwe, aby uzyskać bardziej szczegółowe informacje na temat tokeny? Na przykład, z następującego kodu źródłowego:

struct Type; 
void foo(Type param); 

spodziewałbym wyjście być jak:

  • struct - kluczowe
  • Typ - nazwa typu
  • ; - znaki interpunkcyjne
  • nieważne - typ/Hasło
  • foo - nazwa funkcji
  • (- interpunkcja
  • Typ - typ parametru funkcji
  • param - funkcja nazwa parametru
  • ) - znaki interpunkcyjne
  • ; - interpunkcja

Muszę również odwzorować te obiekty na lokalizacje plików.

Odpowiedz

7

Po pierwsze, prawdopodobnie potrzebujesz odrobiny wiedzy o tym, jak działa parsowanie. Podręcznik dla kompilatorów byłby przydatnym zasobem. Najpierw plik jest konwertowany na serię tokenów; która daje ci identyfikatory, znaki interpunkcyjne itp. Kod, który to robi nazywa się lexer. Następnie działa parser; to zamienia listę tokenów na AST (uporządkowane deklaracje/wyrażenia/itd.).

clang śledzi różne części deklaracji i wyrażeń, ale nie w sposób, w jaki opisujesz. Dla danej deklaracji funkcji śledzi ona takie rzeczy, jak lokalizacja nazwy funkcji i początek listy parametrów, ale zachowuje je pod względem lokalizacji w pliku, a nie tokenów.

A CXToken to tylko żeton; nie ma żadnych dodatkowych powiązanych informacji semantycznych poza pięcioma wymienionymi typami. (Możesz uzyskać rzeczywisty tekst tokenu za pomocą clang_getTokenSpelling, a lokalizacja z .) clang_annotateTokens daje CXCursor s, które pozwalają ci na sprawdzenie odpowiednich deklaracji.

Należy zauważyć, że niektóre szczegóły nie są ujawnione przez interfejs API libclang; jeśli potrzebujesz więcej szczegółów, może zaistnieć potrzeba użycia API C++ klang.

+0

Niektóre linki na którym opierają swoje obserwacje dotyczące Clang prace będą bardzo przydatne (nie twierdząc, jesteś źle, w rzeczywistości widziałem większość z tego, co mówisz podczas eksploracji libclang sam, wskazując tylko, jak edukacyjne będzie miał kilka linków do poparcia swoich uwag.) – Yannis

+0

Wiem, jak działają parsery, zaimplementowałem więcej niż jeden. W późniejszym czasie dodam więcej szczegółów do mojego pytania.Teraz używam 'clang_annotateTokens', ale zwraca on kursory z nieoczekiwanym' CXCursorKind's. – piotrekg2

+0

@ piotrekg2: Jeśli naprawdę wiesz, jak działają analizatory, dlaczego spodziewasz się, że * token stream * będzie zawierał nie-tokenowe informacje, takie jak "nazwa funkcji" i tak dalej? Jest to informacja oparta na analizatorze, a nie na tokenie. –

2

Poszukujesz atrybutów tokenów spelling i location odsłoniętych przez libclang. W C++ można je odzyskać za pomocą funkcji clang_getTokenLocation i clang_getTokenSpelling.Minimalne wykorzystanie tych funkcji (wykorzystujących swoje odpowiedniki Pythona byłoby:

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 

Daje:

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>