Как заставить Ragel выполнять разные действия для разбора

Я новичок в Ragel и пытаюсь разобрать определенный шаблон выражения Regex. Я хочу действия done выполняется, если совпадение найдено и parse_error выполняется, если не найдено ни одного совпадения даже для одного отсутствующего символа.

Вот код, который я написал:

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

%%{
action done {
printf("done\n");
}action parse_error {
printf("error : %c\n",fc);
}machine ldf;
main := (':'.'LoadSdf'.[0-9]+.[a-zA-Z0-9_\-\.])@done |    //execute done
(^(':'.'LoadSdf'.[0-9]+.[a-zA-Z0-9_\-\.])) $err(parse_error); //execute parse error for no match

}%%

%%write data;
int main(int argc, char** argv)
{
int cs;
if(argc > 1) {
char *p = argv[1];
char *pe = p+strlen(p) + 1;
%%write init;
%%write exec;
}
return 0;
}

Поведение, которое я вижу, состоит в том, что действия done а также parse_error оба выполняются, когда есть идеальное совпадение с выражением регулярного выражения.

Кто-нибудь может дать несколько советов, как мне справиться с этим делом?

0

Решение

Есть несколько проблем с этим кодом. Во-первых, техническая ошибка — у вас нет pe определение (оно включает нулевой символ и ваша машина не должна заботиться о нолях (конечно, вы можете заставить его обрабатывать их, но это просто усложняет вещи без причины)). Также полезно иметь eof определяется, потому что это должно быть ошибкой, когда у вас есть что-то вроде «: Load» во входных данных (пропуская «Sdf» и следующие фрагменты). Это исправлено

-char *pe = p+strlen(p) + 1;
+char *pe = p+strlen(p);
+char *eof = pe;

Другая проблема заключается в том, что нет необходимости совмещать какую-либо машину и ее негатив для контроля ошибок. Это разные действия. Посмотрите на изображение вашей машины:

Оригинальный конечный автомат

Вы можете видеть, что в середине просто нет правильной обработки ошибок здесь, и в конце концов вы можете иметь done() вызывается несколько раз, потому что указано, что это происходит при переходе в одно из конечных состояний. Вероятно, он должен быть запущен только при правильном завершении машины (то есть при достижении EOF в конечном состоянии).

Так что если вы хотите изменить определение вашей машины на

main := (':'.'LoadSdf'.[0-9]+.[a-zA-Z0-9_\-\.]) %/done $!(parse_error);

вы, вероятно, получите то, что вы хотите:

$ ./a.out "asdf"error : a
$ ./a.out "qwerty"error : q
$ ./a.out ":Load"error :
$ ./a.out ":LoadSdf"error :
$ ./a.out ":LoadSdf1212"done
$ ./a.out ":LoadSdf1q"done
$ ./a.out ":LoadSdf1qwe"error : w

Который выглядит так в графической форме:

Фиксированный конечный автомат

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]