# HG changeset patch # User Jan Vrany # Date 1412296593 -3600 # Node ID e2b2f08d054e9677249b2ed2308912e3e6dc9355 # Parent 1ba87229ee7e337e4c2dd6628cf55e7f864bfaa5 All tests moved from stx:goodies/petitparser to stx:goodies/petitparser/tests ..,to conform package layout standards. diff -r 1ba87229ee7e -r e2b2f08d054e Make.spec --- a/Make.spec Fri Oct 03 00:52:34 2014 +0100 +++ b/Make.spec Fri Oct 03 01:36:33 2014 +0100 @@ -82,8 +82,6 @@ PPRepeatingParser \ PPSequenceParser \ PPTrimmingParser \ - PPArithmeticParser \ - PPLambdaParser \ PPLimitedRepeatingParser \ PPPossessiveRepeatingParser \ PPTokenParser \ @@ -127,8 +125,6 @@ $(OUTDIR_SLASH)PPRepeatingParser.$(O) \ $(OUTDIR_SLASH)PPSequenceParser.$(O) \ $(OUTDIR_SLASH)PPTrimmingParser.$(O) \ - $(OUTDIR_SLASH)PPArithmeticParser.$(O) \ - $(OUTDIR_SLASH)PPLambdaParser.$(O) \ $(OUTDIR_SLASH)PPLimitedRepeatingParser.$(O) \ $(OUTDIR_SLASH)PPPossessiveRepeatingParser.$(O) \ $(OUTDIR_SLASH)PPTokenParser.$(O) \ diff -r 1ba87229ee7e -r e2b2f08d054e PPAbstractParseTest.st --- a/PPAbstractParseTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -TestCase subclass:#PPAbstractParseTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Core' -! - - -!PPAbstractParseTest class methodsFor:'accessing'! - -packageNamesUnderTest - ^ #('PetitParser' 'PetitTests') -! ! - -!PPAbstractParseTest class methodsFor:'testing'! - -isAbstract - ^ self name = #PPAbstractParseTest -! ! - -!PPAbstractParseTest methodsFor:'utilities'! - -assert: aParser fail: aCollection - self assert: aParser fail: aCollection end: 0 -! - -assert: aParser fail: aCollection end: anInteger - | stream result | - self - assert: aParser isPetitParser - description: 'Parser invalid'. - stream := aCollection asPetitStream. - result := aParser parse: stream. - self - assert: result isPetitFailure - description: 'Parser did not fail'. - self - assert: stream position = anInteger - description: 'Parser failed at wrong position' -! - -assert: aParser parse: aCollection - self assert: aParser parse: aCollection to: nil end: aCollection size -! - -assert: aParser parse: aCollection end: anInteger - self assert: aParser parse: aCollection to: nil end: anInteger -! - -assert: aParser parse: aCollection to: anObject - self assert: aParser parse: aCollection to: anObject end: aCollection size -! - -assert: aParser parse: aParseObject to: aTargetObject end: anInteger - | stream result | - self - assert: aParser isPetitParser - description: 'Parser invalid'. - stream := aParseObject asPetitStream. - result := aParser parse: stream. - aTargetObject isNil - ifTrue: [ self deny: result isPetitFailure ] - ifFalse: [ self assert: result = aTargetObject ]. - self - assert: stream position = anInteger - description: 'Parser accepted at wrong position' - - "Modified: / 18-12-2010 / 18:01:30 / Jan Kurs " -! - -assert: aParser parse: aParserObject toToken: from stop: to - | token | - token := PPToken on: aParserObject start: from stop: to. - ^ self assert: aParser parse: aParserObject to: token -! - -assert: aParser parse: aParserObject toToken: from stop: to end: end - | token | - token := PPToken on: aParserObject start: from stop: to. - ^ self assert: aParser parse: aParserObject to: token end: end -! ! - -!PPAbstractParseTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPAbstractParseTest.st,v 1.3 2012-05-04 22:09:07 vrany Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPAbstractParseTest.st,v 1.3 2012-05-04 22:09:07 vrany Exp $' -! - -version_SVN - ^ '§Id: PPAbstractParseTest.st 4 2010-12-18 17:02:23Z kursjan §' -! ! diff -r 1ba87229ee7e -r e2b2f08d054e PPArithmeticParser.st --- a/PPArithmeticParser.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPCompositeParser subclass:#PPArithmeticParser - instanceVariableNames:'terms addition factors multiplication power primary parentheses - number' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Examples' -! - - -!PPArithmeticParser methodsFor:'accessing'! - -start - ^ terms end -! ! - -!PPArithmeticParser methodsFor:'grammar'! - -addition - ^ (factors separatedBy: ($+ asParser / $- asParser) trim) - foldLeft: [ :a :op :b | a perform: op asSymbol with: b ] -! - -factors - ^ multiplication / power -! - -multiplication - ^ (power separatedBy: ($* asParser / $/ asParser) trim) - foldLeft: [ :a :op :b | a perform: op asSymbol with: b ] -! - -number - ^ ($- asParser optional , #digit asParser plus , ($. asParser , #digit asParser plus) optional) flatten trim - ==> [ :value | value asNumber ] -! - -parentheses - ^ $( asParser trim , terms , $) asParser trim - ==> [ :nodes | nodes second ] -! - -power - ^ (primary separatedBy: $^ asParser trim) - foldRight: [ :a :op :b | a raisedTo: b ] -! - -primary - ^ number / parentheses -! - -terms - ^ addition / factors -! ! - -!PPArithmeticParser class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPArithmeticParser.st,v 1.4 2014-03-04 14:33:59 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPArithmeticParser.st,v 1.4 2014-03-04 14:33:59 cg Exp $' -! - -version_SVN - ^ '$Id: PPArithmeticParser.st,v 1.4 2014-03-04 14:33:59 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPArithmeticParserTest.st --- a/PPArithmeticParserTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPCompositeParserTest subclass:#PPArithmeticParserTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPArithmeticParserTest methodsFor:'accessing'! - -parserClass - ^ PPArithmeticParser -! ! - -!PPArithmeticParserTest methodsFor:'testing'! - -testNum - self assert: '0' is: 0. - self assert: '0.0' is: 0.0. - self assert: '1' is: 1. - self assert: '1.2' is: 1.2. - self assert: '34' is: 34. - self assert: '56.78' is: 56.78. - self assert: '-9' is: -9. - self assert: '-9.9' is: -9.9 -! ! - -!PPArithmeticParserTest methodsFor:'testing-expression'! - -testBrackets - self assert: '(1)' is: 1. - self assert: '(1 + 2)' is: 3. - - self assert: '((1))' is: 1. - self assert: '((1 + 2))' is: 3. - - self assert: '2 * (3 + 4)' is: 14. - self assert: '(2 + 3) * 4' is: 20. - self assert: '6 / (2 + 4)' is: 1. - self assert: '(2 + 6) / 2' is: 4 -! - -testPriority - self assert: '2 * 3 + 4' is: 10. - self assert: '2 + 3 * 4' is: 14. - self assert: '6 / 3 + 4' is: 6. - self assert: '2 + 6 / 2' is: 5 -! ! - -!PPArithmeticParserTest methodsFor:'testing-operations'! - -testAdd - self assert: '1 + 2' is: 3. - self assert: '2 + 1' is: 3. - self assert: '1 + 2.3' is: 3.3. - self assert: '2.3 + 1' is: 3.3. - self assert: '1 + -2' is: -1. - self assert: '-2 + 1' is: -1 -! - -testAddMany - self assert: '1' is: 1. - self assert: '1 + 2' is: 3. - self assert: '1 + 2 + 3' is: 6. - self assert: '1 + 2 + 3 + 4' is: 10. - self assert: '1 + 2 + 3 + 4 + 5' is: 15 -! - -testDiv - self assert: '12 / 3' is: 4. - self assert: '-16 / -4' is: 4 -! - -testDivMany - self assert: '100 / 2' is: 50. - self assert: '100 / 2 / 2' is: 25. - self assert: '100 / 2 / 2 / 5' is: 5. - self assert: '100 / 2 / 2 / 5 / 5' is: 1 - -! - -testMul - self assert: '2 * 3' is: 6. - self assert: '2 * -4' is: -8 -! - -testMulMany - self assert: '1 * 2' is: 2. - self assert: '1 * 2 * 3' is: 6. - self assert: '1 * 2 * 3 * 4' is: 24. - self assert: '1 * 2 * 3 * 4 * 5' is: 120 -! - -testPow - self assert: '2 ^ 3' is: 8. - self assert: '-2 ^ 3' is: -8. - self assert: '-2 ^ -3' is: -0.125 -! - -testPowMany - self assert: '4 ^ 3' is: 64. - self assert: '4 ^ 3 ^ 2' is: 262144. - self assert: '4 ^ 3 ^ 2 ^ 1' is: 262144. - self assert: '4 ^ 3 ^ 2 ^ 1 ^ 0' is: 262144 -! - -testSub - self assert: '1 - 2' is: -1. - self assert: '1.2 - 1.2' is: 0. - self assert: '1 - -2' is: 3. - self assert: '-1 - -2' is: 1 -! - -testSubMany - self assert: '1' is: 1. - self assert: '1 - 2' is: -1. - self assert: '1 - 2 - 3' is: -4. - self assert: '1 - 2 - 3 - 4' is: -8. - self assert: '1 - 2 - 3 - 4 - 5' is: -13 -! ! - -!PPArithmeticParserTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPArithmeticParserTest.st,v 1.4 2014-03-04 14:34:09 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPArithmeticParserTest.st,v 1.4 2014-03-04 14:34:09 cg Exp $' -! - -version_SVN - ^ '$Id: PPArithmeticParserTest.st,v 1.4 2014-03-04 14:34:09 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPComposedTest.st --- a/PPComposedTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,416 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPAbstractParserTest subclass:#PPComposedTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPComposedTest methodsFor:'accessing'! - -comment - ^ ($" asParser , $" asParser negate star , $" asParser) flatten -! - -identifier - ^ (#letter asParser , #word asParser star) flatten -! - -number - ^ ($- asParser optional , #digit asParser plus , ($. asParser , #digit asParser plus) optional) flatten -! ! - -!PPComposedTest methodsFor:'testing'! - -testDoubledString - | parser | - parser := ($' asParser , (($' asParser , $' asParser) / $' asParser negate) star flatten , $' asParser) - ==> [ :nodes | nodes second copyReplaceAll: '''''' with: '''' ]. - - self assert: parser parse: '''''' to: ''. - self assert: parser parse: '''a''' to: 'a'. - self assert: parser parse: '''ab''' to: 'ab'. - self assert: parser parse: '''a''''b''' to: 'a''b'. - self assert: parser parse: '''a''''''''b''' to: 'a''''b' -! - -testEvenNumber - "Create a grammar that parses an even number of a's and b's." - - | a as b bs s | - a := $a asParser ==> [ :char | as := as + 1 ]. - b := $b asParser ==> [ :char | bs := bs + 1 ]. - s := (a / b) star >=> [ :stream :cc | - as := bs := 0. - cc value. - (as even and: [ bs even ]) - ifFalse: [ PPFailure message: 'Even number of a and b expected' at: 0 ] ]. - - self assert: s fail: 'a' end: 1. - self assert: s fail: 'b' end: 1. - self assert: s fail: 'ab' end: 2. - self assert: s fail: 'ba' end: 2. - self assert: s fail: 'aaa' end: 3. - self assert: s fail: 'bbb' end: 3. - self assert: s fail: 'aab' end: 3. - self assert: s fail: 'abb' end: 3. - - self assert: s parse: ''. - self assert: s parse: 'aa'. - self assert: s parse: 'bb'. - self assert: s parse: 'aaaa'. - self assert: s parse: 'aabb'. - self assert: s parse: 'abab'. - self assert: s parse: 'baba'. - self assert: s parse: 'bbaa'. - self assert: s parse: 'bbbb' -! - -testIfThenElse - "S ::= if C then S else S | if C then S | X" - - | start if then else cond expr parser | - start := PPDelegateParser new. - if := 'if' asParser token trim. - then := 'then' asParser token trim. - else := 'else' asParser token trim. - cond := 'C' asParser token trim. - expr := 'X' asParser token trim. - start setParser: (if , cond , then , start , else , start) / (if , cond , then , start) / expr. - parser := start end. - self assert: parser parse: 'X'. - self assert: parser parse: 'if C then X'. - self assert: parser parse: 'if C then X else X'. - self assert: parser parse: 'if C then if C then X'. - self assert: parser parse: 'if C then if C then X else if C then X'. - self assert: parser parse: 'if C then if C then X else X else if C then X'. - self assert: parser parse: 'if C then if C then X else X else if C then X else X'. - self assert: parser fail: 'if C'. - self assert: parser fail: 'if C else X'. - self assert: parser fail: 'if C then if C' -! - -testLeftRecursion - "S ::= S 'x' S / '1'" - - | parser | - parser := PPDelegateParser new. - parser setParser: ((parser , $x asParser , parser) / $1 asParser) memoized flatten. - - self assert: parser parse: '1' to: '1'. - self assert: parser parse: '1x1' to: '1x1'. - self assert: parser parse: '1x1x1' to: '1x1x1'. - self assert: parser parse: '1x1x1x1' to: '1x1x1x1'. - self assert: parser parse: '1x1x1x1x1' to: '1x1x1x1x1'. - self assert: parser parse: '1x1x1x1x1x1' to: '1x1x1x1x1x1' -! - -testListOfIntegers - "S ::= S , number | number" - - | number list parser | - number := #digit asParser plus flatten trim - ==> [ :node | node asInteger ]. - list := (number separatedBy: $, asParser token trim) - ==> [ :node | node select: [ :each | each isInteger ] ]. - parser := list end. - - self assert: parser parse: '1' to: (1 to: 1) asArray. - self assert: parser parse: '1,2' to: (1 to: 2) asArray. - self assert: parser parse: '1,2,3' to: (1 to: 3) asArray. - self assert: parser parse: '1,2,3,4' to: (1 to: 4) asArray. - self assert: parser parse: '1,2,3,4,5' to: (1 to: 5) asArray. - - self assert: parser parse: '1' to: (1 to: 1) asArray. - self assert: parser parse: '1, 2' to: (1 to: 2) asArray. - self assert: parser parse: '1, 2, 3' to: (1 to: 3) asArray. - self assert: parser parse: '1, 2, 3, 4' to: (1 to: 4) asArray. - self assert: parser parse: '1, 2, 3, 4, 5' to: (1 to: 5) asArray. - - self assert: parser parse: '1' to: (1 to: 1) asArray. - self assert: parser parse: '1 ,2' to: (1 to: 2) asArray. - self assert: parser parse: '1 ,2 ,3' to: (1 to: 3) asArray. - self assert: parser parse: '1 ,2 ,3 ,4' to: (1 to: 4) asArray. - self assert: parser parse: '1 ,2 ,3 ,4 ,5' to: (1 to: 5) asArray. - - self assert: parser fail: ''. - self assert: parser fail: ','. - self assert: parser fail: '1,'. - self assert: parser fail: '1,,2' -! - -testNestedComments - "C ::= B I* E" - "I ::= !!E (C | T)" - "B ::= /*" - "E ::= */" - "T ::= ." - - | begin end any inside parser | - begin := '/*' asParser. - end := '*/' asParser. - any := #any asParser. - - parser := PPDelegateParser new. - inside := end not , (parser / any). - parser setParser: begin , inside star , end. - - self assert: parser parse: '/*ab*/cd' end: 6. - self assert: parser parse: '/*a/*b*/c*/'. - self assert: parser fail: '/*a/*b*/c' -! - -testPalindrome - "S0 ::= a S1 a | b S1 b | ... - S1 ::= S0 | epsilon" - - | s0 s1 parser | - s0 := PPDelegateParser new. - s1 := PPDelegateParser new. - s0 setParser: ($a asParser , s1 , $a asParser) - / ($b asParser , s1 , $b asParser) - / ($c asParser , s1 , $c asParser). - s1 setParser: s0 / nil asParser. - parser := s0 flatten end. - - self assert: parser parse: 'aa' to: 'aa'. - self assert: parser parse: 'bb' to: 'bb'. - self assert: parser parse: 'cc' to: 'cc'. - - self assert: parser parse: 'abba' to: 'abba'. - self assert: parser parse: 'baab' to: 'baab'. - - self assert: parser parse: 'abccba' to: 'abccba'. - self assert: parser parse: 'abaaba' to: 'abaaba'. - self assert: parser parse: 'cbaabc' to: 'cbaabc'. - - self assert: parser fail: 'a'. - self assert: parser fail: 'ab'. - self assert: parser fail: 'aab'. - self assert: parser fail: 'abccbb' -! - -testParseAaaBbb - "S0 ::= a S1 b - S1 ::= S0 | epsilon" - - | s0 s1 parser | - s0 := PPDelegateParser new. - s1 := PPDelegateParser new. - s0 setParser: $a asParser , s1 , $b asParser. - s1 setParser: s0 / nil asParser. - parser := s0 flatten. - - self assert: parser parse: 'ab' to: 'ab'. - self assert: parser parse: 'aabb' to: 'aabb'. - self assert: parser parse: 'aaabbb' to: 'aaabbb'. - self assert: parser parse: 'aaaabbbb' to: 'aaaabbbb'. - - self assert: parser parse: 'abb' to: 'ab' end: 2. - self assert: parser parse: 'aabbb' to: 'aabb' end: 4. - self assert: parser parse: 'aaabbbb' to: 'aaabbb' end: 6. - self assert: parser parse: 'aaaabbbbb' to: 'aaaabbbb' end: 8. - - self assert: parser fail: 'a'. - self assert: parser fail: 'b'. - self assert: parser fail: 'aab'. - self assert: parser fail: 'aaabb' -! - -testParseAaaaaa - "S ::= a a S | epsilon" - - | s0 s1 parser | - s0 := PPDelegateParser new. - s1 := $a asParser , $a asParser , s0. - s0 setParser: s1 / nil asParser. - parser := s0 flatten. - - self assert: parser parse: '' to: ''. - self assert: parser parse: 'aa' to: 'aa'. - self assert: parser parse: 'aaaa' to: 'aaaa'. - self assert: parser parse: 'aaaaaa' to: 'aaaaaa'. - - self assert: parser parse: 'a' to: '' end: 0. - self assert: parser parse: 'aaa' to: 'aa' end: 2. - self assert: parser parse: 'aaaaa' to: 'aaaa' end: 4. - self assert: parser parse: 'aaaaaaa' to: 'aaaaaa' end: 6 -! - -testParseAbAbAb - "S ::= (A B)+" - - | parser | - parser := ($a asParser , $b asParser) plus flatten. - - self assert: parser parse: 'ab' to: 'ab'. - self assert: parser parse: 'abab' to: 'abab'. - self assert: parser parse: 'ababab' to: 'ababab'. - self assert: parser parse: 'abababab' to: 'abababab'. - - self assert: parser parse: 'abb' to: 'ab' end: 2. - self assert: parser parse: 'ababa' to: 'abab' end: 4. - self assert: parser parse: 'abababb' to: 'ababab' end: 6. - self assert: parser parse: 'ababababa' to: 'abababab' end: 8. - - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser fail: 'bab' -! - -testParseAbabbb - "S ::= (A | B)+" - - | parser | - parser := ($a asParser / $b asParser) plus flatten. - - self assert: parser parse: 'a' to: 'a'. - self assert: parser parse: 'b' to: 'b'. - self assert: parser parse: 'ab' to: 'ab'. - self assert: parser parse: 'ba' to: 'ba'. - self assert: parser parse: 'aaa' to: 'aaa'. - self assert: parser parse: 'aab' to: 'aab'. - self assert: parser parse: 'aba' to: 'aba'. - self assert: parser parse: 'baa' to: 'baa'. - self assert: parser parse: 'abb' to: 'abb'. - self assert: parser parse: 'bab' to: 'bab'. - self assert: parser parse: 'bba' to: 'bba'. - self assert: parser parse: 'bbb' to: 'bbb'. - - self assert: parser parse: 'ac' to: 'a' end: 1. - self assert: parser parse: 'bc' to: 'b' end: 1. - self assert: parser parse: 'abc' to: 'ab' end: 2. - self assert: parser parse: 'bac' to: 'ba' end: 2. - - self assert: parser fail: ''. - self assert: parser fail: 'c' -! - -testParseAnBnCn - "PEGs for a non context- free language: - - a^n , b^n , c^n - - S <- &P1 P2 - P1 <- AB 'c' - AB <- 'a' AB 'b' / epsilon - P2 <- 'a'* BC end - BC <- 'b' BC 'c' / epsilon" - - | s p1 ab p2 bc | - s := PPDelegateParser new. - p1 := PPDelegateParser new. - ab := PPDelegateParser new. - p2 := PPDelegateParser new. - bc := PPDelegateParser new. - - s setParser: (p1 and , p2 end) flatten. - p1 setParser: ab , $c asParser. - ab setParser: ($a asParser , ab , $b asParser) optional. - p2 setParser: $a asParser star , bc. - bc setParser: ($b asParser , bc , $c asParser) optional. - - self assert: s parse: 'abc' to: 'abc'. - self assert: s parse: 'aabbcc' to: 'aabbcc'. - self assert: s parse: 'aaabbbccc' to: 'aaabbbccc'. - - self assert: s fail: 'bc'. - self assert: s fail: 'ac'. - self assert: s fail: 'ab'. - self assert: s fail: 'abbcc'. - self assert: s fail: 'aabcc'. - self assert: s fail: 'aabbc' -! ! - -!PPComposedTest methodsFor:'testing-examples'! - -testComment - self assert: self comment parse: '""' to: '""'. - self assert: self comment parse: '"a"' to: '"a"'. - self assert: self comment parse: '"ab"' to: '"ab"'. - self assert: self comment parse: '"abc"' to: '"abc"'. - - self assert: self comment parse: '""a' to: '""' end: 2. - self assert: self comment parse: '"a"a' to: '"a"' end: 3. - self assert: self comment parse: '"ab"a' to: '"ab"' end: 4. - self assert: self comment parse: '"abc"a' to: '"abc"' end: 5. - - self assert: self comment fail: '"'. - self assert: self comment fail: '"a'. - self assert: self comment fail: '"aa'. - self assert: self comment fail: 'a"'. - self assert: self comment fail: 'aa"' -! - -testIdentifier - self assert: self identifier parse: 'a' to: 'a'. - self assert: self identifier parse: 'a1' to: 'a1'. - self assert: self identifier parse: 'a12' to: 'a12'. - self assert: self identifier parse: 'ab' to: 'ab'. - self assert: self identifier parse: 'a1b' to: 'a1b'. - - self assert: self identifier parse: 'a_' to: 'a' end: 1. - self assert: self identifier parse: 'a1-' to: 'a1' end: 2. - self assert: self identifier parse: 'a12+' to: 'a12' end: 3. - self assert: self identifier parse: 'ab^' to: 'ab' end: 2. - self assert: self identifier parse: 'a1b*' to: 'a1b' end: 3. - - self assert: self identifier fail: ''. - self assert: self identifier fail: '1'. - self assert: self identifier fail: '1a' -! - -testNumber - self assert: self number parse: '1' to: '1'. - self assert: self number parse: '12' to: '12'. - self assert: self number parse: '12.3' to: '12.3'. - self assert: self number parse: '12.34' to: '12.34'. - - self assert: self number parse: '1..' to: '1' end: 1. - self assert: self number parse: '12-' to: '12' end: 2. - self assert: self number parse: '12.3.' to: '12.3' end: 4. - self assert: self number parse: '12.34.' to: '12.34' end: 5. - - self assert: self number parse: '-1' to: '-1'. - self assert: self number parse: '-12' to: '-12'. - self assert: self number parse: '-12.3' to: '-12.3'. - self assert: self number parse: '-12.34' to: '-12.34'. - - self assert: self number fail: ''. - self assert: self number fail: '-'. - self assert: self number fail: '.'. - self assert: self number fail: '.1' -! - -testReturn - | number spaces return | - number := #digit asParser plus flatten. - spaces := #space asParser star. - return := (spaces , $^ asParser token , spaces , number) - ==> [ :nodes | Array with: #return with: (nodes at: 4) ]. - - self assert: return parse: '^1' to: #(return '1'). - self assert: return parse: '^12' to: #(return '12'). - self assert: return parse: '^ 123' to: #(return '123'). - self assert: return parse: '^ 1234' to: #(return '1234'). - - self assert: return fail: '1'. - self assert: return fail: '^' -! ! - -!PPComposedTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPComposedTest.st,v 1.5 2014-03-04 14:34:10 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPComposedTest.st,v 1.5 2014-03-04 14:34:10 cg Exp $' -! - -version_SVN - ^ '$Id: PPComposedTest.st,v 1.5 2014-03-04 14:34:10 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPExpressionParserTest.st --- a/PPExpressionParserTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPArithmeticParserTest subclass:#PPExpressionParserTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPExpressionParserTest class methodsFor:'testing'! - -shouldInheritSelectors - ^ true -! ! - -!PPExpressionParserTest methodsFor:'accessing'! - -parserInstance - | expression parens number | - expression := PPExpressionParser new. - parens := $( asParser trim , expression , $) asParser trim - ==> [ :value | value second ]. - number := (#digit asParser plus , ($. asParser , #digit asParser plus) optional) flatten trim - ==> [ :value | value asNumber ]. - expression term: parens / number. - expression - group: [ :g | - g prefix: $- asParser trim do: [ :op :a | a negated ] ]; - group: [ :g | - g postfix: '++' asParser trim do: [ :a :op | a + 1 ]. - g postfix: '--' asParser trim do: [ :a :op | a - 1 ] ]; - group: [ :g | - g right: $^ asParser trim do: [ :a :op :b | a raisedTo: b ] ]; - group: [ :g | - g left: $* asParser trim do: [ :a :op :b | a * b ]. - g left: $/ asParser trim do: [ :a :op :b | a / b ] ]; - group: [ :g | - g left: $+ asParser trim do: [ :a :op :b | a + b ]. - g left: $- asParser trim do: [ :a :op :b | a - b ] ]. - ^ expression end -! ! - -!PPExpressionParserTest methodsFor:'testing'! - -testPostfixAdd - self assert: '0++' is: 1. - self assert: '0++++' is: 2. - self assert: '0++++++' is: 3. - - self assert: '0+++1' is: 2. - self assert: '0+++++1' is: 3. - self assert: '0+++++++1' is: 4 -! - -testPostfixSub - self assert: '1--' is: 0. - self assert: '2----' is: 0. - self assert: '3------' is: 0. - - self assert: '2---1' is: 0. - self assert: '3-----1' is: 0. - self assert: '4-------1' is: 0. -! - -testPrefixNegate - self assert: '1' is: 1. - self assert: '-1' is: -1. - self assert: '--1' is: 1. - self assert: '---1' is: -1 -! ! - -!PPExpressionParserTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPExpressionParserTest.st,v 1.4 2014-03-04 14:34:13 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPExpressionParserTest.st,v 1.4 2014-03-04 14:34:13 cg Exp $' -! - -version_SVN - ^ '$Id: PPExpressionParserTest.st,v 1.4 2014-03-04 14:34:13 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPExtensionTest.st --- a/PPExtensionTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPAbstractParserTest subclass:#PPExtensionTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPExtensionTest methodsFor:'testing-parser'! - -testCharacter - | parser | - parser := $a asParser. - self assert: parser parse: 'a' to: $a. - self assert: parser fail: 'b' -! - -testChoice - | parser | - parser := #(1 2) asChoiceParser. - self assert: parser parse: #(1) to: 1. - self assert: parser parse: #(2) to: 2. - self assert: parser parse: #(1 2) to: 1 end: 1. - self assert: parser parse: #(2 1) to: 2 end: 1. - self assert: parser fail: #(). - self assert: parser fail: #(3) -! - -testClosure - | parser | - parser := [ :stream | stream upTo: $s ] asParser. - self assert: parser parse: '' to: ''. - self assert: parser parse: 'a' to: 'a'. - self assert: parser parse: 'aa' to: 'aa'. - self assert: parser parse: 's' to: ''. - self assert: parser parse: 'as' to: 'a'. - self assert: parser parse: 'aas' to: 'aa'. - self assert: parser parse: 'sa' to: '' end: 1. - self assert: parser parse: 'saa' to: '' end: 1. - - parser := [ :stream | stream upTo: $s. PPFailure message: 'stream' at: stream position ] asParser. - self assert: parser fail: ''. - self assert: parser fail: 's'. - self assert: parser fail: 'as' - -! - -testEpsilon - | parser | - parser := nil asParser. - self assert: parser asParser = parser -! - -testOrdered - | parser | - parser := #(1 2) asParser. - self assert: parser parse: #(1 2) to: #(1 2). - self assert: parser parse: #(1 2 3) to: #(1 2) end: 2. - self assert: parser fail: #(). - self assert: parser fail: #(1). - self assert: parser fail: #(1 1). - self assert: parser fail: #(1 1 2) -! - -testParser - | parser | - parser := $a asParser. - self assert: parser asParser = parser -! - -testRange - | parser | - parser := ($a to: $c) asParser. - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'b' to: $b. - self assert: parser parse: 'c' to: $c. - self assert: parser fail: 'd' -! - -testSequence - | parser | - parser := #(1 2) asSequenceParser. - self assert: parser parse: #(1 2) to: #(1 2). - self assert: parser parse: #(1 2 3) to: #(1 2) end: 2. - self assert: parser fail: #(). - self assert: parser fail: #(1). - self assert: parser fail: #(1 1). - self assert: parser fail: #(1 1 2) -! - -testString - | parser | - parser := 'ab' asParser. - self assert: parser parse: 'ab' to: 'ab'. - self assert: parser parse: 'aba' to: 'ab' end: 2. - self assert: parser parse: 'abb' to: 'ab' end: 2. - self assert: parser fail: 'a'. - self assert: parser fail: 'ac' -! - -testSymbol - | parser | - parser := #any asParser. - self assert: parser parse: 'a'. - self assert: parser fail: '' -! - -testUnordered - | parser | - parser := #(1 2) asSet asParser. - self assert: parser parse: #(1) to: 1. - self assert: parser parse: #(2) to: 2. - self assert: parser parse: #(1 2) to: 1 end: 1. - self assert: parser parse: #(2 1) to: 2 end: 1. - self assert: parser fail: #(). - self assert: parser fail: #(3) -! ! - -!PPExtensionTest methodsFor:'testing-stream'! - -testStream - | stream | - stream := 'abc' readStream asPetitStream. - self assert: (stream class = PPStream). - self assert: (stream printString = '·abc'). - self assert: (stream peek) = $a. - self assert: (stream uncheckedPeek = $a). - self assert: (stream next) = $a. - self assert: (stream printString = 'a·bc'). - self assert: (stream asPetitStream = stream) -! - -testText - | stream | - stream := 'abc' asText asPetitStream. - self assert: stream class = PPStream -! ! - -!PPExtensionTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPExtensionTest.st,v 1.4 2014-03-04 14:34:17 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPExtensionTest.st,v 1.4 2014-03-04 14:34:17 cg Exp $' -! - -version_SVN - ^ '$Id: PPExtensionTest.st,v 1.4 2014-03-04 14:34:17 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPLambdaParser.st --- a/PPLambdaParser.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPCompositeParser subclass:#PPLambdaParser - instanceVariableNames:'expression abstraction application variable' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Examples' -! - - -!PPLambdaParser class methodsFor:'curch-booleans'! - -and - ^ self parse: '\p.\q.((p q) p)' -! - -false - ^ self parse: '\x.\y.y' -! - -ifthenelse - ^ self parse: '\p.p' -! - -not - ^ self parse: '\p.\a.\b.((p b) a)' -! - -or - ^ self parse: '\p.\q.((p p) q)' -! - -true - ^ self parse: '\x.\y.x' -! ! - -!PPLambdaParser methodsFor:'accessing'! - -start - ^ expression end -! ! - -!PPLambdaParser methodsFor:'productions'! - -abstraction - ^ $\ asParser trim , variable , $. asParser trim , expression ==> [ :node | Array with: node second with: node fourth ] -! - -application - ^ $( asParser trim , expression , expression , $) asParser trim ==> [ :node | Array with: node second with: node third ] -! - -expression - ^ variable / abstraction / application -! - -variable - ^ (#letter asParser , #word asParser star) flatten trim -! ! - -!PPLambdaParser class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPLambdaParser.st,v 1.4 2014-03-04 14:34:00 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPLambdaParser.st,v 1.4 2014-03-04 14:34:00 cg Exp $' -! - -version_SVN - ^ '$Id: PPLambdaParser.st,v 1.4 2014-03-04 14:34:00 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPLambdaParserTest.st --- a/PPLambdaParserTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPCompositeParserTest subclass:#PPLambdaParserTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPLambdaParserTest methodsFor:'accessing'! - -parserClass - ^ PPLambdaParser -! ! - -!PPLambdaParserTest methodsFor:'testing'! - -testAbstraction - self assert: '\x.y' is: #('x' 'y'). - self assert: '\x.\y.z' is: #('x' ('y' 'z')) -! - -testApplication - self assert: '(x x)' is: #('x' 'x'). - self assert: '(x y)' is: #('x' 'y'). - self assert: '((x y) z)' is: #(('x' 'y') 'z'). - self assert: '(x (y z))' is: #('x' ('y' 'z')) -! - -testVariable - self assert: 'x' is: 'x'. - self assert: 'xy' is: 'xy'. - self assert: 'x12' is: 'x12' -! ! - -!PPLambdaParserTest methodsFor:'testing-curch'! - -testAnd - self assert: self parserClass and = #('p' ('q' (('p' 'q') 'p'))) -! - -testFalse - self assert: self parserClass false = #('x' ('y' 'y')) -! - -testIfThenElse - self assert: self parserClass ifthenelse = #('p' 'p') -! - -testNot - self assert: self parserClass not = #('p' ('a' ('b' (('p' 'b') 'a')))) -! - -testOr - self assert: self parserClass or = #('p' ('q' (('p' 'p') 'q'))) -! - -testTrue - self assert: self parserClass true = #('x' ('y' 'x')) -! ! - -!PPLambdaParserTest methodsFor:'testing-utilities'! - -testParseOnError - | beenHere | - result := self parserClass - parse: '\x.y' - onError: [ self fail ]. - self assert: result = #('x' 'y'). - - beenHere := false. - result := self parserClass - parse: '\x.' - onError: [ beenHere := true ]. - self assert: beenHere. - - beenHere := false. - result := self parserClass - parse: '\x.' - onError: [ :fail | beenHere := true. fail ]. - self assert: beenHere. - self assert: (result message findString: '$(') > 0. - self assert: (result message findString: 'expected') > 0. - self assert: (result position = 0). - - beenHere := false. - result := self parserClass - parse: '\x.' - onError: [ :msg :pos | - self assert: (msg findString: '$(') > 0. - self assert: (msg findString: 'expected') > 0. - self assert: (pos = 0). - beenHere := true ]. - self assert: result. - self assert: beenHere -! - -testParseStartingAtOnError - | beenHere | - result := self parserClass - parse: 'x' - startingAt: #variable - onError: [ self fail ]. - self assert: result = 'x'. - - beenHere := false. - result := self parserClass - parse: '\' - startingAt: #variable - onError: [ beenHere := true ]. - self assert: beenHere. - - beenHere := false. - result := self parserClass - parse: '\' - startingAt: #variable - onError: [ :fail | beenHere := true. fail ]. - self assert: beenHere. - self assert: result message = 'letter expected'. - self assert: result position = 0. - - beenHere := false. - result := self parserClass - parse: '\' - startingAt: #variable - onError: [ :msg :pos | - self assert: msg = 'letter expected'. - self assert: pos = 0. - beenHere := true ]. - self assert: beenHere -! - -testProductionAt - self assert: (parser productionAt: #foo) isNil. - self assert: (parser productionAt: #foo ifAbsent: [ true ]). - - self assert: (parser productionAt: #start) notNil. - self assert: (parser productionAt: #start ifAbsent: [ true ]) notNil. - - self assert: (parser productionAt: #variable) notNil. - self assert: (parser productionAt: #variable ifAbsent: [ true ]) notNil -! ! - -!PPLambdaParserTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPLambdaParserTest.st,v 1.4 2014-03-04 14:34:18 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPLambdaParserTest.st,v 1.4 2014-03-04 14:34:18 cg Exp $' -! - -version_SVN - ^ '$Id: PPLambdaParserTest.st,v 1.4 2014-03-04 14:34:18 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPMappingTest.st --- a/PPMappingTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPAbstractParseTest subclass:#PPMappingTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPMappingTest methodsFor:'testing'! - -testFoldLeft2 - | parser | - parser := #any asParser star - foldLeft: [ :a :b | Array with: a with: b ]. - - self assert: parser parse: #(a) to: #a. - self assert: parser parse: #(a b) to: #(a b). - self assert: parser parse: #(a b c) to: #((a b) c). - self assert: parser parse: #(a b c d) to: #(((a b) c) d). - self assert: parser parse: #(a b c d e) to: #((((a b) c) d) e) -! - -testFoldLeft3 - | parser | - parser := #any asParser star - foldLeft: [ :a :b :c | Array with: a with: b with: c ]. - - self assert: parser parse: #(a) to: #a. - self assert: parser parse: #(a b c) to: #(a b c). - self assert: parser parse: #(a b c d e) to: #((a b c) d e) -! - -testFoldRight2 - | parser | - parser := #any asParser star - foldRight: [ :a :b | Array with: a with: b ]. - - self assert: parser parse: #(a) to: #a. - self assert: parser parse: #(a b) to: #(a b). - self assert: parser parse: #(a b c) to: #(a (b c)). - self assert: parser parse: #(a b c d) to: #(a (b (c d))). - self assert: parser parse: #(a b c d e) to: #(a (b (c (d e)))) -! - -testFoldRight3 - | parser | - parser := #any asParser star - foldRight: [ :a :b :c | Array with: a with: b with: c ]. - - self assert: parser parse: #(a) to: #a. - self assert: parser parse: #(a b c) to: #(a b c). - self assert: parser parse: #(a b c d e) to: #(a b (c d e)) -! - -testMap1 - | parser | - parser := #any asParser - map: [ :a | Array with: a ]. - - self assert: parser parse: #(a) to: #(a) -! - -testMap2 - | parser | - parser := (#any asParser , #any asParser) - map: [ :a :b | Array with: b with: a ]. - - self assert: parser parse: #(a b) to: #(b a) -! - -testMap3 - | parser | - parser := (#any asParser , #any asParser , #any asParser) - map: [ :a :b :c | Array with: c with: b with: a ]. - - self assert: parser parse: #(a b c) to: #(c b a) -! ! - -!PPMappingTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPMappingTest.st,v 1.3 2012-05-04 22:03:40 vrany Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPMappingTest.st,v 1.3 2012-05-04 22:03:40 vrany Exp $' -! - -version_SVN - ^ '§Id: PPMappingTest.st 4 2010-12-18 17:02:23Z kursjan §' -! ! diff -r 1ba87229ee7e -r e2b2f08d054e PPObjectTest.st --- a/PPObjectTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPAbstractParserTest subclass:#PPObjectTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPObjectTest methodsFor:'parsers'! - -integer - ^ PPPredicateObjectParser - on: [ :each | each isInteger ] - message: 'integer expected' -! - -string - ^ PPPredicateObjectParser - on: [ :each | each isString ] - message: 'string expected' -! ! - -!PPObjectTest methodsFor:'testing'! - -testInteger - self assert: self integer parse: #(123) to: 123. - self assert: self integer fail: #('abc') -! - -testString - self assert: self string parse: #('abc') to: 'abc'. - self assert: self string fail: #(123) -! ! - -!PPObjectTest methodsFor:'testing-fancy'! - -testFibonacci - "This parser accepts fibonacci sequences with arbitrary start pairs." - - | parser | - parser := ((self integer , self integer) end ==> [ :pair | pair first + pair last ]) - / (self integer , (self integer , self integer) and >=> [ :stream :continuation | - | result | - result := continuation value. - (result isPetitFailure or: [ result first + result last first ~= result last last ]) - ifFalse: [ parser parseOn: stream ] - ifTrue: [ PPFailure message: 'invalid fibonacci sequence' at: stream position ] ]). - self assert: parser parse: #(1 1) to: 2. - self assert: parser parse: #(1 1 2) to: 3. - self assert: parser parse: #(1 1 2 3) to: 5. - self assert: parser parse: #(1 1 2 3 5) to: 8. - self assert: parser parse: #(1 1 2 3 5 8) to: 13. - self assert: parser parse: #(1 1 2 3 5 8 13) to: 21. - self assert: parser fail: #(). - self assert: parser fail: #(1). - self assert: parser fail: #(1 2 3 4) end: 2 - -! ! - -!PPObjectTest methodsFor:'testing-operators'! - -testChoice - | parser | - parser := self integer / self string. - self assert: parser parse: #(123) to: 123. - self assert: parser parse: #('abc') to: 'abc' -! - -testSequence - | parser | - parser := self integer , self string. - self assert: parser parse: #(123 'abc') to: #(123 'abc'). - self assert: parser fail: #(123 456). - self assert: parser fail: #('abc' 'def'). - self assert: parser fail: #('abc' 123) - -! ! - -!PPObjectTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPObjectTest.st,v 1.4 2014-03-04 14:34:19 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPObjectTest.st,v 1.4 2014-03-04 14:34:19 cg Exp $' -! - -version_SVN - ^ '$Id: PPObjectTest.st,v 1.4 2014-03-04 14:34:19 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPParserResource.st --- a/PPParserResource.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -TestResource subclass:#PPParserResource - instanceVariableNames:'parsers' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Core' -! - - -!PPParserResource methodsFor:'accessing'! - -parserAt: aParserClass - "Answer a cached instance of aParserClass." - - ^ parsers at: aParserClass name ifAbsentPut: [ aParserClass new ] -! ! - -!PPParserResource methodsFor:'running'! - -setUp - super setUp. - parsers := Dictionary new -! ! - -!PPParserResource class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParserResource.st,v 1.3 2012-05-04 22:09:18 vrany Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParserResource.st,v 1.3 2012-05-04 22:09:18 vrany Exp $' -! - -version_SVN - ^ '§Id: PPParserResource.st 4 2010-12-18 17:02:23Z kursjan §' -! ! diff -r 1ba87229ee7e -r e2b2f08d054e PPParserTest.st --- a/PPParserTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1372 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPAbstractParserTest subclass:#PPParserTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPParserTest methodsFor:'testing'! - -testAnd - | parser | - parser := 'foo' asParser flatten , 'bar' asParser flatten and. - - self assert: parser parse: 'foobar' to: #('foo' 'bar') end: 3. - self assert: parser fail: 'foobaz'. - - parser := 'foo' asParser and. - self assert: parser and = parser -! - -testBlock - | parser | - parser := [ :s | s next ] asParser. - - self assert: parser parse: 'ab' to: $a end: 1. - self assert: parser parse: 'b' to: $b. - self assert: parser parse: '' to: nil -! - -testChoice - | parser | - parser := $a asParser / $b asParser. - - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'b' to: $b. - - self assert: parser parse: 'ab' to: $a end: 1. - self assert: parser parse: 'ba' to: $b end: 1. - - self assert: parser fail: ''. - self assert: parser fail: 'c'. - self assert: parser fail: 'ca' -! - -testDelimitedBy - | parser | - parser := $a asParser delimitedBy: $b asParser. - - self assert: parser parse: 'a' to: #($a). - self assert: parser parse: 'aba' to: #($a $b $a). - self assert: parser parse: 'ababa' to: #($a $b $a $b $a). - - self assert: parser parse: 'ab' to: #($a $b). - self assert: parser parse: 'abab' to: #($a $b $a $b). - self assert: parser parse: 'ababab' to: #($a $b $a $b $a $b). - - self assert: parser parse: 'ac' to: #($a) end: 1. - self assert: parser parse: 'abc' to: #($a $b) end: 2. - self assert: parser parse: 'abac' to: #($a $b $a) end: 3. - self assert: parser parse: 'ababc' to: #($a $b $a $b) end: 4. - - self assert: parser fail: ''. - self assert: parser fail: 'b'. - self assert: parser fail: 'c' -! - -testDelimitedByWithoutSeparators - | parser | - parser := ($a asParser delimitedBy: $b asParser) - withoutSeparators. - - self assert: parser parse: 'a' to: #($a). - self assert: parser parse: 'aba' to: #($a $a). - self assert: parser parse: 'ababa' to: #($a $a $a). - - self assert: parser parse: 'ab' to: #($a). - self assert: parser parse: 'abab' to: #($a $a). - self assert: parser parse: 'ababab' to: #($a $a $a). - - self assert: parser parse: 'ac' to: #($a) end: 1. - self assert: parser parse: 'abc' to: #($a) end: 2. - self assert: parser parse: 'abac' to: #($a $a) end: 3. - self assert: parser parse: 'ababc' to: #($a $a) end: 4. - - self assert: parser fail: ''. - self assert: parser fail: 'b'. - self assert: parser fail: 'c' -! - -testEndOfInput - | parser | - parser := PPEndOfInputParser on: $a asParser. - self assert: parser end = parser. - - self assert: parser parse: 'a' to: $a. - self assert: parser fail: ''. - self assert: parser fail: 'aa' -! - -testEndOfInputAfterMatch - | parser | - parser := 'stuff' asParser end. - self assert: parser parse: 'stuff' to: 'stuff'. - self assert: parser fail: 'stufff'. - self assert: parser fail: 'fluff' -! - -testEpsilon - | parser | - parser := nil asParser. - - self assert: parser parse: '' to: nil. - - self assert: parser parse: 'a' to: nil end: 0. - self assert: parser parse: 'ab' to: nil end: 0 -! - -testFailing - | parser result | - parser := PPFailingParser message: 'Plonk'. - self assert: parser message = 'Plonk'. - - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser fail: 'aa'. - - result := parser parse: 'a'. - self assert: result message = 'Plonk'. - self assert: result printString = 'Plonk at 0' -! - -testLiteralObject - | parser | - parser := PPLiteralObjectParser - on: $a - message: 'letter "a" expected'. - self assert: parser literal = $a. - self assert: parser message = 'letter "a" expected'. - - self assert: parser parse: 'a' to: $a. - self assert: parser fail: 'b' - -! - -testLiteralObjectCaseInsensitive - | parser | - parser := $a asParser caseInsensitive. - - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'A' to: $A. - - self assert: parser fail: ''. - self assert: parser fail: 'b'. - self assert: parser fail: 'B' - -! - -testLiteralSequence - | parser | - parser := PPLiteralSequenceParser - on: 'abc' - message: 'sequence "abc" expected'. - self assert: parser size = 3. - self assert: parser literal = 'abc'. - self assert: parser message = 'sequence "abc" expected'. - - self assert: parser parse: 'abc' to: 'abc'. - self assert: parser fail: 'ab'. - self assert: parser fail: 'abd' -! - -testLiteralSequenceCaseInsensitive - | parser | - parser := 'abc' asParser caseInsensitive. - - self assert: parser parse: 'abc' to: 'abc'. - self assert: parser parse: 'ABC' to: 'ABC'. - self assert: parser parse: 'abC' to: 'abC'. - self assert: parser parse: 'AbC' to: 'AbC'. - - self assert: parser fail: 'ab'. - self assert: parser fail: 'abd' -! - -testMax - | parser | - parser := $a asParser max: 2. - self assert: parser min = 0. - self assert: parser max = 2. - - self assert: parser parse: '' to: #(). - self assert: parser parse: 'a' to: #($a). - self assert: parser parse: 'aa' to: #($a $a). - self assert: parser parse: 'aaa' to: #($a $a) end: 2. - self assert: parser parse: 'aaaa' to: #($a $a) end: 2. - - self assert: (parser printString endsWith: '[0, 2]') -! - -testMaxGreedy - | parser | - parser := #word asParser max: 2 greedy: #digit asParser. - - self assert: parser fail: ''. - self assert: parser fail: 'abc'. - - self assert: parser parse: '1' to: #() end: 0. - self assert: parser parse: 'a1' to: #($a) end: 1. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser fail: 'abc1'. - - self assert: parser parse: '12' to: #($1) end: 1. - self assert: parser parse: 'a12' to: #($a $1) end: 2. - self assert: parser parse: 'ab12' to: #($a $b) end: 2. - self assert: parser fail: 'abc12'. - - self assert: parser parse: '123' to: #($1 $2) end: 2. - self assert: parser parse: 'a123' to: #($a $1) end: 2. - self assert: parser parse: 'ab123' to: #($a $b) end: 2. - self assert: parser fail: 'abc123' -! - -testMaxLazy - | parser | - parser := #word asParser max: 2 lazy: #digit asParser. - - self assert: parser fail: ''. - self assert: parser fail: 'abc'. - - self assert: parser parse: '1' to: #() end: 0. - self assert: parser parse: 'a1' to: #($a) end: 1. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser fail: 'abc1'. - - self assert: parser parse: '12' to: #() end: 0. - self assert: parser parse: 'a12' to: #($a) end: 1. - self assert: parser parse: 'ab12' to: #($a $b) end: 2. - self assert: parser fail: 'abc12'. - - self assert: parser parse: '123' to: #() end: 0. - self assert: parser parse: 'a123' to: #($a) end: 1. - self assert: parser parse: 'ab123' to: #($a $b) end: 2. - self assert: parser fail: 'abc123' -! - -testMemoized - | count parser twice | - count := 0. - parser := [ :s | count := count + 1. s next ] asParser memoized. - twice := parser and , parser. - - count := 0. - self assert: parser parse: 'a' to: $a. - self assert: count = 1. - - count := 0. - self assert: twice parse: 'a' to: #($a $a). - self assert: count = 1. - - self assert: parser memoized = parser -! - -testMin - | parser | - parser := $a asParser min: 2. - self assert: parser min = 2. - self assert: parser max > parser min. - - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser parse: 'aa' to: #($a $a). - self assert: parser parse: 'aaa' to: #($a $a $a). - self assert: parser parse: 'aaaa' to: #($a $a $a $a). - - self assert: (parser printString endsWith: '[2, *]') -! - -testMinGreedy - | parser | - parser := #word asParser min: 2 greedy: #digit asParser. - - self assert: parser fail: ''. - self assert: parser fail: 'abcde'. - - self assert: parser fail: '1'. - self assert: parser fail: 'a1'. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd1' to: #($a $b $c $d) end: 4. - self assert: parser parse: 'abcde1' to: #($a $b $c $d $e) end: 5. - - self assert: parser fail: '12'. - self assert: parser parse: 'a12' to: #($a $1) end: 2. - self assert: parser parse: 'ab12' to: #($a $b $1) end: 3. - self assert: parser parse: 'abc12' to: #($a $b $c $1) end: 4. - self assert: parser parse: 'abcd12' to: #($a $b $c $d $1) end: 5. - self assert: parser parse: 'abcde12' to: #($a $b $c $d $e $1) end: 6. - - self assert: parser parse: '123' to: #($1 $2) end: 2. - self assert: parser parse: 'a123' to: #($a $1 $2) end: 3. - self assert: parser parse: 'ab123' to: #($a $b $1 $2) end: 4. - self assert: parser parse: 'abc123' to: #($a $b $c $1 $2) end: 5. - self assert: parser parse: 'abcd123' to: #($a $b $c $d $1 $2) end: 6. - self assert: parser parse: 'abcde123' to: #($a $b $c $d $e $1 $2) end: 7. - - self assert: parser parse: '1234' to: #($1 $2 $3) end: 3. - self assert: parser parse: 'a1234' to: #($a $1 $2 $3) end: 4. - self assert: parser parse: 'ab1234' to: #($a $b $1 $2 $3) end: 5. - self assert: parser parse: 'abc1234' to: #($a $b $c $1 $2 $3) end: 6. - self assert: parser parse: 'abcd1234' to: #($a $b $c $d $1 $2 $3) end: 7. - self assert: parser parse: 'abcde1234' to: #($a $b $c $d $e $1 $2 $3) end: 8 -! - -testMinLazy - | parser | - parser := #word asParser min: 2 lazy: #digit asParser. - - self assert: parser fail: ''. - self assert: parser fail: 'abcde'. - - self assert: parser fail: '1'. - self assert: parser fail: 'a1'. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd1' to: #($a $b $c $d) end: 4. - self assert: parser parse: 'abcde1' to: #($a $b $c $d $e) end: 5. - - self assert: parser fail: '12'. - self assert: parser parse: 'a12' to: #($a $1) end: 2. - self assert: parser parse: 'ab12' to: #($a $b) end: 2. - self assert: parser parse: 'abc12' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd12' to: #($a $b $c $d) end: 4. - self assert: parser parse: 'abcde12' to: #($a $b $c $d $e) end: 5. - - self assert: parser parse: '123' to: #($1 $2) end: 2. - self assert: parser parse: 'a123' to: #($a $1) end: 2. - self assert: parser parse: 'ab123' to: #($a $b) end: 2. - self assert: parser parse: 'abc123' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd123' to: #($a $b $c $d) end: 4. - self assert: parser parse: 'abcde123' to: #($a $b $c $d $e) end: 5. - - self assert: parser parse: '1234' to: #($1 $2) end: 2. - self assert: parser parse: 'a1234' to: #($a $1) end: 2. - self assert: parser parse: 'ab1234' to: #($a $b) end: 2. - self assert: parser parse: 'abc1234' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd1234' to: #($a $b $c $d) end: 4. - self assert: parser parse: 'abcde1234' to: #($a $b $c $d $e) end: 5 -! - -testMinMax - | parser | - parser := $a asParser min: 2 max: 4. - self assert: parser min = 2. - self assert: parser max = 4. - - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser parse: 'aa' to: #($a $a). - self assert: parser parse: 'aaa' to: #($a $a $a). - self assert: parser parse: 'aaaa' to: #($a $a $a $a). - self assert: parser parse: 'aaaaa' to: #($a $a $a $a) end: 4. - self assert: parser parse: 'aaaaaa' to: #($a $a $a $a) end: 4. - - self assert: (parser printString endsWith: '[2, 4]') -! - -testMinMaxGreedy - | parser | - parser := #word asParser min: 2 max: 4 greedy: #digit asParser. - - self assert: parser fail: ''. - self assert: parser fail: 'abcde'. - - self assert: parser fail: '1'. - self assert: parser fail: 'a1'. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd1' to: #($a $b $c $d) end: 4. - self assert: parser fail: 'abcde1'. - - self assert: parser fail: '12'. - self assert: parser parse: 'a12' to: #($a $1) end: 2. - self assert: parser parse: 'ab12' to: #($a $b $1) end: 3. - self assert: parser parse: 'abc12' to: #($a $b $c $1) end: 4. - self assert: parser parse: 'abcd12' to: #($a $b $c $d) end: 4. - self assert: parser fail: 'abcde12'. - - self assert: parser parse: '123' to: #($1 $2) end: 2. - self assert: parser parse: 'a123' to: #($a $1 $2) end: 3. - self assert: parser parse: 'ab123' to: #($a $b $1 $2) end: 4. - self assert: parser parse: 'abc123' to: #($a $b $c $1) end: 4. - self assert: parser parse: 'abcd123' to: #($a $b $c $d) end: 4. - self assert: parser fail: 'abcde123'. - - self assert: parser parse: '1234' to: #($1 $2 $3) end: 3. - self assert: parser parse: 'a1234' to: #($a $1 $2 $3) end: 4. - self assert: parser parse: 'ab1234' to: #($a $b $1 $2) end: 4. - self assert: parser parse: 'abc1234' to: #($a $b $c $1) end: 4. - self assert: parser parse: 'abcd1234' to: #($a $b $c $d) end: 4. - self assert: parser fail: 'abcde1234' -! - -testMinMaxLazy - | parser | - parser := #word asParser min: 2 max: 4 lazy: #digit asParser. - - self assert: parser fail: ''. - self assert: parser fail: 'abcde'. - - self assert: parser fail: '1'. - self assert: parser fail: 'a1'. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd1' to: #($a $b $c $d) end: 4. - self assert: parser fail: 'abcde1'. - - self assert: parser fail: '12'. - self assert: parser parse: 'a12' to: #($a $1) end: 2. - self assert: parser parse: 'ab12' to: #($a $b) end: 2. - self assert: parser parse: 'abc12' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd12' to: #($a $b $c $d) end: 4. - self assert: parser fail: 'abcde12'. - - self assert: parser parse: '123' to: #($1 $2) end: 2. - self assert: parser parse: 'a123' to: #($a $1) end: 2. - self assert: parser parse: 'ab123' to: #($a $b) end: 2. - self assert: parser parse: 'abc123' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd123' to: #($a $b $c $d) end: 4. - self assert: parser fail: 'abcde123'. - - self assert: parser parse: '1234' to: #($1 $2) end: 2. - self assert: parser parse: 'a1234' to: #($a $1) end: 2. - self assert: parser parse: 'ab1234' to: #($a $b) end: 2. - self assert: parser parse: 'abc1234' to: #($a $b $c) end: 3. - self assert: parser parse: 'abcd1234' to: #($a $b $c $d) end: 4. - self assert: parser fail: 'abcde1234' -! - -testNegate - | parser | - parser := 'foo' asParser negate. - - self assert: parser parse: 'f' to: $f end: 1. - self assert: parser parse: 'fo' to: $f end: 1. - self assert: parser parse: 'fob' to: $f end: 1. - self assert: parser parse: 'ffoo' to: $f end: 1. - - self assert: parser fail: ''. - self assert: parser fail: 'foo' -! - -testNot - | parser | - parser := 'foo' asParser flatten , 'bar' asParser flatten not. - - self assert: parser parse: 'foobaz' to: #('foo' nil) end: 3. - self assert: parser fail: 'foobar' -! - -testOptional - | parser | - parser := $a asParser optional. - - self assert: parser parse: '' to: nil. - self assert: parser parse: 'a' to: $a. - - self assert: parser parse: 'aa' to: $a end: 1. - self assert: parser parse: 'ab' to: $a end: 1. - self assert: parser parse: 'b' to: nil end: 0. - self assert: parser parse: 'bb' to: nil end: 0. - self assert: parser parse: 'ba' to: nil end: 0 -! - -testPluggable - | block parser | - block := [ :stream | stream position ]. - parser := block asParser. - self assert: parser block = block -! - -testPlus - | parser | - parser := $a asParser plus. - - self assert: parser min = 1. - self assert: parser max > parser min. - - self assert: parser parse: 'a' to: #($a). - self assert: parser parse: 'aa' to: #($a $a). - self assert: parser parse: 'aaa' to: #($a $a $a). - - self assert: parser parse: 'ab' to: #($a) end: 1. - self assert: parser parse: 'aab' to: #($a $a) end: 2. - self assert: parser parse: 'aaab' to: #($a $a $a) end: 3. - - self assert: parser fail: ''. - self assert: parser fail: 'b'. - self assert: parser fail: 'ba' -! - -testPlusGreedy - | limit parser | - limit := #digit asParser. - parser := #word asParser plusGreedy: limit. - - self assert: parser min = 1. - self assert: parser max > parser min. - self assert: parser limit = limit. - self assert: parser children size = 2. - self assert: parser children last = limit. - - self assert: parser fail: ''. - self assert: parser fail: '1'. - self assert: parser fail: 'a'. - self assert: parser fail: 'ab'. - - self assert: parser parse: 'a1' to: #($a) end: 1. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. - self assert: parser parse: 'a12' to: #($a $1) end: 2. - self assert: parser parse: 'ab12' to: #($a $b $1) end: 3. - self assert: parser parse: 'abc12' to: #($a $b $c $1) end: 4. - self assert: parser parse: 'a123' to: #($a $1 $2) end: 3. - self assert: parser parse: 'ab123' to: #($a $b $1 $2) end: 4. - self assert: parser parse: 'abc123' to: #($a $b $c $1 $2) end: 5. -! - -testPlusLazy - | limit parser | - limit := #digit asParser. - parser := #word asParser plusLazy: limit. - - self assert: parser min = 1. - self assert: parser max > parser min. - self assert: parser limit = limit. - self assert: parser children size = 2. - self assert: parser children last = limit. - - self assert: parser fail: ''. - self assert: parser fail: '1'. - self assert: parser fail: 'a'. - self assert: parser fail: 'ab'. - - self assert: parser parse: 'a1' to: #($a) end: 1. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. - self assert: parser parse: 'a12' to: #($a) end: 1. - self assert: parser parse: 'ab12' to: #($a $b) end: 2. - self assert: parser parse: 'abc12' to: #($a $b $c) end: 3. - self assert: parser parse: 'a123' to: #($a) end: 1. - self assert: parser parse: 'ab123' to: #($a $b) end: 2. - self assert: parser parse: 'abc123' to: #($a $b $c) end: 3 -! - -testSeparatedBy - | parser | - parser := $a asParser separatedBy: $b asParser. - - self assert: parser parse: 'a' to: #($a). - self assert: parser parse: 'aba' to: #($a $b $a). - self assert: parser parse: 'ababa' to: #($a $b $a $b $a). - - self assert: parser parse: 'ab' to: #($a) end: 1. - self assert: parser parse: 'abab' to: #($a $b $a) end: 3. - self assert: parser parse: 'ac' to: #($a) end: 1. - self assert: parser parse: 'abac' to: #($a $b $a) end: 3. - - self assert: parser fail: ''. - self assert: parser fail: 'c' -! - -testSeparatedByWithoutSeparators - | parser | - parser := ($a asParser separatedBy: $b asParser) - withoutSeparators. - - self assert: parser parse: 'a' to: #($a). - self assert: parser parse: 'aba' to: #($a $a). - self assert: parser parse: 'ababa' to: #($a $a $a). - - self assert: parser parse: 'ab' to: #($a) end: 1. - self assert: parser parse: 'abab' to: #($a $a) end: 3. - self assert: parser parse: 'ac' to: #($a) end: 1. - self assert: parser parse: 'abac' to: #($a $a) end: 3. - - self assert: parser fail: ''. - self assert: parser fail: 'c' -! - -testSequence - | parser | - parser := $a asParser , $b asParser. - - self assert: parser parse: 'ab' to: #($a $b). - - self assert: parser parse: 'aba' to: #($a $b) end: 2. - self assert: parser parse: 'abb' to: #($a $b) end: 2. - - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser fail: 'aa'. - self assert: parser fail: 'ba'. - self assert: parser fail: 'bab' -! - -testStar - | parser | - parser := $a asParser star. - - self assert: parser min = 0. - self assert: parser max > parser min. - - self assert: parser parse: '' to: #(). - self assert: parser parse: 'a' to: #($a). - self assert: parser parse: 'aa' to: #($a $a). - self assert: parser parse: 'aaa' to: #($a $a $a). - - self assert: parser parse: 'b' to: #() end: 0. - self assert: parser parse: 'ab' to: #($a) end: 1. - self assert: parser parse: 'aab' to: #($a $a) end: 2. - self assert: parser parse: 'aaab' to: #($a $a $a) end: 3 -! - -testStarGreedy - | limit parser | - limit := #digit asParser. - parser := #word asParser starGreedy: limit. - - self assert: parser min = 0. - self assert: parser max > parser min. - self assert: parser limit = limit. - self assert: parser children size = 2. - self assert: parser children last = limit. - - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser fail: 'ab'. - - self assert: parser parse: '1' to: #() end: 0. - self assert: parser parse: 'a1' to: #($a) end: 1. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. - self assert: parser parse: '12' to: #($1) end: 1. - self assert: parser parse: 'a12' to: #($a $1) end: 2. - self assert: parser parse: 'ab12' to: #($a $b $1) end: 3. - self assert: parser parse: 'abc12' to: #($a $b $c $1) end: 4. - self assert: parser parse: '123' to: #($1 $2) end: 2. - self assert: parser parse: 'a123' to: #($a $1 $2) end: 3. - self assert: parser parse: 'ab123' to: #($a $b $1 $2) end: 4. - self assert: parser parse: 'abc123' to: #($a $b $c $1 $2) end: 5 -! - -testStarLazy - | limit parser | - limit := #digit asParser. - parser := #word asParser starLazy: limit. - - self assert: parser min = 0. - self assert: parser max > parser min. - self assert: parser limit = limit. - self assert: parser children size = 2. - self assert: parser children last = limit. - - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser fail: 'ab'. - - self assert: parser parse: '1' to: #() end: 0. - self assert: parser parse: 'a1' to: #($a) end: 1. - self assert: parser parse: 'ab1' to: #($a $b) end: 2. - self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. - self assert: parser parse: '12' to: #() end: 0. - self assert: parser parse: 'a12' to: #($a) end: 1. - self assert: parser parse: 'ab12' to: #($a $b) end: 2. - self assert: parser parse: 'abc12' to: #($a $b $c) end: 3. - self assert: parser parse: '123' to: #() end: 0. - self assert: parser parse: 'a123' to: #($a) end: 1. - self assert: parser parse: 'ab123' to: #($a $b) end: 2. - self assert: parser parse: 'abc123' to: #($a $b $c) end: 3 -! - -testTimes - | parser | - parser := $a asParser times: 2. - - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser parse: 'aa' to: #($a $a). - self assert: parser parse: 'aaa' to: #($a $a) end: 2 -! - -testUnresolved - | parser | - parser := PPUnresolvedParser new. - - self assert: parser isUnresolved. - self should: [ parser parse: '' ] raise: Error. - self should: [ parser parse: 'a' ] raise: Error. - self should: [ parser parse: 'ab' ] raise: Error. - - parser := nil asParser. - self deny: parser isUnresolved -! - -testWrapped - | parser | - parser := $a asParser wrapped. - - self assert: parser parse: 'a' to: $a. - self assert: parser fail: 'b'. - - parser := (($a asParser , $b asParser ) wrapped , $c asParser). - self assert: parser parse: 'abc' to: #(#($a $b) $c) -! - -testXor - | parser | - parser := ($a asParser / $b asParser) - | ($b asParser / $c asParser). - - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'c' to: $c. - - self assert: parser fail: ''. - self assert: parser fail: 'b'. - self assert: parser fail: 'd'. - - " truly symmetric " - parser := ($b asParser / $c asParser) - | ($a asParser / $b asParser). - - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'c' to: $c. - - self assert: parser fail: ''. - self assert: parser fail: 'b'. - self assert: parser fail: 'd' -! ! - -!PPParserTest methodsFor:'testing-accessing'! - -testNamed - | parser | - parser := PPSequenceParser new. - self assert: parser name isNil. - - parser := PPChoiceParser named: 'choice'. - self assert: parser name = 'choice'. - - parser := $* asParser name: 'star'. - self assert: parser name = 'star' -! - -testPrint - | parser | - parser := PPParser new. - self assert: (parser printString findString: 'PPParser') > 0. - - parser := PPParser named: 'choice'. - self assert: (parser printString findString: 'PPParser(choice') > 0. - - parser := PPLiteralObjectParser on: $a. - self assert: (parser printString findString: '$a') > 0. - - parser := PPFailingParser message: 'error'. - self assert: (parser printString findString: 'error') > 0. - - parser := PPPredicateObjectParser on: [ :c | true ] message: 'error'. - self assert: (parser printString findString: 'error') > 0 -! ! - -!PPParserTest methodsFor:'testing-fixtures'! - -testSideEffectChoice - "Adding another element to a choice should create a copy, otherwise we get unwanted side-effects." - - | p1 p2 p3 | - p1 := $a asParser. - p2 := p1 / $b asParser. - p3 := p1 / $c asParser. - - self assert: p1 parse: 'a'. - self assert: p1 fail: 'b'. - self assert: p1 fail: 'c'. - - self assert: p2 parse: 'a'. - self assert: p2 parse: 'b'. - self assert: p2 fail: 'c'. - - self assert: p3 parse: 'a'. - self assert: p3 fail: 'b'. - self assert: p3 parse: 'c' -! - -testSideEffectListCopy - | old new | - old := $a asParser , $b asParser. - new := old copy. - - self deny: old == new. - self deny: old children == new children. - self assert: old children first == new children first. - self assert: old children last == new children last -! - -testSideEffectSequence - "Adding another element to a sequence should create a copy, otherwise we get unwanted side-effects." - - | p1 p2 p3 | - p1 := $a asParser. - p2 := p1 , $b asParser. - p3 := p1 , $c asParser. - - self assert: p1 parse: 'a'. - self assert: p1 parse: 'ab' end: 1. - self assert: p1 parse: 'ac' end: 1. - - self assert: p2 fail: 'a'. - self assert: p2 parse: 'ab'. - self assert: p2 fail: 'ac'. - - self assert: p3 fail: 'a'. - self assert: p3 fail: 'ab'. - self assert: p3 parse: 'ac' -! ! - -!PPParserTest methodsFor:'testing-mapping'! - -testAction - | block parser | - block := [ :char | char asUppercase ]. - parser := #any asParser ==> block. - self assert: parser block = block. - - self assert: parser parse: 'a' to: $A. - self assert: parser parse: 'b' to: $B -! - -testAnswer - | parser | - parser := $a asParser answer: $b. - - self assert: parser parse: 'a' to: $b. - - self assert: parser fail: ''. - self assert: parser fail: 'b' -! - -testFlatten - | parser | - parser := $a asParser flatten. - - self assert: parser parse: 'a' to: 'a'. - self assert: parser parse: #($a) to: #($a). - - self assert: parser fail: ''. - self assert: parser fail: 'b' -! - -testFoldLeft2 - | parser | - parser := #any asParser star - foldLeft: [ :a :b | Array with: a with: b ]. - - self assert: parser parse: #(a) to: #a. - self assert: parser parse: #(a b) to: #(a b). - self assert: parser parse: #(a b c) to: #((a b) c). - self assert: parser parse: #(a b c d) to: #(((a b) c) d). - self assert: parser parse: #(a b c d e) to: #((((a b) c) d) e) -! - -testFoldLeft3 - | parser | - parser := #any asParser star - foldLeft: [ :a :b :c | Array with: a with: b with: c ]. - - self assert: parser parse: #(a) to: #a. - self assert: parser parse: #(a b c) to: #(a b c). - self assert: parser parse: #(a b c d e) to: #((a b c) d e) -! - -testFoldRight2 - | parser | - parser := #any asParser star - foldRight: [ :a :b | Array with: a with: b ]. - - self assert: parser parse: #(a) to: #a. - self assert: parser parse: #(a b) to: #(a b). - self assert: parser parse: #(a b c) to: #(a (b c)). - self assert: parser parse: #(a b c d) to: #(a (b (c d))). - self assert: parser parse: #(a b c d e) to: #(a (b (c (d e)))) -! - -testFoldRight3 - | parser | - parser := #any asParser star - foldRight: [ :a :b :c | Array with: a with: b with: c ]. - - self assert: parser parse: #(a) to: #a. - self assert: parser parse: #(a b c) to: #(a b c). - self assert: parser parse: #(a b c d e) to: #(a b (c d e)) -! - -testMap1 - | parser | - parser := #any asParser - map: [ :a | Array with: a ]. - - self assert: parser parse: #(a) to: #(a) -! - -testMap2 - | parser | - parser := (#any asParser , #any asParser) - map: [ :a :b | Array with: b with: a ]. - - self assert: parser parse: #(a b) to: #(b a) -! - -testMap3 - | parser | - parser := (#any asParser , #any asParser , #any asParser) - map: [ :a :b :c | Array with: c with: b with: a ]. - - self assert: parser parse: #(a b c) to: #(c b a) -! - -testMapFail1 - self - should: [ #any asParser map: [ ] ] - raise: Error. - self - should: [ #any asParser map: [ :a :b | ] ] - raise: Error -! - -testMapFail2 - self - should: [ (#any asParser , #any asParser) map: [ :a | ] ] - raise: Error. - self - should: [ (#any asParser , #any asParser) map: [ :a :b :c | ] ] - raise: Error -! - -testPermutation - | parser | - parser := #any asParser , #any asParser , #any asParser. - - self assert: (parser permutation: #()) parse: '123' to: #(). - self assert: (parser permutation: #(1)) parse: '123' to: #($1). - self assert: (parser permutation: #(1 3)) parse: '123' to: #($1 $3). - self assert: (parser permutation: #(3 1)) parse: '123' to: #($3 $1). - self assert: (parser permutation: #(2 2)) parse: '123' to: #($2 $2). - self assert: (parser permutation: #(3 2 1)) parse: '123' to: #($3 $2 $1). - - self should: [ parser permutation: #(0) ] raise: Error. - self should: [ parser permutation: #(4) ] raise: Error. - self should: [ parser permutation: #($2) ] raise: Error -! - -testToken - | parser | - parser := $a asParser token. - self assert: parser tokenClass = PPToken. - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser fail: 'b'. - self assert: parser fail: ''. - - parser := $a asParser token: PPToken. - self assert: parser tokenClass = PPToken. - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser fail: ''. - self assert: parser fail: 'b' -! - -testTrim - | parser | - parser := $a asParser token trim. - - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser parse: 'a ' toToken: 1 stop: 1. - self assert: parser parse: 'a ' toToken: 1 stop: 1. - self assert: parser parse: 'a ' toToken: 1 stop: 1. - self assert: parser parse: 'a - ' toToken: 1 stop: 1. - - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser parse: ' a' toToken: 2 stop: 2. - self assert: parser parse: ' a' toToken: 2 stop: 2. - self assert: parser parse: ' a' toToken: 5 stop: 5. - self assert: parser parse: ' -a' toToken: 5 stop: 5. - - self assert: parser parse: 'aa' toToken: 1 stop: 1 end: 1. - self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 2. - self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 3. - - self assert: parser fail: ''. - self assert: parser fail: 'b' -! - -testTrimBlanks - | parser | - parser := $a asParser token trimBlanks. - - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser parse: 'a ' toToken: 1 stop: 1. - self assert: parser parse: 'a ' toToken: 1 stop: 1. - self assert: parser parse: 'a ' toToken: 1 stop: 1. - - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser parse: ' a' toToken: 2 stop: 2. - self assert: parser parse: ' a' toToken: 2 stop: 2. - self assert: parser parse: ' a' toToken: 5 stop: 5. - - self assert: parser parse: 'aa' toToken: 1 stop: 1 end: 1. - self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 2. - self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 3. - - self assert: parser fail: ''. - self assert: parser fail: ' -'. - self assert: parser fail: ' -a'. - self assert: parser fail: 'b'. -! - -testTrimCustom - | parser | - parser := $a asParser token trim: $b asParser. - - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser parse: 'ab' toToken: 1 stop: 1. - self assert: parser parse: 'abb' toToken: 1 stop: 1. - - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser parse: 'ba' toToken: 2 stop: 2. - self assert: parser parse: 'bba' toToken: 3 stop: 3. - - self assert: parser parse: 'aa' toToken: 1 stop: 1 end: 1. - self assert: parser parse: 'ab' toToken: 1 stop: 1 end: 2. - self assert: parser parse: 'abba' toToken: 1 stop: 1 end: 3. - - self assert: parser fail: ''. - self assert: parser fail: 'b' -! - -testTrimSpaces - | parser | - parser := $a asParser token trimSpaces. - - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser parse: 'a ' toToken: 1 stop: 1. - self assert: parser parse: 'a ' toToken: 1 stop: 1. - self assert: parser parse: 'a ' toToken: 1 stop: 1. - self assert: parser parse: 'a - ' toToken: 1 stop: 1. - - self assert: parser parse: 'a' toToken: 1 stop: 1. - self assert: parser parse: ' a' toToken: 2 stop: 2. - self assert: parser parse: ' a' toToken: 2 stop: 2. - self assert: parser parse: ' a' toToken: 5 stop: 5. - self assert: parser parse: ' -a' toToken: 5 stop: 5. - - self assert: parser parse: 'aa' toToken: 1 stop: 1 end: 1. - self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 2. - self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 3. - - self assert: parser fail: ''. - self assert: parser fail: 'b' -! - -testWrapping - | parser result | - parser := #digit asParser plus >=> [ :stream :cc | - Array - with: stream position - with: cc value - with: stream position ]. - - self assert: parser parse: '1' to: #(0 ($1) 1). - self assert: parser parse: '12' to: #(0 ($1 $2) 2). - self assert: parser parse: '123' to: #(0 ($1 $2 $3) 3). - - result := parser parse: 'a'. - self assert: result first = 0. - self assert: result second isPetitFailure. - self assert: result last = 0 -! ! - -!PPParserTest methodsFor:'testing-properties'! - -testHasProperty - | parser | - parser := PPParser new. - self deny: (parser hasProperty: #foo). - parser propertyAt: #foo put: 123. - self assert: (parser hasProperty: #foo) -! - -testPostCopy - | parser copy | - parser := PPParser new. - parser propertyAt: #foo put: true. - copy := parser copy. - copy propertyAt: #foo put: false. - self assert: (parser propertyAt: #foo). - self deny: (copy propertyAt: #foo) -! - -testPropertyAt - | parser | - parser := PPParser new. - self should: [ parser propertyAt: #foo ] raise: Error. - parser propertyAt: #foo put: true. - self assert: (parser propertyAt: #foo) -! - -testPropertyAtIfAbsent - | parser | - parser := PPParser new. - self assert: (parser propertyAt: #foo ifAbsent: [ true ]). - parser propertyAt: #foo put: true. - self assert: (parser propertyAt: #foo ifAbsent: [ false ]) -! - -testPropertyAtIfAbsentPut - | parser | - parser := PPParser new. - self assert: (parser propertyAt: #foo ifAbsentPut: [ true ]). - self assert: (parser propertyAt: #foo ifAbsentPut: [ false ]) -! - -testRemoveProperty - | parser | - parser := PPParser new. - self should: [ parser removeProperty: #foo ] raise: Error. - parser propertyAt: #foo put: true. - self assert: (parser removeProperty: #foo) -! - -testRemovePropertyIfAbsent - | parser | - parser := PPParser new. - self assert: (parser removeProperty: #foo ifAbsent: [ true ]). - parser propertyAt: #foo put: true. - self assert: (parser removeProperty: #foo ifAbsent: [ false ]) -! ! - -!PPParserTest methodsFor:'testing-utilities'! - -testChildren - | p1 p2 p3 | - p1 := #lowercase asParser. - p2 := p1 ==> #asUppercase. - p3 := PPUnresolvedParser new. - p3 def: p2 / p3. - self assert: p1 children isEmpty. - self assert: p2 children size = 1. - self assert: p3 children size = 2 -! - -testFailure - | failure | - failure := PPFailure message: 'Error' at: 3. - - self assert: failure message = 'Error'. - self assert: failure position = 3. - self assert: failure isPetitFailure. - - self deny: 4 isPetitFailure. - self deny: 'foo' isPetitFailure -! - -testListConstructor - | p1 p2 p3 | - p1 := PPChoiceParser with: $a asParser. - p2 := PPChoiceParser with: $a asParser with: $b asParser. - p3 := PPChoiceParser withAll: (Array with: $a asParser with: $b asParser with: $c asParser). - - self assert: p1 children size = 1. - self assert: p2 children size = 2. - self assert: p3 children size = 3 -! - -testMatches - | parser | - parser := $a asParser. - - self assert: (parser matches: 'a'). - self deny: (parser matches: 'b'). - - self assert: (parser matches: 'a' readStream). - self deny: (parser matches: 'b' readStream) -! - -testMatchesIn - | parser result | - parser := $a asParser. - - result := parser matchesIn: 'abba'. - self assert: result size = 2. - self assert: result first = $a. - self assert: result last = $a. - - result := parser matchesIn: 'baaah'. - self assert: result size = 3. - self assert: result first = $a. - self assert: result last = $a -! - -testMatchesInEmpty - "Empty matches should properly advance and match at each position and at the end." - - | parser result | - parser := [ :stream | stream position ] asParser. - - result := parser matchesIn: '123'. - self assert: result asArray = #(0 1 2 3) -! - -testMatchesInOverlapping - "Matches that overlap should be properly reported." - - | parser result | - parser := #digit asParser , #digit asParser. - - result := parser matchesIn: 'a123b'. - self assert: result size = 2. - self assert: result first = #($1 $2). - self assert: result last = #($2 $3) -! - -testMatchesSkipIn - | parser result | - parser := $a asParser. - - result := parser matchesSkipIn: 'abba'. - self assert: result size = 2. - self assert: result first = $a. - self assert: result last = $a. - - result := parser matchesSkipIn: 'baaah'. - self assert: result size = 3. - self assert: result first = $a. - self assert: result last = $a -! - -testMatchesSkipInOverlapping - "Matches that overlap should be properly reported." - - | parser result | - parser := #digit asParser , #digit asParser. - - result := parser matchesSkipIn: 'a123b'. - self assert: result size = 1. - self assert: result first = #($1 $2) -! - -testMatchingRangesIn - | input parser result | - input := 'a12b3'. - parser := #digit asParser plus. - result := parser matchingRangesIn: input. - result := result collect: [ :each | input copyFrom: each first to: each last ]. - self assert: result size = 3. - self assert: result first = '12'. - self assert: result second = '2'. - self assert: result last = '3' -! - -testMatchingSkipRangesIn - | input parser result | - input := 'a12b3'. - parser := #digit asParser plus. - result := parser matchingSkipRangesIn: input. - result := result collect: [ :each | input copyFrom: each first to: each last ]. - self assert: result size = 2. - self assert: result first = '12'. - self assert: result last = '3' -! - -testParse - | parser result | - parser := $a asParser. - - self assert: (parser parse: 'a') = $a. - self assert: (result := parser parse: 'b') isPetitFailure. - self assert: (result message findString: '$a') > 0. - self assert: (result message findString: 'expected') > 0. - self assert: (result position = 0). - - self assert: (parser parse: 'a' readStream) = $a. - self assert: (result := parser parse: 'b' readStream) isPetitFailure. - self assert: (result message findString: '$a') > 0. - self assert: (result message findString: 'expected') > 0. - self assert: (result position = 0) -! - -testParseOnError0 - | parser result seen | - parser := $a asParser. - - result := parser parse: 'a' onError: [ self signalFailure: 'Not supposed to report an error' ]. - self assert: result = $a. - - result := parser parse: 'b' onError: [ seen := true ]. - self assert: result. - self assert: seen -! - -testParseOnError1 - | parser result seen | - parser := $a asParser. - - result := parser parse: 'a' onError: [ self signalFailure: 'Not supposed to report an error' ]. - self assert: result = $a. - - result := parser parse: 'b' onError: [ :failure | - self assert: (failure position = 0). - self assert: (failure message findString: '$a') > 0. - self assert: (failure message findString: 'expected') > 0. - seen := true ]. - self assert: result. - self assert: seen -! - -testParseOnError2 - | parser result seen | - parser := $a asParser. - - result := parser parse: 'a' onError: [ self signalFailure: 'Not supposed to report an error' ]. - self assert: result = $a. - - result := parser parse: 'b' onError: [ :msg :pos | - self assert: (msg findString: '$a') > 0. - self assert: (msg findString: 'expected') > 0. - self assert: pos = 0. - seen := true ]. - self assert: result. - self assert: seen -! - -testParser - | parser | - parser := PPParser new. - - self assert: parser isPetitParser. - - self deny: 4 isPetitParser. - self deny: 'foo' isPetitParser -! ! - -!PPParserTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParserTest.st,v 1.4 2014-03-04 14:34:21 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParserTest.st,v 1.4 2014-03-04 14:34:21 cg Exp $' -! - -version_SVN - ^ '$Id: PPParserTest.st,v 1.4 2014-03-04 14:34:21 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPPredicateTest.st --- a/PPPredicateTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPAbstractParserTest subclass:#PPPredicateTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPPredicateTest methodsFor:'private'! - -charactersDo: aBlock - "cg: isn't 256 one too many?" - - Smalltalk isSmalltalkX ifTrue:[ - 0 to: 255 do: [ :index | aBlock value: (Character codePoint: index) ] - ] ifFalse:[ - 1 to: 256 do: [ :index | aBlock value: (Character codePoint: index) ] - ]. -! ! - -!PPPredicateTest methodsFor:'testing'! - -testOnMessage - | block parser | - block := [ :char | char = $* ]. - parser := PPPredicateObjectParser on: block message: 'starlet'. - self assert: parser block = block. - self assert: parser message = 'starlet'. - - self assertCharacterSets: parser. - self assert: parser parse: '*' to: $*. - self assert: parser parse: '**' to: $* end: 1. - self assert: parser fail: ''. - self assert: parser fail: '1'. - self assert: parser fail: 'a' -! ! - -!PPPredicateTest methodsFor:'testing-chars'! - -testBlank - | parser cr| - parser := #blank asParser. - self assertCharacterSets: parser. - self assert: parser parse: (String with: Character space) to: Character space. - self assert: parser parse: (String with: Character tab) to: Character tab. - self assert: parser fail: ''. - self assert: parser fail: '1'. - cr := Smalltalk isSmalltalkX - ifTrue:[Character return] - ifFalse:[Character cr]. - self assert: parser fail: (String with: cr) -! - -testChar - | parser | - parser := $* asParser. - self assertCharacterSets: parser. - self assert: parser parse: '*' to: $*. - self assert: parser parse: '**' to: $* end: 1. - self assert: parser fail: ''. - self assert: parser fail: '1'. - self assert: parser fail: 'a' -! - -testCr - | parser cr | - - cr := Smalltalk isSmalltalkX - ifTrue:[Character return] - ifFalse:[Character cr]. - - parser := #cr asParser. - self assertCharacterSets: parser. - self assert: parser parse: (String with: cr) to: cr -! - -testDigit - | parser | - parser := #digit asParser. - self assertCharacterSets: parser. - self assert: parser parse: '0' to: $0. - self assert: parser parse: '9' to: $9. - self assert: parser fail: ''. - self assert: parser fail: 'a' -! - -testHex - | parser | - parser := #hex asParser. - self assertCharacterSets: parser. - self assert: parser parse: '0' to: $0. - self assert: parser parse: '5' to: $5. - self assert: parser parse: '9' to: $9. - self assert: parser parse: 'A' to: $A. - self assert: parser parse: 'D' to: $D. - self assert: parser parse: 'F' to: $F. - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'e' to: $e. - self assert: parser parse: 'f' to: $f. - self assert: parser fail: ''. - self assert: parser fail: 'g' -! - -testLetter - | parser | - parser := #letter asParser. - self assertCharacterSets: parser. - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'Z' to: $Z. - self assert: parser fail: ''. - self assert: parser fail: '0' -! - -testLf - | parser | - parser := #lf asParser. - self assertCharacterSets: parser. - self assert: parser parse: (String with: Character lf) to: Character lf -! - -testLowercase - | parser | - parser := #lowercase asParser. - self assertCharacterSets: parser. - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'z' to: $z. - self assert: parser fail: ''. - self assert: parser fail: 'A'. - self assert: parser fail: '0' -! - -testNewline - | parser cr| - cr := Smalltalk isSmalltalkX - ifTrue:[Character return] - ifFalse:[Character cr]. - parser := #newline asParser. - self assertCharacterSets: parser. - self assert: parser parse: (String with: cr) to: cr. - self assert: parser parse: (String with: Character lf) to: Character lf. - self assert: parser fail: ' ' -! - -testPunctuation - | parser | - parser := #punctuation asParser. - self assertCharacterSets: parser. - self assert: parser parse: '.' to: $.. - self assert: parser parse: ',' to: $,. - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser fail: '1' -! - -testSpace - | parser | - parser := #space asParser. - self assertCharacterSets: parser. - self assert: parser parse: (String with: Character tab) to: Character tab. - self assert: parser parse: ' ' to: Character space. - self assert: parser fail: ''. - self assert: parser fail: 'a' -! - -testTab - | parser | - parser := #tab asParser. - self assertCharacterSets: parser. - self assert: parser parse: (String with: Character tab) to: Character tab -! - -testUppercase - | parser | - parser := #uppercase asParser. - self assertCharacterSets: parser. - self assert: parser parse: 'A' to: $A. - self assert: parser parse: 'Z' to: $Z. - self assert: parser fail: ''. - self assert: parser fail: 'a'. - self assert: parser fail: '0' -! - -testWord - | parser | - parser := #word asParser. - self assertCharacterSets: parser. - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'A' to: $A. - self assert: parser parse: '0' to: $0. - self assert: parser fail: ''. - self assert: parser fail: '-' -! ! - -!PPPredicateTest methodsFor:'testing-objects'! - -testAny - | parser | - parser := #any asParser. - self assertCharacterSets: parser. - self assert: parser parse: ' ' to: $ . - self assert: parser parse: '1' to: $1. - self assert: parser parse: 'a' to: $a. - self assert: parser fail: '' -! - -testAnyExceptAnyOf - | parser | - parser := PPPredicateObjectParser anyExceptAnyOf: #($: $,). - self assertCharacterSets: parser. - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'z' to: $z. - self assert: parser fail: ':'. - self assert: parser fail: ',' -! - -testAnyOf - | parser | - parser := PPPredicateObjectParser anyOf: #($a $z). - self assertCharacterSets: parser. - self assert: parser parse: 'a' to: $a. - self assert: parser parse: 'z' to: $z. - self assert: parser fail: 'x' -! - -testBetweenAnd - | parser | - parser := PPPredicateObjectParser between: $b and: $d. - self assertCharacterSets: parser. - self assert: parser fail: 'a'. - self assert: parser parse: 'b' to: $b. - self assert: parser parse: 'c' to: $c. - self assert: parser parse: 'd' to: $d. - self assert: parser fail: 'e' -! - -testExpect - | parser | - parser := PPPredicateObjectParser expect: $a. - self assertCharacterSets: parser. - self assert: parser parse: 'a' to: $a. - self assert: parser fail: 'b'. - self assert: parser fail: '' -! ! - -!PPPredicateTest methodsFor:'testing-sequence'! - -testSequenceParser - | parser | - parser := PPPredicateSequenceParser - on: [ :value | value first isUppercase ] - message: 'uppercase 3 letter words' - size: 3. - self assert: parser size = 3. - self assert: parser parse: 'Abc'. - self assert: parser parse: 'ABc'. - self assert: parser parse: 'ABC'. - self assert: parser fail: 'abc'. - self assert: parser fail: 'aBC'. - self assert: parser fail: 'Ab'. - - parser := parser negate. - self assert: parser size = 3. - self assert: parser fail: 'Abc'. - self assert: parser fail: 'ABc'. - self assert: parser fail: 'ABC'. - self assert: parser parse: 'abc'. - self assert: parser parse: 'aBC'. - self assert: parser fail: 'Ab' -! ! - -!PPPredicateTest methodsFor:'utilities'! - -assertCharacterSets: aParser - "Assert the character set of aParser does not overlap with the character set with the negated parser, and that they both cover the complete character space." - - | positives negatives | - positives := self parsedCharacterSet: aParser. - negatives := self parsedCharacterSet: aParser negate. - self charactersDo: [ :char | - | positive negative | - positive := positives includes: char. - negative := negatives includes: char. - self - assert: ((positive and: [ negative not ]) - or: [ positive not and: [ negative ] ]) - description: char printString , ' should be in exactly one set' ] -! - -parsedCharacterSet: aParser - | result | - result := WriteStream on: String new. - self charactersDo: [ :char | - (aParser matches: (String with: char)) - ifTrue: [ result nextPut: char ] ]. - ^ result contents -! ! - -!PPPredicateTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPPredicateTest.st,v 1.6 2014-03-04 20:09:46 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPPredicateTest.st,v 1.6 2014-03-04 20:09:46 cg Exp $' -! - -version_SVN - ^ '$Id: PPPredicateTest.st,v 1.6 2014-03-04 20:09:46 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPScriptingTest.st --- a/PPScriptingTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPAbstractParserTest subclass:#PPScriptingTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - -PPScriptingTest comment:'These are some simple demo-scripts of parser combinators for the compiler construction course. http://www.iam.unibe.ch/~scg/Teaching/CC/index.html' -! - - -!PPScriptingTest methodsFor:'examples'! - -expressionInterpreter - "Same as #expressionInterpreter but with semantic actions." - - | mul prim add dec | - add := PPUnresolvedParser new. - mul := PPUnresolvedParser new. - prim := PPUnresolvedParser new. - dec := ($0 to: $9) asParser ==> [ :token | token codePoint - $0 codePoint ]. - add def: ((mul , $+ asParser , add) ==> [ :nodes | (nodes at: 1) + (nodes at: 3) ]) - / mul. - mul def: ((prim , $* asParser , mul) ==> [ :nodes | (nodes at: 1) * (nodes at: 3) ]) - / prim. - prim def: (($( asParser , add , $) asParser) ==> [ :nodes | nodes at: 2 ]) - / dec. - ^ add end -! - -expressionParser - "Simple demo of scripting an expression parser." - - | mul prim add dec | - add := PPUnresolvedParser new. - mul := PPUnresolvedParser new. - prim := PPUnresolvedParser new. - dec := ($0 to: $9) asParser. - add def: (mul , $+ asParser , add) - / mul. - mul def: (prim , $* asParser , mul) - / prim. - prim def: ($( asParser , add , $) asParser) - / dec. - ^ add end -! - -straightLineParser - | goal stm stmList id char dec exp expList mulExp primExp nonzero num lower upper | - goal := PPUnresolvedParser new. - stmList := PPUnresolvedParser new. - stm := PPUnresolvedParser new. - exp := PPUnresolvedParser new. - expList := PPUnresolvedParser new. - mulExp := PPUnresolvedParser new. - primExp := PPUnresolvedParser new. - - lower := ($a to: $z) asParser. - upper := ($A to: $Z) asParser. - char := lower / upper. - nonzero := ($1 to: $9) asParser. - dec := ($0 to: $9) asParser. - id := char, ( char / dec ) star. - num := $0 asParser / ( nonzero, dec star). - - goal def: stmList end. - stmList def: stm , ( $; asParser, stm ) star. - stm def: ( id, ':=' asParser, exp ) - / ( 'print' asParser, $( asParser, expList, $) asParser ). - exp def: mulExp, ( ( $+ asParser / $- asParser ), mulExp ) star. - expList def: exp, ( $, asParser, exp ) star. - mulExp def: primExp, ( ( $* asParser / $/ asParser ), primExp ) star. - primExp def: id - / num - / ( $( asParser, stmList, $, asParser, exp, $) asParser ). - ^ goal -! ! - -!PPScriptingTest methodsFor:'tests'! - -testExpressionInterpreter - self - assert: self expressionInterpreter - parse: '2*(3+4)' - to: 14 -! - -testExpressionParser - self - assert: self expressionParser - parse: '2*(3+4)' - to: #($2 $* ($( ($3 $+ $4) $))) -! - -testSLassign - - self assert: self straightLineParser - parse: 'abc:=1' - to: #(#($a #($b $c) ':=' #(#(#($1 #()) #()) #())) #()) -! - -testSLprint - self - assert: self straightLineParser - parse: 'print(3,4)' - to: #(('print' $( ((($3 ()) ()) () (($, ((($4 ()) ()) ())))) $)) ()) -! ! - -!PPScriptingTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPScriptingTest.st,v 1.4 2014-03-04 14:34:23 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPScriptingTest.st,v 1.4 2014-03-04 14:34:23 cg Exp $' -! - -version_SVN - ^ '$Id: PPScriptingTest.st,v 1.4 2014-03-04 14:34:23 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e PPTokenTest.st --- a/PPTokenTest.st Fri Oct 03 00:52:34 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -"{ Package: 'stx:goodies/petitparser' }" - -PPAbstractParserTest subclass:#PPTokenTest - instanceVariableNames:'' - classVariableNames:'' - poolDictionaries:'' - category:'PetitTests-Tests' -! - - -!PPTokenTest methodsFor:'accessing'! - -identifier - ^ #word asParser plus token -! ! - -!PPTokenTest methodsFor:'testing'! - -testCollection - | input result | - input := 'foo '. - result := self - parse: input - using: self identifier. - self assert: (result collection = input). - self assert: (result collection == input) -! - -testInitialize - PPToken initialize -! - -testNew - self should: [ PPToken new ] raise: Error. - -! - -testPrinting - | result | - result := PPToken on: 'var'. - self assert: (result printString findString: 'PPToken[1,3]') > 0 -! - -testSize - | result | - result := self - parse: 'foo' - using: self identifier. - self assert: result size = 3 -! - -testStart - | result | - result := self - parse: 'foo' - using: self identifier. - self assert: result start = 1 -! - -testStop - | result | - result := self - parse: 'foo' - using: self identifier. - self assert: result stop = 3 -! - -testValue - | result | - result := PPToken on: 'var'. - self should: [ result value ] raise: Notification -! ! - -!PPTokenTest methodsFor:'testing-comparing'! - -testEquality - | token1 token2 | - token1 := self parse: 'foo' using: self identifier. - token2 := self parse: 'foo' using: self identifier. - self deny: token1 == token2. - self assert: token1 = token2. - self assert: token1 hash = token2 hash. -! ! - -!PPTokenTest methodsFor:'testing-copying'! - -testCopyFromTo - | result other | - result := PPToken on: 'abc'. - other := result copyFrom: 2 to: 2. - - self assert: other size = 1. - self assert: other start = 2. - self assert: other stop = 2. - self assert: other collection = result collection -! ! - -!PPTokenTest methodsFor:'testing-querying'! - -testColumn - | input parser result cr | - - cr := Smalltalk isSmalltalkX - ifTrue:[ Character return] - ifFalse:[ Character cr ]. - input := '1' , (String with:cr) , '12' , (String with: cr with: Character lf) , '123' , (String with: Character lf) , '1234'. - parser := #any asParser token star. - result := parser parse: input. - result - with: #(1 2 1 2 3 4 1 2 3 4 1 2 3 4) - do: [ :token :line | self assert: token column = line ] -! - -testLine - | input parser result cr| - - cr := Smalltalk isSmalltalkX - ifTrue:[Character return] - ifFalse:[Character cr]. - input := '1' , (String with: cr) , '12' , (String with: cr with: Character lf) , '123' , (String with: Character lf) , '1234'. - parser := #any asParser token star. - result := parser parse: input. - result - with: #(1 1 2 2 2 2 3 3 3 3 4 4 4 4) - do: [ :token :line | self assert: token line = line ] -! ! - -!PPTokenTest methodsFor:'testing-values'! - -testInputValue - | input result | - input := 'foo'. - result := self - parse: input - using: self identifier. - self assert: result inputValue = input. - self deny: result inputValue == input -! - -testParsedValue - | input result | - input := 'foo'. - result := self - parse: input - using: self identifier. - self assert: result parsedValue = #($f $o $o) -! ! - -!PPTokenTest methodsFor:'utilities'! - -parse: aString using: aParser - ^ aParser parse: aString -! ! - -!PPTokenTest class methodsFor:'documentation'! - -version - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPTokenTest.st,v 1.5 2014-03-04 14:34:24 cg Exp $' -! - -version_CVS - ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPTokenTest.st,v 1.5 2014-03-04 14:34:24 cg Exp $' -! - -version_SVN - ^ '$Id: PPTokenTest.st,v 1.5 2014-03-04 14:34:24 cg Exp $' -! ! - diff -r 1ba87229ee7e -r e2b2f08d054e abbrev.stc --- a/abbrev.stc Fri Oct 03 00:52:34 2014 +0100 +++ b/abbrev.stc Fri Oct 03 01:36:33 2014 +0100 @@ -1,31 +1,18 @@ # automagically generated by the project definition # this file is needed for stc to be able to compile modules independently. # it provides information about a classes filename, category and especially namespace. -PPAbstractParseTest PPAbstractParseTest stx:goodies/petitparser 'PetitTests-Core' 1 -PPArithmeticParserTest PPArithmeticParserTest stx:goodies/petitparser 'PetitTests-Tests' 1 PPCharSetPredicate PPCharSetPredicate stx:goodies/petitparser 'PetitParser-Tools' 0 -PPComposedTest PPComposedTest stx:goodies/petitparser 'PetitTests-Tests' 1 -PPExtensionTest PPExtensionTest stx:goodies/petitparser 'PetitTests-Tests' 1 PPFailure PPFailure stx:goodies/petitparser 'PetitParser-Core' 0 -PPLambdaParserTest PPLambdaParserTest stx:goodies/petitparser 'PetitTests-Tests' 1 PPMemento PPMemento stx:goodies/petitparser 'PetitParser-Core' 0 -PPObjectTest PPObjectTest stx:goodies/petitparser 'PetitTests-Tests' 1 PPParser PPParser stx:goodies/petitparser 'PetitParser-Parsers' 0 -PPParserResource PPParserResource stx:goodies/petitparser 'PetitTests-Core' 1 -PPParserTest PPParserTest stx:goodies/petitparser 'PetitTests-Tests' 1 -PPPredicateTest PPPredicateTest stx:goodies/petitparser 'PetitTests-Tests' 1 -PPScriptingTest PPScriptingTest stx:goodies/petitparser 'PetitTests-Tests' 1 PPStream PPStream stx:goodies/petitparser 'PetitParser-Core' 0 PPToken PPToken stx:goodies/petitparser 'PetitParser-Core' 0 -PPTokenTest PPTokenTest stx:goodies/petitparser 'PetitTests-Tests' 1 stx_goodies_petitparser stx_goodies_petitparser stx:goodies/petitparser '* Projects & Packages *' 3 PPDelegateParser PPDelegateParser stx:goodies/petitparser 'PetitParser-Parsers' 0 PPEpsilonParser PPEpsilonParser stx:goodies/petitparser 'PetitParser-Parsers' 0 -PPExpressionParserTest PPExpressionParserTest stx:goodies/petitparser 'PetitTests-Tests' 1 PPFailingParser PPFailingParser stx:goodies/petitparser 'PetitParser-Parsers' 0 PPListParser PPListParser stx:goodies/petitparser 'PetitParser-Parsers' 0 PPLiteralParser PPLiteralParser stx:goodies/petitparser 'PetitParser-Parsers' 0 -PPMappingTest PPMappingTest stx:goodies/petitparser 'PetitTests-Tests' 1 PPPluggableParser PPPluggableParser stx:goodies/petitparser 'PetitParser-Parsers' 0 PPPredicateParser PPPredicateParser stx:goodies/petitparser 'PetitParser-Parsers' 0 PPUnresolvedParser PPUnresolvedParser stx:goodies/petitparser 'PetitParser-Tools' 0 @@ -46,8 +33,6 @@ PPRepeatingParser PPRepeatingParser stx:goodies/petitparser 'PetitParser-Parsers' 0 PPSequenceParser PPSequenceParser stx:goodies/petitparser 'PetitParser-Parsers' 0 PPTrimmingParser PPTrimmingParser stx:goodies/petitparser 'PetitParser-Parsers' 0 -PPArithmeticParser PPArithmeticParser stx:goodies/petitparser 'PetitTests-Examples' 0 -PPLambdaParser PPLambdaParser stx:goodies/petitparser 'PetitTests-Examples' 0 PPLimitedRepeatingParser PPLimitedRepeatingParser stx:goodies/petitparser 'PetitParser-Parsers' 0 PPPossessiveRepeatingParser PPPossessiveRepeatingParser stx:goodies/petitparser 'PetitParser-Parsers' 0 PPTokenParser PPTokenParser stx:goodies/petitparser 'PetitParser-Parsers' 0 diff -r 1ba87229ee7e -r e2b2f08d054e libInit.cc --- a/libInit.cc Fri Oct 03 00:52:34 2014 +0100 +++ b/libInit.cc Fri Oct 03 01:36:33 2014 +0100 @@ -59,8 +59,6 @@ _PPRepeatingParser_Init(pass,__pRT__,snd); _PPSequenceParser_Init(pass,__pRT__,snd); _PPTrimmingParser_Init(pass,__pRT__,snd); -_PPArithmeticParser_Init(pass,__pRT__,snd); -_PPLambdaParser_Init(pass,__pRT__,snd); _PPLimitedRepeatingParser_Init(pass,__pRT__,snd); _PPPossessiveRepeatingParser_Init(pass,__pRT__,snd); _PPTokenParser_Init(pass,__pRT__,snd); diff -r 1ba87229ee7e -r e2b2f08d054e stx_goodies_petitparser.st --- a/stx_goodies_petitparser.st Fri Oct 03 00:52:34 2014 +0100 +++ b/stx_goodies_petitparser.st Fri Oct 03 01:36:33 2014 +0100 @@ -18,6 +18,16 @@ "Created: / 17-12-2010 / 19:44:58 / Jan Vrany " ! ! +!stx_goodies_petitparser class methodsFor:'accessing - tests'! + +testSuite + "generate and return a testSuite containing all of my test-classes" + + Smalltalk loadPackage: 'stx:goodies/petitparser/tests'. + ^ 'stx:goodies/petitparser/tests' asPackageId projectDefinitionClass testSuite + +! ! + !stx_goodies_petitparser class methodsFor:'description'! excludedFromPreRequisites @@ -94,31 +104,18 @@ ^ #( " or ( attributes...) in load order" - (PPAbstractParseTest autoload) - (PPArithmeticParserTest autoload) PPCharSetPredicate - (PPComposedTest autoload) - (PPExtensionTest autoload) PPFailure - (PPLambdaParserTest autoload) PPMemento - (PPObjectTest autoload) PPParser - (PPParserResource autoload) - (PPParserTest autoload) - (PPPredicateTest autoload) - (PPScriptingTest autoload) PPStream PPToken - (PPTokenTest autoload) #'stx_goodies_petitparser' PPDelegateParser PPEpsilonParser - (PPExpressionParserTest autoload) PPFailingParser PPListParser PPLiteralParser - (PPMappingTest autoload) PPPluggableParser PPPredicateParser PPUnresolvedParser @@ -139,8 +136,6 @@ PPRepeatingParser PPSequenceParser PPTrimmingParser - PPArithmeticParser - PPLambdaParser PPLimitedRepeatingParser PPPossessiveRepeatingParser PPTokenParser @@ -253,6 +248,8 @@ !stx_goodies_petitparser class methodsFor:'documentation'! +!stx_goodies_petitparser class methodsFor:'documentation'! + version ^ '$Header: /cvs/stx/stx/goodies/petitparser/stx_goodies_petitparser.st,v 1.15 2014-03-04 20:30:48 cg Exp $' ! diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPAbstractParseTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPAbstractParseTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,97 @@ +"{ Package: 'stx:goodies/petitparser' }" + +TestCase subclass:#PPAbstractParseTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Core' +! + + +!PPAbstractParseTest class methodsFor:'accessing'! + +packageNamesUnderTest + ^ #('PetitParser' 'PetitTests') +! ! + +!PPAbstractParseTest class methodsFor:'testing'! + +isAbstract + ^ self name = #PPAbstractParseTest +! ! + +!PPAbstractParseTest methodsFor:'utilities'! + +assert: aParser fail: aCollection + self assert: aParser fail: aCollection end: 0 +! + +assert: aParser fail: aCollection end: anInteger + | stream result | + self + assert: aParser isPetitParser + description: 'Parser invalid'. + stream := aCollection asPetitStream. + result := aParser parse: stream. + self + assert: result isPetitFailure + description: 'Parser did not fail'. + self + assert: stream position = anInteger + description: 'Parser failed at wrong position' +! + +assert: aParser parse: aCollection + self assert: aParser parse: aCollection to: nil end: aCollection size +! + +assert: aParser parse: aCollection end: anInteger + self assert: aParser parse: aCollection to: nil end: anInteger +! + +assert: aParser parse: aCollection to: anObject + self assert: aParser parse: aCollection to: anObject end: aCollection size +! + +assert: aParser parse: aParseObject to: aTargetObject end: anInteger + | stream result | + self + assert: aParser isPetitParser + description: 'Parser invalid'. + stream := aParseObject asPetitStream. + result := aParser parse: stream. + aTargetObject isNil + ifTrue: [ self deny: result isPetitFailure ] + ifFalse: [ self assert: result = aTargetObject ]. + self + assert: stream position = anInteger + description: 'Parser accepted at wrong position' + + "Modified: / 18-12-2010 / 18:01:30 / Jan Kurs " +! + +assert: aParser parse: aParserObject toToken: from stop: to + | token | + token := PPToken on: aParserObject start: from stop: to. + ^ self assert: aParser parse: aParserObject to: token +! + +assert: aParser parse: aParserObject toToken: from stop: to end: end + | token | + token := PPToken on: aParserObject start: from stop: to. + ^ self assert: aParser parse: aParserObject to: token end: end +! ! + +!PPAbstractParseTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPAbstractParseTest.st,v 1.3 2012-05-04 22:09:07 vrany Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPAbstractParseTest.st,v 1.3 2012-05-04 22:09:07 vrany Exp $' +! + +version_SVN + ^ '§Id: PPAbstractParseTest.st 4 2010-12-18 17:02:23Z kursjan §' +! ! diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPArithmeticParser.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPArithmeticParser.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,70 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPCompositeParser subclass:#PPArithmeticParser + instanceVariableNames:'terms addition factors multiplication power primary parentheses + number' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Examples' +! + + +!PPArithmeticParser methodsFor:'accessing'! + +start + ^ terms end +! ! + +!PPArithmeticParser methodsFor:'grammar'! + +addition + ^ (factors separatedBy: ($+ asParser / $- asParser) trim) + foldLeft: [ :a :op :b | a perform: op asSymbol with: b ] +! + +factors + ^ multiplication / power +! + +multiplication + ^ (power separatedBy: ($* asParser / $/ asParser) trim) + foldLeft: [ :a :op :b | a perform: op asSymbol with: b ] +! + +number + ^ ($- asParser optional , #digit asParser plus , ($. asParser , #digit asParser plus) optional) flatten trim + ==> [ :value | value asNumber ] +! + +parentheses + ^ $( asParser trim , terms , $) asParser trim + ==> [ :nodes | nodes second ] +! + +power + ^ (primary separatedBy: $^ asParser trim) + foldRight: [ :a :op :b | a raisedTo: b ] +! + +primary + ^ number / parentheses +! + +terms + ^ addition / factors +! ! + +!PPArithmeticParser class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPArithmeticParser.st,v 1.4 2014-03-04 14:33:59 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPArithmeticParser.st,v 1.4 2014-03-04 14:33:59 cg Exp $' +! + +version_SVN + ^ '$Id: PPArithmeticParser.st,v 1.4 2014-03-04 14:33:59 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPArithmeticParserTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPArithmeticParserTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,137 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPCompositeParserTest subclass:#PPArithmeticParserTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPArithmeticParserTest methodsFor:'accessing'! + +parserClass + ^ PPArithmeticParser +! ! + +!PPArithmeticParserTest methodsFor:'testing'! + +testNum + self assert: '0' is: 0. + self assert: '0.0' is: 0.0. + self assert: '1' is: 1. + self assert: '1.2' is: 1.2. + self assert: '34' is: 34. + self assert: '56.78' is: 56.78. + self assert: '-9' is: -9. + self assert: '-9.9' is: -9.9 +! ! + +!PPArithmeticParserTest methodsFor:'testing-expression'! + +testBrackets + self assert: '(1)' is: 1. + self assert: '(1 + 2)' is: 3. + + self assert: '((1))' is: 1. + self assert: '((1 + 2))' is: 3. + + self assert: '2 * (3 + 4)' is: 14. + self assert: '(2 + 3) * 4' is: 20. + self assert: '6 / (2 + 4)' is: 1. + self assert: '(2 + 6) / 2' is: 4 +! + +testPriority + self assert: '2 * 3 + 4' is: 10. + self assert: '2 + 3 * 4' is: 14. + self assert: '6 / 3 + 4' is: 6. + self assert: '2 + 6 / 2' is: 5 +! ! + +!PPArithmeticParserTest methodsFor:'testing-operations'! + +testAdd + self assert: '1 + 2' is: 3. + self assert: '2 + 1' is: 3. + self assert: '1 + 2.3' is: 3.3. + self assert: '2.3 + 1' is: 3.3. + self assert: '1 + -2' is: -1. + self assert: '-2 + 1' is: -1 +! + +testAddMany + self assert: '1' is: 1. + self assert: '1 + 2' is: 3. + self assert: '1 + 2 + 3' is: 6. + self assert: '1 + 2 + 3 + 4' is: 10. + self assert: '1 + 2 + 3 + 4 + 5' is: 15 +! + +testDiv + self assert: '12 / 3' is: 4. + self assert: '-16 / -4' is: 4 +! + +testDivMany + self assert: '100 / 2' is: 50. + self assert: '100 / 2 / 2' is: 25. + self assert: '100 / 2 / 2 / 5' is: 5. + self assert: '100 / 2 / 2 / 5 / 5' is: 1 + +! + +testMul + self assert: '2 * 3' is: 6. + self assert: '2 * -4' is: -8 +! + +testMulMany + self assert: '1 * 2' is: 2. + self assert: '1 * 2 * 3' is: 6. + self assert: '1 * 2 * 3 * 4' is: 24. + self assert: '1 * 2 * 3 * 4 * 5' is: 120 +! + +testPow + self assert: '2 ^ 3' is: 8. + self assert: '-2 ^ 3' is: -8. + self assert: '-2 ^ -3' is: -0.125 +! + +testPowMany + self assert: '4 ^ 3' is: 64. + self assert: '4 ^ 3 ^ 2' is: 262144. + self assert: '4 ^ 3 ^ 2 ^ 1' is: 262144. + self assert: '4 ^ 3 ^ 2 ^ 1 ^ 0' is: 262144 +! + +testSub + self assert: '1 - 2' is: -1. + self assert: '1.2 - 1.2' is: 0. + self assert: '1 - -2' is: 3. + self assert: '-1 - -2' is: 1 +! + +testSubMany + self assert: '1' is: 1. + self assert: '1 - 2' is: -1. + self assert: '1 - 2 - 3' is: -4. + self assert: '1 - 2 - 3 - 4' is: -8. + self assert: '1 - 2 - 3 - 4 - 5' is: -13 +! ! + +!PPArithmeticParserTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPArithmeticParserTest.st,v 1.4 2014-03-04 14:34:09 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPArithmeticParserTest.st,v 1.4 2014-03-04 14:34:09 cg Exp $' +! + +version_SVN + ^ '$Id: PPArithmeticParserTest.st,v 1.4 2014-03-04 14:34:09 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPComposedTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPComposedTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,416 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPAbstractParserTest subclass:#PPComposedTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPComposedTest methodsFor:'accessing'! + +comment + ^ ($" asParser , $" asParser negate star , $" asParser) flatten +! + +identifier + ^ (#letter asParser , #word asParser star) flatten +! + +number + ^ ($- asParser optional , #digit asParser plus , ($. asParser , #digit asParser plus) optional) flatten +! ! + +!PPComposedTest methodsFor:'testing'! + +testDoubledString + | parser | + parser := ($' asParser , (($' asParser , $' asParser) / $' asParser negate) star flatten , $' asParser) + ==> [ :nodes | nodes second copyReplaceAll: '''''' with: '''' ]. + + self assert: parser parse: '''''' to: ''. + self assert: parser parse: '''a''' to: 'a'. + self assert: parser parse: '''ab''' to: 'ab'. + self assert: parser parse: '''a''''b''' to: 'a''b'. + self assert: parser parse: '''a''''''''b''' to: 'a''''b' +! + +testEvenNumber + "Create a grammar that parses an even number of a's and b's." + + | a as b bs s | + a := $a asParser ==> [ :char | as := as + 1 ]. + b := $b asParser ==> [ :char | bs := bs + 1 ]. + s := (a / b) star >=> [ :stream :cc | + as := bs := 0. + cc value. + (as even and: [ bs even ]) + ifFalse: [ PPFailure message: 'Even number of a and b expected' at: 0 ] ]. + + self assert: s fail: 'a' end: 1. + self assert: s fail: 'b' end: 1. + self assert: s fail: 'ab' end: 2. + self assert: s fail: 'ba' end: 2. + self assert: s fail: 'aaa' end: 3. + self assert: s fail: 'bbb' end: 3. + self assert: s fail: 'aab' end: 3. + self assert: s fail: 'abb' end: 3. + + self assert: s parse: ''. + self assert: s parse: 'aa'. + self assert: s parse: 'bb'. + self assert: s parse: 'aaaa'. + self assert: s parse: 'aabb'. + self assert: s parse: 'abab'. + self assert: s parse: 'baba'. + self assert: s parse: 'bbaa'. + self assert: s parse: 'bbbb' +! + +testIfThenElse + "S ::= if C then S else S | if C then S | X" + + | start if then else cond expr parser | + start := PPDelegateParser new. + if := 'if' asParser token trim. + then := 'then' asParser token trim. + else := 'else' asParser token trim. + cond := 'C' asParser token trim. + expr := 'X' asParser token trim. + start setParser: (if , cond , then , start , else , start) / (if , cond , then , start) / expr. + parser := start end. + self assert: parser parse: 'X'. + self assert: parser parse: 'if C then X'. + self assert: parser parse: 'if C then X else X'. + self assert: parser parse: 'if C then if C then X'. + self assert: parser parse: 'if C then if C then X else if C then X'. + self assert: parser parse: 'if C then if C then X else X else if C then X'. + self assert: parser parse: 'if C then if C then X else X else if C then X else X'. + self assert: parser fail: 'if C'. + self assert: parser fail: 'if C else X'. + self assert: parser fail: 'if C then if C' +! + +testLeftRecursion + "S ::= S 'x' S / '1'" + + | parser | + parser := PPDelegateParser new. + parser setParser: ((parser , $x asParser , parser) / $1 asParser) memoized flatten. + + self assert: parser parse: '1' to: '1'. + self assert: parser parse: '1x1' to: '1x1'. + self assert: parser parse: '1x1x1' to: '1x1x1'. + self assert: parser parse: '1x1x1x1' to: '1x1x1x1'. + self assert: parser parse: '1x1x1x1x1' to: '1x1x1x1x1'. + self assert: parser parse: '1x1x1x1x1x1' to: '1x1x1x1x1x1' +! + +testListOfIntegers + "S ::= S , number | number" + + | number list parser | + number := #digit asParser plus flatten trim + ==> [ :node | node asInteger ]. + list := (number separatedBy: $, asParser token trim) + ==> [ :node | node select: [ :each | each isInteger ] ]. + parser := list end. + + self assert: parser parse: '1' to: (1 to: 1) asArray. + self assert: parser parse: '1,2' to: (1 to: 2) asArray. + self assert: parser parse: '1,2,3' to: (1 to: 3) asArray. + self assert: parser parse: '1,2,3,4' to: (1 to: 4) asArray. + self assert: parser parse: '1,2,3,4,5' to: (1 to: 5) asArray. + + self assert: parser parse: '1' to: (1 to: 1) asArray. + self assert: parser parse: '1, 2' to: (1 to: 2) asArray. + self assert: parser parse: '1, 2, 3' to: (1 to: 3) asArray. + self assert: parser parse: '1, 2, 3, 4' to: (1 to: 4) asArray. + self assert: parser parse: '1, 2, 3, 4, 5' to: (1 to: 5) asArray. + + self assert: parser parse: '1' to: (1 to: 1) asArray. + self assert: parser parse: '1 ,2' to: (1 to: 2) asArray. + self assert: parser parse: '1 ,2 ,3' to: (1 to: 3) asArray. + self assert: parser parse: '1 ,2 ,3 ,4' to: (1 to: 4) asArray. + self assert: parser parse: '1 ,2 ,3 ,4 ,5' to: (1 to: 5) asArray. + + self assert: parser fail: ''. + self assert: parser fail: ','. + self assert: parser fail: '1,'. + self assert: parser fail: '1,,2' +! + +testNestedComments + "C ::= B I* E" + "I ::= !!E (C | T)" + "B ::= /*" + "E ::= */" + "T ::= ." + + | begin end any inside parser | + begin := '/*' asParser. + end := '*/' asParser. + any := #any asParser. + + parser := PPDelegateParser new. + inside := end not , (parser / any). + parser setParser: begin , inside star , end. + + self assert: parser parse: '/*ab*/cd' end: 6. + self assert: parser parse: '/*a/*b*/c*/'. + self assert: parser fail: '/*a/*b*/c' +! + +testPalindrome + "S0 ::= a S1 a | b S1 b | ... + S1 ::= S0 | epsilon" + + | s0 s1 parser | + s0 := PPDelegateParser new. + s1 := PPDelegateParser new. + s0 setParser: ($a asParser , s1 , $a asParser) + / ($b asParser , s1 , $b asParser) + / ($c asParser , s1 , $c asParser). + s1 setParser: s0 / nil asParser. + parser := s0 flatten end. + + self assert: parser parse: 'aa' to: 'aa'. + self assert: parser parse: 'bb' to: 'bb'. + self assert: parser parse: 'cc' to: 'cc'. + + self assert: parser parse: 'abba' to: 'abba'. + self assert: parser parse: 'baab' to: 'baab'. + + self assert: parser parse: 'abccba' to: 'abccba'. + self assert: parser parse: 'abaaba' to: 'abaaba'. + self assert: parser parse: 'cbaabc' to: 'cbaabc'. + + self assert: parser fail: 'a'. + self assert: parser fail: 'ab'. + self assert: parser fail: 'aab'. + self assert: parser fail: 'abccbb' +! + +testParseAaaBbb + "S0 ::= a S1 b + S1 ::= S0 | epsilon" + + | s0 s1 parser | + s0 := PPDelegateParser new. + s1 := PPDelegateParser new. + s0 setParser: $a asParser , s1 , $b asParser. + s1 setParser: s0 / nil asParser. + parser := s0 flatten. + + self assert: parser parse: 'ab' to: 'ab'. + self assert: parser parse: 'aabb' to: 'aabb'. + self assert: parser parse: 'aaabbb' to: 'aaabbb'. + self assert: parser parse: 'aaaabbbb' to: 'aaaabbbb'. + + self assert: parser parse: 'abb' to: 'ab' end: 2. + self assert: parser parse: 'aabbb' to: 'aabb' end: 4. + self assert: parser parse: 'aaabbbb' to: 'aaabbb' end: 6. + self assert: parser parse: 'aaaabbbbb' to: 'aaaabbbb' end: 8. + + self assert: parser fail: 'a'. + self assert: parser fail: 'b'. + self assert: parser fail: 'aab'. + self assert: parser fail: 'aaabb' +! + +testParseAaaaaa + "S ::= a a S | epsilon" + + | s0 s1 parser | + s0 := PPDelegateParser new. + s1 := $a asParser , $a asParser , s0. + s0 setParser: s1 / nil asParser. + parser := s0 flatten. + + self assert: parser parse: '' to: ''. + self assert: parser parse: 'aa' to: 'aa'. + self assert: parser parse: 'aaaa' to: 'aaaa'. + self assert: parser parse: 'aaaaaa' to: 'aaaaaa'. + + self assert: parser parse: 'a' to: '' end: 0. + self assert: parser parse: 'aaa' to: 'aa' end: 2. + self assert: parser parse: 'aaaaa' to: 'aaaa' end: 4. + self assert: parser parse: 'aaaaaaa' to: 'aaaaaa' end: 6 +! + +testParseAbAbAb + "S ::= (A B)+" + + | parser | + parser := ($a asParser , $b asParser) plus flatten. + + self assert: parser parse: 'ab' to: 'ab'. + self assert: parser parse: 'abab' to: 'abab'. + self assert: parser parse: 'ababab' to: 'ababab'. + self assert: parser parse: 'abababab' to: 'abababab'. + + self assert: parser parse: 'abb' to: 'ab' end: 2. + self assert: parser parse: 'ababa' to: 'abab' end: 4. + self assert: parser parse: 'abababb' to: 'ababab' end: 6. + self assert: parser parse: 'ababababa' to: 'abababab' end: 8. + + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser fail: 'bab' +! + +testParseAbabbb + "S ::= (A | B)+" + + | parser | + parser := ($a asParser / $b asParser) plus flatten. + + self assert: parser parse: 'a' to: 'a'. + self assert: parser parse: 'b' to: 'b'. + self assert: parser parse: 'ab' to: 'ab'. + self assert: parser parse: 'ba' to: 'ba'. + self assert: parser parse: 'aaa' to: 'aaa'. + self assert: parser parse: 'aab' to: 'aab'. + self assert: parser parse: 'aba' to: 'aba'. + self assert: parser parse: 'baa' to: 'baa'. + self assert: parser parse: 'abb' to: 'abb'. + self assert: parser parse: 'bab' to: 'bab'. + self assert: parser parse: 'bba' to: 'bba'. + self assert: parser parse: 'bbb' to: 'bbb'. + + self assert: parser parse: 'ac' to: 'a' end: 1. + self assert: parser parse: 'bc' to: 'b' end: 1. + self assert: parser parse: 'abc' to: 'ab' end: 2. + self assert: parser parse: 'bac' to: 'ba' end: 2. + + self assert: parser fail: ''. + self assert: parser fail: 'c' +! + +testParseAnBnCn + "PEGs for a non context- free language: + + a^n , b^n , c^n + + S <- &P1 P2 + P1 <- AB 'c' + AB <- 'a' AB 'b' / epsilon + P2 <- 'a'* BC end + BC <- 'b' BC 'c' / epsilon" + + | s p1 ab p2 bc | + s := PPDelegateParser new. + p1 := PPDelegateParser new. + ab := PPDelegateParser new. + p2 := PPDelegateParser new. + bc := PPDelegateParser new. + + s setParser: (p1 and , p2 end) flatten. + p1 setParser: ab , $c asParser. + ab setParser: ($a asParser , ab , $b asParser) optional. + p2 setParser: $a asParser star , bc. + bc setParser: ($b asParser , bc , $c asParser) optional. + + self assert: s parse: 'abc' to: 'abc'. + self assert: s parse: 'aabbcc' to: 'aabbcc'. + self assert: s parse: 'aaabbbccc' to: 'aaabbbccc'. + + self assert: s fail: 'bc'. + self assert: s fail: 'ac'. + self assert: s fail: 'ab'. + self assert: s fail: 'abbcc'. + self assert: s fail: 'aabcc'. + self assert: s fail: 'aabbc' +! ! + +!PPComposedTest methodsFor:'testing-examples'! + +testComment + self assert: self comment parse: '""' to: '""'. + self assert: self comment parse: '"a"' to: '"a"'. + self assert: self comment parse: '"ab"' to: '"ab"'. + self assert: self comment parse: '"abc"' to: '"abc"'. + + self assert: self comment parse: '""a' to: '""' end: 2. + self assert: self comment parse: '"a"a' to: '"a"' end: 3. + self assert: self comment parse: '"ab"a' to: '"ab"' end: 4. + self assert: self comment parse: '"abc"a' to: '"abc"' end: 5. + + self assert: self comment fail: '"'. + self assert: self comment fail: '"a'. + self assert: self comment fail: '"aa'. + self assert: self comment fail: 'a"'. + self assert: self comment fail: 'aa"' +! + +testIdentifier + self assert: self identifier parse: 'a' to: 'a'. + self assert: self identifier parse: 'a1' to: 'a1'. + self assert: self identifier parse: 'a12' to: 'a12'. + self assert: self identifier parse: 'ab' to: 'ab'. + self assert: self identifier parse: 'a1b' to: 'a1b'. + + self assert: self identifier parse: 'a_' to: 'a' end: 1. + self assert: self identifier parse: 'a1-' to: 'a1' end: 2. + self assert: self identifier parse: 'a12+' to: 'a12' end: 3. + self assert: self identifier parse: 'ab^' to: 'ab' end: 2. + self assert: self identifier parse: 'a1b*' to: 'a1b' end: 3. + + self assert: self identifier fail: ''. + self assert: self identifier fail: '1'. + self assert: self identifier fail: '1a' +! + +testNumber + self assert: self number parse: '1' to: '1'. + self assert: self number parse: '12' to: '12'. + self assert: self number parse: '12.3' to: '12.3'. + self assert: self number parse: '12.34' to: '12.34'. + + self assert: self number parse: '1..' to: '1' end: 1. + self assert: self number parse: '12-' to: '12' end: 2. + self assert: self number parse: '12.3.' to: '12.3' end: 4. + self assert: self number parse: '12.34.' to: '12.34' end: 5. + + self assert: self number parse: '-1' to: '-1'. + self assert: self number parse: '-12' to: '-12'. + self assert: self number parse: '-12.3' to: '-12.3'. + self assert: self number parse: '-12.34' to: '-12.34'. + + self assert: self number fail: ''. + self assert: self number fail: '-'. + self assert: self number fail: '.'. + self assert: self number fail: '.1' +! + +testReturn + | number spaces return | + number := #digit asParser plus flatten. + spaces := #space asParser star. + return := (spaces , $^ asParser token , spaces , number) + ==> [ :nodes | Array with: #return with: (nodes at: 4) ]. + + self assert: return parse: '^1' to: #(return '1'). + self assert: return parse: '^12' to: #(return '12'). + self assert: return parse: '^ 123' to: #(return '123'). + self assert: return parse: '^ 1234' to: #(return '1234'). + + self assert: return fail: '1'. + self assert: return fail: '^' +! ! + +!PPComposedTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPComposedTest.st,v 1.5 2014-03-04 14:34:10 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPComposedTest.st,v 1.5 2014-03-04 14:34:10 cg Exp $' +! + +version_SVN + ^ '$Id: PPComposedTest.st,v 1.5 2014-03-04 14:34:10 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPExpressionParserTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPExpressionParserTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,86 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPArithmeticParserTest subclass:#PPExpressionParserTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPExpressionParserTest class methodsFor:'testing'! + +shouldInheritSelectors + ^ true +! ! + +!PPExpressionParserTest methodsFor:'accessing'! + +parserInstance + | expression parens number | + expression := PPExpressionParser new. + parens := $( asParser trim , expression , $) asParser trim + ==> [ :value | value second ]. + number := (#digit asParser plus , ($. asParser , #digit asParser plus) optional) flatten trim + ==> [ :value | value asNumber ]. + expression term: parens / number. + expression + group: [ :g | + g prefix: $- asParser trim do: [ :op :a | a negated ] ]; + group: [ :g | + g postfix: '++' asParser trim do: [ :a :op | a + 1 ]. + g postfix: '--' asParser trim do: [ :a :op | a - 1 ] ]; + group: [ :g | + g right: $^ asParser trim do: [ :a :op :b | a raisedTo: b ] ]; + group: [ :g | + g left: $* asParser trim do: [ :a :op :b | a * b ]. + g left: $/ asParser trim do: [ :a :op :b | a / b ] ]; + group: [ :g | + g left: $+ asParser trim do: [ :a :op :b | a + b ]. + g left: $- asParser trim do: [ :a :op :b | a - b ] ]. + ^ expression end +! ! + +!PPExpressionParserTest methodsFor:'testing'! + +testPostfixAdd + self assert: '0++' is: 1. + self assert: '0++++' is: 2. + self assert: '0++++++' is: 3. + + self assert: '0+++1' is: 2. + self assert: '0+++++1' is: 3. + self assert: '0+++++++1' is: 4 +! + +testPostfixSub + self assert: '1--' is: 0. + self assert: '2----' is: 0. + self assert: '3------' is: 0. + + self assert: '2---1' is: 0. + self assert: '3-----1' is: 0. + self assert: '4-------1' is: 0. +! + +testPrefixNegate + self assert: '1' is: 1. + self assert: '-1' is: -1. + self assert: '--1' is: 1. + self assert: '---1' is: -1 +! ! + +!PPExpressionParserTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPExpressionParserTest.st,v 1.4 2014-03-04 14:34:13 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPExpressionParserTest.st,v 1.4 2014-03-04 14:34:13 cg Exp $' +! + +version_SVN + ^ '$Id: PPExpressionParserTest.st,v 1.4 2014-03-04 14:34:13 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPExtensionTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPExtensionTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,154 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPAbstractParserTest subclass:#PPExtensionTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPExtensionTest methodsFor:'testing-parser'! + +testCharacter + | parser | + parser := $a asParser. + self assert: parser parse: 'a' to: $a. + self assert: parser fail: 'b' +! + +testChoice + | parser | + parser := #(1 2) asChoiceParser. + self assert: parser parse: #(1) to: 1. + self assert: parser parse: #(2) to: 2. + self assert: parser parse: #(1 2) to: 1 end: 1. + self assert: parser parse: #(2 1) to: 2 end: 1. + self assert: parser fail: #(). + self assert: parser fail: #(3) +! + +testClosure + | parser | + parser := [ :stream | stream upTo: $s ] asParser. + self assert: parser parse: '' to: ''. + self assert: parser parse: 'a' to: 'a'. + self assert: parser parse: 'aa' to: 'aa'. + self assert: parser parse: 's' to: ''. + self assert: parser parse: 'as' to: 'a'. + self assert: parser parse: 'aas' to: 'aa'. + self assert: parser parse: 'sa' to: '' end: 1. + self assert: parser parse: 'saa' to: '' end: 1. + + parser := [ :stream | stream upTo: $s. PPFailure message: 'stream' at: stream position ] asParser. + self assert: parser fail: ''. + self assert: parser fail: 's'. + self assert: parser fail: 'as' + +! + +testEpsilon + | parser | + parser := nil asParser. + self assert: parser asParser = parser +! + +testOrdered + | parser | + parser := #(1 2) asParser. + self assert: parser parse: #(1 2) to: #(1 2). + self assert: parser parse: #(1 2 3) to: #(1 2) end: 2. + self assert: parser fail: #(). + self assert: parser fail: #(1). + self assert: parser fail: #(1 1). + self assert: parser fail: #(1 1 2) +! + +testParser + | parser | + parser := $a asParser. + self assert: parser asParser = parser +! + +testRange + | parser | + parser := ($a to: $c) asParser. + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'b' to: $b. + self assert: parser parse: 'c' to: $c. + self assert: parser fail: 'd' +! + +testSequence + | parser | + parser := #(1 2) asSequenceParser. + self assert: parser parse: #(1 2) to: #(1 2). + self assert: parser parse: #(1 2 3) to: #(1 2) end: 2. + self assert: parser fail: #(). + self assert: parser fail: #(1). + self assert: parser fail: #(1 1). + self assert: parser fail: #(1 1 2) +! + +testString + | parser | + parser := 'ab' asParser. + self assert: parser parse: 'ab' to: 'ab'. + self assert: parser parse: 'aba' to: 'ab' end: 2. + self assert: parser parse: 'abb' to: 'ab' end: 2. + self assert: parser fail: 'a'. + self assert: parser fail: 'ac' +! + +testSymbol + | parser | + parser := #any asParser. + self assert: parser parse: 'a'. + self assert: parser fail: '' +! + +testUnordered + | parser | + parser := #(1 2) asSet asParser. + self assert: parser parse: #(1) to: 1. + self assert: parser parse: #(2) to: 2. + self assert: parser parse: #(1 2) to: 1 end: 1. + self assert: parser parse: #(2 1) to: 2 end: 1. + self assert: parser fail: #(). + self assert: parser fail: #(3) +! ! + +!PPExtensionTest methodsFor:'testing-stream'! + +testStream + | stream | + stream := 'abc' readStream asPetitStream. + self assert: (stream class = PPStream). + self assert: (stream printString = '·abc'). + self assert: (stream peek) = $a. + self assert: (stream uncheckedPeek = $a). + self assert: (stream next) = $a. + self assert: (stream printString = 'a·bc'). + self assert: (stream asPetitStream = stream) +! + +testText + | stream | + stream := 'abc' asText asPetitStream. + self assert: stream class = PPStream +! ! + +!PPExtensionTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPExtensionTest.st,v 1.4 2014-03-04 14:34:17 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPExtensionTest.st,v 1.4 2014-03-04 14:34:17 cg Exp $' +! + +version_SVN + ^ '$Id: PPExtensionTest.st,v 1.4 2014-03-04 14:34:17 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPLambdaParser.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPLambdaParser.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,74 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPCompositeParser subclass:#PPLambdaParser + instanceVariableNames:'expression abstraction application variable' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Examples' +! + + +!PPLambdaParser class methodsFor:'curch-booleans'! + +and + ^ self parse: '\p.\q.((p q) p)' +! + +false + ^ self parse: '\x.\y.y' +! + +ifthenelse + ^ self parse: '\p.p' +! + +not + ^ self parse: '\p.\a.\b.((p b) a)' +! + +or + ^ self parse: '\p.\q.((p p) q)' +! + +true + ^ self parse: '\x.\y.x' +! ! + +!PPLambdaParser methodsFor:'accessing'! + +start + ^ expression end +! ! + +!PPLambdaParser methodsFor:'productions'! + +abstraction + ^ $\ asParser trim , variable , $. asParser trim , expression ==> [ :node | Array with: node second with: node fourth ] +! + +application + ^ $( asParser trim , expression , expression , $) asParser trim ==> [ :node | Array with: node second with: node third ] +! + +expression + ^ variable / abstraction / application +! + +variable + ^ (#letter asParser , #word asParser star) flatten trim +! ! + +!PPLambdaParser class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPLambdaParser.st,v 1.4 2014-03-04 14:34:00 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPLambdaParser.st,v 1.4 2014-03-04 14:34:00 cg Exp $' +! + +version_SVN + ^ '$Id: PPLambdaParser.st,v 1.4 2014-03-04 14:34:00 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPLambdaParserTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPLambdaParserTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,158 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPCompositeParserTest subclass:#PPLambdaParserTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPLambdaParserTest methodsFor:'accessing'! + +parserClass + ^ PPLambdaParser +! ! + +!PPLambdaParserTest methodsFor:'testing'! + +testAbstraction + self assert: '\x.y' is: #('x' 'y'). + self assert: '\x.\y.z' is: #('x' ('y' 'z')) +! + +testApplication + self assert: '(x x)' is: #('x' 'x'). + self assert: '(x y)' is: #('x' 'y'). + self assert: '((x y) z)' is: #(('x' 'y') 'z'). + self assert: '(x (y z))' is: #('x' ('y' 'z')) +! + +testVariable + self assert: 'x' is: 'x'. + self assert: 'xy' is: 'xy'. + self assert: 'x12' is: 'x12' +! ! + +!PPLambdaParserTest methodsFor:'testing-curch'! + +testAnd + self assert: self parserClass and = #('p' ('q' (('p' 'q') 'p'))) +! + +testFalse + self assert: self parserClass false = #('x' ('y' 'y')) +! + +testIfThenElse + self assert: self parserClass ifthenelse = #('p' 'p') +! + +testNot + self assert: self parserClass not = #('p' ('a' ('b' (('p' 'b') 'a')))) +! + +testOr + self assert: self parserClass or = #('p' ('q' (('p' 'p') 'q'))) +! + +testTrue + self assert: self parserClass true = #('x' ('y' 'x')) +! ! + +!PPLambdaParserTest methodsFor:'testing-utilities'! + +testParseOnError + | beenHere | + result := self parserClass + parse: '\x.y' + onError: [ self fail ]. + self assert: result = #('x' 'y'). + + beenHere := false. + result := self parserClass + parse: '\x.' + onError: [ beenHere := true ]. + self assert: beenHere. + + beenHere := false. + result := self parserClass + parse: '\x.' + onError: [ :fail | beenHere := true. fail ]. + self assert: beenHere. + self assert: (result message findString: '$(') > 0. + self assert: (result message findString: 'expected') > 0. + self assert: (result position = 0). + + beenHere := false. + result := self parserClass + parse: '\x.' + onError: [ :msg :pos | + self assert: (msg findString: '$(') > 0. + self assert: (msg findString: 'expected') > 0. + self assert: (pos = 0). + beenHere := true ]. + self assert: result. + self assert: beenHere +! + +testParseStartingAtOnError + | beenHere | + result := self parserClass + parse: 'x' + startingAt: #variable + onError: [ self fail ]. + self assert: result = 'x'. + + beenHere := false. + result := self parserClass + parse: '\' + startingAt: #variable + onError: [ beenHere := true ]. + self assert: beenHere. + + beenHere := false. + result := self parserClass + parse: '\' + startingAt: #variable + onError: [ :fail | beenHere := true. fail ]. + self assert: beenHere. + self assert: result message = 'letter expected'. + self assert: result position = 0. + + beenHere := false. + result := self parserClass + parse: '\' + startingAt: #variable + onError: [ :msg :pos | + self assert: msg = 'letter expected'. + self assert: pos = 0. + beenHere := true ]. + self assert: beenHere +! + +testProductionAt + self assert: (parser productionAt: #foo) isNil. + self assert: (parser productionAt: #foo ifAbsent: [ true ]). + + self assert: (parser productionAt: #start) notNil. + self assert: (parser productionAt: #start ifAbsent: [ true ]) notNil. + + self assert: (parser productionAt: #variable) notNil. + self assert: (parser productionAt: #variable ifAbsent: [ true ]) notNil +! ! + +!PPLambdaParserTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPLambdaParserTest.st,v 1.4 2014-03-04 14:34:18 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPLambdaParserTest.st,v 1.4 2014-03-04 14:34:18 cg Exp $' +! + +version_SVN + ^ '$Id: PPLambdaParserTest.st,v 1.4 2014-03-04 14:34:18 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPMappingTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPMappingTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,93 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPAbstractParseTest subclass:#PPMappingTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPMappingTest methodsFor:'testing'! + +testFoldLeft2 + | parser | + parser := #any asParser star + foldLeft: [ :a :b | Array with: a with: b ]. + + self assert: parser parse: #(a) to: #a. + self assert: parser parse: #(a b) to: #(a b). + self assert: parser parse: #(a b c) to: #((a b) c). + self assert: parser parse: #(a b c d) to: #(((a b) c) d). + self assert: parser parse: #(a b c d e) to: #((((a b) c) d) e) +! + +testFoldLeft3 + | parser | + parser := #any asParser star + foldLeft: [ :a :b :c | Array with: a with: b with: c ]. + + self assert: parser parse: #(a) to: #a. + self assert: parser parse: #(a b c) to: #(a b c). + self assert: parser parse: #(a b c d e) to: #((a b c) d e) +! + +testFoldRight2 + | parser | + parser := #any asParser star + foldRight: [ :a :b | Array with: a with: b ]. + + self assert: parser parse: #(a) to: #a. + self assert: parser parse: #(a b) to: #(a b). + self assert: parser parse: #(a b c) to: #(a (b c)). + self assert: parser parse: #(a b c d) to: #(a (b (c d))). + self assert: parser parse: #(a b c d e) to: #(a (b (c (d e)))) +! + +testFoldRight3 + | parser | + parser := #any asParser star + foldRight: [ :a :b :c | Array with: a with: b with: c ]. + + self assert: parser parse: #(a) to: #a. + self assert: parser parse: #(a b c) to: #(a b c). + self assert: parser parse: #(a b c d e) to: #(a b (c d e)) +! + +testMap1 + | parser | + parser := #any asParser + map: [ :a | Array with: a ]. + + self assert: parser parse: #(a) to: #(a) +! + +testMap2 + | parser | + parser := (#any asParser , #any asParser) + map: [ :a :b | Array with: b with: a ]. + + self assert: parser parse: #(a b) to: #(b a) +! + +testMap3 + | parser | + parser := (#any asParser , #any asParser , #any asParser) + map: [ :a :b :c | Array with: c with: b with: a ]. + + self assert: parser parse: #(a b c) to: #(c b a) +! ! + +!PPMappingTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPMappingTest.st,v 1.3 2012-05-04 22:03:40 vrany Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPMappingTest.st,v 1.3 2012-05-04 22:03:40 vrany Exp $' +! + +version_SVN + ^ '§Id: PPMappingTest.st 4 2010-12-18 17:02:23Z kursjan §' +! ! diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPObjectTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPObjectTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,94 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPAbstractParserTest subclass:#PPObjectTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPObjectTest methodsFor:'parsers'! + +integer + ^ PPPredicateObjectParser + on: [ :each | each isInteger ] + message: 'integer expected' +! + +string + ^ PPPredicateObjectParser + on: [ :each | each isString ] + message: 'string expected' +! ! + +!PPObjectTest methodsFor:'testing'! + +testInteger + self assert: self integer parse: #(123) to: 123. + self assert: self integer fail: #('abc') +! + +testString + self assert: self string parse: #('abc') to: 'abc'. + self assert: self string fail: #(123) +! ! + +!PPObjectTest methodsFor:'testing-fancy'! + +testFibonacci + "This parser accepts fibonacci sequences with arbitrary start pairs." + + | parser | + parser := ((self integer , self integer) end ==> [ :pair | pair first + pair last ]) + / (self integer , (self integer , self integer) and >=> [ :stream :continuation | + | result | + result := continuation value. + (result isPetitFailure or: [ result first + result last first ~= result last last ]) + ifFalse: [ parser parseOn: stream ] + ifTrue: [ PPFailure message: 'invalid fibonacci sequence' at: stream position ] ]). + self assert: parser parse: #(1 1) to: 2. + self assert: parser parse: #(1 1 2) to: 3. + self assert: parser parse: #(1 1 2 3) to: 5. + self assert: parser parse: #(1 1 2 3 5) to: 8. + self assert: parser parse: #(1 1 2 3 5 8) to: 13. + self assert: parser parse: #(1 1 2 3 5 8 13) to: 21. + self assert: parser fail: #(). + self assert: parser fail: #(1). + self assert: parser fail: #(1 2 3 4) end: 2 + +! ! + +!PPObjectTest methodsFor:'testing-operators'! + +testChoice + | parser | + parser := self integer / self string. + self assert: parser parse: #(123) to: 123. + self assert: parser parse: #('abc') to: 'abc' +! + +testSequence + | parser | + parser := self integer , self string. + self assert: parser parse: #(123 'abc') to: #(123 'abc'). + self assert: parser fail: #(123 456). + self assert: parser fail: #('abc' 'def'). + self assert: parser fail: #('abc' 123) + +! ! + +!PPObjectTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPObjectTest.st,v 1.4 2014-03-04 14:34:19 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPObjectTest.st,v 1.4 2014-03-04 14:34:19 cg Exp $' +! + +version_SVN + ^ '$Id: PPObjectTest.st,v 1.4 2014-03-04 14:34:19 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPParserResource.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPParserResource.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,38 @@ +"{ Package: 'stx:goodies/petitparser' }" + +TestResource subclass:#PPParserResource + instanceVariableNames:'parsers' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Core' +! + + +!PPParserResource methodsFor:'accessing'! + +parserAt: aParserClass + "Answer a cached instance of aParserClass." + + ^ parsers at: aParserClass name ifAbsentPut: [ aParserClass new ] +! ! + +!PPParserResource methodsFor:'running'! + +setUp + super setUp. + parsers := Dictionary new +! ! + +!PPParserResource class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParserResource.st,v 1.3 2012-05-04 22:09:18 vrany Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParserResource.st,v 1.3 2012-05-04 22:09:18 vrany Exp $' +! + +version_SVN + ^ '§Id: PPParserResource.st 4 2010-12-18 17:02:23Z kursjan §' +! ! diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPParserTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPParserTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,1372 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPAbstractParserTest subclass:#PPParserTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPParserTest methodsFor:'testing'! + +testAnd + | parser | + parser := 'foo' asParser flatten , 'bar' asParser flatten and. + + self assert: parser parse: 'foobar' to: #('foo' 'bar') end: 3. + self assert: parser fail: 'foobaz'. + + parser := 'foo' asParser and. + self assert: parser and = parser +! + +testBlock + | parser | + parser := [ :s | s next ] asParser. + + self assert: parser parse: 'ab' to: $a end: 1. + self assert: parser parse: 'b' to: $b. + self assert: parser parse: '' to: nil +! + +testChoice + | parser | + parser := $a asParser / $b asParser. + + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'b' to: $b. + + self assert: parser parse: 'ab' to: $a end: 1. + self assert: parser parse: 'ba' to: $b end: 1. + + self assert: parser fail: ''. + self assert: parser fail: 'c'. + self assert: parser fail: 'ca' +! + +testDelimitedBy + | parser | + parser := $a asParser delimitedBy: $b asParser. + + self assert: parser parse: 'a' to: #($a). + self assert: parser parse: 'aba' to: #($a $b $a). + self assert: parser parse: 'ababa' to: #($a $b $a $b $a). + + self assert: parser parse: 'ab' to: #($a $b). + self assert: parser parse: 'abab' to: #($a $b $a $b). + self assert: parser parse: 'ababab' to: #($a $b $a $b $a $b). + + self assert: parser parse: 'ac' to: #($a) end: 1. + self assert: parser parse: 'abc' to: #($a $b) end: 2. + self assert: parser parse: 'abac' to: #($a $b $a) end: 3. + self assert: parser parse: 'ababc' to: #($a $b $a $b) end: 4. + + self assert: parser fail: ''. + self assert: parser fail: 'b'. + self assert: parser fail: 'c' +! + +testDelimitedByWithoutSeparators + | parser | + parser := ($a asParser delimitedBy: $b asParser) + withoutSeparators. + + self assert: parser parse: 'a' to: #($a). + self assert: parser parse: 'aba' to: #($a $a). + self assert: parser parse: 'ababa' to: #($a $a $a). + + self assert: parser parse: 'ab' to: #($a). + self assert: parser parse: 'abab' to: #($a $a). + self assert: parser parse: 'ababab' to: #($a $a $a). + + self assert: parser parse: 'ac' to: #($a) end: 1. + self assert: parser parse: 'abc' to: #($a) end: 2. + self assert: parser parse: 'abac' to: #($a $a) end: 3. + self assert: parser parse: 'ababc' to: #($a $a) end: 4. + + self assert: parser fail: ''. + self assert: parser fail: 'b'. + self assert: parser fail: 'c' +! + +testEndOfInput + | parser | + parser := PPEndOfInputParser on: $a asParser. + self assert: parser end = parser. + + self assert: parser parse: 'a' to: $a. + self assert: parser fail: ''. + self assert: parser fail: 'aa' +! + +testEndOfInputAfterMatch + | parser | + parser := 'stuff' asParser end. + self assert: parser parse: 'stuff' to: 'stuff'. + self assert: parser fail: 'stufff'. + self assert: parser fail: 'fluff' +! + +testEpsilon + | parser | + parser := nil asParser. + + self assert: parser parse: '' to: nil. + + self assert: parser parse: 'a' to: nil end: 0. + self assert: parser parse: 'ab' to: nil end: 0 +! + +testFailing + | parser result | + parser := PPFailingParser message: 'Plonk'. + self assert: parser message = 'Plonk'. + + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser fail: 'aa'. + + result := parser parse: 'a'. + self assert: result message = 'Plonk'. + self assert: result printString = 'Plonk at 0' +! + +testLiteralObject + | parser | + parser := PPLiteralObjectParser + on: $a + message: 'letter "a" expected'. + self assert: parser literal = $a. + self assert: parser message = 'letter "a" expected'. + + self assert: parser parse: 'a' to: $a. + self assert: parser fail: 'b' + +! + +testLiteralObjectCaseInsensitive + | parser | + parser := $a asParser caseInsensitive. + + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'A' to: $A. + + self assert: parser fail: ''. + self assert: parser fail: 'b'. + self assert: parser fail: 'B' + +! + +testLiteralSequence + | parser | + parser := PPLiteralSequenceParser + on: 'abc' + message: 'sequence "abc" expected'. + self assert: parser size = 3. + self assert: parser literal = 'abc'. + self assert: parser message = 'sequence "abc" expected'. + + self assert: parser parse: 'abc' to: 'abc'. + self assert: parser fail: 'ab'. + self assert: parser fail: 'abd' +! + +testLiteralSequenceCaseInsensitive + | parser | + parser := 'abc' asParser caseInsensitive. + + self assert: parser parse: 'abc' to: 'abc'. + self assert: parser parse: 'ABC' to: 'ABC'. + self assert: parser parse: 'abC' to: 'abC'. + self assert: parser parse: 'AbC' to: 'AbC'. + + self assert: parser fail: 'ab'. + self assert: parser fail: 'abd' +! + +testMax + | parser | + parser := $a asParser max: 2. + self assert: parser min = 0. + self assert: parser max = 2. + + self assert: parser parse: '' to: #(). + self assert: parser parse: 'a' to: #($a). + self assert: parser parse: 'aa' to: #($a $a). + self assert: parser parse: 'aaa' to: #($a $a) end: 2. + self assert: parser parse: 'aaaa' to: #($a $a) end: 2. + + self assert: (parser printString endsWith: '[0, 2]') +! + +testMaxGreedy + | parser | + parser := #word asParser max: 2 greedy: #digit asParser. + + self assert: parser fail: ''. + self assert: parser fail: 'abc'. + + self assert: parser parse: '1' to: #() end: 0. + self assert: parser parse: 'a1' to: #($a) end: 1. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser fail: 'abc1'. + + self assert: parser parse: '12' to: #($1) end: 1. + self assert: parser parse: 'a12' to: #($a $1) end: 2. + self assert: parser parse: 'ab12' to: #($a $b) end: 2. + self assert: parser fail: 'abc12'. + + self assert: parser parse: '123' to: #($1 $2) end: 2. + self assert: parser parse: 'a123' to: #($a $1) end: 2. + self assert: parser parse: 'ab123' to: #($a $b) end: 2. + self assert: parser fail: 'abc123' +! + +testMaxLazy + | parser | + parser := #word asParser max: 2 lazy: #digit asParser. + + self assert: parser fail: ''. + self assert: parser fail: 'abc'. + + self assert: parser parse: '1' to: #() end: 0. + self assert: parser parse: 'a1' to: #($a) end: 1. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser fail: 'abc1'. + + self assert: parser parse: '12' to: #() end: 0. + self assert: parser parse: 'a12' to: #($a) end: 1. + self assert: parser parse: 'ab12' to: #($a $b) end: 2. + self assert: parser fail: 'abc12'. + + self assert: parser parse: '123' to: #() end: 0. + self assert: parser parse: 'a123' to: #($a) end: 1. + self assert: parser parse: 'ab123' to: #($a $b) end: 2. + self assert: parser fail: 'abc123' +! + +testMemoized + | count parser twice | + count := 0. + parser := [ :s | count := count + 1. s next ] asParser memoized. + twice := parser and , parser. + + count := 0. + self assert: parser parse: 'a' to: $a. + self assert: count = 1. + + count := 0. + self assert: twice parse: 'a' to: #($a $a). + self assert: count = 1. + + self assert: parser memoized = parser +! + +testMin + | parser | + parser := $a asParser min: 2. + self assert: parser min = 2. + self assert: parser max > parser min. + + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser parse: 'aa' to: #($a $a). + self assert: parser parse: 'aaa' to: #($a $a $a). + self assert: parser parse: 'aaaa' to: #($a $a $a $a). + + self assert: (parser printString endsWith: '[2, *]') +! + +testMinGreedy + | parser | + parser := #word asParser min: 2 greedy: #digit asParser. + + self assert: parser fail: ''. + self assert: parser fail: 'abcde'. + + self assert: parser fail: '1'. + self assert: parser fail: 'a1'. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd1' to: #($a $b $c $d) end: 4. + self assert: parser parse: 'abcde1' to: #($a $b $c $d $e) end: 5. + + self assert: parser fail: '12'. + self assert: parser parse: 'a12' to: #($a $1) end: 2. + self assert: parser parse: 'ab12' to: #($a $b $1) end: 3. + self assert: parser parse: 'abc12' to: #($a $b $c $1) end: 4. + self assert: parser parse: 'abcd12' to: #($a $b $c $d $1) end: 5. + self assert: parser parse: 'abcde12' to: #($a $b $c $d $e $1) end: 6. + + self assert: parser parse: '123' to: #($1 $2) end: 2. + self assert: parser parse: 'a123' to: #($a $1 $2) end: 3. + self assert: parser parse: 'ab123' to: #($a $b $1 $2) end: 4. + self assert: parser parse: 'abc123' to: #($a $b $c $1 $2) end: 5. + self assert: parser parse: 'abcd123' to: #($a $b $c $d $1 $2) end: 6. + self assert: parser parse: 'abcde123' to: #($a $b $c $d $e $1 $2) end: 7. + + self assert: parser parse: '1234' to: #($1 $2 $3) end: 3. + self assert: parser parse: 'a1234' to: #($a $1 $2 $3) end: 4. + self assert: parser parse: 'ab1234' to: #($a $b $1 $2 $3) end: 5. + self assert: parser parse: 'abc1234' to: #($a $b $c $1 $2 $3) end: 6. + self assert: parser parse: 'abcd1234' to: #($a $b $c $d $1 $2 $3) end: 7. + self assert: parser parse: 'abcde1234' to: #($a $b $c $d $e $1 $2 $3) end: 8 +! + +testMinLazy + | parser | + parser := #word asParser min: 2 lazy: #digit asParser. + + self assert: parser fail: ''. + self assert: parser fail: 'abcde'. + + self assert: parser fail: '1'. + self assert: parser fail: 'a1'. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd1' to: #($a $b $c $d) end: 4. + self assert: parser parse: 'abcde1' to: #($a $b $c $d $e) end: 5. + + self assert: parser fail: '12'. + self assert: parser parse: 'a12' to: #($a $1) end: 2. + self assert: parser parse: 'ab12' to: #($a $b) end: 2. + self assert: parser parse: 'abc12' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd12' to: #($a $b $c $d) end: 4. + self assert: parser parse: 'abcde12' to: #($a $b $c $d $e) end: 5. + + self assert: parser parse: '123' to: #($1 $2) end: 2. + self assert: parser parse: 'a123' to: #($a $1) end: 2. + self assert: parser parse: 'ab123' to: #($a $b) end: 2. + self assert: parser parse: 'abc123' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd123' to: #($a $b $c $d) end: 4. + self assert: parser parse: 'abcde123' to: #($a $b $c $d $e) end: 5. + + self assert: parser parse: '1234' to: #($1 $2) end: 2. + self assert: parser parse: 'a1234' to: #($a $1) end: 2. + self assert: parser parse: 'ab1234' to: #($a $b) end: 2. + self assert: parser parse: 'abc1234' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd1234' to: #($a $b $c $d) end: 4. + self assert: parser parse: 'abcde1234' to: #($a $b $c $d $e) end: 5 +! + +testMinMax + | parser | + parser := $a asParser min: 2 max: 4. + self assert: parser min = 2. + self assert: parser max = 4. + + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser parse: 'aa' to: #($a $a). + self assert: parser parse: 'aaa' to: #($a $a $a). + self assert: parser parse: 'aaaa' to: #($a $a $a $a). + self assert: parser parse: 'aaaaa' to: #($a $a $a $a) end: 4. + self assert: parser parse: 'aaaaaa' to: #($a $a $a $a) end: 4. + + self assert: (parser printString endsWith: '[2, 4]') +! + +testMinMaxGreedy + | parser | + parser := #word asParser min: 2 max: 4 greedy: #digit asParser. + + self assert: parser fail: ''. + self assert: parser fail: 'abcde'. + + self assert: parser fail: '1'. + self assert: parser fail: 'a1'. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd1' to: #($a $b $c $d) end: 4. + self assert: parser fail: 'abcde1'. + + self assert: parser fail: '12'. + self assert: parser parse: 'a12' to: #($a $1) end: 2. + self assert: parser parse: 'ab12' to: #($a $b $1) end: 3. + self assert: parser parse: 'abc12' to: #($a $b $c $1) end: 4. + self assert: parser parse: 'abcd12' to: #($a $b $c $d) end: 4. + self assert: parser fail: 'abcde12'. + + self assert: parser parse: '123' to: #($1 $2) end: 2. + self assert: parser parse: 'a123' to: #($a $1 $2) end: 3. + self assert: parser parse: 'ab123' to: #($a $b $1 $2) end: 4. + self assert: parser parse: 'abc123' to: #($a $b $c $1) end: 4. + self assert: parser parse: 'abcd123' to: #($a $b $c $d) end: 4. + self assert: parser fail: 'abcde123'. + + self assert: parser parse: '1234' to: #($1 $2 $3) end: 3. + self assert: parser parse: 'a1234' to: #($a $1 $2 $3) end: 4. + self assert: parser parse: 'ab1234' to: #($a $b $1 $2) end: 4. + self assert: parser parse: 'abc1234' to: #($a $b $c $1) end: 4. + self assert: parser parse: 'abcd1234' to: #($a $b $c $d) end: 4. + self assert: parser fail: 'abcde1234' +! + +testMinMaxLazy + | parser | + parser := #word asParser min: 2 max: 4 lazy: #digit asParser. + + self assert: parser fail: ''. + self assert: parser fail: 'abcde'. + + self assert: parser fail: '1'. + self assert: parser fail: 'a1'. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd1' to: #($a $b $c $d) end: 4. + self assert: parser fail: 'abcde1'. + + self assert: parser fail: '12'. + self assert: parser parse: 'a12' to: #($a $1) end: 2. + self assert: parser parse: 'ab12' to: #($a $b) end: 2. + self assert: parser parse: 'abc12' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd12' to: #($a $b $c $d) end: 4. + self assert: parser fail: 'abcde12'. + + self assert: parser parse: '123' to: #($1 $2) end: 2. + self assert: parser parse: 'a123' to: #($a $1) end: 2. + self assert: parser parse: 'ab123' to: #($a $b) end: 2. + self assert: parser parse: 'abc123' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd123' to: #($a $b $c $d) end: 4. + self assert: parser fail: 'abcde123'. + + self assert: parser parse: '1234' to: #($1 $2) end: 2. + self assert: parser parse: 'a1234' to: #($a $1) end: 2. + self assert: parser parse: 'ab1234' to: #($a $b) end: 2. + self assert: parser parse: 'abc1234' to: #($a $b $c) end: 3. + self assert: parser parse: 'abcd1234' to: #($a $b $c $d) end: 4. + self assert: parser fail: 'abcde1234' +! + +testNegate + | parser | + parser := 'foo' asParser negate. + + self assert: parser parse: 'f' to: $f end: 1. + self assert: parser parse: 'fo' to: $f end: 1. + self assert: parser parse: 'fob' to: $f end: 1. + self assert: parser parse: 'ffoo' to: $f end: 1. + + self assert: parser fail: ''. + self assert: parser fail: 'foo' +! + +testNot + | parser | + parser := 'foo' asParser flatten , 'bar' asParser flatten not. + + self assert: parser parse: 'foobaz' to: #('foo' nil) end: 3. + self assert: parser fail: 'foobar' +! + +testOptional + | parser | + parser := $a asParser optional. + + self assert: parser parse: '' to: nil. + self assert: parser parse: 'a' to: $a. + + self assert: parser parse: 'aa' to: $a end: 1. + self assert: parser parse: 'ab' to: $a end: 1. + self assert: parser parse: 'b' to: nil end: 0. + self assert: parser parse: 'bb' to: nil end: 0. + self assert: parser parse: 'ba' to: nil end: 0 +! + +testPluggable + | block parser | + block := [ :stream | stream position ]. + parser := block asParser. + self assert: parser block = block +! + +testPlus + | parser | + parser := $a asParser plus. + + self assert: parser min = 1. + self assert: parser max > parser min. + + self assert: parser parse: 'a' to: #($a). + self assert: parser parse: 'aa' to: #($a $a). + self assert: parser parse: 'aaa' to: #($a $a $a). + + self assert: parser parse: 'ab' to: #($a) end: 1. + self assert: parser parse: 'aab' to: #($a $a) end: 2. + self assert: parser parse: 'aaab' to: #($a $a $a) end: 3. + + self assert: parser fail: ''. + self assert: parser fail: 'b'. + self assert: parser fail: 'ba' +! + +testPlusGreedy + | limit parser | + limit := #digit asParser. + parser := #word asParser plusGreedy: limit. + + self assert: parser min = 1. + self assert: parser max > parser min. + self assert: parser limit = limit. + self assert: parser children size = 2. + self assert: parser children last = limit. + + self assert: parser fail: ''. + self assert: parser fail: '1'. + self assert: parser fail: 'a'. + self assert: parser fail: 'ab'. + + self assert: parser parse: 'a1' to: #($a) end: 1. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. + self assert: parser parse: 'a12' to: #($a $1) end: 2. + self assert: parser parse: 'ab12' to: #($a $b $1) end: 3. + self assert: parser parse: 'abc12' to: #($a $b $c $1) end: 4. + self assert: parser parse: 'a123' to: #($a $1 $2) end: 3. + self assert: parser parse: 'ab123' to: #($a $b $1 $2) end: 4. + self assert: parser parse: 'abc123' to: #($a $b $c $1 $2) end: 5. +! + +testPlusLazy + | limit parser | + limit := #digit asParser. + parser := #word asParser plusLazy: limit. + + self assert: parser min = 1. + self assert: parser max > parser min. + self assert: parser limit = limit. + self assert: parser children size = 2. + self assert: parser children last = limit. + + self assert: parser fail: ''. + self assert: parser fail: '1'. + self assert: parser fail: 'a'. + self assert: parser fail: 'ab'. + + self assert: parser parse: 'a1' to: #($a) end: 1. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. + self assert: parser parse: 'a12' to: #($a) end: 1. + self assert: parser parse: 'ab12' to: #($a $b) end: 2. + self assert: parser parse: 'abc12' to: #($a $b $c) end: 3. + self assert: parser parse: 'a123' to: #($a) end: 1. + self assert: parser parse: 'ab123' to: #($a $b) end: 2. + self assert: parser parse: 'abc123' to: #($a $b $c) end: 3 +! + +testSeparatedBy + | parser | + parser := $a asParser separatedBy: $b asParser. + + self assert: parser parse: 'a' to: #($a). + self assert: parser parse: 'aba' to: #($a $b $a). + self assert: parser parse: 'ababa' to: #($a $b $a $b $a). + + self assert: parser parse: 'ab' to: #($a) end: 1. + self assert: parser parse: 'abab' to: #($a $b $a) end: 3. + self assert: parser parse: 'ac' to: #($a) end: 1. + self assert: parser parse: 'abac' to: #($a $b $a) end: 3. + + self assert: parser fail: ''. + self assert: parser fail: 'c' +! + +testSeparatedByWithoutSeparators + | parser | + parser := ($a asParser separatedBy: $b asParser) + withoutSeparators. + + self assert: parser parse: 'a' to: #($a). + self assert: parser parse: 'aba' to: #($a $a). + self assert: parser parse: 'ababa' to: #($a $a $a). + + self assert: parser parse: 'ab' to: #($a) end: 1. + self assert: parser parse: 'abab' to: #($a $a) end: 3. + self assert: parser parse: 'ac' to: #($a) end: 1. + self assert: parser parse: 'abac' to: #($a $a) end: 3. + + self assert: parser fail: ''. + self assert: parser fail: 'c' +! + +testSequence + | parser | + parser := $a asParser , $b asParser. + + self assert: parser parse: 'ab' to: #($a $b). + + self assert: parser parse: 'aba' to: #($a $b) end: 2. + self assert: parser parse: 'abb' to: #($a $b) end: 2. + + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser fail: 'aa'. + self assert: parser fail: 'ba'. + self assert: parser fail: 'bab' +! + +testStar + | parser | + parser := $a asParser star. + + self assert: parser min = 0. + self assert: parser max > parser min. + + self assert: parser parse: '' to: #(). + self assert: parser parse: 'a' to: #($a). + self assert: parser parse: 'aa' to: #($a $a). + self assert: parser parse: 'aaa' to: #($a $a $a). + + self assert: parser parse: 'b' to: #() end: 0. + self assert: parser parse: 'ab' to: #($a) end: 1. + self assert: parser parse: 'aab' to: #($a $a) end: 2. + self assert: parser parse: 'aaab' to: #($a $a $a) end: 3 +! + +testStarGreedy + | limit parser | + limit := #digit asParser. + parser := #word asParser starGreedy: limit. + + self assert: parser min = 0. + self assert: parser max > parser min. + self assert: parser limit = limit. + self assert: parser children size = 2. + self assert: parser children last = limit. + + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser fail: 'ab'. + + self assert: parser parse: '1' to: #() end: 0. + self assert: parser parse: 'a1' to: #($a) end: 1. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. + self assert: parser parse: '12' to: #($1) end: 1. + self assert: parser parse: 'a12' to: #($a $1) end: 2. + self assert: parser parse: 'ab12' to: #($a $b $1) end: 3. + self assert: parser parse: 'abc12' to: #($a $b $c $1) end: 4. + self assert: parser parse: '123' to: #($1 $2) end: 2. + self assert: parser parse: 'a123' to: #($a $1 $2) end: 3. + self assert: parser parse: 'ab123' to: #($a $b $1 $2) end: 4. + self assert: parser parse: 'abc123' to: #($a $b $c $1 $2) end: 5 +! + +testStarLazy + | limit parser | + limit := #digit asParser. + parser := #word asParser starLazy: limit. + + self assert: parser min = 0. + self assert: parser max > parser min. + self assert: parser limit = limit. + self assert: parser children size = 2. + self assert: parser children last = limit. + + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser fail: 'ab'. + + self assert: parser parse: '1' to: #() end: 0. + self assert: parser parse: 'a1' to: #($a) end: 1. + self assert: parser parse: 'ab1' to: #($a $b) end: 2. + self assert: parser parse: 'abc1' to: #($a $b $c) end: 3. + self assert: parser parse: '12' to: #() end: 0. + self assert: parser parse: 'a12' to: #($a) end: 1. + self assert: parser parse: 'ab12' to: #($a $b) end: 2. + self assert: parser parse: 'abc12' to: #($a $b $c) end: 3. + self assert: parser parse: '123' to: #() end: 0. + self assert: parser parse: 'a123' to: #($a) end: 1. + self assert: parser parse: 'ab123' to: #($a $b) end: 2. + self assert: parser parse: 'abc123' to: #($a $b $c) end: 3 +! + +testTimes + | parser | + parser := $a asParser times: 2. + + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser parse: 'aa' to: #($a $a). + self assert: parser parse: 'aaa' to: #($a $a) end: 2 +! + +testUnresolved + | parser | + parser := PPUnresolvedParser new. + + self assert: parser isUnresolved. + self should: [ parser parse: '' ] raise: Error. + self should: [ parser parse: 'a' ] raise: Error. + self should: [ parser parse: 'ab' ] raise: Error. + + parser := nil asParser. + self deny: parser isUnresolved +! + +testWrapped + | parser | + parser := $a asParser wrapped. + + self assert: parser parse: 'a' to: $a. + self assert: parser fail: 'b'. + + parser := (($a asParser , $b asParser ) wrapped , $c asParser). + self assert: parser parse: 'abc' to: #(#($a $b) $c) +! + +testXor + | parser | + parser := ($a asParser / $b asParser) + | ($b asParser / $c asParser). + + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'c' to: $c. + + self assert: parser fail: ''. + self assert: parser fail: 'b'. + self assert: parser fail: 'd'. + + " truly symmetric " + parser := ($b asParser / $c asParser) + | ($a asParser / $b asParser). + + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'c' to: $c. + + self assert: parser fail: ''. + self assert: parser fail: 'b'. + self assert: parser fail: 'd' +! ! + +!PPParserTest methodsFor:'testing-accessing'! + +testNamed + | parser | + parser := PPSequenceParser new. + self assert: parser name isNil. + + parser := PPChoiceParser named: 'choice'. + self assert: parser name = 'choice'. + + parser := $* asParser name: 'star'. + self assert: parser name = 'star' +! + +testPrint + | parser | + parser := PPParser new. + self assert: (parser printString findString: 'PPParser') > 0. + + parser := PPParser named: 'choice'. + self assert: (parser printString findString: 'PPParser(choice') > 0. + + parser := PPLiteralObjectParser on: $a. + self assert: (parser printString findString: '$a') > 0. + + parser := PPFailingParser message: 'error'. + self assert: (parser printString findString: 'error') > 0. + + parser := PPPredicateObjectParser on: [ :c | true ] message: 'error'. + self assert: (parser printString findString: 'error') > 0 +! ! + +!PPParserTest methodsFor:'testing-fixtures'! + +testSideEffectChoice + "Adding another element to a choice should create a copy, otherwise we get unwanted side-effects." + + | p1 p2 p3 | + p1 := $a asParser. + p2 := p1 / $b asParser. + p3 := p1 / $c asParser. + + self assert: p1 parse: 'a'. + self assert: p1 fail: 'b'. + self assert: p1 fail: 'c'. + + self assert: p2 parse: 'a'. + self assert: p2 parse: 'b'. + self assert: p2 fail: 'c'. + + self assert: p3 parse: 'a'. + self assert: p3 fail: 'b'. + self assert: p3 parse: 'c' +! + +testSideEffectListCopy + | old new | + old := $a asParser , $b asParser. + new := old copy. + + self deny: old == new. + self deny: old children == new children. + self assert: old children first == new children first. + self assert: old children last == new children last +! + +testSideEffectSequence + "Adding another element to a sequence should create a copy, otherwise we get unwanted side-effects." + + | p1 p2 p3 | + p1 := $a asParser. + p2 := p1 , $b asParser. + p3 := p1 , $c asParser. + + self assert: p1 parse: 'a'. + self assert: p1 parse: 'ab' end: 1. + self assert: p1 parse: 'ac' end: 1. + + self assert: p2 fail: 'a'. + self assert: p2 parse: 'ab'. + self assert: p2 fail: 'ac'. + + self assert: p3 fail: 'a'. + self assert: p3 fail: 'ab'. + self assert: p3 parse: 'ac' +! ! + +!PPParserTest methodsFor:'testing-mapping'! + +testAction + | block parser | + block := [ :char | char asUppercase ]. + parser := #any asParser ==> block. + self assert: parser block = block. + + self assert: parser parse: 'a' to: $A. + self assert: parser parse: 'b' to: $B +! + +testAnswer + | parser | + parser := $a asParser answer: $b. + + self assert: parser parse: 'a' to: $b. + + self assert: parser fail: ''. + self assert: parser fail: 'b' +! + +testFlatten + | parser | + parser := $a asParser flatten. + + self assert: parser parse: 'a' to: 'a'. + self assert: parser parse: #($a) to: #($a). + + self assert: parser fail: ''. + self assert: parser fail: 'b' +! + +testFoldLeft2 + | parser | + parser := #any asParser star + foldLeft: [ :a :b | Array with: a with: b ]. + + self assert: parser parse: #(a) to: #a. + self assert: parser parse: #(a b) to: #(a b). + self assert: parser parse: #(a b c) to: #((a b) c). + self assert: parser parse: #(a b c d) to: #(((a b) c) d). + self assert: parser parse: #(a b c d e) to: #((((a b) c) d) e) +! + +testFoldLeft3 + | parser | + parser := #any asParser star + foldLeft: [ :a :b :c | Array with: a with: b with: c ]. + + self assert: parser parse: #(a) to: #a. + self assert: parser parse: #(a b c) to: #(a b c). + self assert: parser parse: #(a b c d e) to: #((a b c) d e) +! + +testFoldRight2 + | parser | + parser := #any asParser star + foldRight: [ :a :b | Array with: a with: b ]. + + self assert: parser parse: #(a) to: #a. + self assert: parser parse: #(a b) to: #(a b). + self assert: parser parse: #(a b c) to: #(a (b c)). + self assert: parser parse: #(a b c d) to: #(a (b (c d))). + self assert: parser parse: #(a b c d e) to: #(a (b (c (d e)))) +! + +testFoldRight3 + | parser | + parser := #any asParser star + foldRight: [ :a :b :c | Array with: a with: b with: c ]. + + self assert: parser parse: #(a) to: #a. + self assert: parser parse: #(a b c) to: #(a b c). + self assert: parser parse: #(a b c d e) to: #(a b (c d e)) +! + +testMap1 + | parser | + parser := #any asParser + map: [ :a | Array with: a ]. + + self assert: parser parse: #(a) to: #(a) +! + +testMap2 + | parser | + parser := (#any asParser , #any asParser) + map: [ :a :b | Array with: b with: a ]. + + self assert: parser parse: #(a b) to: #(b a) +! + +testMap3 + | parser | + parser := (#any asParser , #any asParser , #any asParser) + map: [ :a :b :c | Array with: c with: b with: a ]. + + self assert: parser parse: #(a b c) to: #(c b a) +! + +testMapFail1 + self + should: [ #any asParser map: [ ] ] + raise: Error. + self + should: [ #any asParser map: [ :a :b | ] ] + raise: Error +! + +testMapFail2 + self + should: [ (#any asParser , #any asParser) map: [ :a | ] ] + raise: Error. + self + should: [ (#any asParser , #any asParser) map: [ :a :b :c | ] ] + raise: Error +! + +testPermutation + | parser | + parser := #any asParser , #any asParser , #any asParser. + + self assert: (parser permutation: #()) parse: '123' to: #(). + self assert: (parser permutation: #(1)) parse: '123' to: #($1). + self assert: (parser permutation: #(1 3)) parse: '123' to: #($1 $3). + self assert: (parser permutation: #(3 1)) parse: '123' to: #($3 $1). + self assert: (parser permutation: #(2 2)) parse: '123' to: #($2 $2). + self assert: (parser permutation: #(3 2 1)) parse: '123' to: #($3 $2 $1). + + self should: [ parser permutation: #(0) ] raise: Error. + self should: [ parser permutation: #(4) ] raise: Error. + self should: [ parser permutation: #($2) ] raise: Error +! + +testToken + | parser | + parser := $a asParser token. + self assert: parser tokenClass = PPToken. + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser fail: 'b'. + self assert: parser fail: ''. + + parser := $a asParser token: PPToken. + self assert: parser tokenClass = PPToken. + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser fail: ''. + self assert: parser fail: 'b' +! + +testTrim + | parser | + parser := $a asParser token trim. + + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser parse: 'a ' toToken: 1 stop: 1. + self assert: parser parse: 'a ' toToken: 1 stop: 1. + self assert: parser parse: 'a ' toToken: 1 stop: 1. + self assert: parser parse: 'a + ' toToken: 1 stop: 1. + + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser parse: ' a' toToken: 2 stop: 2. + self assert: parser parse: ' a' toToken: 2 stop: 2. + self assert: parser parse: ' a' toToken: 5 stop: 5. + self assert: parser parse: ' +a' toToken: 5 stop: 5. + + self assert: parser parse: 'aa' toToken: 1 stop: 1 end: 1. + self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 2. + self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 3. + + self assert: parser fail: ''. + self assert: parser fail: 'b' +! + +testTrimBlanks + | parser | + parser := $a asParser token trimBlanks. + + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser parse: 'a ' toToken: 1 stop: 1. + self assert: parser parse: 'a ' toToken: 1 stop: 1. + self assert: parser parse: 'a ' toToken: 1 stop: 1. + + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser parse: ' a' toToken: 2 stop: 2. + self assert: parser parse: ' a' toToken: 2 stop: 2. + self assert: parser parse: ' a' toToken: 5 stop: 5. + + self assert: parser parse: 'aa' toToken: 1 stop: 1 end: 1. + self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 2. + self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 3. + + self assert: parser fail: ''. + self assert: parser fail: ' +'. + self assert: parser fail: ' +a'. + self assert: parser fail: 'b'. +! + +testTrimCustom + | parser | + parser := $a asParser token trim: $b asParser. + + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser parse: 'ab' toToken: 1 stop: 1. + self assert: parser parse: 'abb' toToken: 1 stop: 1. + + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser parse: 'ba' toToken: 2 stop: 2. + self assert: parser parse: 'bba' toToken: 3 stop: 3. + + self assert: parser parse: 'aa' toToken: 1 stop: 1 end: 1. + self assert: parser parse: 'ab' toToken: 1 stop: 1 end: 2. + self assert: parser parse: 'abba' toToken: 1 stop: 1 end: 3. + + self assert: parser fail: ''. + self assert: parser fail: 'b' +! + +testTrimSpaces + | parser | + parser := $a asParser token trimSpaces. + + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser parse: 'a ' toToken: 1 stop: 1. + self assert: parser parse: 'a ' toToken: 1 stop: 1. + self assert: parser parse: 'a ' toToken: 1 stop: 1. + self assert: parser parse: 'a + ' toToken: 1 stop: 1. + + self assert: parser parse: 'a' toToken: 1 stop: 1. + self assert: parser parse: ' a' toToken: 2 stop: 2. + self assert: parser parse: ' a' toToken: 2 stop: 2. + self assert: parser parse: ' a' toToken: 5 stop: 5. + self assert: parser parse: ' +a' toToken: 5 stop: 5. + + self assert: parser parse: 'aa' toToken: 1 stop: 1 end: 1. + self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 2. + self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 3. + + self assert: parser fail: ''. + self assert: parser fail: 'b' +! + +testWrapping + | parser result | + parser := #digit asParser plus >=> [ :stream :cc | + Array + with: stream position + with: cc value + with: stream position ]. + + self assert: parser parse: '1' to: #(0 ($1) 1). + self assert: parser parse: '12' to: #(0 ($1 $2) 2). + self assert: parser parse: '123' to: #(0 ($1 $2 $3) 3). + + result := parser parse: 'a'. + self assert: result first = 0. + self assert: result second isPetitFailure. + self assert: result last = 0 +! ! + +!PPParserTest methodsFor:'testing-properties'! + +testHasProperty + | parser | + parser := PPParser new. + self deny: (parser hasProperty: #foo). + parser propertyAt: #foo put: 123. + self assert: (parser hasProperty: #foo) +! + +testPostCopy + | parser copy | + parser := PPParser new. + parser propertyAt: #foo put: true. + copy := parser copy. + copy propertyAt: #foo put: false. + self assert: (parser propertyAt: #foo). + self deny: (copy propertyAt: #foo) +! + +testPropertyAt + | parser | + parser := PPParser new. + self should: [ parser propertyAt: #foo ] raise: Error. + parser propertyAt: #foo put: true. + self assert: (parser propertyAt: #foo) +! + +testPropertyAtIfAbsent + | parser | + parser := PPParser new. + self assert: (parser propertyAt: #foo ifAbsent: [ true ]). + parser propertyAt: #foo put: true. + self assert: (parser propertyAt: #foo ifAbsent: [ false ]) +! + +testPropertyAtIfAbsentPut + | parser | + parser := PPParser new. + self assert: (parser propertyAt: #foo ifAbsentPut: [ true ]). + self assert: (parser propertyAt: #foo ifAbsentPut: [ false ]) +! + +testRemoveProperty + | parser | + parser := PPParser new. + self should: [ parser removeProperty: #foo ] raise: Error. + parser propertyAt: #foo put: true. + self assert: (parser removeProperty: #foo) +! + +testRemovePropertyIfAbsent + | parser | + parser := PPParser new. + self assert: (parser removeProperty: #foo ifAbsent: [ true ]). + parser propertyAt: #foo put: true. + self assert: (parser removeProperty: #foo ifAbsent: [ false ]) +! ! + +!PPParserTest methodsFor:'testing-utilities'! + +testChildren + | p1 p2 p3 | + p1 := #lowercase asParser. + p2 := p1 ==> #asUppercase. + p3 := PPUnresolvedParser new. + p3 def: p2 / p3. + self assert: p1 children isEmpty. + self assert: p2 children size = 1. + self assert: p3 children size = 2 +! + +testFailure + | failure | + failure := PPFailure message: 'Error' at: 3. + + self assert: failure message = 'Error'. + self assert: failure position = 3. + self assert: failure isPetitFailure. + + self deny: 4 isPetitFailure. + self deny: 'foo' isPetitFailure +! + +testListConstructor + | p1 p2 p3 | + p1 := PPChoiceParser with: $a asParser. + p2 := PPChoiceParser with: $a asParser with: $b asParser. + p3 := PPChoiceParser withAll: (Array with: $a asParser with: $b asParser with: $c asParser). + + self assert: p1 children size = 1. + self assert: p2 children size = 2. + self assert: p3 children size = 3 +! + +testMatches + | parser | + parser := $a asParser. + + self assert: (parser matches: 'a'). + self deny: (parser matches: 'b'). + + self assert: (parser matches: 'a' readStream). + self deny: (parser matches: 'b' readStream) +! + +testMatchesIn + | parser result | + parser := $a asParser. + + result := parser matchesIn: 'abba'. + self assert: result size = 2. + self assert: result first = $a. + self assert: result last = $a. + + result := parser matchesIn: 'baaah'. + self assert: result size = 3. + self assert: result first = $a. + self assert: result last = $a +! + +testMatchesInEmpty + "Empty matches should properly advance and match at each position and at the end." + + | parser result | + parser := [ :stream | stream position ] asParser. + + result := parser matchesIn: '123'. + self assert: result asArray = #(0 1 2 3) +! + +testMatchesInOverlapping + "Matches that overlap should be properly reported." + + | parser result | + parser := #digit asParser , #digit asParser. + + result := parser matchesIn: 'a123b'. + self assert: result size = 2. + self assert: result first = #($1 $2). + self assert: result last = #($2 $3) +! + +testMatchesSkipIn + | parser result | + parser := $a asParser. + + result := parser matchesSkipIn: 'abba'. + self assert: result size = 2. + self assert: result first = $a. + self assert: result last = $a. + + result := parser matchesSkipIn: 'baaah'. + self assert: result size = 3. + self assert: result first = $a. + self assert: result last = $a +! + +testMatchesSkipInOverlapping + "Matches that overlap should be properly reported." + + | parser result | + parser := #digit asParser , #digit asParser. + + result := parser matchesSkipIn: 'a123b'. + self assert: result size = 1. + self assert: result first = #($1 $2) +! + +testMatchingRangesIn + | input parser result | + input := 'a12b3'. + parser := #digit asParser plus. + result := parser matchingRangesIn: input. + result := result collect: [ :each | input copyFrom: each first to: each last ]. + self assert: result size = 3. + self assert: result first = '12'. + self assert: result second = '2'. + self assert: result last = '3' +! + +testMatchingSkipRangesIn + | input parser result | + input := 'a12b3'. + parser := #digit asParser plus. + result := parser matchingSkipRangesIn: input. + result := result collect: [ :each | input copyFrom: each first to: each last ]. + self assert: result size = 2. + self assert: result first = '12'. + self assert: result last = '3' +! + +testParse + | parser result | + parser := $a asParser. + + self assert: (parser parse: 'a') = $a. + self assert: (result := parser parse: 'b') isPetitFailure. + self assert: (result message findString: '$a') > 0. + self assert: (result message findString: 'expected') > 0. + self assert: (result position = 0). + + self assert: (parser parse: 'a' readStream) = $a. + self assert: (result := parser parse: 'b' readStream) isPetitFailure. + self assert: (result message findString: '$a') > 0. + self assert: (result message findString: 'expected') > 0. + self assert: (result position = 0) +! + +testParseOnError0 + | parser result seen | + parser := $a asParser. + + result := parser parse: 'a' onError: [ self signalFailure: 'Not supposed to report an error' ]. + self assert: result = $a. + + result := parser parse: 'b' onError: [ seen := true ]. + self assert: result. + self assert: seen +! + +testParseOnError1 + | parser result seen | + parser := $a asParser. + + result := parser parse: 'a' onError: [ self signalFailure: 'Not supposed to report an error' ]. + self assert: result = $a. + + result := parser parse: 'b' onError: [ :failure | + self assert: (failure position = 0). + self assert: (failure message findString: '$a') > 0. + self assert: (failure message findString: 'expected') > 0. + seen := true ]. + self assert: result. + self assert: seen +! + +testParseOnError2 + | parser result seen | + parser := $a asParser. + + result := parser parse: 'a' onError: [ self signalFailure: 'Not supposed to report an error' ]. + self assert: result = $a. + + result := parser parse: 'b' onError: [ :msg :pos | + self assert: (msg findString: '$a') > 0. + self assert: (msg findString: 'expected') > 0. + self assert: pos = 0. + seen := true ]. + self assert: result. + self assert: seen +! + +testParser + | parser | + parser := PPParser new. + + self assert: parser isPetitParser. + + self deny: 4 isPetitParser. + self deny: 'foo' isPetitParser +! ! + +!PPParserTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParserTest.st,v 1.4 2014-03-04 14:34:21 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParserTest.st,v 1.4 2014-03-04 14:34:21 cg Exp $' +! + +version_SVN + ^ '$Id: PPParserTest.st,v 1.4 2014-03-04 14:34:21 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPPredicateTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPPredicateTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,313 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPAbstractParserTest subclass:#PPPredicateTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPPredicateTest methodsFor:'private'! + +charactersDo: aBlock + "cg: isn't 256 one too many?" + + Smalltalk isSmalltalkX ifTrue:[ + 0 to: 255 do: [ :index | aBlock value: (Character codePoint: index) ] + ] ifFalse:[ + 1 to: 256 do: [ :index | aBlock value: (Character codePoint: index) ] + ]. +! ! + +!PPPredicateTest methodsFor:'testing'! + +testOnMessage + | block parser | + block := [ :char | char = $* ]. + parser := PPPredicateObjectParser on: block message: 'starlet'. + self assert: parser block = block. + self assert: parser message = 'starlet'. + + self assertCharacterSets: parser. + self assert: parser parse: '*' to: $*. + self assert: parser parse: '**' to: $* end: 1. + self assert: parser fail: ''. + self assert: parser fail: '1'. + self assert: parser fail: 'a' +! ! + +!PPPredicateTest methodsFor:'testing-chars'! + +testBlank + | parser cr| + parser := #blank asParser. + self assertCharacterSets: parser. + self assert: parser parse: (String with: Character space) to: Character space. + self assert: parser parse: (String with: Character tab) to: Character tab. + self assert: parser fail: ''. + self assert: parser fail: '1'. + cr := Smalltalk isSmalltalkX + ifTrue:[Character return] + ifFalse:[Character cr]. + self assert: parser fail: (String with: cr) +! + +testChar + | parser | + parser := $* asParser. + self assertCharacterSets: parser. + self assert: parser parse: '*' to: $*. + self assert: parser parse: '**' to: $* end: 1. + self assert: parser fail: ''. + self assert: parser fail: '1'. + self assert: parser fail: 'a' +! + +testCr + | parser cr | + + cr := Smalltalk isSmalltalkX + ifTrue:[Character return] + ifFalse:[Character cr]. + + parser := #cr asParser. + self assertCharacterSets: parser. + self assert: parser parse: (String with: cr) to: cr +! + +testDigit + | parser | + parser := #digit asParser. + self assertCharacterSets: parser. + self assert: parser parse: '0' to: $0. + self assert: parser parse: '9' to: $9. + self assert: parser fail: ''. + self assert: parser fail: 'a' +! + +testHex + | parser | + parser := #hex asParser. + self assertCharacterSets: parser. + self assert: parser parse: '0' to: $0. + self assert: parser parse: '5' to: $5. + self assert: parser parse: '9' to: $9. + self assert: parser parse: 'A' to: $A. + self assert: parser parse: 'D' to: $D. + self assert: parser parse: 'F' to: $F. + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'e' to: $e. + self assert: parser parse: 'f' to: $f. + self assert: parser fail: ''. + self assert: parser fail: 'g' +! + +testLetter + | parser | + parser := #letter asParser. + self assertCharacterSets: parser. + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'Z' to: $Z. + self assert: parser fail: ''. + self assert: parser fail: '0' +! + +testLf + | parser | + parser := #lf asParser. + self assertCharacterSets: parser. + self assert: parser parse: (String with: Character lf) to: Character lf +! + +testLowercase + | parser | + parser := #lowercase asParser. + self assertCharacterSets: parser. + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'z' to: $z. + self assert: parser fail: ''. + self assert: parser fail: 'A'. + self assert: parser fail: '0' +! + +testNewline + | parser cr| + cr := Smalltalk isSmalltalkX + ifTrue:[Character return] + ifFalse:[Character cr]. + parser := #newline asParser. + self assertCharacterSets: parser. + self assert: parser parse: (String with: cr) to: cr. + self assert: parser parse: (String with: Character lf) to: Character lf. + self assert: parser fail: ' ' +! + +testPunctuation + | parser | + parser := #punctuation asParser. + self assertCharacterSets: parser. + self assert: parser parse: '.' to: $.. + self assert: parser parse: ',' to: $,. + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser fail: '1' +! + +testSpace + | parser | + parser := #space asParser. + self assertCharacterSets: parser. + self assert: parser parse: (String with: Character tab) to: Character tab. + self assert: parser parse: ' ' to: Character space. + self assert: parser fail: ''. + self assert: parser fail: 'a' +! + +testTab + | parser | + parser := #tab asParser. + self assertCharacterSets: parser. + self assert: parser parse: (String with: Character tab) to: Character tab +! + +testUppercase + | parser | + parser := #uppercase asParser. + self assertCharacterSets: parser. + self assert: parser parse: 'A' to: $A. + self assert: parser parse: 'Z' to: $Z. + self assert: parser fail: ''. + self assert: parser fail: 'a'. + self assert: parser fail: '0' +! + +testWord + | parser | + parser := #word asParser. + self assertCharacterSets: parser. + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'A' to: $A. + self assert: parser parse: '0' to: $0. + self assert: parser fail: ''. + self assert: parser fail: '-' +! ! + +!PPPredicateTest methodsFor:'testing-objects'! + +testAny + | parser | + parser := #any asParser. + self assertCharacterSets: parser. + self assert: parser parse: ' ' to: $ . + self assert: parser parse: '1' to: $1. + self assert: parser parse: 'a' to: $a. + self assert: parser fail: '' +! + +testAnyExceptAnyOf + | parser | + parser := PPPredicateObjectParser anyExceptAnyOf: #($: $,). + self assertCharacterSets: parser. + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'z' to: $z. + self assert: parser fail: ':'. + self assert: parser fail: ',' +! + +testAnyOf + | parser | + parser := PPPredicateObjectParser anyOf: #($a $z). + self assertCharacterSets: parser. + self assert: parser parse: 'a' to: $a. + self assert: parser parse: 'z' to: $z. + self assert: parser fail: 'x' +! + +testBetweenAnd + | parser | + parser := PPPredicateObjectParser between: $b and: $d. + self assertCharacterSets: parser. + self assert: parser fail: 'a'. + self assert: parser parse: 'b' to: $b. + self assert: parser parse: 'c' to: $c. + self assert: parser parse: 'd' to: $d. + self assert: parser fail: 'e' +! + +testExpect + | parser | + parser := PPPredicateObjectParser expect: $a. + self assertCharacterSets: parser. + self assert: parser parse: 'a' to: $a. + self assert: parser fail: 'b'. + self assert: parser fail: '' +! ! + +!PPPredicateTest methodsFor:'testing-sequence'! + +testSequenceParser + | parser | + parser := PPPredicateSequenceParser + on: [ :value | value first isUppercase ] + message: 'uppercase 3 letter words' + size: 3. + self assert: parser size = 3. + self assert: parser parse: 'Abc'. + self assert: parser parse: 'ABc'. + self assert: parser parse: 'ABC'. + self assert: parser fail: 'abc'. + self assert: parser fail: 'aBC'. + self assert: parser fail: 'Ab'. + + parser := parser negate. + self assert: parser size = 3. + self assert: parser fail: 'Abc'. + self assert: parser fail: 'ABc'. + self assert: parser fail: 'ABC'. + self assert: parser parse: 'abc'. + self assert: parser parse: 'aBC'. + self assert: parser fail: 'Ab' +! ! + +!PPPredicateTest methodsFor:'utilities'! + +assertCharacterSets: aParser + "Assert the character set of aParser does not overlap with the character set with the negated parser, and that they both cover the complete character space." + + | positives negatives | + positives := self parsedCharacterSet: aParser. + negatives := self parsedCharacterSet: aParser negate. + self charactersDo: [ :char | + | positive negative | + positive := positives includes: char. + negative := negatives includes: char. + self + assert: ((positive and: [ negative not ]) + or: [ positive not and: [ negative ] ]) + description: char printString , ' should be in exactly one set' ] +! + +parsedCharacterSet: aParser + | result | + result := WriteStream on: String new. + self charactersDo: [ :char | + (aParser matches: (String with: char)) + ifTrue: [ result nextPut: char ] ]. + ^ result contents +! ! + +!PPPredicateTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPPredicateTest.st,v 1.6 2014-03-04 20:09:46 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPPredicateTest.st,v 1.6 2014-03-04 20:09:46 cg Exp $' +! + +version_SVN + ^ '$Id: PPPredicateTest.st,v 1.6 2014-03-04 20:09:46 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPScriptingTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPScriptingTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,124 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPAbstractParserTest subclass:#PPScriptingTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + +PPScriptingTest comment:'These are some simple demo-scripts of parser combinators for the compiler construction course. http://www.iam.unibe.ch/~scg/Teaching/CC/index.html' +! + + +!PPScriptingTest methodsFor:'examples'! + +expressionInterpreter + "Same as #expressionInterpreter but with semantic actions." + + | mul prim add dec | + add := PPUnresolvedParser new. + mul := PPUnresolvedParser new. + prim := PPUnresolvedParser new. + dec := ($0 to: $9) asParser ==> [ :token | token codePoint - $0 codePoint ]. + add def: ((mul , $+ asParser , add) ==> [ :nodes | (nodes at: 1) + (nodes at: 3) ]) + / mul. + mul def: ((prim , $* asParser , mul) ==> [ :nodes | (nodes at: 1) * (nodes at: 3) ]) + / prim. + prim def: (($( asParser , add , $) asParser) ==> [ :nodes | nodes at: 2 ]) + / dec. + ^ add end +! + +expressionParser + "Simple demo of scripting an expression parser." + + | mul prim add dec | + add := PPUnresolvedParser new. + mul := PPUnresolvedParser new. + prim := PPUnresolvedParser new. + dec := ($0 to: $9) asParser. + add def: (mul , $+ asParser , add) + / mul. + mul def: (prim , $* asParser , mul) + / prim. + prim def: ($( asParser , add , $) asParser) + / dec. + ^ add end +! + +straightLineParser + | goal stm stmList id char dec exp expList mulExp primExp nonzero num lower upper | + goal := PPUnresolvedParser new. + stmList := PPUnresolvedParser new. + stm := PPUnresolvedParser new. + exp := PPUnresolvedParser new. + expList := PPUnresolvedParser new. + mulExp := PPUnresolvedParser new. + primExp := PPUnresolvedParser new. + + lower := ($a to: $z) asParser. + upper := ($A to: $Z) asParser. + char := lower / upper. + nonzero := ($1 to: $9) asParser. + dec := ($0 to: $9) asParser. + id := char, ( char / dec ) star. + num := $0 asParser / ( nonzero, dec star). + + goal def: stmList end. + stmList def: stm , ( $; asParser, stm ) star. + stm def: ( id, ':=' asParser, exp ) + / ( 'print' asParser, $( asParser, expList, $) asParser ). + exp def: mulExp, ( ( $+ asParser / $- asParser ), mulExp ) star. + expList def: exp, ( $, asParser, exp ) star. + mulExp def: primExp, ( ( $* asParser / $/ asParser ), primExp ) star. + primExp def: id + / num + / ( $( asParser, stmList, $, asParser, exp, $) asParser ). + ^ goal +! ! + +!PPScriptingTest methodsFor:'tests'! + +testExpressionInterpreter + self + assert: self expressionInterpreter + parse: '2*(3+4)' + to: 14 +! + +testExpressionParser + self + assert: self expressionParser + parse: '2*(3+4)' + to: #($2 $* ($( ($3 $+ $4) $))) +! + +testSLassign + + self assert: self straightLineParser + parse: 'abc:=1' + to: #(#($a #($b $c) ':=' #(#(#($1 #()) #()) #())) #()) +! + +testSLprint + self + assert: self straightLineParser + parse: 'print(3,4)' + to: #(('print' $( ((($3 ()) ()) () (($, ((($4 ()) ()) ())))) $)) ()) +! ! + +!PPScriptingTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPScriptingTest.st,v 1.4 2014-03-04 14:34:23 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPScriptingTest.st,v 1.4 2014-03-04 14:34:23 cg Exp $' +! + +version_SVN + ^ '$Id: PPScriptingTest.st,v 1.4 2014-03-04 14:34:23 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/PPTokenTest.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/PPTokenTest.st Fri Oct 03 01:36:33 2014 +0100 @@ -0,0 +1,168 @@ +"{ Package: 'stx:goodies/petitparser' }" + +PPAbstractParserTest subclass:#PPTokenTest + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'PetitTests-Tests' +! + + +!PPTokenTest methodsFor:'accessing'! + +identifier + ^ #word asParser plus token +! ! + +!PPTokenTest methodsFor:'testing'! + +testCollection + | input result | + input := 'foo '. + result := self + parse: input + using: self identifier. + self assert: (result collection = input). + self assert: (result collection == input) +! + +testInitialize + PPToken initialize +! + +testNew + self should: [ PPToken new ] raise: Error. + +! + +testPrinting + | result | + result := PPToken on: 'var'. + self assert: (result printString findString: 'PPToken[1,3]') > 0 +! + +testSize + | result | + result := self + parse: 'foo' + using: self identifier. + self assert: result size = 3 +! + +testStart + | result | + result := self + parse: 'foo' + using: self identifier. + self assert: result start = 1 +! + +testStop + | result | + result := self + parse: 'foo' + using: self identifier. + self assert: result stop = 3 +! + +testValue + | result | + result := PPToken on: 'var'. + self should: [ result value ] raise: Notification +! ! + +!PPTokenTest methodsFor:'testing-comparing'! + +testEquality + | token1 token2 | + token1 := self parse: 'foo' using: self identifier. + token2 := self parse: 'foo' using: self identifier. + self deny: token1 == token2. + self assert: token1 = token2. + self assert: token1 hash = token2 hash. +! ! + +!PPTokenTest methodsFor:'testing-copying'! + +testCopyFromTo + | result other | + result := PPToken on: 'abc'. + other := result copyFrom: 2 to: 2. + + self assert: other size = 1. + self assert: other start = 2. + self assert: other stop = 2. + self assert: other collection = result collection +! ! + +!PPTokenTest methodsFor:'testing-querying'! + +testColumn + | input parser result cr | + + cr := Smalltalk isSmalltalkX + ifTrue:[ Character return] + ifFalse:[ Character cr ]. + input := '1' , (String with:cr) , '12' , (String with: cr with: Character lf) , '123' , (String with: Character lf) , '1234'. + parser := #any asParser token star. + result := parser parse: input. + result + with: #(1 2 1 2 3 4 1 2 3 4 1 2 3 4) + do: [ :token :line | self assert: token column = line ] +! + +testLine + | input parser result cr| + + cr := Smalltalk isSmalltalkX + ifTrue:[Character return] + ifFalse:[Character cr]. + input := '1' , (String with: cr) , '12' , (String with: cr with: Character lf) , '123' , (String with: Character lf) , '1234'. + parser := #any asParser token star. + result := parser parse: input. + result + with: #(1 1 2 2 2 2 3 3 3 3 4 4 4 4) + do: [ :token :line | self assert: token line = line ] +! ! + +!PPTokenTest methodsFor:'testing-values'! + +testInputValue + | input result | + input := 'foo'. + result := self + parse: input + using: self identifier. + self assert: result inputValue = input. + self deny: result inputValue == input +! + +testParsedValue + | input result | + input := 'foo'. + result := self + parse: input + using: self identifier. + self assert: result parsedValue = #($f $o $o) +! ! + +!PPTokenTest methodsFor:'utilities'! + +parse: aString using: aParser + ^ aParser parse: aString +! ! + +!PPTokenTest class methodsFor:'documentation'! + +version + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPTokenTest.st,v 1.5 2014-03-04 14:34:24 cg Exp $' +! + +version_CVS + ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPTokenTest.st,v 1.5 2014-03-04 14:34:24 cg Exp $' +! + +version_SVN + ^ '$Id: PPTokenTest.st,v 1.5 2014-03-04 14:34:24 cg Exp $' +! ! + diff -r 1ba87229ee7e -r e2b2f08d054e tests/stx_goodies_petitparser_tests.st --- a/tests/stx_goodies_petitparser_tests.st Fri Oct 03 00:52:34 2014 +0100 +++ b/tests/stx_goodies_petitparser_tests.st Fri Oct 03 01:36:33 2014 +0100 @@ -65,9 +65,24 @@ ^ #( " or ( attributes...) in load order" - PPAbstractParserTest + (PPAbstractParserTest autoload) #'stx_goodies_petitparser_tests' - PPCompositeParserTest + (PPCompositeParserTest autoload) + (PPAbstractParseTest autoload) + (PPArithmeticParserTest autoload) + (PPComposedTest autoload) + (PPExtensionTest autoload) + (PPLambdaParserTest autoload) + (PPObjectTest autoload) + (PPParserResource autoload) + (PPParserTest autoload) + (PPPredicateTest autoload) + (PPScriptingTest autoload) + (PPTokenTest autoload) + (PPExpressionParserTest autoload) + (PPMappingTest autoload) + (PPArithmeticParser autoload) + (PPLambdaParser autoload) ) !