How batch parsing phases work?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
lockedscope
Posts: 31
Joined: 12 Jun 2020 10:38

How batch parsing phases work?

#1 Post by lockedscope » 15 Jun 2020 07:37

I have following interpretation of phases. Is "set "c=%b%"" explanation correct? :?:

Code: Select all

rem @echo off
setlocal enableDelayedExpansion
set text=my
set "a=^^^^^^^!text^^^^^^^!"
echo "a: %a%"
  rem echo "a: ^^^!text^^^!"
  rem "a: ^!text^!"
set "b=%a%"
  rem set "b=^^^!text^^^!"  

echo "b: %b%"
  rem echo "b: ^!text^!"
  rem "b: !text!"

set "c=%b%"
  rem set "c=^!text^!" - First %b% expands to "^^^!text^^^!"(check the "set b=%a%" above) and then resolving of carets(Phase 2) to single carets "^!text^!" and 
  rem at delayed expansion (phase 5), carets resolved so its resolved to !text! literally (So, value !text! of is not expanded because carets already resolved from ^! to ! in this phase).

echo c: %c%
  rem echo c: !text! - Previous expansion/unescaping(resolving of caret) returns !text! literally and delayed expansion expands it to "my" value.
  rem c: my

set "d=%c%"
  rem set "d=!text!" - So, we understand that %c% still contains !text! value literally although it still echoes "my". Check the echo %d% below
echo d: %d%
  rem echo d: my - Because when we echo %c%, it first "echo !text!" and "my" value but now with echo d we get "echo my" and so "my" directly without !text!.
  rem d: my
  
goto :eof
Last edited by lockedscope on 15 Jun 2020 09:50, edited 2 times in total.

lockedscope
Posts: 31
Joined: 12 Jun 2020 10:38

Re: How batch parsing phases work?

#2 Post by lockedscope » 15 Jun 2020 09:42

After jeb's explanation of phases, i grasped it now (not all rules :lol: ).

  • EXPANSION - In 1. percent expansion phase, %b% expands to ^^^!text!^^^
  • CARET RESOLVING - In 2. special characters phase, we encounter carets so resolve them, 1. and 3. carets removed on both sides so we have ^!text!^ literally.
  • CARET RESOLVING - In 5. delayed expansion phase, we encounter carets, so resolve them, 1. carets removed on both sides so we have ! kept only on both sides.
    • After !, the next character is not a ! but the variables name, so there is no !! variable expansion here.
    • Thus, we have !text! literally and it is assigned to c literally as !text!.

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: How batch parsing phases work?

#3 Post by jeb » 16 Jun 2020 00:09

Hi lockedscope,

it's quite correct.

But my first rule is: Always monitor variables unmodified :!:
You can use delayed expansion for that or the SET command, but never percent expansion, that only confuses the result 8)

If you add set b after the line

Code: Select all

set "b=%a%"
you see that the content of <b> is "^!text^!"


For the line: set "c=%b%"
The rules

Code: Select all

Percent expansion of "b" results into: set "c=^!text^!"
Phase2: No changes, because the carets are inside quotes
Phase5: The carets escape the exclamation marks (quotes are ignored in phase 5)
result: c=!text!

lockedscope
Posts: 31
Joined: 12 Jun 2020 10:38

Re: How batch parsing phases work?

#4 Post by lockedscope » 16 Jun 2020 04:28

Thanks jeb, set b is a good advice, i was also on it.
So, when we assign without quotes

Code: Select all

set "a=^^^^^^^!text^^^^^^^!" - So, a=^^^!text^^^!
set b=%a%
For set b=%a%;
phase 2, converts ^^^!text!^^^ to ^!text!^
phase 5, convert ^!text!^ to !text!
phase 7, execute command, !text! is assigned literally to b

Also when we assign without quotes

Code: Select all

set text=my
set c=^^^!text^^^!
echo %c%
For echo %c%;
phase 2, converts ^^^!text!^^^ to ^!text^!
phase 5, converts ^!text^! to its value !text!
phase 7, execute command, echo !text!, echoes text's value `my`

Is it right? :?:

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: How batch parsing phases work?

#5 Post by jeb » 22 Jun 2020 00:30

Hi,

your first analysis is correct, but not the second one.

the line: set c=^^^!text^^^!
assigns !text! to c

Therefore the line: echo %c%

only has to expand !text! to "my"

Post Reply