passagemath-standard-no-symbolics 10.6.31rc3__cp314-cp314-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-standard-no-symbolics might be problematic. Click here for more details.

Files changed (82) hide show
  1. passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-grep +5 -0
  2. passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-grepdoc +5 -0
  3. passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-list-packages +103 -0
  4. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/METADATA +151 -0
  5. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/RECORD +82 -0
  6. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/WHEEL +6 -0
  7. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/top_level.txt +1 -0
  8. sage/all.py +207 -0
  9. sage/all_cmdline.py +36 -0
  10. sage/cli/__init__.py +61 -0
  11. sage/cli/__main__.py +5 -0
  12. sage/cli/eval_cmd.py +45 -0
  13. sage/cli/eval_cmd_test.py +25 -0
  14. sage/cli/interactive_shell_cmd.py +28 -0
  15. sage/cli/notebook_cmd.py +51 -0
  16. sage/cli/notebook_cmd_test.py +39 -0
  17. sage/cli/options.py +26 -0
  18. sage/cli/run_file_cmd.py +50 -0
  19. sage/cli/version_cmd.py +26 -0
  20. sage/databases/all.py +83 -0
  21. sage/databases/cubic_hecke_db.py +1527 -0
  22. sage/dynamics/all.py +31 -0
  23. sage/dynamics/surface_dynamics_deprecation.py +32 -0
  24. sage/ext_data/kenzo/CP2.txt +45 -0
  25. sage/ext_data/kenzo/CP3.txt +349 -0
  26. sage/ext_data/kenzo/CP4.txt +4774 -0
  27. sage/ext_data/kenzo/README.txt +49 -0
  28. sage/ext_data/kenzo/S4.txt +20 -0
  29. sage/ext_data/mwrank/PRIMES +1 -0
  30. sage/ext_data/nbconvert/postprocess.py +48 -0
  31. sage/ext_data/nbconvert/rst_sage.tpl +99 -0
  32. sage/ext_data/nodoctest +0 -0
  33. sage/ext_data/notebook-ipython/kernel.json.in +11 -0
  34. sage/ext_data/notebook-ipython/logo-64x64.png +0 -0
  35. sage/ext_data/notebook-ipython/logo.svg +352 -0
  36. sage/ext_data/valgrind/pyalloc.supp +58 -0
  37. sage/ext_data/valgrind/sage-additional.supp +417 -0
  38. sage/ext_data/valgrind/sage.supp +43 -0
  39. sage/ext_data/valgrind/valgrind-python.supp +480 -0
  40. sage/geometry/all.py +12 -0
  41. sage/groups/matrix_gps/pickling_overrides.py +110 -0
  42. sage/homology/tests.py +66 -0
  43. sage/interacts/algebra.py +20 -0
  44. sage/interacts/all.py +25 -0
  45. sage/interacts/calculus.py +24 -0
  46. sage/interacts/fractals.py +18 -0
  47. sage/interacts/geometry.py +19 -0
  48. sage/interacts/library.py +1950 -0
  49. sage/interacts/library_cython.cpython-314-darwin.so +0 -0
  50. sage/interacts/statistics.py +19 -0
  51. sage/interfaces/axiom.py +1002 -0
  52. sage/interfaces/kash.py +834 -0
  53. sage/interfaces/lie.py +950 -0
  54. sage/interfaces/matlab.py +413 -0
  55. sage/interfaces/mupad.py +686 -0
  56. sage/interfaces/octave.py +858 -0
  57. sage/interfaces/phc.py +943 -0
  58. sage/interfaces/psage.py +189 -0
  59. sage/interfaces/qsieve.py +4 -0
  60. sage/interfaces/r.py +2096 -0
  61. sage/interfaces/read_data.py +46 -0
  62. sage/interfaces/scilab.py +576 -0
  63. sage/interfaces/tests.py +81 -0
  64. sage/libs/all.py +11 -0
  65. sage/libs/cremona/__init__.py +0 -0
  66. sage/libs/mwrank/__init__.py +0 -0
  67. sage/logic/all.py +3 -0
  68. sage/logic/booleval.py +160 -0
  69. sage/logic/boolformula.py +1490 -0
  70. sage/logic/logic.py +856 -0
  71. sage/logic/logicparser.py +696 -0
  72. sage/logic/logictable.py +272 -0
  73. sage/logic/propcalc.py +311 -0
  74. sage/misc/all.py +28 -0
  75. sage/misc/lazy_attribute.pyi +11 -0
  76. sage/rings/all.py +48 -0
  77. sage/rings/commutative_algebra.py +38 -0
  78. sage/rings/finite_rings/all.py +21 -0
  79. sage/rings/numbers_abc.py +58 -0
  80. sage/rings/polynomial/all.py +22 -0
  81. sage/rings/polynomial/convolution.py +421 -0
  82. sage/symbolic/all__sagemath_standard_no_symbolics.py +0 -0
@@ -0,0 +1,696 @@
1
+ r"""
2
+ Module that creates and modifies parse trees of well formed boolean formulas.
3
+
4
+ A parse tree of a boolean formula is a nested list, where each branch is either
5
+ a single variable, or a formula composed of either two variables and a binary
6
+ operator or one variable and a unary operator. The function parse produces
7
+ a parse tree that is simplified for the purposes of more efficient truth value
8
+ evaluation. The function :func:`~sage.logic.logicparser.polish_parse()`
9
+ produces the full parse tree of a boolean formula which is used in functions
10
+ related to proof and inference. That is,
11
+ :func:`~sage.logic.logicparser.parse()` is meant to be used with functions
12
+ in the logic module that perform semantic operations on a boolean formula,
13
+ and :func:`~sage.logic.logicparser.polish_parse()` is to be used with
14
+ functions that perform syntactic operations on a boolean formula.
15
+
16
+ AUTHORS:
17
+
18
+ - Chris Gorecki (2007): initial version
19
+
20
+ - Paul Scurek (2013-08-01): added polish_parse, cleaned up python code,
21
+ updated docstring formatting
22
+
23
+ - Paul Scurek (2013-08-06): added
24
+ :func:`~sage.logic.logicparser.recover_formula()`,
25
+ :func:`~sage.logic.logicparser.recover_formula_internal()`,
26
+ :func:`~sage.logic.logicparser.prefix_to_infix()`,
27
+ :func:`~sage.logic.logicparser.to_infix_internal()`
28
+
29
+ - Paul Scurek (2013-08-08): added get_trees, error handling in polish_parse,
30
+ recover_formula_internal, and tree_parse
31
+
32
+ EXAMPLES:
33
+
34
+ Find the parse tree and variables of a string representation of a boolean
35
+ formula::
36
+
37
+ sage: import sage.logic.logicparser as logicparser
38
+ sage: s = 'a|b&c'
39
+ sage: t = logicparser.parse(s)
40
+ sage: t
41
+ (['|', 'a', ['&', 'b', 'c']], ['a', 'b', 'c'])
42
+
43
+ Find the full syntax parse tree of a string representation of a boolean
44
+ formula::
45
+
46
+ sage: import sage.logic.logicparser as logicparser
47
+ sage: s = '(a&b)->~~c'
48
+ sage: logicparser.polish_parse(s)
49
+ ['->', ['&', 'a', 'b'], ['~', ['~', 'c']]]
50
+
51
+ Find the tokens and distinct variables of a boolean formula::
52
+
53
+ sage: import sage.logic.logicparser as logicparser
54
+ sage: s = '~(a|~b)<->(c->c)'
55
+ sage: logicparser.tokenize(s)
56
+ (['(', '~', '(', 'a', '|', '~', 'b', ')', '<->', '(', 'c', '->', 'c', ')', ')'], ['a', 'b', 'c'])
57
+
58
+ Find the parse tree of a boolean formula from a list of the formula's tokens::
59
+
60
+ sage: import sage.logic.logicparser as logicparser
61
+ sage: t = ['(', 'a', '->', '~', 'c', ')']
62
+ sage: logicparser.tree_parse(t)
63
+ ['->', 'a', ['~', 'c', None]]
64
+ sage: r = ['(', '~', '~', 'a', '|', 'b', ')']
65
+ sage: logicparser.tree_parse(r)
66
+ ['|', 'a', 'b']
67
+
68
+ Find the full syntax parse tree of a boolean formula from a list of tokens::
69
+
70
+ sage: import sage.logic.logicparser as logicparser
71
+ sage: t = ['(', 'a', '->', '~', 'c', ')']
72
+ sage: logicparser.tree_parse(t, polish = True)
73
+ ['->', 'a', ['~', 'c']]
74
+ sage: r = ['(', '~', '~', 'a', '|', 'b', ')']
75
+ sage: logicparser.tree_parse(r, polish = True)
76
+ ['|', ['~', ['~', 'a']], 'b']
77
+ """
78
+ # ****************************************************************************
79
+ # Copyright (C) 2007 Chris Gorecki <chris.k.gorecki@gmail.com>
80
+ # Copyright (C) 2013 Paul Scurek <scurek86@gmail.com>
81
+ #
82
+ # Distributed under the terms of the GNU General Public License (GPL)
83
+ # as published by the Free Software Foundation; either version 2 of
84
+ # the License, or (at your option) any later version.
85
+ # https://www.gnu.org/licenses/
86
+ # ****************************************************************************
87
+
88
+ import string
89
+
90
+
91
+ __symbols = '()&|~<->^'
92
+ __op_list = ['~', '&', '|', '^', '->', '<->']
93
+
94
+
95
+ def parse(s):
96
+ r"""
97
+ Return a parse tree from a boolean formula ``s``.
98
+
99
+ INPUT:
100
+
101
+ - ``s`` -- string containing a boolean formula
102
+
103
+ OUTPUT:
104
+
105
+ A list containing the parse tree and a list containing the
106
+ variables in a boolean formula in this order:
107
+
108
+ 1. the list containing the parse tree
109
+ 2. the list containing the variables
110
+
111
+ EXAMPLES:
112
+
113
+ This example illustrates how to produce the parse tree of a boolean
114
+ formula ``s``::
115
+
116
+ sage: import sage.logic.logicparser as logicparser
117
+ sage: s = 'a|b&c'
118
+ sage: t = logicparser.parse(s)
119
+ sage: t
120
+ (['|', 'a', ['&', 'b', 'c']], ['a', 'b', 'c'])
121
+ """
122
+ toks, vars_order = tokenize(s)
123
+ tree = tree_parse(toks)
124
+ # special case of tree == single variable
125
+ if isinstance(tree, str):
126
+ return ['&', tree, tree], vars_order
127
+ return tree, vars_order
128
+
129
+
130
+ def polish_parse(s):
131
+ r"""
132
+ Return the full syntax parse tree from a boolean formula ``s``.
133
+
134
+ INPUT:
135
+
136
+ - ``s`` -- string containing a boolean expression
137
+
138
+ OUTPUT: the full syntax parse tree as a nested list
139
+
140
+ EXAMPLES:
141
+
142
+ This example illustrates how to find the full syntax parse tree
143
+ of a boolean formula::
144
+
145
+ sage: import sage.logic.logicparser as logicparser
146
+ sage: s = 'a|~~b'
147
+ sage: t = logicparser.polish_parse(s)
148
+ sage: t
149
+ ['|', 'a', ['~', ['~', 'b']]]
150
+
151
+ AUTHORS:
152
+
153
+ - Paul Scurek (2013-08-03)
154
+ """
155
+ if (s.count('(') != s.count(')')) or not s:
156
+ raise SyntaxError("malformed statement")
157
+
158
+ toks, vars_order = tokenize(s)
159
+ tree = tree_parse(toks, polish=True)
160
+ # special case where the formula s is a single variable
161
+ if isinstance(tree, str):
162
+ return vars_order
163
+ return tree
164
+
165
+
166
+ def get_trees(*statements):
167
+ r"""
168
+ Return the full syntax parse trees of the statements.
169
+
170
+ INPUT:
171
+
172
+ - ``*statements`` -- strings or :class:`BooleanFormula` instances
173
+
174
+ OUTPUT: the parse trees in a list
175
+
176
+ EXAMPLES:
177
+
178
+ This example illustrates finding the parse trees of multiple formulas.
179
+
180
+ ::
181
+
182
+ sage: import sage.logic.propcalc as propcalc
183
+ sage: import sage.logic.logicparser as logicparser
184
+ sage: f = propcalc.formula("((a|b)&~~c)")
185
+ sage: g = "a<->(~(c))"
186
+ sage: h = "~b"
187
+ sage: logicparser.get_trees(f, g, h)
188
+ [['&', ['|', 'a', 'b'], ['~', ['~', 'c']]],
189
+ ['<->', 'a', ['~', 'c']],
190
+ ['~', 'b']]
191
+
192
+ ::
193
+
194
+ sage: i = "(~q->p)"
195
+ sage: j = propcalc.formula("a")
196
+ sage: logicparser.get_trees(i, j)
197
+ [['->', ['~', 'q'], 'p'], ['a']]
198
+
199
+ ::
200
+
201
+ sage: k = "p"
202
+ sage: logicparser.get_trees(k)
203
+ [['p']]
204
+
205
+ AUTHORS:
206
+
207
+ - Paul Scurek (2013-08-06)
208
+ """
209
+ trees = []
210
+ from . import boolformula
211
+ for statement in statements:
212
+ if not isinstance(statement, boolformula.BooleanFormula):
213
+ try:
214
+ trees.append(polish_parse(statement))
215
+ except (NameError, SyntaxError):
216
+ raise SyntaxError("malformed statement")
217
+ else:
218
+ trees.append(statement.full_tree())
219
+ return trees
220
+
221
+
222
+ def recover_formula(prefix_tree):
223
+ r"""
224
+ Recover the formula from a parse tree in prefix form.
225
+
226
+ INPUT:
227
+
228
+ - ``prefix_tree`` -- list; this is a full syntax parse
229
+ tree in prefix form
230
+
231
+ OUTPUT: the formula as a string
232
+
233
+ EXAMPLES:
234
+
235
+ This example illustrates the recovery of a formula from a parse tree::
236
+
237
+ sage: import sage.logic.propcalc as propcalc
238
+ sage: import sage.logic.logicparser as logicparser
239
+ sage: t = ['->', ['&', 'a', ['~', ['~', 'c']]], ['~', ['|', ['~', 'c'], 'd']]]
240
+ sage: logicparser.recover_formula(t)
241
+ '(a&~~c)->~(~c|d)'
242
+
243
+ sage: f = propcalc.formula("a&(~~c|d)")
244
+ sage: logicparser.recover_formula(f.full_tree())
245
+ 'a&(~~c|d)'
246
+
247
+ sage: r = ['~', 'a']
248
+ sage: logicparser.recover_formula(r)
249
+ '~a'
250
+
251
+ sage: s = ['d']
252
+ sage: logicparser.recover_formula(s)
253
+ 'd'
254
+
255
+ .. NOTE::
256
+
257
+ The function :func:`~sage.logic.logicparser.polish_parse()` may be
258
+ passed as an argument, but :func:`~sage.logic.logicparser.tree_parse()`
259
+ may not unless the parameter ``polish`` is set to ``True``.
260
+
261
+ AUTHORS:
262
+
263
+ - Paul Scurek (2013-08-06)
264
+ """
265
+ formula = ''
266
+ if not isinstance(prefix_tree, list):
267
+ raise TypeError("the input must be a parse tree as a list")
268
+
269
+ formula = apply_func(prefix_tree, recover_formula_internal)
270
+ if prefix_tree[0] == '~' or len(prefix_tree) == 1:
271
+ return formula
272
+ return formula[1:-1]
273
+
274
+
275
+ def recover_formula_internal(prefix_tree):
276
+ r"""
277
+ Recover the formula from a parse tree in prefix form.
278
+
279
+ INPUT:
280
+
281
+ - ``prefix_tree`` -- list; this is a simple tree
282
+ with at most one operator in prefix form
283
+
284
+ OUTPUT: the formula as a string
285
+
286
+ EXAMPLES:
287
+
288
+ This example illustrates recovering the formula from a parse tree::
289
+
290
+ sage: import sage.logic.logicparser as logicparser
291
+ sage: import sage.logic.propcalc as propcalc
292
+ sage: t = ['->', 'a', 'b']
293
+ sage: logicparser.recover_formula_internal(t)
294
+ '(a->b)'
295
+
296
+ sage: r = ['~', 'c']
297
+ sage: logicparser.recover_formula_internal(r)
298
+ '~c'
299
+
300
+ sage: s = ['d']
301
+ sage: logicparser.recover_formula_internal(s)
302
+ 'd'
303
+
304
+ We can pass :func:`~sage.logic.logicparser.recover_formula_internal()`
305
+ as an argument in :func:`~sage.logic.logicparser.apply_func()`::
306
+
307
+ sage: f = propcalc.formula("~(d|c)<->(a&~~~c)")
308
+ sage: logicparser.apply_func(f.full_tree(), logicparser.recover_formula_internal)
309
+ '(~(d|c)<->(a&~~~c))'
310
+
311
+ .. NOTE::
312
+
313
+ This function is for internal use by :mod:`~sage.logic.logicparser`.
314
+ The function recovers the formula of a simple parse tree in prefix
315
+ form. A simple parse tree contains at most one operator.
316
+
317
+ The function :func:`~sage.logic.logicparser.polish_parse()` may be
318
+ passed as an argument, but :func:`~sage.logic.logicparser.tree_parse()`
319
+ may not unless the parameter ``polish`` is set to ``True``.
320
+
321
+ AUTHORS:
322
+
323
+ - Paul Scurek (2013-08-06)
324
+ """
325
+ from .propcalc import formula as propcalc_formula
326
+ if len(prefix_tree) == 3:
327
+ bool_formula = '(' + prefix_tree[1] + prefix_tree[0] + prefix_tree[2] + ')'
328
+ else:
329
+ bool_formula = ''.join(prefix_tree)
330
+
331
+ try:
332
+ bool_formula = propcalc_formula(bool_formula)
333
+ except (SyntaxError, NameError):
334
+ raise SyntaxError
335
+
336
+ return repr(bool_formula)
337
+
338
+
339
+ def prefix_to_infix(prefix_tree):
340
+ r"""
341
+ Convert a parse tree from prefix form to infix form.
342
+
343
+ INPUT:
344
+
345
+ - ``prefix_tree`` -- list; this is a full syntax parse
346
+ tree in prefix form
347
+
348
+ OUTPUT: list containing the tree in infix form
349
+
350
+ EXAMPLES:
351
+
352
+ This example illustrates converting a prefix tree to an infix tree::
353
+
354
+ sage: import sage.logic.logicparser as logicparser
355
+ sage: import sage.logic.propcalc as propcalc
356
+ sage: t = ['|', ['~', 'a'], ['&', 'b', 'c']]
357
+ sage: logicparser.prefix_to_infix(t)
358
+ [['~', 'a'], '|', ['b', '&', 'c']]
359
+
360
+ ::
361
+
362
+ sage: f = propcalc.formula("(a&~b)<->~~~(c|d)")
363
+ sage: logicparser.prefix_to_infix(f.full_tree())
364
+ [['a', '&', ['~', 'b']], '<->', ['~', ['~', ['~', ['c', '|', 'd']]]]]
365
+
366
+ .. NOTE::
367
+
368
+ The function :func:`~sage.logic.logicparser.polish_parse()` may be
369
+ passed as an argument, but :func:`~sage.logic.logicparser.tree_parse()`
370
+ may not unless the parameter ``polish`` is set to ``True``.
371
+
372
+ AUTHORS:
373
+
374
+ - Paul Scurek (2013-08-06)
375
+ """
376
+ if not isinstance(prefix_tree, list):
377
+ raise TypeError("the input must be a parse tree as a list")
378
+ return apply_func(prefix_tree, to_infix_internal)
379
+
380
+
381
+ def to_infix_internal(prefix_tree):
382
+ r"""
383
+ Convert a simple parse tree from prefix form to infix form.
384
+
385
+ INPUT:
386
+
387
+ - ``prefix_tree`` -- list; this is a simple parse tree
388
+ in prefix form with at most one operator
389
+
390
+ OUTPUT: the tree in infix form as a list
391
+
392
+ EXAMPLES:
393
+
394
+ This example illustrates converting a simple tree from prefix
395
+ to infix form::
396
+
397
+ sage: import sage.logic.logicparser as logicparser
398
+ sage: import sage.logic.propcalc as propcalc
399
+ sage: t = ['|', 'a', 'b']
400
+ sage: logicparser.to_infix_internal(t)
401
+ ['a', '|', 'b']
402
+
403
+ We can pass :func:`~sage.logic.logicparser.to_infix_internal()` as an
404
+ argument in :func:`~sage.logic.logicparser.apply_func()`::
405
+
406
+ sage: f = propcalc.formula("(a&~b)<->~~~(c|d)")
407
+ sage: logicparser.apply_func(f.full_tree(), logicparser.to_infix_internal)
408
+ [['a', '&', ['~', 'b']], '<->', ['~', ['~', ['~', ['c', '|', 'd']]]]]
409
+
410
+ .. NOTE::
411
+
412
+ This function is for internal use by :mod:`~sage.logic.logicparser`.
413
+ It converts a simple parse tree from prefix form to infix form. A
414
+ simple parse tree contains at most one operator.
415
+
416
+ The function :func:`polish_parse` may be passed as an argument,
417
+ but :func:`~sage.logic.logicparser.tree_parse()` may not unless the
418
+ parameter ``polish`` is set to ``True``.
419
+
420
+ AUTHORS:
421
+
422
+ - Paul Scurek (2013-08-06)
423
+ """
424
+ if prefix_tree[0] != '~' and len(prefix_tree) == 3:
425
+ return [prefix_tree[1], prefix_tree[0], prefix_tree[2]]
426
+ return prefix_tree
427
+
428
+
429
+ def tokenize(s):
430
+ r"""
431
+ Return the tokens and the distinct variables appearing in a boolean
432
+ formula ``s``.
433
+
434
+ INPUT:
435
+
436
+ - ``s`` -- string representation of a boolean formula
437
+
438
+ OUTPUT:
439
+
440
+ The tokens and variables as an ordered pair of lists in the following
441
+ order:
442
+
443
+ 1. A list containing the tokens of ``s``, in the order they appear in ``s``
444
+ 2. A list containing the distinct variables in ``s``, in the order
445
+ they appear in ``s``
446
+
447
+ EXAMPLES:
448
+
449
+ This example illustrates how to tokenize a string representation of a
450
+ boolean formula::
451
+
452
+ sage: import sage.logic.logicparser as logicparser
453
+ sage: s = 'a|b&c'
454
+ sage: t = logicparser.tokenize(s)
455
+ sage: t
456
+ (['(', 'a', '|', 'b', '&', 'c', ')'], ['a', 'b', 'c'])
457
+ """
458
+ i = 0
459
+ toks = ['(']
460
+ vars_order = []
461
+
462
+ while i < len(s):
463
+ tok = ""
464
+ skip = valid = 1
465
+ if s[i] in '()~&|^':
466
+ tok = s[i]
467
+ elif s[i:i + 2] == '->':
468
+ tok = '->'
469
+ skip = 2
470
+ elif s[i:i + 3] == '<->':
471
+ tok = '<->'
472
+ skip = 3
473
+ # check to see if '-', '<' or '>' are used incorrectly
474
+ elif s[i] in '<->':
475
+ raise SyntaxError("'{}' can only be used as part of the operators '<->' or '->'.".format(s[i]))
476
+
477
+ if len(tok) > 0:
478
+ toks.append(tok)
479
+ i += skip
480
+ continue
481
+
482
+ # token is a variable name
483
+ if s[i] == ' ':
484
+ i += 1
485
+ continue
486
+
487
+ while i < len(s) and s[i] not in __symbols and s[i] != ' ':
488
+ tok += s[i]
489
+ i += 1
490
+
491
+ if len(tok) > 0:
492
+ if tok[0] not in string.ascii_letters:
493
+ valid = 0
494
+ for c in tok:
495
+ if c not in string.ascii_letters and c not in string.digits and c != '_':
496
+ valid = 0
497
+
498
+ if valid == 1:
499
+ toks.append(tok)
500
+ if tok not in vars_order:
501
+ vars_order.append(tok)
502
+ else:
503
+ msg = "invalid variable name " + tok
504
+ msg += ": identifiers must begin with a letter and contain only "
505
+ msg += "alphanumerics and underscores"
506
+ raise NameError(msg)
507
+
508
+ toks.append(')')
509
+ return toks, vars_order
510
+
511
+
512
+ def tree_parse(toks, polish=False):
513
+ r"""
514
+ Return a parse tree from the tokens in ``toks``.
515
+
516
+ INPUT:
517
+
518
+ - ``toks`` -- list of tokens from a boolean formula
519
+
520
+ - ``polish`` -- boolean (default: ``False``); when ``True``,
521
+ :func:`~sage.logic.logicparser.tree_parse()` will return
522
+ the full syntax parse tree
523
+
524
+ OUTPUT:
525
+
526
+ A parse tree in the form of a nested list that depends on ``polish``
527
+ as follows:
528
+
529
+ - If ``False``, then return a simplified parse tree.
530
+
531
+ - If ``True``, then return the full syntax parse tree.
532
+
533
+ EXAMPLES:
534
+
535
+ This example illustrates the use of
536
+ :func:`~sage.logic.logicparser.tree_parse()` when ``polish`` is ``False``::
537
+
538
+ sage: import sage.logic.logicparser as logicparser
539
+ sage: t = ['(', 'a', '|', 'b', '&', 'c', ')']
540
+ sage: logicparser.tree_parse(t)
541
+ ['|', 'a', ['&', 'b', 'c']]
542
+
543
+ We now demonstrate the use of :func:`~sage.logic.logicparser.tree_parse()`
544
+ when ``polish`` is ``True``::
545
+
546
+ sage: t = ['(', 'a', '->', '~', '~', 'b', ')']
547
+ sage: logicparser.tree_parse(t)
548
+ ['->', 'a', 'b']
549
+ sage: t = ['(', 'a', '->', '~', '~', 'b', ')']
550
+ sage: logicparser.tree_parse(t, polish = True)
551
+ ['->', 'a', ['~', ['~', 'b']]]
552
+ """
553
+ if toks[1] in ['|', '&', '->', '<->', '^']:
554
+ raise SyntaxError
555
+
556
+ stack = []
557
+ for tok in toks:
558
+ stack.append(tok)
559
+ if tok == ')':
560
+ lrtoks = []
561
+ while tok != '(':
562
+ tok = stack.pop()
563
+ lrtoks.insert(0, tok)
564
+ branch = parse_ltor(lrtoks[1:-1], polish=polish)
565
+ stack.append(branch)
566
+ return stack[0]
567
+
568
+
569
+ def parse_ltor(toks, n=0, polish=False):
570
+ r"""
571
+ Return a parse tree from ``toks``, where each token in ``toks`` is atomic.
572
+
573
+ INPUT:
574
+
575
+ - ``toks`` -- list of tokens; each token is atomic
576
+
577
+ - ``n`` -- integer (default: 0) representing which order of
578
+ operations are occurring
579
+
580
+ - ``polish`` -- boolean (default: ``False``); when ``True``, double
581
+ negations are not cancelled and negated statements are turned into
582
+ list of length two
583
+
584
+ OUTPUT: the parse tree as a nested list that depends on ``polish`` as follows:
585
+
586
+ - If ``False``, then return a simplified parse tree.
587
+
588
+ - If ``True``, then return the full syntax parse tree.
589
+
590
+ EXAMPLES:
591
+
592
+ This example illustrates the use of
593
+ :func:`~sage.logic.logicparser.parse_ltor()` when ``polish`` is ``False``::
594
+
595
+ sage: import sage.logic.logicparser as logicparser
596
+ sage: t = ['a', '|', 'b', '&', 'c']
597
+ sage: logicparser.parse_ltor(t)
598
+ ['|', 'a', ['&', 'b', 'c']]
599
+
600
+ ::
601
+
602
+ sage: import sage.logic.logicparser as logicparser
603
+ sage: t = ['a', '->', '~', '~', 'b']
604
+ sage: logicparser.parse_ltor(t)
605
+ ['->', 'a', 'b']
606
+
607
+ We now repeat the previous example, but with ``polish`` being ``True``::
608
+
609
+ sage: import sage.logic.logicparser as logicparser
610
+ sage: t = ['a', '->', '~', '~', 'b']
611
+ sage: logicparser.parse_ltor(t, polish = True)
612
+ ['->', 'a', ['~', ['~', 'b']]]
613
+ """
614
+ i = 0
615
+ for tok in toks:
616
+ if tok == __op_list[n]:
617
+ if tok == '~':
618
+ if not polish:
619
+ # cancel double negations
620
+ if toks[i] == '~' and toks[i + 1] == '~':
621
+ del toks[i]
622
+ del toks[i]
623
+ return parse_ltor(toks, n)
624
+ args = [toks[i], toks[i + 1], None]
625
+ toks[i] = args
626
+ del toks[i + 1]
627
+ return parse_ltor(toks, n)
628
+ # This executes when creating the full syntax parse tree
629
+ else:
630
+ j = i
631
+ while toks[j] == '~':
632
+ j += 1
633
+ while j > i:
634
+ args = [toks[j - 1], toks[j]]
635
+ toks[j - 1] = args
636
+ del toks[j]
637
+ j -= 1
638
+ return parse_ltor(toks, n=n, polish=polish)
639
+ else:
640
+ args = [toks[i - 1], toks[i], toks[i + 1]]
641
+ toks[i - 1] = [args[1], args[0], args[2]]
642
+ del toks[i]
643
+ del toks[i]
644
+ return parse_ltor(toks, n)
645
+ i += 1
646
+ if n + 1 < len(__op_list):
647
+ return parse_ltor(toks, n + 1)
648
+ if len(toks) > 1:
649
+ raise SyntaxError
650
+ return toks[0]
651
+
652
+
653
+ def apply_func(tree, func):
654
+ r"""
655
+ Apply ``func`` to each node of ``tree``, and return a new parse tree.
656
+
657
+ INPUT:
658
+
659
+ - ``tree`` -- a parse tree of a boolean formula
660
+
661
+ - ``func`` -- a function to be applied to each node of tree; this may
662
+ be a function that comes from elsewhere in the logic module
663
+
664
+ OUTPUT: the new parse tree in the form of a nested list
665
+
666
+ EXAMPLES:
667
+
668
+ This example uses :func:`~sage.logic.logicparser.apply_func()` where
669
+ ``func`` switches two entries of tree::
670
+
671
+ sage: import sage.logic.logicparser as logicparser
672
+ sage: t = ['|', ['&', 'a', 'b'], ['&', 'a', 'c']]
673
+ sage: f = lambda t: [t[0], t[2], t[1]]
674
+ sage: logicparser.apply_func(t, f)
675
+ ['|', ['&', 'c', 'a'], ['&', 'b', 'a']]
676
+ """
677
+ # used when full syntax parse tree is passed as argument
678
+ if len(tree) == 1:
679
+ return func(tree)
680
+ # used when full syntax parse tree is passed as argument
681
+ elif len(tree) == 2:
682
+ rval = apply_func(tree[1], func)
683
+ return func([tree[0], rval])
684
+ elif isinstance(tree[1], list) and isinstance(tree[2], list):
685
+ lval = apply_func(tree[1], func)
686
+ rval = apply_func(tree[2], func)
687
+ elif isinstance(tree[1], list):
688
+ lval = apply_func(tree[1], func)
689
+ rval = tree[2]
690
+ elif isinstance(tree[2], list):
691
+ lval = tree[1]
692
+ rval = apply_func(tree[2], func)
693
+ else:
694
+ lval = tree[1]
695
+ rval = tree[2]
696
+ return func([tree[0], lval, rval])