(F) lex всегда соответствует максимально возможному токену. Так как .*
будет соответствовать любой последовательности, не содержащей символа новой строки, он будет с удовольствием соответствовать 12sdaesre34
. (В (f) lex, .
соответствует любому символу, отличному от новой строки.) Таким образом, 34
больше не может быть сопоставлен.
Чтобы исправить это, вы должны быть в курсе, что вы хотите content
для соответствия. Например, следующий будет соответствовать все, что не содержит цифры:
[^[:digit:]]+ { printf("content\n"); }
Вы могли бы хотеть, чтобы добавить новую строку в списке символов не совпадают:
[^\n[:digit:]]+ { printf("content\n"); }
Или, возможно, вы хотите соответствуют самой длинной последовательности, не содержащей 34
. Это сложнее, но это может быть сделано:
([^3]|3+[^34])+ { printf("content\n"); }
Однако, это все равно будет соответствовать первоначальному 12
, поэтому он не будет достаточно, чтобы решить эту проблему.
Если ваш вход всегда состоит из строк 12...34
, которые могут быть перемешаны с другим содержимым, вы можете сопоставить всю последовательность 12...34
и разделить ее на три маркера. Это, несомненно, самое простое решение, поскольку маркеры начала и конца имеют известную длину. Первый из следующих шаблонов соответствует строке, которая не запускается 12
, заканчивающаяся непосредственно перед первым экземпляром 12
, а вторая соответствует строке, начинающейся 12
, и заканчивается в первом экземпляре 34
(что соответствует). Ни один из шаблонов не будет соответствовать входу, который содержит непревзойденный 12
; поэтому добавляется третье правило для соответствия этому случаю; он очень похож на второе правило, но не включает в себя матч для 34
в конце. Поскольку (f) lex всегда совпадает с самым длинным возможным токеном, третье правило будет успешным только в случае неудачи второго правила.
([^1]|1+[^12])* { puts("content"); }
12([^3]|3+[^34])*34 { puts("head content tail"); }
12([^3]|3+[^34])* { puts("error"); }
Обычно, вы хотели бы, чтобы фактически захватить значение content
, чтобы перейти к вызывающей программе. В первом правиле это всего лишь yytext
, но во втором правиле содержание состоит из yyleng-4
символов, начинающихся с yytext+2
(чтобы удалить лидирующие и конечные разделители).
Для большинства целей необходимо скопировать согласованный токен, если вам нужно его сохранить, потому что yytext
указывает на внутреннюю структуру данных, используемую лексическим сканером, и указатель будет недействителен следующим сопоставлением шаблонов. В случае первого правила, вы можете создать копию строки, используя strcpy
, но для второго правила, вы хотите, чтобы сделать копию самостоятельно:
([^1]|1+[^12])* { yylval = strcpy(yytext); ... }
12([^3]|3+[^34])*34 { yylval = malloc(yyleng-3);
memcpy(yylval, yytext, yyleng-4);
yylval[yyleng-4] = '\0';
...
}
Те предполагают, что yylval
является глобальным переменным типа char*
, и что где-то в коде вы free()
строка, сохраненная правилом. Они также предполагают, что вы делаете что-то с yylval
в пропущенном коде (...
), или что вы возвращаетесь к вызывающей стороне с указанием о том, встречались ли голова и хвост.
Спасибо, но все же ответ не совсем правильный, я пробовал правило ([^ 3] | 3 + [^ 34]) + {printf ("content \ n"); } Теперь результат все равно не я wated: \t $ эха 12dsfadsf34 | a.out \t содержания \t хвоста \t содержания –
@HindForsum: Да, вы совершенно правы. Я добавил несколько предложений относительно того, как вы можете продолжить, но, очевидно, это всего лишь грубая схема, потому что я действительно не знаю ваших требований. Обычно я предполагаю, что вы знакомы с строковой обработкой в C. – rici