Skip to content

Commit 4548310

Browse files
committed
parser: support ->a()->b()->c()
1 parent 28f5fb3 commit 4548310

File tree

2 files changed

+109
-24
lines changed

2 files changed

+109
-24
lines changed

resources/minitscript/tests/string-test.tscript

+1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ function: main()
1919
if (String::regexSearch("Who is this Andreas0815?", "Andreas([0-9]*)", $matches) == true)
2020
console.printLine('String::regexSearch("Who is this Andreas0815?", "Andreas([0-9]*)", $matches): ' + $matches)
2121
end
22+
console.printLine("\" ABCDEF \"->toLowerCase()->trim(): " + " ABCDEF "->toLowerCase()->trim());
2223
end

src/minitscript/minitscript/MinitScript.cpp

+108-24
Original file line numberDiff line numberDiff line change
@@ -2865,6 +2865,76 @@ const string MinitScript::doStatementPreProcessing(const string& processedStatem
28652865
return trimArgument(argument, removeBrackets);
28662866
};
28672867
//
2868+
auto findNextMemberExecutionStatement = [&](const string& statement, int position, int& length) -> const string {
2869+
//
2870+
auto bracketCount = 0;
2871+
auto squareBracketCount = 0;
2872+
auto curlyBracketCount = 0;
2873+
auto quote = '\0';
2874+
auto lc = '\0';
2875+
string executionStatement;
2876+
length = 0;
2877+
for (auto i = position; i < statement.size(); i++) {
2878+
auto c = statement[i];
2879+
auto nc = i + 1 < statement.size()?statement[i + 1]:'\0';
2880+
// quote?
2881+
if ((c == '"' || c == '\'') && lc != '\\') {
2882+
if (quote == '\0') {
2883+
quote = c;
2884+
} else
2885+
if (quote == c) {
2886+
quote = '\0';
2887+
}
2888+
executionStatement+= c;
2889+
} else
2890+
// no quote
2891+
if (quote == '\0') {
2892+
if (c == '(') {
2893+
bracketCount++;
2894+
executionStatement+= c;
2895+
} else
2896+
if (c == '[') {
2897+
squareBracketCount++;
2898+
executionStatement+= c;
2899+
} else
2900+
if (c == '{') {
2901+
curlyBracketCount++;
2902+
executionStatement+= c;
2903+
} else
2904+
if (c == ')') {
2905+
bracketCount--;
2906+
executionStatement+= c;
2907+
} else
2908+
if (c == ']') {
2909+
squareBracketCount--;
2910+
executionStatement+= c;
2911+
} else
2912+
if (c == '}') {
2913+
curlyBracketCount--;
2914+
executionStatement+= c;
2915+
} else
2916+
if (squareBracketCount == 0 && curlyBracketCount == 0 && bracketCount == 0 && lc == '-' && c == '>') {
2917+
length++;
2918+
return trimArgument(executionStatement);
2919+
} else {
2920+
if (squareBracketCount == 0 && curlyBracketCount == 0 && bracketCount == 0 && c == '-' && nc == '>') {
2921+
// no op
2922+
} else {
2923+
executionStatement+= c;
2924+
}
2925+
}
2926+
} else
2927+
if (quote != '\0') {
2928+
executionStatement+= c;
2929+
}
2930+
length++;
2931+
//
2932+
lc = lc == '\\' && c == '\\'?'\0':c;
2933+
}
2934+
//
2935+
return trimArgument(executionStatement);
2936+
};
2937+
//
28682938
auto viewIsLamdaFunctionWithoutArgumentsHead = [](const string_view& candidate, int& i) -> bool {
28692939
//
28702940
i = 0;
@@ -3456,41 +3526,55 @@ const string MinitScript::doStatementPreProcessing(const string& processedStatem
34563526
string rightArgumentBrackets;
34573527
int rightArgumentLength = 0;
34583528
auto rightArgument = findRightArgument(preprocessedStatement, nextOperator.idx + operatorString.size(), rightArgumentLength, rightArgumentBrackets);
3459-
// object member access
3460-
string_view subMethodName;
3461-
vector<ParserArgument> subArguments;
3462-
//
3463-
if (parseStatement(rightArgument, subMethodName, subArguments, statement) == false) {
3464-
Console::printLine(getStatementInformation(statement, getStatementSubLineIdx(preprocessedStatement, nextOperator.idx)) + ": " + method->getMethodName() + ": Could not parse statement: " + rightArgument);
3465-
scriptValid = false;
3466-
return preprocessedStatement;
3467-
}
34683529
//
3469-
string arguments;
3470-
// TODO: not required really, would require string operations on validation
3471-
// arguments+= "\"" + string(subMethodName) + "\"";
3472-
arguments+= string(subMethodName);
3473-
arguments+= ", " + to_string(encodeOperatorString(operatorString));
3474-
for (const auto& argument: subArguments) {
3475-
arguments+= ", " + string(argument.argument);
3530+
auto leftArgumentNewLines = 0;
3531+
for (auto i = 0; i < leftArgument.size(); i++) {
3532+
auto c = leftArgument[i];
3533+
if (c == '\n') leftArgumentNewLines++; else break;
34763534
}
3535+
// find member execution statements
3536+
string memberExecutionStatementMethodCall;
3537+
string memberExecutionStatement;
3538+
auto memberExecutionStatementPosition = 0;
3539+
auto memberExecutionStatementLength= 0;
3540+
while(true == true) {
3541+
// extract member execution statement
3542+
memberExecutionStatement = findNextMemberExecutionStatement(
3543+
rightArgument,
3544+
memberExecutionStatementPosition,
3545+
memberExecutionStatementLength
3546+
);
3547+
memberExecutionStatementPosition+= memberExecutionStatementLength;
3548+
if (memberExecutionStatement.empty() == true) break;
3549+
// extract method name and arguments
3550+
string_view subMethodName;
3551+
vector<ParserArgument> subArguments;
3552+
if (parseStatement(memberExecutionStatement, subMethodName, subArguments, statement) == false) {
3553+
Console::printLine(getStatementInformation(statement, getStatementSubLineIdx(preprocessedStatement, nextOperator.idx)) + ": " + method->getMethodName() + ": Could not parse statement: " + rightArgument);
3554+
scriptValid = false;
3555+
return preprocessedStatement;
3556+
}
3557+
// generate method call
3558+
string arguments;
3559+
arguments+= string(subMethodName);
3560+
arguments+= ", " + to_string(encodeOperatorString(operatorString));
3561+
for (const auto& argument: subArguments) {
3562+
arguments+= ", " + string(argument.argument);
3563+
}
3564+
memberExecutionStatementMethodCall = method->getMethodName() + "(" + leftArgument + ", " + arguments + ")";
3565+
// next left argument is our generated method call
3566+
leftArgument = memberExecutionStatementMethodCall;
3567+
};
34773568
//
34783569
if (leftArgument.empty() == true || rightArgument.empty() == true) {
34793570
Console::printLine(getStatementInformation(statement, getStatementSubLineIdx(preprocessedStatement, nextOperator.idx)) + ": " + method->getMethodName() + ": Requires left and right argument");
34803571
scriptValid = false;
34813572
return preprocessedStatement;
34823573
}
3483-
//
3484-
auto leftArgumentNewLines = 0;
3485-
for (auto i = 0; i < leftArgument.size(); i++) {
3486-
auto c = leftArgument[i];
3487-
if (c == '\n') leftArgumentNewLines++; else break;
3488-
}
34893574
// substitute with method call
34903575
preprocessedStatement =
34913576
StringTools::substring(preprocessedStatement, 0, nextOperator.idx - leftArgumentLength) +
3492-
StringTools::generate("\n", leftArgumentNewLines) +
3493-
method->getMethodName() + "(" + StringTools::substring(leftArgument, leftArgumentNewLines) + ", " + arguments + ")" +
3577+
StringTools::generate("\n", leftArgumentNewLines) + memberExecutionStatementMethodCall +
34943578
StringTools::substring(preprocessedStatement, nextOperator.idx + operatorString.size() + rightArgumentLength, preprocessedStatement.size()
34953579
);
34963580
//

0 commit comments

Comments
 (0)