Page 1 of 1

Find matching brackets (or other nested tag pairs)

Posted: Sun Oct 09, 2016 6:32 am
by Lunasole
Hi once more. Here is some stuff which can parse nested brackets or other tags.
Tag len currently is limited to 1 char, but can be easily modified to fit any len.
Also it's not too optimized, I've just made it 30 min ago for "let it do what needed" ^^
But should be fine enough anyway. Additionaly, some error-correction added for cases when opening or closing tag is missing.

Code: Select all

EnableExplicit


; v 1.0.0.1
;	2016			(c) Luna Sole

; returns array with string data between matching pair of 2 specified chars
; StrIn$		a string to parse
; Char1$		character which opens pair
; Char2$		closing character
; UseWildcards	if true, then wildcards like "Char1$ + % + INDEX + % + Char2$" are used instead of nested pairs
; RETURN:		number of pairs found and data placed to Out$() array starting from index 1
Procedure GetPairs (Array Out$(1), StrIn$, Char1$ = "[", Char2$ = "]", UseWildcards = #False)
	Protected CntMin, LenMax = Len(StrIn$)
	Protected Dim Chars1.POINT(LenMax), Cnt1, Tmp1 ; the X field used to mark Char1 positions
	Protected Dim Chars2.POINT(LenMax), Cnt2, Tmp2 ; Y - to mark Char2
	Protected Tmp, tChr$ = " "
	Protected OutCount

	; step 1, mark all matches
	For Tmp = 1 To LenMax
		PokeC(@tChr$, PeekC(@StrIn$ + (Tmp - 1) * SizeOf(Character))) ; tChr$ = Mid(StrIn$, Tmp, 1)
		If tChr$ = Char1$ 
			Cnt1 + 1	; opening char found
			Chars1(Cnt1)\x = Tmp
		ElseIf tChr$ = Char2$ 
			Cnt2 + 1	; closing char
			Chars2(Cnt2)\y = Tmp
		EndIf
	Next Tmp
	
	; step 2, fix mismatches + prepare output buffer
	If Cnt1 > Cnt2
		Cnt2 + 1
		CntMin = 1
		Chars2(Cnt2)\y = LenMax
		Dim Out$(Cnt1)
	ElseIf Cnt2 > Cnt1
		Chars1(0)\x = 1
		CntMin = 0
		Dim Out$(Cnt2)
	Else
		CntMin = 1
		Dim Out$(Cnt1)
	EndIf

	; step 3, collect results
	For Tmp1 = Cnt1 To CntMin Step -1
		For Tmp2 = 1 To Cnt2
			If Chars2(Tmp2)\y > Chars1(Tmp1)\x
				Chars1(Tmp1)\y = Chars2(Tmp2)\y
				OutCount + 1
				If UseWildcards And OutCount > 1
					If Chars1(Tmp1 + 1)\x >= Chars1(Tmp1)\x And Chars1(Tmp1 + 1)\y <= Chars1(Tmp1)\y
						; add result with wildcard
						Out$(OutCount) = Mid(StrIn$, Chars1(Tmp1)\x, Chars1(Tmp1 + 1)\x - Chars1(Tmp1)\x) + 
						                 Char1$ + "%" + Str(OutCount - 1) + "%" + Char2$ + 
						                 Mid(StrIn$, Chars1(Tmp1 + 1)\y + 1, Chars1(Tmp1)\y - Chars1(Tmp1 + 1)\y)  
					Else
						Out$(OutCount) = Mid(StrIn$, Chars1(Tmp1)\x, 1 + Chars1(Tmp1)\y - Chars1(Tmp1)\x)
					EndIf
				Else
					; add raw result
					Out$(OutCount) = Mid(StrIn$, Chars1(Tmp1)\x, 1 + Chars1(Tmp1)\y - Chars1(Tmp1)\x)
				EndIf
				
				Chars2(Tmp2)\y = -1
				Break
			EndIf
		Next Tmp2
	Next Tmp1
	
	; fin
	ProcedureReturn OutCount
EndProcedure


;;;;;;;;;
; usage ;
Global Dim T$(0)
Global Tmp


Debug Str(GetPairs(T$(), "[0][1][2][5[6]]", "[", "]", 1)) + " found:" ; that doesn't work OK in previous version
For Tmp = 1 To ArraySize(T$())
	Debug T$(Tmp)
Next Tmp
Debug ""

Debug Str(GetPairs(T$(), "[000[11[2[33]2]11]000]", "[", "]", 1)) + " found:"
For Tmp = 1 To ArraySize(T$())
	Debug T$(Tmp)
Next Tmp
Debug ""

; here should be example using recursive wildcards expanding, but looks like I'm too lazy to finish it today ^^
; Out$(Count) = ReplaceString(Out$(Count), Char1$ + "%" + Str(Count - 1) + "%" + Char2$, Out$(Count-1))

Re: Find matching brackets (or other nested tag pairs)

Posted: Sun Oct 09, 2016 4:15 pm
by Lunasole
Updated because of bug fixes / improvements

Re: Find matching brackets (or other nested tag pairs)

Posted: Mon Oct 10, 2016 10:42 am
by Kwai chang caine
I don't know, what is the real use of this code, but it works very well
Thanks for sharing 8)

Re: Find matching brackets (or other nested tag pairs)

Posted: Wed Oct 12, 2016 7:42 pm
by Lunasole
Kwai chang caine wrote:I don't know, what is the real use of this code
Nice question, btw, as I don't know it too ^^

Well, years ago I've used it to parse some server configs of Lineage II server. The current version posted here is extended and improved version of that old code (originally it was "just another custom algorithm used for single specific case").
So I did newer version of it "for fun"... or just because I've remembered it being smoked out. Not sure and doesn't matter :3 Probably there will be a case to use this.

Re: Find matching brackets (or other nested tag pairs)

Posted: Thu Oct 13, 2016 10:38 am
by Kwai chang caine
Nice question, btw, as I don't know it too ^^
:lol:
Personally, it's not the first time i create a code i don't understand, even nearly all the days :mrgreen: :oops:
But never i create a code, i don't know why ? :lol:

Thanks also for your explanation :wink: 8)