passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.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.
- passagemath_categories-10.6.32.dist-info/METADATA +156 -0
- passagemath_categories-10.6.32.dist-info/RECORD +719 -0
- passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
- passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
- sage/all__sagemath_categories.py +28 -0
- sage/arith/all.py +38 -0
- sage/arith/constants.pxd +27 -0
- sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/functions.pxd +4 -0
- sage/arith/functions.pyx +221 -0
- sage/arith/misc.py +6552 -0
- sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/multi_modular.pxd +39 -0
- sage/arith/multi_modular.pyx +994 -0
- sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/rational_reconstruction.pxd +4 -0
- sage/arith/rational_reconstruction.pyx +115 -0
- sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/srange.pyx +571 -0
- sage/calculus/all__sagemath_categories.py +2 -0
- sage/calculus/functional.py +481 -0
- sage/calculus/functions.py +151 -0
- sage/categories/additive_groups.py +73 -0
- sage/categories/additive_magmas.py +1044 -0
- sage/categories/additive_monoids.py +114 -0
- sage/categories/additive_semigroups.py +184 -0
- sage/categories/affine_weyl_groups.py +238 -0
- sage/categories/algebra_ideals.py +95 -0
- sage/categories/algebra_modules.py +96 -0
- sage/categories/algebras.py +349 -0
- sage/categories/algebras_with_basis.py +377 -0
- sage/categories/all.py +160 -0
- sage/categories/aperiodic_semigroups.py +29 -0
- sage/categories/associative_algebras.py +47 -0
- sage/categories/bialgebras.py +101 -0
- sage/categories/bialgebras_with_basis.py +414 -0
- sage/categories/bimodules.py +206 -0
- sage/categories/chain_complexes.py +268 -0
- sage/categories/classical_crystals.py +480 -0
- sage/categories/coalgebras.py +405 -0
- sage/categories/coalgebras_with_basis.py +232 -0
- sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/coercion_methods.pyx +52 -0
- sage/categories/commutative_additive_groups.py +104 -0
- sage/categories/commutative_additive_monoids.py +45 -0
- sage/categories/commutative_additive_semigroups.py +48 -0
- sage/categories/commutative_algebra_ideals.py +87 -0
- sage/categories/commutative_algebras.py +94 -0
- sage/categories/commutative_ring_ideals.py +58 -0
- sage/categories/commutative_rings.py +736 -0
- sage/categories/complete_discrete_valuation.py +293 -0
- sage/categories/complex_reflection_groups.py +145 -0
- sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
- sage/categories/coxeter_group_algebras.py +186 -0
- sage/categories/coxeter_groups.py +3402 -0
- sage/categories/crystals.py +2628 -0
- sage/categories/cw_complexes.py +216 -0
- sage/categories/dedekind_domains.py +137 -0
- sage/categories/discrete_valuation.py +325 -0
- sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
- sage/categories/division_rings.py +114 -0
- sage/categories/domains.py +95 -0
- sage/categories/drinfeld_modules.py +789 -0
- sage/categories/dual.py +42 -0
- sage/categories/enumerated_sets.py +1146 -0
- sage/categories/euclidean_domains.py +271 -0
- sage/categories/examples/algebras_with_basis.py +102 -0
- sage/categories/examples/all.py +1 -0
- sage/categories/examples/commutative_additive_monoids.py +130 -0
- sage/categories/examples/commutative_additive_semigroups.py +199 -0
- sage/categories/examples/coxeter_groups.py +8 -0
- sage/categories/examples/crystals.py +236 -0
- sage/categories/examples/cw_complexes.py +163 -0
- sage/categories/examples/facade_sets.py +187 -0
- sage/categories/examples/filtered_algebras_with_basis.py +204 -0
- sage/categories/examples/filtered_modules_with_basis.py +154 -0
- sage/categories/examples/finite_coxeter_groups.py +252 -0
- sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
- sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
- sage/categories/examples/finite_enumerated_sets.py +208 -0
- sage/categories/examples/finite_monoids.py +150 -0
- sage/categories/examples/finite_semigroups.py +190 -0
- sage/categories/examples/finite_weyl_groups.py +191 -0
- sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
- sage/categories/examples/graded_modules_with_basis.py +168 -0
- sage/categories/examples/graphs.py +122 -0
- sage/categories/examples/hopf_algebras_with_basis.py +145 -0
- sage/categories/examples/infinite_enumerated_sets.py +190 -0
- sage/categories/examples/lie_algebras.py +352 -0
- sage/categories/examples/lie_algebras_with_basis.py +196 -0
- sage/categories/examples/magmas.py +162 -0
- sage/categories/examples/manifolds.py +94 -0
- sage/categories/examples/monoids.py +144 -0
- sage/categories/examples/posets.py +178 -0
- sage/categories/examples/semigroups.py +580 -0
- sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/examples/semigroups_cython.pyx +221 -0
- sage/categories/examples/semirings.py +249 -0
- sage/categories/examples/sets_cat.py +706 -0
- sage/categories/examples/sets_with_grading.py +101 -0
- sage/categories/examples/with_realizations.py +542 -0
- sage/categories/fields.py +991 -0
- sage/categories/filtered_algebras.py +63 -0
- sage/categories/filtered_algebras_with_basis.py +548 -0
- sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
- sage/categories/filtered_modules.py +210 -0
- sage/categories/filtered_modules_with_basis.py +1209 -0
- sage/categories/finite_complex_reflection_groups.py +1506 -0
- sage/categories/finite_coxeter_groups.py +1138 -0
- sage/categories/finite_crystals.py +103 -0
- sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
- sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
- sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
- sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
- sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
- sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
- sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
- sage/categories/finite_enumerated_sets.py +769 -0
- sage/categories/finite_fields.py +252 -0
- sage/categories/finite_groups.py +256 -0
- sage/categories/finite_lattice_posets.py +242 -0
- sage/categories/finite_monoids.py +316 -0
- sage/categories/finite_permutation_groups.py +339 -0
- sage/categories/finite_posets.py +1994 -0
- sage/categories/finite_semigroups.py +136 -0
- sage/categories/finite_sets.py +93 -0
- sage/categories/finite_weyl_groups.py +39 -0
- sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
- sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
- sage/categories/finitely_generated_magmas.py +57 -0
- sage/categories/finitely_generated_semigroups.py +214 -0
- sage/categories/function_fields.py +76 -0
- sage/categories/g_sets.py +77 -0
- sage/categories/gcd_domains.py +65 -0
- sage/categories/generalized_coxeter_groups.py +94 -0
- sage/categories/graded_algebras.py +85 -0
- sage/categories/graded_algebras_with_basis.py +258 -0
- sage/categories/graded_bialgebras.py +32 -0
- sage/categories/graded_bialgebras_with_basis.py +32 -0
- sage/categories/graded_coalgebras.py +65 -0
- sage/categories/graded_coalgebras_with_basis.py +51 -0
- sage/categories/graded_hopf_algebras.py +41 -0
- sage/categories/graded_hopf_algebras_with_basis.py +169 -0
- sage/categories/graded_lie_algebras.py +91 -0
- sage/categories/graded_lie_algebras_with_basis.py +44 -0
- sage/categories/graded_lie_conformal_algebras.py +74 -0
- sage/categories/graded_modules.py +133 -0
- sage/categories/graded_modules_with_basis.py +329 -0
- sage/categories/graphs.py +138 -0
- sage/categories/group_algebras.py +430 -0
- sage/categories/groupoid.py +94 -0
- sage/categories/groups.py +667 -0
- sage/categories/h_trivial_semigroups.py +64 -0
- sage/categories/hecke_modules.py +185 -0
- sage/categories/highest_weight_crystals.py +980 -0
- sage/categories/hopf_algebras.py +219 -0
- sage/categories/hopf_algebras_with_basis.py +309 -0
- sage/categories/infinite_enumerated_sets.py +115 -0
- sage/categories/integral_domains.py +203 -0
- sage/categories/j_trivial_semigroups.py +29 -0
- sage/categories/kac_moody_algebras.py +82 -0
- sage/categories/kahler_algebras.py +203 -0
- sage/categories/l_trivial_semigroups.py +63 -0
- sage/categories/lambda_bracket_algebras.py +280 -0
- sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
- sage/categories/lattice_posets.py +89 -0
- sage/categories/left_modules.py +49 -0
- sage/categories/lie_algebras.py +1070 -0
- sage/categories/lie_algebras_with_basis.py +261 -0
- sage/categories/lie_conformal_algebras.py +350 -0
- sage/categories/lie_conformal_algebras_with_basis.py +147 -0
- sage/categories/lie_groups.py +73 -0
- sage/categories/loop_crystals.py +1290 -0
- sage/categories/magmas.py +1189 -0
- sage/categories/magmas_and_additive_magmas.py +149 -0
- sage/categories/magmatic_algebras.py +365 -0
- sage/categories/manifolds.py +352 -0
- sage/categories/matrix_algebras.py +40 -0
- sage/categories/metric_spaces.py +387 -0
- sage/categories/modular_abelian_varieties.py +78 -0
- sage/categories/modules.py +989 -0
- sage/categories/modules_with_basis.py +2794 -0
- sage/categories/monoid_algebras.py +38 -0
- sage/categories/monoids.py +739 -0
- sage/categories/noetherian_rings.py +87 -0
- sage/categories/number_fields.py +242 -0
- sage/categories/ore_modules.py +189 -0
- sage/categories/partially_ordered_monoids.py +49 -0
- sage/categories/permutation_groups.py +63 -0
- sage/categories/pointed_sets.py +42 -0
- sage/categories/polyhedra.py +74 -0
- sage/categories/poor_man_map.py +270 -0
- sage/categories/posets.py +722 -0
- sage/categories/principal_ideal_domains.py +270 -0
- sage/categories/quantum_group_representations.py +543 -0
- sage/categories/quotient_fields.py +728 -0
- sage/categories/r_trivial_semigroups.py +45 -0
- sage/categories/regular_crystals.py +898 -0
- sage/categories/regular_supercrystals.py +170 -0
- sage/categories/right_modules.py +49 -0
- sage/categories/ring_ideals.py +74 -0
- sage/categories/rings.py +1904 -0
- sage/categories/rngs.py +175 -0
- sage/categories/schemes.py +393 -0
- sage/categories/semigroups.py +1060 -0
- sage/categories/semirings.py +71 -0
- sage/categories/semisimple_algebras.py +114 -0
- sage/categories/sets_with_grading.py +235 -0
- sage/categories/shephard_groups.py +43 -0
- sage/categories/signed_tensor.py +120 -0
- sage/categories/simplicial_complexes.py +134 -0
- sage/categories/simplicial_sets.py +1206 -0
- sage/categories/super_algebras.py +149 -0
- sage/categories/super_algebras_with_basis.py +144 -0
- sage/categories/super_hopf_algebras_with_basis.py +126 -0
- sage/categories/super_lie_conformal_algebras.py +193 -0
- sage/categories/super_modules.py +229 -0
- sage/categories/super_modules_with_basis.py +193 -0
- sage/categories/supercommutative_algebras.py +99 -0
- sage/categories/supercrystals.py +406 -0
- sage/categories/tensor.py +110 -0
- sage/categories/topological_spaces.py +170 -0
- sage/categories/triangular_kac_moody_algebras.py +439 -0
- sage/categories/tutorial.py +58 -0
- sage/categories/unique_factorization_domains.py +318 -0
- sage/categories/unital_algebras.py +426 -0
- sage/categories/vector_bundles.py +159 -0
- sage/categories/vector_spaces.py +357 -0
- sage/categories/weyl_groups.py +853 -0
- sage/combinat/all__sagemath_categories.py +34 -0
- sage/combinat/backtrack.py +180 -0
- sage/combinat/combinat.py +2269 -0
- sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/combinat_cython.pxd +6 -0
- sage/combinat/combinat_cython.pyx +390 -0
- sage/combinat/combination.py +796 -0
- sage/combinat/combinatorial_map.py +416 -0
- sage/combinat/composition.py +2192 -0
- sage/combinat/dlx.py +510 -0
- sage/combinat/integer_lists/__init__.py +7 -0
- sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/base.pxd +16 -0
- sage/combinat/integer_lists/base.pyx +713 -0
- sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/invlex.pxd +4 -0
- sage/combinat/integer_lists/invlex.pyx +1650 -0
- sage/combinat/integer_lists/lists.py +328 -0
- sage/combinat/integer_lists/nn.py +48 -0
- sage/combinat/integer_vector.py +1818 -0
- sage/combinat/integer_vector_weighted.py +413 -0
- sage/combinat/matrices/all__sagemath_categories.py +5 -0
- sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/matrices/dancing_links.pyx +1159 -0
- sage/combinat/matrices/dancing_links_c.h +380 -0
- sage/combinat/matrices/dlxcpp.py +136 -0
- sage/combinat/partition.py +10070 -0
- sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/partitions.pyx +743 -0
- sage/combinat/permutation.py +10168 -0
- sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/permutation_cython.pxd +11 -0
- sage/combinat/permutation_cython.pyx +407 -0
- sage/combinat/q_analogues.py +1090 -0
- sage/combinat/ranker.py +268 -0
- sage/combinat/subset.py +1561 -0
- sage/combinat/subsets_hereditary.py +202 -0
- sage/combinat/subsets_pairwise.py +184 -0
- sage/combinat/tools.py +63 -0
- sage/combinat/tuple.py +348 -0
- sage/data_structures/all.py +2 -0
- sage/data_structures/all__sagemath_categories.py +2 -0
- sage/data_structures/binary_matrix.pxd +138 -0
- sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/binary_search.pxd +3 -0
- sage/data_structures/binary_search.pyx +66 -0
- sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset.pxd +40 -0
- sage/data_structures/bitset.pyx +2385 -0
- sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset_base.pxd +926 -0
- sage/data_structures/bitset_base.pyx +117 -0
- sage/data_structures/bitset_intrinsics.h +487 -0
- sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/blas_dict.pxd +12 -0
- sage/data_structures/blas_dict.pyx +469 -0
- sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/list_of_pairs.pxd +16 -0
- sage/data_structures/list_of_pairs.pyx +122 -0
- sage/data_structures/mutable_poset.py +3312 -0
- sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/pairing_heap.h +346 -0
- sage/data_structures/pairing_heap.pxd +88 -0
- sage/data_structures/pairing_heap.pyx +1464 -0
- sage/data_structures/sparse_bitset.pxd +62 -0
- sage/data_structures/stream.py +5070 -0
- sage/databases/all__sagemath_categories.py +7 -0
- sage/databases/sql_db.py +2236 -0
- sage/ext/all__sagemath_categories.py +3 -0
- sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_callable.pxd +4 -0
- sage/ext/fast_callable.pyx +2746 -0
- sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_eval.pxd +1 -0
- sage/ext/fast_eval.pyx +102 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_categories.py +2 -0
- sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_el.pxd +18 -0
- sage/ext/interpreters/wrapper_el.pyx +148 -0
- sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_py.pxd +17 -0
- sage/ext/interpreters/wrapper_py.pyx +133 -0
- sage/functions/airy.py +937 -0
- sage/functions/all.py +97 -0
- sage/functions/bessel.py +2102 -0
- sage/functions/error.py +784 -0
- sage/functions/exp_integral.py +1529 -0
- sage/functions/gamma.py +1087 -0
- sage/functions/generalized.py +672 -0
- sage/functions/hyperbolic.py +747 -0
- sage/functions/hypergeometric.py +1156 -0
- sage/functions/jacobi.py +1705 -0
- sage/functions/log.py +1402 -0
- sage/functions/min_max.py +338 -0
- sage/functions/orthogonal_polys.py +3106 -0
- sage/functions/other.py +2303 -0
- sage/functions/piecewise.py +1505 -0
- sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/functions/prime_pi.pyx +262 -0
- sage/functions/special.py +1212 -0
- sage/functions/spike_function.py +278 -0
- sage/functions/transcendental.py +690 -0
- sage/functions/trig.py +1062 -0
- sage/functions/wigner.py +726 -0
- sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/geometry/abc.pyx +82 -0
- sage/geometry/all__sagemath_categories.py +1 -0
- sage/groups/all__sagemath_categories.py +11 -0
- sage/groups/generic.py +1733 -0
- sage/groups/groups_catalog.py +113 -0
- sage/groups/perm_gps/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/all.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
- sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
- sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
- sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
- sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
- sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
- sage/interfaces/abc.py +140 -0
- sage/interfaces/all.py +58 -0
- sage/interfaces/all__sagemath_categories.py +1 -0
- sage/interfaces/expect.py +1643 -0
- sage/interfaces/interface.py +1682 -0
- sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/process.pxd +5 -0
- sage/interfaces/process.pyx +288 -0
- sage/interfaces/quit.py +167 -0
- sage/interfaces/sage0.py +604 -0
- sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/sagespawn.pyx +308 -0
- sage/interfaces/tab_completion.py +101 -0
- sage/misc/all__sagemath_categories.py +78 -0
- sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/allocator.pxd +6 -0
- sage/misc/allocator.pyx +47 -0
- sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/binary_tree.pxd +29 -0
- sage/misc/binary_tree.pyx +537 -0
- sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/callable_dict.pyx +89 -0
- sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/citation.pyx +159 -0
- sage/misc/converting_dict.py +293 -0
- sage/misc/defaults.py +129 -0
- sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/derivative.pyx +223 -0
- sage/misc/functional.py +2005 -0
- sage/misc/html.py +589 -0
- sage/misc/latex.py +2673 -0
- sage/misc/latex_macros.py +236 -0
- sage/misc/latex_standalone.py +1833 -0
- sage/misc/map_threaded.py +38 -0
- sage/misc/mathml.py +76 -0
- sage/misc/method_decorator.py +88 -0
- sage/misc/mrange.py +755 -0
- sage/misc/multireplace.py +41 -0
- sage/misc/object_multiplexer.py +92 -0
- sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/parser.pyx +1107 -0
- sage/misc/random_testing.py +264 -0
- sage/misc/rest_index_of_methods.py +377 -0
- sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/search.pxd +2 -0
- sage/misc/search.pyx +68 -0
- sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/stopgap.pyx +95 -0
- sage/misc/table.py +853 -0
- sage/monoids/all__sagemath_categories.py +1 -0
- sage/monoids/indexed_free_monoid.py +1071 -0
- sage/monoids/monoid.py +82 -0
- sage/numerical/all__sagemath_categories.py +1 -0
- sage/numerical/backends/all__sagemath_categories.py +1 -0
- sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_backend.pxd +61 -0
- sage/numerical/backends/generic_backend.pyx +1893 -0
- sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_sdp_backend.pxd +38 -0
- sage/numerical/backends/generic_sdp_backend.pyx +755 -0
- sage/parallel/all.py +6 -0
- sage/parallel/decorate.py +575 -0
- sage/parallel/map_reduce.py +1997 -0
- sage/parallel/multiprocessing_sage.py +76 -0
- sage/parallel/ncpus.py +35 -0
- sage/parallel/parallelism.py +364 -0
- sage/parallel/reference.py +47 -0
- sage/parallel/use_fork.py +333 -0
- sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/abc.pxd +31 -0
- sage/rings/abc.pyx +526 -0
- sage/rings/algebraic_closure_finite_field.py +1154 -0
- sage/rings/all__sagemath_categories.py +91 -0
- sage/rings/big_oh.py +227 -0
- sage/rings/continued_fraction.py +2754 -0
- sage/rings/continued_fraction_gosper.py +220 -0
- sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/factorint.pyx +295 -0
- sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fast_arith.pxd +21 -0
- sage/rings/fast_arith.pyx +535 -0
- sage/rings/finite_rings/all__sagemath_categories.py +9 -0
- sage/rings/finite_rings/conway_polynomials.py +542 -0
- sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_base.pxd +12 -0
- sage/rings/finite_rings/element_base.pyx +1176 -0
- sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/finite_field_base.pxd +7 -0
- sage/rings/finite_rings/finite_field_base.pyx +2171 -0
- sage/rings/finite_rings/finite_field_constructor.py +827 -0
- sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
- sage/rings/finite_rings/galois_group.py +154 -0
- sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field.pxd +23 -0
- sage/rings/finite_rings/hom_finite_field.pyx +856 -0
- sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
- sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
- sage/rings/finite_rings/homset.py +357 -0
- sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/integer_mod.pxd +56 -0
- sage/rings/finite_rings/integer_mod.pyx +4586 -0
- sage/rings/finite_rings/integer_mod_limits.h +11 -0
- sage/rings/finite_rings/integer_mod_ring.py +2044 -0
- sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field.pxd +30 -0
- sage/rings/finite_rings/residue_field.pyx +1811 -0
- sage/rings/finite_rings/stdint.pxd +19 -0
- sage/rings/fraction_field.py +1452 -0
- sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fraction_field_element.pyx +1357 -0
- sage/rings/function_field/all.py +7 -0
- sage/rings/function_field/all__sagemath_categories.py +2 -0
- sage/rings/function_field/constructor.py +218 -0
- sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element.pxd +11 -0
- sage/rings/function_field/element.pyx +1008 -0
- sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element_rational.pyx +513 -0
- sage/rings/function_field/extensions.py +230 -0
- sage/rings/function_field/function_field.py +1468 -0
- sage/rings/function_field/function_field_rational.py +1005 -0
- sage/rings/function_field/ideal.py +1155 -0
- sage/rings/function_field/ideal_rational.py +629 -0
- sage/rings/function_field/jacobian_base.py +826 -0
- sage/rings/function_field/jacobian_hess.py +1053 -0
- sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
- sage/rings/function_field/maps.py +1039 -0
- sage/rings/function_field/order.py +281 -0
- sage/rings/function_field/order_basis.py +586 -0
- sage/rings/function_field/order_rational.py +576 -0
- sage/rings/function_field/place.py +426 -0
- sage/rings/function_field/place_rational.py +181 -0
- sage/rings/generic.py +320 -0
- sage/rings/homset.py +332 -0
- sage/rings/ideal.py +1885 -0
- sage/rings/ideal_monoid.py +215 -0
- sage/rings/infinity.py +1890 -0
- sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer.pxd +45 -0
- sage/rings/integer.pyx +7874 -0
- sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer_ring.pxd +8 -0
- sage/rings/integer_ring.pyx +1693 -0
- sage/rings/laurent_series_ring.py +931 -0
- sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/laurent_series_ring_element.pxd +11 -0
- sage/rings/laurent_series_ring_element.pyx +1927 -0
- sage/rings/lazy_series.py +7815 -0
- sage/rings/lazy_series_ring.py +4356 -0
- sage/rings/localization.py +1043 -0
- sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/morphism.pxd +39 -0
- sage/rings/morphism.pyx +3299 -0
- sage/rings/multi_power_series_ring.py +1145 -0
- sage/rings/multi_power_series_ring_element.py +2184 -0
- sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/noncommutative_ideals.pyx +423 -0
- sage/rings/number_field/all__sagemath_categories.py +1 -0
- sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_base.pxd +8 -0
- sage/rings/number_field/number_field_base.pyx +507 -0
- sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_element_base.pxd +6 -0
- sage/rings/number_field/number_field_element_base.pyx +36 -0
- sage/rings/number_field/number_field_ideal.py +3550 -0
- sage/rings/padics/all__sagemath_categories.py +4 -0
- sage/rings/padics/local_generic.py +1670 -0
- sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/local_generic_element.pxd +5 -0
- sage/rings/padics/local_generic_element.pyx +1017 -0
- sage/rings/padics/misc.py +256 -0
- sage/rings/padics/padic_generic.py +1911 -0
- sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer.pxd +38 -0
- sage/rings/padics/pow_computer.pyx +671 -0
- sage/rings/padics/precision_error.py +24 -0
- sage/rings/polynomial/all__sagemath_categories.py +25 -0
- sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/commutative_polynomial.pxd +6 -0
- sage/rings/polynomial/commutative_polynomial.pyx +24 -0
- sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/cyclotomic.pyx +404 -0
- sage/rings/polynomial/flatten.py +711 -0
- sage/rings/polynomial/ideal.py +102 -0
- sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
- sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
- sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial.pxd +18 -0
- sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
- sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
- sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
- sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
- sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial.pxd +12 -0
- sage/rings/polynomial/multi_polynomial.pyx +3082 -0
- sage/rings/polynomial/multi_polynomial_element.py +2570 -0
- sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
- sage/rings/polynomial/multi_polynomial_ring.py +947 -0
- sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
- sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
- sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polydict.pxd +45 -0
- sage/rings/polynomial/polydict.pyx +2701 -0
- sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_compiled.pxd +59 -0
- sage/rings/polynomial/polynomial_compiled.pyx +509 -0
- sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_element.pxd +64 -0
- sage/rings/polynomial/polynomial_element.pyx +13255 -0
- sage/rings/polynomial/polynomial_element_generic.py +1637 -0
- sage/rings/polynomial/polynomial_fateman.py +97 -0
- sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
- sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
- sage/rings/polynomial/polynomial_ring.py +3784 -0
- sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
- sage/rings/polynomial/polynomial_singular_interface.py +549 -0
- sage/rings/polynomial/symmetric_ideal.py +989 -0
- sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/symmetric_reduction.pxd +8 -0
- sage/rings/polynomial/symmetric_reduction.pyx +669 -0
- sage/rings/polynomial/term_order.py +2279 -0
- sage/rings/polynomial/toy_buchberger.py +449 -0
- sage/rings/polynomial/toy_d_basis.py +387 -0
- sage/rings/polynomial/toy_variety.py +362 -0
- sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_mpoly.pxd +9 -0
- sage/rings/power_series_mpoly.pyx +161 -0
- sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_poly.pxd +10 -0
- sage/rings/power_series_poly.pyx +1317 -0
- sage/rings/power_series_ring.py +1441 -0
- sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_ring_element.pxd +12 -0
- sage/rings/power_series_ring_element.pyx +3028 -0
- sage/rings/puiseux_series_ring.py +487 -0
- sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/puiseux_series_ring_element.pxd +7 -0
- sage/rings/puiseux_series_ring_element.pyx +1055 -0
- sage/rings/qqbar_decorators.py +167 -0
- sage/rings/quotient_ring.py +1598 -0
- sage/rings/quotient_ring_element.py +979 -0
- sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/rational.pxd +20 -0
- sage/rings/rational.pyx +4284 -0
- sage/rings/rational_field.py +1730 -0
- sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_double.pxd +16 -0
- sage/rings/real_double.pyx +2218 -0
- sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_lazy.pxd +30 -0
- sage/rings/real_lazy.pyx +1773 -0
- sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/ring.pxd +30 -0
- sage/rings/ring.pyx +850 -0
- sage/rings/semirings/all.py +3 -0
- sage/rings/semirings/non_negative_integer_semiring.py +107 -0
- sage/rings/semirings/tropical_mpolynomial.py +972 -0
- sage/rings/semirings/tropical_polynomial.py +997 -0
- sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/semirings/tropical_semiring.pyx +676 -0
- sage/rings/semirings/tropical_variety.py +1701 -0
- sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/sum_of_squares.pxd +3 -0
- sage/rings/sum_of_squares.pyx +336 -0
- sage/rings/tests.py +504 -0
- sage/schemes/affine/affine_homset.py +508 -0
- sage/schemes/affine/affine_morphism.py +1574 -0
- sage/schemes/affine/affine_point.py +460 -0
- sage/schemes/affine/affine_rational_point.py +308 -0
- sage/schemes/affine/affine_space.py +1264 -0
- sage/schemes/affine/affine_subscheme.py +592 -0
- sage/schemes/affine/all.py +25 -0
- sage/schemes/all__sagemath_categories.py +5 -0
- sage/schemes/generic/algebraic_scheme.py +2092 -0
- sage/schemes/generic/all.py +5 -0
- sage/schemes/generic/ambient_space.py +400 -0
- sage/schemes/generic/divisor.py +465 -0
- sage/schemes/generic/divisor_group.py +313 -0
- sage/schemes/generic/glue.py +84 -0
- sage/schemes/generic/homset.py +820 -0
- sage/schemes/generic/hypersurface.py +234 -0
- sage/schemes/generic/morphism.py +2107 -0
- sage/schemes/generic/point.py +237 -0
- sage/schemes/generic/scheme.py +1190 -0
- sage/schemes/generic/spec.py +199 -0
- sage/schemes/product_projective/all.py +6 -0
- sage/schemes/product_projective/homset.py +236 -0
- sage/schemes/product_projective/morphism.py +517 -0
- sage/schemes/product_projective/point.py +568 -0
- sage/schemes/product_projective/rational_point.py +550 -0
- sage/schemes/product_projective/space.py +1301 -0
- sage/schemes/product_projective/subscheme.py +466 -0
- sage/schemes/projective/all.py +24 -0
- sage/schemes/projective/proj_bdd_height.py +453 -0
- sage/schemes/projective/projective_homset.py +718 -0
- sage/schemes/projective/projective_morphism.py +2792 -0
- sage/schemes/projective/projective_point.py +1484 -0
- sage/schemes/projective/projective_rational_point.py +569 -0
- sage/schemes/projective/projective_space.py +2571 -0
- sage/schemes/projective/projective_subscheme.py +1574 -0
- sage/sets/all.py +17 -0
- sage/sets/cartesian_product.py +376 -0
- sage/sets/condition_set.py +525 -0
- sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/disjoint_set.pxd +36 -0
- sage/sets/disjoint_set.pyx +998 -0
- sage/sets/disjoint_union_enumerated_sets.py +625 -0
- sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/family.pxd +12 -0
- sage/sets/family.pyx +1556 -0
- sage/sets/finite_enumerated_set.py +406 -0
- sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/finite_set_map_cy.pxd +34 -0
- sage/sets/finite_set_map_cy.pyx +708 -0
- sage/sets/finite_set_maps.py +591 -0
- sage/sets/image_set.py +448 -0
- sage/sets/integer_range.py +829 -0
- sage/sets/non_negative_integers.py +241 -0
- sage/sets/positive_integers.py +93 -0
- sage/sets/primes.py +188 -0
- sage/sets/real_set.py +2760 -0
- sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/recursively_enumerated_set.pxd +31 -0
- sage/sets/recursively_enumerated_set.pyx +2082 -0
- sage/sets/set.py +2083 -0
- sage/sets/set_from_iterator.py +1021 -0
- sage/sets/totally_ordered_finite_set.py +329 -0
- sage/symbolic/all__sagemath_categories.py +1 -0
- sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/function.pxd +29 -0
- sage/symbolic/function.pyx +1488 -0
- sage/symbolic/symbols.py +56 -0
- sage/tests/all__sagemath_categories.py +1 -0
- sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/cython.pyx +37 -0
- sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/stl_vector.pyx +171 -0
- sage/typeset/all.py +6 -0
- sage/typeset/ascii_art.py +295 -0
- sage/typeset/character_art.py +789 -0
- sage/typeset/character_art_factory.py +572 -0
- sage/typeset/symbols.py +334 -0
- sage/typeset/unicode_art.py +183 -0
- sage/typeset/unicode_characters.py +101 -0
sage/misc/parser.pyx
ADDED
|
@@ -0,0 +1,1107 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
"""
|
|
3
|
+
A parser for symbolic equations and expressions
|
|
4
|
+
|
|
5
|
+
It is both safer and more powerful than using Python's eval, as one has
|
|
6
|
+
complete control over what names are used (including dynamically creating
|
|
7
|
+
variables) and how integer and floating point literals are created.
|
|
8
|
+
|
|
9
|
+
AUTHOR:
|
|
10
|
+
|
|
11
|
+
- Robert Bradshaw 2008-04 (initial version)
|
|
12
|
+
"""
|
|
13
|
+
# ***************************************************************************
|
|
14
|
+
# Copyright (C) 2008 Robert Bradshaw <robertwb@math.washington.edu>
|
|
15
|
+
#
|
|
16
|
+
# This program is free software: you can redistribute it and/or modify
|
|
17
|
+
# it under the terms of the GNU General Public License as published by
|
|
18
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
19
|
+
# (at your option) any later version.
|
|
20
|
+
# https://www.gnu.org/licenses/
|
|
21
|
+
# ***************************************************************************
|
|
22
|
+
|
|
23
|
+
from cpython.list cimport PyList_Append
|
|
24
|
+
|
|
25
|
+
import math
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def foo(*args, **kwds):
|
|
29
|
+
"""
|
|
30
|
+
This is a function for testing that simply returns the arguments and
|
|
31
|
+
keywords passed into it.
|
|
32
|
+
|
|
33
|
+
EXAMPLES::
|
|
34
|
+
|
|
35
|
+
sage: from sage.misc.parser import foo
|
|
36
|
+
sage: foo(1, 2, a=3)
|
|
37
|
+
((1, 2), {'a': 3})
|
|
38
|
+
"""
|
|
39
|
+
return args, kwds
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
function_map = {
|
|
43
|
+
'foo': foo,
|
|
44
|
+
'sqrt': math.sqrt,
|
|
45
|
+
'sin': math.sin,
|
|
46
|
+
'cos': math.cos,
|
|
47
|
+
'tan': math.tan,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
cdef enum token_types:
|
|
52
|
+
# leave room for ASCII character tokens such as '+'
|
|
53
|
+
INT = 128
|
|
54
|
+
FLOAT
|
|
55
|
+
NAME
|
|
56
|
+
EOS
|
|
57
|
+
ERROR
|
|
58
|
+
|
|
59
|
+
LESS_EQ
|
|
60
|
+
GREATER_EQ
|
|
61
|
+
NOT_EQ
|
|
62
|
+
MATRIX
|
|
63
|
+
|
|
64
|
+
enum_map = {
|
|
65
|
+
INT: 'INT',
|
|
66
|
+
FLOAT: 'FLOAT',
|
|
67
|
+
NAME: 'NAME',
|
|
68
|
+
EOS: 'EOS',
|
|
69
|
+
ERROR: 'ERROR',
|
|
70
|
+
LESS_EQ: 'LESS_EQ',
|
|
71
|
+
GREATER_EQ: 'GREATER_EQ',
|
|
72
|
+
NOT_EQ: 'NOT_EQ',
|
|
73
|
+
MATRIX: 'MATRIX',
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def token_to_str(int token):
|
|
78
|
+
"""
|
|
79
|
+
For speed reasons, tokens are integers. This function returns a string
|
|
80
|
+
representation of a given token.
|
|
81
|
+
|
|
82
|
+
EXAMPLES::
|
|
83
|
+
|
|
84
|
+
sage: from sage.misc.parser import Tokenizer, token_to_str
|
|
85
|
+
sage: t = Tokenizer("+ 2")
|
|
86
|
+
sage: token_to_str(t.next())
|
|
87
|
+
'+'
|
|
88
|
+
sage: token_to_str(t.next())
|
|
89
|
+
'INT'
|
|
90
|
+
"""
|
|
91
|
+
try:
|
|
92
|
+
return enum_map[token]
|
|
93
|
+
except KeyError:
|
|
94
|
+
return chr(token)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
cdef inline bint is_alphanumeric(c) noexcept:
|
|
98
|
+
return c.isalnum() or c == '_'
|
|
99
|
+
|
|
100
|
+
cdef inline bint is_whitespace(c) noexcept:
|
|
101
|
+
return c.isspace()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
cdef class Tokenizer:
|
|
105
|
+
cdef str s
|
|
106
|
+
cdef int token
|
|
107
|
+
cdef int pos
|
|
108
|
+
cdef int last_pos
|
|
109
|
+
|
|
110
|
+
def __init__(self, s):
|
|
111
|
+
r"""
|
|
112
|
+
This class takes a string and turns it into a list of tokens for use
|
|
113
|
+
by the parser.
|
|
114
|
+
|
|
115
|
+
The tokenizer wraps a string object, to tokenize a different string
|
|
116
|
+
create a new tokenizer.
|
|
117
|
+
|
|
118
|
+
EXAMPLES::
|
|
119
|
+
|
|
120
|
+
sage: from sage.misc.parser import Tokenizer
|
|
121
|
+
sage: Tokenizer("1.5+2*3^4-sin(x)").test()
|
|
122
|
+
['FLOAT(1.5)', '+', 'INT(2)', '*', 'INT(3)', '^', 'INT(4)', '-', 'NAME(sin)', '(', 'NAME(x)', ')']
|
|
123
|
+
|
|
124
|
+
The single character tokens are given by::
|
|
125
|
+
|
|
126
|
+
sage: Tokenizer("+-*/^(),=<>[]{}").test()
|
|
127
|
+
['+', '-', '*', '/', '^', '(', ')', ',', '=', '<', '>', '[', ']', '{', '}']
|
|
128
|
+
|
|
129
|
+
Two-character comparisons accepted are::
|
|
130
|
+
|
|
131
|
+
sage: Tokenizer("<= >= != == **").test()
|
|
132
|
+
['LESS_EQ', 'GREATER_EQ', 'NOT_EQ', '=', '^']
|
|
133
|
+
|
|
134
|
+
Integers are strings of 0-9::
|
|
135
|
+
|
|
136
|
+
sage: Tokenizer("1 123 9879834759873452908375013").test()
|
|
137
|
+
['INT(1)', 'INT(123)', 'INT(9879834759873452908375013)']
|
|
138
|
+
|
|
139
|
+
Floating point numbers can contain a single decimal point and possibly exponential notation::
|
|
140
|
+
|
|
141
|
+
sage: Tokenizer("1. .01 1e3 1.e-3").test()
|
|
142
|
+
['FLOAT(1.)', 'FLOAT(.01)', 'FLOAT(1e3)', 'FLOAT(1.e-3)']
|
|
143
|
+
|
|
144
|
+
Note that negative signs are not attached to the token::
|
|
145
|
+
|
|
146
|
+
sage: Tokenizer("-1 -1.2").test()
|
|
147
|
+
['-', 'INT(1)', '-', 'FLOAT(1.2)']
|
|
148
|
+
|
|
149
|
+
Names are alphanumeric sequences not starting with a digit::
|
|
150
|
+
|
|
151
|
+
sage: Tokenizer("a a1 _a_24").test()
|
|
152
|
+
['NAME(a)', 'NAME(a1)', 'NAME(_a_24)']
|
|
153
|
+
|
|
154
|
+
There is special handling for matrices::
|
|
155
|
+
|
|
156
|
+
sage: Tokenizer("matrix(a)").test()
|
|
157
|
+
['MATRIX', '(', 'NAME(a)', ')']
|
|
158
|
+
|
|
159
|
+
Anything else is an error::
|
|
160
|
+
|
|
161
|
+
sage: Tokenizer("&@~").test()
|
|
162
|
+
['ERROR', 'ERROR', 'ERROR']
|
|
163
|
+
|
|
164
|
+
No attempt for correctness is made at this stage::
|
|
165
|
+
|
|
166
|
+
sage: Tokenizer(") )( 5e5e5").test()
|
|
167
|
+
[')', ')', '(', 'FLOAT(5e5)', 'NAME(e5)']
|
|
168
|
+
sage: Tokenizer("?$%").test()
|
|
169
|
+
['ERROR', 'ERROR', 'ERROR']
|
|
170
|
+
|
|
171
|
+
TESTS:
|
|
172
|
+
|
|
173
|
+
Check support for unicode characters (:issue:`29280`)::
|
|
174
|
+
|
|
175
|
+
sage: Tokenizer("λ+α_β0 Γ^ω").test()
|
|
176
|
+
['NAME(λ)', '+', 'NAME(α_β0)', 'NAME(Γ)', '^', 'NAME(ω)']
|
|
177
|
+
"""
|
|
178
|
+
self.pos = 0
|
|
179
|
+
self.last_pos = 0
|
|
180
|
+
self.s = s
|
|
181
|
+
|
|
182
|
+
def test(self):
|
|
183
|
+
"""
|
|
184
|
+
This is a utility function for easy testing of the tokenizer.
|
|
185
|
+
|
|
186
|
+
Destructively read off the tokens in self, returning a list of string
|
|
187
|
+
representations of the tokens.
|
|
188
|
+
|
|
189
|
+
EXAMPLES::
|
|
190
|
+
|
|
191
|
+
sage: from sage.misc.parser import Tokenizer
|
|
192
|
+
sage: t = Tokenizer("a b 3")
|
|
193
|
+
sage: t.test()
|
|
194
|
+
['NAME(a)', 'NAME(b)', 'INT(3)']
|
|
195
|
+
sage: t.test()
|
|
196
|
+
[]
|
|
197
|
+
"""
|
|
198
|
+
all = []
|
|
199
|
+
cdef int token = self.next()
|
|
200
|
+
while token != EOS:
|
|
201
|
+
if token in [INT, FLOAT, NAME]:
|
|
202
|
+
all.append("%s(%s)" % (token_to_str(token), self.last_token_string()))
|
|
203
|
+
else:
|
|
204
|
+
all.append(token_to_str(token))
|
|
205
|
+
token = self.next()
|
|
206
|
+
return all
|
|
207
|
+
|
|
208
|
+
cpdef reset(self, int pos=0):
|
|
209
|
+
"""
|
|
210
|
+
Reset the tokenizer to a given position.
|
|
211
|
+
|
|
212
|
+
EXAMPLES::
|
|
213
|
+
|
|
214
|
+
sage: from sage.misc.parser import Tokenizer
|
|
215
|
+
sage: t = Tokenizer("a+b*c")
|
|
216
|
+
sage: t.test()
|
|
217
|
+
['NAME(a)', '+', 'NAME(b)', '*', 'NAME(c)']
|
|
218
|
+
sage: t.test()
|
|
219
|
+
[]
|
|
220
|
+
sage: t.reset()
|
|
221
|
+
sage: t.test()
|
|
222
|
+
['NAME(a)', '+', 'NAME(b)', '*', 'NAME(c)']
|
|
223
|
+
sage: t.reset(3)
|
|
224
|
+
sage: t.test()
|
|
225
|
+
['*', 'NAME(c)']
|
|
226
|
+
|
|
227
|
+
No care is taken to make sure we don't jump in the middle of a token::
|
|
228
|
+
|
|
229
|
+
sage: t = Tokenizer("12345+a")
|
|
230
|
+
sage: t.test()
|
|
231
|
+
['INT(12345)', '+', 'NAME(a)']
|
|
232
|
+
sage: t.reset(2)
|
|
233
|
+
sage: t.test()
|
|
234
|
+
['INT(345)', '+', 'NAME(a)']
|
|
235
|
+
"""
|
|
236
|
+
self.pos = self.last_pos = pos
|
|
237
|
+
|
|
238
|
+
cdef int find(self) except -1:
|
|
239
|
+
"""
|
|
240
|
+
This function actually does all the work, and is extensively tested
|
|
241
|
+
above.
|
|
242
|
+
"""
|
|
243
|
+
cdef bint seen_exp, seen_decimal
|
|
244
|
+
cdef int type
|
|
245
|
+
cdef str s = self.s
|
|
246
|
+
cdef int pos = self.pos
|
|
247
|
+
cdef int s_len = len(s)
|
|
248
|
+
|
|
249
|
+
# skip whitespace
|
|
250
|
+
if pos < s_len and is_whitespace(s[pos]):
|
|
251
|
+
while pos < s_len and is_whitespace(s[pos]):
|
|
252
|
+
pos += 1
|
|
253
|
+
self.pos = pos
|
|
254
|
+
|
|
255
|
+
# end of string
|
|
256
|
+
if pos == s_len:
|
|
257
|
+
return EOS
|
|
258
|
+
|
|
259
|
+
# diphthongs
|
|
260
|
+
if pos+1 < s_len:
|
|
261
|
+
if s[pos+1] == '=':
|
|
262
|
+
if s[pos] == '<':
|
|
263
|
+
self.pos += 2
|
|
264
|
+
return LESS_EQ
|
|
265
|
+
elif s[pos] == '>':
|
|
266
|
+
self.pos += 2
|
|
267
|
+
return GREATER_EQ
|
|
268
|
+
elif s[pos] == '!':
|
|
269
|
+
self.pos += 2
|
|
270
|
+
return NOT_EQ
|
|
271
|
+
elif s[pos] == '=':
|
|
272
|
+
self.pos += 2
|
|
273
|
+
return ord('=')
|
|
274
|
+
|
|
275
|
+
elif s[pos] == '*' and s[pos+1] == '*':
|
|
276
|
+
self.pos += 2
|
|
277
|
+
return ord('^')
|
|
278
|
+
|
|
279
|
+
# simple tokens
|
|
280
|
+
if s[pos] in "+-*/^()=><,[]{}!":
|
|
281
|
+
type = ord(s[pos])
|
|
282
|
+
self.pos += 1
|
|
283
|
+
return type
|
|
284
|
+
|
|
285
|
+
# numeric literals
|
|
286
|
+
if s[pos].isdigit() or s[pos] == '.':
|
|
287
|
+
type = INT
|
|
288
|
+
seen_exp = False
|
|
289
|
+
seen_decimal = False
|
|
290
|
+
while pos < s_len:
|
|
291
|
+
if s[pos].isdigit():
|
|
292
|
+
pass
|
|
293
|
+
elif s[pos] == '.':
|
|
294
|
+
if seen_decimal or seen_exp:
|
|
295
|
+
self.pos = pos
|
|
296
|
+
return type
|
|
297
|
+
else:
|
|
298
|
+
type = FLOAT
|
|
299
|
+
seen_decimal = True
|
|
300
|
+
elif s[pos] == 'e' or s[pos] == 'E':
|
|
301
|
+
if seen_exp:
|
|
302
|
+
self.pos = pos
|
|
303
|
+
return type
|
|
304
|
+
else:
|
|
305
|
+
type = FLOAT
|
|
306
|
+
seen_exp = True
|
|
307
|
+
elif s[pos] == '+' or s[pos] == '-':
|
|
308
|
+
if not (seen_exp and (s[pos-1] == 'e' or s[pos-1] == 'E')):
|
|
309
|
+
self.pos = pos
|
|
310
|
+
return type
|
|
311
|
+
else:
|
|
312
|
+
break
|
|
313
|
+
pos += 1
|
|
314
|
+
self.pos = pos
|
|
315
|
+
return type
|
|
316
|
+
|
|
317
|
+
# name literals
|
|
318
|
+
if is_alphanumeric(s[pos]):
|
|
319
|
+
while pos < s_len and is_alphanumeric(s[pos]):
|
|
320
|
+
pos += 1
|
|
321
|
+
# matrices
|
|
322
|
+
if s[self.pos:pos] == 'matrix':
|
|
323
|
+
self.pos = pos
|
|
324
|
+
return MATRIX
|
|
325
|
+
self.pos = pos
|
|
326
|
+
return NAME
|
|
327
|
+
|
|
328
|
+
pos += 1
|
|
329
|
+
self.pos = pos
|
|
330
|
+
return ERROR
|
|
331
|
+
|
|
332
|
+
cpdef int next(self) noexcept:
|
|
333
|
+
"""
|
|
334
|
+
Return the next token in the string.
|
|
335
|
+
|
|
336
|
+
EXAMPLES::
|
|
337
|
+
|
|
338
|
+
sage: from sage.misc.parser import Tokenizer, token_to_str
|
|
339
|
+
sage: t = Tokenizer("a+3")
|
|
340
|
+
sage: token_to_str(t.next())
|
|
341
|
+
'NAME'
|
|
342
|
+
sage: token_to_str(t.next())
|
|
343
|
+
'+'
|
|
344
|
+
sage: token_to_str(t.next())
|
|
345
|
+
'INT'
|
|
346
|
+
sage: token_to_str(t.next())
|
|
347
|
+
'EOS'
|
|
348
|
+
"""
|
|
349
|
+
while self.pos < len(self.s) and is_whitespace(self.s[self.pos]):
|
|
350
|
+
self.pos += 1
|
|
351
|
+
self.last_pos = self.pos
|
|
352
|
+
self.token = self.find()
|
|
353
|
+
return self.token
|
|
354
|
+
|
|
355
|
+
cpdef int last(self) noexcept:
|
|
356
|
+
"""
|
|
357
|
+
Return the last token seen.
|
|
358
|
+
|
|
359
|
+
EXAMPLES::
|
|
360
|
+
|
|
361
|
+
sage: from sage.misc.parser import Tokenizer, token_to_str
|
|
362
|
+
sage: t = Tokenizer("3a")
|
|
363
|
+
sage: token_to_str(t.next())
|
|
364
|
+
'INT'
|
|
365
|
+
sage: token_to_str(t.last())
|
|
366
|
+
'INT'
|
|
367
|
+
sage: token_to_str(t.next())
|
|
368
|
+
'NAME'
|
|
369
|
+
sage: token_to_str(t.last())
|
|
370
|
+
'NAME'
|
|
371
|
+
"""
|
|
372
|
+
return self.token
|
|
373
|
+
|
|
374
|
+
cpdef int peek(self) noexcept:
|
|
375
|
+
"""
|
|
376
|
+
Return the next token that will be encountered, without changing
|
|
377
|
+
the state of ``self``.
|
|
378
|
+
|
|
379
|
+
EXAMPLES::
|
|
380
|
+
|
|
381
|
+
sage: from sage.misc.parser import Tokenizer, token_to_str
|
|
382
|
+
sage: t = Tokenizer("a+b")
|
|
383
|
+
sage: token_to_str(t.peek())
|
|
384
|
+
'NAME'
|
|
385
|
+
sage: token_to_str(t.next())
|
|
386
|
+
'NAME'
|
|
387
|
+
sage: token_to_str(t.peek())
|
|
388
|
+
'+'
|
|
389
|
+
sage: token_to_str(t.peek())
|
|
390
|
+
'+'
|
|
391
|
+
sage: token_to_str(t.next())
|
|
392
|
+
'+'
|
|
393
|
+
"""
|
|
394
|
+
cdef int save_pos = self.pos
|
|
395
|
+
cdef int token = self.find()
|
|
396
|
+
self.pos = save_pos
|
|
397
|
+
return token
|
|
398
|
+
|
|
399
|
+
cpdef bint backtrack(self) except -2:
|
|
400
|
+
"""
|
|
401
|
+
Put ``self`` in such a state that the subsequent call to ``next()``
|
|
402
|
+
will return the same as if ``next()`` had not been called.
|
|
403
|
+
|
|
404
|
+
Currently, one can only backtrack once.
|
|
405
|
+
|
|
406
|
+
EXAMPLES::
|
|
407
|
+
|
|
408
|
+
sage: from sage.misc.parser import Tokenizer, token_to_str
|
|
409
|
+
sage: t = Tokenizer("a+b")
|
|
410
|
+
sage: token_to_str(t.next())
|
|
411
|
+
'NAME'
|
|
412
|
+
sage: token_to_str(t.next())
|
|
413
|
+
'+'
|
|
414
|
+
sage: t.backtrack() # the return type is bint for performance reasons
|
|
415
|
+
False
|
|
416
|
+
sage: token_to_str(t.next())
|
|
417
|
+
'+'
|
|
418
|
+
"""
|
|
419
|
+
if self.pos == self.last_pos and self.token != EOS:
|
|
420
|
+
raise NotImplementedError("Can only backtrack once.")
|
|
421
|
+
else:
|
|
422
|
+
self.pos = self.last_pos
|
|
423
|
+
self.token = 0
|
|
424
|
+
|
|
425
|
+
cpdef last_token_string(self):
|
|
426
|
+
"""
|
|
427
|
+
Return the actual contents of the last token.
|
|
428
|
+
|
|
429
|
+
EXAMPLES::
|
|
430
|
+
|
|
431
|
+
sage: from sage.misc.parser import Tokenizer, token_to_str
|
|
432
|
+
sage: t = Tokenizer("a - 1e5")
|
|
433
|
+
sage: token_to_str(t.next())
|
|
434
|
+
'NAME'
|
|
435
|
+
sage: t.last_token_string()
|
|
436
|
+
'a'
|
|
437
|
+
sage: token_to_str(t.next())
|
|
438
|
+
'-'
|
|
439
|
+
sage: token_to_str(t.next())
|
|
440
|
+
'FLOAT'
|
|
441
|
+
sage: t.last_token_string()
|
|
442
|
+
'1e5'
|
|
443
|
+
"""
|
|
444
|
+
return self.s[self.last_pos:self.pos]
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
cdef class Parser:
|
|
448
|
+
|
|
449
|
+
cdef integer_constructor
|
|
450
|
+
cdef float_constructor
|
|
451
|
+
cdef variable_constructor
|
|
452
|
+
cdef callable_constructor
|
|
453
|
+
cdef bint implicit_multiplication
|
|
454
|
+
|
|
455
|
+
def __init__(self, make_int=int, make_float=float, make_var=str, make_function={}, bint implicit_multiplication=True):
|
|
456
|
+
"""
|
|
457
|
+
Create a symbolic expression parser.
|
|
458
|
+
|
|
459
|
+
INPUT:
|
|
460
|
+
|
|
461
|
+
- ``make_int`` -- callable object to construct integers from strings (default: int)
|
|
462
|
+
- ``make_float`` -- callable object to construct real numbers from strings (default: float)
|
|
463
|
+
- ``make_var`` -- callable object to construct variables from strings (default: str)
|
|
464
|
+
this may also be a dictionary of variable names
|
|
465
|
+
- ``make_function`` -- callable object to construct callable functions from strings
|
|
466
|
+
this may also be a dictionary
|
|
467
|
+
- ``implicit_multiplication`` -- whether or not to accept implicit multiplication
|
|
468
|
+
|
|
469
|
+
OUTPUT:
|
|
470
|
+
|
|
471
|
+
The evaluated expression tree given by the string, where the above
|
|
472
|
+
functions are used to create the leaves of this tree.
|
|
473
|
+
|
|
474
|
+
EXAMPLES::
|
|
475
|
+
|
|
476
|
+
sage: from sage.misc.parser import Parser
|
|
477
|
+
sage: p = Parser()
|
|
478
|
+
sage: p.parse("1+2")
|
|
479
|
+
3
|
|
480
|
+
sage: p.parse("1+2 == 3")
|
|
481
|
+
True
|
|
482
|
+
|
|
483
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
484
|
+
sage: p.parse("a*b^c - 3a") # needs sage.symbolic
|
|
485
|
+
a*b^c - 3*a
|
|
486
|
+
|
|
487
|
+
sage: R.<x> = QQ[]
|
|
488
|
+
sage: p = Parser(make_var={'x': x})
|
|
489
|
+
sage: p.parse("(x+1)^5-x")
|
|
490
|
+
x^5 + 5*x^4 + 10*x^3 + 10*x^2 + 4*x + 1
|
|
491
|
+
sage: p.parse("(x+1)^5-x").parent() is R
|
|
492
|
+
True
|
|
493
|
+
|
|
494
|
+
sage: p = Parser(make_float=RR, make_var=var, # needs sage.symbolic
|
|
495
|
+
....: make_function={'foo': (lambda x: x*x+x)})
|
|
496
|
+
sage: p.parse("1.5 + foo(b)") # needs sage.symbolic
|
|
497
|
+
b^2 + b + 1.50000000000000
|
|
498
|
+
sage: p.parse("1.9").parent() # needs sage.symbolic
|
|
499
|
+
Real Field with 53 bits of precision
|
|
500
|
+
"""
|
|
501
|
+
self.integer_constructor = make_int
|
|
502
|
+
self.float_constructor = make_float
|
|
503
|
+
if not callable(make_var):
|
|
504
|
+
make_var = LookupNameMaker(make_var)
|
|
505
|
+
if not callable(make_function):
|
|
506
|
+
make_function = LookupNameMaker(make_function)
|
|
507
|
+
self.variable_constructor = make_var
|
|
508
|
+
self.callable_constructor = make_function
|
|
509
|
+
self.implicit_multiplication = implicit_multiplication
|
|
510
|
+
|
|
511
|
+
def _variable_constructor(self):
|
|
512
|
+
"""
|
|
513
|
+
Return the variable constructor of this parser.
|
|
514
|
+
|
|
515
|
+
EXAMPLES::
|
|
516
|
+
|
|
517
|
+
sage: from sage.calculus.calculus import SR_parser # needs sage.symbolic
|
|
518
|
+
sage: SR_parser._variable_constructor() # needs sage.symbolic
|
|
519
|
+
<sage.misc.parser.LookupNameMaker...
|
|
520
|
+
"""
|
|
521
|
+
return self.variable_constructor
|
|
522
|
+
|
|
523
|
+
def _callable_constructor(self):
|
|
524
|
+
"""
|
|
525
|
+
Return the callable constructor of this parser.
|
|
526
|
+
|
|
527
|
+
EXAMPLES::
|
|
528
|
+
|
|
529
|
+
sage: from sage.calculus.calculus import SR_parser # needs sage.symbolic
|
|
530
|
+
sage: SR_parser._callable_constructor() # needs sage.symbolic
|
|
531
|
+
<sage.misc.parser.LookupNameMaker...
|
|
532
|
+
"""
|
|
533
|
+
return self.callable_constructor
|
|
534
|
+
|
|
535
|
+
cpdef parse(self, s, bint accept_eqn=True):
|
|
536
|
+
"""
|
|
537
|
+
Parse the given string.
|
|
538
|
+
|
|
539
|
+
EXAMPLES::
|
|
540
|
+
|
|
541
|
+
sage: from sage.misc.parser import Parser
|
|
542
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
543
|
+
sage: p.parse("E = m c^2") # needs sage.symbolic
|
|
544
|
+
E == c^2*m
|
|
545
|
+
"""
|
|
546
|
+
cdef Tokenizer tokens = Tokenizer(s)
|
|
547
|
+
if tokens.peek() == MATRIX:
|
|
548
|
+
tokens.next()
|
|
549
|
+
expr = self.p_matrix(tokens)
|
|
550
|
+
else:
|
|
551
|
+
expr = self.p_eqn(tokens) if accept_eqn else self.p_expr(tokens)
|
|
552
|
+
|
|
553
|
+
if tokens.next() != EOS:
|
|
554
|
+
self.parse_error(tokens)
|
|
555
|
+
return expr
|
|
556
|
+
|
|
557
|
+
cpdef parse_expression(self, s):
|
|
558
|
+
"""
|
|
559
|
+
Parse an expression.
|
|
560
|
+
|
|
561
|
+
EXAMPLES::
|
|
562
|
+
|
|
563
|
+
sage: from sage.misc.parser import Parser
|
|
564
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
565
|
+
sage: p.parse_expression('a-3b^2') # needs sage.symbolic
|
|
566
|
+
-3*b^2 + a
|
|
567
|
+
"""
|
|
568
|
+
cdef Tokenizer tokens = Tokenizer(s)
|
|
569
|
+
expr = self.p_expr(tokens)
|
|
570
|
+
if tokens.next() != EOS:
|
|
571
|
+
self.parse_error(tokens)
|
|
572
|
+
return expr
|
|
573
|
+
|
|
574
|
+
cpdef parse_sequence(self, s):
|
|
575
|
+
"""
|
|
576
|
+
Parse a (possibly nested) set of lists and tuples.
|
|
577
|
+
|
|
578
|
+
EXAMPLES::
|
|
579
|
+
|
|
580
|
+
sage: # needs sage.symbolic
|
|
581
|
+
sage: from sage.misc.parser import Parser
|
|
582
|
+
sage: p = Parser(make_var=var)
|
|
583
|
+
sage: p.parse_sequence("1,2,3")
|
|
584
|
+
[1, 2, 3]
|
|
585
|
+
sage: p.parse_sequence("[1,2,(a,b,c+d)]")
|
|
586
|
+
[1, 2, (a, b, c + d)]
|
|
587
|
+
sage: p.parse_sequence("13")
|
|
588
|
+
13
|
|
589
|
+
"""
|
|
590
|
+
cdef Tokenizer tokens = Tokenizer(s)
|
|
591
|
+
all = self.p_sequence(tokens)
|
|
592
|
+
if tokens.next() != EOS:
|
|
593
|
+
self.parse_error(tokens)
|
|
594
|
+
if len(all) == 1 and isinstance(all, list):
|
|
595
|
+
all = all[0]
|
|
596
|
+
return all
|
|
597
|
+
|
|
598
|
+
cpdef p_matrix(self, Tokenizer tokens):
|
|
599
|
+
"""
|
|
600
|
+
Parse a matrix.
|
|
601
|
+
|
|
602
|
+
EXAMPLES::
|
|
603
|
+
|
|
604
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
605
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
606
|
+
sage: p.p_matrix(Tokenizer("([a,0],[0,a])")) # needs sage.symbolic
|
|
607
|
+
[a 0]
|
|
608
|
+
[0 a]
|
|
609
|
+
"""
|
|
610
|
+
cdef int token
|
|
611
|
+
all = []
|
|
612
|
+
if tokens.next() == c'(':
|
|
613
|
+
token = c','
|
|
614
|
+
while token == c',':
|
|
615
|
+
all.append(self.p_list(tokens))
|
|
616
|
+
token = tokens.next()
|
|
617
|
+
|
|
618
|
+
if token == c')':
|
|
619
|
+
from sage.matrix.constructor import matrix
|
|
620
|
+
return matrix(all)
|
|
621
|
+
else:
|
|
622
|
+
self.parse_error(tokens, "Malformed matrix")
|
|
623
|
+
else:
|
|
624
|
+
self.parse_error(tokens, "Malformed matrix")
|
|
625
|
+
|
|
626
|
+
cpdef p_sequence(self, Tokenizer tokens):
|
|
627
|
+
"""
|
|
628
|
+
Parse a (possibly nested) set of lists and tuples.
|
|
629
|
+
|
|
630
|
+
EXAMPLES::
|
|
631
|
+
|
|
632
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
633
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
634
|
+
sage: p.p_sequence(Tokenizer("[1+2,0]")) # needs sage.symbolic
|
|
635
|
+
[[3, 0]]
|
|
636
|
+
sage: p.p_sequence(Tokenizer("(1,2,3) , [1+a, 2+b, (3+c), (4+d,)]")) # needs sage.symbolic
|
|
637
|
+
[(1, 2, 3), [a + 1, b + 2, c + 3, (d + 4,)]]
|
|
638
|
+
"""
|
|
639
|
+
all = []
|
|
640
|
+
cdef int token = c','
|
|
641
|
+
while token == c',':
|
|
642
|
+
token = tokens.peek()
|
|
643
|
+
if token == MATRIX:
|
|
644
|
+
tokens.next()
|
|
645
|
+
obj = self.p_matrix(tokens)
|
|
646
|
+
elif token == INT:
|
|
647
|
+
# we optimize for this rather than going all the way to atom
|
|
648
|
+
tokens.next()
|
|
649
|
+
if tokens.peek() == c',':
|
|
650
|
+
obj = self.integer_constructor(tokens.last_token_string())
|
|
651
|
+
else:
|
|
652
|
+
tokens.backtrack()
|
|
653
|
+
obj = self.p_eqn(tokens)
|
|
654
|
+
elif token == c'[':
|
|
655
|
+
obj = self.p_list(tokens)
|
|
656
|
+
elif token == c'(':
|
|
657
|
+
obj = self.p_tuple(tokens)
|
|
658
|
+
elif token == EOS:
|
|
659
|
+
return all
|
|
660
|
+
elif token == c']' or token == c')':
|
|
661
|
+
tokens.token = c','
|
|
662
|
+
return all
|
|
663
|
+
else:
|
|
664
|
+
obj = self.p_eqn(tokens)
|
|
665
|
+
PyList_Append(all, obj)
|
|
666
|
+
token = tokens.next()
|
|
667
|
+
|
|
668
|
+
tokens.backtrack()
|
|
669
|
+
return all
|
|
670
|
+
|
|
671
|
+
cpdef p_list(self, Tokenizer tokens):
|
|
672
|
+
"""
|
|
673
|
+
Parse a list of items.
|
|
674
|
+
|
|
675
|
+
EXAMPLES::
|
|
676
|
+
|
|
677
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
678
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
679
|
+
sage: p.p_list(Tokenizer("[1+2, 1e3]")) # needs sage.symbolic
|
|
680
|
+
[3, 1000.0]
|
|
681
|
+
sage: p.p_list(Tokenizer("[]")) # needs sage.symbolic
|
|
682
|
+
[]
|
|
683
|
+
"""
|
|
684
|
+
cdef int token = tokens.next()
|
|
685
|
+
if token != c'[':
|
|
686
|
+
self.parse_error(tokens, "Malformed list")
|
|
687
|
+
all = self.p_sequence(tokens)
|
|
688
|
+
token = tokens.next()
|
|
689
|
+
if token != c']':
|
|
690
|
+
self.parse_error(tokens, "Malformed list")
|
|
691
|
+
return all
|
|
692
|
+
|
|
693
|
+
cpdef p_tuple(self, Tokenizer tokens):
|
|
694
|
+
"""
|
|
695
|
+
Parse a tuple of items.
|
|
696
|
+
|
|
697
|
+
EXAMPLES::
|
|
698
|
+
|
|
699
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
700
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
701
|
+
sage: p.p_tuple(Tokenizer("( (), (1), (1,), (1,2), (1,2,3), (1+2)^2, )")) # needs sage.symbolic
|
|
702
|
+
((), 1, (1,), (1, 2), (1, 2, 3), 9)
|
|
703
|
+
"""
|
|
704
|
+
cdef int start = tokens.pos
|
|
705
|
+
cdef int token = tokens.next()
|
|
706
|
+
cdef bint real_tuple = True
|
|
707
|
+
if token != c'(':
|
|
708
|
+
self.parse_error(tokens, "Malformed tuple")
|
|
709
|
+
all = self.p_sequence(tokens)
|
|
710
|
+
if len(all) == 1:
|
|
711
|
+
if tokens.last() != c',':
|
|
712
|
+
real_tuple = False
|
|
713
|
+
token = tokens.next()
|
|
714
|
+
if token != c')':
|
|
715
|
+
self.parse_error(tokens, "Malformed tuple")
|
|
716
|
+
if real_tuple:
|
|
717
|
+
return tuple(all)
|
|
718
|
+
else:
|
|
719
|
+
token = tokens.peek()
|
|
720
|
+
if token == c',' or token == EOS:
|
|
721
|
+
return all[0]
|
|
722
|
+
else:
|
|
723
|
+
# we have to reparse the entire thing as an expression
|
|
724
|
+
tokens.reset(start)
|
|
725
|
+
return self.p_eqn(tokens)
|
|
726
|
+
|
|
727
|
+
# eqn ::= expr op expr | expr
|
|
728
|
+
cpdef p_eqn(self, Tokenizer tokens):
|
|
729
|
+
r"""
|
|
730
|
+
Parse an equation or expression.
|
|
731
|
+
|
|
732
|
+
This is the top-level node called by the \code{parse} function.
|
|
733
|
+
|
|
734
|
+
EXAMPLES::
|
|
735
|
+
|
|
736
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
737
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
738
|
+
sage: p.p_eqn(Tokenizer("1+a")) # needs sage.symbolic
|
|
739
|
+
a + 1
|
|
740
|
+
|
|
741
|
+
sage: # needs sage.symbolic
|
|
742
|
+
sage: p.p_eqn(Tokenizer("a == b"))
|
|
743
|
+
a == b
|
|
744
|
+
sage: p.p_eqn(Tokenizer("a < b"))
|
|
745
|
+
a < b
|
|
746
|
+
sage: p.p_eqn(Tokenizer("a > b"))
|
|
747
|
+
a > b
|
|
748
|
+
sage: p.p_eqn(Tokenizer("a <= b"))
|
|
749
|
+
a <= b
|
|
750
|
+
sage: p.p_eqn(Tokenizer("a >= b"))
|
|
751
|
+
a >= b
|
|
752
|
+
sage: p.p_eqn(Tokenizer("a != b"))
|
|
753
|
+
a != b
|
|
754
|
+
"""
|
|
755
|
+
lhs = self.p_expr(tokens)
|
|
756
|
+
cdef int op = tokens.next()
|
|
757
|
+
if op == c'=':
|
|
758
|
+
return lhs == self.p_expr(tokens)
|
|
759
|
+
elif op == NOT_EQ:
|
|
760
|
+
return lhs != self.p_expr(tokens)
|
|
761
|
+
elif op == c'<':
|
|
762
|
+
return lhs < self.p_expr(tokens)
|
|
763
|
+
elif op == LESS_EQ:
|
|
764
|
+
return lhs <= self.p_expr(tokens)
|
|
765
|
+
elif op == c'>':
|
|
766
|
+
return lhs > self.p_expr(tokens)
|
|
767
|
+
elif op == GREATER_EQ:
|
|
768
|
+
return lhs >= self.p_expr(tokens)
|
|
769
|
+
else:
|
|
770
|
+
tokens.backtrack()
|
|
771
|
+
return lhs
|
|
772
|
+
|
|
773
|
+
# expr ::= term | expr '+' term | expr '-' term
|
|
774
|
+
cpdef p_expr(self, Tokenizer tokens):
|
|
775
|
+
"""
|
|
776
|
+
Parse a list of one or more terms.
|
|
777
|
+
|
|
778
|
+
EXAMPLES::
|
|
779
|
+
|
|
780
|
+
sage: # needs sage.symbolic
|
|
781
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
782
|
+
sage: p = Parser(make_var=var)
|
|
783
|
+
sage: p.p_expr(Tokenizer("a+b"))
|
|
784
|
+
a + b
|
|
785
|
+
sage: p.p_expr(Tokenizer("a"))
|
|
786
|
+
a
|
|
787
|
+
sage: p.p_expr(Tokenizer("a - b + 4*c - d^2"))
|
|
788
|
+
-d^2 + a - b + 4*c
|
|
789
|
+
sage: p.p_expr(Tokenizer("a - -3"))
|
|
790
|
+
a + 3
|
|
791
|
+
sage: p.p_expr(Tokenizer("a + 1 == b"))
|
|
792
|
+
a + 1
|
|
793
|
+
"""
|
|
794
|
+
# Note: this is left-recursive, so we can't just recurse
|
|
795
|
+
cdef int op
|
|
796
|
+
operand1 = self.p_term(tokens)
|
|
797
|
+
op = tokens.next()
|
|
798
|
+
while op == c'+' or op == c'-':
|
|
799
|
+
operand2 = self.p_term(tokens)
|
|
800
|
+
if op == c'+':
|
|
801
|
+
operand1 = operand1 + operand2
|
|
802
|
+
else:
|
|
803
|
+
operand1 = operand1 - operand2
|
|
804
|
+
op = tokens.next()
|
|
805
|
+
tokens.backtrack()
|
|
806
|
+
return operand1
|
|
807
|
+
|
|
808
|
+
# term ::= factor | term '*' factor | term '/' factor
|
|
809
|
+
cpdef p_term(self, Tokenizer tokens):
|
|
810
|
+
"""
|
|
811
|
+
Parse a single term (consisting of one or more factors).
|
|
812
|
+
|
|
813
|
+
EXAMPLES::
|
|
814
|
+
|
|
815
|
+
sage: # needs sage.symbolic
|
|
816
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
817
|
+
sage: p = Parser(make_var=var)
|
|
818
|
+
sage: p.p_term(Tokenizer("a*b"))
|
|
819
|
+
a*b
|
|
820
|
+
sage: p.p_term(Tokenizer("a * b / c * d"))
|
|
821
|
+
a*b*d/c
|
|
822
|
+
sage: p.p_term(Tokenizer("-a * b + c"))
|
|
823
|
+
-a*b
|
|
824
|
+
sage: p.p_term(Tokenizer("a*(b-c)^2"))
|
|
825
|
+
a*(b - c)^2
|
|
826
|
+
sage: p.p_term(Tokenizer("-3a"))
|
|
827
|
+
-3*a
|
|
828
|
+
"""
|
|
829
|
+
# Note: this is left-recursive, so we can't just recurse
|
|
830
|
+
cdef int op
|
|
831
|
+
operand1 = self.p_factor(tokens)
|
|
832
|
+
op = tokens.next()
|
|
833
|
+
if op == NAME and self.implicit_multiplication:
|
|
834
|
+
op = c'*'
|
|
835
|
+
tokens.backtrack()
|
|
836
|
+
while op == c'*' or op == c'/':
|
|
837
|
+
operand2 = self.p_factor(tokens)
|
|
838
|
+
if op == c'*':
|
|
839
|
+
operand1 = operand1 * operand2
|
|
840
|
+
else:
|
|
841
|
+
operand1 = operand1 / operand2
|
|
842
|
+
op = tokens.next()
|
|
843
|
+
if op == NAME and self.implicit_multiplication:
|
|
844
|
+
op = c'*'
|
|
845
|
+
tokens.backtrack()
|
|
846
|
+
tokens.backtrack()
|
|
847
|
+
return operand1
|
|
848
|
+
|
|
849
|
+
# factor ::= '+' factor | '-' factor | power
|
|
850
|
+
cpdef p_factor(self, Tokenizer tokens):
|
|
851
|
+
"""
|
|
852
|
+
Parse a single factor, which consists of any number of unary +/-
|
|
853
|
+
and a power.
|
|
854
|
+
|
|
855
|
+
EXAMPLES::
|
|
856
|
+
|
|
857
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
858
|
+
sage: R.<t> = ZZ[['t']]
|
|
859
|
+
sage: p = Parser(make_var={'t': t})
|
|
860
|
+
sage: p.p_factor(Tokenizer("- -t"))
|
|
861
|
+
t
|
|
862
|
+
sage: p.p_factor(Tokenizer("- + - -t^2"))
|
|
863
|
+
-t^2
|
|
864
|
+
sage: p.p_factor(Tokenizer("t^11 * x"))
|
|
865
|
+
t^11
|
|
866
|
+
"""
|
|
867
|
+
cdef int token = tokens.next()
|
|
868
|
+
if token == c'+':
|
|
869
|
+
return self.p_factor(tokens)
|
|
870
|
+
elif token == c'-':
|
|
871
|
+
return -self.p_factor(tokens)
|
|
872
|
+
else:
|
|
873
|
+
tokens.backtrack()
|
|
874
|
+
return self.p_power(tokens)
|
|
875
|
+
|
|
876
|
+
# power ::= (atom | atom!) ^ factor | atom | atom!
|
|
877
|
+
cpdef p_power(self, Tokenizer tokens):
|
|
878
|
+
"""
|
|
879
|
+
Parses a power. Note that exponentiation groups right to left.
|
|
880
|
+
|
|
881
|
+
EXAMPLES::
|
|
882
|
+
|
|
883
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
884
|
+
sage: R.<t> = ZZ[['t']]
|
|
885
|
+
sage: p = Parser(make_var={'t': t})
|
|
886
|
+
sage: p.p_factor(Tokenizer("-(1+t)^-1"))
|
|
887
|
+
-1 + t - t^2 + t^3 - t^4 + t^5 - t^6 + t^7 - t^8 + t^9 - t^10 + t^11 - t^12 + t^13 - t^14 + t^15 - t^16 + t^17 - t^18 + t^19 + O(t^20)
|
|
888
|
+
sage: p.p_factor(Tokenizer("t**2"))
|
|
889
|
+
t^2
|
|
890
|
+
sage: p.p_power(Tokenizer("2^3^2")) == 2^9
|
|
891
|
+
True
|
|
892
|
+
|
|
893
|
+
sage: # needs sage.symbolic
|
|
894
|
+
sage: p = Parser(make_var=var)
|
|
895
|
+
sage: p.p_factor(Tokenizer('x!'))
|
|
896
|
+
factorial(x)
|
|
897
|
+
sage: p.p_factor(Tokenizer('(x^2)!'))
|
|
898
|
+
factorial(x^2)
|
|
899
|
+
sage: p.p_factor(Tokenizer('x!^2'))
|
|
900
|
+
factorial(x)^2
|
|
901
|
+
"""
|
|
902
|
+
operand1 = self.p_atom(tokens)
|
|
903
|
+
cdef int token = tokens.next()
|
|
904
|
+
if token == c'^':
|
|
905
|
+
operand2 = self.p_factor(tokens)
|
|
906
|
+
return operand1 ** operand2
|
|
907
|
+
elif token == c"!":
|
|
908
|
+
from sage.functions.all import factorial
|
|
909
|
+
operand1 = factorial(operand1)
|
|
910
|
+
if tokens.peek() == c'^':
|
|
911
|
+
tokens.next()
|
|
912
|
+
operand2 = self.p_factor(tokens)
|
|
913
|
+
return operand1 ** operand2
|
|
914
|
+
else:
|
|
915
|
+
return operand1
|
|
916
|
+
else:
|
|
917
|
+
tokens.backtrack()
|
|
918
|
+
return operand1
|
|
919
|
+
|
|
920
|
+
# atom ::= int | float | name | '(' expr ')' | name '(' args ')'
|
|
921
|
+
cpdef p_atom(self, Tokenizer tokens):
|
|
922
|
+
"""
|
|
923
|
+
Parse an atom. This is either a parenthesized expression, a function call, or a literal name/int/float.
|
|
924
|
+
|
|
925
|
+
EXAMPLES::
|
|
926
|
+
|
|
927
|
+
sage: # needs sage.symbolic
|
|
928
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
929
|
+
sage: p = Parser(make_var=var, make_function={'sin': sin})
|
|
930
|
+
sage: p.p_atom(Tokenizer("1"))
|
|
931
|
+
1
|
|
932
|
+
sage: p.p_atom(Tokenizer("12"))
|
|
933
|
+
12
|
|
934
|
+
sage: p.p_atom(Tokenizer("12.5"))
|
|
935
|
+
12.5
|
|
936
|
+
sage: p.p_atom(Tokenizer("(1+a)"))
|
|
937
|
+
a + 1
|
|
938
|
+
sage: p.p_atom(Tokenizer("(1+a)^2"))
|
|
939
|
+
a + 1
|
|
940
|
+
sage: p.p_atom(Tokenizer("sin(1+a)"))
|
|
941
|
+
sin(a + 1)
|
|
942
|
+
sage: p = Parser(make_var=var,
|
|
943
|
+
....: make_function={'foo': sage.misc.parser.foo})
|
|
944
|
+
sage: p.p_atom(Tokenizer("foo(a, b, key=value)"))
|
|
945
|
+
((a, b), {'key': value})
|
|
946
|
+
sage: p.p_atom(Tokenizer("foo()"))
|
|
947
|
+
((), {})
|
|
948
|
+
"""
|
|
949
|
+
cdef int token = tokens.next()
|
|
950
|
+
if token == INT:
|
|
951
|
+
return self.integer_constructor(tokens.last_token_string())
|
|
952
|
+
elif token == FLOAT:
|
|
953
|
+
return self.float_constructor(tokens.last_token_string())
|
|
954
|
+
elif token == NAME:
|
|
955
|
+
name = tokens.last_token_string()
|
|
956
|
+
token = tokens.next()
|
|
957
|
+
if token == c'(':
|
|
958
|
+
func = self.callable_constructor(name)
|
|
959
|
+
args, kwds = self.p_args(tokens)
|
|
960
|
+
token = tokens.next()
|
|
961
|
+
if token != c')':
|
|
962
|
+
self.parse_error(tokens, "Bad function call")
|
|
963
|
+
return func(*args, **kwds)
|
|
964
|
+
else:
|
|
965
|
+
tokens.backtrack()
|
|
966
|
+
return self.variable_constructor(name)
|
|
967
|
+
elif token == c'(':
|
|
968
|
+
expr = self.p_expr(tokens)
|
|
969
|
+
token = tokens.next()
|
|
970
|
+
if token != c')':
|
|
971
|
+
self.parse_error(tokens, "Mismatched parentheses")
|
|
972
|
+
return expr
|
|
973
|
+
else:
|
|
974
|
+
self.parse_error(tokens)
|
|
975
|
+
|
|
976
|
+
# args = arg (',' arg)* | EMPTY
|
|
977
|
+
cpdef p_args(self, Tokenizer tokens):
|
|
978
|
+
"""
|
|
979
|
+
Return a ``list, dict`` pair.
|
|
980
|
+
|
|
981
|
+
EXAMPLES::
|
|
982
|
+
|
|
983
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
984
|
+
sage: p = Parser()
|
|
985
|
+
sage: p.p_args(Tokenizer("1,2,a=3"))
|
|
986
|
+
([1, 2], {'a': 3})
|
|
987
|
+
sage: p.p_args(Tokenizer("1, 2, a = 1+5^2"))
|
|
988
|
+
([1, 2], {'a': 26})
|
|
989
|
+
"""
|
|
990
|
+
args = []
|
|
991
|
+
kwds = {}
|
|
992
|
+
if tokens.peek() == c')':
|
|
993
|
+
return args, kwds
|
|
994
|
+
cdef int token = c','
|
|
995
|
+
while token == c',':
|
|
996
|
+
arg = self.p_arg(tokens)
|
|
997
|
+
if isinstance(arg, tuple):
|
|
998
|
+
name, value = arg
|
|
999
|
+
kwds[name] = value
|
|
1000
|
+
else:
|
|
1001
|
+
args.append(arg)
|
|
1002
|
+
token = tokens.next()
|
|
1003
|
+
tokens.backtrack()
|
|
1004
|
+
return args, kwds
|
|
1005
|
+
|
|
1006
|
+
# arg = expr | name '=' expr
|
|
1007
|
+
cpdef p_arg(self, Tokenizer tokens):
|
|
1008
|
+
"""
|
|
1009
|
+
Return an ``expr``, or a ``(name, expr)`` tuple corresponding to a
|
|
1010
|
+
single function call argument.
|
|
1011
|
+
|
|
1012
|
+
EXAMPLES:
|
|
1013
|
+
|
|
1014
|
+
Parsing a normal expression::
|
|
1015
|
+
|
|
1016
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
1017
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
1018
|
+
sage: p.p_arg(Tokenizer("a+b")) # needs sage.symbolic
|
|
1019
|
+
a + b
|
|
1020
|
+
|
|
1021
|
+
A keyword expression argument::
|
|
1022
|
+
|
|
1023
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
1024
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
1025
|
+
sage: p.p_arg(Tokenizer("val=a+b")) # needs sage.symbolic
|
|
1026
|
+
('val', a + b)
|
|
1027
|
+
|
|
1028
|
+
A lone list::
|
|
1029
|
+
|
|
1030
|
+
sage: from sage.misc.parser import Parser, Tokenizer
|
|
1031
|
+
sage: p = Parser(make_var=var) # needs sage.symbolic
|
|
1032
|
+
sage: p.p_arg(Tokenizer("[x]")) # needs sage.symbolic
|
|
1033
|
+
[x]
|
|
1034
|
+
"""
|
|
1035
|
+
cdef int token = tokens.next()
|
|
1036
|
+
if token == NAME and tokens.peek() == c'=':
|
|
1037
|
+
name = tokens.last_token_string()
|
|
1038
|
+
tokens.next()
|
|
1039
|
+
return name, self.p_expr(tokens)
|
|
1040
|
+
if token == c"[":
|
|
1041
|
+
tokens.backtrack()
|
|
1042
|
+
return self.p_list(tokens)
|
|
1043
|
+
else:
|
|
1044
|
+
tokens.backtrack()
|
|
1045
|
+
return self.p_expr(tokens)
|
|
1046
|
+
|
|
1047
|
+
cdef parse_error(self, Tokenizer tokens, msg="Malformed expression"):
|
|
1048
|
+
raise SyntaxError(msg, tokens.s, tokens.pos)
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
cdef class LookupNameMaker:
|
|
1052
|
+
cdef object names
|
|
1053
|
+
cdef object fallback
|
|
1054
|
+
|
|
1055
|
+
def __init__(self, names, fallback=None):
|
|
1056
|
+
"""
|
|
1057
|
+
This class wraps a dictionary as a callable for use in creating names.
|
|
1058
|
+
It takes a dictionary of names, and an (optional) callable to use
|
|
1059
|
+
when the given name is not found in the dictionary.
|
|
1060
|
+
|
|
1061
|
+
EXAMPLES::
|
|
1062
|
+
|
|
1063
|
+
sage: # needs sage.symbolic
|
|
1064
|
+
sage: from sage.misc.parser import LookupNameMaker
|
|
1065
|
+
sage: maker = LookupNameMaker({'pi': pi}, var)
|
|
1066
|
+
sage: maker('pi')
|
|
1067
|
+
pi
|
|
1068
|
+
sage: maker('pi') is pi
|
|
1069
|
+
True
|
|
1070
|
+
sage: maker('a')
|
|
1071
|
+
a
|
|
1072
|
+
"""
|
|
1073
|
+
self.names = names
|
|
1074
|
+
self.fallback = fallback
|
|
1075
|
+
|
|
1076
|
+
def set_names(self, new_names):
|
|
1077
|
+
"""
|
|
1078
|
+
TESTS::
|
|
1079
|
+
|
|
1080
|
+
sage: from sage.misc.parser import LookupNameMaker
|
|
1081
|
+
sage: maker = LookupNameMaker({}, str)
|
|
1082
|
+
sage: maker.set_names({'a': x}) # needs sage.symbolic
|
|
1083
|
+
sage: maker('a') is x # needs sage.symbolic
|
|
1084
|
+
True
|
|
1085
|
+
"""
|
|
1086
|
+
self.names = new_names
|
|
1087
|
+
|
|
1088
|
+
def __call__(self, name):
|
|
1089
|
+
"""
|
|
1090
|
+
TESTS::
|
|
1091
|
+
|
|
1092
|
+
sage: # needs sage.symbolic
|
|
1093
|
+
sage: from sage.misc.parser import LookupNameMaker
|
|
1094
|
+
sage: maker = LookupNameMaker({'a': x}, str)
|
|
1095
|
+
sage: maker('a')
|
|
1096
|
+
x
|
|
1097
|
+
sage: maker('a') is x
|
|
1098
|
+
True
|
|
1099
|
+
sage: maker('b')
|
|
1100
|
+
'b'
|
|
1101
|
+
"""
|
|
1102
|
+
try:
|
|
1103
|
+
return self.names[name]
|
|
1104
|
+
except KeyError:
|
|
1105
|
+
if self.fallback is not None:
|
|
1106
|
+
return self.fallback(name)
|
|
1107
|
+
raise NameError(f"Unknown variable: '{name}'")
|