New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
about_parsing additional expression mode start characters #3440
Comments
I noticed today that the opening bracket |
@msftrncs, some good points, but I don't think (write-output -10).GetType().Name
(write-output +10).GetType().Name
(write-output !0).GetType().Name
(write-output [string]).GetType().Name All these commands output Unquoted "number-looking" literals without a sign - e.g., PS> (Write-Output 0xa).GetType().Name
Int32 # !! Parsed as number
# However, on output the original string representation is retained:
PS> Write-Output 0xa
0xa # !! Not, 10, as you would get with Write-Output (0xa) This awkward hybrid behavior must be retained for backward compatibility, however; it is implemented inconsistently in PowerShell code, unfortunately: see PowerShell/PowerShell#9157 for background information (note what said issue proposes as a resolution is misguided - I'm planning to revise it soon). However, a char. that is missing from the list of expression-initiating chars. is PS> Write-Output {ha}
ha # !! stringified script-block == literal contents between { and } As for compound tokens such as |
@mklement0, in the examples of (write-output xxx), you have already switched to aurgument mode. My issue was when sitting at the point between when deciding to go to expression mode or argument mode. Once in a given mode, that mode remains until certain delimiting characters come along, such as the closing ')' in your examples. The opening '(' does two things, it switches the mode to expression mode, but then enters a subexpression, which starts with a new decision of argument mode or expression mode. The command name sends the sub-expression to argument mode. If instead of a command name, a + character appeared, it would have switched to expression mode. |
I should note in my previous comment about '[', that only if the contents after the '[' is a type name, and not an attribute, will it result in expression mode, so the '[' by itself does not mark the switch to expression mode. |
@msftrncs: I thought this issue is about what characters at the start of a token in argument mode decide whether argument mode or expression mode is chosen for that argument - that's the passage from the docs you're quoting in the initial post is about - and that passage is missing My point was that
PS> Write-Output [int]
[int] # string literal
PS> (Write-Output [int]).GetType().Name
String Now, intra-token use of special characters seems to follow the same rules: inside an unquoted token, encountering one of the special chars.:
PS> Write-Output a(2) # parses as *2* arguments
a # string literal 'a'
2 # [int] 2 due to (2) being parsed as an expression Again, a PS> Write-Output foo+10
foo+10 # single string literal |
@msftrncs: I think I now understand where the confusion lies: You are talking about what characters determine whether to enter argument or expression mode, either at the start of a statement (start of a line or after And, yes, I agree that it's worth spelling out how that decision is made in the docs. |
Correct, as that is what I take the 'about_parsing' document to be referring to. |
What's missing is a description of what determines which parsing mode is chosen when: The rules, from what I understand are (I have not looked at the source code):
|
I understand what you are getting at, @mklement0. Its dawned on me now that this particular document is trying to describe something differently that I am thinking. However, I still have a problem with it. I think its describing the wrong subject, and its phrasing everything poorly. I think it was understood well from other areas that '(' starts a subexpression. However, '$' does not start an expression in the same sense. Yes, I can reference members of the object, but I cannot go beyond that, so I do not feel that is an expression, and definitely not expression mode. (I consider it a reference) I think we both agree that people need a better explanation of the mode switch that occurs when you start a statement with a function name, versus a variable reference (as one example). A function name expects to be followed by parameter arguments, of which may be expressions if that's what they are called, but expression mode, allows arithmetic and the other operators, which cannot be used directly in an argument without a subexpression, and this is what I always thought the 'about_parsing' document was trying to describe. BTW, Here is my list of what is allowed with the dot-source operator, in REGEX form, as is in my PR #156 in EditorSyntax:
The Everything else you list I have handled. Ultimately I think I will close this issue. I think the document needs clarified, but that can be a new issue that starts off on the right context. |
Thanks, @msftrncs. Fully agreed that there's a lot of room for improvement of the help topic at hand. Good point re a variable reference (e.g. |
On the unquoted expansion, the only thing I am having problems parsing in TextMate is a reference such as
You get
|
Yeah, that's surprising:
Such compound tokens - by that I mean the direct concatenation of two or more distinct syntax constructs that may or may not be parsed as a single argument - show surprising behavior:
This makes for a surprising asymmetry, which is the subject of PowerShell/PowerShell#6467 Notable examples: ## $(...) asymmetry
# $(...) after unquoted literal: 1 string argument
PS> Write-Output 3$(1+2)
33
# $(...) before unquoted literal: 2 arguments (both [int])
PS> Write-Output $(1+2)3
3
3
## Quoted-string asymmetry:
# Quoted string after unquoted literal: 1 string argument (with quotes stripped)
PS> Write-Output 3'3'
33
# Quoted string before unquoted literal: 2 arguments (1 string, 1 [int])
PS> Write-Output '3'3
3
3 |
Adding link to PowerShell/PowerShell#6467 |
Issue Details
I have left the template blank at this time, but I believe this might affect all versions.
If preceded by one of these characters, the value is treated as a value expression.
On about_parsing, there are additional characters that cause the expression mode, including:
-$a
or-2
or!$a
is an expression mode-hello
or+hello
or!test
is an argument modeAlso, I think the last line should actually be part of the bulleted paragraph.
I think this whole section also fails to explain that the mode determination is based on the first token of each command statement and then applies to the remainder of the statement, noting that parenthesis and braces begin a new sub-statement. Instead this section implies that the mode is determine for each token (it mentions the tokens are interpreted independently, but they are not, as interpretation of all tokens after the first one depend on the first one's evaluation). Assuming a function named 'hello',
hello $a-3
, the token$a-3
is still treated as an expandable string, not an expression. An example in the doc also shows this,Write-Output $a/H
.Also, I think the word 'value' may have gotten used where 'token' should have been used, for consistency. The doc started off talking about 'tokens' and then switches to 'values' in the bulleted items.
Document Details
Do not edit this section. It is required for docs.microsoft.com GitHub issue linking.
The text was updated successfully, but these errors were encountered: