35 """C99 Preprocessor Syntax Rules. 67 def match_cpp_directive(reader):
68 """Creates single-line C99 preprocessor directive object from the 69 current line, if any is found. 71 :param reader: the fortran file reader containing the line \ 72 of code that we are trying to match. 73 :type reader: :py:class:`fparser.common.readfortran.FortranFileReader` \ 75 :py:class:`fparser.common.readfortran.FortranStringReader` 77 :return: the matched preprocessor directive object or `None`. 78 :rtype: one of (:py:class:`fparser.two.C99Preprocess.Cpp_*_Stmt`,) or \ 84 is_potential_cpp_directive =
True 85 if isinstance(reader, FortranReaderBase):
86 item = reader.get_item()
87 is_potential_cpp_directive = isinstance(item, CppDirective)
92 if is_potential_cpp_directive:
93 for cls
in CPP_CLASS_NAMES:
94 obj = getattr(sys.modules[__name__], cls)(reader)
110 """Generic class for preprocessor tokens that form the right hand 111 side of a preprocessor directive (such as #error, #line, #if, etc.). 118 """Implements the matching for arbitrary preprocessor tokens 119 that form the right hand side of a preprocessor directive. It 120 does not impose any restrictions other than the string not 123 :param str string: the string to be matched as pp-tokens. 125 :return: a 1-tuple containing the matched string or None. 126 :rtype: (str,) or NoneType 131 line = string.strip()
138 :return: this pp-tokens as a string. 152 C99 6.10.1 Conditional inclusion 154 if-stmt is # if constant-expression new-line 155 or ifdef identifier new-line 156 or ifndef identifier new-line 161 use_names = [
"Cpp_Macro_Identifier",
"Cpp_Pp_Tokens"]
163 _regex = re.compile(
r"#\s*(ifdef|ifndef|if)\b")
164 _if_pattern = pattern.Pattern(
"<if>",
r"^\s*#\s*if\b", value=
"#if")
166 pattern.Pattern(
"<ifdef>",
r"^\s*#\s*ifdef\b", value=
"#ifdef"),
167 pattern.Pattern(
"<ifndef>",
r"^\s*#\s*ifndef\b", value=
"#ifndef"),
172 """Implements the matching for an if preprocessor directive 173 (or its variations ifdef, ifndef). For ifdef and ifndef 174 statements it matches the macro identifier using 175 :py:class:`fparser.two.C99Preprocesser.Cpp_Macro_Identifier` 176 otherwise it uses :py:class:`fparser.two.C99Preprocessor.Cpp_Pp_Tokens` 177 to accept any non-empty string as rhs. 179 :param str string: the string to match with as an if statement. 181 :return: a tuple of size 2 containing the statement's keyword \ 182 and the right hand side, or `None` if there is no match. 184 (`str`, py:class:`fparser.two.C99Preprocessor.Cpp_Macro_Identifier`)\ 185 or (`str`, py:class:`fparser.two.C99Preprocessor.Cpp_Pp_Tokens`) \ 191 result = WORDClsBase.match(
192 Cpp_If_Stmt._if_pattern,
198 return result
or WORDClsBase.match(
199 Cpp_If_Stmt._def_pattern,
200 Cpp_Macro_Identifier,
208 :return: this if-stmt as a string. 211 return "{0} {1}".format(*self.
items)
216 C99 6.10.1 Conditional inclusion 218 elif-stmt is # elif constant-expression new-line 223 use_names = [
"Cpp_Pp_Tokens"]
225 _pattern = pattern.Pattern(
"<elif-stmt>",
r"^\s*#\s*elif\b", value=
"#elif")
229 """Implements the matching for an elif preprocessor directive. 231 :param str string: the string to match with as an elif statement. 233 :return: a tuple of size 2 containing the statements keyword and \ 234 right hand side, or `None` if there is no match. 236 (`str`, :py:class:`fparser.two.C99_Preprocessor.Cpp_Pp_Tokens`) \ 242 return WORDClsBase.match(
243 Cpp_Elif_Stmt._pattern,
252 :return: this elif-stmt as a string. 255 return "{0} {1}".format(*self.
items)
260 C99 6.10.1 Conditional inclusion 262 else-stmt is # else new-line 268 _pattern = pattern.Pattern(
"<else>",
r"^\s*#\s*else\b")
272 """Implements the matching for an else preprocessor directive. 274 :param str string: the string to match with as an else statement. 276 :return: a 1-tuple containing the matched string or `None` if \ 278 :rtype: (str,) or NoneType 283 return StringBase.match(Cpp_Else_Stmt._pattern, string)
287 :return: this else-stmt as a string. 295 C99 6.10.1 Conditional inclusion 297 endif-stmt is # endif new-line 303 _pattern = pattern.Pattern(
"<endif>",
r"^\s*#\s*endif\b", value=
"#endif")
307 """Implements the matching for an endif preprocessor directive. 309 :param str string: the string to match with as an endif statement. 311 :return: a 1-tuple containing the matched string or `None` if \ 313 :rtype: (str,) or NoneType 318 return StringBase.match(Cpp_Endif_Stmt._pattern, string)
322 :return: this endif-stmt as a string. 330 C99 6.10.2 Source file inclusion 332 include_stmt is # include [ <h-char-sequence> 334 or pp-tokens ] new-line 337 _regex = re.compile(
r"#\s*include\b")
339 use_names = [
"Include_Filename"]
343 """Implements the matching for an include statement. 345 Allows for the filename to appear in double quotes or angle 346 brackets. Only very loose restrictions are enforced for the 347 filename, which is matched by 348 py:class:`fparser.two.Fortran2003.Include_Filename`. 350 :param str string: the string to match with as an include statement. 352 :return: a tuple of size 1 containing a \ 353 py:class:`fparser.two.C99Preprocessor.Cpp_Include_Filename` \ 354 object with the matched filename if there is a match, \ 355 or `None` if there is not. 356 :rtype: (:py:class:`fparser.two.Fortran2003.Include_Filename`, ) \ 364 line = string.strip()
365 found = Cpp_Include_Stmt._regex.match(line)
369 rhs = line[found.end() :].strip()
370 if rhs
is None or len(rhs) < 3:
375 if not (rhs[0] ==
'"' and rhs[-1] ==
'"')
and not (
376 rhs[0] ==
"<" and rhs[-1] ==
">" 382 file_name = rhs[1:-1]
384 return (Include_Filename(file_name),)
388 :return: this include-stmt as a string. 391 return '#include "{0}"'.format(self.
items[0])
396 C99 6.10.3 Macro replacement 398 macro_stmt is # define identifier [( [identifier-list] ) or (...) ] 399 [ replacement-list ] new-line 401 Important: No preceding whitespace is allowed for the left parenthesis of 402 the optional identifier-list. If a preceding whitespace is encountered, 403 the bracket is considered part of the replacement-list. 406 use_names = [
"Cpp_Macro_Identifier",
"Cpp_Macro_Identifier_List",
"Cpp_Pp_Tokens"]
408 _regex = re.compile(
r"#\s*define\b")
412 """Implements the matching for a preprocessor macro definition. 414 It matches define directives with macro identifier, optional 415 identifier list, and optional replacement list. The macro 416 identifier is matched using 417 :py:class:`fparser.two.C99Preprocessor.Cpp_Macro_Identifier` 418 and the optional argument identifier list using 419 :py:class:`fparser.two.C99Preprocessor.Cpp_Macro_Identifier_List`. 421 Important: No preceding whitespace is allowed for the left 422 parentheses of the dentifier-list. If a preceding whitespace is 423 encountered, the it is considered part of the replacement-list. 425 :param str string: the string to match with as an if statement. 427 :return: a tuple of size 3 containing the macro identifier, \ 428 identifier list or None, and replacement list or None, \ 429 or `None` if there is no match. 431 (py:class:`fparser.two.C99Preprocessor.Cpp_Macro_Identifier`, \ 432 py:class:`fparser.two.C99Preprocessor.Cpp_Macro_Identifier_List` \ 434 py:class:`fparser.two.C99Preprocessor.Cpp_Pp_Tokens` or NoneType) \ 440 line = string.strip()
441 found = Cpp_Macro_Stmt._regex.match(line)
445 rhs = line[found.end() :].strip()
446 found = pattern.macro_name.match(rhs)
450 definition = rhs[found.end() :]
454 return (name,
None,
None)
455 if definition[0] ==
"(":
456 found = Cpp_Macro_Identifier_List._pattern.match(definition)
466 definition = definition[found.end() :]
468 parameter_list =
None 470 definition = definition.strip()
475 return (name, parameter_list, definition)
479 :return: this macro-stmt as a string. 482 return "#define {0}{1}{2}{3}".format(
485 " " if self.
items[2]
else "",
491 """Implements the matching of a macro identifier.""" 498 """Implements the matching of a macro identifier. 500 It matches the string with the regular expression abs_macro_name 501 in the pattern_tools file. The macro identifier may contain 502 only letters and underscore. 504 :param str string: the string to match with the pattern rule. 506 :return: a tuple of size 1 containing a string with the \ 507 matched name if there is a match, or None if there is not. 508 :rtype: (str) or NoneType 511 return StringBase.match(pattern.abs_macro_name, string.strip())
515 """Implements the matching of an identifier list in a macro definition. 517 identifier-list is (identifier [, identifier-list or ...]) 523 _pattern = pattern.Pattern(
525 r"\((\s*[A-Za-z_]\w*" 526 r"(?:\s*,\s*[A-Za-z_]\w*)*" 527 r"(?:\s*,\s*\.{3})?|\.{3})?\s*\)",
532 """Implements the matching of a macro identifier list as part of 533 a macro definition. It must consist of one or more macro 534 identifier separated by comma, or "..." for a variadic argument 535 list, and must be surrouned by parentheses. 537 For simplicity, the matched list is kept as a single string and not 539 :py:class:`fparser.two.C99Preprocessor.Cpp_Macro_Identifier`. 541 :param str string: the string to match with the pattern rule. 543 :return: a tuple of size 1 containing a string with the \ 544 matched identifier list if there is a match, or None if \ 546 :rtype: (`str`,) or `NoneType` 551 return StringBase.match(Cpp_Macro_Identifier_List._pattern, string)
555 :return: this macro-identifier-list as a string. 562 """Implements the matching of a preprocessor undef statement for a macro. 564 undef-stmt is # undef identifier new-line 566 Strictly, this is part of 6.10.3 but since it is identified by a different 567 directive keyword (undef instead of define) we treat it separately. 573 use_names = [
"Cpp_Macro_Identifier"]
575 _pattern = pattern.Pattern(
"<undef>",
r"^\s*(#\s*undef)\b", value=
"#undef")
579 """Implements the matching for a preprocessor undef statement 580 for a macro. The macro identifier is matched using 581 :py:class:`fparser.two.C99Preprocessor.Cpp_Macro_Identifier`. 583 :param str string: the string to match with as an if statement. 585 :return: a tuple of size 1 containing the macro identifier, or\ 586 `None` if there is no match. 587 :rtype: (py:class:`fparser.two.C99Preprocessor.Cpp_Macro_Identifier`) \ 593 return WORDClsBase.match(
594 Cpp_Undef_Stmt._pattern,
595 Cpp_Macro_Identifier,
603 :return: this undef-stmt as a string. 606 return "{0} {1}".format(*self.
items)
611 C99 6.10.4 Line control 613 line-stmt is # line digit-sequence [ "s-char-sequence" ] new-line 614 or pp-tokens new-line 618 use_names = [
"Cpp_Pp_Tokens"]
620 _pattern = pattern.Pattern(
"<line>",
r"^\s*#\s*line\b", value=
"#line")
624 """Implements the matching for a line preprocessor directive. 625 The right hand side of the directive is not matched any further 626 but simply kept as a string. 628 :param str string: the string to match with as a line statement. 630 :return: a tuple of size 1 with the right hand side as a string, \ 631 or `None` if there is no match. 632 :rtype: (`str`) or `NoneType` 637 return WORDClsBase.match(
638 Cpp_Line_Stmt._pattern,
647 :return: this line-stmt as a string. 650 return "{0} {1}".format(*self.
items)
655 C99 6.10.5 Error directive 657 error-stmt is # error [pp-tokens] new-line 662 use_names = [
"Cpp_Pp_Tokens"]
664 _pattern = pattern.Pattern(
"<error>",
r"^\s*#\s*error\b", value=
"#error")
668 """Implements the matching for an error preprocessor directive. 669 The optional right hand side of the directive is not matched any 670 further but simply kept as a string. 672 :param str string: the string to match with as a line statement. 674 :return: an empty tuple or a tuple of size 1 with the right hand \ 675 side as a string, or `None` if there is no match. 676 :rtype: () or (`str`) or `NoneType` 681 return WORDClsBase.match(
682 Cpp_Error_Stmt._pattern,
691 :return: this error-stmt as a string. 695 return "{0} {1}".format(*self.
items)
701 Not actually part of C99 but supported by most preprocessors and 702 with syntax identical to Cpp_Error_Stmt 704 warning-stmt is # warning [pp-tokens] new-line 709 use_names = [
"Cpp_Pp_Tokens"]
711 _pattern = pattern.Pattern(
"<warning>",
r"^\s*#\s*warning\b", value=
"#warning")
715 """Implements the matching for a warning preprocessor directive. 716 The optional right hand side of the directive is not matched any 717 further but simply kept as a string. 719 :param str string: the string to match with as a line statement. 721 :return: an empty tuple or a tuple of size 1 with the right hand \ 722 side as a string, or `None` if there is no match. 723 :rtype: () or (`str`) or `NoneType` 728 return WORDClsBase.match(
729 Cpp_Warning_Stmt._pattern,
738 :return: this warning-stmt as a string. 742 return "{0} {1}".format(*self.
items)
754 C99 6.10.7 Null directive 756 null-stmt is # new-line 764 """Implements the matching for a Null (empty) directive. 766 :param str string: the string to match with as a line statement. 768 :return: an empty tuple or `None` if there is no match. 769 :rtype: () or `NoneType` 774 line = string.strip()
781 :return: this null-stmt as a string.
def match(keyword, cls, string, colons=False, require_cls=False)