tail head cat sleep
QR code linking to this page

Man page  — FLEX

명칭

flex - 고속의 어휘분석 처리계의 생성 툴

내용

서식

flex [-bcdfhilnpstvwBFILTV78+? -C[aefFmr] -ooutput -Pprefix -Sskeleton] [--help --version] [filename ...]

개요

본메뉴얼은, 텍스트의 패턴 매칭을 실시하는 프로그램을 생성하는 툴 flex (을)를 취급합니다. 본메뉴얼은 튜토리얼과 레퍼런스절을 포함합니다:

해설 툴의 짧은 개요

간단한 예

입력 파일의 포맷

패턴 flex 가 사용하는 확장한 정규 표현

입력의 매치 방법 무엇이 매치 할까를 결정하는 규칙

액션 패턴이 매치 했을 때에 무엇을 실시하는지를 지정하는 방법

생성된 스캐너 flex 가 생성하는 스캐너에 관한 상세; 입력원의 제어 방법

개시 조건 스캐너에의 문맥의 도입과 "미니 스캐너" 의 제어 방법

복수의 입력 버퍼 복수의 입력원을 취급하는 방법; 파일은 아니고 캐릭터 라인으로부터 스캔 하는 방법

파일의 끝의 룰 파일의 끝나에 매치 하는 특별한 룰

잡다한 매크로 액션으로 사용 가능한 매크로의 통계

유저가 사용 가능한 값 액션으로 사용 가능한 값의 통계

Yacc 와의 인터페이스 lex 스캐너와 yacc 파서와의 결합

옵션 flex 의 명령행 옵션과 "%option" 지시문

성능 관련 스캐너를 가능한 한 고속으로 하는 방법

C++ 스캐너의 생성 C++ 스캐너 클래스 생성을 위한 (실험적인) 기능

Lex 및 POSIX 와의 비호환성 AT&T lex 및 POSIX lex 표준과 flex 와의 달라

진단 flex (혹은 생성한 스캐너)가 출력한다 에러 메세지로 의미가 명확하지 않은 걸

관련 파일 flex 가 사용하는 파일

결함 / 버그 flex 의 기존의 문제

관련 항목 툴에 관계하는 다른 문서

저자 연락 방법을 포함합니다

해설

flex스캐너 (을)를 생성하기 위한 툴입니다. 여기서, 스캐너란, 텍스트내의 자구 패턴을 해석하는 프로그램입니다. flex (은)는 지정한 파일, 혹은 파일명이 주어지지 않았던 경우는 표준 입력으로부터, 생성하는 스캐너의 기술을 읽어들입니다. 이 기술은, 정규 표현과 C 코드의 페어의 형태를 취하고 있습니다. 이것은 (으)로 불립니다. flex (은)는, 출력으로서 C 원시 파일의 lex.yy.c (을)를 생성합니다만, 그 중에 yylex() routine가 정의됩니다. 이 파일은 컴파일 되어 -ll 프로그램 라이브러리와 함께 링크 되어, 실행 형식이 됩니다. 실행 형식이 달리기 시작하면(자), 정규 표현을 매치 시키기 위해서(때문에) 입력이 해석됩니다. 매치 하는 것을 찾아내면(자), 대응하는 C 코드가 실행됩니다.

간단한 예

우선 간단한 예로부터, flex 의 사용법을 봐 갑시다. 다음의 flex 의 입력은,"username" 라고 하는 캐릭터 라인을 만나면(자) 유저의 로그인명에 옮겨놓는다 스캐너를 지정해 있습니다:

%% username printf( "%s", getlogin() );

디폴트에서는, flex 스캐너에 매치 하지 않았던 텍스트는 출력에 카피되기 때문에, "username" 를 전개하면서 입력을 출력에 카피하는 것이 이 스캐너의 최종적인 결과가 됩니다. 이 입력에는 다만 하나의 룰만이 있습니다. "username" 는 패턴 (이어)여,"printf" 는 액션 입니다. "%%" 는 룰의 시작의 표입니다.

다른 예를 보고 봅시다:

%{ int num_lines = 0, num_chars = 0; %}

%%   ++num_lines; ++num_chars; . ++num_chars;

%% main() { yylex(); printf( "# of lines = %d, # of chars = %d , num_lines, num_chars ); }

이 스캐너는 입력의 캐릭터수 및 행수를 셉니다 (센 최종 결과를 보고할 뿐입니다). 최초의 행은 2 개의 광역 변수 "num_lines" 와 "num_chars" 를 선언합니다. 이러한 변수는, 2 번째의 "%%" 의 뒤에 선언되고 있다 yylex() (와)과 main() 의 routine로부터 액세스 가능합니다. 여기에는 2 살의 룰이 있습니다. 1 번째는 개행 캐릭터 (" )에 매치 해, 행수와 캐릭터수의 카운트를 증가시킵니다. 이제(벌써) 1 개(살)은, 개행 캐릭터 이외의 모든 캐릭터 (". " 그렇다고 하는 정규 표현으로 나타내지고 있습니다)에 매치 합니다.

다음은 좀 더 복잡한 예입니다:

/* scanner for a toy Pascal-like language */

%{ /* need this for the call to atof() below */ #include <math.h> %}

DIGIT [0-9] ID [a-z][a-z0-9]*

%%

{DIGIT}+ { printf( "An integer: %s (%d)  , yytext, atoi( yytext ) ); }

{DIGIT}+". "{DIGIT}* { printf( "A float: %s (%g)  , yytext, atof( yytext ) ); }

if|then|begin|end|procedure|function { printf( "A keyword: %s , yytext ); }

{ID} printf( "An identifier: %s , yytext );

"+"|"-"|"*"|"/" printf( "An operator: %s , yytext );

"{"[^} *"}" /* eat up one-line comments */

[ \t + /* eat up whitespace */

. printf( "Unrecognized character: %s , yytext );

%%

main( argc, argv ) int argc; char **argv; { ++argv, --argc; /* skip over program name */ if ( argc > 0 ) yyin = fopen( argv[0], "r" ); else yyin = stdin;

yylex(); }

이것은 Pascal 와 같은 언어의 단순한 스캐너의 원형입니다. 다른 타입의 토큰 (을)를 정의해, 이것을 찾아내면(자) 보고합니다.

이 예의 자세한 것은, 이후시에로 설명합니다.

입력 파일의 포맷

flex 의 입력 파일은 3 개의 부분으로부터 되어, %% 만일 수 있는으로부터 되는 행에 의해 나눌 수 있습니다:

정의 %% 룰 %% 유저 코드

정의 부분은, 스캐너의 선언을 단순화 하는 단순한 이름 의 정의의 선언이라고 다음에 설명한다 개시 조건 의 선언이라든지들 됩니다.

이름의 정의는 다음의 형식입니다:

이름 정의

"이름" 은 말이며, 레터나 언더 스코아 ('_')로부터 시작되어 0 개 이상의 레터·숫자·'_'·'-' (데쉬)(이)가 계속됩니다. 정의는, 이름에 계속되는 최초의 비공백 캐릭터로부터 시작되어, 줄 끝까지 계속되는 것으로 여겨집니다. 정의는 다음에 "{이름}" 으로 참조할 수 있어"(정의)" 를 전개합니다. 예를 들면,

DIGIT [0-9] ID [a-z][a-z0-9]*

(은)는, "DIGIT" 가 단일의 숫자에 매치 하는 정규 표현이다고 정의해, "ID" 가 레터에 0 개 이상의 레터나 숫자가 계속되는 정규 표현이다고 정의합니다. 다음에 나오는 참조

{DIGIT}+". "{DIGIT}*

([0-9])+". "([0-9])*

(와)과 같고, 1 개 이상의 숫자에 '. '가 계속되어, 0 개 이상의 숫자가 계속되는 것에 매치 합니다.

flex 의 입력의 (은)는 다음의 형식의 일련의 룰로부터 됩니다:

패턴 액션

여기서, 패턴은 인덴트 되고 있어 안되어, 액션은 같은 행으로부터 시작될 필요가 있습니다.

패턴과 액션의 자세한 것은 후의 해설을 봐 주세요.

마지막으로, 유저 코드의 부분은 단순하게 그대로의 형태로 lex.yy.c 에 카피됩니다. 스캐너를 호출하는 또는 불려 가는 부수 routine를 위해서(때문에) 사용됩니다. 이 부분은 있어도 없어도 상관하지 않습니다; 없는 경우에는, 입력 파일중의 2 번째의 %% 도 생략 할 수 있습니다.

정의와 룰의 부분에서는, 인덴트 되었다 텍스트와 %{ (와)과 %} (와)과의 사이의 텍스트는 그대로의 형태로 출력에 카피됩니다 (이 때 %{} 는 삭제됩니다). %{} 는 인덴트되어 있지 않은 행에 나타날 필요가 있습니다.

룰의 부분에서는, 최초의 룰의 전에 나타나는 인덴트 된 혹은 %{} 부분의 텍스트는, 스캔 routine에 로컬인 변수와 (선언의 후에는) 스캔 routine에 들어갈 때마다 실행되는 코드를 선언합니다. 룰 부분의 다른 인덴트 된 혹은 %{} 부분의 텍스트는 출력에 카피됩니다만, 의미는 분명하게 정의되지 않고 컴파일시에 에러가 될지도 모릅니다 (이 사양은 POSIX 호환을 위해서(때문에) 있습니다; 다른 이러한 사양은 이후를 봐 주세요).

정의의 부분(룰의 부분은 아닙니다)에서는, 인덴트되어 있지 않은 코멘트("/*" 로부터 시작되는 행)는 다음의 것 "*/" 까지 그대로의 형태로 카피됩니다.

패턴

입력 파일의 패턴은 확장한 정규 표현을 사용해 기술합니다. 이하에 나타냅니다:

x 캐릭터 'x'에 매치. . 개행을 제외한 모든 캐릭터(바이트). [xyz] "캐릭터 클래스"; 이 경우, 'x', 'y', 'z'의 어느 것에도 매치 합니다. [abj-oZ] 범위 지정을 포함한 "캐릭터 클래스"; 이 경우, 'a', 'b'와 'j'로부터 'o'까지의 임의의 레터와 'Z'에 매치 합니다. [^A-Z] "부정문자 클래스"; 클래스에 포함되지 않는 임의의 캐릭터에 매치 합니다. 이 경우, 'A'로부터 'Z'까지의 대문자 「이외의」캐릭터에 매치 합니다. [^A-Z  대문자와 개행을 「제외하다」모든 캐릭터. r* 0 혹은 그 이상의 r. r 는 임의의 정규 표현. r+ 1 혹은 그 이상의 r. r? 0 혹은 1개의 r ( 「덤」의 r) r{2,5} 2 개(살)에서 5개까지의 r. r{2,} 2 개(살) 이상의 r. r{4} 정확히 4개의 r. {이름} "이름" 의 정의의 전개. (위를 참조) "[xyz]\"foo" 캐릭터 라인 [xyz]"foo \X X 가 'a', 'b', 'f', 'n', 'r', 't', 'v'의 몇개의 (이)라고 해 ANSI-C 에서의 \X 의 해석이 됩니다. 그 이외의 경우, 캐릭터 'X' ('*'와 같은 오퍼레이터의 의미를 지워, 그 캐릭터 자체를 지정할 때에 사용합니다). \123 8 진수로 123 으로 나타내지는 캐릭터. \x2a 16 진수로 2a 로 나타내지는 캐릭터. (r) r 에 매치; ()은 우선 순위를 바꾸기 위해서(때문에) 사용. (이하를 참조)

rs 정규 표현 r 에 정규 표현 s 가 계속되는; 「연결(concatenation)」 (이)라고 부릅니다.

r|s r 혹은 s.

r/s 뒤로 s 가 계속될 때의 r. s 에 매치 하는 텍스트는 이 룰의 "최장 적합" 을 판정한다 때로는 포함됩니다만, 액션이 실행되기 전에 입력에 되돌려집니다. 액션은 r 에 매치 하는 텍스트만을 봅니다. 이 패턴은 "우문맥(trailing context)" 으로 불립니다. (flex 가 정확하게 매치 불능인 r/s 의 편성은 다수 있습니다; "위험한 우문맥" 에 대해서는, 이후의, 결함 / 버그의 마디의 기술을 봐 주세요. ) ^r 줄머리에 있는 r. (스캔의 시작 혹은 스캔 된 개행의 오른쪽입니다). r$ 줄 끝에 있는 r. "r/  와 등가(개행 전입니다). "r/  와 같습니다.

flex 의 "개행" 의 표현은 flex 를 컴파일 했다 C 컴파일러가 해석하는 ' 와 완전하게 일치하는 것에 주의해 주세요; 특정의 시스템 DOS 에서는 \r 를 입력으로부터 없앨까 "r$" 를 나타내기 위해서(때문에) 명시적으로 r/\r 를 사용할 필요가 있습니다.

<s>r 개시 조건 s 에 있어서의 r. (개시 조건에 대해서는 이하를 참조). <s1,s2,s3>r 위에 같다. 다만 개시 조건은 s1, s2, s3 의 머지않아 이라도 좋다. <*>r 임의의 개시 조건의 r. 개시 조건은 배타적인 물건이라도 좋다.

<<EOF>> 파일의 종료. <s1,s2><<EOF>> 개시 조건이 s1 혹은 s2 일 때의 파일의 종료.

캐릭터 클래스안에서는, 모든 정규 표현의 오퍼레이터는, 이스케이프 ('\') 및 캐릭터 클래스 오퍼레이터인 '-'와 ']'와 클래스의 선두의 '^'를 제외해 특별한 의미를 잃는 것에 주의해 주세요.

우에에 둔 정규 표현은 우선 순위에 의해 그룹으로 나눌 수 있고 있습니다. 맨 위의 그룹이 가장 높은 우선도로, 맨 밑의 그룹의 우선 순위가 가장 낮아지고 있습니다. 그룹내에서는 같은 우선 순위입니다. 예를 들면,

foo|bar*

(foo)|(ba(r*))

(와)과 같습니다. 왜냐하면 '*'오퍼레이터는 연결보다 우선도가 높고, 연결은 선거말 ('|')보다 우선도가 높기 때문입니다. 이 패턴은 캐릭터 라인 "foo" 혹은 캐릭터 라인 "ba" 에 0 개 이상의 r 가 계속되지만 어느 쪽에도 매치 합니다. "foo" 혹은 0 개 이상의 "bar" 에 매치 시키기 위해서(때문에)는 다음의 표현을 사용해 주세요:

foo|(bar)*

0 개 이상의 "foo" 또는 "bar" 에 매치 하기 위해서는 다음의 표현을 사용해 주세요:

(foo|bar)*

캐릭터 혹은 캐릭터 범위에 가세해 캐릭터 클래스도 캐릭터 클래스의 표현 (을)를 포함합니다. 이러한 표현은 [::] 의 딜리미터에 둘러싸입니다 (캐릭터 클래스의 '['와 ']'와의 사이에 나타날 필요가 있습니다; 다른 요소가 캐릭터 클래스안에 나타나도 상관하지 않습니다). 유효한 표현은 이하와 같습니다:

[:alnum:] [:alpha:] [:blank:] [:cntrl:] [:digit:] [:graph:] [:lower:] [:print:] [:punct:] [:space:] [:upper:] [:xdigit:]

이러한 표현은 대응하는 표준 C 의 isXXX 함수에 적합하는 모든 캐릭터 집합을 지시합니다. 예를 들면, [:alnum:]isalnum() 하지만 진을 돌려주는 캐릭터를 지시합니다 - 즉 모든 알파벳과 숫자입니다. isblank(), 하지만 없는 시스템에서는, flex 는 [:blank:] (을)를 공백과 탭이라고 정의합니다.

예를 들면 이하의 표현은 모두 같습니다:

[[:alnum:]] [[:alpha:][:digit:]] [[:alpha:]0-9] [a-zA-Z0-9]

스캐너가 대문자 소문자를 의식하지 않는 경우( -i 플래그 지정시) [:upper:] (와)과 [:lower:][:alpha:] (와)과 같습니다.

패턴에 관한 주의점입니다:
- 부정문자 클래스, 예를 들면 위의 "[^A-Z]" 는 "  (혹은 이것을 나타내는 escape sequence)가 명시적으로 부정문자 클래스에 나타나고 있는 경우 (예를 들면 "[^A-Z ")를 제외해 개행에 매치 합니다. 이것은 다른 정규 표현 툴이 부정문자 클래스를 취급하는 방법과는 다릅니다만, 불행한 일로 이 모순은 역사적으로 확립해 있습니다. 개행에 매치 한다는 것은, 입력에 다른 쿼츠가 존재하지 않는 경우에 [^"]* 와 같은 패턴이 입력 전체에 매치 하는 것을 의미합니다.
- 룰은 우문맥('/'오퍼레이터 혹은 '$'오퍼레이터) (을)를 고들 한 살 밖에 가질 수 없습니다. 개시 조건 '^'와 "<<EOF>>" 패턴은 패턴이 최초로 없으면 안되어, '/', '$' (와)과 같이 () 안에 넣을 수 없습니다. 룰의 선두는 아닌 '^'혹은 룰의 끝은 아닌 '$'는 특별한 의미를 잃어, 통상의 캐릭터로서 다루어집니다.
이하는 무효입니다:

foo/bar$ <sc1>foo<sc2>bar

전자는 "foo/bar  라고 쓸 수 있습니다.
이하에서는 '$'와 '^'와는 통상의 캐릭터로서 다루어집니다:

foo|(bar$) foo|^bar

"foo" 혹은 "개행이 계속되는 bar" 를 지정하고 싶은 경우는, 다음의 표현을 사용해 주세요 (특별한 '|'의 동작은 다음에 설명합니다):

foo | bar$ /* action goes here */

같은 방법으로, foo 혹은 줄머리의 bar 를 지정 가능합니다.

입력의 매치 방법

생성한 스캐너를 실행하면(자), 스캐너는 입력을 봐 패턴에 매치 하는 캐릭터 라인을 찾습니다. 1 보다 많은 매치을 찾아내면(자), 최장 텍스트의 성냥을 채용합니다 (우문맥(trailing context rule)의 뒤의 부분도 길이에 포함합니다만, 뒤의 부분은 입력에 되돌려집니다). 같은 길이의 매치을 2 개 이상 찾아냈을 경우, flex 입력 파일로 최초로 기술된 룰을 채용합니다.

매치이 결정되면(자), 성냥에 대응하는 텍스트( 토큰 (으)로 불립니다)가 글로벌 캐릭터 포인터 yytext 에 의해 사용 가능해져, 길이가 글로벌 정수 yyleng 에 의해 사용 가능해집니다. 그 후, 매치 한 패턴에 대응한다 액션 하지만 실행되고(액션의 상세한 기술은 다음에 실시합니다), 나머지의 입력이 나머지의 매치을 위해서(때문에) 스캔 됩니다.

매치이 발견되지 않으면 디폴트 룰 하지만 실행됩니다: 입력의 다음의 캐릭터가 매치 했다고 보고 방 되어 표준 출력에 카피됩니다. 가장 간단하고 정당한 flex 의 입력은 이하와 같습니다:

%%

이것은, 입력을 단순하게 출력에 카피(1 번에 1 캐릭터씩)하는 스캐너를 생성합니다.

yytext (은)는 2 개(살)이 다른 방법에 의해 정의될 수 있는 일로 주의해 주세요: 캐릭터 포인터 혹은 캐릭터 배열 입니다. flex 하지만 어느 쪽의 정의를 사용할까는 특별한 지시문 %pointer 혹은 %array (을)를 flex 의 입력의 최초의(정의) 부분에 포함하는 것으로 제어할 수 있습니다. 디폴트는 %pointer (이어)여, -l lex 호환 옵션을 사용했을 경우에는 예외적으로 yytext (은)는 배열이 됩니다. %pointer (을)를 사용하는 이점은 스캔이 고속으로 있는 것, 매우 큰 토큰에 매치 할 때에도 (동적 메모리를 다 사용하지 않는 한) 버퍼 오버플로우가 되지 않는 것입니다. 결점은, 액션이 yytext (을)를 수정하는 것이 제한되는 것(차절 참조), unput() 호출이 yytext 의 현재의 내용을 파괴하는 것입니다. 이것은 다르다 lex 버젼간에서의 이식성에 관한 두통거리입니다.

%array 의 이점은 yytext 의 내용을 뜻한대로 변경할 수 있는 것, unput() (을)를 호출해도 yytext 의 내용이 파괴되지 않는 것입니다(아래와 같이 참조). 게다가, 기존의 lex 프로그램은 yytext (을)를 외부로부터 다음의 형식의 선언을 사용해 액세스 하고 있는 일이 있습니다:

    extern char yytext[];
이 정의는 %pointer 사용시에는 잘못입니다만, %array 사용시에는 올바릅니다.

%arrayyytext (을)를 캐릭터수 YYLMAX (디폴트는 충분히 큰 값)의 배열이다고 정의합니다. 이 크기는, flex 의 입력의 최초의 부분에서 단순하게 YYLMAX (을)를 다른 값에 #define 하는 것으로써 변경할 수 있습니다. 상기대로, %pointer 사용시에는 yytext 는 큰 토큰을 격납하기 위해서 동적으로 커집니다. 이것은 %pointer (을)를 사용한 스캐너는 매우 큰 토큰 (예를 들면 코멘트 블록 전체)(을)를 격납 가능한 것을 의미합니다만, 스캐너가 yytext 의 크기를 바꿀 때마다 토큰 전체를 선두로부터 재스캔 하는 것이 필요하기 (위해)때문에 이러한 토큰에 대한 매칭은 늦어질 수 있는 일을 기억해 두어 주세요. 현재, yytextunput() 하지만 결과적으로 돌려주는 텍스트가 클 때에는 동적이게는 커져 선; 실행시 에러가 됩니다.

또, %array 하 C++ 스캐너 클래스에서는 사용할 수 없는 것에 주의해 주세요( c++ 옵션에 관해서는 아래와 같이 참조).

액션

룰중의 패턴은 대응하는 액션을 가집니다. 액션은 임의의 C 의 문장입니다. 패턴은 최초의 이스케이프되어 있지 않은 공백 캐릭터로 끝납니다; 행의 나머지가 액션입니다. 액션이 하늘인 경우, 패턴이 매치 했을 때에 입력 토큰은 단순하게 버려집니다. 예를 들면 입력으로부터 모든 "zap me" 를 삭제하는 프로그램의 사양을 나타냅니다:

%% "zap me"

(입력의 다른 모든 캐릭터를 출력에 카피합니다. 왜냐하면 디폴트 룰에 매치 하기 때문입니다. )

다음은, 복수의 공백이나 캐릭터를 단일의 공백에 압축해 줄 끝의 공백을 버리는 프로그램입니다:

%% [ \t]+ putchar( ' ' ); [ \t]+$ /* ignore this token */

액션이 '{'를 포함한 경우, 액션은 대응하는 '}'까지 계속되어, 복수행에 건너는 경우도 있습니다. flex (은)는 C 의 캐릭터 라인 및 코멘트에 관해서 알고 있어, 그러한 안의 brace를 오해할 것은 없습니다만, 액션이 %{ 그리고 시작되는 것을 허락해, 다음의 %} 까지의 텍스트가 액션이다고 합니다 (액션 내부의 임의개의 brace에는 관계 없습니다).

수직 바 ('|')만으로부터 되는 액션은 "다음의 룰과 같은" 을 의미합니다. 설명은 이하를 봐 주세요.

액션은 임의의 C 코드를 포함할 수가 있습니다. 이것에는, yylex() (을)를 호출한 routine에 대해서 값을 돌려준다 return 문장도 포함됩니다. yylex() 하지만 불릴 때, 마지막에 남은 토큰으로부터 처리를 재개해, 파일의 종료 혹은 return 를 실행할 때까지 처리를 실시합니다.

액션은 자유롭게 yytext (을)를 변경할 수 있습니다만, 예외는 길이를 늘리는 것입니다 (캐릭터를 말미에 가세하게 되어, 이것은 입력 스트림의 후속 하는 캐릭터를 덧쓰기합니다). 이것은 %array 사용시에는 들어맞지 않습니다(상술); 이 경우 yytext (을)를 자유롭게 변경할 수 있습니다.

액션은 자유롭게 yyleng (을)를 변경할 수 있습니다만, 액션이 yymore() (을)를 사용할 때에는 예외적으로 변경 해서는 안됩니다(후술).

많은 특별한 지시문이 있어, 액션중에 포함할 수가 있습니다:
- ECHO yytext 를 스캐너의 출력에 카피합니다.
- BEGIN 뒤로 개시 조건의 이름을 쓰면(자), 스캐너를 대응하는 개시 조건으로 설정합니다(후술).
- REJECT 입력(혹은 입력의 머리)에 "2 번째에 자주(잘)(second best)" 매치 하는 룰 에 진행되도록(듯이) 스캐너에 지시합니다. "입력의 매치 방법" 으로 가리킨 것처럼 룰은 선택되어 yytext (와)과 yyleng (은)는 적절히 설정됩니다. 선택되는 룰은, 최초로 선택된 룰과 같은 길이이지만 flex 의 입력 파일에서 다음에 나오는 것, 혹은 적은 캐릭터수에 매치 하는 것입니다. 예를 들면 다음의 예에서는 입력중의 말을 세어 "frob" 가 발견될 때마다 routine special()를 부릅니다:

int word_count = 0; %%

frob special(); REJECT; [^ \t + ++word_count;

REJECT 하지만 없는 경우, 입력중의 "frob" 는 말로서 셀 수 있는 두, 스캐너는 통상 대로 토큰마다 1 개의 액션만을 실시합니다. 복수의 REJECT (을)를 사용 가능하고, 각각 현재 유효한 룰의 다음에 좋은 선택을 찾아냅니다. 예를 들면 다음의 스캐너는,"abcd" 라고 하는 토큰을 스캔 해, 출력에 "abcdabcaba" 를 씁니다:

%% a | ab | abc | abcd ECHO; REJECT; . |  /* eat up any unmatched character */

(전의 3 살의 룰은 4 번째의 룰의 액션을 공유합니다. 왜냐하면 특별한 '|'액션이 사용되고 있기 때문입니다. ) REJECT (은)는 스캐너의 성능이라고 하는 점으로 특히 코스트가 드는 기능입니다; 만약 스캐너의 액션의 언젠가 (이)라도 REJECT 가 사용되었다면, 스캐너의 모든 매칭 속도를 저하시킨다고 하는 것입니다. 한층 더 REJECT (을)를 옵션 -Cf (이)나 -CF (와)과 함께 이용할 수 없습니다.
또, 다른 특별 액션과 달라 REJECT분기(branch) 인 것에 주의해 주세요; 즉 REJECT 직후의 액션은 실행 되지 않습니다.
- yymore() 다음에 룰과 매치 했을 때에는, 대응하는 토큰은, 현재의 yytext 의 내용과 바꿔 넣는 것이 아니라 yytext추가 하도록(듯이) 스캐너에 지시합니다. 예를 들면, 입력 "mega-kludge" 가 주어지면(자), 이하는 "mega-mega-kludge" 를 출력에 씁니다:

%% mega- ECHO; yymore(); kludge ECHO;

최초의 "mega-" 는 매치 해 출력에 에코 됩니다. 다음에 "kludge" 가 매치 합니다만, 직전의 "mega-" 가 아직 yytext 의 선두에 남아 있어"kludge" 의 ECHO 룰은 실제로는 "mage-kludge" 를 씁니다.
yymore() 의 사용에 관계되어 2 개의 주의점이 있습니다. 우선, yymore() (은)는 현재의 토큰의 크기를 반영한다 yyleng 의 값의 정확함에 의존하는 것이어, yymore() 사용시에는 yyleng (을)를 변경해 되지 않습니다. 다음에, 스캐너의 액션에 yymore() (이)가 있으면(자), 스캐너의 매치 속도에 약간 악영향이 있습니다.
- yyless(n) 현재의 토큰으로부터 최초의 n 캐릭터를 제외한 것을 입력 스트림에 되돌립니다. 되돌린 캐릭터 라인은 스캐너가 다음의 매칭을 취할 때 재차 스캔 됩니다. yytext (와)과 yyleng (은)는 적절히 조정됩니다(예를 들면 yylengn 됩니다). 예를 들면, 입력 "foobar" 가 주어지면(자), 이하는 "foobarbar" 를 씁니다:

%% foobar ECHO; yyless(3); [a-z]+ ECHO;

인수 0 을 yyless 에게 주면(자), 현재의 입력 캐릭터 라인 전체가 재차 스캔 됩니다. (예를 들면 BEGIN (을)를 사용해) 다음에 스캐너가 입력하는 방법을 변경하고 있지 않으면 엔들레스 루프가 됩니다.
yyless (은)는 매크로이며, flex 입력 파일에서만 사용 가능하고, 다른 원시 파일로부터는 사용 불능인 것에 주의해 주세요.
- unput(c) 캐릭터 c (을)를 입력 스트림에 되돌립니다. 되돌린 캐릭터는 다음에 스캔 되는 캐릭터가 됩니다. 다음의 액션은 현재의 토큰을 채택해 괄호내에 들어갈 수 있어 재스캔 합니다.

{ int i; /* Copy yytext because unput() trashes yytext */ char *yycopy = strdup( yytext ); unput( ')' ); for ( i = yyleng - 1; i >= 0; --i ) unput( yycopy[i] ); unput( '(' ); free( yycopy ); }

unput() (은)는 캐릭터를 입력 스트림의 선두 에 되돌리므로, 캐릭터 라인을 되돌리는 경우에는 뒤로부터 전으로 향해 되돌릴 필요가 있습니다.
unput() 사용시의 중요한 잠재적인 문제는, %pointer 사용시(디폴트)에 unput() (을)를 호출하면(자), 우단의 캐릭터로부터 개시해 1 캐릭터씩 왼쪽을 향해 소비되어 yytext 의 내용이 파괴 되는 것입니다. (상기 예의 같게) unput() 호출 후도 yytext 의 내용을 보존하기 위해서는, 시작해에 다른 장소에 카피하는지, 스캐너를 %array (을)를 사용하도록(듯이) 구축하는 것입니다(입력의 매치 방법 참조).
마지막으로, EOF (을)를 되돌려 입력 스트림에 파일의 끝을 마크 한다고는 할 수 없는 것에 주의해 주세요.
- input() 다음의 캐릭터를 입력 스트림로부터 읽습니다. 다음의 예는 C 코멘트를 먹습니다:

%% "/*" { register int c;

for ( ; ; ) { while ( (c = input()) ! = '*' && c ! = EOF ) ; /* eat up text of comment */

if ( c == '*' ) { while ( (c = input()) == '*' ) ; if ( c == '/' ) break; /* found the end */ }

if ( c == EOF ) { error( "EOF in comment" ); break; } } }

(스캐너가 C++ 그리고 컴파일 되었을 때는, 이 routine는 yyinput() 그렇다고 하는 명칭이 되어, C++ 스트림의 input (와)과 이름이 충돌하는 것을 피합니다. )
- YY_FLUSH_BUFFER 스캐너의 내부 버퍼를 플래시 해, 다음에 스캐너가 토큰을 매치 하려고 했을 때 버퍼를 YY_INPUT 에서 리필 합니다(생성된 스캐너로 후술). 이 액션은, 복수의 입력 버퍼에 대해 후술 한다 보다 일반적인 yy_flush_buffer() 함수의 특별한 케이스입니다.
- yyterminate() 액션의 return 문 대신에 사용할 수가 있습니다. yyterminate() (은)는 스캐너를 종료해,"모두 종료" 를 의미하는 0 을 호출해 원함수에 돌려줍니다. 디폴트에서는 yyterminate() (은)는 파일의 마지막에 이르렀을 때에도 불립니다. yyterminate() (은)는 매크로이며, 정의 다시 할 수가 있습니다.

생성된 스캐너

flex 의 출력은 lex.yy.c 그렇다고 하는 파일이며, 스캔 routine yylex() 라고 토큰의 매칭에 사용하는 복수의 테이블과 복수의 부속 routine와 매크로로부터 됩니다. 디폴트에서는, yylex() (은)는 다음과 같이 선언됩니다:

int yylex() { ... various definitions and the actions in here ... }

(환경이 함수 prototype를 서포트하고 있는 경우, "int yylex( void )" 가 됩니다. ) 이 정의는 "YY_DECL" 매크로를 정의하는 것으로써 변경할 수 있습니다. 예를 들면 다음과 같이 사용할 수가 있습니다:

#define YY_DECL float lexscan( a, b ) float a, b;

이것은 스캔 routine의 이름을 lexscan (으)로 해, 부동 소수점수(실수)를 돌려주도록(듯이) 해, 2 개의 부동 소수점수(실수)를 인수로 합니다. K&R 의 비prototype의 함수 선언을 사용해 스캔 routine에 대해서 인수를 주는 경우, 정의를 세미콜론(;)으로 종료할 필요가 있습니다.

yylex() (은)는 불릴 때, 글로벌 입력 파일 yyin (디폴트에서는 표준 입력)(으)로부터 토큰을 스캔 합니다. 파일의 끝이 되는(이 경우 0 을 돌려줍니다)인가, 액션이 return 문장을 실행할 때까지, 실행을 계속합니다.

스캐너가 파일의 끝나에 도달하면(자), yyin 하지만 새로운 파일을 가리키지 않는가 (새로운 파일을 가리키는 경우는 이 파일의 스캔을 계속합니다), yyrestart() 하지만 불리지 않는 이상 후속 하는 호출은 미정도리입니다. yyrestart()FILE * 포인터( YY_INPUT (을)를 설정해 yyin 이외의 소스를 스캔 하도록(듯이) 했을 경우에는 nil 도 가능입니다) 인 인수를 1 개 취해, 그 파일로부터의 스캔을 위해서(때문에) yyin (을)를 초기화합니다. 본질적으로, yyin (을)를 새로운 입력 파일에 할당하는 것으로 yyrestar() (을)를 사용하는 것으로는 같습니다; 후자는 전의 버젼의 flex (와)과의 호환성을 위해서(때문에) 사용 가능하고, 또 스캔의 도중에 입력 파일을 바꾸는 것이 가능합니다. 인수를 yyin (으)로서 호출하는 것으로, 현재의 입력 버퍼를 버릴 수도 있습니다; 다만, YY_FLUSH_BUFFER (상술)(을)를 사용하는 편이 좋습니다. yyrestart()INITIAL 의 개시 조건을 변경해 없다 일로 주의해 주세요 (후술의 개시 조건 참조).

어느 액션중에서 return 문장을 실행하는 것으로써 yylex() 하지만 스캔을 멈추었을 경우, 스캐너는 재차 호출해 가능하고, 이 경우 스캔의 나머지의 부분으로부터 재개합니다.

디폴트로(효율이기 때문에), 스캐너는 단순한 getc() 콜은 아니고 블록 리드를 실시해, yyin (으)로부터 캐릭터를 읽습니다. 입력 취득 방법은 YY_INPUT 매크로를 정의하는 것으로써 제어할 수 있습니다. YY_INPUT 호출 순서는 "YY_INPUT(buf, result, max_size)" 입니다. 이 액션은, buf 캐릭터 배열중에 최대 max_size 캐릭터를 준비해, 정수 변수 result 안에 읽을 수 있었던 캐릭터수 혹은 정수 YY_NULL (Unix 시스템에서는 0)를 넣어 돌려줍니다. 디폴트의 YY_INPUT 는 글로벌 파일 포인터 "yyin" 로부터 읽습니다.

YY_INPUT 의 샘플 정의입니다(입력 파일의 정의부에 격납):

%{ #define YY_INPUT(buf, result, max_size) \ { \ int c = getchar(); \ result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \ } %}

이 정의에 의해, 입력 처리는 1 번에 1 캐릭터씩 실시하도록(듯이) 변경됩니다.

스캐너가 YY_INPUT 로부터 파일의 끝이 통지되었을 경우, 스캐너는 yywrap() 함수를 체크합니다. yywrap() 함수가 가짜(제로)를 돌려주는 경우, 함수는 속행중이라고 되어 yyin (을)를 다른 입력 파일을 가리키도록(듯이) 설정해, 스캔을 속행합니다. 함수가 진(비제로)을 돌려주는 경우, 스캐너는 종료해, 호출 바탕으로 0 을 돌려줍니다. 어느 쪽의 경우도 개시 조건은 변화하지 않는 것에 주의해 주세요; 즉 INITIAL 에는 귀가 선.

독자적인 yywrap() (을)를 설정하지 않는 경우, %option noyywrap (이 경우 스캐너는 yywrap() 하지만 1 을 돌려주었는지와 같이 동작합니다)를 사용하는지, 플래그 -ll (을)를 지정해 디폴트의 routine(항상 1 을 돌려줍니다)를 사용하지 않으면 안됩니다.

파일은 아니고 메모리중의 버퍼로부터 스캔하기 위한 3 개의 routine를 사용 가능합니다: yy_scan_string(), yy_scan_bytes(), yy_scan_buffer() 이것들에 관한 논의는 복수의 입력 버퍼의 마디를 참조해 주세요.

스캐너는, 자기의 ECHO 출력을 yyout 글로벌(디폴트에서는 표준 출력이며, 다른 FILE 포인터에 할당하는 것으로 재정의할 수 있습니다)에 씁니다.

개시 조건

flex (은)는, 조건적으로 유효가 되는 룰을 위한 기구를 제공합니다. 패턴의 프레픽스가 "<sc>" 되고 있는 룰은, 스캐너가 "sc" 라는 이름의 개시 조건에 있는 경우만 유효합니다. 예를 들면,

<STRING>[^"]* { /* eat up the string body ... */ ... }

(은)는 스캐너가 "STRING" 개시 조건에 있을 때 마셔 유효하고,

<INITIAL,STRING,QUOTE>\. { /* handle an escape ... */ ... }

(은)는 현재의 개시 조건이, "INITIAL", "STRING", "QUOTE" 의 몇개의 경우만 유효합니다.

개시 조건은, 입력의 정의(선두) 부에 있어, 인덴트 되지 않는 행으로 %s 혹은 %x (으)로부터 시작 이름이 계속되는 행에 대해 선언됩니다. 전자는 내포적 개시 조건을, 후자는 배타적 개시 조건을, 각각 선언합니다. 개시 조건을 유효하게 하는 것은 BEGIN 액션입니다. 다음의 BEGIN 액션이 실행될 때까지, 주어진 개시 조건의 룰은 유효하고, 다른 개시 조건의 룰은 무효입니다. 개시 조건이 내포적 경우, 개시 조건을 가지지 않는 룰도 또 유효합니다. 개시 조건이 배타적 경우, 개시 조건을 채우는 룰 하지만 유효합니다. 같은 배타 개시 조건에 의존하는 룰의 조는, flex 입력중의 다른 룰과는 독립인 스캐너를 기술합니다. 그 때문에, 배타 개시 조건을 사용하면,"미니 스캐너" (별부분과는 문법적으로 다른 부분(예를 들면 코멘트)에 대한 스캐너) (을)를 간단하게 지정할 수 있습니다.

내포적 개시 조건과 배타적 개시 조건이 아직 조금 애매하다면, 양자의 관계를 나타내는 예를 나타내 설명합니다. 이하의 룰의 조:

%s example %%

<example>foo do_something();

bar something_else();

%x example %%

<example>foo do_something();

<INITIAL,example>bar something_else();

(와)과 등가입니다. <INITIAL,example> 하지만 없으면 2 번째의 예에 있어서의 bar 패턴은, 개시 조건이 example 의 경우, 유효가 되지 않습니다(즉 매치 하지 않습니다). <example> 만을 bar 에 붙이면(자), example 인 만큼 있어 유효가 되어, INITIAL 그럼 유효가 되지 않습니다. 한편, 최초의 예에서는 어느 쪽의 경우에서도 유효합니다. 왜냐하면 최초의 예에서는 example 개시 조건은 내포적 (%s) 개시 조건이기 때문입니다.

특수한 개시 조건 지정자 <*> (은)는 모든 개시 조건에 매치 하는 것에 주의해 주세요. 이 때문에, 위의 예는 다음과 같이도 쓸 수 있습니다;

%x example %%

<example>foo do_something();

<*>bar something_else();

디폴트 룰(매치 하지 않았던 캐릭터에 대해서는 ECHO 입니다)는 개시 조건중에서도 유효합니다. 이것은 다음의 것과 등가입니다:

<*>. |  ECHO;

BEGIN(0) (은)는, 개시 조건이 없는 룰만이 유효하다, 최초 상태로 돌아옵니다. 이 상태는 개시 조건 "INITIAL" 로서 참조할 수 있기 (위해)때문에, BEGIN(INITIAL)BEGIN(0) (와)과 등가입니다. (개시 조건명을 괄괄호는 불필요합니다만, 좋은 스타일이라고 되고 있습니다. )

BEGIN 액션은, 룰부의 선두의 인덴트 된 코드중에 나타나도 좋습니다. 예를 들면 이하의 예에서는, yylex() 하지만 불리고 글로벌 변수 enter_special 하지만 진정한 경우에는, 스캐너는 "SPECIAL" 개시 조건에 들어갑니다:

int enter_special;

%x SPECIAL %% if ( enter_special ) BEGIN(SPECIAL);

<SPECIAL>blahblahblah ...more rules follow...

개시 조건을 설명하기 위해서, "123.456" 과 같은 캐릭터 라인을 2 방법이 다른 해석을 하는 스캐너를 나타냅니다. 디폴트에서는 이것은, 정수 "123" 으로 닷 ('. ')와 정수 "456" 의 3 토큰으로 꼽힙니다. 그러나, 이 캐릭터 라인의 전에 "expect-floats" 의 캐릭터 라인이 있는 경우, 이것은 단일의 토큰이라고 되어 부동 소수점수(실수) 123.456 으로 여겨집니다:

%{ #include <math.h> %} %s expect

%% expect-floats BEGIN(expect);

<expect>[0-9]+". "[0-9]+ { printf( "found a float, = %f , atof( yytext ) ); } <expect>  { /* that's the end of the line, so * we need another "expect-number" * before we'll recognize any more * numbers */ BEGIN(INITIAL); }

[0-9]+ { printf( "found an integer, = %d , atoi( yytext ) ); }

". " printf( "found a dot  );

다음은, C 의 코멘트를 이해(해 버린다) 한편, 현재의 입력행을 세는 스캐너입니다.

%x comment %% int line_num = 1;

"/*" BEGIN(comment);

<comment>[^* * /* eat anything that's not a '*' */ <comment>"*"+[^*/ * /* eat up '*'s not followed by '/'s */ <comment>  ++line_num; <comment>"*"+"/" BEGIN(INITIAL);

이 스캐너는 각 룰로 가능한 최대의 텍스트에 매치 하려고 하는 경우, 약간의 문제가 일어납니다. 일반적으로는, 고속의 스캐너를 기술하는 경우, 각 룰로 최대의 매치을 얻으려고 하는 것이 가장 성공합니다.

개시 조건명은 실제로는 정수치이며, 격납할 수가 있는 것에 주의해 주세요. 그 때문에, 상기예는 이하와 같이 확장할 수 있습니다:

%x comment foo %% int line_num = 1; int comment_caller;

"/*" { comment_caller = INITIAL; BEGIN(comment); }

...

<foo>"/*" { comment_caller = foo; BEGIN(comment); }

<comment>[^* * /* eat anything that's not a '*' */ <comment>"*"+[^*/ * /* eat up '*'s not followed by '/'s */ <comment>  ++line_num; <comment>"*"+"/" BEGIN(comment_caller);

게다가 현재의 개시 조건을 정수치인 매크로 YY_START 에서 액세스 할 수 있습니다. 예를 들면, 상기의 comment_caller 에의 대입은 다음과 같이 기술할 수 있습니다.

comment_caller = YY_START;

flex 는 YYSTATE (을)를 YY_START 의 앨리어스(alias)로서 제공합니다 (AT&T 의 lex 하지만 사용하고 있습니다).

개시 조건은 독자적인 이름 공간을 가지지 않는 것에 주의해 주세요; %s 나 %x 의 선언에 있어서의 이름 선언의 취급은 #define 와 같습니다.

마지막으로, 배타적 개시 조건을 사용하는, 전개된 escape sequence를 포함한다(너무 긴 캐릭터 라인의 체크는 포함하지 않습니다) C 스타일의 쿼츠 캐릭터 라인에의 매치 방법을 나타냅니다:

%x str

%% char string_buf[MAX_STR_CONST]; char *string_buf_ptr;

\" string_buf_ptr = string_buf; BEGIN(str);

<str>\" { /* saw closing quote - all done */ BEGIN(INITIAL); *string_buf_ptr = '\0'; /* return string constant token type and * value to parser */ }

<str>  { /* error - unterminated string constant */ /* generate error message */ }

<str>\\[0-7]{1,3} { /* octal escape sequence */ int result;

(void) sscanf( yytext + 1, "%o", &result );

if ( result > 0xff ) /* error, constant is out-of-bounds */

*string_buf_ptr++ = result; }

<str>\\[0-9]+ { /* generate error - bad escape sequence; something * like '\48' or '\0777777' */ }

<str>nbsp; *string_buf_ptr++ = ' ; <str>\\t *string_buf_ptr++ = '\t'; <str>\\r *string_buf_ptr++ = '\r'; <str>\\b *string_buf_ptr++ = '\b'; <str>\\f *string_buf_ptr++ = '\f';

<str>\\(. |  *string_buf_ptr++ = yytext[1];

<str>[^\nbsp; char *yptr = yytext;

while ( *yptr ) *string_buf_ptr++ = *yptr++; }

상기 예의 같게 동일한 개시 조건을 가지는 모든 룰의 전에 개시 조건을 쓰지 않으면 안 되는 것이 많습니다. flex 는 이것을 간단하고 깨끗이 하기 위한(해) 개시 조건 스코프 (을)를 도입했습니다. 개시 조건 스코프는 다음과 같이 시작됩니다:

<SCs>{

여기서 SCs (은)는 1 개(살) 이상의 개시 조건의 리스트입니다. 개시 조건 스코프내에서는, 최초의 '{' 에 매치 할 때까지의 '}' 에 두어, 모든 룰은 자동적으로 <SCs> 의 프레픽스가 붙습니다. 그 때문에, 예를 들면

<ESC>{ "nbsp; return ' ; "\\r" return '\r'; "\\f" return '\f'; "\\0" return '\0'; }

(은)는 다음의 것과 등가입니다:

<ESC>"nbsp; return ' ; <ESC>"\\r" return '\r'; <ESC>"\\f" return '\f'; <ESC>"\\0" return '\0';

개시 조건 스코프는 네스트 할 수가 있습니다.

개시 조건의 스택을 제어하기 위해서 3 개의 routine를 사용 가능합니다:
void yy_push_state(int new_state)
  현재의 개시 조건을 개시 조건 스택의 선두에 푸쉬 해, BEGIN new_state (을)를 사용했는지와 같이 new_state (으)로 전환합니다 (개시 조건명은 정수치이기도 한 것을 생각해 내 주세요).
void yy_pop_state()
  스택의 선두를 팝 해, BEGIN (을)를 사용해 그 개시 조건으로 전환합니다.
int yy_top_state()
  스택의 내용을 변경하지 않고 , 스택의 선두를 돌려줍니다.
개시 조건 스택은 동적으로 커져, 또 짜넣어 때의 사이즈 제한은 없습니다. 메모리를 다 사용하면(자), 프로그램 실행은 중지됩니다.

개시 조건 스택을 사용하기 위해서는, 스캐너는 %option stack 지시문을 인클루드 할 필요가 있습니다 (아래와 같이 옵션을 참조해 주세요).

복수의 입력 버퍼

스캐너에 따라서는(파일의 "include" 를 서포트하는 등 ) 복수의 입력 스트림을 취급할 필요가 있습니다. flex 스캐너에서는 큰 버퍼링을 실시하기 (위해)때문에, 스캔 문맥에 영향을 받는다 YY_INPUT (을)를 단순하게 고쳐 쓰는 것 만으로는 다음의 입력이 어디에서 읽혀지는지를 제어할 수 없습니다. YY_INPUT 하지만 불리는 것은 스캐너가 버퍼의 끝나에 도달하는 때만이므로, 예를 들면 "include" 와 같이 입력원을 바꿀 필요가 있는 문장을 스캔 한 다음에도 장시간을 비 경우가 있습니다.

이와 같은 문제를 해결하기 위해(때문에), flex (은)는 복수의 입력 버퍼를 생성해 바꾸는 기구를 제공합니다. 입력 버퍼는 다음과 같이 생성됩니다:

YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )

이것은 FILE 포인터와 size 를 취해, 주어지는 file 에 관련해 size 캐릭터를 보관 유지하기에 충분한 버퍼를 생성합니다 (의심스러운 경우에는 size 에는 YY_BUF_SIZE (을)를 사용해 주세요). 이것은, 다른 routine(아래와 같이 참조)에 건네주기 위한 YY_BUFFER_STATE 핸들을 돌려줍니다. YY_BUFFER_STATE 의 타입은 struct yy_buffer_state 구조체에의 포인터이기 (위해)때문에, 안전이기 때문에 YY_BUFFER_STATE 변수를 ((YY_BUFFER_STATE) 0) (와)과 초기화할 수가 있어 스캐너는 아니고 원시 파일에 대해 입력 버퍼를 올바르게 선언하기 위해서 이 구조체를 참조할 수가 있습니다. yy_create_buffer 호출해에 있어서의 FILE 포인터는 YY_INPUT (으)로부터 보인다 yyin 의 값과 같이만 사용되는 것에 주의해 주세요; YY_INPUT (을)를 재정의해 yyin (을)를 사용하지 않게 하는 것으로써, yy_create_buffer 에 대해서 안전하게 닐 FILE 포인터를 건네줄 수 있습니다. 스캔 하는 버퍼를 선택하기 위해서는 다음과 같이 합니다:

void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )

이것은 스캐너의 입력 버퍼를 바꾸어 토큰이 new_buffer (으)로부터 오게 됩니다. 새로운 파일을 오픈해 yyin (을)를 가리키는 것이 아니라, 스캔을 계속하기 위해서 yywrap()로부터 yy_switch_to_buffer() (을)를 사용하는 일이 있는 것에 주의해 주세요. 또, yy_switch_to_buffer() 또는 yywrap() 에 의한 입력원의 변환은 개시 조건을 변경해 없다 일에도 주의해 주세요.

void yy_delete_buffer( YY_BUFFER_STATE buffer )

(은)는 버퍼에 관련 지을 수 있었던 스토리지의 반환 요구에 사용합니다. ( buffer (은)는 닐에서도 상관하지 않습니다만 이 경우 이 routine는 아무것도 하지 않습니다. ) 현재의 버퍼의 내용을 클리어 하려면 다음과 같이 합니다:

void yy_flush_buffer( YY_BUFFER_STATE buffer )

이 함수는 버퍼의 내용을 버리기 (위해)때문에, 다음에 스캐너가 이 버퍼와 토큰의 매치을 실시하는 경우, 스캐너는 우선 YY_INPUT (을)를 사용해 이 버퍼를 필 합니다.

yy_new_buffer()yy_create_buffer() 의 앨리어스(alias)이며, 동적 오브젝트의 생성과 파괴를 위해서(때문에) 사용하는 C++ 의 new (와)과 delete (와)과의 호환성을 위해서(때문에) 제공하고 있습니다.

마지막에 YY_CURRENT_BUFFER 매크로는, 현재의 버퍼에 대한다 YY_BUFFER_STATE 핸들을 돌려줍니다.

이 기능을 사용해 인클루드 파일을 전개하는 스캐너의 기술예입니다( <<EOF>> 기능은 후술 합니다):

/* the "incl" state is used for picking up the name * of an include file */ %x incl

%{ #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; %}

%% include BEGIN(incl);

[a-z]+ ECHO; [^a-z *  ECHO;

<incl>[ \t]* /* eat the whitespace */ <incl>[^ \t + { /* got the include file name */ if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) { fprintf( stderr, "Includes nested too deeply" ); exit( 1 ); }

include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;

yyin = fopen( yytext, "r" );

if ( ! yyin ) error( ... );

yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE ) );

BEGIN(INITIAL); }

<<EOF>> { if ( --include_stack_ptr < 0 ) { yyterminate(); }

else { yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer( include_stack[include_stack_ptr] ); } }

파일은 아니고 메모리상의 캐릭터 라인을 스캔하기 위한 입력 버퍼를 설정하기 위한 3 개의 routine를 사용 가능합니다. 모두 캐릭터 라인을 스캔 하는 새로운 입력 버퍼를 생성해, 대응한다 YY_BUFFER_STATE 핸들(종료시에는 yy_delete_buffer() 에서 소거합니다)를 돌려줍니다. 새로운 버퍼로 전환할 때에는 yy_switch_to_buffer() (을)를 사용해, 다음의 yylex() 의 호출시에는 이 캐릭터 라인을 스캔 개시합니다.
yy_scan_string(const char *str)
  NUL 타미네이트 된 캐릭터 라인을 스캔 합니다.
yy_scan_bytes(const char *bytes, int len)
  len 바이트 (NUL 가 포함될지도 모릅니다)를 위치 bytes (으)로부터 스캔 합니다.
어느 쪽의 함수도 캐릭터 라인 혹은 바이트열의 카피 (을)를 생성하고 나서 스캔 합니다. ( yylex() (은)는 스캔 하는 버퍼의 내용을 변경하기 위해(때문에), 이것이 바람직합니다. ) 카피를 피하기 위해서(때문에)는 다음과 같이 합니다:
yy_scan_buffer(char *base, yy_size_t size)
  버퍼내에서 base (으)로부터 size 바이트의 길이를 스캔 합니다. 마지막 2 바이트는 YY_END_OF_BUFFER_CHAR (ASCII NUL) 이다 필요가 있습니다. 이러한 마지막 2 바이트는 스캔 되지 않습니다; 그 때문에 스캔의 내용은 base[0] (으)로부터 base[size-2] 까지로 양단을 포함합니다.
이와 같게 되도록(듯이) base (을)를 설정하지 않았던 경우(즉 마지막 2 개(살)의 YY_END_OF_BUFFER_CHAR 바이트를 잊었을 경우), yy_scan_buffer() (은)는 새로운 버퍼를 생성하는 것이 아니라 니르포인타를 돌려줍니다.
yy_size_t (은)는 정수형이며, 버퍼의 크기를 반영하는 정수식을 이 형태에 캐스트 할 수가 있습니다.

파일의 끝의 룰

특별 룰 "<<EOF>>" 은, 파일의 종료시 혹은 yywrap()가 비제로(즉 처리하는 파일이 없는 일을 나타낸다)때에 행해져야 할 액션을 나타냅니다. 액션은 이하의 4 개 중 어느쪽이든으로 끝날 필요가 있습니다.
- yyin 에 새로운 파일을 할당한다(전의 버젼의 flex 에서는, 할당 후에 특별한 액션 YY_NEW_FILE (을)를 호출할 필요가 있었습니다; 지금은 불필요합니다. );
- return 문장을 실행한다;
- 특별한 yyterminate() 액션을 실행한다;
- yy_switch_to_buffer() (을)를 사용해 새로운 버퍼로 전환한다 (상기예로 가리킨 대로).
<<EOF>> 룰을 다른 패턴과 함께 사용해 되지 않습니다; 다른 패턴은 개시 조건의 리스트 모두만 채워지기 때문입니다. 채워지지 않은 <<EOF>> 룰이 주어졌을 경우, <<EOF>> 액션을 아직 가지고 있지 않다 모든 개시 조건에 적용됩니다. <<EOF>> 룰을 최초의 개시 조건인 만큼 지정하기 위해서는 다음과 같이 해 주세요.

<INITIAL><<EOF>>

이러한 룰은 닫지 않은 코멘트를 잡는 경우등에 편리합니다. 예를 들면:

%x quote %%

...other rules for dealing with quotes...

<quote><<EOF>> { error( "unterminated quote" ); yyterminate(); } <<EOF>> { if ( *++filelist ) yyin = fopen( *filelist, "r" ); else yyterminate(); }

잡다한 매크로

매크로 YY_USER_ACTION 에는 매치 룰 액션에 앞서 항상 실시하는 액션을 정의할 수 있습니다. 예를 들면, yytext 를 소문자로 변환하는 routine를 부르도록(듯이) #define 할 수 있습니다. YY_USER_ACTION 기동시에는, 변수 yy_act (은)는 매치 한 룰의 번호를 줍니다(룰은 1 번으로부터 셉니다). 각 룰이 매치 하는 빈도를 알고 싶은 경우를 상상해 주세요. 이하에 장치를 나타냅니다:

#define YY_USER_ACTION ++ctr[yy_act]

여기서 ctr (은)는 배열이며, 각각의 룰이 매치 한 회수를 계수 합니다. 매크로 YY_NUM_RULES (은)는 룰의 총수를 나타내기 (위해)때문에( -s (을)를 사용했을 때조차 디폴트 룰을 포함합니다), 올바르다 ctr 의 선언은 다음과 같이 됩니다:

int ctr[YY_NUM_RULES];

매크로 YY_USER_INIT 에는 최초의 스캔의 전에 항상 실시하는 액션을 재정의할 수 있습니다 (스캐너의 내부 초기화 전에 행해집니다). 예를 들면 데이터표를 읽어들이거나 로그 파일을 오픈하기 위해서 사용할 수 있습니다.

매크로 yy_set_interactive(is_interactive) (은)는 현재의 버퍼가 대화적 (이)라고 보고 방 되고 있는지 아닌지를 제어하기 위해서 사용합니다. 대화적인 버퍼의 처리는 늦어집니다만, 스캐너의 입력원이 대화적이고 버퍼를 필 하는 것을 기다리는 것에 기인한다 문제를 피하기 위해서(때문에)는 지정하지 않으면 안됩니다(이하의 -I %option interactive 플래그에 관한 논의를 참조해 주세요). 매크로 기동시에 비제로를 지정하면(자) 버퍼는 대화적으로 되어, 제로를 지정하면(자) 비대화적으로 됩니다. 이 매크로의 사용은 %option interactive, %option always-interactive, %option never-interactive 에 우선합니다(아래와 같이 옵션을 참조해 주세요). 버퍼를 스캔 해 대화적인(혹은이 아니다)라고 판단 되기 전에, yy_set_interactive() (을)를 기동해 주세요.

매크로 yy_set_bol(at_bol) (은)는 현재의 버퍼에 있어서의 다음의 토큰에 대한 매치을 위한 스캔이 줄머리로부터 시작되는지 아닌지를 제어합니다. 비제로의 매크로 인수는, '^'가 붙은 룰을 유효하게 합니다만, 제로의 매크로 인수는 '^'가 붙은 룰을 무효로 합니다.

현재의 버퍼로부터 스캔 된 다음의 토큰이 유효한 '^'룰을 가질 때, 매크로 YY_AT_BOL() (은)는 진을 돌려줍니다. 그렇지 않은 경우는 가짜를 돌려줍니다.

생성된 스캐너에서는, 모든 액션은 큰 하나의 switch 문에 모아져 YY_BREAK 그리고 나눌 수 있고 있습니다. YY_BREAK (은)는 재정의 가능합니다. 디폴트에서는 각각의 룰의 액션을 나누기 위한 단순한 "break" 입니다. YY_BREAK (을)를 재정의하는 것으로써, 예를 들면 C++ 유저가 #define YY_BREAK 를 아무것도 하지 않게 정의해 (다만 모든 룰이 "break" 나 "return" 로 끝나도록(듯이) 주의하지 않으면 안됩니다! ), 룰의 액션이 "return" 로 끝나는 것으로 YY_BREAK 하지만 액세스 할 수 없는 것에 기인하는, 도달할 수 없는 문장이 있다고 하는 경고를 피할 수가 있습니다.

유저가 사용 가능한 값

이 마디에서는 유저가 룰의 액션 부분에서 사용 가능한 값을 정리합니다.
- char *yytext 현토큰의 텍스트를 보관 유지하고 있습니다. 내용을 변경해도 상관하지 않습니다만, 그 길이를 늘려서는 안됩니다(끝나에 캐릭터를 추가해선 안 된다).
스캐너의 기술의 최초의 부분에 특별한 지시이다 %array 하지만 쓰여져 있을 때, yytextchar yytext[YYLMAX] (이)라고 정의됩니다. YYLMAX (은)는 매크로로, 디폴트의 값 (많은 경우 8KB)을 변경하고 싶은 경우에는 최초의 부분에서 재정의 가능합니다. %array (을)를 사용하면(자) 얼마인가 늦은 스캐너가 됩니다만, yytext 의 값은 input() (와)과 unput() 의 호출에서도 파괴되지 않게 됩니다. yytext 하지만 캐릭터 포인터인 경우, 이러한 함수 호출은 yytext (을)를 파괴할 가능성이 있습니다. %array (와)과 대칭인 지정 %pointer 하지만 디폴트입니다.
C++ 의 스캐너 클래스를 생성한다 (옵션 -+ ) 때로는 %array (은)는 사용할 수 없습니다.
- int yyleng 현토큰의 길이를 보관 유지하고 있습니다.
- FILE *yyin (은)는 디폴트로 flex 하지만 읽는 파일입니다. 재정의하는 것은 가능합니다만, 스캔을 시작하기 전이나 EOF 에 도달한 다음에 마셔 재정의는 의미를 가집니다. 스캔의 도중에 변경하면(자) 예상외의 결과를 가져옵니다. 그렇다고 하는 것도 flex (은)는 입력을 버퍼링 하고 있기 때문입니다; 그러한 경우에는, 직접재정의하지 않고 yyrestart() (을)를 사용해 주세요. 파일의 마지막으로 스캔이 종료했을 경우에는 yyin (을)를 새로운 입력 파일에 할당해 다시 스캐너를 호출해 스캔을 계속할 수가 있습니다.
- void yyrestart( FILE *new_file ) (을)를 부르는 것으로 yyin 하지만 새로운 입력 파일을 가리키도록(듯이) 할 수 있습니다. 새로운 파일에의 변경은 곧바로 행해집니다 (그때까지 버퍼에 읽히고 있던 입력은 없어집니다). yyin (을)를 인수로서 yyrestart() (을)를 부르면(자), 현재의 입력 버퍼를 버려 같은 입력 파일을 스캔 계속 하는 것에 주의해 주세요.
- FILE *yyoutECHO 액션을 하는 대상의 파일입니다. 유저가 재할당 할 수가 있습니다.
- YY_CURRENT_BUFFER 경향 버퍼의 YY_BUFFER_STATE 핸들을 돌려줍니다.
- YY_START 현재의 개시 조건에 대응하는 정수치를 돌려줍니다. 계속되어 이 값을 BEGIN (와)과 함께 사용하는 것으로, 스캐너를 그 개시 조건에 되돌릴 수가 있습니다.

YACC 와의 인터페이스

flex 의 주된 사용 방법의 하나는, yacc 파서 제네레이터와 함께 사용하는 것입니다. yacc 파서는 yylex() (이)라는 이름 전의 routine를 불러, 다음의 입력 토큰을 찾아내는 것으로 하고 있습니다. 이 routine는, 다음의 토큰의 형태를 돌려주어, 관련하는 값을 글로벌의 yylval 에 격납하는 것으로 되어 있습니다. flex (을)를 yacc (와)과 함께 사용하려면 , yacc-d 옵션을 지정해, yacc 의 입력에 나타나는 모든 %tokens 의 정의를 포함한다 y.tab.h 파일을 생성시킵니다. 이 파일은 flex 스캐너에 인클루드 됩니다. 예를 들면 토큰의 하나가 "TOK_NUMBER" 인 경우, 스캐너의 일부분은 다음과 같이 되어 있습니다:

%{ #include "y.tab.h" %}

%%

[0-9]+ yylval = atoi( yytext ); return TOK_NUMBER;

옵션

flex 에는 이하와 같은 옵션이 있습니다:
-b 백업 정보를 lex.backup 에 출력합니다. 이 파일에는, 스캐너의 백업(backing-up)을 필요로 하는 상태와 거기에 대응하는 입력 캐릭터의 일람이 리스트 됩니다. 룰을 추가하는 것으로 백업 상태를 없애는 것 하지만 할 수 있습니다. 백업 상태가 모두 제거되어 -Cf 또는 -CF (을)를 지정하면(자), 생성된 스캐너의 실행 속도가 향상합니다( -p 플래그를 봐 주세요). 스캐너를 직전까지 최적화하려고 하고 있는 유저만이 이 옵션에 관계 있습니다. (후술의 성능 관련의 경우(때)를 봐 주세요. )
-c 아무것도 하지 않습니다. POSIX 호환을 위해서(때문에) 준비되어 있습니다.
-d 생성된 스캐너가 디버그 모드로 실행됩니다. yy_flex_debug 하지만 비제로의 경우(디폴트), 패턴이 인식될 때마다, 스캐너는 다음과 같은 메세지를 표준 에러 출력 에 출력합니다.

--accepting rule at line 53 ("the matched text")

행 번호는 스캐너를 정의하고 있는 파일 (flex에게 줄 수 있었던 파일) 에서의 룰의 위치입니다. 스캐너가 백업 했을 때, 디폴트 룰을 받아들였을 때, 입력 버퍼의 마지막에 도달했을 때 (혹은, NUL에 도달했을 때; 스캐너에는, 이 두 개의 구별은 다하지 않습니다), 파일의 마지막에 도달했다 때에도 메세지가 출력됩니다.
-f 고속의 스캐너 (을)를 지정합니다. 테이블 압축은 행해지지 않고, 표준 입출력을 우회도로 합니다. 그 결과 생성되는 스캐너는 커집니다만, 고속의 것이 됩니다. 이 옵션은 -Cfr (와)과 동등합니다 (이하를 참조).
-h flex 의 옵션의 요약으로부터 되는 "헬프" 를 표준 출력 에 서두 종료합니다. -? (와)과 --help (이)란 -h (와)과 같습니다.
-i 대문자 소문자를 구별하지 않는다 스캐너를 생성합니다. flex 의 입력 패턴에게 줄 수 있는 캐릭터가 대문자일까 소문자일까는 구별되지 않고, 스캐너에 입력되는 캐릭터 라인은 대문자 소문자에 관계없이 매치 합니다. 매치 한 텍스트 yytext 그럼 입력시의 대문자 소문자가 보존됩니다 (대문자를 소문자로 변환하거나 하지 않습니다).
-l AT&T 의 lex 의 실장에 대해서 최대한의 호환성을 갖게합니다. 이것은 완전한 호환성을 의미하지 않습니다. 이 옵션을 사용하면(자) 성능에 큰 영향이 있습니다. 이 옵션은, -+, -f, -F, -Cf, -CF 그와 동시에 사용할 수 없습니다. 자세하게는, 후술의 "Lex 및 POSIX 와의 비호환성" 시에를 봐 주세요. 또 이 옵션을 사용하면(자), YY_FLEX_LEX_COMPAT 하지만 생성된 스캐너의 이름에 #define 됩니다.
-n 아무것도 하지 않습니다. POSIX 호환을 위해서(때문에)만 준비된 옵션입니다.
-p 성능 정보를 표준 에러 출력에 출력합니다. flex 입력 파일의 기술 가운데, 생성되는 스캐너의 성능 저하의 심각한 원인이 되는 부분에 도착해, 코멘트됩니다. 옵션을 2회 지정하면(자), 보다 섬세한 성능 저하에 대해서도 코멘트가 출력됩니다.
REJECT · %option yylineno ·가변장 우문맥(결함/버그의 마디로 후술)은 막대한 성능에의 악영향이 있습니다; yymore() 의 사용· ^ 오퍼레이터· -I 플래그는 작은 성능의 악영향이 있습니다.
-s 디폴트 룰 (매치 하지 않는 스캐너의 입력을 표준 출력 에 출력한다) 하지만 억제됩니다. 룰에 매치 하지 않는 입력이 나타났을 때, 스캐너는 에러로 이상종료(ABEND) 합니다. 스캐너의 룰의 조에 누락이 없는가를 확인하는 경우에 유효합니다.
-t lex.yy.c (이)가 아니고, 표준 출력에 스캐너를 써냅니다.
-v 생성하는 스캐너의 특징의 요약을 표준 에러 출력 에 출력하도록(듯이) flex 에 지시합니다. 대부분의 특징은 통상의 flex 유저에게는 의미가 없습니다만, 최초의 행은 flex 의 버젼을 표시해( -V 그리고 표시되는 것도 것과 같습니다), 다음의 행은 디폴트를 포함한 스캐너 생성시의 플래그입니다.
-w 경고 메세지를 억제합니다.
-B 대화적 스캐너 (이하의 -I 의 항을 참조)는 아니고 배치적 스캐너를 생성하는 듯 flex 에 지시합니다. 통상 -B (을)를 사용하는 것은, 스캐너를 대화적으로 사용하지 않는 것이 알고 있다 때이며, 조금이라도 성능을 추구하고 싶을 때입니다. 보다 큰 성능을 추구하는 경우에는, -Cf 혹은 -CF 옵션을 사용해야 합니다(후술). -B (을)를 자동적으로 설정합니다.
-F 고속의 스캐너 테이블의 표현을 사용하는(표준 입출력은 우회도로 한다) 일을 지정합니다. 이 표현은, 완전 테이블 표현 (-f) (와)과 거의 같은 정도 고속으로 , 어떤 종류의 패턴에 대해서는 꽤 작고 (어느 종류에 대해서는 크고) 됩니다. 통상, 다음과 같이, 패턴의 조가 "keywords" 와 그 대응 및 "identifier" 룰로부터 되는 경우:

"case" return TOK_CASE; "switch" return TOK_SWITCH; ... "default" return TOK_DEFAULT; [a-z]+ return TOK_ID;

이 경우, 완전 테이블 표현을 사용하는 편이 좋습니다. 만약 "identifier" 룰로부터 마셔 표현되어 키워드를 검지하기 위해서 해시표등을 사용하는 경우는, -F (을)를 사용하는 편이 좋습니다.
이 옵션은 -CFr (와)과 등가입니다 (이하를 참조). 이것은 -+ 옵션과는 동시에 지정할 수 없습니다.
-I flex대화적 스캐너를 생성하도록(듯이) 지시합니다. 대화적인 스캐너는, 예측하는 것으로써 매치 하는 토큰이 완전하게 정해지는 경우만 예측합니다. 현재의 토큰이 이미 분명한 경우에서도 항상 예측하는 방법은, 필요시만 예측하는 방법보다 조금 빠릅니다. 그러나, 항상 예측하는 방법에서는 대화 성능에 현저하게 악영향이 있습니다; 예를 들면 유저가 개행을 입력했을 경우, 별의 토큰을 입력할 때까지 그것은 개행으로서 인식되지 않습니다. 대개의 경우, 다음의 행 전체를 입력하게 됩니다.
flex 의 스캐너의 디폴트는 대화적 (이어)여, 예외는 -Cf (이)나 -CF 그렇다고 하는 테이블 압축 옵션(후술) 사용시입니다. 고성능 추구시에는 이러한 옵션을 사용하고 있어야 합니다 것으로, 이러한 옵션을 사용하고 있지 않는 경우에는, flex (은)는 실행시 성능을 조금 희생해 직관적인 대화적인 행동을 취하고 있는 것으로 합니다. -I 옵션을 -Cf (이)나 -CF (와)과 함께 사용할 수 없다 일에도 주의해 주세요. 실제는 이 옵션은 불필요합니다; 용서되는 경우, 디폴트로 유효하게 되어 있습니다.
isatty() 하지만 스캐너의 입력에 대해서 가짜를 돌려주는 경우, -I 하지만 지정되어 있었을 경우에서도, flex 는 배치 모드에 돌아옵니다. 뭐가 있어도 대화 모드를 강제하려면 , %option always-interactive (후술의 옵션을 참조)(을)를 사용합니다.
스캐너를 대화적이어 없다 같게 강제하려면 -B (전제)(을)를 사용합니다.
-L flex#line 지시문을 lex.yy.c 안에 생성하지 않게 지시합니다. 디폴트에서는 이 #line 지시문을 생성하므로, 액션에 있어서의 에러 메세지는, 오리지날의 flex 입력 파일( 에러가 입력 파일의 코드에 기인하는 경우) 혹은 파일 lex.yy.c ( flex 의 잘못 -- 이하의 전자메일 주소에 보고해 주세요) 에 있어서의 올바른 위치를 줍니다.
-T flex (을)를 트레이스 모드로 실행합니다. 입력의 형식과 그 결과적으로 출력되는 비결정성/결정성 유한 자동 장치에 관해서 표준 에러 출력 에 다량의 메세지를 출력합니다. 이 옵션은 주로 flex (을)를 메인트넌스 하기 위해서 사용됩니다.
-V 버젼 번호를 표준 출력 에 출력해 종료합니다. --version-V (와)과 같습니다.
-7 7 비트의 스캐너를 생성합니다. 즉, 입력에 7 비트의 캐릭터만을 사용하는 것을 의미합니다. -7 (을)를 지정하는 이점은, -8 옵션(후술)을 지정해 생성하는 테이블의 반까지 작아질 수 있는 일입니다. 결점은, 입력에 8 비트 캐릭터가 포함되어 있을 때에, 스캐너가 헹 혹은 크래쉬 하는 것입니다.
그렇지만, -Cf (이)나 -CF 그렇다고 하는 테이블 압축 옵션 사용시에는 테이블 압축의 효과는 적고, 이식성이 현저하게 저하하는 것에 주의해 주세요. flex 의 디폴트의 동작에서는, -Cf (이)나 -CF, (을)를 지정하지 않는 한 8 비트 스캐너를 생성합니다. 지정시에는, 당신의 사이트가 항상 8 비트 스캐너를 생성하도록(듯이) (USA 이외의 사이트에서는 잘 있는) 하고 있지 않는 경우에는, 7 비트 스캐너를 생성합니다. flex 가 7 비트 혹은 8 비트의 어느 스캐너를 생성하는지를 알고 싶은 경우에는, 상술의 -v 의 출력의 플래그의 요약을 조사해 주세요.
-Cfe 혹은 -CFe (이러한 테이블 압축 옵션 및 등가 클래스는 후술) (을)를 사용해도, flex 는 디폴트로 8 비트 스캐너를 생성하는 것에 주의해 주세요. 왜냐하면, 완전한 8 비트 테이블은 7 비트 테이블과 비교해도 별로 고가이게는 안 되기 때문입니다.
-8 8 비트의 스캐너를 생성하도록(듯이) flex 에 지시합니다. 즉 8 비트 캐릭터를 해석합니다. 압축 옵션 -Cf (와)과 -CF 사용시에게만 필요합니다. 왜냐하면 flex 는 디폴트에서는 8 비트 스캐너를 생성하기 때문입니다.
flex 의 디폴트 동작과 7 비트 및 8 비트 스캐너의 트레이드 오프에 관해서는, 상기 -7 의 논의를 봐 주세요.
-+ C++ 의 스캐너 클래스를 생성합니다. 자세하게는 C++ 스캐너의 생성으로 후술 합니다.
-C[aefFmr]
  테이블 압축의 정도와 보다 일반적으로는 작은 스캐너와 고속의 스캐너와의 트레이드 오프를 지정합니다.
-Ca ("아라인") 생성되는 스캐너의 테이블은, 메모리아크세스 및 계산을 위해서(때문에) 아라인 되기 (위해)때문에, 보다 큰 것이 됩니다. RISC 아키텍쳐에서는 롱 워드의 페치 및 조작은 쇼트 워드라고 했던 것보다 작은 크기의 것에 대하는 것 보다 효율적입니다. 경우에 따라서는 스캐너의 테이블 사이즈가 통상의 2배가 될 수도 있습니다.
-Ce 등가 클래스 (동일한 자구 속성을 가지는 캐릭터 세트)(을)를 구축합니다 (예를 들면, flex 입력중에 숫자가 나타나는 것이 캐릭터 클래스 "[0-9]" 만의 경우, 숫자 '0', '1', ..., '9'는 모두 같은 등가 클래스가 됩니다). 많은 경우, 등가 클래스를 이용하는 것으로 최종적인 테이블/ 오브젝트 파일의 사이즈를 극적(평균해 1/2-1/5)으로 줄일 수가 있습니다. 또, 그 때의 성능 코스트는 매우 낮게 억제 당합니다 ( 1 캐릭터 스캔 할 때 마다 1회의 배열 검색을 실시할 뿐입니다).
-Cf 완전(full) 스캐너 테이블을 생성하는 것을 지시합니다 - flex (은)는, 다른 상태에 관한 유사한 천이 함수를 잘 이용한다고 하는, 테이블 압축 수법을 이용하지 않습니다.
-CF 다른 고속 스캐너 표현( -F 플래그에서 기술)을 이용하는 것을 지정합니다. 이 옵션은 -+ 그와 동시에 사용할 수 없습니다.
-Cm flex메타 등가 클래스 (을)를 구축하도록 지시합니다. 메타 등가 클래스는 함께 사용되는 것이 많은 등가 클래스 (등가 클래스가 사용되지 않을 때에는 캐릭터군)의 집합입니다. 압축 테이블을 사용하고 있을 때, 메타 등가 클래스는 많은 경우에 상당한 효과적을 가져옵니다만, 약간 성능에 영향을 줍니다 (1-2 회의 조건 테스트와 1 회의 배열 검색이 스캔 한 캐릭터 마다 행해집니다).
-Cr 생성된 스캐너는 입력에 대해서는 표준 입출력 프로그램 라이브러리(표준 입출력)를 우회도로 합니다. 스캐너는, fread() (이)나 getc() (이)가 아니고, read() 시스템 콜을 사용합니다. 성능 개선 결과는 시스템에 의존합니다. 옵션 -Cf 혹은 -CF (을)를 사용하고 있지 않는 경우에는, 일반적으로 이 옵션은 성능을 그다지 개선하지 않습니다. -Cr (을)를 지정하면(자), 예를 들면 스캐너를 설정하기 전에 표준 입출력을 사용해 yyin (을)를 읽어내는 등 했을 경우 기묘한 동작이 될 수 있습니다 (표준 입출력의 입력 버퍼에 이전 읽어들인 것을, 스캐너는 읽을 수 없습니다).
-CrYY_INPUT (을)를 정의했을 경우 의미가 없습니다 (전술의 생성된 스캐너를 참조). 스캐너의 호출에 앞서 표준 입력을 사용해 yyin (으)로부터 읽어내고 있을 때는, 예상외의 행동을 하는 일이 있습니다.
-C 만을 지정했을 때에는, 스캐너는 테이블 압축은 실시합니다만, 등가 클래스도 메타 등가 클래스도 사용하지 않습니다.
옵션 -Cf (와)과 -CF (은)는 옵션 -Cm (을)를 동시에 지정해도 의미를 만들어내지 않습니다 - 왜냐하면, 테이블 압축을 하지 않을 때 메타 등가 클래스 (은)는 나타나지 않기 때문입니다. 그 이외의 옵션은 자유롭게 조합할 수가 있습니다.
디폴트의 설정은 -Cem 입니다. 이 때 flex (은)는 등가 클래스와 메타 등가 클래스를 생성합니다. 이 설정은 가장 높은 테이블 압축을 실시합니다. 테이블 사이즈의 크기와 실행의 고속성은 트레이드 오프의 관계에 있어, 일반적으로

늦지만 작다 -Cem -Cm -Ce -C -C{f, F}e -C{f, F} -C{f, F}a 빠르지만 크다

됩니다. 작은 테이블의 스캐너는 통상 생성도 컴파일도 고속으로 있기 (위해)때문에, 통상의 개발시는 최대의 압축을 실시하겠지요.
제품의 스캐너에서는, -Cfe 하지만 속도와 크기가 좋은 밸런스입니다.
-ooutput
  lex.yy.c (은)는 아니고 파일 output 에 스캐너를 쓰도록(듯이) flex 에 지시합니다. -o (와)과 -t 옵션을 조합하면(자), 스캐너는 표준 출력 에 쓰여집니다만, #line 지시문( \-L 에서 상술)은 파일 output (을)를 참조합니다.
-Pprefix
  flex (이)가 사용하는 디폴트의 프레픽스 yy 대신에 prefix (을)를 사용합니다. 이것은 글로벌 변수와 파일명에 영향을 줍니다. 예를 들면 -Pfoo (으)로 하면(자), yytext 의 이름은 footext 됩니다. 또 디폴트의 출력 파일명을 lex.yy.c (으)로부터 lex.foo.c 에 바꿉니다. 영향을 받는 이름의 일람입니다:

yy_create_buffer yy_delete_buffer yy_flex_debug yy_init_buffer yy_flush_buffer yy_load_buffer_state yy_switch_to_buffer yyin yyleng yylex yylineno yyout yyrestart yytext yywrap

(C++ 스캐너 사용시에는 yywrap (와)과 yyFlexLexer 만이 영향을 받습니다. ) 스캐너 중(안)에서는, 글로벌 변수 및 함수를 어느 쪽의 이름으로라도 참조할 수 있습니다; 외부적으로는 수정한 이름만 가집니다.
이 옵션을 사용하는 것으로써, 복수의 flex 프로그램을 동일한 실행 형식에 용이하게 링크 할 수가 있습니다. 그러나, 이 옵션은 yywrap() 의 이름도 바꾸기 때문에, 독자적인(적절히 이름을 붙인) routine를 스캐너를 위해서(때문에) 준비하는지, %option noyywrap (을)를 사용해 -ll (와)과 링크 한다 필요가 있습니다. 어느 것도 디폴트에서는 제공되지 않습니다.
-Sskeleton_file
  flex 하지만 스캐너를 구축하는데 사용하는 디폴트의 스켈리턴 파일에 우선합니다. flex 의 메인트넌스나 개발을 하는 경우 이외, 이 옵션은 필요 없습니다.
flex (은)는, flex 의 명령행이 아니고, 스캐너 사양 기술중으로부터 옵션을 제어하는 기구를 제공합니다. 이것은 스캐너의 최초의 부분에 %option 지시문을 포함하는 것으로 실현될 수 있습니다. 단일의 %option 지시문에 대해 복수의 옵션을 지정할 수 있어 또 복수의 지시문을 flex 입력 파일의 최초의 부분에 둘 수가 있습니다.
대부분의 옵션이 단순한 이름이며, 옵션으로서 전에 "no" 라고 하는 말(공백을 끼우지 않습니다)을 붙여 의미를 반전할 수 있습니다. 수치는 flex 의 플래그나 그 반전과 등가입니다.

7bit -7 옵션 8bit -8 옵션 align -Ca 옵션 backup -b 옵션 batch -B 옵션 c++ -+ 옵션

caseful 또는 case-sensitive -i 옵션의 역(디폴트)

case-insensitive 또는 caseless -i 옵션

debug -d 옵션 default -s 옵션의 역 ecs -Ce 옵션 fast -F 옵션 full -f 옵션 interactive -I 옵션 lex-compat -l 옵션 meta-ecs -Cm 옵션 perf-report -p 옵션 read -Cr 옵션 stdout -t 옵션 verbose -v 옵션 warn -w 옵션의 역 (-w 옵션에는 "%option nowarn" 를 사용해 주세요)

array "%array" 과 등가 pointer "%pointer" 과 등가(디폴트)

%option 에는, 외에서는 이용할 수 없는 기능을 제공하는 것도 있습니다:
always-interactive
  입력을 항상 "대화적" 으로 취급하는 스캐너를 생성하도록(듯이) flex 에 지시합니다. 통상, 새로운 입력 파일마다 스캐너는 isatty() (을)를 호출해, 스캐너의 입력원이 대화적이고 1 번에 1 캐릭터씩 읽어야할 것인가 제발 판정하려고 합니다. 한편 이 옵션을 사용하는 곳의 같은 호출은 실시하지 않습니다.
main
  스캐너에 대해, yylex() (을)를 호출할 뿐(만큼)의 디폴트의 main() 프로그램을 제공하도록(듯이) 지시합니다. 이 옵션은 noyywrap (후술)도 암묵적으로 지시합니다.
never-interactive
  입력을 "대화적" 과는 하지 않는 스캐너를 생성하도록(듯이) flex 에 지시합니다 (이것도 또 isatty() (을)를 호출하지 않습니다). 이것은 always-interactive 의 역입니다.
stack
  개시 조건 스택의 사용을 유효하게 합니다(전술의 개시 조건을 참조).
stdinit
  설정되어 있는 경우 (즉 %option stdinit) yyinyyout (을)를, 디폴트의 nil (이)가 아니고, 표준 입력 (와)과 표준 출력 (으)로 설정합니다. 기존의 lex 프로그램에는, ANSI C 호환은 아니기는 하지만, 이 동작에 의존하고 있는 것이 있습니다. ANSI C 에서는 표준 입력 (와)과 표준 출력 하지만 컴파일시의 정수일 필요는 없습니다.
yylineno
  입력으로부터 읽어낸 현재의 행 번호를 글로벌 변수 yylineno (으)로 유지하는 스캐너를 생성하도록(듯이), flex 에 지시합니다. 이 옵션은 %option lex-compat (으)로부터 암묵적으로 지정됩니다.
yywrap
  세트되어 있지 않은 경우 (즉 %option noyywrap) , 스캐너는 파일의 끝에 즈음해 yywrap() (을)를 부르지 않고 단지 스캔 해야 할 파일이 이제 없는 것으로 할 것 같게 됩니다( 유저가 yyin (을)를 새로운 파일을 가리키도록(듯이) 해, 재차 yylex() (을)를 호출할 때까지입니다).
flex (은)는 룰 액션을 스캔 해, REJECT (와)과 yymore() 의 기능이 사용되고 있는지 어떤지를 조사합니다. reject (와)과 yymore 의 옵션을 사용하면(자), 옵션으로 지정한 대로 이 판정에 우선합니다. 옵션의 지정은, 세트 해 기능을 사용하고 있는 것을 나타낸다(예를 들면 %option reject) , 혹은 안 세트 해 기능을 사용하고 있지 않는 것을 나타낸다(예를 들면 %option noyymore) 것으로 합니다.

다음의 옵션은 캐릭터 라인의 값을 받아, '='로 단락짓습니다:

%option outfile="ABC"

이것은 -oABC (와)과 같고,

%option prefix="XYZ"

-PXYZ (와)과 같습니다. 마지막으로,

%option yyclass="foo"

(은)는 C++ 스캐너 생성시만 유효( -+ 옵션)입니다. 이것은 flex 에 대해서, foo 하지만 yyFlexLexer 의 서브 클래스인 것을 알리기 때문에, flex (은)는 액션을 yyFlexLexer::yylex() (은)는 아니고 foo::yylex() 의 멤버 함수로 합니다. 또, ( yyFlexLexer::LexerError() (을)를 기동하는 것으로써) 호출하면(자) 실행시 에러를 제거한다 yyFlexLexer::yylex() 멤버 함수를 생성합니다. 자세한 것은 후술의 C++ 스캐너의 생성을 봐 주세요.

생성된 스캐너로부터 불필요한 routine를 제외하고 싶은 lint 순정 주의자를 위해서(때문에) 많은 옵션이 준비되어 있습니다. 이하를 안 세트 하면(자)(예를 들면 %option nounput ), 대응하는 routine는 생성되는 스캐너로부터 제외해집니다:

input, unput yy_push_state, yy_pop_state, yy_top_state yy_scan_buffer, yy_scan_bytes, yy_scan_string

( yy_push_state() 등은 %option stack (을)를 사용하지 않는 경우에는 나타나지 않습니다).

성능 관련

flex 의 주된 디자인 골은 고성능인 스캐너를 생성하는 것입니다. 많은 룰 세트를 잘 취급하는 것으로 최적화됩니다. 이미 개요했다 -C 옵션 사용에 의한 테이블 압축에 기인하는 속도에의 영향 외에, 성능을 악화시키는 많은 옵션/액션이 있습니다. 그것들을 고가의 것으로부터 염가의 것으로 늘어놓습니다:

REJECT %option yylineno 자유장의 우문맥(trailing context)

백업이 필요한 패턴의 조 %array %option interactive %option always-interactive

'^'줄머리 오퍼레이터 yymore()

최초의 3 개는 매우 고가이고, 마지막 2 개(살)은 매우 염가로. unput() (은)는 잠재적으로 매우 큰 일을 하는 routine 호출로서 실장되고 있는데 대해, yyless() (은)는 매우 염가의 매크로입니다; 그러니까 스캔 한 여분의 텍스트를 되돌릴 뿐(만큼)의 경우에는 yyless() (을)를 사용해 주세요.

성능이 중요한 경우에는, 할 수 있을 수 있는 한계의 노력에서도는 REJECT (을)를 피해 주세요. 이것은 특히 고가의 옵션입니다.

백업을 없애면(자), 난잡하게 되어, 몹시 고생해 복잡한 스캐너를 만들게 됩니다. 실제적으로는 -b 플래그를 지정해 lex.backup 파일을 생성하는 것으로부터 시작합니다. 예를 들면, 입력

%% foo return TOK_KEYWORD; foobar return TOK_KEYWORD;

에 대해서는, 파일은 다음과 같이 됩니다:

State #6 is non-accepting - associated rule line numbers: 2 3 out-transitions: [ o ] jam-transitions: EOF [ \001-n p-\177 ]

State #8 is non-accepting - associated rule line numbers: 3 out-transitions: [ a ] jam-transitions: EOF [ \001-` b-\177 ]

State #9 is non-accepting - associated rule line numbers: 3 out-transitions: [ r ] jam-transitions: EOF [ \001-q s-\177 ]

Compressed tables always back up.

최초의 몇 줄기는, 'o'에 천이 할 수 있지만 다른 캐릭터에는 천이 할 수 없는 상태가 있어, 그 상태에서는 현재 스캔 된 텍스트는 다른 룰에는 매치 하지 않는 것을 나타냅니다. 이 상태가 발생한 것은, 입력 파일의 행 2, 3 의 룰에 매치 하려고 했을 때입니다. 스캐너가 이와 같은 상태에 있어 'o'이외의 캐릭터를 읽었을 경우에는, 매치 하는 룰을 찾기 위한 백업이 필요합니다. 조금 생각하면, 이것은 "fo" 를 보았을 때에 있는 상태가 틀림없는 것이 밝혀지겠지요. 이와 같은 때, 'o'이외의 것이 나타나면(자), 스캐너는, 단지 'f'에 매치 하는(디폴트 룰) 곳까지 귀가(백업 해).

상태 #8 에 관계하는 코멘트는, "foob" 가 스캔 되었을 때에 문제가 있는 것을 나타내고 있습니다. 실제, 'a'이외의 캐릭터를 만나면(자), 스캐너는 "foo" 를 수리하는 곳(중)까지 돌아옵니다. (와)과 같이 상태 #9 에 관계하는 코멘트는, "fooba" 가 스캔 되고 'r'가 계속되지 않는 경우에 관계합니다.

마지막 코멘트가 통지하는 것은, -Cf (이)나 -CF (을)를 사용하고 있으므로 않으면 백업을 없애려고 노력하는 것은 무의미한 것입니다. 왜냐하면, 압축된 스캐너에 대해서 그러한 일을 해도, 성능상의 이익은 없기 때문입니다.

백업을 없애기 위해서(때문에)는 "에러" 룰을 추가합니다:

%% foo return TOK_KEYWORD; foobar return TOK_KEYWORD;

fooba | foob | fo { /* false alarm, not really a keyword */ return TOK_ID; }

키워드의 리스트로부터 백업을 없애려면 ,"모두를 잡는다" 룰을 사용할 수가 있습니다:

%% foo return TOK_KEYWORD; foobar return TOK_KEYWORD;

[a-z]+ return TOK_ID;

통상, 적절한 때에는 이것은 제일 좋은 해결책입니다.

백업 메세지는 cascade 하는 것이 많습니다. 복잡한 룰의 조에서는, 수백의 메세지를 얻는 것은 보통 일입니다. 그러나, 이것을 해석하면, 백업을 제거하기 위해서는 대체로의 경우수다스의 룰에만 관계 있는 것을 알겠지요 (그러나, 잘못하는 것이 많아, 잘못한 룰이 우연히 유효한 토큰에 매치 할 수 있습니다. 장래의 flex 의 기능에서는, 자동적으로 백업을 제거하는 룰을 추가하게 될지도 모릅니다).

백업을 제거하는 것으로써 이익이 있는 것은, 모든 백업을 제거한 때만이라고 하는 것을 기억해 두는 것은 중요합니다. 단 하나를 남겨도 아무것도 얻을 수가 없습니다.

가변장의 우문맥 (왼쪽 부분과 위 부분의 언젠가 혹은 양쪽 모두가 가변장)은 REJECT (와)과 거의 동일한(즉 상당한 ) 성능 열화가 됩니다. 그 때문에 다음과 같은 룰:

%% mouse|rat/(cat|dog) run();

(은)는 다음과 같이 쓸까:

%% mouse/cat|dog run(); rat/cat|dog run();

다음과 같이 쓰는 것이 좋습니다:

%% mouse|rat/cat run(); mouse|rat/dog run();

특별한 '|'액션은 도움으로는 되어 해, 오히려 상황을 나쁘게 합니다 (후술의 결함/버그를 참조).

스캐너의 성능을 향상시키기 위한 여지(실현은 가장 용이)는, 매치 하는 토큰이 길면 스캐너가 고속으로 되는 것에 있습니다. 긴 토큰에서는 대부분의 입력 처리는(짧다) 내부 루프로 처리되어 액션을 위해서(때문에) 스캐너 환경을 설정하는 추가의 일(예를 들면 yytext) (을)를 거의 하지 않기 때문입니다. C 코멘트의 스캐너를 생각해 냅시다:

%x comment %% int line_num = 1;

"/*" BEGIN(comment);

<comment>[^* * <comment>"*"+[^*/ * <comment>  ++line_num; <comment>"*"+"/" BEGIN(INITIAL);

다음과 같이 쓰면(자) 고속으로 됩니다:

%x comment %% int line_num = 1;

"/*" BEGIN(comment);

<comment>[^* * <comment>[^* *  ++line_num; <comment>"*"+[^*/ * <comment>"*"+[^*/ * ++line_num; <comment>"*"+"/" BEGIN(INITIAL);

이번은, 개행마다별의 액션의 처리를 실시하는 것이 아니라, 개행 인식은 룰간에 "분산" 되어 가능한 한 긴 텍스트에 매치 하게 되어 있습니다. 룰의 추가 (은)는 스캐너를 늦고 하지 않습니다! 스캐너의 속도는, 룰수와도, 오퍼레이터 '*'나 '|'라고 한 것에 근거하는 룰의 복잡함 (이 마디의 초로 취급했습니다)(와)과도 독립입니다.

마지막 고속화의 예입니다: 1 행에 1 개씩이어 다른 캐릭터는 붙지 않는 것 같은, 식별자와 키워드를 모두 파일로부터 스캔 하는 것을 생각합니다. 처음은 다음과 같이 되겠지요:

%% asm | auto | break | ... etc ... volatile | while /* it's a keyword */

. |  /* it's not a keyword */

퇴보를 피하기 위해서(때문에) 모두를 잡는 룰을 도입합니다:

%% asm | auto | break | ... etc ... volatile | while /* it's a keyword */

[a-z]+ | . |  /* it's not a keyword */

1 행에 정확하게 1 어만 있는 것이 프로텍션되고 있는 경우, 개행의 인식을 다른 토큰과 합치는 것으로, 매치의 총수를 반으로 줄일 수가 있습니다:

%% asm  | auto  | break  | ... etc ... volatile | while  /* it's a keyword */

[a-z]+ | . |  /* it's not a keyword */

여기서, 재차 백업을 스캐너에 짜넣었던 것에 조심하지 않으면 안됩니다. 실제 우리는 입력 스트림은 레터와 개행 뿐인 것을 알고 있습니다만, flex (은)는 이것을 모르기 때문에, 토큰 "auto" 등을 스캔 한 다음의 캐릭터가 개행도 레터도 아닌 경우에는 백업이 필요하다라고 생각합니다. 이전에는 "auto" 룰에 적합해 그래서 끝이었지만, 지금은 "auto" 룰은 없고,"auto  룰만이 있습니다. 백업의 가능성을 제거하기 위해서는, 마지막 개행 이외의 룰을 이중화하는지, 그러한 입력을 당하지 않기 때문에 분류는 불요라고 알고 있기 (위해)때문에, 개행을 도입하고하나 더의 모두를 잡는 룰을 도입할 수가 있습니다:

%% asm  | auto  | break  | ... etc ... volatile | while  /* it's a keyword */

[a-z]+ | [a-z]+ | . |  /* it's not a keyword */

-Cf (을)를 붙여 컴파일 하면(자), 실제문제상 flex 그리고 얻을 수 있는 거의 최고 속도가 됩니다.

마지막 주의 사항: flex (은)는 NUL 에 매치 할 때에는 늦고, 토큰이 복수의 NUL 를 포함할 때에는 특히 늦습니다. 텍스트가 자주 NUL 를 포함하는 것으로 예상되는 경우에는, 텍스트의 짧다 부분과 매치 하도록(듯이) 룰을 써야 합니다.

하나 더의 성능에 관한 최종 주의 사항: 입력의 매치 방법의 마디로 이미 가리킨 것처럼, 큰 토큰을 납입하기 위해서(때문에) yytext 의 사이즈를 동적으로 변경하면 처리가 늦어집니다. 왜냐하면, (거대한) 토큰을 재차 선두로부터 스캔 다시 하지 않으면 안 되기 때문입니다. 성능이 중요한 경우, 텍스트의 "큰" 부분에 매치 시켜야 합니다가 "거대한" 부분에 성냥 시킨다 하지는 않습니다. 양자 계목은 8K 캐릭터/토큰입니다.

C++ 스캐너의 생성

flex (은)는 2 방법의 C++ 스캐너 생성 방법을 제공합니다. 최초의 방법은 flex 하지만 생성한 스캐너를 단지 C 컴파일러는 아니고 C++ 컴파일러로 컴파일 한다고 하는 것입니다. 이 경우 compile error에는 만나지 않을 것입니다 (찾아냈을 경우에는 저자의 마디로 후술 하는 전자메일 주소에 보고해 주세요). 이 경우 룰에 대해 C 코드는 아니고 C++ 코드를 쓸 수가 있습니다. 스캐너의 디폴트의 입력원래는 yyin 인 채여, 디폴트의 에코처는 yyout 인 채인 것에 주의해 주세요. 어느쪽이나 FILE * 변수인 채여, C++ streams (은)는 아닙니다.

flex 에 C++ 스캐너 클래스를 생성시킬 수도 있습니다. -+ 옵션을 지정한다(혹은 등가적으로 %option c++ (을)를 사용한다) 곳과 같이 실행되어 flex 의 실행 형식명이 '+'로 끝나고 있는 경우에는 자동적으로 지정됩니다. 이 옵션을 지정하면(자) flex 가 생성하는 스캐너의 디폴트는 파일 lex.yy.cc 되어 lex.yy.c (이)가 아닙니다. 생성된 스캐너는 2 개의 C++ 클래스와의 인터페이스를 정의하는 헤더 파일 FlexLexer.h (을)를 인클루드 합니다.

최초의 클래스 FlexLexer (은)는 일반적인 스캐너 클래스를 정의하는 추상 기반 클래스를 제공합니다. 이하의 멤버 함수를 제공합니다:
const char* YYText()
  마지막에 매치 한 텍스트를 돌려줍니다. yytext (와)과 등가입니다.
int YYLeng()
  마지막에 매치 한 토큰의 길이를 돌려줍니다. yyleng (와)과 등가입니다.
int lineno() const
  현재의 입력의 행 번호( %option yylineno 참조) 혹은 %option yylineno (을)를 사용하고 있지 않는 경우에는 1 (을)를 돌려줍니다.
void set_debug( int flag )
  스캐너의 디버그 플래그를 세트 합니다. yy_flex_debug 에 대입하는 것과 같습니다(옵션의 마디로 전술). 스캐너 구축시에 %option debug (을)를 사용해 디버그 정보를 짜넣을 필요가 있는 것에 주의해 주세요.
int debug() const
  현재의 디버그 플래그의 설정을 돌려줍니다.
또 다음의 것과 등가인 멤버 함수도 제공됩니다 yy_switch_to_buffer(), yy_create_buffer() (최초의 인수는 istream* 오브젝트 포인터이며 FILE* (이)가 아닙니다), yy_flush_buffer(), yy_delete_buffer(), yyrestart() (이것도 또 최초의 인수는 istream* 오브젝트 포인터입니다).
2 번째의 클래스는 FlexLexer.h 그리고 정의된다 yyFlexLexer (이어)여, FlexLexer (으)로부터 도출한 것입니다. 이하의 추가의 멤버 함수를 정의합니다:
yyFlexLexer( istream* arg_yyin = 0, ostream* arg_yyout = 0 ) 주어진 입출력 스트림을 사용한다 yyFlexLexer 오브젝트를 구축합니다. 지정하지 않는 경우에는 각각 스트림의 디폴트 cin (와)과 cout (이)가 됩니다.
virtual int yylex()
  이것은 yylex() 하지만 통상의 flex 스캐너에 대해서 간 것과 같은 역할을 담당합니다: 룰의 액션이 값을 돌려줄 때까지, 입력 스트림을 스캔 해, 토큰을 소비합니다. yyFlexLexer (으)로부터 서브 클래스 S (을)를 도출해 yylex() (으)로부터 S 의 멤버 함수 및 변수를 액세스 하고 싶은 경우, %option yyclass="S" (을)를 지정해 yyFlexLexer (은)는 아니고 서브 클래스를 사용하는 것을 flex 에 알릴 필요가 있습니다. 이 경우 yyFlexLexer::yylex() (을)를 생성하는 것이 아니라, flexS::yylex() ( 및 불려 갔다면 yyFlexLexer::LexerError() (을)를 호출하는 더미의 yyFlexLexer::yylex() 도)를 생성합니다.
virtual void switch_streams(istream* new_in = 0, ostream* new_out = 0) yyin (을)를 new_in (비닐의 경우) 에 재할당 해, yyout (을)를 new_out (같이)에 재할당 합니다. yyin 하지만 재할당 되었을 경우에는 이전의 입력 버퍼는 소거됩니다.
int yylex( istream* new_in, ostream* new_out = 0 ) 우선 입력 스트림을 switch_streams( new_in, new_out ) (을)를 사용해 바꾸어 yylex() 의 값을 돌려줍니다.
게다가 yyFlexLexer (은)는 다음의 프로텍트 된 가상 함수를 정의합니다. 스캐너에 맞추어 이것들을 도출 클래스에 있어 재정의 할 수 있습니다:
virtual int LexerInput( char* buf, int max_size ) 최대 max_size 캐릭터를 buf 에 읽어들여, 읽을 수 있었던 캐릭터수를 돌려줍니다. 입력의 끝을 나타내려면 0 캐릭터를 돌려줍니다. "대화적" 스캐너( -B (와)과 -I 플래그를 참조)는 매크로 YY_INTERACTIVE (을)를 정의하는 것에 주의해 주세요. LexerInput() (을)를 재정의해, 대화적인 입력원을 스캔 할 가능성이 있는지 어떤지에 의존해 다른 액션이 필요한 경우, 이 이름이 존재하는지 어떤지의 테스트는 #ifdef 에서 가능합니다.
virtual void LexerOutput( const char* buf, int size ) size 캐릭터를 버퍼 buf (으)로부터 써냅니다. 스캐너의 룰이 NUL 를 포함한 텍스트에 매치 가능한 경우, NUL 종단 되고 있는 이 버퍼는 "내부에" NUL 를 포함하고 있어도 상관하지 않습니다.
virtual void LexerError( const char* msg ) 치명적인 에러 메세지를 보고합니다. 디폴트의 이 함수는 메세지를 스트림 cerr 에 써, 종료합니다.
yyFlexLexer 오브젝트는 모든 스캔시 상태를 포함하는 것에 주의해 주세요. 그러므로 이와 같은 오브젝트를 re-entrant인 스캐너로서 사용할 수 있습니다. 동일한 yyFlexLexer 클래스의 복수의 인스턴스를 구체화 가능하고, 복수의 C++ 스캐너 클래스를 편성 상기 -P 옵션을 사용하는 것으로 동일한 프로그램으로 사용 가능합니다.

마지막에 %array 기능은 C++ 스캐너 클래스에서는 사용할 수 없는 것에 주의해 주세요; %pointer (을)를 사용하지 않으면 안됩니다(디폴트).

단순한 C++ 스캐너의 예를 이하에 나타냅니다:

// An example of using the flex C++ scanner class.

%{ int mylineno = 0; %}

string \"[^ ]+\"

ws [ \t]+

alpha [A-Za-z] dig [0-9] name ({alpha}|{dig}|\$)({alpha}|{dig}|[_.\-/$])* num1 [-+]? {dig}+\.?([eE][-+]? {dig}+)? num2 [-+]? {dig}*\. {dig}+([eE][-+]? {dig}+)? number {num1}|{num2}

%%

{ws} /* skip blanks and tabs */

"/*" { int c;

while((c = yyinput()) ! = 0) { if(c == ' ) ++mylineno;

else if(c == '*') { if((c = yyinput()) == '/') break; else unput(c); } } }

{number} cout << "number " << YYText() << ' ;

  mylineno++;

{name} cout << "name " << YYText() << ' ;

{string} cout << "string " << YYText() << ' ;

%%

int main( int /* argc */, char** /* argv */ ) { FlexLexer* lexer = new yyFlexLexer; while(lexer->yylex() ! = 0) ; return 0; }

복수의(다른) 어휘분석 클래스를 생성하고 싶은 경우, -P 플래그 (혹은 prefix= 옵션)을 사용해 각 yyFlexLexer (을)를 xxFlexLexer 등의 다른 이름으로 합니다. 다음에 어휘분석 클래스의 소스 마다 <FlexLexer.h> (을)를 인클루드 합니다. 이하와 같이 yyFlexLexer (을)를 rename 합니다:

#undef yyFlexLexer #define yyFlexLexer xxFlexLexer #include <FlexLexer.h>

#undef yyFlexLexer #define yyFlexLexer zzFlexLexer #include <FlexLexer.h>

이것은 있는 스캐너에 대해 %option prefix="xx" (을)를 사용해 이제(벌써) 한편에 대해 %option prefix="zz" (을)를 사용했을 경우입니다.

중요: 현재의 스캔 클래스의 형식은 실험적 (이어)여, 메이저 릴리스가 바뀌면(자) 크게 변경될 가능성이 있습니다.

LEX 및 POSIX 와의 비호환성

flex (은)는 AT&T Unix 의 lex 툴의 리라이트입니다만(2 개의 실장은 어떠한 코드도 공유하지 않습니다), 약간의 확장과 비호환성을 가지고 있어 어느 쪽의 실장에서도 수리 가능한 스캐너를 쓰고 싶은 (분)편은 이것을 의식하지 않으면 안됩니다. flex 는 POSIX lex 사양에 완전 합치합니다만, 예외는 %pointer (디폴트) 사용과 unput() 호출에 의해 yytext 의 내용을 파괴하는 것이어, 이것은 POSIX 사양에 반합니다.

이 마디에서는, flex 와 AT&T lex 와 POSIX 사양과의 사이의 모든 기존의 비호환성을 취급합니다.

flex-l 옵션은 오리지날의 AT&T lex 실장과의 최대의 호환성을 유효하게 합니다만, 생성된 스캐너의 성능은 크게 저하합니다. -l 옵션을 사용해도 발생할 수 있는 비호환성은 다음에 말합니다.

flex (은)는 이하의 예외를 제외해 lex (와)과 완전 호환입니다:
- 문서에 기재되지 않았다 lex 스캐너 내부의 변수 yylineno-l 혹은 %option yylineno (을)를 사용하지 않으면 서포트되지 않습니다.
yylineno (은)는 스캐너마다(단일의 글로벌 변수)가 아니고, 버퍼마다 관리되어야 합니다.
yylineno (은)는 POSIX 사양이 아닙니다.
- input() routine는 재정의할 수 없습니다만, 룰에 매치 한 것에 후속 하는 캐릭터를 읽기 위해서(때문에) 불릴 수 있습니다. input() 하지만 파일의 끝나에 도달하면(자), 통상의 yywrap() 처리는 종료합니다. ``실제의''파일의 끝은 EOF (으)로서 돌려주어집니다.
실제로는 입력은 YY_INPUT 매크로를 정의하는 것으로써 제어됩니다.
input() (을)를 재정의할 수 없다고 한다 flex 의 제한은, 최초로 yyin (을)를 설정하는 이외의 스캐너 입력 제어 방법을 단지 규정하고 있지 않다고 하는, POSIX 사양과 합치합니다.
- unput() routine는 재정의할 수 없습니다. 이 제한은 POSIX 에 합치하고 있습니다.
- flex 스캐너는 lex 스캐너와는 달라 re-entrant가 아닙니다. 실제, 대화적인 스캐너에 대해, 인터럽트 처리기에서 롱 점프를 이용해 스캐너로부터 탈출해, 그 후 스캐너를 재차 호출하는 경우, 이하의 메세지를 얻겠지요:

fatal flex scanner internal error--end of buffer missed

스캐너에 재차 들어가기 위해서(때문에)는, 우선 이하와 같이 해 주세요

yyrestart( yyin );

이 호출에 의해 입력 버퍼는 버려지는 것에 주의해 주세요; 통상 이것은 대화적 스캐너에서는 문제가 아닙니다.
또, C++ 스캐너 클래스는 re-entrant 입니다 의로, C++ 를 사용할 수 있다면, C++ 를 사용해야 합니다. 전술의 "C++ 스캐너의 생성" 을 참조해 주세요.
- output() (은)는 서포트되고 있지 않습니다. ECHO 매크로로부터의 출력은 파일 포인터 yyout (디폴트에서는 표준 출력 )에 대해서 행해집니다.
output() (은)는 POSIX 사양에는 없습니다.
- lex (은)는 배타적 개시 조건 (%x)을 서포트합니다만, 이것은 POSIX 사양에 있습니다.
- 정의를 전개할 때, flex 그럼 괄호로 괄. lex 에서는 이하는:

NAME [A-Z][A-Z0-9]* %% foo{NAME}? printf( "Found it  ); %%

캐릭터 라인 "foo" 에는 매치 하지 않습니다. 왜냐하면 전개된 매크로는 룰 "foo[A-Z][A-Z0-9]*? " (이)라고 등가가 되어, 우선도에서 `? '는 "[A-Z0-9]*" 와 연결해 붙습니다. flex 그럼 룰이 전개되면(자) "foo([A-Z][A-Z0-9]*)? " 되어, 캐릭터 라인 "foo" 가 매치 합니다.
^ 그리고 시작될까 $ 그리고 끝나는 정의는, 전개시에 괄호로 괄등않다, 이러한 오퍼레이터가 정의에 대해 특별한 의미를 잃지 않게 하는 것에 주의해 주세요. 그러나 <s>, /, <<EOF>> 오퍼레이터는 flex 의 정의에서는 사용할 수 없습니다.
-l (을)를 사용하면(자), lex 의 행동과 같이 정의를 괄호로 괄선.
POSIX 사양에서는, 정의를 괄호로 괄.
- lex 의 실장에 따라서는, 룰의 패턴의 우측으로 공백이 있는 경우, 룰의 액션을 다른 행으로부터 시작하는 것을 허락합니다:

%% foo|bar<space here> { foobar_action(); }

flex (은)는 이 기능을 서포트하지 않습니다.
- lex%r (Ratfor 스캐너의 생성) 옵션은 서포트되고 있지 않습니다. 이것은 POSIX 사양에는 포함되지 않습니다.
- 스캐너를 %array (을)를 사용해 구축한 것은 아닌 한, unput() 호출 후에는, 다음의 토큰에 매치 할 때까지 yytext (은)는 미정도리입니다. 이것은 lex 에도 POSIX 사양에도 들어맞지 않습니다. -l 옵션을 지정하는 곳의 비호환성을 없앱니다.
- {} (수치 범위) 오퍼레이터의 우선도가 다릅니다. lex (은)는 "abc{1,3}" 을 "1 도나 2 도나 3 도의 'abc'에 매치" 이라고 해석합니다만, flex (은)는 "'ab'에 1 번이나 2 번이나 3 번의 'c'가 계속되는 것에 매치" 이라고 해석합니다. 후자가 POSIX 사양에 합치합니다.
- ^ 오퍼레이터의 우선도가 다릅니다. lex (은)는 "^foo|bar" 를 "줄머리의 'foo'인가 임의 위치의 'bar'에 매치" 이라고 해석합니다만, flex (은)는 "줄머리의 'foo'인가 'bar'에 매치" 이라고 해석합니다. 후자가 POSIX 사양에 합치합니다.
- lex 그리고 서포트되고 있다 %a 등의 특별한 테이블 사이즈의 선언은 flex 스캐너에서는 불필요합니다; flex (은)는 이것들을 무시합니다.
- flex (와)과 lex 의 어디라도 스캐너를 사용 가능하게 쓸 수 있도록(듯이), FLEX_SCANNER (이)라는 이름을 정의합니다. 스캐너를 생성했다 flex 의 버젼을 나타낸다 YY_FLEX_MAJOR_VERSION (와)과 YY_FLEX_MINOR_VERSION (을)를, 스캐너는 포함합니다 (예를 들면 2.5 릴리스에서는 이것들은 각각 2 로 5 가 됩니다).
이하의 flex 의 기능은 lex 및 POSIX 사양에는 포함되지 않습니다:

C++ 스캐너 %option 개시 조건 스코프 개시 조건 스택 대화적/비대화적 스캐너 yy_scan_string() 등 yyterminate() yy_set_interactive() yy_set_bol() YY_AT_BOL() <<EOF>> <*> YY_DECL YY_START YY_USER_ACTION YY_USER_INIT #line 지시문 액션의 주위의 %{} 단일행에 있어서의 복수의 액션

한층 더 거의 모든 flex 플래그입니다. 리스트의 마지막 기능의 의미는, flex 그럼 복수의 액션을 세미콜론으로 단락지어 동일행에 기술 가능합니다만, lex 그럼 다음의

foo handle_foo(); ++num_foos_seen;

(은)는 (놀랄 만한 일로) 다음과 같이 절약할 수 있다고 하는 것입니다.

foo handle_foo();

flex (은)는 액션을 절약하지 않습니다. brace로 괄없는 액션은 단순하게 줄 끝으로 종료합니다.

진단

warning, rule cannot be matched 항상 같은 텍스트에 매치 하는 룰이 전에 있으므로, 주어진 룰이 매치 하지 않습니다. 예를 들면 이하의 "foo" 는 "모두를 잡는" 룰의 뒤에 있기 때문에 결코 매치 하지 않습니다:

[a-z]+ got_identifier(); foo got_foo();

스캐너중에서 REJECT (을)를 사용하는 곳의 경고를 억제합니다.

warning, -s option given but default rule can be matched (아마 어느 특정의 개시 조건의 아래에서는) 디폴트 룰 (임의의 한 글자에 매치 한다) 밖에 특정의 입력에 대해 매치 하지 않는 것이 있습니다. -s (을)를 지정해 있으므로, 아마 그렇게 되지 않습니다.

reject_used_but_not_detected undefined 혹은 yymore_used_but_not_detected undefined - 이러한 에러는 컴파일시에 일어납니다. 스캐너가 REJECT 혹은 yymore() (을)를 사용하고 있습니다만 flex 하지만 그것을 눈치채지 못했다고 하는 것입니다. 즉, flex (은)는 최초의 2 개의 부분을 찾아도 이러한 액션의 출현을 찾아낼 수 없었습니다만, 실제로는 어떠한 방법 (예를 들면 #include 파일을 개입시켜)(으)로 이것들이 기술되고 있었다는 일입니다. %option reject 인가 %option yymore (을)를 사용해, flex 에 이러한 기능을 실제로 사용하고 있는 것을 가르쳐 주세요.

flex scanner jammed - -s 그리고 컴파일 된 스캐너가, 어느 룰에도 매치 하지 않는다 입력 캐릭터 라인에 조우했습니다. 내부적인 문제에 기인해 이 에러가 일어나는 일도 있습니다.

token too large, exceeds YYLMAX - 스캐너가 %array (을)를 사용하고 있는 경우에, 어느 룰이 정수 YYLMAX (디폴트로 8K 바이트)보다 큰 캐릭터 라인과 매치 했습니다. flex 의 입력 파일의 정의부에서 YYLMAX (을)를 #define 하는 것으로 값을 크게 할 수 있습니다.

scanner requires -8 flag to use the character 'x' - 스캐너의 기술에 8 비트의 캐릭터 'x' (을)를 식별하는 부분이 있어, -Cf 혹은 -CF 의 테이블 압축 옵션을 위해서(때문에) 디폴트의 7 비트가 되어 있다 그럼에도 불구하고, -8 옵션을 붙이지 않다고 하는 것입니다. 자세한 것은 -7 플래그의 옵션의 논의를 참조해 주세요.

flex scanner push-back overflow - unput() 그리고 텍스트를 너무 되돌렸기 때문에 , 스캐너의 버퍼는 되돌린 텍스트와 현토큰을 yytext 에 유지할 수 없습니다. 이 경우, 이상적이게는 스캐너가 동적으로 버퍼의 크기를 바꾸어야 합니다가, 현재로서는 그렇게 되고는 있지 않습니다.

input buffer overflow, can't enlarge buffer because scanner uses REJECT - 스캐너는 매우 큰 토큰의 매치을 조사하고 있어, 입력 버퍼를 확장할 필요가 일어났습니다. 그렇지만, 버퍼의 확장은 REJECT (을)를 사용하는 스캐너에서는 일하지 않습니다.

fatal flex scanner internal error--end of buffer missed - 스캐너가 사용하고 있는 프레임으로부터(를 넘어) 롱 점프 한 후, 재차 스캐너에 들어갔을 경우에 일어납니다. 재차 스캐너에 들어가기 전에:

yyrestart( yyin );

(을)를 사용하는지, 전술과 같이 C++ 스캐너 클래스를 사용하도록(듯이) 해 주세요.

too many start conditions in <> construct! - 존재하는 것보다 많은 개시 조건을 <> 안에 기재했습니다 (적어도 하나를 두 번 기재했습니다).

관련 파일

-ll 스캐너가 링크 해야 하는 프로그램 라이브러리.
lex.yy.c
  생성된 스캐너(시스템에 따라서는 lexyy.c (이)라는 이름이 됩니다).
lex.yy.cc
  -+ (을)를 사용했을 때에 작성된 C++ 스캐너 클래스.
<FlexLexer.h> C++ 스캐너 베이스 클래스 FlexLexer (와)과 그 도출 클래스 yyFlexLexer (을)를 정의하는 헤더 파일.
flex.skl
  스켈리턴 스캐너. 이 파일은 flex 의 실행시가 아니고, flex 를 구축할 때 마셔 이용됩니다.
lex.backup
  -b 플래그용의 백업 정보(시스템에 따라서는 lex.bck (이)라는 이름이 됩니다).

결함 / 버그

우문맥(trailing context) 패턴안에는, 올바르게 매치 하지 않고 경고 메세지 ("dangerous trailing context")를 보내는 것이 있습니다. 이러한 패턴은, 룰의 최초의 부분이 2번째의 머리의 부분과 매치 하는 것 같은 것입니다. 예를 들면 "zx*/xy*" 의 경우, 'x*'는 우문맥의 머리의 'x'와 매치 합니다. (POSIX 드래프트에서는 그러한 패턴에 매치 하는 텍스트는 미정도리이다고 말하고 있는 것에 주의해 주세요. )

우문맥안에는, 실제로는 고정장인데 한다고는 해석되지 않는 것이 있어, 위에 말한 성능의 저하가 일어납니다. 특히, '|'나 {n} (예를 들면 "foo{3}")는 항상 가변장이다고 해석됩니다.

우문맥과 특별한 액션 '|'를 조합하면(자) 고정의 우문맥이 보다 코스트가 든다 가변의 우문맥이 됩니다. 예를 들면, 다음과 같은 것입니다:

%% abc | xyz/def

%array 혹은 -l 옵션을 지정하지 않는 경우, unput() (을)를 사용하면(자) yytext 와 yyleng 를 파괴합니다.

NUL 의 패턴 매칭은 다른 캐릭터의 비교보다 꽤 늦어지고 있습니다.

입력 버퍼의 동적인 크기의 재조정은 시간이 걸립니다. 이것은 현토큰 (일반적으로 거대)까지의 매치 한 전텍스트의 재스캔을 수반하기 (위해)때문입니다.

입력의 버퍼링과 예측을 위해, <stdio.h> routine와 혼합해 사용할 수가 없습니다. 예를 들면, getchar() (와)과 flex 의 룰은 잘 되어가지 않습니다. 대신에 input() (을)를 사용해 주세요.

-v 옵션으로 표시되는 전테이블 엔트리에는, 어느 룰이 매치 했는지를 결정하는데 필요한 테이블 엔트리수가 포함되어 있지 않습니다. 엔트리의 수는 스캐너가 REJECT (을)를 사용하지 않을 때에는 DFA 상태수에 동일하고, 사용하고 있을 때는 DFA 상태수부터 얼마인가 커집니다.

REJECT 하지만 옵션 -f 혹은 -F (와)과 함께 사용할 수 없습니다.

flex 의 내부 알고리즘에 대한 문서가 필요합니다.

관련 항목

lex(1), yacc(1), sed(1), awk(1) [영어]

John Levine, Tony Mason, and Doug Brown, Lex & Yacc, O'Reilly and Associates. 제 2 판을 입수하는 것.

M. E. Lesk and E. Schmidt, LEX - Lexical Analyzer Generator

Alfred Aho, Ravi Sethi and Jeffrey Ullman, Compilers: Principles, Techniques and Tools, Addison-Wesley(1) . flex 그리고 사용하고 있는 패턴 매칭 기법을 해설하고 있다(결정성 자동 장치).

저자

Vern Paxson 가 많은 아이디어와 인스피레이션을 얻는 도움을 Van Jacobson 로부터 받았습니다. 오리지날 버젼은 Jef Poskanzer 가 작성했습니다. 고속 테이블 표현은 Van Jacobson 의 디자인의 부분 실장입니다. 이 실장은 Kevin Gong 와 Vern Paxson 가 실시했습니다.

많은 flex 베타 테스타, 피드 바보, 콘트리뷰타, 특히 Francois Pinard, Casey Leedom, Robert Abramovitz, Stan Adermann, Terry Allen, David Barker-Plummer, John Basrai, Neal Becker, Nelson H.F. Beebe, benson@odi.com, Karl Berry, Peter A. Bigot, Simon Blanchard, Keith Bostic, Frederic Brehm, Ian Brockbank, Kin Cho, Nick Christopher, Brian Clapper, J.T. Conklin, Jason Coughlin, Bill Cox, Nick Cropper, Dave Curtis, Scott David Daniels, Chris G. Demetriou, Theo Deraadt, Mike Donahue, Chuck Doucette, Tom Epperly, Leo Eskin, Chris Faylor, Chris Flatters, Jon Forrest, Jeffrey Friedl, Joe Gayda, Kaveh R. Ghazi, Wolfgang Glunz, Eric Goldman, Christopher M. Gould, Ulrich Grepel, Peer Griebel, Jan Hajic, Charles Hemphill, NORO Hideo, Jarkko Hietaniemi, Scott Hofmann, Jeff Honig, Dana Hudes, Eric Hughes, John Interrante, Ceriel Jacobs, Michal Jaegermann, Sakari Jalovaara, Jeffrey R. Jones, Henry Juengst, Klaus Kaempf, Jonathan I. Kamens, Terrence O Kane, Amir Katz, ken@ken.hilco.com, Kevin B. Kenny, Steve Kirsch, Winfried Koenig, Marq Kole, Ronald Lamprecht, Greg Lee, Rohan Lenard, Craig Leres, John Levine, Steve Liddle, David Loffredo, Mike Long, Mohamed el Lozy, Brian Madsen, Malte, Joe Marshall, Bengt Martensson, Chris Metcalf, Luke Mewburn, Jim Meyering, R. Alexander Milowski, Erik Naggum, G.T. Nicol, Landon Noll, James Nordby, Marc Nozell, Richard Ohnemus, Karsten Pahnke, Sven Panne, Roland Pesch, Walter Pelissero, Gaumond Pierre, Esmond Pitt, Jef Poskanzer, Joe Rahmeh, Jarmo Raiha, Frederic Raimbault, Pat Rankin, Rick Richardson, Kevin Rodgers, Kai Uwe Rommel, Jim Roskind, Alberto Santini, Andreas Scherer, Darrell Schiebel, Raf Schietekat, Doug Schmidt, Philippe Schnoebelen, Andreas Schwab, Larry Schwimmer, Alex Siegel, Eckehard Stolz, Jan-Erik Strvmquist, Mike Stump, Paul Stuart, Dave Tallman, Ian Lance Taylor, Chris Thewalt, Richard M. Timoney, Jodi Tsai, Paul Tuinenga, Gary Weik, Frank Whaley, Gerhard Wilhelms, Kent Williams, Ken Yap, Ron Zellar, Nathan Zelle, David Zuhn, 및 나의 최저의 메일 아카이브(archive) 능력으로부터 미끄러져 떨어진 분들, 그러한 분들의 협력에도와 같이 감사합니다.

Keith Bostic, Jon Forrest, Noah Friedman, John Gilmore, Craig Leres, John Levine, Bob Mulcahy, G.T. Nicol, Francois Pinard, Rich Salz, Richard Stallman 에는 많은 고민의 분산에 관해서 감사합니다.

Esmond Pitt 와 Earle Horton 에는 8 비트 캐릭터 서포트에 관해서; Benson Margulies 와 Fred Burke 에는 C++ 서포트에 관해서; Kent Williams 와 Tom Epperly 에는 C++ 클래스 서포트에 관해서; Ove Ewerlid 에는 NUL 의 서포트에 관해서; Eric Hughes 에는 복수 버퍼의 서포트에 관해서, 각각 감사합니다.

이 작품은 당초, 내가 CA Berkeley 의 Lawrence Berkeley Laboratory 에 있어서의 Real Time Systems Group 에 있었을 때에 작성되었습니다. 나에게 협력해 준 분들에게 감사합니다.

코멘트는 vern@ee.lbl.gov 에 보내 주세요.


April 1995 FLEX (1) Version 2.5

tail head cat sleep
QR code linking to this page


Ben Bullock이 유닉스 매뉴얼 페이지에서 서비스에 대한 의견을 주시기 바랍니다. Privacy policy.

The wonderful thing about standards is that there are so many of them to choose from.
— Grace Murray Hopper