I am in search of BNF or EBNF of LINQ. It seems as if a grammar specification of C# is not readily available anywhere, but then, the LINQ fragment might be easy to infer, if not found.
In particular, I cannot figure out the precedence/associativity of join. Note that join may include nested queries, for example:
var result = from a in T
join b in B on a.key equals b.key
join c in C on ???
where ...
...
Here is the grammar I came up with so far:
<Query> ::= <From> <Body>
<Body> ::= <Clause>* <Conclusion> <Continutation>?
<Clause> ::= <From> | <Join> | <Let> | <Order> | <OrderBy>
<From> ::= "from " <Item> "in " <Source>
<Join> ::= "join " <Item> "in " <Source> "on " <Key> "equals " <Key> ( "into " <Item> )?
<Let> ::= "let " <Item> " = " <Selection>
<Order> ::= "where " <Condition>
<OrderBy> ::= "orderby " ( <Key> ( "ascending " | "descending " )?)
<Conclusion> ::= <Select> | <Group>
<Select> ::= " select " <Selection>
<Group> ::= " group " <Selection> "by " <Key>
<Continutation> ::= "into " <Item> <Body>
<Item> ::= "x" [0-9] " "
<Source> ::= "DB" [0-9] <Id> " "
<Selection> ::= "new " "{ " <Fields> "} "
<Key> ::= "K" [0-9] <Id> " "
<Condition> ::= <And>
<And> ::= <Or> ( " && " <Or> )
<Or> ::= <Not> ( " || " <Not> )
<Not> ::= " !"? ( "(" <Condition> ")" | <Comparison> )
<Comparison> ::= <Value> ( "<" | ">" | "==" | "<=" | ">=" | "!=" ) <Value>
<Value> ::= <Key> | <Number>
<Number> ::= [0-0] | ( [1-9] [0-9]* )
<Fields> ::= <Field> (", " <Field>)*
<Field> ::= "F" <Item>
<Id> ::= ( [a-z] | [A-Z] ) ( E | ( [0-9] | [A-Z] | [a-z] ) )
You can play with this grammar in here: "in "
For example, you can generate sample queries based on this syntax.
CodePudding user response:
This document specifies the query syntax:
query_expression
: from_clause query_body
;
from_clause
: 'from' type? identifier 'in' expression
;
query_body
: query_body_clauses? select_or_group_clause query_continuation?
;
query_body_clauses
: query_body_clause
| query_body_clauses query_body_clause
;
query_body_clause
: from_clause
| let_clause
| where_clause
| join_clause
| join_into_clause
| orderby_clause
;
let_clause
: 'let' identifier '=' expression
;
where_clause
: 'where' boolean_expression
;
join_clause
: 'join' type? identifier 'in' expression 'on' expression 'equals' expression
;
join_into_clause
: 'join' type? identifier 'in' expression 'on' expression 'equals' expression 'into' identifier
;
orderby_clause
: 'orderby' orderings
;
orderings
: ordering (',' ordering)*
;
ordering
: expression ordering_direction?
;
ordering_direction
: 'ascending'
| 'descending'
;
select_or_group_clause
: select_clause
| group_clause
;
select_clause
: 'select' expression
;
group_clause
: 'group' expression 'by' expression
;
query_continuation
: 'into' identifier query_body
;