@@ -430,10 +430,10 @@ then it will return 'Right' (to indicate success)
430Infix Notation
430Infix Notation
431--------------
431--------------
433−So far we have implemented a prefix notation for operators (like this: '+ expr expr')
433+So far we have implemented a prefix notation for operators (like this:
434−but the aim is to implemented an infix notation (like this: 'expr + expr'). To do
434+'+ expr expr') but the aim is to implemented an infix notation (like this:
435−this we must be able to deal with potentially infinite data structures (see Codata Types
435+'expr + expr'). To do this we must be able to deal with potentially
436−here :ref:`sect-typefuns`).
436+infinite data structures (see Codata Types here :ref:`sect-typefuns`).
438First alter the grammar to have infix operations:
438First alter the grammar to have infix operations:
@@ -479,4 +479,134 @@ First alter the grammar to have infix operations:
480However, if this was run, the code would not terminate.
480However, if this was run, the code would not terminate.
482+Implement Left Recursion Elimination
483+------------------------------------
485+Left factoring, like this, is a general problem.
487+If we have a rule like this:
489+.. code-block:: idris
491+ A -> (x<*>y) <|> (x<*>z)
493+If 'x<*>y' fails but 'x<*>z' would succeed a problem is that, 'x<*>y' has already consumed 'x', so now 'x<*>z' will fail.
495+so we could write code to backtrack. That is 'try' 'x<*>y' without consuming so that, if the first token succeeds but the following tokens fail, then the first tokens would not be consumed.
497+Another approach is left factoring:
502+Replace the rule with two rules (that is we add a non-terminal symbol) so for example, instead of:
504+.. code-block:: idris
506+ A -> (x<*>y) <|> (x<*>z)
508+we add an extra rule to give:
510+.. code-block:: idris
515+That is we convert a general context-free grammar to a LL(1) grammar. Although not every context-free grammar can be converted to a LL(1) grammar.
517+This still does not solve the infinite recursion issue and there is another problem: the precedence of the operators +, - and * is not explicit.
519+To resolve this we can alter the example like this:
521+.. code-block:: idris
523+ paren : Rule Integer -> Rule Integer
524+ paren exp = openParen *> exp <* closeParen
526+ addInt : Integer -> Integer -> Integer
529+ subInt : Integer -> Integer -> Integer
532+ multInt : Integer -> Integer -> Integer
539+ exprAtom : Rule Integer
540+ exprAtom = intLiteral <|> (paren expr)
543+ expr1 : Rule Integer
544+ expr1 = map multInt exprAtom <*> ((op "*") *> exprAtom)
547+ exprMult : Rule Integer
548+ exprMult = expr1 <|> exprAtom
551+ expr2 : Rule Integer
552+ expr2 = map addInt exprMult <*> ((op "+") *> exprMult)
555+ exprAdd : Rule Integer
556+ exprAdd = expr2 <|> exprMult
559+ expr3 : Rule Integer
560+ expr3 = map subInt exprAdd <*> ((op "-") *> expr)
562+ expr = expr3 <|> exprAdd
564+As the following tests show, this now handles infix operators and precedence.
568+ * - For example '*' is an infix operator:
570+ - .. code-block:: idris
572+ *parserExInfix> test "2*3"
574+ []) : Either (ParseError (TokenData ExpressionToken))
575+ (Integer, List (TokenData ExpressionToken))
577+ * - Check that atomic number literals work:
579+ - .. code-block:: idris
581+ *parserExInfix> test "2"
583+ []) : Either (ParseError (TokenData ExpressionToken))
584+ (Integer, List (TokenData ExpressionToken))
586+ * - Check that '*' has a higher precedence than '+'.
588+ - .. code-block:: idris
590+ *parserExInfix> test "2+3*4"
592+ []) : Either (ParseError (TokenData ExpressionToken))
593+ (Integer, List (TokenData ExpressionToken))
595+ * - Also '*' has a higher precedence than '+' when the order is reversed.
597+ - .. code-block:: idris
599+ *parserExInfix> test "3*4+2"
601+ []) : Either (ParseError (TokenData ExpressionToken))
602+ (Integer, List (TokenData ExpressionToken))
604+ * - Also precedence can be overridden by parenthesis.
606+ - .. code-block:: idris
608+ *parserExInfix> test "(2+3)*4"
610+ []) : Either (ParseError (TokenData ExpressionToken))
611+ (Integer, List (TokenData ExpressionToken))