May 9th, 2006

PowerShell Grammar

PowerShell Team
PowerShell Team

A number of people have asked about the PowerShell grammar.  Here is a draft write up (I’ve also included it as an attachement) that George Xie and Bruce Payette are working on.

 

Grammar of PowerShell (formerly known as Monad)  is separated into parsing rules and tokenizing rules. Parsing rules in turn can be separated into 4 layers |

 

1.      Statement list: this includes statement list and statement blocks.

2.      Statement: this includes different statements

3.      Expression:

4.      Value

 

 

1. Statement List

 

<statementListRule> = <statementRule> [ <statementSeparatorToken> <statementRule> ]*

 

# this is a variation of statement list used mainly in script blocks.

<statementBlockRule> = ‘{‘ <statementListRule> ‘}’

 

2. Statement

 

# an aggregation rule for all statements.

<statementRule> = <ifStatementRule> |

                    <switchStatementRule> |

                    <foreachStatementRule> |

                    <forWhileStatementRule> |

                    <doWhileStatementRule> |

                    <functionDeclarationRule> |

                    <parameterDeclarationRule> |

                    <flowControlStatementRule> |

                    <trapStatementRule> |

                    <finallyStatementRule> |

                    <pipelineRule>

 

2.1 Pipeline

 

# A pipeline can look like

#   get-childitem -recurse -filter *.cs | sort name

#   2+2 |3 |4 | sort  # sort a literal array in a pipeline…

#   . profile.msh | count-object    # . source a script

#   & “c:\a path\with spaces.doc”   # execute a path with spaces in it

#   get-childitem | sort-object > c:/tmp/junk.txt  # use i/o redirection…

<pipelineRule> = <assignmentStatement> | <firstPipelineElement> [ ‘|’ <cmdletCall> ]*

 

<assignmentStatementRule> = <lvalueExpression>

                            <AssignmentOperatorToken> <pipelineRule>

 

<lvalueExpression> := <lvalue> [? |? <lvalue>]*

 

<lvalue> :=  <simpleLvalue> <propertyOrArrayReferenceOperator>*

 

<simpleLvalue> := <AttributeSpecificationToken>* <variableToken>

 

<firstPipelineElement> = <expressionRule> | <cmdletCall>

 

<cmdletCall> = [ ‘&’ | ‘.’ | <empty> ] [ <name> | <expressionRule> ]

    [ <parameterToken> |

        <parameterArgumentToken> |

        <postfixOperatorRule> |

        <redirectionRule> ]*

 

<redirectionRule> = <redirectionOperatorToken> <propertyOrArrayReferenceRule>

 

2.2 If statement

 

<ifStatementRule> = ‘if’ ‘(‘ <pipelineRule> ‘)’ <statementBlockRule>  [

                        ‘elseif’ ‘(‘ <pipelineRule> ‘)’ <statementBlockRule>

                    ]* [

                        ‘else’ <statementBlockRule>

                    ]{0 |1}

             

2.3 Switch statement

 

# The syntax for a switch statement looks like:

#     switch -regex -casesensitive (get-childitem | sort length)

#     {

#         “^5”                  { “length for $_ started with 5” ; continue}

#         { $_.length > 20000 } { “length of $_ is greated than 20000” }

#         default               { “Didn’t match anything else…” }

#     }

# Note that there can only be 1 default clause in a switch statement

<switchStatementRule> = ‘switch’ [‘-regex’ | ‘-wildcard’ | ‘-exact’ ]{0 |1}

                      [‘-casesensitive’]{0 |1}

                      [‘-file’ <propertyOrArrayReferenceRule> | ‘(‘ <pipelineRule> ‘)’ ]

                      ‘{‘ [

                               [

                               ‘default’ |

                               <ParameterArgumentToken> |

                               <propertyOrArrayReferenceRule> |

                               <statementBlockRule>

                               ]

                               <statementBlockRule>

                        ]+ ‘}’

 

2.4 Foreach statement

 

# Foreach statement looks like

#   foreach ($i in get-childitem | sort-object length) {

#       write-host $i ; $sum += $i.length }

<foreachStatementRule> = <LoopLabelToken>{0 |1} ‘foreach’

                        ‘(‘ <variableToken>  ‘in’ <pipelineRule> ‘)’

                            <statementBlockRule>

                           

2.5 Forwhile statement

 

# A while statement looks like

#   while ($i -lt 100) {

#       write-host $i

#       $i += 1

#   }

#

# A for statement looks like

#   for ($i=0; $i -lt 10; $i += 1) {

#   while ($i -lt 100) {

#       write-host $i

#       $i += 1

#   }

#

<forWhileStatementRule> =

        <LoopLabelToken>{0 |1} ‘while’ ‘(‘ <pipelineRule> ‘)’ <statementBlockRule> |

        <LoopLabelToken>{0 |1} ‘for’ ‘(‘ <pipelineRule>{0 |1} ‘;’

             <pipelineRule>{0 |1} ‘;’ <pipelineRule>{0 |1} ‘)’ <statementBlockRule>

            

2.5 Dowhile statement

 

# A do/while statement looks like

#   do

#   {

#       write-host $i

#       $i += 1

#   } while ($i -lt 100)

#

# A do/until statement looks like

#   do

#   {

#       write-host $i

#       $i += 1

#   } until ($i -ge 100)

#

<doWhileStatementRule> =

        <LoopLabelToken>{0 |1} ‘do’ <statementBlockRule> [‘while’ | ‘until’] ‘(‘ <pipelineRule> ‘)’

       

2.6 Trap statement

 

# A trap statement looks like

#   trap { … }

# or

#   trap [system.nullreferenceexception] { … }

#

<trapStatementRule> = ‘trap’ <AttributeSpecificationToken>{0 |1}

                    <statementBlockRule>

 

2.7 Finally statement                   

 

# A finally statement looks like

#   finally { … }

#

<finallyStatementRule> = ‘finally’ <statementBlockRule>

 

2.8 flow control statement

 

# Flow control statements look like

#   break

#   break label

#   break $labelArray[2].name

#   return

#   return 13

#   return get-content | sort | pick-object -head 10

 

<flowControlStatementRule> =

    [‘break’ | ‘continue’] [<propertyNameToken> | <propertyOrArrayReferenceRule>]{0 |1} |

    ‘return’ <pipelineRule>

 

2.9 Function declaration   

 

# a function definition looks like

#   function foo { … }

# or

#   filter foo { … }

<functionDeclarationRule> = <FunctionDeclarationToken>

    <ParameterArgumentToken> [ ‘(‘ <parameterDeclarationExpressionRule> ‘)’ ] <cmdletBodyRule>

 

# The following rule defines the grammar for a cmdlet (function/script/scriptblock) body

<cmdletBodyRule> =  ‘{‘ [ ‘(‘ <parameterDeclarationExpressionRule> ‘)’ ] (

    [ ‘begin’ <statementBlock> | ‘process’ <statementBlock> | ‘end’ <statementBlock> ]* |

    <statementList> ‘}’

 

2.10 Parameter declaration

 

# a parameter definition looks like

#   param argumentList

<parameterDeclarationRule> =

    <ParameterDeclarationToken> ‘(‘ <parameterDeclarationExpressionRule> ‘)’

   

<parameterDeclarationExpressionRule> = <parameterWithIntializer> [ <CommaToken> <parameterWithIntializer> ]*

 

<parameterWithIntializer> = <simpleLvalue> [ ‘=’  <expressionRule> ]

 

3. Expression

 

<expressionRule> = <logicalExpressionRule>

 

<logicalExpressionRule> = <bitwiseExpressionRule>

                        [<LogicalOperatorToken> <bitwiseExpressionRule>]*

 

<bitwiseExpressionRule> = <comparisonExpressionRule>

                        [ <BitwiseOperatorToken> <comparisonExpressionRule> ]*

                       

<comparisonExpressionRule> = <addExpressionRule>

                            [ <ComparisonOperatorToken> <addExpressionRule> ]*

                           

<addExpressionRule> = <multiplyExpressionRule>

                    [ <AdditionOperatorToken> <multiplyExpressionRule> ]*

                   

<multiplyExpressionRule> = <formatExpressionRule>

                        [ <MultiplyOperatorToken> <formatExpressionRule> ]

                       

<formatExpressionRule> = <rangeExpressionRule>

                        [ <FormatOperatorToken> <rangeExpressionRule> ]*

                       

<rangeExpressionRule> = <arrayLiteralRule>

                    [ <RangeOperatorToken> <arrayLiteralRule> ]*

 

<arrayLiteralRule> = <postfixOperatorRule> [ <CommaToken> <postfixOperatorRule> ]*

                   

<postfixOperatorRule> =     <lvalueExpression> <PrePostfixOperatorToken> |

                            <propertyOrArrayReferenceRule>

 

<propertyOrArrayReferenceRule> = <valueRule> <propertyOrArrayReferenceOperator>*

 

<propertyOrArrayReferenceOperator> = ‘[‘ <expressionRule> ‘]’ ] |

                                     ‘.’ [

                                         <PropertyNameToken> <parseCallRule>{0 |1} |

                                         <valueRule>

                                     ]

                           

<parseCallRule> = ‘(‘ <arrayLiteralRule> ‘)’

 

4. Value                                    

 

<valueRule> =   ‘(‘ <assignmentStatementRule> ‘)’ |

                ‘$(‘ <statementListRule> ‘)’ |

                ‘@(‘ <statementListRule> ‘)’ |

                <cmdletBodyRule> |

                ‘@{‘ <hashLiteralRule> ‘}’ |

Category
PowerShell

Author

PowerShell Team
PowerShell Team

PowerShell is a task-based command-line shell and scripting language built on .NET. PowerShell helps system administrators and power-users rapidly automate tasks that manage operating systems (Linux, macOS, and Windows) and processes.

0 comments

Discussion are closed.