プログラミングユーティリティ

演算子

ほとんどの式は、orange のように簡単に指定することはできません。式自体は非常に長いものであったり、あるいは (こちらの方がよくある事例ですが) その式のクラスが非常に大きい可能性があります。実際、無限の大きさである可能性も考えられます。

lex 演算子 (表 2-1 を参照) を使用して、特定のクラスのあらゆる式を表すための正規表現を形成できます。たとえば + 演算子は、直前の式が 1 個以上存在することを表します (つまり、直前の式は省略可能です)。? は、直前の式が 0 個または 1 個存在することを表します。* は、直前の式が 0 個以上存在することを表します。したがって m+ は、1 個以上の m で構成される文字列すべてと一致する正規表現になります。

mmm 
m 
mmmmm 

また、7* は、0 個以上の 7 で構成される文字列すべてと一致する正規表現となります。

77 
77777 

777

空白の 3 行目が正規表現に一致したのは、その行に 7 が 1 つも含まれていないためです。

| 演算子は、二者択一を表します。したがって、ab|cdab または cd と一致します。演算子 {} は、繰り返しを指定します。したがって a{1,5} は、a が 1 〜 5 個含まれている文字列と一致します。A(B{1,4}) は、ABCABBCABBBCABBBBC と一致します (グループ化するための記号として丸括弧 ()を使用している点に注目してください)。

角括弧 [] は、角括弧内に指定された文字列のいずれかの文字を表します。したがって [dgka] は、1 個の dgk、または a と一致します。角括弧内の文字は、間に空白文字や句読点を入れないで隣接して並べてください。

^ 演算子は、左角括弧の直後の文字として使用したときには、角括弧内に指定した文字を除く標準セットのすべての文字を表します。|{}、および ^ は、他の目的で使用する場合もあるので注意してください。

標準のアルファベットや数字 (A 〜 Z、a 〜 z、0 〜 9) の範囲は、ハイフンを使用して指定します。たとえば、[a-z] は、任意の小文字を表します。

[A-Za-z0-9*&#]

これは、任意の文字 (大文字または小文字)、任意の数字、アスタリスク、アンパサント、または # と一致する正規表現の式です。

以下に示した入力テキストを与えられると、上記の仕様を規則の 1 つとして持つ字句アナライザは、*&r# を認識して、規則が指定するアクションをその認識した各文字に対して実行し、残りのテキストをそのまま出力します。

$$$$?? ????!!!*$$ $$$$$$&+====r‾‾# (( 

ハイフン文字をクラスに加えるには、[-A-Z] または [A-Z-] のように、角括弧内の最初または最後の文字として入力してください。

演算子は、組み合わせて使用すると非常に効果的です。たとえば、複数のプログラミング言語の識別子を認識するための正規表現は、次のようになります。

[a-zA-Z][0-9a-zA-Z]*

これらの言語における識別子は、文字の後にゼロ、文字、または数字が続く文字列として定義されており、上記の正規表現は、その識別子を表しています。 1 組目の角括弧は、任意の文字に一致します。2 組目の角括弧は、その後の * がなければ、任意の数字または文字に一致します。

2 つの角括弧の組とそれに囲まれた文字は、後ろに 1 個の数字または文字が続く任意の文字と一致します。しかし * が付いているため、この例は後ろに任意の数の文字または数字が続く任意の文字と一致します。たとえば、この例は以下の文字列を識別子として認識します。

e 
not 
idenTIFIER 
pH 
EngineNo99 
R2D2

一方、以下の文字列は識別子として認識されません。not_idenTIFIER には下線が含まれており、5times は文字でなく数字で始まっており、$hello は特殊文字で始まっているためです。

not_idenTIFIER
5times 
$hello 

演算子文字に潜在する問題は、検索する文字としてどのようにその演算子文字を検索パターン内で指定するかということです。たとえば、前述の例は * を含むテキストを認識しません。lex では、2 つの方法のいずれかでこの問題を解決します。バックスラッシュの後の演算子文字、二重引用符で囲まれた文字 (バックスラッシュは除く) は、そのまま文字として扱われます。つまり、検索されるテキストの一部となります。

たとえば、バックスラッシュによる方法を使用して、* の後に任意の数の数字が続く文字列を認識するには、以下のパターンを使用できます。

¥*[1-9]*

¥ 自体を認識するには、バックスラッシュを 2 つ並べる必要があります (¥¥)。同様に、"x¥*x"x*x と一致し、"y¥"z"y"z と一致します。その他の lex 演算子については、表 2-1 で説明しています。

表 2-1 lex 演算子

式 

説明 

¥x

x が lex 演算子の場合は x

"xy"

x または y が lex 演算子 (¥ は除く) の場合でも xy

[xy]

x または y 

[x-z]

x、y、または z 

[^x]

x 以外の文字 

.

復帰改行以外の文字 

^x

行の先頭の x 

<y>x

lex が開始状態 y にあるときは x

x$

行の最後の x 

x?

0 個または 1 個の x 

x*

0 個以上の x 

x+

1 個以上の x 

x{m,n}

m 〜 n 個の x 

xx|yy

xx または yy 

x |

x に対するアクションは、次の規則のアクション 

(x)

x/y

x の後に y が続く場合にのみ x 

{xx}

定義セクションからの xx の変換