2013-06-04 3 views
1

저는 Ragel에 약간의 문제가 있습니다. 대부분 모든 것이 어떻게 작동하는지 여전히 파악하고 있기 때문입니다.SQL과 유사한 문을 구문 분석하기위한 Ragel FSM

SQL (비슷하지만 유연하지 않음), 함수 (모두 대문자), 식별자 (모두 소문자) 및 함수 내에서 함수를 중첩 할 수있는 곳에서 간단한 구문 분석기를 만들려고합니다.

는 여기에 지금까지 무엇을 : 그것은, 캐릭터 당 한 번 function_call 조치를 호출

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 

typedef struct Parser { 
    int current_line; 
    int nesting; 

    /* Ragel FSM */ 
    int cs; 
    const char *ts; 
    const char *te; 
    int act; 
} Parser; 

%%{ 
    machine gql; 
    access parser->; 

    Function = [A-Z][A-Z_]+ ; 

    Identifier = [a-z][a-z_]+ ; 
    Integer  = [0-9]+ ; 

    Parameter = (Identifier | Integer)+ ; 

    WhiteSpace = [ \t\r\n] ; 

    action function_call { 
    parser->nesting++; 
    printf("FUNCTION CALL\n"); 
    } 

    action function_finish { 
    parser->nesting--; 
    printf("FUNCTION FINISH!\n"); 
    } 

    action function_add_identifier { 
    printf("FUNCTION ADD IDENTIFIER\n"); 
    } 

    FunctionCall = 
    Function @function_call WhiteSpace* "(" 
     Parameter %function_add_identifier 
     (WhiteSpace* ',' WhiteSpace* Parameter %function_add_identifier)* WhiteSpace* 
    %function_finish ')' ; 

    main := FunctionCall ; 
}%% 


%% write data; 

void Parser_Init(Parser *parser) { 
    parser->current_line = 1; 
    parser->nesting  = 0; 
    %% write init; 
} 

void Parser_Execute(Parser *parser, const char *buffer, size_t len) { 
    if(len == 0) return; 

    const char *p, *pe, *eof; 
    p = buffer; 
    pe = buffer+len; 
    eof = pe; 

    %% write exec; 
} 

int main(int argc, char *argv[]) { 
    Parser *parser = malloc(sizeof(Parser)); 
    Parser_Init(parser); 

    printf("Parsing:\n%s\n\n\n", argv[1]); 

    Parser_Execute(parser, argv[1], sizeof(argv[1])); 

    printf("Parsed %d lines\n", parser->current_line); 
    return 0; 
} 

Parameter들 따기하지, 나는 기능은 내부 기능을 작동하게하는 방법을 생각할 수 없다.

여기에 내가 뭘 잘못하고 있는지에 대한 도움말이 있습니까?

답변

4

표준 접근법은 언어 입력을 토큰 화하는 렉서 (Ragel 또는 GNU Flex로 작성)를 만드는 것입니다. 그런 다음 토큰은 GNU Bison과 같은 파서 생성기를 사용하여 재귀 구조 (예 : 중첩 함수)를 구문 분석 할 수있는 파서 (Ragel로 작성되지 않음)에서 소비됩니다.

Ragel은 (재귀 구조를 구문 분석 할 수있게 해주는) 스택을 관리하기위한 (고급 기능으로) 지시어를 포함하고 있지만, 그렇지 않으면 ragel 사양으로 작업하는 일반 언어의 도메인을 남겨 두는 점에 유의하십시오. 따라서 중첩 된 함수를 Ragel과 완전히 파싱 할 수있는 파서를 작성할 수 있습니다. 그러나 올바르게 계층화 된 아키텍처 (1 층 : 렉서, 2 계층 : 파서 ​​등)는 작업을 단순화합니다. 즉, 디버깅, 테스트 및 유지 관리가 더 쉽습니다.

관련 문제