Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SyntaxQ and add a new "String Tests" Section #1248

Merged
merged 3 commits into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ repos:
hooks:
- id: check-merge-conflict
- id: debug-statements
stages: [commit]
stages: [pre-commit]
- id: end-of-file-fixer
stages: [commit]
stages: [pre-commit]
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
stages: [commit]
stages: [pre-commit]
- repo: https://github.com/psf/black
rev: 23.12.1
hooks:
- id: black
language_version: python3
stages: [commit]
stages: [pre-commit]
78 changes: 4 additions & 74 deletions mathics/builtin/atomic/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,22 @@

from mathics.core.atoms import Integer, Integer0, Integer1, String
from mathics.core.attributes import A_LISTABLE, A_PROTECTED
from mathics.core.builtin import Builtin, Predefined, PrefixOperator, Test
from mathics.core.builtin import Builtin, Predefined, PrefixOperator
from mathics.core.convert.expression import to_mathics_list
from mathics.core.convert.python import from_bool
from mathics.core.convert.regex import to_regex
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.list import ListExpression
from mathics.core.parser import MathicsFileLineFeeder, parse
from mathics.core.symbols import Symbol, SymbolTrue
from mathics.core.systemsymbols import (
SymbolFailed,
SymbolInputForm,
SymbolNone,
SymbolOutputForm,
SymbolToExpression,
)
from mathics.eval.strings import eval_ToString
from mathics.eval.strings import eval_StringContainsQ, eval_ToString
from mathics.settings import SYSTEM_CHARACTER_ENCODING

SymbolToExpression = Symbol("ToExpression")

# covers all of the variations. Here we just give some minimal basics

# Data taken from:
Expand Down Expand Up @@ -130,48 +126,6 @@ def push(i, iter, form):
push(i, iter, form)


def _pattern_search(name, string, patt, evaluation, options, matched):
# Get the pattern list and check validity for each
if patt.has_form("List", None):
patts = patt.elements
else:
patts = [patt]
re_patts = []
for p in patts:
py_p = to_regex(p, show_message=evaluation.message)
if py_p is None:
evaluation.message("StringExpression", "invld", p, patt)
return
re_patts.append(py_p)

flags = re.MULTILINE
if options["System`IgnoreCase"] is SymbolTrue:
flags = flags | re.IGNORECASE

def _search(patts, str, flags, matched):
if any(re.search(p, str, flags=flags) for p in patts):
return from_bool(matched)
return from_bool(not matched)

# Check string validity and perform regex searchhing
if string.has_form("List", None):
py_s = [s.get_string_value() for s in string.elements]
if any(s is None for s in py_s):
evaluation.message(
name, "strse", Integer1, Expression(Symbol(name), string, patt)
)
return
return to_mathics_list(*[_search(re_patts, s, flags, matched) for s in py_s])
else:
py_s = string.get_string_value()
if py_s is None:
evaluation.message(
name, "strse", Integer1, Expression(Symbol(name), string, patt)
)
return
return _search(re_patts, py_s, flags, matched)


def anchor_pattern(patt):
"""
anchors a regex in order to force matching against an entire string.
Expand Down Expand Up @@ -691,35 +645,11 @@ class StringContainsQ(Builtin):

def eval(self, string, patt, evaluation: Evaluation, options: dict):
"StringContainsQ[string_, patt_, OptionsPattern[%(name)s]]"
return _pattern_search(
return eval_StringContainsQ(
self.__class__.__name__, string, patt, evaluation, options, True
)


class StringQ(Test):
"""
<url>
:WMA link:
https://reference.wolfram.com/language/ref/StringQ.html</url>
<dl>
<dt>'StringQ[$expr$]'
<dd>returns 'True' if $expr$ is a 'String', or 'False' otherwise.
</dl>

>> StringQ["abc"]
= True
>> StringQ[1.5]
= False
>> Select[{"12", 1, 3, 5, "yz", x, y}, StringQ]
= {12, yz}
"""

summary_text = "test whether an expression is a string"

def test(self, expr) -> bool:
return isinstance(expr, String)


class StringRepeat(Builtin):
"""
<url>
Expand Down
1 change: 1 addition & 0 deletions mathics/builtin/string/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
Strings and Characters

"""
# FIXME: Redo. This is a Tech note, not a Guide Section.
82 changes: 9 additions & 73 deletions mathics/builtin/string/characters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""
Characters in Strings
"""

# FIXME: Redo: this is part of a Tech note, not a guide section.

from mathics.core.atoms import String
from mathics.core.attributes import A_LISTABLE, A_PROTECTED, A_READ_PROTECTED
Expand Down Expand Up @@ -72,74 +72,6 @@ def eval(self, start, stop, evaluation: Evaluation):
return ListExpression(*[String(chr(code)) for code in range(start, stop + 1)])


class DigitQ(Builtin):
"""
<url>
:WMA link:
https://reference.wolfram.com/language/ref/DigitQ.html</url>

<dl>
<dt>'DigitQ[$string$]'
<dd>yields 'True' if all the characters in the $string$ are \
digits, and yields 'False' otherwise.

</dl>

>> DigitQ["9"]
= True

>> DigitQ["a"]
= False

>> DigitQ["01001101011000010111010001101000011010010110001101110011"]
= True

>> DigitQ["-123456789"]
= False

"""

rules = {
"DigitQ[string_]": (
"If[StringQ[string], StringMatchQ[string, DigitCharacter...], False, False]"
),
}
summary_text = "test whether all the characters are digits"


class LetterQ(Builtin):
"""
<url>
:WMA link:
https://reference.wolfram.com/language/ref/LetterQ.html</url>

<dl>
<dt>'LetterQ[$string$]'
<dd> yields 'True' if all the characters in the $string$ are \
letters, and yields 'False' otherwise.
</dl>

>> LetterQ["m"]
= True

>> LetterQ["9"]
= False

>> LetterQ["Mathics"]
= True

>> LetterQ["Welcome to Mathics"]
= False
"""

rules = {
"LetterQ[string_]": (
"If[StringQ[string], StringMatchQ[string, LetterCharacter...], False, False]"
),
}
summary_text = "test whether all the characters are letters"


class LowerCaseQ(Test):
"""
<url>:WMA link:https://reference.wolfram.com/language/ref/LowerCaseQ.html</url>
Expand All @@ -159,8 +91,10 @@ class LowerCaseQ(Test):

summary_text = "test whether all the characters are lower-case letters"

def test(self, s) -> bool:
return isinstance(s, String) and all(c.islower() for c in s.get_string_value())
def test(self, expr) -> bool:
return isinstance(expr, String) and all(
c.islower() for c in expr.get_string_value()
)


class ToLowerCase(Builtin):
Expand Down Expand Up @@ -224,5 +158,7 @@ class UpperCaseQ(Test):

summary_text = "test whether all the characters are upper-case letters"

def test(self, s) -> bool:
return isinstance(s, String) and all(c.isupper() for c in s.get_string_value())
def test(self, expr) -> bool:
return isinstance(expr, String) and all(
c.isupper() for c in expr.get_string_value()
)
2 changes: 1 addition & 1 deletion mathics/builtin/string/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
_parallel_match,
_StringFind,
mathics_split,
to_regex,
)
from mathics.core.atoms import Integer, Integer1, Integer3, String
from mathics.core.attributes import (
Expand All @@ -23,6 +22,7 @@
)
from mathics.core.builtin import Builtin, InfixOperator
from mathics.core.convert.python import from_python
from mathics.core.convert.regex import to_regex
from mathics.core.evaluation import Evaluation
from mathics.core.expression import BoxError, Expression, string_list
from mathics.core.expression_predefined import MATHICS3_INFINITY
Expand Down
Loading
Loading