Skip to content

Commit a851b13

Browse files
authored
Merge pull request #1001 from Abdelrahman-Kh-Fouad/str@strip
Strings methods: `lstrip()`, `rstrip()`, `strip()`
2 parents c089957 + 8f6e426 commit a851b13

File tree

50 files changed

+228
-49
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+228
-49
lines changed

integration_tests/test_str_attributes.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,16 @@ def lower():
1515
assert s.lower() == "aaaaaabbbbbbbb!@12223bn"
1616
assert "DDd12Vv" .lower() == "ddd12vv"
1717

18+
def strip():
19+
s: str
20+
s = " AASAsaSas "
21+
assert s.rstrip() == " AASAsaSas"
22+
assert s.lstrip() == "AASAsaSas "
23+
assert s.strip() == "AASAsaSas"
24+
assert " AASAsaSas " .rstrip() == " AASAsaSas"
25+
assert " AASAsaSas " .lstrip() == "AASAsaSas "
26+
assert " AASAsaSas " .strip() == "AASAsaSas"
27+
1828
capitalize()
1929
lower()
30+
strip()

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4292,6 +4292,48 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
42924292
args.push_back(al, arg);
42934293
tmp = make_call_helper(al, fn_div, current_scope, args, "_lpython_str_lower", x.base.base.loc);
42944294
return;
4295+
} else if (std::string(at->m_attr) == std::string("rstrip")) {
4296+
if(args.size() != 0) {
4297+
throw SemanticError("str.srtrip() takes no arguments",
4298+
x.base.base.loc);
4299+
}
4300+
ASR::symbol_t *fn_div = resolve_intrinsic_function(x.base.base.loc, "_lpython_str_rstrip");
4301+
Vec<ASR::call_arg_t> args;
4302+
args.reserve(al, 1);
4303+
ASR::call_arg_t arg;
4304+
arg.loc = x.base.base.loc;
4305+
arg.m_value = se;
4306+
args.push_back(al, arg);
4307+
tmp = make_call_helper(al, fn_div, current_scope, args, "_lpython_str_rstrip", x.base.base.loc);
4308+
return;
4309+
} else if (std::string(at->m_attr) == std::string("lstrip")) {
4310+
if(args.size() != 0) {
4311+
throw SemanticError("str.lrtrip() takes no arguments",
4312+
x.base.base.loc);
4313+
}
4314+
ASR::symbol_t *fn_div = resolve_intrinsic_function(x.base.base.loc, "_lpython_str_lstrip");
4315+
Vec<ASR::call_arg_t> args;
4316+
args.reserve(al, 1);
4317+
ASR::call_arg_t arg;
4318+
arg.loc = x.base.base.loc;
4319+
arg.m_value = se;
4320+
args.push_back(al, arg);
4321+
tmp = make_call_helper(al, fn_div, current_scope, args, "_lpython_str_lstrip", x.base.base.loc);
4322+
return;
4323+
} else if (std::string(at->m_attr) == std::string("strip")) {
4324+
if(args.size() != 0) {
4325+
throw SemanticError("str.srtrip() takes no arguments",
4326+
x.base.base.loc);
4327+
}
4328+
ASR::symbol_t *fn_div = resolve_intrinsic_function(x.base.base.loc, "_lpython_str_strip");
4329+
Vec<ASR::call_arg_t> args;
4330+
args.reserve(al, 1);
4331+
ASR::call_arg_t arg;
4332+
arg.loc = x.base.base.loc;
4333+
arg.m_value = se;
4334+
args.push_back(al, arg);
4335+
tmp = make_call_helper(al, fn_div, current_scope, args, "_lpython_str_strip", x.base.base.loc);
4336+
return;
42954337
}
42964338
}
42974339
handle_attribute(se, at->m_attr, x.base.base.loc, eles);
@@ -4356,6 +4398,55 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
43564398
1, 1, nullptr, nullptr , 0));
43574399
tmp = ASR::make_StringConstant_t(al, x.base.base.loc, s2c(al, res), str_type);
43584400
return;
4401+
} else if (std::string(at->m_attr) == std::string("rstrip")) {
4402+
if(args.size() != 0) {
4403+
throw SemanticError("str.rstrip() takes no arguments",
4404+
x.base.base.loc);
4405+
}
4406+
AST::ConstantStr_t *n = AST::down_cast<AST::ConstantStr_t>(at->m_value);
4407+
std::string res = n->m_value;
4408+
int ind = res.size()-1;
4409+
while (ind >= 0 && res[ind] == ' '){
4410+
ind--;
4411+
}
4412+
res = std::string(res.begin(), res.begin() + ind +1);
4413+
ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, x.base.base.loc,
4414+
1, 1, nullptr, nullptr , 0));
4415+
tmp = ASR::make_StringConstant_t(al, x.base.base.loc, s2c(al, res), str_type);
4416+
return;
4417+
} else if (std::string(at->m_attr) == std::string("lstrip")) {
4418+
if(args.size() != 0) {
4419+
throw SemanticError("str.lstrip() takes no arguments",
4420+
x.base.base.loc);
4421+
}
4422+
AST::ConstantStr_t *n = AST::down_cast<AST::ConstantStr_t>(at->m_value);
4423+
std::string res = n->m_value;
4424+
int ind = 0;
4425+
while (ind < res.size() && res[ind] == ' ') {
4426+
ind++;
4427+
}
4428+
res = std::string(res.begin() + ind, res.end());
4429+
ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, x.base.base.loc,
4430+
1, 1, nullptr, nullptr , 0));
4431+
tmp = ASR::make_StringConstant_t(al, x.base.base.loc, s2c(al, res), str_type);
4432+
return;
4433+
} else if (std::string(at->m_attr) == std::string("strip")) {
4434+
if(args.size() != 0) {
4435+
throw SemanticError("str.strip() takes no arguments",
4436+
x.base.base.loc);
4437+
}
4438+
AST::ConstantStr_t *n = AST::down_cast<AST::ConstantStr_t>(at->m_value);
4439+
std::string res = n->m_value;
4440+
int l = 0 ,r = res.size() - 1;
4441+
while (l < res.size() && r >= 0 && (res[l] == ' ' || res[r] == ' ')) {
4442+
l += res[l] == ' ';
4443+
r -= res[r] == ' ';
4444+
}
4445+
res = std::string(res.begin() + l, res.begin() + r + 1);
4446+
ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, x.base.base.loc,
4447+
1, 1, nullptr, nullptr , 0));
4448+
tmp = ASR::make_StringConstant_t(al, x.base.base.loc, s2c(al, res), str_type);
4449+
return;
43594450
} else {
43604451
throw SemanticError("'str' object has no attribute '" + std::string(at->m_attr) + "'",
43614452
x.base.base.loc);

src/lpython/semantics/python_comptime_eval.h

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ struct PythonIntrinsicProcedures {
6363
{"max" , {m_builtin , &eval_max}},
6464
{"min" , {m_builtin , &eval_min}},
6565
{"_lpython_str_capitalize", {m_builtin, &eval__lpython_str_capitalize}},
66-
{"_lpython_str_lower", {m_builtin, &eval__lpython_str_lower}}
67-
66+
{"_lpython_str_lower", {m_builtin, &eval__lpython_str_lower}},
67+
{"_lpython_str_rstrip", {m_builtin, &eval__lpython_str_rstrip}},
68+
{"_lpython_str_lstrip", {m_builtin, &eval__lpython_str_lstrip}},
69+
{"_lpython_str_strip", {m_builtin, &eval__lpython_str_strip}}
6870
};
6971
}
7072

@@ -687,7 +689,59 @@ struct PythonIntrinsicProcedures {
687689
return ASR::down_cast<ASR::expr_t>(ASR::make_StringConstant_t(al, loc, s2c(al, val), res_type));
688690
}
689691

692+
static ASR::expr_t *eval__lpython_str_rstrip(Allocator &al, const Location &loc, Vec<ASR::expr_t *> &args) {
693+
LFORTRAN_ASSERT(ASRUtils::all_args_evaluated(args));
694+
if (args.size() != 0) {
695+
throw SemanticError("str.rstrip() takes no arguments", loc);
696+
}
697+
ASR::expr_t *arg = args[0];
698+
ASR::ttype_t *arg_type = ASRUtils::expr_type(arg);
699+
std::string res = ASR::down_cast<ASR::StringConstant_t>(arg)->m_s;
700+
int ind = res.size()-1;
701+
while (ind >= 0 && res[ind--] == ' ');
702+
res = std::string(res.begin(), res.begin() + ind +1);
703+
ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Character_t(al, loc,
704+
1, 1, nullptr, nullptr, 0));
705+
ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_StringConstant_t(al, loc, s2c(al, ""), type));
706+
return ASR::down_cast<ASR::expr_t>(ASR::make_StringConstant_t(al, loc, s2c(al, res), res_type));
707+
}
708+
709+
static ASR::expr_t *eval__lpython_str_lstrip(Allocator &al, const Location &loc, Vec<ASR::expr_t *> &args) {
710+
LFORTRAN_ASSERT(ASRUtils::all_args_evaluated(args));
711+
if (args.size() != 0) {
712+
throw SemanticError("str.lstrip() takes no arguments", loc);
713+
}
714+
ASR::expr_t *arg = args[0];
715+
ASR::ttype_t *arg_type = ASRUtils::expr_type(arg);
716+
std::string res = ASR::down_cast<ASR::StringConstant_t>(arg)->m_s;
717+
int ind = 0;
718+
while (ind < res.size() && res[ind++] == ' ');
719+
res = std::string(res.begin() + ind, res.end());
720+
ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Character_t(al, loc,
721+
1, 1, nullptr, nullptr, 0));
722+
ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_StringConstant_t(al, loc, s2c(al, ""), type));
723+
return ASR::down_cast<ASR::expr_t>(ASR::make_StringConstant_t(al, loc, s2c(al, res), res_type));
724+
}
690725

726+
static ASR::expr_t *eval__lpython_str_strip(Allocator &al, const Location &loc, Vec<ASR::expr_t *> &args) {
727+
LFORTRAN_ASSERT(ASRUtils::all_args_evaluated(args));
728+
if (args.size() != 0) {
729+
throw SemanticError("str.strip() takes no arguments", loc);
730+
}
731+
ASR::expr_t *arg = args[0];
732+
ASR::ttype_t *arg_type = ASRUtils::expr_type(arg);
733+
std::string res = ASR::down_cast<ASR::StringConstant_t>(arg)->m_s;
734+
int l = 0 ,r = res.size() - 1;
735+
while (l < res.size() && r >= 0 && (res[l] == ' ' || res[r] == ' ')) {
736+
l += res[l] == ' ';
737+
r -= res[r] == ' ';
738+
}
739+
res = std::string(res.begin() + l, res.begin() + r + 1);
740+
ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Character_t(al, loc,
741+
1, 1, nullptr, nullptr, 0));
742+
ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_StringConstant_t(al, loc, s2c(al, ""), type));
743+
return ASR::down_cast<ASR::expr_t>(ASR::make_StringConstant_t(al, loc, s2c(al, res), res_type));
744+
}
691745
}; // ComptimeEval
692746

693747
} // namespace LFortran

src/runtime/lpython_builtin.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ def _lpython_str_capitalize(x: str) -> str:
626626
return x
627627

628628
@overload
629-
def _lpython_str_lower(x: str) ->str:
629+
def _lpython_str_lower(x: str) -> str:
630630
res: str
631631
res = ""
632632
i:str
@@ -636,3 +636,26 @@ def _lpython_str_lower(x: str) ->str:
636636
else:
637637
res += i
638638
return res
639+
640+
@overload
641+
def _lpython_str_rstrip(x: str) -> str:
642+
ind: i32
643+
ind = len(x) - 1
644+
while ind >= 0 and x[ind] == ' ':
645+
ind -= 1
646+
return x[0: ind + 1]
647+
648+
@overload
649+
def _lpython_str_lstrip(x: str) -> str:
650+
ind :i32
651+
ind = 0
652+
while ind < len(x) and x[ind] == ' ':
653+
ind += 1
654+
return x[ind :len(x)]
655+
656+
@overload
657+
def _lpython_str_strip(x: str) -> str:
658+
res :str
659+
res = _lpython_str_lstrip(x)
660+
res = _lpython_str_rstrip(res)
661+
return res

tests/reference/asr-complex1-f26c460.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-complex1-f26c460.stdout",
9-
"stdout_hash": "0fb9cae39aefa01c8744f5657e256f05bb9efa74fefed59000535758",
9+
"stdout_hash": "339be2545e1bb94b7c1e71af21f5261ffce5abd8d202a8767f1a47f4",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

0 commit comments

Comments
 (0)