NOTE: Microsoft Power Fx is the new name for canvas apps formula language. These articles are work in progress as we extract the language from canvas apps, integrate it with other products of the Power Platform, and make available as open source. Start with the Power Fx Overview for an introduction to the language.
Microsoft Power Fx is based on formulas that binds a name to an expression. Just like in spreadsheet, as inbound dependencies to the expression change, the expression is recalculated and the value of the name changes, possibly cascading the recalculation into other formulas.
This grammar covers the expression part of the formula. Binding to a name to create a formula is dependent on how Power Fx is integrated. In spreadsheets, the binding syntax is not exposed and is implied by where the expression is written, for example typing =B1
in the A1 cell. In some cases, no binding is required at all and Power Fx is used as an expression evaluator, for example in supporting calculated columns of a database table. For Power Apps, the binding is implied when in Power Apps Studio with a serialization format based on YAML for use outside Power Apps Studio.
This article is an annotated version of the grammar. The raw grammar, suitable for use with tools, is also available as a .grammar file.
The lexical and syntactic grammars are presented using grammar productions. Each grammar production defines a non-terminal symbol and the possible expansions of that non-terminal symbol into sequences of non-terminal or terminal symbols. In grammar productions, non-terminal symbols are shown in italic type, and terminal symbols are shown in a fixed-width font.
The first line of a grammar production is the name of the non-terminal symbol being defined, followed by a colon. Each successive indented line contains a possible expansion of the non-terminal given as a sequence of non-terminal or terminal symbols. For example, the production:
ββGlobalIdentifier :
ββββ[@
βIdentifierβ]
defines a GlobalIdentifier to consist of the token [@
, followed by an Identifier, followed by the token ]
When there is more than one possible expansion of a non-terminal symbol, the alternatives are listed on separate lines. A subscripted suffix "opt" is used to indicate an optional symbol. For example, the production:
ββFunctionCall :
ββββFunctionIdentifierβ(
βFunctionArgumentsoptβ)
is shorthand for:
ββFunctionCall :
ββββFunctionIdentifierβ(
β)
ββββFunctionIdentifierβ(
βFunctionArgumentsβ)
Alternatives are normally listed on separate lines, though in cases where there are many alternatives, the phrase "one of" may precede a list of expansions given on a single line. This is simply shorthand for listing each of the alternatives on a separate line.
For example, the production:
ββDecimalDigit : one of
ββββ0
β1
β2
β3
β4
β5
β6
β7
β8
β9
is shorthand for:
ββDecimalDigit :
ββββ0
ββββ1
ββββ2
ββββ3
ββββ4
ββββ5
ββββ6
ββββ7
ββββ8
ββββ9
The lexical-unit production defines the lexical grammar for a Power Fx expression. Every valid Power Fx expression conforms to this grammar.
ββExpressionUnit :
ββββExpressionElementsopt
ββExpressionElements :
ββββExpressionElement
ββββExpressionElementβExpressionElementsopt
ββExpressionElement :
ββββWhitespace
ββββComment
ββββToken
At the lexical level, a Power Fx expression consists of a stream of Whitespace, Comment, and Token elements. Each of these productions is covered in the following sections. Only Token elements are significant in the syntactic grammar.
Whitespace is used to separate comments and tokens within a Power Apps document.
ββWhitespace :
ββββany Unicode Space separator (class Zs)
ββββany Unicode Line separator (class Zl)
ββββany Unicode Paragraph separator (class Zp)
ββββHorizontal tab character (U+0009)
ββββLine feed character (U+000A)
ββββVertical tab character (U+000B)
ββββForm feed character (U+000C)
ββββCarriage return character (U+000D)
ββββNext line character (U+0085)
Two forms of comments are supported:
- Single-line comments that start with the characters // and extend to the end of the source line.
- Delimited comments that start with the characters /* and end with the characters */. Delimited comments may span multiple lines.
ββComment :
ββββDelimitedComment
ββββSingleLineComment
ββSingleLineComment :
ββββ//
βSingleLineCommentCharactersopt
ββSingleLineCommentCharacters :
ββββSingleLineCommentCharacter
ββββSingleLineCommentCharacterβSingleLineCommentCharactersopt
ββSingleLineCommentCharacter :
ββββany Unicode characters except a NewLineCharacter
ββDelimitedComment :
ββββ/*
βDelimitedCommentCharactersoptβ*/
ββDelimitedCommentCharacters :
ββββDelimitedCommentCharactersNoAsteriskβDelimitedCommentCharactersopt
ββββ*
βDelimitedCommentAfterAsteriskCharacters
ββDelimitedCommentAfterAsteriskCharacters :
ββββDelimitedCommentNoSlashAsteriskCharacterβDelimitedCommentCharactersopt
ββββ*
βDelimitedCommentAfterAsteriskCharacters
ββDelimitedCommentCharactersNoAsterisk :
ββββany Unicode character except * (asterisk)
ββDelimitedCommentNoSlashAsteriskCharacter :
ββββany Unicode character except a / (slash) or * (asterisk)
Comments do not nest. The character sequences /*
and */
have no special meaning within a single-line-comment, and the character sequences //
and /*
have no special meaning within a delimited-comment.
Comments are not processed within text-literal.
The following example includes two delimited comments:
/* Hello, world
*/
"Hello, world" /* This is an example of a text literal */
The following examples include three single-line comments:
// Hello, world
//
"Hello, world" // This is an example of a text literal
A literal is a source code representation of a value.
ββLiteral :
ββββLogicalLiteral
ββββNumberLiteral
ββββTextLiteral
A logical literal is used to write the values true and false and produces a logical value.
ββLogicalLiteral : one of
ββββtrue
βfalse
A number literal is used to write a numeric value and produces a number value.
ββNumberLiteral :
ββββDecimalDigitsβExponentPartopt
ββββDecimalDigitsβDecimalSeparatorβDecimalDigitsoptβExponentPartopt
ββββDecimalSeparatorβDecimalDigitsβExponentPartopt
ββDecimalDigits :
ββββDecimalDigit
ββββDecimalDigitsβDecimalDigit
ββDecimalDigit : one of
ββββ0
β1
β2
β3
β4
β5
β6
β7
β8
β9
ββExponentPart :
ββββExponentIndicatorβSignoptβDecimalDigits
ββExponentIndicator : one of
ββββe
βE
ββSign : one of
ββββ+
β-
A text literal is used to write a sequence of Unicode characters and produces a text value. Text literals are enclosed in double quotes. To include double quotes in the text value, the double quote mark is repeated:
"The ""quoted"" text" // The "quoted" text
ββTextLiteral :
ββββ"
βTextLiteralCharactersoptβ"
ββTextLiteralCharacters :
ββββTextLiteralCharacterβTextLiteralCharactersopt
ββTextLiteralCharacter :
ββββTextCharacterNoDoubleQuote
ββββDoubleQuoteEscapeSequence
ββTextCharacterNoDoubleQuote :
ββββany Unicode code point except double quote
ββDoubleQuoteEscapeSequence :
ββββ"
β"
An identifier is a name used to refer to a value. Identifiers can either be regular identifiers or single quoted identifiers.
ββIdentifier :
ββββIdentifierName but not Operator or ContextKeyword
ββIdentifierName :
ββββIdentifierStartCharacterβIdentifierContinueCharactersopt
ββββ'
βSingleQuotedIdentifierβ'
ββIdentifierStartCharacter :
ββββLetterCharacter
ββββ_
ββIdentifierContinueCharacter :
ββββIdentifierStartCharacter
ββββDecimalDigitCharacter
ββββConnectingCharacter
ββββCombiningCharacter
ββββFormattingCharacter
ββIdentifierContinueCharacters :
ββββIdentifierContinueCharacterβIdentifierContinueCharactersopt
ββLetterCharacter :
ββββany Unicode character of the classes Uppercase letter (Lu), Lowercase letter (Ll)
ββββany Unicode character of the class Titlecase letter (Lt)
ββββany Unicode character of the classes Letter modifier (Lm), Letter other (Lo)
ββββany Unicode character of the class Number letter (Nl)
ββCombiningCharacter :
ββββany Unicode character of the classes Non-spacing mark (Mn), Spacing combining mark (Mc)
ββDecimalDigitCharacter :
ββββany Unicode character of the class Decimal digit (Nd)
ββConnectingCharacter :
ββββany Unicode character of the class Connector punctuation (Pc)
ββFormattingCharacter :
ββββany Unicode character of the class Format (Cf)
A SingleQuotedIdentifier can contain any sequence of Unicode characters to be used as an identifier, including keywords, whitespace, comments, and operators. Single quote characters are supported with a double single quote escape sequence.
ββSingleQuotedIdentifier :
ββββSingleQuotedIdentifierCharacters
ββSingleQuotedIdentifierCharacters :
ββββSingleQuotedIdentifierCharacterβSingleQuotedIdentifierCharactersopt
ββSingleQuotedIdentifierCharacter :
ββββTextCharactersNoSingleQuote
ββββSingleQuoteEscapeSequence
ββTextCharactersNoSingleQuote :
ββββany Unicode character except ' (U+0027)
ββSingleQuoteEscapeSequence :
ββββ'
β'
ββDisambiguatedIdentifier:
ββββTableColumnIdentifier
ββββGlobalIdentifier
ββTableColumnIdentifier :
ββββIdentifierβ[@
βIdentifierβ]
ββGlobalIdentifier:
ββββ[@
βIdentifierβ]
ββContextKeyword:
ββββParent
ββββSelf
ββββThisItem
ββββThisRecord
Power Apps identifiers are case-sensitive. The authoring tool will auto correct to the correct case when a formula is being written.
ββDecimalSeparator:
ββββ.
(dot) for language that uses a dot as the separator for decimal numbers, for example 1.23
ββββ,
(comma) for languages that use a comma as the separator for decimal numbers, for example 1,23
ββListSeparator:
ββββ,
(comma) if DecimalSeparator is .
(dot)
ββββ;
(semi-colon) if DecimalSeparator is ,
(comma)
ββChainingSeparator:
ββββ;
(semi-colon) if DecimalSeparator is .
(dot)
ββββ;;
(double semi-colon) if DecimalSeparator is ,
(comma)
Operators are used in formulas to describe operations involving one or more operands. For example, the expression a + b
uses the +
operator to add the two operands a
and b
.
ββOperator:
ββββBinaryOperator
ββββBinaryOperatorRequiresWhitespace
ββββPrefixOperator
ββββPrefixOperatorRequiresWhitespace
ββββPostfixOperator
ββBinaryOperator: one of
ββββ=
β<
β<=
β>
β>=
β<>
ββββ+
β-
β*
β/
β^
ββββ&
ββββ&&
β||
ββββin
βexactin
ββBinaryOperatorRequiresWhitespace:
ββββAnd
βWhitespace
ββββOr
βWhitespace
ββPrefixOperator:
ββββ!
ββPrefixOperatorRequiresWhitespace:
ββββNot
βWhitespace
ββPostfixOperator:
ββββ%
ββReferenceOperator: one of
ββββ.
β!
ββReference:
ββββBaseReference
ββββBaseReferenceβReferenceOperatorβReferenceList
ββBaseReference:
ββββIdentifier
ββββDisambiguatedIdentifier
ββββContextKeyword
ββReferenceList:
ββββIdentifier
ββββIdentifierβReferenceOperatorβReferenceList
ββInlineRecord:
ββββ{
βInlineRecordListoptβ}
ββInlineRecordList:
ββββIdentifierβ:
βExpression
ββββIdentifierβ:
βExpressionβListSeparatorβInlineRecordList
ββInlineTable:
ββββ[
βInlineTableListoptβ]
ββInlineTableList:
ββββExpression
ββββExpressionβListSeparatorβInlineTableList
ββExpression:
ββββLiteral
ββββReference
ββββInlineRecord
ββββInlineTable
ββββFunctionCall
ββββ(
βExpressionβ)
ββββPrefixOperatorβExpression
ββββExpressionβPostfixOperator
ββββExpressionβBinaryOperatorβExpression
ββChainedExpression:
ββββExpression
ββββExpressionβChainingSeparatorβChainedExpressionopt
ββFunctionCall:
ββββFunctionIdentifierβ(
βFunctionArgumentsoptβ)
ββFunctionIdentifier:
ββββIdentifier
ββββIdentifierβ.
βFunctionIdentifier
ββFunctionArguments:
ββββChainedExpression
ββββChainedExpressionβListSeparatorβFunctionArguments