Package madgraph :: Package iolibs :: Module file_writers
[hide private]
[frames] | no frames]

Source Code for Module madgraph.iolibs.file_writers

  1  ################################################################################ 
  2  # 
  3  # Copyright (c) 2009 The MadGraph Development team and Contributors 
  4  # 
  5  # This file is a part of the MadGraph 5 project, an application which  
  6  # automatically generates Feynman diagrams and matrix elements for arbitrary 
  7  # high-energy processes in the Standard Model and beyond. 
  8  # 
  9  # It is subject to the MadGraph license which should accompany this  
 10  # distribution. 
 11  # 
 12  # For more information, please visit: http://madgraph.phys.ucl.ac.be 
 13  # 
 14  ################################################################################ 
 15   
 16  """Classes to write good-looking output in different languages: 
 17  Fortran, C++, etc.""" 
 18   
 19   
 20  import re 
 21  import collections 
 22   
23 -class FileWriter(file):
24 """Generic Writer class. All writers should inherit from this class.""" 25
26 - class FileWriterError(IOError):
27 """Exception raised if an error occurs in the definition 28 or the execution of a Writer.""" 29 30 pass
31 32
33 - def __init__(self, name, opt = 'w'):
34 """Initialize file to write to""" 35 36 return file.__init__(self, name, opt)
37
38 - def write_line(self, line):
39 """Write a line with proper indent and splitting of long lines 40 for the language in question.""" 41 42 pass
43
44 - def write_comment_line(self, line):
45 """Write a comment line, with correct indent and line splits, 46 for the language in question""" 47 48 pass
49
50 - def write_comments(self, lines):
51 """Write set of comment lines, with correct indent and line splits, 52 for the language in question""" 53 54 splitlines = [] 55 if isinstance(lines, list): 56 for line in lines: 57 if not isinstance(line, str): 58 raise self.FileWriterError("%s not string" % repr(line)) 59 splitlines.extend(line.split('\n')) 60 elif isinstance(lines, str): 61 splitlines.extend(lines.split('\n')) 62 else: 63 raise self.FileWriterError("%s not string" % repr(lines)) 64 65 for line in splitlines: 66 res_lines = self.write_comment_line(line) 67 for line_to_write in res_lines: 68 self.write(line_to_write) 69 70 pass
71
72 - def writelines(self, lines):
73 """Extends the regular file.writeline() function to write out 74 nicely formatted code""" 75 76 splitlines = [] 77 if isinstance(lines, list): 78 for line in lines: 79 if not isinstance(line, str): 80 raise self.FileWriterError("%s not string" % repr(line)) 81 splitlines.extend(line.split('\n')) 82 elif isinstance(lines, str): 83 splitlines.extend(lines.split('\n')) 84 else: 85 raise self.FileWriterError("%s not string" % repr(lines)) 86 87 for line in splitlines: 88 res_lines = self.write_line(line) 89 for line_to_write in res_lines: 90 self.write(line_to_write)
91 92 #=============================================================================== 93 # FortranWriter 94 #===============================================================================
95 -class FortranWriter(FileWriter):
96 """Routines for writing fortran lines. Keeps track of indentation 97 and splitting of long lines""" 98
99 - class FortranWriterError(FileWriter.FileWriterError):
100 """Exception raised if an error occurs in the definition 101 or the execution of a FortranWriter.""" 102 pass
103 104 # Parameters defining the output of the Fortran writer 105 keyword_pairs = {'^if.+then\s*$': ('^endif', 2), 106 '^do\s+': ('^enddo\s*$', 2), 107 '^subroutine': ('^end\s*$', 0), 108 'function': ('^end\s*$', 0)} 109 single_indents = {'^else\s*$':-2, 110 '^else\s*if.+then\s*$':-2} 111 number_re = re.compile('^(?P<num>\d+)\s+(?P<rest>.*)') 112 line_cont_char = '$' 113 comment_char = 'c' 114 downcase = False 115 line_length = 71 116 max_split = 10 117 split_characters = "+-*/,) " 118 comment_split_characters = " " 119 120 # Private variables 121 __indent = 0 122 __keyword_list = [] 123 __comment_pattern = re.compile(r"^(\s*#|c$|(c\s+([^=]|$)))", re.IGNORECASE) 124
125 - def write_line(self, line):
126 """Write a fortran line, with correct indent and line splits""" 127 128 # This Routine is for a single line 129 assert(isinstance(line, str) and line.find('\n') == -1) 130 131 132 res_lines = [] 133 134 # Check if empty line and write it 135 if not line.lstrip(): 136 res_lines.append("\n") 137 return res_lines 138 139 # Check if this line is a comment 140 if self.__comment_pattern.search(line): 141 # This is a comment 142 res_lines = self.write_comment_line(line.lstrip()[1:]) 143 return res_lines 144 145 else: 146 # This is a regular Fortran line 147 148 # Strip leading spaces from line 149 myline = line.lstrip() 150 151 # Check if line starts with number 152 num_group = self.number_re.search(myline) 153 num = "" 154 if num_group: 155 num = num_group.group('num') 156 myline = num_group.group('rest') 157 158 # Convert to upper or lower case 159 # Here we need to make exception for anything within quotes. 160 (myline, part, post_comment) = myline.partition("!") 161 # Set space between line and post-comment 162 if part: 163 part = " " + part 164 # Replace all double quotes by single quotes 165 myline = myline.replace('\"', '\'') 166 # Downcase or upcase Fortran code, except for quotes 167 splitline = myline.split('\'') 168 myline = "" 169 i = 0 170 while i < len(splitline): 171 if i % 2 == 1: 172 # This is a quote - check for escaped \'s 173 while splitline[i][len(splitline[i]) - 1] == '\\': 174 splitline[i] = splitline[i] + '\'' + splitline.pop(i + 1) 175 else: 176 # Otherwise downcase/upcase 177 if FortranWriter.downcase: 178 splitline[i] = splitline[i].lower() 179 else: 180 splitline[i] = splitline[i].upper() 181 i = i + 1 182 183 myline = "\'".join(splitline).rstrip() 184 185 # Check if line starts with dual keyword and adjust indent 186 if self.__keyword_list and re.search(self.keyword_pairs[\ 187 self.__keyword_list[-1]][0], myline.lower()): 188 key = self.__keyword_list.pop() 189 self.__indent = self.__indent - self.keyword_pairs[key][1] 190 191 # Check for else and else if 192 single_indent = 0 193 for key in self.single_indents.keys(): 194 if re.search(key, myline.lower()): 195 self.__indent = self.__indent + self.single_indents[key] 196 single_indent = -self.single_indents[key] 197 break 198 199 # Break line in appropriate places 200 # defined (in priority order) by the characters in split_characters 201 res = self.split_line(" " + num + \ 202 " " * (5 + self.__indent - len(num)) + myline, 203 self.split_characters, 204 " " * 5 + self.line_cont_char + \ 205 " " * (self.__indent + 1)) 206 207 # Check if line starts with keyword and adjust indent for next line 208 for key in self.keyword_pairs.keys(): 209 if re.search(key, myline.lower()): 210 self.__keyword_list.append(key) 211 self.__indent = self.__indent + self.keyword_pairs[key][1] 212 break 213 214 # Correct back for else and else if 215 if single_indent != None: 216 self.__indent = self.__indent + single_indent 217 single_indent = None 218 219 # Write line(s) to file 220 res_lines.append("\n".join(res) + part + post_comment + "\n") 221 222 return res_lines
223
224 - def write_comment_line(self, line):
225 """Write a comment line, with correct indent and line splits""" 226 227 # write_comment_line must have a single line as argument 228 assert(isinstance(line, str) and line.find('\n') == -1) 229 230 res_lines = [] 231 232 # This is a comment 233 myline = " " * (5 + self.__indent) + line.lstrip() 234 if FortranWriter.downcase: 235 self.comment_char = self.comment_char.lower() 236 else: 237 self.comment_char = self.comment_char.upper() 238 myline = self.comment_char + myline 239 # Break line in appropriate places 240 # defined (in priority order) by the characters in 241 # comment_split_characters 242 res = self.split_line(myline, 243 self.comment_split_characters, 244 self.comment_char + " " * (5 + self.__indent)) 245 246 # Write line(s) to file 247 res_lines.append("\n".join(res) + "\n") 248 249 return res_lines
250
251 - def split_line(self, line, split_characters, line_start):
252 """Split a line if it is longer than self.line_length 253 columns. Split in preferential order according to 254 split_characters, and start each new line with line_start.""" 255 256 res_lines = [line] 257 258 while len(res_lines[-1]) > self.line_length: 259 split_at = self.line_length 260 for character in split_characters: 261 index = res_lines[-1][(self.line_length - self.max_split): \ 262 self.line_length].rfind(character) 263 if index >= 0: 264 split_at = self.line_length - self.max_split + index 265 break 266 267 res_lines.append(line_start + \ 268 res_lines[-1][split_at:]) 269 res_lines[-2] = res_lines[-2][:split_at] 270 271 return res_lines
272 273 #=============================================================================== 274 # CPPWriter 275 #===============================================================================
276 -class CPPWriter(FileWriter):
277 """Routines for writing C++ lines. Keeps track of brackets, 278 spaces, indentation and splitting of long lines""" 279
280 - class CPPWriterError(FileWriter.FileWriterError):
281 """Exception raised if an error occurs in the definition 282 or the execution of a CPPWriter.""" 283 pass
284 285 # Parameters defining the output of the C++ writer 286 standard_indent = 2 287 line_cont_indent = 4 288 289 indent_par_keywords = {'^if': standard_indent, 290 '^else if': standard_indent, 291 '^for': standard_indent, 292 '^while': standard_indent, 293 '^switch': standard_indent} 294 indent_single_keywords = {'^else': standard_indent} 295 indent_content_keywords = {'^class': standard_indent, 296 '^namespace': 0} 297 cont_indent_keywords = {'^case': standard_indent, 298 '^default': standard_indent, 299 '^public': standard_indent, 300 '^private': standard_indent, 301 '^protected': standard_indent} 302 303 spacing_patterns = [('\s*\"\s*}', '\"'), 304 ('\s*,\s*', ', '), 305 ('\s*-\s*', ' - '), 306 ('([{(,=])\s*-\s*', '\g<1> -'), 307 ('(return)\s*-\s*', '\g<1> -'), 308 ('\s*\+\s*', ' + '), 309 ('([{(,=])\s*\+\s*', '\g<1> +'), 310 ('\(\s*', '('), 311 ('\s*\)', ')'), 312 ('\{\s*', '{'), 313 ('\s*\}', '}'), 314 ('\s*=\s*', ' = '), 315 ('\s*>\s*', ' > '), 316 ('\s*<\s*', ' < '), 317 ('\s*!\s*', ' !'), 318 ('\s*/\s*', '/'), 319 ('\s*\*\s*', ' * '), 320 ('\s*-\s+-\s*', '-- '), 321 ('\s*\+\s+\+\s*', '++ '), 322 ('\s*-\s+=\s*', ' -= '), 323 ('\s*\+\s+=\s*', ' += '), 324 ('\s*\*\s+=\s*', ' *= '), 325 ('\s*/=\s*', ' /= '), 326 ('\s*>\s+>\s*', ' >> '), 327 ('<\s*double\s*>>\s*', '<double> > '), 328 ('\s*<\s+<\s*', ' << '), 329 ('\s*-\s+>\s*', '->'), 330 ('\s*=\s+=\s*', ' == '), 331 ('\s*!\s+=\s*', ' != '), 332 ('\s*>\s+=\s*', ' >= '), 333 ('\s*<\s+=\s*', ' <= '), 334 ('\s*&&\s*', ' && '), 335 ('\s*\|\|\s*', ' || '), 336 ('\s*{\s*}', ' {}'), 337 ('\s*;\s*', '; '), 338 (';\s*\}', ';}'), 339 (';\s*$}', ';'), 340 ('\s*<\s*([a-zA-Z0-9]+?)\s*>', '<\g<1>>'), 341 ('^#include\s*<\s*(.*?)\s*>', '#include <\g<1>>'), 342 ('(\d+\.{0,1}\d*|\.\d+)\s*[eE]\s*([+-]{0,1})\s*(\d+)', 343 '\g<1>e\g<2>\g<3>'), 344 ('\s+',' ')] 345 spacing_re = dict([(key[0], re.compile(key[0])) for key in \ 346 spacing_patterns]) 347 348 init_array_pattern = re.compile(r"=\s*\{.*\}") 349 short_clause_pattern = re.compile(r"\{.*\}") 350 351 comment_char = '//' 352 comment_pattern = re.compile(r"^(\s*#\s+|\s*//)") 353 start_comment_pattern = re.compile(r"^(\s*/\*)") 354 end_comment_pattern = re.compile(r"(\s*\*/)$") 355 356 quote_chars = re.compile(r"[^\\][\"\']|^[\"\']") 357 no_space_comment_patterns = re.compile(r"--|\*\*|==|\+\+") 358 line_length = 80 359 max_split = 40 360 split_characters = " " 361 comment_split_characters = " " 362 363 # Private variables 364 __indent = 0 365 __keyword_list = collections.deque() 366 __comment_ongoing = False 367
368 - def write_line(self, line):
369 """Write a C++ line, with correct indent, spacing and line splits""" 370 371 # write_line must have a single line as argument 372 assert(isinstance(line, str) and line.find('\n') == -1) 373 374 res_lines = [] 375 376 # Check if this line is a comment 377 if self.comment_pattern.search(line) or \ 378 self.start_comment_pattern.search(line) or \ 379 self.__comment_ongoing: 380 # This is a comment 381 res_lines = self.write_comment_line(line.lstrip()) 382 return res_lines 383 384 # This is a regular C++ line 385 386 # Strip leading spaces from line 387 myline = line.lstrip() 388 389 # Return if empty line 390 if not myline: 391 return ["\n"] 392 393 # Check if line starts with "{" 394 if myline[0] == "{": 395 # Check for indent 396 indent = self.__indent 397 key = "" 398 if self.__keyword_list: 399 key = self.__keyword_list[-1] 400 if key in self.indent_par_keywords: 401 indent = indent - self.indent_par_keywords[key] 402 elif key in self.indent_single_keywords: 403 indent = indent - self.indent_single_keywords[key] 404 elif key in self.indent_content_keywords: 405 indent = indent - self.indent_content_keywords[key] 406 else: 407 # This is free-standing block, just use standard indent 408 self.__indent = self.__indent + self.standard_indent 409 # Print "{" 410 res_lines.append(" " * indent + "{" + "\n") 411 # Add "{" to keyword list 412 self.__keyword_list.append("{") 413 myline = myline[1:].lstrip() 414 if myline: 415 # If anything is left of myline, write it recursively 416 res_lines.extend(self.write_line(myline)) 417 return res_lines 418 419 # Check if line starts with "}" 420 if myline[0] == "}": 421 # First: Check if no keywords in list 422 if not self.__keyword_list: 423 raise self.CPPWriterError(\ 424 'Non-matching } in C++ output: ' \ 425 + myline) 426 # First take care of "case" and "default" 427 if self.__keyword_list[-1] in self.cont_indent_keywords.keys(): 428 key = self.__keyword_list.pop() 429 self.__indent = self.__indent - self.cont_indent_keywords[key] 430 # Now check that we have matching { 431 if not self.__keyword_list.pop() == "{": 432 raise self.CPPWriterError(\ 433 'Non-matching } in C++ output: ' \ 434 + ",".join(self.__keyword_list) + myline) 435 # Check for the keyword before and close 436 key = "" 437 if self.__keyword_list: 438 key = self.__keyword_list[-1] 439 if key in self.indent_par_keywords: 440 self.__indent = self.__indent - \ 441 self.indent_par_keywords[key] 442 self.__keyword_list.pop() 443 elif key in self.indent_single_keywords: 444 self.__indent = self.__indent - \ 445 self.indent_single_keywords[key] 446 self.__keyword_list.pop() 447 elif key in self.indent_content_keywords: 448 self.__indent = self.__indent - \ 449 self.indent_content_keywords[key] 450 self.__keyword_list.pop() 451 else: 452 # This was just a { } clause, without keyword 453 self.__indent = self.__indent - self.standard_indent 454 455 # Write } or }; and then recursively write the rest 456 breakline_index = 1 457 if len(myline) > 1: 458 if myline[1] == ";": 459 breakline_index = 2 460 elif myline[1:].lstrip()[:2] == "//": 461 breakline_index = len(myline) - 1 462 res_lines.append("\n".join(self.split_line(\ 463 myline[:breakline_index], 464 self.split_characters)) + "\n") 465 myline = myline[breakline_index + 1:].lstrip() 466 if myline: 467 # If anything is left of myline, write it recursively 468 res_lines.extend(self.write_line(myline)) 469 return res_lines 470 471 # Check if line starts with keyword with parentesis 472 for key in self.indent_par_keywords.keys(): 473 if re.search(key, myline): 474 # Step through to find end of parenthesis 475 parenstack = collections.deque() 476 for i, ch in enumerate(myline[len(key)-1:]): 477 if ch == '(': 478 parenstack.append(ch) 479 elif ch == ')': 480 try: 481 parenstack.pop() 482 except IndexError: 483 # no opening parenthesis left in stack 484 raise self.CPPWriterError(\ 485 'Non-matching parenthesis in C++ output' \ 486 + myline) 487 if not parenstack: 488 # We are done 489 break 490 endparen_index = len(key) + i 491 # Print line, make linebreak, check if next character is { 492 res_lines.append("\n".join(self.split_line(\ 493 myline[:endparen_index], \ 494 self.split_characters)) + \ 495 "\n") 496 myline = myline[endparen_index:].lstrip() 497 # Add keyword to list and add indent for next line 498 self.__keyword_list.append(key) 499 self.__indent = self.__indent + \ 500 self.indent_par_keywords[key] 501 if myline: 502 # If anything is left of myline, write it recursively 503 res_lines.extend(self.write_line(myline)) 504 505 return res_lines 506 507 # Check if line starts with single keyword 508 for key in self.indent_single_keywords.keys(): 509 if re.search(key, myline): 510 end_index = len(key) - 1 511 # Print line, make linebreak, check if next character is { 512 res_lines.append(" " * self.__indent + myline[:end_index] + \ 513 "\n") 514 myline = myline[end_index:].lstrip() 515 # Add keyword to list and add indent for next line 516 self.__keyword_list.append(key) 517 self.__indent = self.__indent + \ 518 self.indent_single_keywords[key] 519 if myline: 520 # If anything is left of myline, write it recursively 521 res_lines.extend(self.write_line(myline)) 522 523 return res_lines 524 525 # Check if line starts with content keyword 526 for key in self.indent_content_keywords.keys(): 527 if re.search(key, myline): 528 # Print line, make linebreak, check if next character is { 529 if "{" in myline: 530 end_index = myline.index("{") 531 else: 532 end_index = len(myline) 533 res_lines.append("\n".join(self.split_line(\ 534 myline[:end_index], \ 535 self.split_characters)) + \ 536 "\n") 537 myline = myline[end_index:].lstrip() 538 # Add keyword to list and add indent for next line 539 self.__keyword_list.append(key) 540 self.__indent = self.__indent + \ 541 self.indent_content_keywords[key] 542 if myline: 543 # If anything is left of myline, write it recursively 544 res_lines.extend(self.write_line(myline)) 545 546 return res_lines 547 548 # Check if line starts with continuous indent keyword 549 for key in self.cont_indent_keywords.keys(): 550 if re.search(key, myline): 551 # Check if we have a continuous indent keyword since before 552 if self.__keyword_list[-1] in self.cont_indent_keywords.keys(): 553 self.__indent = self.__indent - \ 554 self.cont_indent_keywords[\ 555 self.__keyword_list.pop()] 556 # Print line, make linebreak 557 res_lines.append("\n".join(self.split_line(myline, \ 558 self.split_characters)) + \ 559 "\n") 560 # Add keyword to list and add indent for next line 561 self.__keyword_list.append(key) 562 self.__indent = self.__indent + \ 563 self.cont_indent_keywords[key] 564 565 return res_lines 566 567 # Check if this line is an array initialization a ={b,c,d}; 568 if self.init_array_pattern.search(myline): 569 res_lines.append("\n".join(self.split_line(\ 570 myline, 571 self.split_characters)) + \ 572 "\n") 573 return res_lines 574 575 # Check if this is a short xxx {yyy} type line; 576 if self.short_clause_pattern.search(myline): 577 lines = self.split_line(myline, 578 self.split_characters) 579 if len(lines) == 1: 580 res_lines.append("\n".join(lines) + "\n") 581 return res_lines 582 583 # Check if there is a "{" somewhere in the line 584 if "{" in myline: 585 end_index = myline.index("{") 586 res_lines.append("\n".join(self.split_line(\ 587 myline[:end_index], \ 588 self.split_characters)) + \ 589 "\n") 590 myline = myline[end_index:].lstrip() 591 if myline: 592 # If anything is left of myline, write it recursively 593 res_lines.extend(self.write_line(myline)) 594 return res_lines 595 596 # Check if there is a "}" somewhere in the line 597 if "}" in myline: 598 end_index = myline.index("}") 599 res_lines.append("\n".join(self.split_line(\ 600 myline[:end_index], \ 601 self.split_characters)) + \ 602 "\n") 603 myline = myline[end_index:].lstrip() 604 if myline: 605 # If anything is left of myline, write it recursively 606 res_lines.extend(self.write_line(myline)) 607 return res_lines 608 609 # Write line(s) to file 610 res_lines.append("\n".join(self.split_line(myline, \ 611 self.split_characters)) + "\n") 612 613 # Check if this is a single indented line 614 if self.__keyword_list: 615 if self.__keyword_list[-1] in self.indent_par_keywords: 616 self.__indent = self.__indent - \ 617 self.indent_par_keywords[self.__keyword_list.pop()] 618 elif self.__keyword_list[-1] in self.indent_single_keywords: 619 self.__indent = self.__indent - \ 620 self.indent_single_keywords[self.__keyword_list.pop()] 621 elif self.__keyword_list[-1] in self.indent_content_keywords: 622 self.__indent = self.__indent - \ 623 self.indent_content_keywords[self.__keyword_list.pop()] 624 625 return res_lines
626
627 - def write_comment_line(self, line):
628 """Write a comment line, with correct indent and line splits""" 629 630 # write_comment_line must have a single line as argument 631 assert(isinstance(line, str) and line.find('\n') == -1) 632 633 res_lines = [] 634 635 # This is a comment 636 637 if self.start_comment_pattern.search(line): 638 self.__comment_ongoing = True 639 line = self.start_comment_pattern.sub("", line) 640 641 if self.end_comment_pattern.search(line): 642 self.__comment_ongoing = False 643 line = self.end_comment_pattern.sub("", line) 644 645 line = self.comment_pattern.sub("", line).strip() 646 # Avoid extra space for lines starting with certain multiple patterns 647 if self.no_space_comment_patterns.match(line): 648 myline = self.comment_char + line 649 else: 650 myline = self.comment_char + " " + line 651 # Break line in appropriate places defined (in priority order) 652 # by the characters in comment_split_characters 653 res = self.split_comment_line(myline) 654 655 # Write line(s) to file 656 res_lines.append("\n".join(res) + "\n") 657 658 return res_lines
659
660 - def split_line(self, line, split_characters):
661 """Split a line if it is longer than self.line_length 662 columns. Split in preferential order according to 663 split_characters. Also fix spacing for line.""" 664 665 # First split up line if there are comments 666 comment = "" 667 if line.find(self.comment_char) > -1: 668 line, dum, comment = line.partition(self.comment_char) 669 670 # Then split up line if there are quotes 671 quotes = self.quote_chars.finditer(line) 672 673 start_pos = 0 674 line_quotes = [] 675 line_no_quotes = [] 676 for i, quote in enumerate(quotes): 677 if i % 2 == 0: 678 # Add text before quote to line_no_quotes 679 line_no_quotes.append(line[start_pos:quote.start()]) 680 start_pos = quote.start() 681 else: 682 # Add quote to line_quotes 683 line_quotes.append(line[start_pos:quote.end()]) 684 start_pos = quote.end() 685 686 line_no_quotes.append(line[start_pos:]) 687 688 # Fix spacing for line, but only outside of quotes 689 line.rstrip() 690 for i, no_quote in enumerate(line_no_quotes): 691 for key in self.spacing_patterns: 692 no_quote = self.spacing_re[key[0]].sub(key[1], no_quote) 693 line_no_quotes[i] = no_quote 694 695 # Glue together quotes and non-quotes: 696 line = line_no_quotes[0] 697 for i in range(len(line_quotes)): 698 line += line_quotes[i] 699 if len(line_no_quotes) > i + 1: 700 line += line_no_quotes[i+1] 701 702 # Add indent 703 res_lines = [" " * self.__indent + line] 704 705 while len(res_lines[-1]) > self.line_length: 706 long_line = res_lines[-1] 707 split_at = self.line_length 708 for character in split_characters: 709 index = long_line[(self.line_length - self.max_split): \ 710 self.line_length].rfind(character) 711 if index >= 0: 712 split_at = self.line_length - self.max_split + index + 1 713 break 714 715 # Don't allow split within quotes 716 quotes = self.quote_chars.findall(long_line[:split_at]) 717 if quotes and len(quotes) % 2 == 1: 718 quote_match = self.quote_chars.search(long_line[split_at:]) 719 if not quote_match: 720 raise self.CPPWriterError(\ 721 "Error: Unmatched quote in line " + long_line) 722 split_at = quote_match.end() + split_at + 1 723 split_match = re.search(self.split_characters, 724 long_line[split_at:]) 725 if split_match: 726 split_at = split_at + split_match.start() 727 else: 728 split_at = len(long_line) + 1 729 730 # Append new line 731 if long_line[split_at:].lstrip(): 732 # Replace old line 733 res_lines[-1] = long_line[:split_at].rstrip() 734 res_lines.append(" " * \ 735 (self.__indent + self.line_cont_indent) + \ 736 long_line[split_at:].strip()) 737 else: 738 break 739 740 if comment: 741 res_lines[-1] += " " + self.comment_char + comment 742 743 return res_lines
744
745 - def split_comment_line(self, line):
746 """Split a line if it is longer than self.line_length 747 columns. Split in preferential order according to 748 split_characters.""" 749 750 # First fix spacing for line 751 line.rstrip() 752 res_lines = [" " * self.__indent + line] 753 754 while len(res_lines[-1]) > self.line_length: 755 long_line = res_lines[-1] 756 split_at = self.line_length 757 index = long_line[(self.line_length - self.max_split): \ 758 self.line_length].rfind(' ') 759 if index >= 0: 760 split_at = self.line_length - self.max_split + index + 1 761 762 # Append new line 763 if long_line[split_at:].lstrip(): 764 # Replace old line 765 res_lines[-1] = long_line[:split_at].rstrip() 766 res_lines.append(" " * \ 767 self.__indent + self.comment_char + " " + \ 768 long_line[split_at:].strip()) 769 else: 770 break 771 772 return res_lines
773