This project is read-only.

The AST of QInjection

A simple BNF-Like.

Internally current version of QInjection uses Microsoft Roslyn to build the AST (Abstract Syntax Tree) of the Lambda-Expression.
So if you want to build your own Validation Syntax you have to know how an AST is made.
Following codes illustrate a very simple and intuitive BNF.

<Expression> ::= <BinaryExpression>|<UnaryExpression>|<ConditionExpression>|<IdentifierName>|<LiteralExpression>|<InvocationExpression>|<MemberAccessExpression>|<ParenthesizedExpression>

<BinaryExpression> ::= <LeftMember><Operator><RightMember>
<LeftMember> ::= <Expression>
<RightMember> ::= <Expression>

<UnaryExpression> ::= <PreFixUnaryExpression>|<PostFixUnaryExpression>
<PreFixUnaryExpression> ::= <Operator><Expression>
<PostFixUnaryExpression> ::= <Expression><Operator>

<ConditionExpression> ::= <Condition> ? <WhenTrue> : <WhenFalse>
<Condition> ::= <Expression>
<WhenTrue> ::= <Expression>
<WhenFalse> ::= <Expression>

<ParenthesizedExpression> ::= (<Expression>)


Maybe this is not the official and formal BNF but reading it you can also better understand how a "node" is made in term of branches.
For example for a Conditional Expression you have three main "parts" which branches are named <Condition>, <WhenTrue> and <WhenFalse>

Nodes, Branches, Elements, Operators, OperatorCategories

In order to use the Validation Syntax you have to know following enumerations:
  • Nodes: this is the set of supported AST Nodes.
  • Branches: this is the set of supported AST Branches.
  • Elements: this is the set of Macro-Nodes over Nodes, usually for each Macro-Node you have one or more AST Nodes.
  • Operators: this is the set of supported C# Operators
  • OperatorCategory: this is the set of C# Operator groups

Some AST

Here you find list some example of AST.

Literal Expression

x => 1

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
  Parameter :: Roslyn.Compilers.CSharp.ParameterSyntax

Indentifier Expression

x => x

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
  Parameter :: Roslyn.Compilers.CSharp.ParameterSyntax

Unary Expression

x => !x

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.PrefixUnaryExpressionSyntax
   Expression :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
  Parameter :: Roslyn.Compilers.CSharp.ParameterSyntax


Binary Expression

x => x == 1

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.BinaryExpressionSyntax
   LeftMember :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
   RightMember :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
  Parameter :: Roslyn.Compilers.CSharp.ParameterSyntax

Conditional Expression (ternary)

x => x ? 1 : 0

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.ConditionalExpressionSyntax
   Condition :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
   WhenFalse :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
   WhenTrue :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
  Parameter :: Roslyn.Compilers.CSharp.ParameterSyntax

Member Access Expression

x => x.item == 0

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.MemberAccessExpressionSyntax
   Expression :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
  Parameter :: Roslyn.Compilers.CSharp.ParameterSyntax

Invocation Expression

x => x.Check(x,x)

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.InvocationExpressionSyntax
   Argument :: Roslyn.Compilers.CSharp.ArgumentSyntax
    Expression :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
   Argument :: Roslyn.Compilers.CSharp.ArgumentSyntax
    Expression :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
  Parameter :: Roslyn.Compilers.CSharp.ParameterSyntax

Nested Binary Expression

x => x + 1 == 1

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.BinaryExpressionSyntax
   LeftMember :: Roslyn.Compilers.CSharp.BinaryExpressionSyntax
    LeftMember :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
    RightMember :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
   RightMember :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
  Parameter :: Roslyn.Compilers.CSharp.ParameterSyntax

Parenthesized Expression

x => (x == 1)

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.ParenthesizedExpressionSyntax
   Expression :: Roslyn.Compilers.CSharp.BinaryExpressionSyntax
    LeftMember :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
    RightMember :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
  Parameter :: Roslyn.Compilers.CSharp.ParameterSyntax

Nested Expression

x => x.Check(x ? x : 1, x + 1) && !x && (x + 1 == 2)

The AST generated by Roslyn is:
 Input :: Roslyn.Compilers.CSharp.SimpleLambdaExpressionSyntax
  Body :: Roslyn.Compilers.CSharp.BinaryExpressionSyntax
   LeftMember :: Roslyn.Compilers.CSharp.BinaryExpressionSyntax
    LeftMember :: Roslyn.Compilers.CSharp.InvocationExpressionSyntax
     Argument :: Roslyn.Compilers.CSharp.ArgumentSyntax
      Expression :: Roslyn.Compilers.CSharp.ConditionalExpressionSyntax
       Condition :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
       WhenFalse :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
       WhenTrue :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
     Argument :: Roslyn.Compilers.CSharp.ArgumentSyntax
      Expression :: Roslyn.Compilers.CSharp.BinaryExpressionSyntax
       LeftMember :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
       RightMember :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
    RightMember :: Roslyn.Compilers.CSharp.PrefixUnaryExpressionSyntax
     Expression :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
   RightMember :: Roslyn.Compilers.CSharp.ParenthesizedExpressionSyntax
    Expression :: Roslyn.Compilers.CSharp.BinaryExpressionSyntax
     LeftMember :: Roslyn.Compilers.CSharp.BinaryExpressionSyntax
      LeftMember :: Roslyn.Compilers.CSharp.IdentifierNameSyntax
      RightMember :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax
     RightMember :: Roslyn.Compilers.CSharp.LiteralExpressionSyntax

Last edited Jan 8, 2014 at 8:53 PM by SamNium, version 1