If/EndIf for IDE autoindent

Blitz3D Forums/Blitz3D Programming/If/EndIf for IDE autoindent

After using IDEal, and finding it's the best IDE I've ever used, I noticed it can't tell which If's need an endif and which don't. So I made this function. It was hard as HELL!

This takes a line of blitz3d code that begins with "If" and tells if it needs and EndIf (and thus the next line should be indented.)

Anyone want to test it? There could be bugs.
Does anyone have a better way of doing it or a way of optimizing it?
Trixx: wanna put it in IDEal?


Here's a test program.
Graphics 800,600

Dim tests$(20)
;should need endif:
tests(1)="If a Then"
tests(2)="If 3And b"
tests(3)="If Not x_"
tests(4)="If a12.go"
tests(5)="If array[get( -14+1 )]> 5 -b"
tests(6)="If First bullet <> Null"
tests(7)="If guy.guy\target\x# + basex=10.5"
tests(8)="If x$="+Chr(34)+"a Then b"+Chr(34)
tests(9)="If Andy>Joe Or(will_not)"
tests(10)="If(jim.person)"
;should not need endif:
tests(11)="If a Thenn"
tests(12)="If a3And b"
tests(13)="If Not2 x_"
tests(14)="If 12.go"
tests(15)="If array[get( -14+1 )]> 5 b"
tests(16)="If Not(car\moving)go(car)"
tests(17)="If(x#>5)x#=5"
tests(18)="If b_52(52, 12) Then x=10"
tests(19)="If x2#=(15 Xor %10) Or y% End"
tests(20)="If RectsOverlap(t2\x-t2\sizex/2,t2\y-t2\sizey/2,t2\sizex,t2\sizey, b\x-gl\tnow\sizex/2,b\y-gl\tnow\sizey/2,gl\tnow\sizex,gl\tnow\sizey) die(1)"

For i=1 To 20
	Write "Test "+i+" "
	If needsendif(tests(i)) Then
		Write "needs EndIf: "
	Else
		Write "is okay    : "
	EndIf
	Print tests(i)
Next

WaitKey
End



;Returns 1 if the string is a If statment that would require and EndIf
;Assumes s$ is a string that starts with "If"
;Assumes no syntax errors.
Function NeedsEndIf(s$)
	
	;How it works:
	;If "a" refers to any letter or number or underscore.
	;The only possible ways for it to not need an endif are:
	;a a
	;)a
	;]a
	;"a
	
	Local lastchar$
	Local char$
	Local space
	Local add
	Local quote
	Local i
	Local lastwordwasnumber
	
	s=Lower(s)
	
	
	For i=3 To Len(s)
		char=Mid(s,i,1)
		
		;Keep track of whether we are in quotes.
		If char=Chr(34) Then
			quote=Not quote
			lastchar=char
			
		ElseIf quote=0 Then
			
			;Ignore optional symbols and decimal points.
			If char<>"%" And char<>"#" And char<>"$" And char<>"." Then
				
				If lastchar<>"" Then
					;Check for a separation of words.
					If space=1 Or lastchar=")" Or lastchar="]" Or lastchar=Chr(34) Or (lastwordwasnumber And isletter(char)) Then
						;Check for starting of a new word.
						If isletter(char) Or isnumber(char) Then
							;Check if it's a "Then"
							If char="t" Then
								If Len(s)>=i+3 Then
									If Mid(s,i,4)="then" Then
										If Len(s)=i+3 Then Return True
										If Mid(s,i+4)=" " Then Return True
									EndIf
								EndIf
							EndIf
							;Check if it's ok to have 2 words in a row as one line.
							add=isoperator(s,i)
							If add=0 Then
								Return False
							Else
								i=i+add
							EndIf
						EndIf
					EndIf
				EndIf
				
				space=0
				If char=" " Then
					space=1
					lastwordwasnumber=0
					
					;Ignore unary operators.
					If isunary(s,i) Then
						lastchar=""
					EndIf
				ElseIf isletter(char) Or isnumber(char) Or char="_" Or char=")" Or char="]" Then
					If isnumber(char) Then
						;for the rare case of "If 4go()" or "If 2And a"
						If lastchar="" Then
							lastwordwasnumber=1
						EndIf
					Else
						lastwordwasnumber=0
					EndIf
					lastchar=char
				Else
					lastchar=""
				EndIf
			EndIf
		EndIf
	Next
	
	Return True
	
End Function


;Checks if there is a text binary operator here
Function IsOperator(s$,i)
	Local add
	
	If Mid(s,i,3)="and" Then
		add=3
	ElseIf Mid(s,i,2)="or" Then
		add=2
	ElseIf Mid(s,i,3)="xor" Then
		add=3
	Else
		Return 0
	EndIf
	
	;Make sure it isnt actually a variable like android.
	If Mid(s,i+add,1)=" " Or Mid(s,i+add,1)="(" Then
		Return add
	Else
		Return 0
	EndIf
End Function

;Checks if there is a text unary operator on the left
Function IsUnary(s$,i)
	Local add
	
	If i<6 Then Return
	
	If Mid(s,i-5,5)="first" Then
		add=5
	ElseIf Mid(s,i-4,4)="last" Then
		add=4
	ElseIf Mid(s,i-3,3)="not" Then
		add=3
	Else
		Return 0
	EndIf
	
	;Make sure it isnt actually a variable like cannot.
	Local m$
	m=Mid(s,i-add-1,1)
	If isletter(m)=0 And isnumber(m)=0 And m<>"_" Then
		Return 1
	Else
		Return 0
	EndIf
End Function

Function IsNumber(char$)
	Return char="0" Or Int(char)>0
End Function

Function IsLetter(char$)
	Return (char>="a" And char<="z")
End Function


I wrote this a while back, you might be able to use it?

http://www.blitzbasic.com/codearcs/codearcs.php?code=1229

Actually you should be able to use my code to help your indent program.
Times it will NOT work:
If you've got if statements without 'then' formed like 'If a=true a=false'

My code solves that problem. That is the only purpose of my code.