Issue 49: Allow dots ('.') in string escapes for the sake of #line directives with Windows paths like "..\..\test"
+ added tests
diff --git a/_clean_tables.py b/_clean_tables.py
new file mode 100644
index 0000000..48417b0
--- /dev/null
+++ b/_clean_tables.py
@@ -0,0 +1,24 @@
+# Cleanup all table and PYC files to ensure no PLY stuff is cached

+#

+import fnmatch

+import os, shutil

+

+file_patterns = ('yacctab.*', 'lextab.*', '*.pyc')

+

+def do_cleanup(root):

+    for path, dirs, files in os.walk(root):

+        for file in files:

+            try:

+                for pattern in file_patterns:

+                    if fnmatch.fnmatch(file, pattern):

+                        fullpath = os.path.join(path, file)

+                        os.remove(fullpath)

+                        print 'Deleted', fullpath

+            except OSError:

+                pass

+

+if __name__ == "__main__":

+    do_cleanup('.')

+

+

+    
\ No newline at end of file
diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py
index 0fda764..235f8f0 100644
--- a/pycparser/c_lexer.py
+++ b/pycparser/c_lexer.py
@@ -179,13 +179,13 @@
     bad_octal_constant = '0[0-7]*[89]'
 
     # character constants (K&R2: A.2.5.2)
-    # Note: a-zA-Z are allowed as escape chars to support #line
-    # directives with Windows paths as filenames (\dir\file...)
+    # Note: a-zA-Z and '.' are allowed as escape chars to support #line
+    # directives with Windows paths as filenames (..\..\dir\file)
     #
-    simple_escape = r"""([a-zA-Z\\?'"])"""
+    simple_escape = r"""([a-zA-Z.\\?'"])"""
     octal_escape = r"""([0-7]{1,3})"""
     hex_escape = r"""(x[0-9a-fA-F]+)"""
-    bad_escape = r"""([\\][^a-zA-Z\\?'"x0-7])"""
+    bad_escape = r"""([\\][^a-zA-Z.\\?'"x0-7])"""
 
     escape_sequence = r"""(\\("""+simple_escape+'|'+octal_escape+'|'+hex_escape+'))'
     cconst_char = r"""([^'\\\n]|"""+escape_sequence+')'    
diff --git a/tests/test_c_lexer.py b/tests/test_c_lexer.py
index 5f3f83e..3851569 100644
--- a/tests/test_c_lexer.py
+++ b/tests/test_c_lexer.py
@@ -219,6 +219,10 @@
         dsf

         # 9 

         armo

+        #line 10 "..\..\test.h"

+        tok1

+        #line 99999 "include/me.h"

+        tok2

         """

         

         #~ self.clex.filename

@@ -243,6 +247,18 @@
         self.assertEqual(t.lineno, 9)

         self.assertEqual(self.clex.filename, r'kwas\df.h')

         

+        t4 = self.clex.token()

+        self.assertEqual(t4.type, 'ID')

+        self.assertEqual(t4.value, 'tok1')

+        self.assertEqual(t4.lineno, 10)

+        self.assertEqual(self.clex.filename, r'..\..\test.h')

+        

+        t5 = self.clex.token()

+        self.assertEqual(t5.type, 'ID')

+        self.assertEqual(t5.value, 'tok2')

+        self.assertEqual(t5.lineno, 99999)

+        self.assertEqual(self.clex.filename, r'include/me.h')

+        

 

 

 # Keeps all the errors the lexer spits in one place, to allow

diff --git a/z_test.py b/z_test.py
index 6f22260..7cad4ac 100644
--- a/z_test.py
+++ b/z_test.py
@@ -95,6 +95,9 @@
         #~ printme([tok.value, tok.type, tok.lineno, clex.filename, tok.lexpos])

 

     #--------------- Parsing

+    source_code = r'''#line 1 "..\..\test.h"

+    int a;

+    '''

     parser = CParser(lex_optimize=False, yacc_optimize=False, yacc_debug=True)

     ast = parser.parse(source_code, filename='zz')

     ast.show(showcoord=False)