詞彙分析器採取的動作

當詞彙分析器符合規格檔案之規則區段中的其中一個延伸正規表示式時,它會執行對應於延伸正規表示式的 動作 。 如果沒有足夠的規則來符合輸入串流中的所有字串,詞彙分析器會將輸入複製到標準輸出。 因此,請勿建立只將輸入複製到輸出的規則。 預設輸出可協助尋找規則中的間隙。

使用 lex 指令來處理 yacc 指令所產生剖析器的輸入時,請提供規則以符合所有輸入字串。 那些規則必須產生 yacc 指令可以解譯的輸出。

空值動作

若要忽略與延伸正規表示式相關聯的輸入,請使用; (C 語言空值陳述式) 作為動作。 下列範例會忽略三個間距字元 (空白、Tab 及換行):
[ \t\n] ;

與下一個動作相同

若要避免重複寫入相同的動作,請使用 | (垂直線符號)。 此字元指出此規則的動作與下一個規則的動作相同。 例如,前一個忽略空白、Tab 及換行字元的範例也可以撰寫如下:
" "                     |
"\t"                    |
"\n"                    ;

以引號括住\n\t不需要。

列印相符字串

若要判定哪些文字符合規格檔案之規則區段中的表示式,您可以併入 C 語言 printf 子常式呼叫作為該表示式的其中一個動作。 當詞彙分析器在輸入串流中找到相符項時,程式會將相符字串放入外部字元 (char) 和寬字元 (wchar_t) 陣列中,稱為 yytextyywtext ,分別為 。 例如,您可以使用下列規則來列印相符字串:
[a-z]+            printf("%s",yytext);

C 語言 printf 子常式接受要列印的格式引數和資料。 在此範例中, printf 子常式的引數具有下列意義:

%s
在列印之前將資料轉換為字串類型的符號
%S
在列印之前將資料轉換為寬字串 (wchar_t) 的符號
yytext
包含要列印之資料的陣列名稱
yywtext
包含要列印之多位元組類型 (wchar_t) 資料的陣列名稱
lex 指令定義 ECHO; 作為列印 yytext內容的特殊動作。 例如,下列兩個規則相等:
[a-z]+       ECHO;
[a-z]+       printf("%s",yytext);
您可以在 lex 規格檔案的定義區段中使用 %array%pointer 來變更 yytext 的表示法,如下所示:
%array
yytext 定義為以空值結尾的字元陣列。 此為預設動作。
指標 (%P)
yytext 定義為以空值結尾的字串的指標。

尋找相符字串的長度

若要尋找詞彙分析器符合特定延伸正規表示式的字元數,請使用 yylengyywleng 外部變數。
於倫
追蹤符合的位元組數。
yywleng
追蹤相符字串中的寬字元數。 多位元組字元的長度大於 1。
若要同時計算輸入中單字的數目及單字的字元數目,請使用下列動作:
[a-zA-Z]+       {words++;chars += yyleng;}

此動作會總計相符單字中的字元數,並將該數字放入chars.

下列表示式會尋找字串中符合的最後一個字元:
yytext[yyleng-1]

字串內的相符字串

lex 指令會分割輸入串流,並且不會搜尋每一個表示式的所有可能相符項。 每一個字元只會計算一次。 若要置換此選項並搜尋可能彼此重疊或併入的項目,請使用 REJECT 動作。 例如,若要計算的所有實例shehe,包括的實例he包含在she,請使用下列動作:
she              {s++; REJECT;}
he               {h++}
\n               |
.                ;

在計算的出現次數之後shelex 指令會拒絕輸入字串,然後計算出現次數he因為he不包括she,在上不需要 REJECT 動作he.

將結果新增至 yytext 陣列

通常,輸入串流中的下一個字串會改寫 yytext 陣列中的現行項目。 如果您使用 yymore 子常式,則會將輸入串流中的下一個字串新增至 yytext 陣列中現行項目的結尾。

例如,下列詞彙分析器會尋找字串:
%s instring
%%
<INITIAL>\"     {  /* start of string */
         BEGIN instring;
         yymore();
        }
<instring>\"    {  /* end of string */
         printf("matched %s\n", yytext);
         BEGIN INITIAL;
        }
<instring>.     {
         yymore();
        }
<instring>\n    {
         printf("Error, new line in string\n");
         BEGIN INITIAL;
        }

即使可以透過符合數個規則來辨識字串,重複呼叫 yymore 子常式仍可確保 yytext 陣列將包含整個字串。

將字元傳回至輸入串流

若要將字元傳回至輸入串流,請使用下列呼叫:
yyless(n)

其中n是要保留之現行字串的字元數。 超過此數字的字串中的字元會傳回至輸入串流。 yyless 子常式提供的預視函數類型與/(斜線) 運算子使用,但它容許更多控制其使用。

使用 yyless 子常式多次處理文字。 例如,在剖析 C 語言程式時,表示式如x=-a很難理解 意思是x 等於- a,或它是較舊的代表x -= a,表示 減少 x 依值 a? 將此表示式視為x 等於- a,但列印警告訊息,請使用如下所示的規則:
=-[a-zA-Z]      {
                printf("Operator (=-) ambiguous\n");
                yyless(yyleng-1);
                ... action for = ...
                }

輸入/輸出子常式

lex 程式容許程式使用下列輸入/輸出 (I/O) 子常式:
input ()
傳回下一個輸入字元
output (c)
在輸出上寫入字元 c
unput (c)
將字元 c 推回輸入串流,稍後由 input 子常式讀取
winput ()
傳回下一個多位元組輸入字元
woutput (C)
將多位元組字元 C 寫回輸出串流
wunput (C)
將多位元組字元 C 推回輸入串流,供 winput 子常式讀取

lex 程式提供這些子常式作為巨集定義。 子常式在 lex.yy.c 檔案中編碼。 您可以置換它們並提供其他版本。

winputwunputwoutput 巨集定義為使用 yywinputyywunput、 及 yywoutput 子常式。 為了相容性, yy 子常式隨後會使用 輸入unputoutput 子常式,以完整多位元組字元讀取、取代及寫入必要的位元組數。

這些子常式定義外部檔案與內部字元之間的關係。 如果您變更子常式,請以相同方式全部變更它們。 這些子常式應該遵循下列規則:
  • 所有子常式都必須使用相同的字集。
  • input 子常式必須傳回值 0 ,以指出檔案結尾。
  • 請勿變更 unput 子常式與 input 子常式的關係,否則預視函數將無法運作。

lex.yy.c 檔案容許詞彙分析器備份最多 200 個字元。

若要讀取包含空值的檔案,請建立不同版本的 input 子常式。 在正常版本的 input 子常式中,回覆值 0 (來自空值字元) 指出檔案結尾並結束輸入。

字集

lex 指令透過 輸入、輸出unput 子常式產生處理程序字元 I/O 的詞彙分析器。 因此,若要在 yytext 子常式中傳回值, lex 指令會使用這些子常式所使用的字元表示法。 不過,在內部, lex 指令會以小整數代表每一個字元。 使用標準程式庫時,此整數是電腦用來代表字元的位元型樣值。 通常,字母 a 以與字元常數 a相同的格式表示。 如果您使用不同的 I/O 子常式來變更此解譯,請將轉換表放置在規格檔案的定義區段中。 轉換表以僅包含下列項目的行開頭和結尾:
%T
轉換表包含其他行,指出與每一個字元相關聯的值。 例如:
%T
{integer}       {character string}
{integer}       {character string}
{integer}       {character string}
%T

檔案結尾處理

當詞彙分析器到達檔案結尾時,它會呼叫 yywrap 程式庫子常式,它會傳回值 1 ,以向詞彙分析器指出它應該在輸入結束時繼續正常收合。

不過,如果詞彙分析器收到來自多個來源的輸入,請變更 yywrap 子常式。 新功能必須取得新的輸入,並將值 0 傳回詞彙分析器。 回覆值 0 表示程式應繼續處理。

當詞彙分析器在新版本的 yywrap 子常式中結束時,您也可以包括程式碼來列印摘要報告和表格。 yywrap 子常式是強制 yylex 子常式辨識輸入結尾的唯一方法。