Member
|
03-08-2020
, 11:03
Parsing a string
|
#1
|
Greetings,
I am trying to make a simple parser for this notation:
PHP Code:
Example 1: "(some,(weird,string),list)"
Example 2: "(some,weird,string,list)"
Example 3: "(some,weird,string,list,(with,(more,random),words))"
I want to split it to multiple parts separated by comma.
Let me give you an example:
For this input:
PHP Code:
(some,weird,string,list,(with,(more,random),words))
I want this output:
PHP Code:
some
weird
string
list
(with,(more,random),words)
I have written this code, but it gives me the error which I can not solve:
PHP Code:
#include <amxmodx>
#define MAX_PARTS 64
#define MAX_PART_LENGTH 256
public plugin_init() {
register_plugin("Text Parse Test", "1.0", "Author");
RunTests();
}
stock Parse(const text[], parts[][], partNumbers, partLength) {
if(!IsValidFormat(text))
return 0;
if(partNumbers > MAX_PARTS || partLength > MAX_PART_LENGTH) {
partNumbers = MAX_PARTS;
partLength = MAX_PART_LENGTH;
}
new textLength = strlen(text);
new i, currentChar;
new bool: foundFirst = false;
new bool: inASubstring = false;
new tempPart = 0;
new tempParts[MAX_PARTS][MAX_PART_LENGTH];
new tempLength = 0;
for(i = 0; i < textLength; i ++) {
currentChar = text[i];
// Break if there are more than MAX_MARTS parts
if(tempPart > MAX_PARTS)
break;
// Skip first '('
if(!foundFirst && currentChar == '(') {
foundFirst = true;
continue;
}
// Enter to the substring
else if(foundFirst && currentChar == '(')
inASubstring = true;
// Skip last ')'
if(i == textLength - 1 && currentChar == ')')
continue;
// Exit the substring
else if(currentChar == ')')
inASubstring = false;
// Skip ',' and move on to the next part if not in a substring
if(!inASubstring && currentChar == ',') {
tempParts[tempPart][tempLength] = EOS;
tempLength = 0;
tempPart ++;
continue;
}
// Truncate over MAX_PART_LENGTH
if(tempLength > MAX_PART_LENGTH) {
tempLength = MAX_PART_LENGTH;
tempParts[tempPart][tempLength] = EOS;
tempLength = 0;
tempPart ++;
continue;
}
tempParts[tempPart][tempLength ++] = currentChar;
}
for(new x = 0; x < partNumbers; x ++)
copy(parts[x], partLength, tempParts[x]);
return tempPart;
}
stock bool: IsValidFormat(const text[]) {
new fistParentheses = indexOf(text, '(');
new lastParentheses = lastIndexOf(text, ')');
// If the text does not contain '(' and ')' at all, abort
if(fistParentheses == -1 || lastParentheses == -1)
return false;
// If the text does not start with '(' and end with ')', abort
if(!(fistParentheses == 0 && lastParentheses == strlen(text) - 1))
return false;
return true;
}
stock indexOf(const text[], const character, bool: last = false) {
new textLength = strlen(text);
new i, lastIndex = -1;
for(i = 0; i < textLength; i ++) {
if(text[i] == character) {
lastIndex = i;
if(!last)
break;
}
}
return lastIndex;
}
stock lastIndexOf(const text[], const character)
return indexOf(text, character, true);
stock RunTests() {
TestIndexOf("indexOf & lastIndexOf");
TestValidFormat("valid format");
TestParse("parse");
}
stock TestIndexOf(const test[]) {
new text[64];
copy(text, charsmax(text), "(some,(weird,string),list)");
server_print("[Test: %s] Text: %s (Length: %d) - Found '(': %s (%d) | Found: ')': %s (%d) - Is accurate: %s", test,
text, strlen(text), indexOf(text, '(') != -1 ? "Yes" : "No", indexOf(text, '('), lastIndexOf(text, ')') != -1 ? "Yes" : "No",
lastIndexOf(text, ')'), indexOf(text, '(') == 0 && lastIndexOf(text, ')') == 25 ? "Yes" : "No" );
}
stock TestValidFormat(const test[]) {
new sample[4][64];
copy(sample[0], charsmax(sample[]), "(some,(weird,string),list)");
copy(sample[1], charsmax(sample[]), "(some,(weird,string),list");
copy(sample[2], charsmax(sample[]), "some,(weird,string),list)");
copy(sample[3], charsmax(sample[]), "some,(weird,string),list");
for(new i = 0; i < 4; i ++)
server_print("[Test: %s] Sample %d is valid format?: %s", test, i + 1, IsValidFormat(sample[i]) ? "Yes" : "No");
}
stock TestParse(const test[]) {
new text[512];
copy(text, charsmax(text), "(some,(weird,string),list,1234,,(more,text,in,a,substring),some,more,$$$,###,@annotation)");
new parts[12][128];
new partsNumber = Parse(text, parts, 12, 128);
if(partsNumber > 0) {
for(new i = 0; i < partsNumber; i ++)
server_print("[Test: %s] Parsed part %d/%d: %s", test, i, partsNumber, parts[i]);
} else server_print("[Test: %s] Failed to parse, 0 parts returned!", test);
}
Error:
PHP Code:
L 03/08/2020 - 15:48:09: Start of error session.
L 03/08/2020 - 15:48:09: Info (map "de_dust2") (file "addons/amxmodx/logs/error_20200308.log")
L 03/08/2020 - 15:48:09: [AMXX] Displaying debug trace (plugin "test_parse.amxx")
L 03/08/2020 - 15:48:09: [AMXX] Run time error 3: stack error
L 03/08/2020 - 15:48:09: [AMXX] [0] parser.sma::Parse (line 27)
L 03/08/2020 - 15:48:09: [AMXX] [1] parser.sma::TestParse (line 145)
L 03/08/2020 - 15:48:09: [AMXX] [2] parser.sma::RunTests (line 117)
L 03/08/2020 - 15:48:09: [AMXX] [3] parser.sma::plugin_init (line 9)
I know this has to do somthing with the stack of the Pawn Amxx VM, but I am not sure what is the exact problem.
I have tried this, but got the same resoults:
PHP Code:
#define MAX_PARTS 64
#define MAX_PART_LENGTH 256
Can you help me?
Thank you.
Last edited by Ludak; 03-21-2020 at 06:27.
|
|