2016-08-01 6 views
2

私はa text editorで、LPEGを使って構文強調表示を実装しています。物事を稼働させることはかなりシンプルでしたが、私は最低限必要な作業しか行っていませんでした。lpegを使って単語境界だけをキャプチャする

私はこのようなパターンの束を定義しました:

-- Keywords 
local keyword = C(
    P"auto" + 
    P"break" + 
    P"case" + 
    P"char" + 
    P"int" 
    -- more .. 
)/function() add_syntax(RED, ...) 

これが正しく入力を処理しますが、残念ながらあまり一致しました。たとえば、intprintfの中で一致します。これはリテラルの一致に "P"を使用しているためです。明らかに

は「INT」は「INT」に一致するように、私はワード境界に一致する必要が強調し、「適切な」実行することではなく、「printf関数」、「vsprintfの」など

私が使用してみましたこれは唯一の「<[{ \n」を後に発生に試合を制限するが、これは私がやりたいしませんでした。

-- space, newline, comma, brackets followed by the keyword 
    S(" \n(<{,")^1 * P"auto" + 

私は唯一のキーワード/トークンを一致させるためにここに欠けている、単純な、明白な、解決策があることCコードで期待される空白やその他の文字で囲まれていますか?私はキャプチャされたトークンが必要なので、私はそれを強調することができますが、そうでなければ私は特定のアプローチに結婚していません。

これらは一致する必要があります:

int foo; 
void(int argc,std::list<int,int>) { .. }; 

しかし、これはいけないを:

fprintf(stderr, "blah. patterns are hard\n"); 

答えて

3

LPeg構造-pattern(またはより具体的に-idchar次の例では)現在の一致がpatternによって(すなわちidchar)に続いていないことを確認するのに良い仕事をしていません。幸運なことに、これは入力の最後にある空文字列に対しても機能するので、特別な処理は必要ありません。一致がのパターンでの前にないことを確認するため、LPegはlpeg.B(pattern)を提供します。残念なことに、これには固定長文字列に一致するパターンが必要となり、入力の始めには機能しません。

local L = require("lpeg") 

local function decorate(word) 
    -- highlighting in UNIX terminals 
    return "\27[32;1m"..word.."\27[0m" 
end 

-- matches characters that may be part of an identifier 
local idchar = L.R("az", "AZ", "09") + L.P"_" 
-- list of keywords to be highlighted 
local keywords = L.C(L.P"in" + 
         L.P"for") 

local function highlight(s) 
    local p = L.P{ 
    (L.V"nosuffix" + "") * (L.V"exactmatch" + 1)^0, 
    nosuffix = (keywords/decorate) * -idchar, 
    exactmatch = L.B(1 - idchar) * L.V"nosuffix", 
    } 
    return L.match(L.Cs(p), s) 
end 

-- tests: 
print(highlight"") 
print(highlight"hello world") 
print(highlight"in 0in int for xfor for_ |for| in") 
+0

私は欲しいと思っていましたが、答えを欲しがっていましたが、私の期待をはるかに上回りました。受け入れられました。どうもありがとうございます。 –

+0

バウンスマジックが適用されました。 –

2

私はあなたがそれがdocumentationからの例で行うの方法に似マッチングパターンを否定すべきだと思う:

場合ワード境界でのみパターンを検索したい場合は、次のトランスを使用できます。

local t = lpeg.locale() 
function atwordboundary (p) 
    return lpeg.P{ 
    [1] = p + t.alpha^0 * (1 - t.alpha)^1 * lpeg.V(1) 
    } 
end 

このSO answerもやや似たような解決策が議論されていますので、興味があります。

また、構文ハイライトの目的で解析するためにLPegを使用するanother editor componentもありますので、どのように処理するかを見てみるとよいでしょう。

+0

OKより慎重にこれを見て:文字列の残りのための接尾辞プレフィックスをチェックパターンに戻って落ちる前に次のコードは、別途入力の先頭にlpeg.B()せずに一致させようとすることを修正するにはこのアプローチは強調表示には機能しますが、サフィックスマッチングのみを処理します。つまり「エンディング」は「終了」と一致しませんが、「販売」は一致します。 –

関連する問題