]> Savannah Git Hosting - gnulib.git/commitdiff
dfa: new options DFA_STAR_WARN, DFA_PLUS_WARN
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 24 May 2022 23:03:29 +0000 (16:03 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 24 May 2022 23:04:04 +0000 (16:04 -0700)
This lets ‘grep -E '(*a|+b)'’ warn about the * and the +.
* lib/dfa.h (DFA_STAR_WARN, DFA_PLUS_WARN): New flags.
* lib/dfa.c (lex): Support them.

ChangeLog
lib/dfa.c
lib/dfa.h

index 088e3b3134d0f41c0676299ffcb1f09aaa3144fa..5b20aa58e75a7ef12c81125b6e4e7da9bfbc8469 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2022-05-24  Paul Eggert  <eggert@cs.ucla.edu>
+
+       dfa: new options DFA_STAR_WARN, DFA_PLUS_WARN
+       This lets ‘grep -E '(*a|+b)'’ warn about the * and the +.
+       * lib/dfa.h (DFA_STAR_WARN, DFA_PLUS_WARN): New flags.
+       * lib/dfa.c (lex): Support them.
+
 2022-05-23  Paul Eggert  <eggert@cs.ucla.edu>
 
        dfa: '\n' is not governed by RE_LIMITED_OPS
index 5d92b38b4cae4194e88bf6dc4d88e0eb83ae2ad8..bd4c5f05825b1c975bf87237040d9aed71a69b3b 100644 (file)
--- a/lib/dfa.c
+++ b/lib/dfa.c
@@ -1311,17 +1311,25 @@ lex (struct dfa *dfa)
             goto default_case;
           if (backslash != ((dfa->syntax.syntax_bits & RE_BK_PLUS_QM) != 0))
             goto normal_char;
-          if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS)
-              && dfa->lex.laststart)
-            goto normal_char;
+          if (dfa->lex.laststart)
+            {
+              if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS))
+                goto default_case;
+              if (dfa->syntax.dfaopts & DFA_PLUS_WARN)
+                dfawarn (_("? at start of expression"));
+            }
           return dfa->lex.lasttok = QMARK;
 
         case '*':
           if (backslash)
             goto normal_char;
-          if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS)
-              && dfa->lex.laststart)
-            goto normal_char;
+          if (dfa->lex.laststart)
+            {
+              if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS))
+                goto default_case;
+              if (dfa->syntax.dfaopts & DFA_STAR_WARN)
+                dfawarn (_("* at start of expression"));
+            }
           return dfa->lex.lasttok = STAR;
 
         case '+':
@@ -1329,9 +1337,13 @@ lex (struct dfa *dfa)
             goto default_case;
           if (backslash != ((dfa->syntax.syntax_bits & RE_BK_PLUS_QM) != 0))
             goto normal_char;
-          if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS)
-              && dfa->lex.laststart)
-            goto normal_char;
+          if (dfa->lex.laststart)
+            {
+              if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS))
+                goto default_case;
+              if (dfa->syntax.dfaopts & DFA_PLUS_WARN)
+                dfawarn (_("+ at start of expression"));
+            }
           return dfa->lex.lasttok = PLUS;
 
         case '{':
@@ -1339,9 +1351,6 @@ lex (struct dfa *dfa)
             goto default_case;
           if (backslash != ((dfa->syntax.syntax_bits & RE_NO_BK_BRACES) == 0))
             goto normal_char;
-          if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS)
-              && dfa->lex.laststart)
-            goto normal_char;
 
           /* Cases:
              {M} - exact count
@@ -1374,16 +1383,24 @@ lex (struct dfa *dfa)
                                   dfa->lex.maxrep * 10 + *p - '0'));
                   }
               }
-            if (! ((! backslash || (p != lim && *p++ == '\\'))
+            bool invalid_content
+              = ! ((! backslash || (p != lim && *p++ == '\\'))
                    && p != lim && *p++ == '}'
                    && 0 <= dfa->lex.minrep
                    && (dfa->lex.maxrep < 0
-                       || dfa->lex.minrep <= dfa->lex.maxrep)))
+                       || dfa->lex.minrep <= dfa->lex.maxrep));
+            if (invalid_content
+                && (dfa->syntax.syntax_bits & RE_INVALID_INTERVAL_ORD))
+              goto normal_char;
+            if (dfa->lex.laststart)
               {
-                if (dfa->syntax.syntax_bits & RE_INVALID_INTERVAL_ORD)
-                  goto normal_char;
-                dfaerror (_("invalid content of \\{\\}"));
+                if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS))
+                  goto default_case;
+                if (dfa->syntax.dfaopts & DFA_PLUS_WARN)
+                  dfawarn (_("{...} at start of expression"));
               }
+            if (invalid_content)
+              dfaerror (_("invalid content of \\{\\}"));
             if (RE_DUP_MAX < dfa->lex.maxrep)
               dfaerror (_("regular expression too big"));
             dfa->lex.ptr = p;
index 8674929e90f5731c34f186129ab039b5467f8db1..91ec1d809fcca70d77a2a591528f90ada2344c77 100644 (file)
--- a/lib/dfa.h
+++ b/lib/dfa.h
@@ -81,6 +81,14 @@ enum
 
     /* Warn about stray backslashes before ordinary characters.  */
     DFA_STRAY_BACKSLASH_WARN = 1 << 3,
+
+    /* Warn about * appearing out of context at the start of an
+       expression or subexpression.  */
+    DFA_STAR_WARN = 1 << 4,
+
+    /* Warn about +, ?, {...} appearing out of context at the start of
+       an expression or subexpression.  */
+    DFA_PLUS_WARN = 1 << 5,
   };
 
 /* Initialize or reinitialize a DFA.  The arguments are: