Page 1 of 1

Identifying a command within a line

Posted: Wed Jan 16, 2008 8:28 am
by Mistrel
I have a tool that looks for command keyword on a line and changes it, i.e.: "Find all instances of Procedure and change it to ProcedureC".

This is the procedure I'm using for this. Can anyone tell if I'm missing any cases?

Code: Select all

Procedure KeyPart(string.s,keypart.s)
	If CountString(string.s,keypart.s)
		ProcedureReturn 1
	EndIf
EndProcedure

Procedure FindCommand(String.s,StringToFind.s)
	Macro fcEndCase()
		; check for comment character and endcase
		:If pos And Not KeyPart(Left(String.s,pos-1),";")
		:Exists=1: ProcedureReturn Exists
		:EndIf
	EndMacro
	String.s=LCase(String.s): StringToFind.s=LCase(StringToFind.s)
	pos=FindString(String.s,Chr(9)+StringToFind.s+Chr(9),1):fcEndCase(); (tab)string(tab)
	pos=FindString(String.s,Chr(9)+StringToFind.s+":",1):fcEndCase(); (tab)string:
	pos=FindString(String.s,Chr(9)+StringToFind.s+".",1):fcEndCase(); (tab)string.
	pos=FindString(String.s,Chr(9)+StringToFind.s+";",1):fcEndCase(); (tab)string;
	pos=FindString(String.s,":"+StringToFind.s+Chr(9),1):fcEndCase(); :string(tab)
	pos=FindString(String.s,":"+StringToFind.s+":",1):fcEndCase(); :string:
	pos=FindString(String.s,":"+StringToFind.s+".",1):fcEndCase(); :string.
	pos=FindString(String.s,":"+StringToFind.s+";",1):fcEndCase(); :string;
	pos=FindString(String.s," "+StringToFind.s+" ",1):fcEndCase(); (s)string(s)
	pos=FindString(String.s," "+StringToFind.s+":",1):fcEndCase(); (s)string:
	pos=FindString(String.s," "+StringToFind.s+".",1):fcEndCase(); (s)string.
	pos=FindString(String.s," "+StringToFind.s+";",1):fcEndCase(); (s)string;
	pos=FindString(String.s,":"+StringToFind.s+" ",1):fcEndCase(); :string(s)
	pos=FindString(String.s,Chr(9)+StringToFind.s+" ",1):fcEndCase(); (tab)string(s)
	pos=FindString(String.s," "+StringToFind.s+Chr(9),1):fcEndCase(); (s)string(tab)
	pos=Left(String.s,Len(StringToFind.s)+1)=StringToFind.s+Chr(9):fcEndCase(); |string(tab)
	pos=Left(String.s,Len(StringToFind.s)+1)=StringToFind.s+" ":fcEndCase(); |string(s)
	pos=Left(String.s,Len(StringToFind.s)+1)=StringToFind.s+":":fcEndCase(); |string:
	pos=Left(String.s,Len(StringToFind.s)+1)=StringToFind.s+".":fcEndCase(); |string.
	pos=Left(String.s,Len(StringToFind.s)+1)=StringToFind.s+";":fcEndCase(); |string;
	pos=Right(String.s,Len(StringToFind.s)+1)=Chr(9)+StringToFind.s:fcEndCase(); (tab)string(crlf)
	pos=Right(String.s,Len(StringToFind.s)+1)=" "+StringToFind.s:fcEndCase(); (s)string(crlf)
	pos=Right(String.s,Len(StringToFind.s)+1)=":"+StringToFind.s:fcEndCase(); :string(crlf)
	If String.s=StringToFind.s; |string(crlf)
		Exists=1
	EndIf
	ProcedureReturn Exists
EndProcedure

Posted: Wed Jan 16, 2008 2:31 pm
by Trond
"Find all instances of Procedure and change it to ProcedureC"
Have you tried ReplaceString()?

Posted: Wed Jan 16, 2008 2:51 pm
by PB
> Have you tried ReplaceString()?

No good if he wants to replace just the word "Procedure":

"ProcedureReturn 1" would become "ProcedureC 1"
"ProcedureDLL" would become "ProcedureC"

and so on.

Posted: Wed Jan 16, 2008 3:21 pm
by #NULL
you can replace "Procedure "

Posted: Wed Jan 16, 2008 3:30 pm
by PB
> you can replace "Procedure "

That won't work with Procedure.s, Procedure.l, etc; but I guess there's
nothing stopping replacing "Procedure." with "ProcedureC." though. :)

Posted: Wed Jan 16, 2008 3:33 pm
by Dare
:)

But Trond is basically right, unless you are writing a full blown parser of some sort.

Code: Select all

  src = ReplaceString(src,"Procedure","ProcedureC",1,1)
  src = ReplaceString(src,"ProcedureCReturn","ProcedureReturn",1,1)
  src = ReplaceString(src,"EndProcedureC","EndProcedure",1,1)
;  src = ReplaceString(src,"ProcedureCDLL","ProcedureDLL",1,1)     ; if not to be 'c'ed.

Edit:

Is it "procedure" embedded in strings and after ";" that concerns you?

Posted: Wed Jan 16, 2008 8:44 pm
by Mistrel
PB wrote:> you can replace "Procedure "

That won't work with Procedure.s, Procedure.l, etc; but I guess there's
nothing stopping replacing "Procedure." with "ProcedureC." though. :)
Thanks. I forgot about the procedures with a return type. I also forgot the possibility of a trailing comment.

I've updated my the code in my first post with the changes. I think this covers every case.

Posted: Thu Jan 17, 2008 7:50 am
by superadnim
Try using a stack, it'll open doors for other parsing options as well.

Posted: Thu Jan 17, 2008 8:20 am
by Mistrel
superadnim wrote:Try using a stack, it'll open doors for other parsing options as well.
What would I need a stack for if I parse everything in a single pass?

Posted: Thu Jan 17, 2008 9:09 am
by Hroudtwolf
I recommend an lexical analysis with a tokenizer.
On big sources, it would be faster.

Example for tokenizing:

Code: Select all

MyProc (lMyVar)
; Comment

Code: Select all

Token             Typ
-------------------------------------------
MyProc         |  Identifier 
(              |  Open bracket
lMyVar         |  Identifier
)              |  Closed bracket
; Comment      |  Comment