2

Python プラグインである Pygments のレクサーを使用しています。特に新しい変数が宣言されている場合など、C++ コードのトークンを取得したい

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

ここで、a、b、c には「宣言された変数」タイプを指定する必要があります。

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

ここで、a、b、c は以前に宣言されているため、単純に「変数」型を指定する必要があります。

一度に複数のトークンをスキャンするレクサーの機能を使用したい ( Pygments のドキュメントを参照) 次の行に沿って正規表現を書きたい

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

(「?:」は、このグループ化が bygroup で使用されるべきではないことを Pygments に伝えるためのものです。)

ただし、行内の任意の数の宣言に一致する代わりに、行内の最後の宣言のトークンのみを返します (この場合、「c=4」の部分)。この線?

4

1 に答える 1

3

必要なのはステートフルなレクサーです。正規表現が機能しない理由は、グループが連続していないためです。

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

ここでは、文字 0..2 を Type、3..3 スペース、4..7 Name、Equal Number、および Comma、次に Name、Equal、Number、および Comma にします。それは良くないね。

解決策は、型宣言がいつ見られたかを記憶し、次のセミコロンまで続く新しいレクサーモードに入ることです。pygments のドキュメントの状態の変更を参照 してください。

以下は、CFamilyLexer を使用し、3 つの新しいレクサー状態を追加するソリューションです。したがって、function 状態中に次のような行が表示されると:

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

最初に消費します:

int

追加した新しいルールと一致するため、次のvardecl状態になります。

m

ああ、変数の名前!lexer は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())
于 2013-02-03T13:59:55.427 に答える