PowerShell Grammar

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> ‘}’ |

0 comments

Discussion is closed.

Feedback usabilla icon