用于解析类sql语句的Ragel FSM



我在使用Ragel时遇到了一些问题,主要是由于我仍然试图掌握整个事情是如何工作的。

我正试图为一种类似于SQL(但不太灵活)的语言做一个简单的解析器,在那里你有函数(全部大写),标识符(全部小写),你可以在函数内嵌套函数。

到目前为止我写的是:

#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  = [ trn] ;
  action function_call {
    parser->nesting++;
    printf("FUNCTION CALLn");
  }
  action function_finish {
    parser->nesting--;
    printf("FUNCTION FINISH!n");
  }
  action function_add_identifier {
    printf("FUNCTION ADD IDENTIFIERn");
  }
  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%snnn", argv[1]);
  Parser_Execute(parser, argv[1], sizeof(argv[1]));
  printf("Parsed %d linesn", parser->current_line);
  return 0;
}

每个字符调用一次function_call动作,而不是拾取Parameter s,我无法想象如何使函数在函数内工作。

我哪里做错了,有什么建议吗?

标准方法是创建一个词法分析器(用Ragel或GNU Flex编写),它只对语言输入进行标记。然后,这些令牌被解析器(不是用Ragel编写的)使用,该解析器能够解析递归结构(例如嵌套函数)-使用像GNU Bison这样的解析器生成器。

请注意,Ragel包含(作为高级功能)管理堆栈的指令(它使您能够解析递归结构)-但是这样您就离开了常规语言的领域,否则您将在Ragel规范中使用。因此,您可以编写一个能够使用Ragel完全解析嵌套函数的解析器。但是一个适当的分层架构(第一层:词法分析器,第二层:解析器,…)简化了任务,即各部分更容易调试,测试和维护。

最新更新