lex 명령

용도

입력 스트림의 단순 어휘 분석 패턴과 대응하는 C 또는 C++ 언어 프로그램을 생성합니다.

구문

lex [ -C ] [ -t ] [ -v| -n ] [ File... ]

설명

lex 명령은 File 또는 표준 입력을 읽고 C 언어 프로그램을 생성하여 lex.yy.c 파일에 기록합니다. 이 lex.yy.c 파일은 컴파일 가능한 C 언어 프로그램입니다. C++ 컴파일러 또한 lex 명령의 출력을 컴파일할 수 있습니다. -C 플래그는 C++ 컴파일러의 경우 출력 파일의 이름을 lex.yy.C로 바꿉니다.

lex 명령으로 생성된 C++ 프로그램은 STDIO 또는 IOSTREAMS를 사용할 수 있습니다. C++ 컴파일 동안 cpp define_CPP_IOSTREAMS가 참이면, 프로그램은 모든 입출력에 대해 IOSTREAMS를 사용합니다. 그렇지 않으면 STDIO를 사용합니다.

lex 명령은 File에 포함된 규칙과 조치를 사용하여 lex.yy.c 프로그램을 생성하며 이 프로그램은 cc 명령으로 컴파일될 수 있습니다. 컴파일된 lex.yy.c는 입력을 수신하고, File의 규칙으로 정의된 논리적 부분으로 입력을 나누고, File의 조치에 포함된 프로그램 프래그먼트를 실행할 수 있습니다.

생성된 프로그램은 C 언어 함수 yylex입니다. lex 명령은 yylex 기능을 lex.yy.c 파일에 저장합니다. yylex 기능만 사용하여 간단한 한 단어 입력을 인식하거나, 이 기능을 다른 C 언어 프로그램과 함께 사용하여 보다 어려운 입력 분석 기능을 수행할 수 있습니다. 예를 들어, lex 명령을 사용하여 yacc 명령으로 작성된 구문 분석기 프로그램으로 보내기 전에 입력 스트림을 단순화하는 프로그램을 작성할 수 있습니다.

yylex 함수는 유한 상태 기계라는 프로그램 구조를 사용하여 입력 스트림을 분석합니다. 이 구조에서는 프로그램이 한번에 한 상태(또는 조건)로만 존재할 수 있습니다. 허용되는 상태 개수는 한정적입니다. File의 규칙은 프로그램이 특정 상태에서 다른 상태로 이동하는 방식을 판별합니다.

File을 지정하지 않으면 lex 명령은 표준 입력을 읽습니다. 여러 파일을 단일 파일로 취급합니다.

참고: lex 명령은 중간 및 출력 파일에 대해 고정 이름을 사용하므로 lex로 생성된 프로그램은 지정된 디렉토리에 하나만 존재할 수 있습니다.

lex 스펙 파일

입력 파일은 세 가지 섹션(정의, 규칙, 사용자 서브루틴)으로 구성됩니다. 각 섹션은 분리 문자인 %%(이중 퍼센트 부호)만을 포함하는 행으로 다른 섹션과 구분해야 합니다. 형식은 다음과 같습니다.

각각의 용도와 형식은 다음 섹션에 설명되어 있습니다.

정의

규칙에서 변수를 사용하려는 경우 이 섹션에서 정의해야 합니다. 변수는 왼쪽 열을 구성하고 해당 정의는 오른쪽 열을 구성합니다. 예를 들어, D를 숫자로 정의하려면 다음과 같이 작성합니다.


D   [0-9]

변수 이름을 {}(중괄호)로 묶어 규칙 섹션에서 정의된 변수를 사용할 수 있습니다.


{D}

공백으로 시작하거나 %{, %} 분리 문자로 묶은 정의 섹션의 행은 lex.yy.c 파일에 복사됩니다. 이 구조를 사용하여 lex 조치에서 사용하거나 헤더 파일을 포함할 C 언어 변수를 선언할 수 있습니다.

%{
#include <math.h>
int count;
%}

이러한 행은 규칙 섹션의 시작 부분에서 첫 번째 %% 분리 문자 바로 다음에 나타날 수도 있지만 규칙 섹션의 다른 위치에서는 사용해서는 안 됩니다. 행이 File의 정의 섹션에 있는 경우, lex 명령은 lex.yy.c 파일의 외부 선언 섹션에 행을 복사합니다. 행이 규칙 섹션에서 첫 번째 규칙 앞에 나타나는 경우에는 lex 명령이 lex.yy.c에서 yylex 서브루틴의 로컬 선언 섹션에 행을 복사합니다. 해당 행은 첫 번째 규칙 다음에 나타나서는 안 됩니다.

lex 외부 유형 즉, yytext는 정의 섹션에 다음 중 하나를 지정하여 널(null) 종료 문자 배열(디폴트) 또는 널(null) 문자 종료 문자열의 포인터로 설정될 수 있습니다.


%array    (default)
%pointer

정의 섹션에서 결과 유한 상태 기계에 대한 테이블 크기를 설정할 수 있습니다. 디폴트 크기는 작은 프로그램에 충분할 만큼 큽니다. 보다 복잡한 프로그램의 경우 더 큰 크기를 설정할 수 있습니다.

항목 설명
%an 전이 횟수는 n(디폴트 5000)입니다.
%en 구문 분석 트리 노드의 수는 n(디폴트 2000)입니다.
%hn 복수 바이트 문자 출력 슬롯의 수(디폴트 0)
%kn 압축된 문자 클래스의 수(디폴트 1000)
%mn 복수 바이트 "문자 클래스" 문자 출력 슬롯의 수(디폴트 0)
%nn 상태의 수는 n(디폴트 2500)입니다.
%on 출력 슬롯의 수(디폴트 5000, 최소 257)
%pn 위치의 수는 n(디폴트 5000)입니다.
%vp %h%m으로 제어되는 해쉬 테이블에서 비어 있는 슬롯의 백분율(디폴트 20, 범위 0 <= P < 100)
%zn 복수 바이트 문자 클래스 출력 슬롯의 수(디폴트 0)

복수 바이트 문자가 확장 정규식 문자열에 나타나는 경우, %o 인수를 사용하여 출력 배열 크기를 가능한 10,000 - 20,000 범위 내의 배열 크기로 재설정해야 합니다. 이 재설정에는 1바이트 문자 개수보다 훨씬 많은 문자 수가 반영됩니다.

복수 바이트 문자가 확장 정규식에 나타나는 경우, %h%m 인수로 복수 바이트 해쉬 테이블 크기를 lex 파일에 포함된 총 복수 바이트 문자 수보다 많은 크기로 설정해야 합니다.

복수 바이트 문자가 확장 정규식에 나타나지 않지만 '.'를 복수 바이트 문자와 대응시키려는 경우에는 %z를 0보다 크게 설정해야 합니다. 마찬가지로, 역문자 클래스(예: [^abc])를 복수 바이트 문자와 대응시키려면 %h%m을 0보다 크게 설정해야 합니다.

복수 바이트 문자를 사용하는 경우 -qmbcs 컴파일러 옵션으로 lex.yy.c 파일이 컴파일되어야 합니다.

규칙

항목을 정의한 후 규칙 섹션을 작성할 수 있습니다. 규칙 섹션에는 yylex 서브루틴이 대응시킬 문자열과 표현식이 포함되며 대응되는 경우 실행할 C 명령이 포함됩니다. 이 섹션은 필수사항이며 정의 섹션 유무에 관계 없이 분리 문자 %%(이중 퍼센트 부호)가 앞에 와야 합니다. 이 분리 문자가 없으면 lex 명령이 규칙을 인식하지 못합니다.

이 섹션에서 왼쪽 열에는 확장 정규식 양식의 패턴이 포함되며 이 패턴은 yylex 서브루틴의 입력 파일에서 인식됩니다. 오른쪽 열에는 이 패턴이 인식될 때 실행되는 C 프로그램 프래그먼트인 action이 포함됩니다.

어휘 분석기가 확장 정규식에 대한 대응 항목을 찾으면 어휘 분석기가 해당 확장 정규식과 연관된 조치를 실행합니다.

패턴은 확장 문자를 포함할 수 있습니다. 복수 바이트 로케일이 시스템에 설치된 경우, 설치된 코드 세트의 일부인 복수 바이트 문자가 패턴에 포함될 수도 있습니다.

열은 탭 또는 공백으로 구분됩니다. 예를 들어, 파일에서 키워드 KEY를 검색하려면 다음을 작성할 수 있습니다.

(KEY) printf ("found KEY");

이 규칙을 File에 포함하면 yylex 허위 분석기가 패턴 KEY를 대응시키고 printf 서브루틴을 실행합니다.

각 패턴은 상응하는 조치(즉, 패턴을 대응시킬 때 실행할 C 명령)를 가질 수 있습니다. 각 명령문은 ;(세미콜론)으로 끝나야 합니다. 조치에서 두 개 이상의 명령문을 사용하는 경우 모든 명령문을 { }(중괄호)로 묶어야 합니다. 사용자 서브루틴 섹션이 있으면 두 번째 분리 문자, %%가 규칙 섹션 뒤에 와야 합니다. 패턴 대응에 지정된 조치가 없으면 어휘 분석기는 입력 패턴을 변경하지 않고 출력에 복사합니다.

yylex 어휘 분석기는 입력 스트림의 문자열을 대응시킬 때 규칙 섹션의 명령을 실행하기 전에 대응된 문자열을 외부 배열(또는 문자열 포인터), yytext에 복사합니다. 마찬가지로, 외부 int yyleng는 바이트 단위로 대응 문자열 길이로 설정됩니다. 따라서, 다중 바이트 문자의 크기는 1보다 큽니다.

사용자 서브루틴

lex 라이브러리는 lex 스펙 파일의 규칙 섹션에서 사용할 수 있는 매크로로 다음 서브루틴을 정의합니다.

항목 설명
input yyin에서 바이트를 읽습니다.
unput 바이트를 읽은 후 대체합니다.
output 출력 바이트를 yyout에 씁니다.
winput yyin으로부터 복수 바이트 문자를 읽습니다.
wunput 복수 바이트 문자를 읽은 후 대체합니다.
woutput 복수 바이트 출력 문자를 yyout에 씁니다.
yysetlocale 현재 로케일을 판별하기 위해 setlocale (LC_ALL, " " ) 서브루틴을 호출합니다.

winput, wunput, woutput 매크로는 lex.yy.c 파일에서 코드화된 yywinput, yywunput, yywoutput 서브루틴을 사용하도록 정의됩니다. 호환성을 위해 이 yy 서브루틴은 input, unput, output 서브루틴을 연달아 사용하여 전체 복수 바이트 문자에서 필요한 바이트 수를 읽고, 대체하며 씁니다.

사용자 서브루틴 섹션에서 이 루틴에 대한 코드를 직접 작성하여 이 매크로를 재정의할 수 있습니다. 그러나 직접 작성하는 경우 다음과 같이 정의 섹션에서 이 매크로를 정의 해제해야 합니다.

%{
#undef input
#undef unput
#undef output
#undef winput
#undef wunput
#undef woutput
#undef yysetlocale
%}

lex 라이브러리에는 yylex 어휘 분석기를 호출하는 main 서브루틴과 File 끝에서 yylex( )로 호출되는 yywrap 서브루틴도 있으므로 lex.yy.c에는 main 서브루틴이 없습니다. 따라서 사용자 서브루틴 섹션에서 main( ) 또는 yywrap( )이나 둘 다 포함하지 않는 경우 lex.yy.c를 컴파일할 때 cclex.yy.c-ll를 입력해야 합니다. 여기서 lllex 라이브러리를 호출합니다.

lex 명령으로 생성되는 외부 이름은 모두 머리말 yy로 시작됩니다(예를 들어, yyin, yyout, yylex, yytext).

유한 상태 기계

유한 상태 기계에 대한 디폴트 스켈레톤은 /usr/ccs/lib/lex/ncform에서 정의됩니다. 사용자는 환경 변수 LEXER=PATH를 설정하여 개인적으로 구성된 유한 상태 기계를 사용할 수 있습니다. PATH 변수는 사용자 정의 유한 상태 기계 경로와 파일 이름을 지정합니다. lex 명령은 이 변수의 환경을 검사하고 설정된 경우 제공된 경로를 사용합니다.

표현식에 공백 넣기

일반적으로 규칙과 규칙을 정의하는 표현식은 공백 또는 탭으로 끝납니다. 그러나 공백 또는 탭 문자를 " "(인용 부호)로 묶어 표현식에 포함시킬 수 있습니다. 아직 [ ](대괄호) 세트로 묶지 않은 표현식의 모든 공백을 묶는 데는 인용 부호를 사용하십시오.

기타 특수 문자

lex 프로그램은 많은 일반 C 언어 특수 문자를 인식합니다. 문자 시퀀스는 다음과 같습니다.

시퀀스 의미
\a 경고
\b 백스페이스
\f 용지 넘김
\n 줄 바꾸기 문자(표현식에서는 실제 줄 바꾸기 문자를 사용하지 않습니다.)
\r 돌아가기
\t
\v 세로 탭
\\ 백슬래시
\digits digits로 지정된 하나, 둘 또는 세 자리 8진수로 표시되는 인코딩 문자
\xdigits digits로 지정된 16진수 문자 시퀀스로 표시되는 인코딩 문자
\c 여기서 c는 위에 나열된 문자가 아니며 문자 c가 변경되지 않음을 나타냅니다.

참고: lex 규칙에서 \0 또는 \x0을 사용하지 마십시오.

이러한 특수 문자를 표현식에서 사용하는 경우 인용 부호로 묶지 않아도 됩니다. 이들 특수 문자와 연산자 기호를 제외한 모든 문자는 항상 텍스트 문자입니다.

대응 규칙

두 개 이상의 표현식이 현재 입력과 대응될 수 있는 경우 lex 명령은 긴 대응 항목을 먼저 선택합니다. 여러 규칙이 동일한 수의 문자와 대응되는 경우에는 lex 명령이 가장 먼저 나타나는 규칙을 선택합니다. 예를 들어, 다음 규칙이 해당 순서로 제공되고

integer    keyword action...;
[a-z]+       identifier action...;

integers가 입력 단어인 경우, lex는 입력을 ID로 대응시킵니다. integer가 7자만 대응시키는 반면 [a-z]+는 8자를 대응시키기 때문입니다. 그러나 입력이 정수이면 두 규칙이 모두 7자를 대응시킵니다. lex는 가장 먼저 나타나는 키워드 규칙을 선택합니다. int와 같은 축약형 입력은 표현식 정수에 대응하지 않으므로 lex가 ID 규칙을 선택합니다.

와일드카드 문자를 사용하여 문자열 대응

lex는 가장 긴 일치 항목을 먼저 선택하므로 .*와 같은 표현식을 포함하는 규칙은 사용하지 마십시오. 예:

'.*'

단일 인용 부호 안의 문자열을 인식하는 좋은 방법일 수 있습니다. 그러나 어휘 분석기는 훨씬 앞쪽을 읽어 멀리 있는 단일 인용 부호를 찾아 긴 대응을 완성하려고 합니다. 이러한 규칙을 갖는 어휘 분석기에 다음과 같이 입력하면

'first' quoted string here, 'second' here

다음과 같이 대응됩니다.

'first' quoted string here, 'second'

더 작은 문자열 firstsecond를 찾으려면 다음 규칙을 사용하십시오.

'[^'\n]*'

이 규칙은 'first' 다음에 중지됩니다.

이 유형의 오류는 큰 영향을 미치지 않습니다. .(마침표) 연산자가 줄 바꾸기 문자에 대응되지 않기 때문입니다. 따라서 .*(마침표 별표)와 같은 표현식은 현재 행에서 중지됩니다. [.\n]+과 같은 표현식으로 이 오류를 해결하려고 시도하지 마십시오. 어휘 분석기는 전체 입력 파일을 읽으려고 시도하여 내부 버퍼 오버플로우가 발생합니다.

문자열 내에서 문자열 찾기

lex 프로그램은 입력 스트림을 분할하며 각 표현식의 가능한 모든 대응을 검색하지는 않습니다. 각 문자는 한 번만 계산됩니다. 예를 들어, 입력 텍스트에서 shehe가 몇 번 나타나는지 계산하려면 다음 규칙을 시도하십시오.

she         s++
he          h++
\n          |.           ;

여기서 마지막 두 규칙은 heshe 이외의 모든 것을 무시합니다. 그러나 she에는 he가 포함되므로 lexshe에 포함된 he의 인스턴스를 인식하지 않습니다.

이 선택을 재정의하려면 REJECT 조치를 사용하십시오. 이 지시문은 lex가 다음 규칙으로 이동하도록 지시합니다. 그런 다음 lex가 입력 포인터의 위치를 첫 번째 규칙이 실행되기 전 위치로 조정하고 두 번째 선택 규칙을 실행합니다. 예를 들어, he의 포함된 인스턴스를 계산하려면 다음 규칙을 사용하십시오.

she                 {s++;REJECT;}
he                  {h++;REJECT;}
\n                  |.                   ;

lexshe 발생 횟수를 계산한 후 입력 스트림을 거부하고 he 발생 횟수를 계산합니다. 이 경우 she에는 he가 포함되지만 그 반대의 경우는 해당되지 않으므로 he에 대한 REJECT 조치를 생략할 수 있습니다. 다른 경우에는 두 클래스에 모두 속하는 입력 문자를 판별하기 어려울 수 있습니다.

일반적으로 REJECTlex의 용도가 입력 스트림을 분할하는 것이 아니라 입력에서 일부 항목의 모든 예를 발견하는 것일 때, 또한 이러한 항목의 인스턴스가 중첩되거나 서로를 포함할 때 항상 유용합니다.

플래그

항목 설명
-C C++ 컴파일러와 사용하기 위해 lex.yy.c 대신 lex.yy.C 파일을 생성합니다. 입출력 스트림 라이브러리를 가져오려면 매크로 _CPP_IOSTREAMS 또한 사용하십시오.
-n 통계 요약을 억제합니다. 유한 상태 기계에 대한 사용자 표 크기를 설정할 때, lex 명령은 사용자가 이 플래그를 선택하지 않으면 자동으로 요약을 생성합니다.
-t lex.yy.c를 파일 대신 표준 출력에 씁니다.
-v 생성된 유한 상태 기계 통계에 대한 한 행 길이의 요약을 제공합니다.

종료 상태

이 명령은 다음 종료값을 리턴합니다.

항목 설명
0 정상적으로 완료되었습니다.
>0 오류가 발생했습니다.

  1. 파일 lexcommands에서 lex 명령어를 가져와 lex.yy.c의 출력에 배치하려면 다음 명령을 사용하십시오.
    lex lexcommands
  2. 대문자를 소문자로 변환하고 행 끝의 공백을 제거하며 여러 공백을 단일 공백으로 대체하는 lex 프로그램을 작성하려면 lex 명령 파일에 다음을 포함시키십시오.
    %%
    [A-Z]   putchar(yytext[0]+ 'a'-'A');
    [ ]+$ ;
    [ ]+    putchar(' '); 

파일

항목 설명
/usr/ccs/lib/libl.a 실행시간 라이브러리를 포함합니다.
/usr/ccs/lib/lex/ncform 유한 상태 기계를 정의합니다.