Я бы посоветовал вам добавить
%option yylineno
в ваш файл Flex, а затем использовать переменную yylineno
вместо того, чтобы пытаться самостоятельно подсчитывать переводы строки. Flex получает правильное значение и обычно умудряется оптимизировать вычисления.
Тем не менее, \"([^"])*\"
не является оптимальным способом чтения строковых литералов, потому что он заканчивается в первой кавычке. Это приведет к катастрофическим сбоям, если строковый литерал будет "\"Bother,\" he said. \"It's too short.\""
Вот лучший вариант:
\"(\\(.|\n)|[^\\"\n])*\"
(Это не будет соответствовать строковым литералам, которые содержат символы новой строки без экранирования; в C ++ это не законно. Но вам нужно будет добавить другое правило, чтобы оно соответствовало ошибочной строке и выдало соответствующее сообщение об ошибке.)
Я полагаю, возможно, что вы должны соответствовать искусственным требованиям курса разработан кем-то, кто не знает о функции yylineno
. В этом случае простое решение добавления line_number = yylineno;
в начале каждого правила, вероятно, будет считаться обманом.
Что вам нужно будет сделать, это то, что делает сам Flex (но он не делает ошибок, и мы, программисты, делаем): выясним, какие правила могут соответствовать тексту, включая одну или несколько строк новой строки, и вставьте код в эти конкретные c правила для подсчета совпадений новой строки. Как правило, речь идет о многострочных комментариях и самих строковых литералах (поскольку строковый литерал может включать в себя обратную строку sh продолжение строки.)
Один из способов выяснить, какие правила могут соответствовать символам новой строки, состоит в включите функцию yylineno
, а затем изучите код, сгенерированный flex. Найдите YY_RULE_SETUP
в этом файле; обработчик для каждого правила синтаксического анализатора (включая те, чье действие ничего не делает) начинается с этого вызова макроса. Если вы включили %option yylineno
, flex определяет, какие правила могут соответствовать символу новой строки, и вставляет код перед YY_RULE_SETUP
, чтобы исправить yylineno
. Эти правила начинаются с комментария /* rule N can match eol */
, где N
- индекс правила. Вам нужно будет посчитать правила в исходном файле, чтобы они соответствовали N
номеру строки. Или вы можете посмотреть директиву #line
в сгенерированном коде.