Changeset 7827:8e00d4b32962
- Timestamp:
- 11/23/07 12:58:03 (5 years ago)
- Branch:
- default
- Parents:
- 7826:b9231b8d1a11 (diff), 7402:cad57dea1832 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 2 edited
-
sage/misc/preparser.py (modified) (1 diff)
-
sage/misc/preparser.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sage/misc/preparser.py
r7311 r7827 470 470 def preparse(line, reset=True, do_time=False, ignore_prompts=False): 471 471 r""" 472 sage: preparse("ZZ.<x> = ZZ['x']") 473 'ZZ = ZZ["x"]; (x,) = ZZ._first_ngens(Integer(1))' 474 sage: preparse("ZZ.<x> = ZZ['y']") 475 'ZZ = ZZ["x"]; (x,) = ZZ._first_ngens(Integer(1))' 476 sage: preparse("ZZ.<x,y> = ZZ[]") 477 'ZZ = ZZ["x, y"]; (x, y,) = ZZ._first_ngens(Integer(2))' 478 sage: preparse("ZZ.<x,y> = ZZ['u,v']") 479 'ZZ = ZZ["x, y"]; (x, y,) = ZZ._first_ngens(Integer(2))' 480 sage: preparse("ZZ.<x> = QQ[2^(1/3)]") 481 'ZZ = QQ["x"]; (x,) = ZZ._first_ngens(Integer(1))' 482 sage: QQ[2^(1/3)] 483 Number Field in a with defining polynomial x^3 - 2 472 484 """ 473 485 try: -
sage/misc/preparser.py
r7826 r7827 301 301 ix = code.find('..') 302 302 return code 303 303 304 def strip_prompts(line): 305 r"""Get rid of leading sage: and >>> prompts so that pasting of examples from 306 the documentation works. 307 308 sage: from sage.misc.preparser import strip_prompts 309 sage: strip_prompts("sage: 2 + 2") 310 '2 + 2' 311 sage: strip_prompts(">>> 3 + 2") 312 '3 + 2' 313 sage: strip_prompts(" 2 + 4") 314 ' 2 + 4' 315 """ 316 for prompt in ['sage:', '>>>']: 317 if line.startswith(prompt): 318 line = line[len(prompt):].lstrip() 319 break 320 return line 321 322 def parse_generators(line, start_index): 323 r"""Parse R.<a, b> in line[start_index:]. 324 325 Returns (modified_line, continue_index); you should resume parsing 326 modified_line[continue_index:]. 327 328 Support for generator construction syntax: 329 "obj.<gen0,gen1,...,genN> = objConstructor(...)" 330 is converted into 331 "obj = objConstructor(..., names=("gen0", "gen1", ..., "genN")); \ 332 (gen0, gen1, ..., genN,) = obj.gens()" 333 334 Also, obj.<gen0,gen1,...,genN> = R[interior] is converted into 335 "obj = R[interior]; (gen0, gen1, ..., genN,) = obj.gens()" 336 337 LIMITATIONS: 338 - The entire constructor *must* be on one line. 339 340 AUTHORS: 341 -- 2006-04-14: Joe Wetherell (jlwether@alum.mit.edu) 342 -- 2006-04-17: William Stein - improvements to allow multiple statements. 343 -- 2006-05-01: William -- fix bug that Joe found 344 -- 2006-10-31: William -- fix so obj doesn't have to be mutated 345 346 TESTS: 347 sage: from sage.misc.preparser import preparse 348 349 Vanilla: 350 351 sage: preparse("R.<x> = ZZ['x']") 352 "R = ZZ['x']; (x,) = R._first_ngens(Integer(1))" 353 sage: preparse("R.<x,y> = ZZ['x,y']") 354 "R = ZZ['x,y']; (x, y,) = R._first_ngens(Integer(2))" 355 356 No square brackets: 357 358 sage: preparse("R.<x> = PolynomialRing(ZZ, 'x')") 359 "R = PolynomialRing(ZZ, 'x',names=('x',)); (x,) = R._first_ngens(Integer(1))" 360 sage: preparse("R.<x,y> = PolynomialRing(ZZ, 'x,y')") 361 "R = PolynomialRing(ZZ, 'x,y',names=('x', 'y')); (x, y,) = R._first_ngens(Integer(2))" 362 363 Names filled in: 364 365 sage: preparse("R.<x> = ZZ[]") 366 "R = ZZ['x']; (x,) = R._first_ngens(Integer(1))" 367 sage: preparse("R.<x,y> = ZZ[]") 368 "R = ZZ['x, y']; (x, y,) = R._first_ngens(Integer(2))" 369 370 Names given not the same as generator names: 371 372 sage: preparse("R.<x> = ZZ['y']") 373 "R = ZZ['y']; (x,) = R._first_ngens(Integer(1))" 374 sage: preparse("R.<x,y> = ZZ['u,v']") 375 "R = ZZ['u,v']; (x, y,) = R._first_ngens(Integer(2))" 376 377 Number fields: 378 379 sage: preparse("K.<a> = QQ[2^(1/3)]") 380 'K = QQ[Integer(2)**(Integer(1)/Integer(3))]; (a,) = K._first_ngens(Integer(1))' 381 sage: preparse("K.<a, b> = QQ[2^(1/3), 2^(1/2)]") 382 'K = QQ[Integer(2)**(Integer(1)/Integer(3)), Integer(2)**(Integer(1)/Integer(2))]; (a, b,) = K._first_ngens(Integer(2))' 383 384 Just the .<> notation: 385 386 sage: preparse("R.<x> = ZZx") 387 'R = ZZx; (x,) = R._first_ngens(Integer(1))' 388 sage: preparse("R.<x, y> = a+b") 389 'R = a+b; (x, y,) = R._first_ngens(Integer(2))' 390 391 Ensure we don't eat too much: 392 393 sage: preparse("R.<x, y> = ZZ;2") 394 'R = ZZ; (x, y,) = R._first_ngens(Integer(2));Integer(2)' 395 sage: preparse("R.<x, y> = ZZ['x,y'];2") 396 "R = ZZ['x,y']; (x, y,) = R._first_ngens(Integer(2));Integer(2)" 397 """ 398 i = start_index 399 if not line.startswith(".<", i): 400 return (line, i) 401 try: 402 gen_end = line.index(">", i+2) 403 except ValueError: 404 # Syntax Error -- let Python notice and raise the error 405 i += 2 406 return (line, i) 407 408 gen_begin = i 409 while gen_begin > 0 and line[gen_begin-1] != ';': 410 gen_begin -= 1 411 412 # parse out the object name and the list of generator names 413 gen_obj = line[gen_begin:i].strip() 414 gen_list = [s.strip() for s in line[i+2:gen_end].split(',')] 415 for g in gen_list: 416 if (not g.isalnum() and not g.replace("_","").isalnum()) or len(g) == 0 or not g[0].isalpha(): 417 raise SyntaxError, "variable name (='%s') must be alpha-numeric and begin with a letter"%g 418 419 # format names as a list of strings and a list of variables 420 gen_names = tuple(gen_list) 421 gen_vars = ", ".join(gen_list) 422 423 # find end of constructor: 424 # either end of line, next semicolon, or next #. 425 line_after = line[gen_end:] 426 c = line_after.find('#') 427 if c==-1: c = len(line_after) 428 s = line_after.find(';') 429 if s==-1: s = len(line_after) 430 c = min(c,s) + gen_end 431 432 gens_assignment = '; (%s,) = %s._first_ngens(%s)' % (gen_vars, gen_obj, gen_vars.count(',')+1) 433 ring_assignment = "" 434 # Find where the parenthesis of the constructor ends 435 if line[:c].rstrip()[-1] == ']': 436 # brackets constructor 437 c0 = line[:c].find(']') 438 d0 = line[:c0].rfind('[') 439 if c0 == -1: 440 raise SyntaxError, 'constructor must end with ) or ]' 441 442 in_square_brackets = line[d0+1:c0] 443 if in_square_brackets.strip() == '': 444 # as a convenience to the user, 'K.<a> = ZZ[]' -> 'K.<a> = ZZ["a"]' 445 in_square_brackets = "'%s'" % gen_vars 446 447 ring_assignment = '%s%s%s' % (line[:i] + line[gen_end+1:d0+1], in_square_brackets, line[c0:c]) 448 elif line[:c].rstrip()[-1] == ')': 449 c0 = line[:c].rfind(')') 450 # General constructor -- rewrite the input line as two commands 451 # We have to determine whether or not to put a comma before 452 # the list of names. We do this only if there are already 453 # arguments to the constructor. Some constructors have no 454 # arguments, e.g., "K.<a> = f.root_field( )" 455 c1 = line[:c0].rfind('(') 456 in_parentheses = line[c1+1:c0].strip() 457 if len(in_parentheses) > 0: 458 sep = ',' 459 else: 460 sep = '' 461 ring_assignment = '%s%snames=%s)' % (line[:i] + line[gen_end+1:c0], sep, gen_names) 462 else: 463 ring_assignment = line[:i] + line[gen_end+1:c] 464 465 line = ring_assignment + gens_assignment + line[c:] 466 i += 1 467 468 return (line, i) 304 469 305 470 def preparse(line, reset=True, do_time=False, ignore_prompts=False): … … 376 541 377 542 if ignore_prompts: 378 # Get rid of leading sage: so that pasting of examples from543 # Get rid of leading sage: and >>> so that pasting of examples from 379 544 # the documentation works. 380 for prompt in ['sage:', '>>>']: 381 while True: 382 strip = False 383 if line[:3] == prompt: 384 line = line[3:].lstrip() 385 strip = True 386 elif line[:5] == prompt: 387 line = line[5:].lstrip() 388 strip = True 389 if not strip: 390 break 391 else: 392 line = line.lstrip() 545 line = strip_prompts(line) 393 546 394 547 while i < len(line): … … 472 625 # -- 2006-05-01: William -- fix bug that Joe found 473 626 # -- 2006-10-31: William -- fix so obj doesn't have to be mutated 474 elif (line[i:i+2] == ".<") and not in_quote(): 475 try: 476 gen_end = line.index(">", i+2) 477 except ValueError: 478 # Syntax Error -- let Python notice and raise the error 479 i += 2 480 continue 481 482 gen_begin = i 483 while gen_begin > 0 and line[gen_begin-1] != ';': 484 gen_begin -= 1 485 486 # parse out the object name and the list of generator names 487 gen_obj = line[gen_begin:i].strip() 488 gen_list = [s.strip() for s in line[i+2:gen_end].split(',')] 489 for g in gen_list: 490 if (not g.isalnum() and not g.replace("_","").isalnum()) or len(g) == 0 or not g[0].isalpha(): 491 raise SyntaxError, "variable name (='%s') must be alpha-numeric and begin with a letter"%g 492 493 # format names as a list of strings and a list of variables 494 gen_names = tuple(gen_list) 495 gen_vars = ", ".join(gen_list) 496 497 # find end of constructor: 498 # either end of line, next semicolon, or next #. 499 line_after = line[gen_end:] 500 c = line_after.find('#') 501 if c==-1: c = len(line_after) 502 s = line_after.find(';') 503 if s==-1: s = len(line_after) 504 c = min(c,s) + gen_end 505 506 # Find where the parenthesis of the constructor ends 507 if line[:c].rstrip()[-1] == ']': 508 # brackets constructor 509 c0 = line[:c].find(']') 510 d0 = line[:c0].rfind('[') 511 if c0 == -1: 512 raise SyntaxError, 'constructor must end with ) or ]' 513 line_new = '%s"%s"%s; (%s,) = %s._first_ngens(%s)'%( 514 line[:i] + line[gen_end+1:d0+1], gen_vars, 515 line[c0:c], gen_vars, gen_obj, gen_vars.count(',')+1) 516 else: 517 c0 = line[:c].rfind(')') 518 # General constructor -- rewrite the input line as two commands 519 # We have to determine whether or not to put a comma before 520 # the list of names. We do this only if there are already 521 # arguments to the constructor. Some constructors have no 522 # arguments, e.g., "K.<a> = f.root_field( )" 523 c1 = line[:c0].rfind('(') 524 if len(line[c1+1:c0].strip()) > 0: 525 sep = ',' 526 else: 527 sep = '' 528 529 line_new = '%s%snames=%s); (%s,) = %s._first_ngens(%s)'%( 530 line[:i] + line[gen_end+1:c0], sep, gen_names, 531 gen_vars, gen_obj, gen_vars.count(',')+1) 532 533 line = line_new + line[c:] 534 #i = len(line_new) 535 i += 1 536 537 continue 627 elif not in_quote() and (line[i:i+2] == ".<"): 628 line, i = parse_generators(line, i) 538 629 539 630 # Support for calculus-like function assignment, the line … … 690 781 return line 691 782 692 693 694 783 ###################################################### 695 784 ## Apply the preparser to an entire file
Note: See TracChangeset
for help on using the changeset viewer.
