2012-09-20 2 views
1

저는 Python 플러그인 인 Pygments의 렉서를 사용하고 있습니다. C++ 코드에 대한 토큰을 얻고 싶습니다. 특히 새로운 변수가 선언되었을 때 그렇습니다. 여기 파이어 렉서 다중 토큰

int a=3,b=5,c=4; 

는, B는 C 여기

a=3,b=5,c=4; 

A, B, C는 단순히 유형 "변수"를 부여한다 보낸 상이한 유형 "선언 된 변수"를 제공해야 그들은 전에 선언되었습니다.

(See Pygments documentation가) 내가

(int)(\s)(?:([a-z]+)(=)([0-9]+)(,))*, bygroups(Type,Space,Name,Equal,Number,Comma) 

의 라인 ((가) 따라 정규식 작성하려는 내가 한 번에 여러 토큰을 스캔 할 렉서의 능력을 사용하고 싶습니다 "?"만하는 것입니다

그러나 라인의 여러 개의 선언과 일치하는 대신 라인의 마지막 선언에 대한 토큰 만 반환합니다 (이 경우에는 해당 그룹의 " c = 4 "부분). 라인의 모든 선언에 대해 토큰을 반환하려면 어떻게합니까?

답변

2

필요한 것은 상태 저장 렉서입니다. 정규 표현식이 작업을하지 않는 이유는 그룹이 연속적이지 않기 때문입니다.

int a=3,b=5,c=4; 

은 여기에서 문자 0..2이 유형 3..3 공간, 4..7 이름, 평등 번호와 쉼표 다시 이름, 평등, 번호 및 쉼표가되고 싶어요. 그건 입니다.

해결책은 유형 선언이 보일 때를 기억하는 것입니다. 은 다음 세미콜론까지 계속되는 새로운 렉서 모드로 들어갑니다. pygments 설명서에서 Changing states을 참조하십시오.

다음은 CFamilyLexer를 사용하고 세 가지 새로운 lexer 상태를 추가하는 솔루션입니다. 그것은 function 상태에있는 동안이 같은 라인을보고 그래서 때

int m = 3 * a + b, x = /* comments ; everywhere */ a * a; 

첫째는 소비 :

int 

그것은 내가 추가 한 새 규칙과 일치, 그것은 vardecl 상태가되도록 :

m 

아 변수 이름! 렉서가 vardecl 상태이므로, 이것은 새로 정의 된 변수입니다. 그것을 NameDecl 토큰으로 내 보냅니다. 그런 다음 varvalue 상태를 입력하십시오.

3 

그냥 숫자입니다.

* 

그냥 운영자.

a 

오 변수의 이름!하지만 이제 우리는 varvalue 상태에 있으므로 은 이 아니며 변수 선언, 그냥 일반적인 변수 참조입니다.

+ b 

연산자와 다른 변수 참조.

, 

가변 값 m 완전히 선언 됨. vardecl 상태로 돌아갑니다.

x = 

새로운 변수 선언.

/* comments ; everywhere */ 

다른 상태가 스택에 푸시됩니다. 주석 토큰의 경우 등의 의미가있는 경우 ;과 같은 중요성은 무시됩니다.

a * a 

값이 x입니다.

; 

function 상태로 돌아갑니다. 특수 변수 선언 규칙 이 수행됩니다.

from pygments import highlight 
from pygments.formatters import HtmlFormatter, TerminalFormatter 
from pygments.formatters.terminal import TERMINAL_COLORS 
from pygments.lexer import inherit 
from pygments.lexers.compiled import CFamilyLexer 
from pygments.token import * 

# New token type for variable declarations. Red makes them stand out 
# on the console. 
NameDecl = Token.NameDecl 
STANDARD_TYPES[NameDecl] = 'ndec' 
TERMINAL_COLORS[NameDecl] = ('red', 'red') 

class CDeclLexer(CFamilyLexer): 
    tokens = { 
     # Only touch variables declared inside functions. 
     'function': [ 
      # The obvious fault that is hard to get around is that 
      # user-defined types won't be cathed by this regexp. 
      (r'(?<=\s)(bool|int|long|float|short|double|char|unsigned|signed|void|' 
      r'[a-z_][a-z0-9_]*_t)\b', 
      Keyword.Type, 'vardecl'), 
      inherit 
     ], 
     'vardecl' : [ 
      (r'\s+', Text), 
      # Comments 
      (r'/(\\\n)?[*](.|\n)*?[*](\\\n)?/', Comment.Multiline), 
      (r';', Punctuation, '#pop'), 
      (r'[~!%^&*+=|?:<>/-]', Operator), 
      # After the name of the variable has been tokenized enter 
      # a new mode for the value. 
      (r'[a-zA-Z_][a-zA-Z0-9_]*', NameDecl, 'varvalue'), 
     ], 
     'varvalue' : [ 
      (r'\s+', Text), 
      (r',', Punctuation, '#pop'), 
      (r';', Punctuation, '#pop:2'), 
      # Comments 
      (r'/(\\\n)?[*](.|\n)*?[*](\\\n)?/', Comment.Multiline),     
      (r'[~!%^&*+=|?:<>/-\[\]]', Operator), 
      (r'\d+[LlUu]*', Number.Integer),    
      # Rules for strings and chars. 
      (r'L?"', String, 'string'), 
      (r"L?'(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])'", String.Char), 
      (r'[a-zA-Z_][a-zA-Z0-9_]*', Name), 
      # Getting arrays right is tricky. 
      (r'{', Punctuation, 'arrvalue'), 
     ], 
     'arrvalue' : [ 
      (r'\s+', Text), 
      (r'\d+[LlUu]*', Number.Integer), 
      (r'}', Punctuation, '#pop'), 
      (r'[~!%^&*+=|?:<>/-\[\]]', Operator), 
      (r',', Punctuation), 
      (r'[a-zA-Z_][a-zA-Z0-9_]*', Name), 
      (r'{', Punctuation, '#push'), 
     ] 
    } 

code = ''' 
#include <stdio.h> 

void main(int argc, char *argv[]) 
{ 
    int vec_a, vec_b; 
    int a = 3, /* Mo;yo */ b=5, c=7; 
    int m = 3 * a + b, x = /* comments everywhere */ a * a; 
    char *myst = "hi;there"; 
    char semi = ';'; 
    time_t now = /* Null; */ NULL; 
    int arr[10] = {1, 2, 9/c}; 
    int foo[][2] = {{1, 2}}; 

    a = b * 9; 
    c = 77; 
    d = (int) 99; 
} 
''' 
for formatter in [TerminalFormatter, HtmlFormatter]: 
    print highlight(code, CDeclLexer(), formatter()) 
관련 문제