on master help sign in
dont use partial functions
a99e963martinbaker
docs/parserLibrary/parser.rst+51−55
@@ -598,10 +598,11 @@ problem: the precedence of the operators ``+``, ``-`` and ``*`` is not explicit.
598.. list-table::
598.. list-table::
599
599
600 * - To resolve this we can alter the example to have a BNF like this:
600 * - To resolve this we can alter the example to have a BNF like this:
601+ Where braces ``{ ... }`` mean the contents can occur 1 or more times.
601
602
602 - .. code-block:: idris
603 - .. code-block:: idris
603
604
604− 'expression' ::= ['+'|'-'] 'term' {('+'|'-') 'term'}
605+ 'expression' ::= ('+'|'-') 'term' {('+'|'-') 'term'}
605
606
606 'term' ::= 'factor' {'*' 'factor'}
607 'term' ::= 'factor' {'*' 'factor'}
607
608
@@ -612,46 +613,44 @@ problem: the precedence of the operators ``+``, ``-`` and ``*`` is not explicit.
612
613
613.. code-block:: idris
614.. code-block:: idris
614
615
615− paren : Rule Integer -> Rule Integer
616− paren exp = openParen *> exp <* closeParen
617−
618− addInt : Integer -> Integer -> Integer
619− addInt a b = a+b
620−
621− subInt : Integer -> Integer -> Integer
622− subInt a b = a-b
623−
624− multInt : Integer -> Integer -> Integer
625− multInt a b = a*b
626−
627− partial
628 expr : Rule Integer
616 expr : Rule Integer
629
617
630− partial
631− exprAtom : Rule Integer
618+ factor : Rule Integer
632− exprAtom = intLiteral <|> (paren expr)
619+ factor = intLiteral <|> do
633−
620+ openParen
634− partial
621+ r <- expr
635− expr1 : Rule Integer
622+ closeParen
636− expr1 = map multInt exprAtom <*> ((op "*") *> exprAtom)
623+ pure r
637−
638− partial
639− exprMult : Rule Integer
640− exprMult = expr1 <|> exprAtom
641
624
642− partial
643− expr2 : Rule Integer
625+ term : Rule Integer
644− expr2 = map addInt exprMult <*> ((op "+") *> exprMult)
626+ term = map multInt factor <*> (
627+ (op "*")
628+ *> factor)
629+ <|> factor
630+
631+ expr = map addInt term <*> (
632+ (op "+")
633+ *> term)
634+ <|> map subInt term <*> (
635+ (op "-")
636+ *> term)
637+ <|> term
638+
639+ calc : String -> Either (ParseError (TokenData ExpressionToken))
640+ (Integer, List (TokenData ExpressionToken))
641+ calc s = parse expr (fst (lex expressionTokens s))
645
642
646− partial
643+ lft : (ParseError (TokenData ExpressionToken)) -> IO ()
647− exprAdd : Rule Integer
644+ lft (Error s lst) = putStrLn ("error:"++s)
648− exprAdd = expr2 <|> exprMult
649
645
650− partial
646+ rht : (Integer, List (TokenData ExpressionToken)) -> IO ()
651− expr3 : Rule Integer
647+ rht i = putStrLn ("right " ++ (show i))
652− expr3 = map subInt exprAdd <*> ((op "-") *> expr)
653
648
654− expr = expr3 <|> exprAdd
649+ main : IO ()
650+ main = do
651+ putStr "alg>"
652+ x <- getLine
653+ either lft rht (calc x) -- eliminator for Either
655
654
656As the following tests show, this now handles infix operators and precedence.
655As the following tests show, this now handles infix operators and precedence.
657
656
@@ -661,44 +660,41 @@ As the following tests show, this now handles infix operators and precedence.
661
660
662 - .. code-block:: idris
661 - .. code-block:: idris
663
662
664− *parserExInfix> test "2*3"
663+ *algebraREPL> :exec
665− Right (6,
664+ alg>2*3
666− []) : Either (ParseError (TokenData ExpressionToken))
665+ right (6, [])
667− (Integer, List (TokenData ExpressionToken))
668
666
669 * - Check that atomic number literals work:
667 * - Check that atomic number literals work:
670
668
671 - .. code-block:: idris
669 - .. code-block:: idris
672
670
673− *parserExInfix> test "2"
671+ *algebraREPL> :exec
674− Right (2,
672+ alg>2
675− []) : Either (ParseError (TokenData ExpressionToken))
673+ right (2, [])
676− (Integer, List (TokenData ExpressionToken))
677
674
678 * - Check that '*' has a higher precedence than '+'.
675 * - Check that '*' has a higher precedence than '+'.
679
676
680 - .. code-block:: idris
677 - .. code-block:: idris
681
678
682− *parserExInfix> test "2+3*4"
679+ *algebraREPL> :exec
683− Right (14,
680+ alg>2+3*4
684− []) : Either (ParseError (TokenData ExpressionToken))
681+ right (14, [])
685− (Integer, List (TokenData ExpressionToken))
686
682
687 * - Also '*' has a higher precedence than '+' when the order is reversed.
683 * - Also '*' has a higher precedence than '+' when the order is reversed.
688
684
689 - .. code-block:: idris
685 - .. code-block:: idris
690
686
691− *parserExInfix> test "3*4+2"
687+ *algebraREPL> :exec
692− Right (14,
688+ alg>3*4+2
693− []) : Either (ParseError (TokenData ExpressionToken))
689+ right (14, [])
694− (Integer, List (TokenData ExpressionToken))
695
690
696 * - Also precedence can be overridden by parenthesis.
691 * - Also precedence can be overridden by parenthesis.
697
692
698 - .. code-block:: idris
693 - .. code-block:: idris
699
694
700− *parserExInfix> test "(2+3)*4"
695+ *algebraREPL> :exec
701− Right (20,
696+ alg>(2+3)*4
702− []) : Either (ParseError (TokenData ExpressionToken))
697+ right (20, [])
703− (Integer, List (TokenData ExpressionToken))
704
698
699+This is still not correct because it does not correctly parse multiple sums or terms
700+like ``1+2+3`` or ``1*2*3``.