diff --git a/README.md b/README.md index 8d2408f..66cfe28 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,7 @@ twine upload dist/* | Ruby | text/x-ruby | | Shell | text/x-shellscript | | XML | text/xml | +| PHP | text/x-php | And more to come! diff --git a/comment_parser/comment_parser.py b/comment_parser/comment_parser.py index 04d5ba6..d8564db 100755 --- a/comment_parser/comment_parser.py +++ b/comment_parser/comment_parser.py @@ -11,6 +11,7 @@ Javascript Ruby XML + PHP Dependencies: python-magic: pip install python-magic (optional) @@ -32,6 +33,7 @@ from comment_parser.parsers import python_parser from comment_parser.parsers import ruby_parser from comment_parser.parsers import shell_parser +from comment_parser.parsers import php_parser MIME_MAP = { 'application/javascript': js_parser, # Javascript @@ -46,6 +48,7 @@ 'text/x-ruby': ruby_parser, # Ruby 'text/x-shellscript': shell_parser, # Unix shell 'text/xml': html_parser, # XML + 'text/x-php': php_parser, # PHP } diff --git a/comment_parser/parsers/php_parser.py b/comment_parser/parsers/php_parser.py new file mode 100644 index 0000000..3d93bad --- /dev/null +++ b/comment_parser/parsers/php_parser.py @@ -0,0 +1,72 @@ +#!/usr/bin/python +"""This module provides methods for parsing comments from PHP. + +Works with: + PHP +""" + +import re +from bisect import bisect_left +from comment_parser.parsers import common + + +def extract_comments(code): + """Extracts a list of comments from the given PHP source code. + + Comments are represented with the Comment class found in the common module. + PHP comments come in two forms, single and multi-line comments. + - Single-line comments begin with '//' or '#' and continue to the end of line. + - Multi-line comments begin with '/*' and end with '*/' and can span + multiple lines of code. If a multi-line comment does not terminate + before EOF is reached, then an exception is raised. + + Note that this doesn't take language-specific preprocessor directives into + consideration. + + Args: + code: String containing code to extract comments from. + Returns: + Python list of common.Comment in the order that they appear in the code. + Raises: + common.UnterminatedCommentError: Encountered an unterminated multi-line + comment. + """ + pattern = r""" + (?P (?:([\"'])((?:\\\2|(?:(?!\2)).|\n)*)(\2))|\?>((?!<\?php\s).|\n)*<\?php\s|<<<('?)(([a-zA-Z0-9_]|[^\x00-\x7F])([a-zA-Z0-9_]|[^\x00-\x7F])*)\6((?!^\7;?$)(.|\n))*^\7;?$) | + (?P (?://|\#)(?P.*)?$) | + (?P /\*(?P(.|\n)*?)?\*/) | + (?P /\*(.*)?) + """ + + compiled = re.compile(pattern, re.VERBOSE | re.MULTILINE) + # The regex recognizes stuff between ?> and \n" + code + "\n + /* Wouldn't be a commend if commented php end tag was misinterpreted */''' + comments = php_parser.extract_comments(code) + expected = [ + common.Comment(' ?>', 2, multiline=False), + common.Comment( + " Wouldn't be a commend if commented php end tag was misinterpreted ", + 3, + multiline=True) + ] + self.assertEqual(comments, expected) + + def testCommentsOutsidePhpTag(self): + code = ''' + // This is no comment + + + \nAä_0;\n +