Regex для файла lex для соответствия инструкциям printf и scanf - PullRequest
0 голосов
/ 11 апреля 2020

Я пытаюсь создать компилятор, в котором файл lex соответствует следующим простым вариантам операторов printf и scanf:

printf("\n Enter your string:");
scanf("%s",str);
scanf("%d",&prelength);

В примерах scanf str объявлен как char str[20] и prelength as int prelength.

Регулярное выражение, которое я в настоящее время включаю в свой файл lex, следующее (соответственно для scanf и printf):

scanf\(\"([\w\W]*(%[d|c|f|lf|s])*)+\"(,\s*&?[a-zA-Z]+)*\); 
printf\(\"([\w\W]*(%[d|c|f|lf|s])*)+\"(,\s*[a-zA-Z]+)*\); 

Я не знаю, почему выше регулярные выражения не совпадают с приведенными выше примерами printf и scanf (аналогичные тем, которые можно найти в c, но проще).

1 Ответ

2 голосов
/ 11 апреля 2020

Ваши две scanf строки фактически совпадают. Строка printf не соответствует, потому что шаблон для строкового литерала не совпадает. Проблема в том, что lex не понимает \w или \W, поэтому [\w\W] соответствует только буквам w и W.

Если lex действительно поддерживает \w и \W, тогда [\w\W] будет соответствовать каждому символу, который является или не является "символом слова". Другими словами, это будет соответствовать всему. Это говорит нам о том, что вместо [\w\W] вы можете просто написать ., который поддерживается lex и соответствует всему. Он также говорит нам, что бит (%[d|c|f|lf|s])*)+ является избыточным, потому что все, что может быть сопоставлено этой частью, уже было бы сопоставлено частью .*. Следовательно, квалификатор + снаружи также является избыточным.

Таким образом, с учетом этого регулярное выражение для строковых литералов станет \".*\" (что не соответствует символам новой строки, но это нормально, потому что C не делает не разрешать неэкранированные символы новой строки в строковых литералах). Проблема в том, что это будет соответствовать всему от первого " на входе до last ", а не next ". Итак, вы хотите запретить " s появляться внутри строки. Тем не менее, " внутри строки допускается, если ее экранировать, предшествуя ей с обратной косой чертой sh (как и переводы строки). Итак, принимая во внимание все это, подходящее регулярное выражение для строковых литералов:

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