- 참조

- http://www.colm.net/open-source/ragel/

- http://www.colm.net/wp-content/uploads/2014/10/ragel-guide-6.9.pdf


- Ragel 사용이 더 좋은 작업

- 문자열 파싱

- 프로그래밍 언어 분석(컴파일러 제작)

- 사용자 입력 검증


- 지원 언어

- C, C++, Obj-C, C#, D, Java, Go, Ruby


- 코드

- Ragel은 유한상태머신(Finite State Machine, FSM)을 구현

- 여러줄 인 경우 "%%{"와 "}%%"로 감싸고, 한줄 인 경우 라인의 앞에 "%%"를 입력한다.

- C언어처럼 한 줄의 마지막에 ";"을 입력한다.

예)

%%{

machine atoi;

...

%%}

%%write init;


- 코드 삽입

- FSM의 이름 삽입

%% machine {FSM 이름};


- Ragel 코드 시작은 main이다.

- ":=" 연산자는 R-Value의 표현식을 나타내는 상태 셋을 생성한다.

%% main := {수식};


- 수식

- 사용자 정의 된 이름 혹은 미리 정의된 이름, 사용자 정의 Action이 올 수 있다.

- Action은 사용자 입력이 수식과 매칭되는 경우 실행할 코드를 넣는 일종의 함수로 각 언어별 실행 코드를 넣는다.

%% action on_word {printf("%n\n", n);}

- 사용자 정의 수식을 정의하려면 "=" 을 사용한다.

%% word = ^space+;


- FSM 초기화 및 시작

- FSM 에서 필요한 상수 선언

%% write data;

- FSM 데이터 초기화

%% write init;

- FSM 실행

- 실제 FSM이 실행 될 위치에 다음과 같이 삽입한다.

%% write exec;


- Action 종류

- Action은 연산자에 따라서 실행하는 방법이 달라진다.

- {수식} > {Action}: Entering Action(FSM state: from the start state)

- 수식에 진입하는 시점에서 Action이 실행된다.

- 예를들어, 문자열을 파싱할 때, 처음 한번만 실행하는 경우

%% action onStart {puts("Start Parsing");}

%% main := alpha+ > onStart;

- {수식} @ {Action}: Finishing Action(FSM state: into a final state)

- 수식의 마지막에 Action이 실행된다.

- 다음은 a-z까지의 소문자가 하나 있을때마다 lower Action이 실행된다.

%% word = ([a-z] @lower)+;

- 다음은 a-z까지의 소문자가 아닌 경우 notLower Action이 실행된다.

%% word = [a-z]+ @notLower;

- {수식} $ {Action}: All Transition Action(FSM state: all state for matched)

- 수식과 매칭될 때마다 Action이 실행된다.

- 다음은 a-z까지의 소문자가 하나 있을때마다 lower Action이 실행된다. (Finishing Action 예제의 변형)

%% word = [a-z]+ $lower;

- {수식} % {Action}: Leaving Action(FSM state: go out of a machine via a final state)

- 수식을 벗어날 때 실행된다.

- 다음은 a-z까지의 소문자가 아닌 경우 lastLower Action이 실행 된 후 notLower Action 실행된다.

%% word = [a-z]+ %lastLower @notLower;

- Action의 순서

>(Entering) $(All) %(Leaving) @(Finishing)


- 주요 연산자

- {수식}+: 1개 이상

- {수식}*: 0개 이상

- {수식}?: 0개 혹은 1개

- ^{수식}: 수식의 반대, ^space 는 공백문자가 아닌 모든 문자를 뜻함.

- ({수식}): 그룹핑, 여러 수식을 하나의 수식으로 처리

- {수식1}|{수식2}: or 연산, 수식1 혹은 수식2와 매칭


- cs(Current State): FSM 상태를 나타내는 변수, 에러, 성공등의 값이 저장.


- 스캐너
- 상태 셋을 생성하는 ":=" 연산자를 사용하여 정의한다.
- 여러가지 패턴 목록을 정의한 후 각 패턴마다 action을 실행할 수 있다.
- main을 정의할 때 스캐너로 정의할 수 있으며, 별도로 정의한 경우 "@{fcall" {스캐너이름}"}" 형태로 실행한다.
- 기본 구조는 다음처럼 스캐너 이름을 정의하고 "|*" 와 "*|" 사이에 패턴과, 패턴 매칭시 실행 될 Action을 정의한다.
- Action을 정의할 때 "=>" 연산자는 생략가능하다.
{스캐너 이름} := |*
{패턴} [{[=>] Action}];
...
*|
- 다음은 영문자와 숫자가 합쳐져 있는 문자열에서 숫자를 검색하는 스캐너이다.
digit_scan := |*
alpha+;
digit+ {puts("digit!");};
*|
- 스캐너는 매칭된 문자열의 시작과 종료를 ts(token start), te(token end)에 저장한다.
- 매칭되기 전의 ts와 te는 같은 값을 가지며, 하나의 패턴이 매칭되면 그 다음 위치를 저장한다.
- 예를들어 90번지에서 100번지까지 패턴이 매칭되었으면 그 다음 패턴 검색시 ts, te의 값은 101이다.
digit_scan := |* ...
digit+ => {char buf[12]; memcpy(buf, ts, te - ts); puts(buf);};
*|


+ Recent posts