상세 컨텐츠

본문 제목

계산기용 스캐너 만들기 - Lex 편

etc

by ryujt 2010. 11. 1. 16:41

본문

http://ryujt.textcube.com/61 에서 공개된 계산기 프로그램의 경우에는 Lex를 사용하지 않고 순수한 코딩으로 스캐너를 만들었습니다.  Lex를 사용하지 않은 이유는 생성된 코드가 제 맘에 들지 않아서 입니다.  하지만, Lex 사용법에 대해서 설명하는 것이 좋겠다 싶어서, 이번에는 Lex를 이용해서 만들어 보기로 하겠습니다.

우선 델파이용 Lex와 Yacc는 아래의 링크에서 구하실 수 있습니다.

강의에서는  제가 위의 자료를 Subversion으로 옮겨 둔 것을 사용할 것 입니다.  주소는 아래와 같습니다.

Subversion의 저장소는 아래와 같습니다.
    https://dev.naver.com/svn/lexyacc

우선 확장자가 (.l)인 Lex 파일부터 작성합니다.  스캐닝을 위한 문법을 정규식을 이용하여 정의 합니다.  여기서 정규식에 대한 설명은 지나가도록 하겠습니다.  이부분에 대해서는 제가 다른 사이트나 책자보다 쉽게 설명해드릴 능력이 되지 않습니다.  정규식만 보면 두통이 ㅡ.ㅡ;

L                               [\(]

R                               [\)]

D                          [0-9]

O                          [\+\-\*\/\%\^]

I                              [A-Za-z][A-Za-z0-9_]*

 

%start

 

  var

    ConvertResult : extended;

 

%%

 

{L}                        WriteLn(Format('Left Parenthesis : %s', [yytext]));

 

{R}                        WriteLn(Format('Right Parenthesis : %s', [yytext]));

 

{D}+(\.{D}+)?([Ee][+-]?{D}+)?    begin

                                  try

                                    ConvertResult := StrToFloat(yytext);

                               WriteLn(Format('Number : %s', [FloatToStr(ConvertResult)]))

                                  except

                               WriteLn(Format('Error : %s', [yytext]))

                                  end;

                           end;

 

{I}                        WriteLn(Format('Identifier : %s', [yytext]));

 

{O}                        WriteLn(Format('Operation : %s', [yytext]));

 

" "                    ;

 

.                          |

\n                         ;

 

위의 내용을 exprlex.l로 저장해 두고, 위의 Subversion 저장소 (이후 svn://)의 다음 위치에 옮겨서 [그림 1]과 같이 pas 파일로 변환합니다.  결과적으로 정규식을 만족하는 문자열이 발견되면 오른쪽의 델파이 코드가 실행됩니다.
  •  svn://trunk\Bin
[그림 1] Lex 파일 Pas로 변환

델파이 콘솔용 프로젝트를 새로 만드시고, 아래와 같이 코딩을 완료합니다.

[Code delphi]
program Sample;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  dlib,
  lexlib;

type
  TLexer = class(TLexerParserBase)
  public
    function parse() : integer; override;
  end;

{$I exprlex.pas}

var
  Lexer : TLexer;

begin
  Lexer := TLexer.Create;
  try
    Lexer.parse();
  finally
    Lexer.Free;
  end;

  ReadLn;
end.
[/Code]

uses 절에 있는 유닛 중 dlib와 lexlib는 svn://trunk\Lib에 저장되어 있습니다.  변환기를 통해서 만들어진 exprlex.pas 파일은 16 라인에서처럼 Include 컴파일러 지시자를 통해서 사용합니다.  변환기를 통해서 만들어진 파일은 TLexer(TLexerParserBase)의 parse 메소드를 재정의하는 내용이 담겨져 있습니다.

이제 프로그램을 실행하시면, 콘솔창이 나타나며, [그림 2]와 같이 원하시는 표현식을 입력하고 엔터를 치시면, 각각의 토큰을 분석하여 의미를 찾아내어 표시하게 됩니다.

[그림 2] 프로그램 실행 결과

어때요 참 쉽죠 ㅡ.ㅡ;  다음에는 순수 코딩으로 스캐너를 만드는 방법을 설명하도록 하겠습니다.

위의 샘플에 대한 예제 소스는 "svn://trunk\Src\계산기용 스캐너"을 참고하시기 바랍니다.

'etc' 카테고리의 다른 글

기술에 대한 가치 평가  (1) 2010.11.08
계산기용 스캐너 만들기 - State Pattern  (1) 2010.11.04
계산기  (0) 2010.10.27
영풍문고의 서비스  (0) 2010.10.14
시스템 함수  (0) 2010.10.13

관련글 더보기