diff options
author | Sergio Queiroz <sqmedeiros@gmail.com> | 2016-07-14 16:05:13 -0300 |
---|---|---|
committer | Sergio Queiroz <sqmedeiros@gmail.com> | 2016-07-14 16:05:13 -0300 |
commit | 2f74ecc812c5ad7e95a55175c3d4de9ab9e0c551 (patch) | |
tree | c1f5541a90a0f2083acfb37e1d420a1614cf6a5b /testlabel.lua | |
parent | a0891e8f58c5ea1ab777bf607949237894249907 (diff) | |
download | lpeglabel-2f74ecc812c5ad7e95a55175c3d4de9ab9e0c551.tar.gz lpeglabel-2f74ecc812c5ad7e95a55175c3d4de9ab9e0c551.tar.bz2 lpeglabel-2f74ecc812c5ad7e95a55175c3d4de9ab9e0c551.zip |
Adding more tests
Diffstat (limited to 'testlabel.lua')
-rw-r--r-- | testlabel.lua | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/testlabel.lua b/testlabel.lua index 2243826..db16354 100644 --- a/testlabel.lua +++ b/testlabel.lua | |||
@@ -589,6 +589,144 @@ checkeqlab({nil, 0, "bc"}, g:match("bbc")) | |||
589 | assert(g:match("xxc") == 4) | 589 | assert(g:match("xxc") == 4) |
590 | assert(g:match("c") == 2) | 590 | assert(g:match("c") == 2) |
591 | checkeqlab({nil, 0, ""}, g:match("fail")) | 591 | checkeqlab({nil, 0, ""}, g:match("fail")) |
592 | checkeqlab({nil, 0, ""}, g:match("aaxx")) | ||
593 | |||
594 | --[[ | ||
595 | S -> (A //{99} (!c .)*) C | ||
596 | A -> a+ (b / ^99) | ||
597 | C -> c+ | ||
598 | ]] | ||
599 | g = m.P{ | ||
600 | "S", | ||
601 | S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0, 99) * m.V"C", | ||
602 | A = m.P"a"^1 * ("b" + m.T(99)), | ||
603 | C = m.P"c"^1, | ||
604 | } | ||
605 | |||
606 | assert(g:match("abc") == 4) | ||
607 | assert(g:match("aabc") == 5) | ||
608 | assert(g:match("aadc") == 5) | ||
609 | checkeqlab({nil, 0, "bc"}, g:match("bc")) | ||
610 | checkeqlab({nil, 0, "bbc"}, g:match("bbc")) | ||
611 | checkeqlab({nil, 0, "b"}, g:match("abb")) | ||
612 | checkeqlab({nil, 0, ""}, g:match("axx")) | ||
613 | assert(g:match("accc") == 5) | ||
614 | assert(g:match("axxc") == 5) | ||
615 | checkeqlab({nil, 0, "c"}, g:match("c")) | ||
616 | checkeqlab({nil, 0, "fail"}, g:match("fail")) | ||
617 | |||
618 | |||
619 | |||
620 | -- Matthew's recovery example | ||
621 | lpeg = m | ||
622 | |||
623 | local R, S, P, V = lpeg.R, lpeg.S, lpeg.P, lpeg.V | ||
624 | local C, Cc, Ct, Cmt = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cmt | ||
625 | local T, Lc = lpeg.T, lpeg.Lc | ||
626 | |||
627 | local labels = { | ||
628 | {"NoExp", "no expression found"}, | ||
629 | {"Extra", "extra characters found after the expression"}, | ||
630 | {"ExpTerm", "expected a term after the operator"}, | ||
631 | {"ExpExp", "expected an expression after the parenthesis"}, | ||
632 | {"MisClose", "missing a closing ')' after the expression"}, | ||
633 | } | ||
634 | |||
635 | local function labelindex(labname) | ||
636 | for i, elem in ipairs(labels) do | ||
637 | if elem[1] == labname then | ||
638 | return i | ||
639 | end | ||
640 | end | ||
641 | error("could not find label: " .. labname) | ||
642 | end | ||
643 | |||
644 | local errors = {} | ||
645 | |||
646 | local function expect(patt, labname) | ||
647 | local i = labelindex(labname) | ||
648 | function recorderror(input, pos) | ||
649 | table.insert(errors, {i, pos}) | ||
650 | return true | ||
651 | end | ||
652 | return patt + Cmt("", recorderror) * T(i) | ||
653 | end | ||
654 | |||
655 | local num = R("09")^1 / tonumber | ||
656 | local op = S("+-*/") | ||
657 | |||
658 | local function compute(tokens) | ||
659 | local result = tokens[1] | ||
660 | for i = 2, #tokens, 2 do | ||
661 | if tokens[i] == '+' then | ||
662 | result = result + tokens[i+1] | ||
663 | elseif tokens[i] == '-' then | ||
664 | result = result - tokens[i+1] | ||
665 | elseif tokens[i] == '*' then | ||
666 | result = result * tokens[i+1] | ||
667 | elseif tokens[i] == '/' then | ||
668 | result = result / tokens[i+1] | ||
669 | else | ||
670 | error('unknown operation: ' .. tokens[i]) | ||
671 | end | ||
672 | end | ||
673 | return result | ||
674 | end | ||
675 | |||
676 | local g = P { | ||
677 | "Exp", | ||
678 | Exp = Ct(V"Term" * (C(op) * V"OpRecov")^0) / compute; | ||
679 | OpRecov = m.Rec(V"Operand", Cc(0), labelindex("ExpTerm")); | ||
680 | Operand = expect(V"Term", "ExpTerm"); | ||
681 | Term = num + V"Group"; | ||
682 | Group = "(" * V"InnerExp" * m.Rec(expect(")", "MisClose"), P"", labelindex("MisClose")); | ||
683 | InnerExp = m.Rec(expect(V"Exp", "ExpExp"), (P(1) - ")")^0 * Cc(0), labelindex("ExpExp")); | ||
684 | } | ||
685 | |||
686 | g = expect(g, "NoExp") * expect(-P(1), "Extra") | ||
687 | |||
688 | local function eval(input) | ||
689 | local result, label, suffix = g:match(input) | ||
690 | if #errors == 0 then | ||
691 | return result | ||
692 | else | ||
693 | local out = {} | ||
694 | for i, err in ipairs(errors) do | ||
695 | local pos = err[2] | ||
696 | local msg = labels[err[1]][2] | ||
697 | table.insert(out, "syntax error: " .. msg .. " (at index " .. pos .. ")") | ||
698 | end | ||
699 | errors = {} | ||
700 | return nil, table.concat(out, "\n") | ||
701 | end | ||
702 | end | ||
703 | |||
704 | print(eval "98-76*(54/32)") | ||
705 | --> 37.125 | ||
706 | |||
707 | print(eval "(1+1-1*2/2") | ||
708 | --> syntax error: missing a closing ')' after the expression (at index 11) | ||
709 | |||
710 | print(eval "(1+)-1*(2/2)") | ||
711 | --> syntax error: expected a term after the operator (at index 4) | ||
712 | |||
713 | print(eval "(1+1)-1*(/2)") | ||
714 | --> syntax error: expected an expression after the parenthesis (at index 10) | ||
715 | |||
716 | print(eval "1+(1-(1*2))/2x") | ||
717 | --> syntax error: extra chracters found after the expression (at index 14) | ||
718 | |||
719 | print(eval "-1+(1-(1*2))/2") | ||
720 | --> syntax error: no expression found (at index 1) | ||
721 | |||
722 | print(eval "(1+1-1*(2/2+)-():") | ||
723 | --> syntax error: expected a term after the operator (at index 13) | ||
724 | --> syntax error: expected an expression after the parenthesis (at index 16) | ||
725 | --> syntax error: missing a closing ')' after the expression (at index 17) | ||
726 | --> syntax error: extra characters found after the expression (at index | ||
727 | |||
728 | |||
729 | |||
592 | 730 | ||
593 | print("OK") | 731 | print("OK") |
594 | 732 | ||