Skip to content

Commit f5a772c

Browse files
advikkabraAgent-Hellboy
authored andcommitted
Refactor string attributes and add constant string implementations (lcompilers#2524)
1 parent c5e86d8 commit f5a772c

File tree

4 files changed

+103
-30
lines changed

4 files changed

+103
-30
lines changed

integration_tests/test_str_01.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ def test_str_slice():
3737
# TODO:
3838
# assert a[0:5:-1] == ""
3939

40-
<<<<<<< HEAD
41-
42-
=======
4340
def test_str_isalpha():
4441
a: str = "helloworld"
4542
b: str = "hj kl"
@@ -56,7 +53,6 @@ def test_str_isalpha():
5653
assert res3 == False
5754
assert res4 == False
5855
assert res5 == False
59-
>>>>>>> 08e1f4502 (Fixes empty string bug in str isalpha method)
6056

6157

6258
def test_str_title():
@@ -179,8 +175,6 @@ def check():
179175
test_str_join_empty_list()
180176
test_constant_str_subscript()
181177
test_str_title()
182-
test_str_istitle()
183-
test_str_isalpha()
184178
test_str_split()
185179

186180
check()

integration_tests/test_str_attributes.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,53 @@ def is_alpha():
343343
s = " "
344344
assert s.isalpha() == False
345345

346+
def is_alpha():
347+
a: str = "helloworld"
348+
b: str = "hj kl"
349+
c: str = "a12(){}A"
350+
d: str = " "
351+
e: str = ""
352+
res: bool = a.isalpha()
353+
res2: bool = b.isalpha()
354+
res3: bool = c.isalpha()
355+
res4: bool = d.isalpha()
356+
res5: bool = e.isalpha()
357+
assert res == True
358+
assert res2 == False
359+
assert res3 == False
360+
assert res4 == False
361+
assert res5 == False
362+
363+
assert "helloworld".isalpha() == True
364+
assert "hj kl".isalpha() == False
365+
assert "a12(){}A".isalpha() == False
366+
assert " ".isalpha() == False
367+
assert "".isalpha() == False
368+
369+
370+
def is_title():
371+
a: str = "Hello World"
372+
b: str = "Hj'kl"
373+
c: str = "hELlo wOrlD"
374+
d: str = " Hello"
375+
e: str = " "
376+
res: bool = a.istitle()
377+
res2: bool = b.istitle()
378+
res3: bool = c.istitle()
379+
res4: bool = d.istitle()
380+
res5: bool = e.istitle()
381+
assert res == True
382+
assert res2 == False
383+
assert res3 == False
384+
assert res4 == True
385+
assert res5 == False
386+
387+
assert "Hello World".istitle() == True
388+
assert "Hj'kl".istitle() == False
389+
assert "hELlo wOrlD".istitle() == False
390+
assert " Hello".istitle() == True
391+
assert " ".istitle() == False
392+
346393
def is_space():
347394
assert "\n".isspace() == True
348395
assert " ".isspace() == True
@@ -357,6 +404,7 @@ def is_space():
357404
assert s.isspace() == False
358405

359406

407+
360408
def check():
361409
capitalize()
362410
lower()
@@ -372,6 +420,8 @@ def check():
372420
is_upper()
373421
is_decimal()
374422
is_ascii()
423+
is_alpha()
424+
is_title()
375425
is_space()
376426
is_title()
377427
is_alpha()

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6577,26 +6577,6 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
65776577
arg.loc = loc;
65786578
arg.m_value = s_var;
65796579
fn_args.push_back(al, arg);
6580-
} else if (attr_name == "isalpha") {
6581-
if (args.size() != 0) {
6582-
throw SemanticError("str.isalpha() takes no arguments",
6583-
loc);
6584-
}
6585-
fn_call_name = "_lpython_str_isalpha";
6586-
ASR::call_arg_t arg;
6587-
arg.loc = loc;
6588-
arg.m_value = s_var;
6589-
fn_args.push_back(al, arg);
6590-
} else if (attr_name == "istitle") {
6591-
if (args.size() != 0) {
6592-
throw SemanticError("str.istitle() takes no arguments",
6593-
loc);
6594-
}
6595-
fn_call_name = "_lpython_str_istitle";
6596-
ASR::call_arg_t arg;
6597-
arg.loc = loc;
6598-
arg.m_value = s_var;
6599-
fn_args.push_back(al, arg);
66006580
} else if (attr_name == "title") {
66016581
if (args.size() != 0) {
66026582
throw SemanticError("str.title() takes no arguments",
@@ -7116,7 +7096,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
71167096
* islower() method is limited to English Alphabets currently
71177097
* TODO: We can support other characters from Unicode Library
71187098
*/
7119-
std::vector<std::string> validation_methods{"lower", "upper", "decimal", "ascii", "space","alpha","title"}; // Database of validation methods supported
7099+
std::vector<std::string> validation_methods{"lower", "upper", "decimal", "ascii", "space", "alpha", "title"}; // Database of validation methods supported
71207100
std::string method_name = attr_name.substr(2);
71217101
if(std::find(validation_methods.begin(),validation_methods.end(), method_name) == validation_methods.end()) {
71227102
throw SemanticError("String method not implemented: " + attr_name, loc);
@@ -7272,6 +7252,57 @@ we will have to use something else.
72727252
tmp = ASR::make_LogicalConstant_t(al, loc, is_space,
72737253
ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)));
72747254
return;
7255+
} else if (attr_name == "isalpha") {
7256+
/*
7257+
* Specification -
7258+
Return True if all characters in the string are alphabets,
7259+
and there is at least one character in the string.
7260+
*/
7261+
bool is_alpha = (s_var.size() != 0);
7262+
for (auto &i : s_var) {
7263+
if (!((i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z'))) {
7264+
is_alpha = false;
7265+
break;
7266+
}
7267+
}
7268+
tmp = ASR::make_LogicalConstant_t(al, loc, is_alpha,
7269+
ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)));
7270+
return;
7271+
} else if (attr_name == "istitle") {
7272+
/*
7273+
* Specification -
7274+
Returns True if all words in the string are in title case,
7275+
and there is at least one character in the string.
7276+
*/
7277+
bool is_title = (s_var.size() != 0);
7278+
7279+
bool in_word = false; // Represents if we are in a word or not
7280+
bool is_alpha_present = false;
7281+
for (auto &i : s_var) {
7282+
if (i >= 'A' && i <= 'Z') {
7283+
is_alpha_present = true;
7284+
if (in_word) {
7285+
// We have come across an uppercase character in the middle of a word
7286+
is_title = false;
7287+
break;
7288+
} else {
7289+
in_word = true;
7290+
}
7291+
} else if (i >= 'a' && i <= 'z') {
7292+
is_alpha_present = true;
7293+
if (!in_word) {
7294+
//We have come across a lowercase character at the start of a word
7295+
is_title = false;
7296+
break;
7297+
}
7298+
} else {
7299+
in_word = false;
7300+
}
7301+
}
7302+
is_title = is_title && is_alpha_present;
7303+
tmp = ASR::make_LogicalConstant_t(al, loc, is_title,
7304+
ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)));
7305+
return;
72757306
} else {
72767307
throw SemanticError("'str' object has no attribute '" + attr_name + "'", loc);
72777308
}

src/runtime/lpython_builtin.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -764,9 +764,7 @@ def _lpython_str_istitle(s: str) -> bool:
764764
ch: str
765765
only_whitespace: bool = True
766766
for ch in s:
767-
if (ch == ' ' or ch == '\t' or ch == '\n') and word_start:
768-
continue # Found a space character at the start of a word
769-
elif ch.isalpha() and (ord('A') <= ord(ch) and ord(ch) <= ord('Z')):
767+
if ch.isalpha() and (ord('A') <= ord(ch) and ord(ch) <= ord('Z')):
770768
only_whitespace = False
771769
if word_start:
772770
word_start = False

0 commit comments

Comments
 (0)