본문 바로가기

Programming/LEX & YACC

LEX 의 정규 표현식

LEX 의 정규  표현식

정규식은 메타 언어를 사용한 패턴의 기술(description)을 말한다. 하나의 수식은 기호들로 구성되어 있다. 기호들은 보통 문자와 숫자이다. 그러나 Lex에서 특별한 의미를 지니는 기호들이 있다. 다음 두 표는 Lex에서 사용되는 여러 기호를 규정하고 있으며 약간의 전형적인 예제를 제시한다.

Lex에서의 레귤러 표현 규정

문자

의미

A-Z, 0-9, a-z

패턴의 일부를 구성하는 문자와 숫자.

.

\n을 제외한 어느 문자와도 일치.

-

범위를 표시할 때 사용. : A-Z은 문자 A부터 Z까지를 의미.

[ ]

문자 클래스. 괄호 안의 어느 문자와도 일치. 첫 문자가 ^이면 부정 패턴을 나타냄. : [abC] a,b 혹은 C와 일치.

*

선행 패턴의 발생이 0 이상.

+

선행 패턴의 발생이 1 이상.

?

선행 패턴의 발생이 0 또는 1 일 때 일치.

$

패턴의 마지막 문자가 행 종료일 때 일치.

{ }

패턴이 나타날 수 있는 횟수를 표시. : A{1,3} A 1회나 3회 표시 가능을 의미.

\

메타 문자를 피하기 위해 사용. 또한 이 표에 규정된 문자의 특별한 의미를 제거하는데 사용.

^

부정.

|

수식의 논리합.

"<some symbols>"

문자 그대로의 의미. 메타 문자 보류.

/

표현이 계속되는 경우에 한하여 선행 패턴과 일치. : A0/1 A01이 입력일 경우에 한하여 A0와 일치.

( )

일련의 정규식을 그룹화.


레귤러 표현의 예제

레귤러 표현

의미

joke[rs]

jokes 혹은 joker와 일치.

A{1,2}shis+

AAshis, Ashis, Aashi, Ashi와 일치.

(A[b-e])+

A의 발생이 없거나 한 번 이상이고 b에서 e까지의 어느 한 문자가 이어질 경우에 일치 .

Lex에서의 토큰은 C의 변수명 같이 선언된다. 토큰은 모두 관련된 수식을 가지고 있다. (다음 표에 토큰과 수식의 예가 나와 있다.) 표를 예로 들어 워드 카운트(단어의 개수를 세는) 프로그램을 작성할 것이다. 첫번째 일은 토큰이 선언되는 방식을 제시하는 것이다.


토큰 선언 예제

토큰

관련 수식

의미

number

([0-9])+

숫자가 1회 이상 발생

chars

[A-Za-z]

임의 문자

blank

" "

1개의 블랭크 스페이스

word

(chars)+

chars1회 이상 발생

variable

(chars)+(number)*(chars)*( number)*

 

 

LEXER YACC로 토큰 리턴 방식.

lex 에 의해 만들어진 lexer 의 시작은 yylex() 라는 함수를 호출하면서 시작한다. 특정 패턴이 토큰에 매치했을때 실행되는 c 코드는 yylex() 의 결과 값을 호출함수에 리턴하는 return 문을 포함 할 수 있다.

 

some1            {return 1;}

some2            {return 2;}

 

이런 호출은 보통 yacc 가 생성한 Parser에서 호출한다. yylex() 가 다시 호출될때 스캐너는 마지막에 리턴했던 위치에서 부터 다시 스캔을 시작하게 된다.

스캐너가 Parser에서 관심을 두는 토큰(즉 키워드, 변수명, 또는 연산자)를 발견하면, 해당 토큰을 Parser에 전달하기 위해 return을 이용한다. 만약 Parser가 관심을 갖지 않는 토큰(즉 공백이나 주석)을 발견하면, 스캐너는 리턴하지 않고 다른 토큰을 찾기 위한 작업을 계속 수행한다.

이는 yylex()를 다시 호출한다 해도, Lexer를 처음부터 재 시작할 수 없다는 것을 의미한다.

Lexer를 처음부터 재 시작하기 위해서는 BEGIN_INITIAL 을 이용해 기본 상태로 되돌아가서 unput()을 이용해 버퍼에 저장된 입력 텍스트는 모두 버리고, input() 에 대한 호출이 새로운 입력을 읽어 들이도록 해야 한다.

Lex에서는 Lexer를 매우 쉽게 재 시작할 수 있다. file이 표준 I/O 파일에 대한 포인터라고 가정 했을때, yyrestart(file) 를 호출하면 이 파일을 새로운 입력으로 삼아 처음부터 다시 읽기 시작한다.

피시Lex에서는 매크로 YY_INIT를 이용하여 스캐너의 상태를 다시 설정할 수 있다. 아마 yyin에 연결된 파일을 되감거나 이곳에 새로운 파일을 할당해야 할 것이다.

MKS Lex에서는 스캐너 파일 안에서만 작동하는 매크로 YY_INIT를 이용하거나, 어디서나 호출할 수 있는 루틴인 yy_reset를 이용한다.



참고 ㅣ lex와 yacc 존 레빈 , 토니 메이슨 ,더그 브라운 저