<NME> ValueDecl.txt
<BEF> Elm File
  ElmValueDeclaration(VALUE_DECLARATION)
    ElmFunctionDeclarationLeft(FUNCTION_DECLARATION_LEFT)
      PsiElement(LOWER_CASE_IDENTIFIER)('f1')
    PsiWhiteSpace(' ')
    PsiElement(EQ)('=')
    PsiErrorElement:<expression> expected
      <empty list>
  PsiElement(VIRTUAL_END_DECL)('\n')
  PsiWhiteSpace('\n')
  ElmValueDeclaration(VALUE_DECLARATION)
    ElmFunctionDeclarationLeft(FUNCTION_DECLARATION_LEFT)
      PsiElement(LOWER_CASE_IDENTIFIER)('f2')
    PsiWhiteSpace(' ')
    PsiElement(EQ)('=')
    PsiErrorElement:<expression> expected, got 'type'
      <empty list>
  PsiWhiteSpace(' ')
  PsiElement(TYPE)('type')
  PsiWhiteSpace(' ')
  PsiElement(UPPER_CASE_IDENTIFIER)('Blah')
  PsiElement(VIRTUAL_END_DECL)('\n')
  PsiWhiteSpace('\n')
  ElmValueDeclaration(VALUE_DECLARATION)
    ElmFunctionDeclarationLeft(FUNCTION_DECLARATION_LEFT)
      PsiElement(LOWER_CASE_IDENTIFIER)('f3')
      PsiWhiteSpace(' ')
      ElmNumberConstantExpr(NUMBER_CONSTANT_EXPR)
        PsiElement(NUMBER_LITERAL)('42')
    PsiWhiteSpace(' ')
    PsiElement(EQ)('=')
    PsiErrorElement:<expression> expected, got ','
      <empty list>
  PsiWhiteSpace(' ')
  PsiElement(COMMA)(',')

<MSG> First pass on optimizing parser for deeply nested expressions (#506)

Fixes 2 separate performance bugs caused by excessive backtracking in the parser:

1. backtracking when FuncCallExpr parse fails
2. backtracking in parenthesized expressions and tuples

Case 1 is fixed by re-writing the parse rule so that the function call target is relaxed to the superset of Atom expressions and then using obscure GrammarKit functionality (`left`) so that when we try to parse the target as an Atom, we can still use the parsed result even if it is not a function call (no whitespace separated arguments follow).

Case 2 backtracking can occur in:

- parenthesized expression `(4 + 3)`
- a tuple `(4, 3)`
- or a field access expression `(foo model).bar`

The problem is that the naive approach has to parse the expression following the opening ( multiple times since we don't know what we are parsing until we reach a: comma, a right paren followed immediately by a dot, or a right paren. For simple examples like above, this backtracking is not that bad, but when it involves nested expressions, execution time goes non-linear.

I fixed the parenthesized expr and tuple expr cases, but I have not fixed the backtracking caused by field access expressions.

<DFF> @@ -4,7 +4,7 @@ Elm File
       PsiElement(LOWER_CASE_IDENTIFIER)('f1')
     PsiWhiteSpace(' ')
     PsiElement(EQ)('=')
-    PsiErrorElement:<expression> expected
+    PsiErrorElement:<expr> expected
       <empty list>
   PsiElement(VIRTUAL_END_DECL)('\n')
   PsiWhiteSpace('\n')
@@ -13,7 +13,7 @@ Elm File
       PsiElement(LOWER_CASE_IDENTIFIER)('f2')
     PsiWhiteSpace(' ')
     PsiElement(EQ)('=')
-    PsiErrorElement:<expression> expected, got 'type'
+    PsiErrorElement:<expr> expected, got 'type'
       <empty list>
   PsiWhiteSpace(' ')
   PsiElement(TYPE)('type')
@@ -29,7 +29,7 @@ Elm File
         PsiElement(NUMBER_LITERAL)('42')
     PsiWhiteSpace(' ')
     PsiElement(EQ)('=')
-    PsiErrorElement:<expression> expected, got ','
+    PsiErrorElement:<expr> expected, got ','
       <empty list>
   PsiWhiteSpace(' ')
   PsiElement(COMMA)(',')
\ No newline at end of file

First pass on optimizing parser for deeply nested expressions (#506)