From 0a3f0d7dadd2a5469ea1bdd535ef73504d749736 Mon Sep 17 00:00:00 2001 From: Till Varoquaux Date: Tue, 2 Jul 2013 17:18:13 -0400 Subject: [PATCH] Adjust yylineno properly when rewinding trailing contexts. --- configure.ac | 1 + flex.skl | 8 +++ nfa.c | 11 ++++ tests/Makefile.am | 2 + tests/test-lineno-trailing/.gitignore | 8 +++ tests/test-lineno-trailing/Makefile.am | 45 +++++++++++++ tests/test-lineno-trailing/scanner.l | 87 ++++++++++++++++++++++++++ tests/test-lineno-trailing/test.input | 13 ++++ 8 files changed, 175 insertions(+) create mode 100644 tests/test-lineno-trailing/.gitignore create mode 100644 tests/test-lineno-trailing/Makefile.am create mode 100644 tests/test-lineno-trailing/scanner.l create mode 100644 tests/test-lineno-trailing/test.input diff --git a/configure.ac b/configure.ac index f0a4fda..e82f72f 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,7 @@ tests/test-string-r/Makefile tests/test-yyextra/Makefile tests/test-alloc-extra/Makefile tests/test-lineno-nr/Makefile +tests/test-lineno-trailing/Makefile tests/test-lineno-r/Makefile tests/test-linedir-r/Makefile tests/test-debug-r/Makefile diff --git a/flex.skl b/flex.skl index aebf2ae..f878ff0 100644 --- a/flex.skl +++ b/flex.skl @@ -503,9 +503,17 @@ m4_ifdef( [[M4_YY_NOT_IN_HEADER]], if ( yytext[yyl] == '\n' )\ --yylineno;\ }while(0) + #define YY_LINENO_REWIND_TO(dst) \ + do {\ + const char *p;\ + for ( p = yy_cp-1; p >= (dst); --p)\ + if ( *p == '\n' )\ + --yylineno;\ + }while(0) ]], [[ #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) ]]) ]]) diff --git a/nfa.c b/nfa.c index dbd1557..26b162c 100644 --- a/nfa.c +++ b/nfa.c @@ -257,12 +257,23 @@ void finish_rule (mach, variable_trail_rule, headcnt, trailcnt, ("*yy_cp = YY_G(yy_hold_char); /* undo effects of setting up yytext */\n"); if (headcnt > 0) { + if (rule_has_nl[num_rules]) { + snprintf (action_text, sizeof(action_text), + "YY_LINENO_REWIND_TO(%s + %d);\n", scanner_bp, headcnt); + add_action (action_text); + } snprintf (action_text, sizeof(action_text), "%s = %s + %d;\n", scanner_cp, scanner_bp, headcnt); add_action (action_text); } else { + if (rule_has_nl[num_rules]) { + snprintf (action_text, sizeof(action_text), + "YY_LINENO_REWIND_TO(yy_cp - %d);\n", trailcnt); + add_action (action_text); + } + snprintf (action_text, sizeof(action_text), "%s -= %d;\n", scanner_cp, trailcnt); add_action (action_text); diff --git a/tests/Makefile.am b/tests/Makefile.am index 33c20bd..25d8b0c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -53,6 +53,7 @@ DIST_SUBDIRS = \ test-debug-r \ test-lineno-r \ test-lineno-nr \ + test-lineno-trailing \ test-linedir-r \ TEMPLATE \ test-top \ @@ -102,6 +103,7 @@ SUBDIRS = \ test-debug-r \ test-lineno-r \ test-lineno-nr \ + test-lineno-trailing \ test-linedir-r \ test-array-nr \ test-array-r \ diff --git a/tests/test-lineno-trailing/.gitignore b/tests/test-lineno-trailing/.gitignore new file mode 100644 index 0000000..84b3fa9 --- /dev/null +++ b/tests/test-lineno-trailing/.gitignore @@ -0,0 +1,8 @@ +Makefile +Makefile.in +parser.c +parser.h +scanner.c +test-lineno-trailing +OUTPUT +.deps diff --git a/tests/test-lineno-trailing/Makefile.am b/tests/test-lineno-trailing/Makefile.am new file mode 100644 index 0000000..bb303c3 --- /dev/null +++ b/tests/test-lineno-trailing/Makefile.am @@ -0,0 +1,45 @@ +# This file is part of flex. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: + +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. + +# Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. + +# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE. + + +FLEX = $(top_builddir)/flex + +EXTRA_DIST = scanner.l test.input +CLEANFILES = scanner.c $(testname)$(EXEEXT) OUTPUT $(OBJS) +OBJS = scanner.o + +AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir) -I$(top_builddir) + +testname = test-lineno-trailing + +scanner.c: $(srcdir)/scanner.l + $(FLEX) $(LFLAGS) $< + + +$(testname)$(EXEEXT): $(OBJS) + $(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(OBJS) $(LOADLIBES) + +test: $(testname)$(EXEEXT) + test `./$(testname)$(EXEEXT) < $(srcdir)/test.input` -eq \ + `./$(testname)$(EXEEXT) 1 < $(srcdir)/test.input` || exit 1 + +.c.o: + $(CC) -c -o $@ $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $< diff --git a/tests/test-lineno-trailing/scanner.l b/tests/test-lineno-trailing/scanner.l new file mode 100644 index 0000000..20d3c8a --- /dev/null +++ b/tests/test-lineno-trailing/scanner.l @@ -0,0 +1,87 @@ +/* + * This file is part of flex. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +%{ +/* A template scanner file to build "scanner.c". + Run as: + test-lineno-trailing # report flex's yylineno + test-lineno-trailing 1 # report count_newlines(stdin) +*/ + +#include +#include +#include "config.h" + +%} + +%option 8bit outfile="scanner.c" prefix="test" +%option nounput nomain noyywrap yylineno +%option warn + +WORD [[:alpha:]]+ + +%% + /* The goal here is to test the yylineno in the context of trailing-contexts. + Using rules that have newlines in look-ahead. + */ +"Fixed_trailing:"/[\n]"test"[\n] {} +"Var_trailing:"{WORD}/[\n] {} +"Var_prefix_and_trailing:"{WORD}":"/(\n{WORD})* {} +\n {} +. {} +<> { printf("%d\n", yylineno); + yyterminate(); + } + +%% + +/* returns number of '\n' characters in input, plus one. + This is what flex does, essentially. */ + +static int +count_newlines (FILE* in) +{ + int n=1,c; + while ((c=fgetc(in)) != EOF) + if( c == '\n') + n++; + return n; +} + +int main ( int, char**); + +int +main ( argc, argv ) + int argc; + char** argv; +{ + if( argc > 1 ) + printf("%d\n", count_newlines(stdin)); + + else{ + yyin = stdin; + yyout = stdout; + yylex(); + } + return 0; +} diff --git a/tests/test-lineno-trailing/test.input b/tests/test-lineno-trailing/test.input new file mode 100644 index 0000000..201164d --- /dev/null +++ b/tests/test-lineno-trailing/test.input @@ -0,0 +1,13 @@ +We are testing rules with trailing contexts containing newlines (see scanner.l): + +Fixed_trailing: +test + +Var_trailing:word +test + +Var_prefix_and_trailing:word: +more +text +comes +here -- 2.40.0