Как я могу использовать lex для идентификации строк, отличных от кавычек? - PullRequest
1 голос
/ 21 мая 2019

Настоящий лекс новобранец. Я пытаюсь использовать регулярное выражение, чтобы идентифицировать строки в printf(), например, printf("hello world!");, но лучший результат - просто "Привет, мир!" и я не хочу двойных кавычек, просто привет мир! Как мне быть?

Регулярное выражение до сих пор: ("\"")(.)*("\"")

1 Ответ

1 голос
/ 21 мая 2019

Хорошее регулярное выражение для соответствия строковым литералам:

["]([^"]|\\(.|\n))*["]
["]([^"\n]|\\(.|\n))*["]

Первое не выполняется на многострочных строках;второй принимает их.В обоих случаях непревзойденные кавычки не будут совпадать, так что вам придется иметь дело с этими ошибочными входными данными с помощью другого шаблона.Оба шаблона допускают экранирование обратной косой черты (включая переводы обратной косой черты), не пытаясь их интерпретировать.Большинство реальных лексических сканеров захотят обрабатывать escape-последовательности обратной косой черты, часто превращая их в символы, которые они представляют.Но для этого нужен другой механизм, который выходит за рамки этого вопроса.

Как вы обнаружили, совпадение включает в себя кавычки, поэтому вы захотите удалить их.Поскольку обычно вы должны сделать копию сопоставленного токена (поскольку содержимое yytext будет перезаписано при следующем вызове сканера), это можно легко сделать, просто скопировав интересующую вас часть совпадения.

Помните, что yyleng - это длина токена.Следовательно, подстрока, которую вы хотите, начинается с yytext + 1 (чтобы пропустить открывающую кавычку) и продолжается для yyleng - 2 символов (не включая ни одну кавычку):

["]([^"]|\\(.|\n))*["]  {
          yylval.str = malloc(yyleng -1);
          memcpy(yylval.str, yytext + 1, yyleng - 2);
          yylval.str[yyleng - 2] = 0;
        }

Есть другие способы записать это,конечно, но все они будут похожи.

...