lex 명령
용도
입력 스트림의 단순 어휘 분석 패턴과 대응하는 C 또는 C++ 언어 프로그램을 생성합니다.
구문
설명
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가 true인 경우 프로그램은 모든 I/O에 대해 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)입니다. |
| %v:p | %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 스펙 파일의 규칙 섹션에서 사용할 수 있는 매크로로 다음 서브루틴을 정의합니다.
| 항목 | 설명 |
|---|---|
| 입력 | yyin에서 바이트를 읽습니다. |
| 넣지 않음 | 바이트를 읽은 후 대체합니다. |
| 출력 | 출력 바이트를 yyout에 씁니다. |
| winput (winput) | yyin으로부터 복수 바이트 문자를 읽습니다. |
| wunput (Wunput) | 복수 바이트 문자를 읽은 후 대체합니다. |
| 출력 (woutput) | 복수 바이트 출력 문자를 yyout에 씁니다. |
| yyset로케일 | 현재 로케일을 판별하기 위해 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 서브루틴이 없습니다. 따라서 lex.yy.c를 컴파일할 때 사용자 서브루틴 섹션에 main (), yywrap ()또는 둘 다를 포함하지 않으면 다음을 입력해야 합니다.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로 지정된 하나, 둘 또는 세 자리 8진수로 표시되는 인코딩 문자 |
| \xdigits | digits로 지정된 16진수 문자 시퀀스로 표시되는 인코딩 문자 |
| \c | 여기서 c는 위에 나열된 문자가 아니며 문자 c가 변경되지 않음을 나타냅니다. |
주: \0 또는 \x0을 lex 규칙에 사용하지 마십시오.
이러한 특수 문자를 표현식에서 사용하는 경우 인용 부호로 묶지 않아도 됩니다. 이들 특수 문자와 연산자 기호를 제외한 모든 문자는 항상 텍스트 문자입니다.
일치 규칙
두 개 이상의 표현식이 현재 입력과 대응될 수 있는 경우 lex 명령은 긴 대응 항목을 먼저 선택합니다. 여러 규칙이 동일한 수의 문자와 대응되는 경우에는 lex 명령이 가장 먼저 나타나는 규칙을 선택합니다. 예를 들어, 다음 규칙이 해당 순서로 제공되고
integer keyword action...;
[a-z]+ identifier action...;해당 순서로 제공됩니다.integers입력 단어 lex 는 입력을 ID로 일치시킵니다.[a-z]+8자와 일치합니다.integer7개만 일치합니다. 그러나 입력이 정수이면 두 규칙이 모두 7자를 대응시킵니다. lex는 가장 먼저 나타나는 키워드 규칙을 선택합니다. 더 짧은 입력 (예:int표현식 정수와 일치하지 않으므로 lex 가 ID 규칙을 선택합니다.
와일드카드 문자를 사용하여 문자열 대응
lex 가 가장 긴 일치를 먼저 선택하므로 다음과 같은 표현식을 포함하는 규칙을 사용하지 마십시오..*. 예:
'.*'단일 인용 부호 안의 문자열을 인식하는 좋은 방법일 수 있습니다. 그러나 어휘 분석기는 훨씬 앞쪽을 읽어 멀리 있는 단일 인용 부호를 찾아 긴 대응을 완성하려고 합니다. 이러한 규칙을 갖는 어휘 분석기에 다음과 같이 입력하면
'first' quoted string here, 'second' here다음과 같이 대응됩니다.
'first' quoted string here, 'second'더 작은 문자열을 찾으려면 다음을 수행하십시오.first및second, 다음 규칙을 사용하십시오.
'[^'\n]*'이 규칙은 다음 이후에 중지됨'first'.
이 유형의 오류는 그리 멀리 미치지 않습니다. 그 이유는 .(마침표) 연산자가 새 행 문자에 대응하지 않기 때문입니다. 따라서 다음과 같은 표현식은.*(마침표 별표) 가 현재 행에서 중지됩니다. 다음과 같은 표현식을 사용하여 이를 패배시키지 마십시오. [.\n]+. 어휘 분석기는 전체 입력 파일을 읽으려고 시도하고 내부 버퍼 오버플로우가 발생합니다.
문자열 내에서 문자열 찾기
lex 프로그램은 입력 스트림을 분할하며 각 표현식의 가능한 모든 대응을 검색하지는 않습니다. 각 문자는 한 번만 계산됩니다. 예를 들어,she및he입력 텍스트에서 다음 규칙을 시도하십시오.
she s++
he h++
\n |. ;여기서 마지막 두 개의 규칙은he및she하지만,she포함he, lex 는 다음의 인스턴스를 인식하지 않습니다 .he포함되어 있는she.
이 선택을 재정의하려면 REJECT 조치를 사용하십시오. 이 지시문은 lex가 다음 규칙으로 이동하도록 지시합니다. 그런 다음 lex가 입력 포인터의 위치를 첫 번째 규칙이 실행되기 전 위치로 조정하고 두 번째 선택 규칙을 실행합니다. 예를 들어,he다음 규칙을 사용하십시오.
she {s++;REJECT;}
he {h++;REJECT;}
\n |. ;발생 횟수를 계산한 후she, lex 는 입력 스트림을 거부한 후he. 이 경우에는she포함he반대의 경우에는 REJECT 조치를 생략할 수 있습니다.he. 다른 경우에는 두 클래스 모두에 있는 입력 문자를 판별하기 어려울 수 있습니다.
일반적으로 REJECT는 lex의 용도가 입력 스트림을 분할하는 것이 아니라 입력에서 일부 항목의 모든 예를 발견하는 것일 때, 또한 이러한 항목의 인스턴스가 중첩되거나 서로를 포함할 때 항상 유용합니다.
플래그
| 항목 | 설명 |
|---|---|
| -c | C++ 컴파일러와 사용하기 위해 lex.yy.c 대신 lex.yy.C 파일을 생성합니다. 입출력 스트림 라이브러리를 가져오려면 매크로 _CPP_IOSTREAMS 또한 사용하십시오. |
| -n | 통계 요약을 억제합니다. 유한 상태 기계에 대한 사용자 표 크기를 설정할 때, lex 명령은 사용자가 이 플래그를 선택하지 않으면 자동으로 요약을 생성합니다. |
| -t | lex.yy.c를 파일 대신 표준 출력에 씁니다. |
| -v | 생성된 유한 상태 기계 통계에 대한 한 행 길이의 요약을 제공합니다. |
종료 상태
이 명령은 다음과 같은 종료값을 리턴합니다.
| 항목 | 설명 |
|---|---|
| 0 | 정상적으로 완료되었습니다. |
| > 0 | 오류가 발생했습니다. |
예
- 파일에서 lex 명령어를 그리려면 다음을 수행하십시오.lexcommands출력을 lex.yy.c에 배치하고 다음 명령을 사용하십시오.
lex lexcommands - 대문자를 소문자로 변환시키고, 행의
끝의 공백을 없애고, 여러 개의 공백을 하나의 공백으로 대체하는
lex 프로그램을 작성하려면 lex
명령 파일에 다음을 포함시키십시오.
%% [A-Z] putchar(yytext[0]+ 'a'-'A'); [ ]+$ ; [ ]+ putchar(' ');
파일
| 항목 | 설명 |
|---|---|
| /usr/ccs/lib/libl.a | 실행시간 라이브러리를 포함합니다. |
| /usr/ccs/lib/lex/ncform | 유한 상태 기계를 정의합니다. |