Page 1 of 1

Reworking batch/cmd syntax into a user defined syntax

Posted: 05 Nov 2009 20:15
by isacmahad
This is a re-post from a previous question I had asked on this forum about parsing strings and processing bytes/chars one at a time and comparing them as you go along. I myself do not have all the answers to what I am trying to accomplish so I reached out for help here. The idea is simple.
Here are some specs that need to be incorporated.

1) Create a batch script capable of processing an external user defined script.
2) Define the syntax for the external script inside the main batch script.
3) Incorporate functions for string and byte processing (xml,html.etc...)
4) Only use native batch scripting(No 3rd party resources or scripting host, however later on when spiders,etc...are needed(incorporate those utilities into the build of the batch or rather offer support for))

Example of the main batch source used to process the external script.

Code: Select all

@echo off
 setlocal
 set var=0
 set val=1
 set Script=%1

:FUNCTION_[GrabString]
REM Grab the current string in the script to process
for /f "tokens=* skip=%val%" %%- in (%Script%) do (
call set "str=%%-"&&set /a val=%val%+1&&goto :FUNCTION_[ParseString]
)

:FUNCTION_[ParseString]
REM Parse the first token to retrieve the keyword symbol or command
for /f "tokens=1" %%- in ("%str%") do (
       if /i "%%-"=="-"               (call :FUNCTION_[EchoString]
) else if /i "%%-"=="->"              (call :FUNCTION_[EchoBlock]
) else if /i "%%-"=="//"              (call :FUNCTION_[SingleComment]
) else if /i "%%-"=="/*"              (call :FUNCTION_[CommentBlock]

REM These are the keyword commands
) else if /i "%%-"=="-BeginScript"    (call :FUNCTION_[BeginScript]
) else if /i "%%-"=="PrintToScreen"   (call :FUNCTION_[EchoString]
) else if /i "%%-"=="-EndScript"      (goto :eof
))
goto :FUNCTION_[GrabString]

:FUNCTION_[ParseBytes]

goto :eof

:FUNCTION_[BeginScript]

goto :eof

:FUNCTION_[EchoString]
:: BEGIN_FUNCTION
   for /f "tokens=* delims=-PpRrIiNnTtOoSsCcEe" %%- in ("%str%") do (
   set "MAINStr=%%-"
   )
   set "MAINStr=%MAINStr:~1%"
   echo.%MAINStr%
goto :eof
:: END_FUNCTION

:FUNCTION_[EchoBlock]
:: BEGIN_FUNCTION
set /a val=%val%+1
for /f "tokens=* skip=%val% delims=" %%- in (%Script%) do (
if /i "%%-"=="<-" (goto :eof
) else echo.%%-&&goto :FUNCTION_[EchoBlock]
)
goto :eof
:: END_FUNCTION

:FUNCTION_[SingleComment]

goto :eof

:FUNCTION_[CommentBlock]
:: BEGIN_FUNCTION
set /a val=%val%+1
for /f "tokens=* skip=%val% delims=" %%- in (%Script%) do (
if /i "%%-"=="*/" (goto :eof
) else goto :FUNCTION_[CommentBlock]
)
goto :eof
:: END_FUNCTION

:FUNCTION_[SetVar]
:: BEGIN_FUNCTION
set /a var=%var%+1
for /f "tokens=2* delims=$ " %%a in ("%str%") do (
set SYS-%var%=%%a %%b
)
call echo.%%SYS-%var%%%
goto :eof
:: END_FUNCTION

:FUNCTION_[EndScript]

goto :eof


Here is an example of an external script file to be processed by the source.

Code: Select all

// Purpose(ERROR TESTING)
// This is a comment
/*
This is a comment block
This is a line inside of a comment block
Every blank line between commands requires
One white space to separate lines as shown
on line 11 however the same is not true for
block commands, no single white spaces are
required
*/
 
-BeginScript
->

This is a line inside of a printed block
...and so is this

<-
->
This line does not work
<-
->

This line does work
<-
- This is another line
-      This is a line with leading spaces
-    ...and this is a tabbed line with 1 leading space
- This is a line with quotes around a single sub-string, this line "works"
- This is another line with quotes around a group of strings, "this line does not work!"
- Printable chars on a single line ! @ # $ () _ + {} : ? ` - = [] \ ; ' , . /
// Non printable chars on a single line & * | < >
/*
Chars not printable on single lines or single comments ^ " %
*/
->

Printable chars inside of a printed block (all of them)
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
~ ! @ # $ & * ( ) _ + { } | : < > ? ` - = [ ] \ ; ' , . / ^ " %

<-
PrintToScreen ...This is yet another line represented by the PrintToScreen command.
-EndScript


In the above external file we can see the syntax is defined by the main batch source. Now a few problems that need to be addressed.
1) Processing illegal characters.
2) Processing single sets of double quotes as well as opening and closing quotes.
3) Setting and retrieving variables predefined from the source batch to the external script (some sort of call to or if defined statements)

As of now variables are defined by doing var $VarName Hello
A white space is left blank between the var name and its value because what if the value is to be an =
I use a for command to set the variable using a delims so if I use = in the command the = would be taken out of the value. As well when defining variables from an external script to the batch source. The method to currently do this is to append a number to a string in this case SYS-(number value). So as described above in setting variables "$VarName Hello" would actually be defined in the source batch as "SYS-1". I have not yet created a routine for retrieving these variables when called from the external script but something along the lines of a comparison until the var name and value have been found and then executing whatever is to occur.
I have attempted to create an example of an external script for error testing so you can see some of the issues that reside for the moment.
My idea was to process all the byte/chars one at a time and go from there, however this has run into many issues.
Avery_Larry was kind enough to cleanup the function I was currently using in order to retrieve strings beginning with $ which I use currently to define vars. However in this next example the script processes everything starting with $ up until the next white space, whereas it should be able to differentiate between a $Hello which is the variable and a Hello$World where the $ is a normal char and should be used as such.
Thanks to Avery_Larry
His Code.

Code: Select all

@echo off
 setlocal

set "string=hel  $howe owe  $sodfi asf$wer23 $wer"
for /f "tokens=1* delims=$" %%a in ("%string%") do if not "%%~b"=="" call :recurse "%%~b"
goto :eof


:recurse
for /f "tokens=1*" %%a in ("%~1") do (
   echo %%a
   for /f "tokens=1* delims=$" %%a in ("%~1") do if not "%%~b"=="" call :recurse "%%~b"
)
goto :eof


Finally my original idea to combat this same issue was to do.

Code: Select all

@echo off
 setlocal

:: BEGIN_FUNCTION
REM Find the variable in the string
set MAINStr=Hello $Wor$ld $Hello $World ..

   set BYTEval=0
   set NEXTval=0
   :SUB-FUNCTION[BeginBYTELoop]
   set /a BYTEval=%BYTEval%+1
   call set "StrByte=%%MAINStr:~0,%BYTEval%%%"
   set "StrChar=%StrByte:~-1%"
   if "%BYTE%"=="1" goto :VARByte
   if /i "%StrChar%"=="$" (
   set BYTE=1&&goto :SUB-FUNCTION[BeginBYTELoop]
   )
   if /i "%StrByte%"=="%MAINStr%" goto :eof
   goto :SUB-FUNCTION[BeginBYTELoop]

   :VARByte
   set /a NEXTval=%NEXTval%+1
   if "%StrChar%"==" " (
      call set "SUBStr=%%StrByte:~-%NEXTval%%%"
      call set "BYTE="
      call :FoundStringVAR
      call set NEXTval=0
   )
   goto :SUB-FUNCTION[BeginBYTELoop]

   :FoundStringVAR
   for /f "tokens=1 delims= " %%- in ("%SUBStr%") do (
   echo.%%-
   )
:: END_FUNCTION

Which will process only strings beginning with $ and ending with a space, and process all $ included in strings just as normal characters.
However my script includes a lot of unneeded extra code and as well if the string happens to be something like "Hello $World $Hello" the last $Hello will cause the script to hang. In order to solve this a white space is needed at the end of the second $Hello so "Hello $World $Hello " would behave as it should. This is not what should happen though this is a bug and needs to be corrected.
In conclusion as a beginning to this thread we are starting off from the top and moving forward. First taking care of the string, line, byte, char processing and moving onto the basic "echo" command equivalence, and finally setting and retrieving variables and progressing on.
Run the external script through the source and if possible correct, cleanup, and/or offer any constructive feedback.

P.S. If you wish to see what it is I'm taking about in setting variables just add another if else statement to the block of if else statements in the main batch source and make a call to the FUNCTION_[SetVar] label. Then add a line somewhere in the external script that states something along the lines of
var $Hello World
I left this section out for now so the primary focus would be put on the processing and echo, comment block commands.
The variable command will just print to the screen Hello World. which is equal to in the main batch source variable as SYS-1. add more variable commands and the system adds a value of 1 to each source variable.
var $Hello Hello
var $World World
Becomes "SYS-1=Hello Hello" and "SYS-2=World World"
Both variable name and value are stored within the source SYS- variable.
This is to be parsed later on when the variable is called by the external script. Of course it would be ideal if multiple variables could be specified on the same line using ,, or something like &
So var $Hello Hello ,, $World World
Which would be the same as the above only stated on a single line rather then to separate lines.