无法将URL解析器正则表达式转换为Ragel

时间:2012-01-09 07:01:08

标签: regex uri ragel

我在RFC 2396和RFC 3986上找到了一个URL解析器正则表达式。

^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?

我将它转换为Ragel:

%%{    
  # RFC 3986 URI Generic Syntax (January 2005)
  machine url_parser;

  action pchar     {
    printf("%c", fc);
  }
  action scheme            { printf("scheme\n"); }
  action scheme_end        { printf("\nscheme_end\n"); }
  action authority         { printf("authority\n"); }
  action authority_end     { printf("\nauthority_end\n"); }
  action path              { printf("path\n"); }
  action path_end          { printf("\npath_end\n"); }
  action query             { printf("query\n"); }
  action query_end         { printf("\nquery_end\n"); }
  action fragment          { printf("fragment\n"); }
  action fragment_end      { printf("\nfragment_end\n"); }

  scheme    = (any - [:/?#])+ >scheme    $pchar %scheme_end ;
  authority = (any - [/?#])*  >authority $pchar %authority_end ;
  path      = (any - [?#])*   >path      $pchar %path_end ;
  query     = (any - [#])*    >query     $pchar %query_end ;
  fragment  = (any)*          >fragment  $pchar %fragment_end ; 
  main     := (( scheme ":" )?) <: (( "//" authority )?) <: path ( "?" query )? ( "#" fragment )?;
}%%

#include <cstdio>
#include <cstdlib>
#include <string>

/** Data **/
%% write data;

int main(int argc, char **argv) {
  std::string str(argv[1]);
  char const* p = str.c_str();
  char const* pe = p + str.size();
  char const* eof = pe;
  int cs = 0;

  %% write init;
  %% write exec;

  return p - str.c_str();
}

输入绝对URI时它起作用。

liangxu@dev64:~$ ./uri_test "http://www.ics.uci.edu/pub/ietf/uri/?c=www&rot=1&e=%20%20"
scheme
http
scheme_end
authority
www.ics.uci.edu
authority_end
path
/pub/ietf/uri/
path_end
query
c=www&rot=1&e=%20%20
query_end

当我输入权限和路径时成功:

liangxu@dev64:~$ ./uri_test "//www.ics.uci.edu/pub/ietf/uri/?c=www&rot=1&e=%20%20"
authority
www.ics.uci.edu
authority_end
path
/pub/ietf/uri/
path_end
query
c=www&rot=1&e=%20%20
query_end

但是当我只输入路径时失败了:

liangxu@dev64:~$ ./uri_test "/pub/ietf/uri"

出了什么问题?

2 个答案:

答案 0 :(得分:0)

你使用了错误的监护人<:,一旦权限部分看到你的第一个/,控制权就会被授予权限部分。

如果您看到<:的别名

,则表明这一点
expr $(unique_name,1) . expr >(unique_name,0)

这意味着,在左边的expr上匹配的每个过渡状态下,它将保持HIGHER优先级,避免正确表达。

如果你将ABNF符号转换为ragel,那就容易多了。

答案 1 :(得分:0)

我最近自己做了同样的事情,你可以看看我的ragel语法https://github.com/maximecaron/ragel-url-parser