| 68 | raise ParseError(msg, filename=self.filename, lineno=self.line_number) |
| 69 | |
| 70 | def writeline(self, line: str) -> None: |
| 71 | self.line_number += 1 |
| 72 | line = line.strip() |
| 73 | |
| 74 | def pop_stack() -> TokenAndCondition: |
| 75 | if not self.stack: |
| 76 | self.fail(f"#{token} without matching #if / #ifdef / #ifndef!") |
| 77 | return self.stack.pop() |
| 78 | |
| 79 | if self.continuation: |
| 80 | line = self.continuation + line |
| 81 | self.continuation = None |
| 82 | |
| 83 | if not line: |
| 84 | return |
| 85 | |
| 86 | if line.endswith('\\'): |
| 87 | self.continuation = line[:-1].rstrip() + " " |
| 88 | return |
| 89 | |
| 90 | # we have to ignore preprocessor commands inside comments |
| 91 | # |
| 92 | # we also have to handle this: |
| 93 | # /* start |
| 94 | # ... |
| 95 | # */ /* <-- tricky! |
| 96 | # ... |
| 97 | # */ |
| 98 | # and this: |
| 99 | # /* start |
| 100 | # ... |
| 101 | # */ /* also tricky! */ |
| 102 | if self.in_comment: |
| 103 | if '*/' in line: |
| 104 | # snip out the comment and continue |
| 105 | # |
| 106 | # GCC allows |
| 107 | # /* comment |
| 108 | # */ #include <stdio.h> |
| 109 | # maybe other compilers too? |
| 110 | _, _, line = line.partition('*/') |
| 111 | self.in_comment = False |
| 112 | |
| 113 | while True: |
| 114 | if '/*' in line: |
| 115 | if self.in_comment: |
| 116 | self.fail("Nested block comment!") |
| 117 | |
| 118 | before, _, remainder = line.partition('/*') |
| 119 | comment, comment_ends, after = remainder.partition('*/') |
| 120 | if comment_ends: |
| 121 | # snip out the comment |
| 122 | line = before.rstrip() + ' ' + after.lstrip() |
| 123 | continue |
| 124 | # comment continues to eol |
| 125 | self.in_comment = True |
| 126 | line = before.rstrip() |
| 127 | break |