on master help sign in
dont use partial functions
commita99e9632a7198a6f3b322ab256a25b48cb9e933f authormartinbaker <git29f185@martinb.com> dateThu 16 Jan 2020, 12:45 (7 years ago) parent50db7e1
1 file changed+51−55
docs/parserLibrary/parser.rst+51−55
docs/parserLibrary/parser.rst+51−55
@@ -598,10 +598,11 @@ problem: the precedence of the operators ``+``, ``-`` and ``*`` is not explicit.
598598.. list-table::
599599
600600 * - 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.
601602
602603 - .. code-block:: idris
603604
604− 'expression' ::= ['+'|'-'] 'term' {('+'|'-') 'term'}
605+ 'expression' ::= ('+'|'-') 'term' {('+'|'-') 'term'}
605606
606607 'term' ::= 'factor' {'*' 'factor'}
607608
@@ -612,46 +613,44 @@ problem: the precedence of the operators ``+``, ``-`` and ``*`` is not explicit.
612613
613614.. code-block:: idris
614615
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
628616 expr : Rule Integer
629617
630− partial
631− exprAtom : Rule Integer
632− exprAtom = intLiteral <|> (paren expr)
633−
634− partial
635− expr1 : Rule Integer
636− expr1 = map multInt exprAtom <*> ((op "*") *> exprAtom)
637−
638− partial
639− exprMult : Rule Integer
640− exprMult = expr1 <|> exprAtom
618+ factor : Rule Integer
619+ factor = intLiteral <|> do
620+ openParen
621+ r <- expr
622+ closeParen
623+ pure r
641624
642− partial
643− expr2 : Rule Integer
644− expr2 = map addInt exprMult <*> ((op "+") *> exprMult)
625+ term : Rule Integer
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))
645642
646− partial
647− exprAdd : Rule Integer
648− exprAdd = expr2 <|> exprMult
643+ lft : (ParseError (TokenData ExpressionToken)) -> IO ()
644+ lft (Error s lst) = putStrLn ("error:"++s)
649645
650− partial
651− expr3 : Rule Integer
652− expr3 = map subInt exprAdd <*> ((op "-") *> expr)
646+ rht : (Integer, List (TokenData ExpressionToken)) -> IO ()
647+ rht i = putStrLn ("right " ++ (show i))
653648
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
655654
656655As the following tests show, this now handles infix operators and precedence.
657656
@@ -661,44 +660,41 @@ As the following tests show, this now handles infix operators and precedence.
661660
662661 - .. code-block:: idris
663662
664− *parserExInfix> test "2*3"
665− Right (6,
666− []) : Either (ParseError (TokenData ExpressionToken))
667− (Integer, List (TokenData ExpressionToken))
663+ *algebraREPL> :exec
664+ alg>2*3
665+ right (6, [])
668666
669667 * - Check that atomic number literals work:
670668
671669 - .. code-block:: idris
672670
673− *parserExInfix> test "2"
674− Right (2,
675− []) : Either (ParseError (TokenData ExpressionToken))
676− (Integer, List (TokenData ExpressionToken))
671+ *algebraREPL> :exec
672+ alg>2
673+ right (2, [])
677674
678675 * - Check that '*' has a higher precedence than '+'.
679676
680677 - .. code-block:: idris
681678
682− *parserExInfix> test "2+3*4"
683− Right (14,
684− []) : Either (ParseError (TokenData ExpressionToken))
685− (Integer, List (TokenData ExpressionToken))
679+ *algebraREPL> :exec
680+ alg>2+3*4
681+ right (14, [])
686682
687683 * - Also '*' has a higher precedence than '+' when the order is reversed.
688684
689685 - .. code-block:: idris
690686
691− *parserExInfix> test "3*4+2"
692− Right (14,
693− []) : Either (ParseError (TokenData ExpressionToken))
694− (Integer, List (TokenData ExpressionToken))
687+ *algebraREPL> :exec
688+ alg>3*4+2
689+ right (14, [])
695690
696691 * - Also precedence can be overridden by parenthesis.
697692
698693 - .. code-block:: idris
699694
700− *parserExInfix> test "(2+3)*4"
701− Right (20,
702− []) : Either (ParseError (TokenData ExpressionToken))
703− (Integer, List (TokenData ExpressionToken))
695+ *algebraREPL> :exec
696+ alg>(2+3)*4
697+ right (20, [])
704698
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``.