title: EBNF or BNF of LINQ? Associativity of join? Other clauses?
body: <p>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.</p>
  <p>In particular, I cannot figure out the precedence/associativity of join. Note that join may include nested queries, for example:</p>
  <pre><code>var result = from a in T 
               join b in B on a.key equals b.key
               join c in C on ??? 
               where ... 
               ...
  </code></pre>
  <p>Here is the grammar I came up with so far:</p>
  <pre><code>&lt;Query&gt; ::= &lt;From&gt; &lt;Body&gt;
  &lt;Body&gt; ::= &lt;Clause&gt;* &lt;Conclusion&gt; &lt;Continutation&gt;?
  &lt;Clause&gt; ::= &lt;From&gt; | &lt;Join&gt; | &lt;Let&gt; | &lt;Order&gt; | &lt;OrderBy&gt;
  &lt;From&gt; ::= &quot;from &quot; &lt;Item&gt; &quot;in &quot; &lt;Source&gt; 
  &lt;Join&gt; ::= &quot;join &quot; &lt;Item&gt; &quot;in &quot; &lt;Source&gt; &quot;on &quot; &lt;Key&gt; &quot;equals &quot; &lt;Key&gt; ( &quot;into &quot; &lt;Item&gt; )?
  &lt;Let&gt; ::= &quot;let &quot; &lt;Item&gt; &quot; = &quot; &lt;Selection&gt; 
  &lt;Order&gt; ::= &quot;where &quot; &lt;Condition&gt; 
  &lt;OrderBy&gt; ::= &quot;orderby &quot; ( &lt;Key&gt; ( &quot;ascending &quot; | &quot;descending &quot; )?)+
  &lt;Conclusion&gt; ::=  &lt;Select&gt; | &lt;Group&gt; 
  &lt;Select&gt; ::= &quot; select &quot; &lt;Selection&gt; 
  &lt;Group&gt; ::= &quot; group &quot; &lt;Selection&gt; &quot;by &quot; &lt;Key&gt; 
  &lt;Continutation&gt; ::= &quot;into &quot; &lt;Item&gt; &lt;Body&gt; 
  &lt;Item&gt; ::= &quot;x&quot; [0-9]+ &quot; &quot;
  &lt;Source&gt; ::= &quot;DB&quot; [0-9]+  &lt;Id&gt; &quot; &quot;
  &lt;Selection&gt; ::= &quot;new &quot; &quot;{ &quot; &lt;Fields&gt; &quot;} &quot;
  &lt;Key&gt; ::= &quot;K&quot; [0-9]+  &lt;Id&gt; &quot; &quot;
  &lt;Condition&gt; ::= &lt;And&gt;
  &lt;And&gt; ::= &lt;Or&gt; ( &quot; &amp;&amp; &quot; &lt;Or&gt; )
  &lt;Or&gt;  ::= &lt;Not&gt; ( &quot; || &quot; &lt;Not&gt; )
  &lt;Not&gt; ::= &quot; !&quot;? ( &quot;(&quot; &lt;Condition&gt; &quot;)&quot; | &lt;Comparison&gt; )  
  &lt;Comparison&gt; ::= &lt;Value&gt; ( &quot;&lt;&quot; | &quot;&gt;&quot; | &quot;==&quot; | &quot;&lt;=&quot; | &quot;&gt;=&quot; | &quot;!=&quot; ) &lt;Value&gt;
  &lt;Value&gt; ::= &lt;Key&gt; | &lt;Number&gt;
  &lt;Number&gt; ::= [0-0] | ( [1-9] [0-9]*  )
  &lt;Fields&gt; ::= &lt;Field&gt; (&quot;, &quot; &lt;Field&gt;)*
  &lt;Field&gt; ::= &quot;F&quot; &lt;Item&gt;
  &lt;Id&gt; ::= ( [a-z] | [A-Z] ) ( E | ( [0-9] | [A-Z] | [a-z] ) ) 
  </code></pre>
  <p>You can play with this grammar in here: <a href="https://bnfplayground.pauliankline.com/?bnf=%3CQuery%3E%20%3A%3A%3D%20%3CFrom%3E%20%3CBody%3E%0A%3CBody%3E%20%3A%3A%3D%20%3CClause%3E*%20%3CConclusion%3E%20%3CContinutation%3E%3F%0A%3CClause%3E%20%3A%3A%3D%20%3CFrom%3E%20%7C%20%3CJoin%3E%20%7C%20%3CLet%3E%20%7C%20%3COrder%3E%20%7C%20%3COrderBy%3E%0A%3CFrom%3E%20%3A%3A%3D%20%22from%20%22%20%3CItem%3E%20%22in%20%22%20%3CSource%3E%20%0A%3CJoin%3E%20%3A%3A%3D%20%22join%20%22%20%3CItem%3E%20%22in%20%22%20%3CSource%3E%20%22on%20%22%20%3CKey%3E%20%22equals%20%22%20%3CKey%3E%20(%20%22into%20%22%20%3CItem%3E%20)%3F%0A%3CLet%3E%20%3A%3A%3D%20%22let%20%22%20%3CItem%3E%20%22%20%3D%20%22%20%3CSelection%3E%20%0A%3COrder%3E%20%3A%3A%3D%20%22where%20%22%20%3CCondition%3E%20%0A%3COrderBy%3E%20%3A%3A%3D%20%22orderby%20%22%20(%20%3CKey%3E%20(%20%22ascending%20%22%20%7C%20%22descending%20%22%20)%3F)%2B%0A%3CConclusion%3E%20%3A%3A%3D%20%20%3CSelect%3E%20%7C%20%3CGroup%3E%20%0A%3CSelect%3E%20%3A%3A%3D%20%22%20select%20%22%20%3CSelection%3E%20%0A%3CGroup%3E%20%3A%3A%3D%20%22%20group%20%22%20%3CSelection%3E%20%22by%20%22%20%3CKey%3E%20%0A%3CContinutation%3E%20%3A%3A%3D%20%22into%20%22%20%3CItem%3E%20%3CBody%3E%20%0A%3CItem%3E%20%3A%3A%3D%20%22x%22%20%5B0-9%5D%2B%20%22%20%22%0A%3CSource%3E%20%3A%3A%3D%20%22DB%22%20%5B0-9%5D%2B%20%20%3CId%3E%20%22%20%22%0A%3CSelection%3E%20%3A%3A%3D%20%22new%20%22%20%22%7B%20%22%20%3CFields%3E%20%22%7D%20%22%0A%3CKey%3E%20%3A%3A%3D%20%22K%22%20%5B0-9%5D%2B%20%20%3CId%3E%20%22%20%22%0A%3CCondition%3E%20%3A%3A%3D%20%3CAnd%3E%0A%3CAnd%3E%20%3A%3A%3D%20%3COr%3E%20(%20%22%20%26%26%20%22%20%3COr%3E%20)%0A%3COr%3E%20%20%3A%3A%3D%20%3CNot%3E%20(%20%22%20%7C%7C%20%22%20%3CNot%3E%20)%0A%3CNot%3E%20%3A%3A%3D%20%22%20!%22%3F%20(%20%22(%22%20%3CCondition%3E%20%22)%22%20%7C%20%3CComparison%3E%20)%20%20%0A%3CComparison%3E%20%3A%3A%3D%20%3CValue%3E%20(%20%22%3C%22%20%7C%20%22%3E%22%20%7C%20%22%3D%3D%22%20%7C%20%22%3C%3D%22%20%7C%20%22%3E%3D%22%20%7C%20%22!%3D%22%20)%20%3CValue%3E%0A%3CValue%3E%20%3A%3A%3D%20%3CKey%3E%20%7C%20%3CNumber%3E%0A%3CNumber%3E%20%3A%3A%3D%20%5B0-0%5D%20%7C%20(%20%5B1-9%5D%20%5B0-9%5D*%20%20)%0A%3CFields%3E%20%3A%3A%3D%20%3CField%3E%20(%22%2C%20%22%20%3CField%3E)*%0A%3CField%3E%20%3A%3A%3D%20%22F%22%20%3CItem%3E%0A%3CId%3E%20%3A%3A%3D%20(%20%5Ba-z%5D%20%7C%20%5BA-Z%5D%20)%20(%20E%20%7C%20(%20%5B0-9%5D%20%7C%20%5BA-Z%5D%20%7C%20%5Ba-z%5D%20)%20)%20&amp;name=Real%20Numbers" rel="nofollow noreferrer">https://bnfplayground.pauliankline.com/?bnf=%3CQuery%3E%20%3A%3A%3D%20%3CFrom%3E%20%3CBody%3E%0A%3CBody%3E%20%3A%3A%3D%20%3CClause%3E*%20%3CConclusion%3E%20%3CContinutation%3E%3F%0A%3CClause%3E%20%3A%3A%3D%20%3CFrom%3E%20%7C%20%3CJoin%3E%20%7C%20%3CLet%3E%20%7C%20%3COrder%3E%20%7C%20%3COrderBy%3E%0A%3CFrom%3E%20%3A%3A%3D%20%22from%20%22%20%3CItem%3E%20%22in%20%22%20%3CSource%3E%20%0A%3CJoin%3E%20%3A%3A%3D%20%22join%20%22%20%3CItem%3E%20%22in%20%22%20%3CSource%3E%20%22on%20%22%20%3CKey%3E%20%22equals%20%22%20%3CKey%3E%20(%20%22into%20%22%20%3CItem%3E%20)%3F%0A%3CLet%3E%20%3A%3A%3D%20%22let%20%22%20%3CItem%3E%20%22%20%3D%20%22%20%3CSelection%3E%20%0A%3COrder%3E%20%3A%3A%3D%20%22where%20%22%20%3CCondition%3E%20%0A%3COrderBy%3E%20%3A%3A%3D%20%22orderby%20%22%20(%20%3CKey%3E%20(%20%22ascending%20%22%20%7C%20%22descending%20%22%20)%3F)%2B%0A%3CConclusion%3E%20%3A%3A%3D%20%20%3CSelect%3E%20%7C%20%3CGroup%3E%20%0A%3CSelect%3E%20%3A%3A%3D%20%22%20select%20%22%20%3CSelection%3E%20%0A%3CGroup%3E%20%3A%3A%3D%20%22%20group%20%22%20%3CSelection%3E%20%22by%20%22%20%3CKey%3E%20%0A%3CContinutation%3E%20%3A%3A%3D%20%22into%20%22%20%3CItem%3E%20%3CBody%3E%20%0A%3CItem%3E%20%3A%3A%3D%20%22x%22%20%5B0-9%5D%2B%20%22%20%22%0A%3CSource%3E%20%3A%3A%3D%20%22DB%22%20%5B0-9%5D%2B%20%20%3CId%3E%20%22%20%22%0A%3CSelection%3E%20%3A%3A%3D%20%22new%20%22%20%22%7B%20%22%20%3CFields%3E%20%22%7D%20%22%0A%3CKey%3E%20%3A%3A%3D%20%22K%22%20%5B0-9%5D%2B%20%20%3CId%3E%20%22%20%22%0A%3CCondition%3E%20%3A%3A%3D%20%3CAnd%3E%0A%3CAnd%3E%20%3A%3A%3D%20%3COr%3E%20(%20%22%20%26%26%20%22%20%3COr%3E%20)%0A%3COr%3E%20%20%3A%3A%3D%20%3CNot%3E%20(%20%22%20%7C%7C%20%22%20%3CNot%3E%20)%0A%3CNot%3E%20%3A%3A%3D%20%22%20!%22%3F%20(%20%22(%22%20%3CCondition%3E%20%22)%22%20%7C%20%3CComparison%3E%20)%20%20%0A%3CComparison%3E%20%3A%3A%3D%20%3CValue%3E%20(%20%22%3C%22%20%7C%20%22%3E%22%20%7C%20%22%3D%3D%22%20%7C%20%22%3C%3D%22%20%7C%20%22%3E%3D%22%20%7C%20%22!%3D%22%20)%20%3CValue%3E%0A%3CValue%3E%20%3A%3A%3D%20%3CKey%3E%20%7C%20%3CNumber%3E%0A%3CNumber%3E%20%3A%3A%3D%20%5B0-0%5D%20%7C%20(%20%5B1-9%5D%20%5B0-9%5D*%20%20)%0A%3CFields%3E%20%3A%3A%3D%20%3CField%3E%20(%22%2C%20%22%20%3CField%3E)*%0A%3CField%3E%20%3A%3A%3D%20%22F%22%20%3CItem%3E%0A%3CId%3E%20%3A%3A%3D%20(%20%5Ba-z%5D%20%7C%20%5BA-Z%5D%20)%20(%20E%20%7C%20(%20%5B0-9%5D%20%7C%20%5BA-Z%5D%20%7C%20%5Ba-z%5D%20)%20)%20&amp;name=Real%20Numbers</a></p>
  <p>For example, you can generate sample queries based on this syntax.</p>