Если проблема настолько проста, как показывает ваш пример, вы можете просто использовать fscanf
. Проблема с fscanf
, вероятно, не будет отличаться от проблемы с использованием вашего гибкого сканера, который заключается в том, что новые строки просто обрабатываются как пробелы. Если ваш сканер возвращает специальный токен для новой строки (или вас убедили сделать это, см. Ниже), продолжайте читать.
Если я правильно понимаю, что вы хотите сделать, вам просто нужно правильно настроить ввод, а затем повторно вызывать yylex
. Если вы используете API без повторного входа по умолчанию, это может выглядеть примерно так:
// Returns a count, and sets the out parameter to a
// malloc'd array of malloc'd strings.
// The free function is left as an exercise.
int read_headers(char*** out) {
int count = 0;
char** id_array = NULL;
*out = id_array;
int token;
while ((token = yylex()) == TOKEN_IDENTIFIER) {
id_array = realloc(id_array, (count + 1) * sizeof *id_array);
if (id_array) *out = id_array;
else
// Handle error
id_array[count ++] = strdup(yytext);
}
if (token != '\n')
// Handle error
return count;
}
// Reads exactly n numbers and stores them in the out parameter,
// which must point at an array of size n.
// Returns: n on success. 0 if EOF reached. -1 on error
int read_n_numbers(double* out, int n) {
for (int i = 0; i < n; ++i, ++out) {
int token = yylex();
if (token != TOKEN_NUMBER) {
if (i == 0 && token == 0) return 0;
// Error: non-number or too few numbers
return -1;
}
*out = yylval.number;
}
if (yylex() != '\n') {
// Error: too many numbers
return -1;
}
return 0;
}
Вероятно, ваш сканер на самом деле не возвращает \n
для новой строки. Это редко бывает полезно в грамматике выражений (хотя иногда и бывает). Но легко модифицировать сканер для обработки новых строк по запросу; вам просто нужно использовать начальное условие. Мы делаем его включающим условием запуска, потому что оно должно обрабатывать только новые строки, но имейте в виду, что это означает, что все немаркированные правила также активны, поэтому вам нужно убедиться, что немаркированное правило, которое обрабатывает новые строки, также только обрабатывает одну новую строку.
%s RETURN_NEWLINES
%%
<RETURN_NEWLINES>\n { return '\n'; }
\n ; // Ignore a single newline
[ \t]+ ; // Ignore any number of horizontal whitespace
Имея это на месте, вы можете включить новые строки, просто вызвав BEGIN(RETURN_NEWLINES)
перед сканированием (и BEGIN(INITIAL)
, чтобы вернуться к их игнорированию). Вам нужно будет разместить функции, которые включают и отключают сканирование новой строки в вашем файле определения гибкости, потому что требуются макросы не экспортируются.
person
rici
schedule
28.07.2015