diff -r e1b11f74e142 -r 90de244a7fa2 PPParserTest.st --- a/PPParserTest.st Mon Sep 12 19:48:53 2011 +0200 +++ b/PPParserTest.st Fri Jan 13 12:22:50 2012 +0100 @@ -1,4 +1,4 @@ -"{ Package: 'squeak:petitparser' }" +"{ Package: 'stx:goodies/petitparser' }" PPAbstractParseTest subclass:#PPParserTest instanceVariableNames:'' @@ -23,10 +23,10 @@ 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 ! @@ -34,9 +34,9 @@ testAnswer | parser | parser := $a asParser answer: $b. - + self assert: parser parse: 'a' to: $b. - + self assert: parser fail: ''. self assert: parser fail: 'b' ! @@ -44,7 +44,7 @@ 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 @@ -53,7 +53,7 @@ testChoice | parser | parser := $a asParser / $b asParser. - + self assert: parser parse: 'a' to: $a. self assert: parser parse: 'b' to: $b. @@ -68,7 +68,7 @@ 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). @@ -76,12 +76,12 @@ 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' @@ -91,7 +91,7 @@ | 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' @@ -108,9 +108,9 @@ 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 ! @@ -119,11 +119,11 @@ | 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' @@ -132,49 +132,49 @@ 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' ! testLiteralObject | parser | - parser := PPLiteralObjectParser + 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 + 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' @@ -183,12 +183,12 @@ 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' ! @@ -204,7 +204,7 @@ 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]') ! @@ -213,7 +213,7 @@ 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. @@ -221,7 +221,7 @@ count := 0. self assert: twice parse: 'a' to: #($a $a). self assert: count = 1. - + self assert: parser memoized = parser ! @@ -230,13 +230,13 @@ 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, *]') ! @@ -245,7 +245,7 @@ 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). @@ -253,19 +253,19 @@ 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]') ! 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' ! @@ -273,7 +273,7 @@ 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' ! @@ -281,10 +281,10 @@ 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. @@ -302,7 +302,7 @@ 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 @@ -320,15 +320,15 @@ 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' @@ -377,16 +377,16 @@ 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' ! @@ -394,12 +394,12 @@ 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'. @@ -412,12 +412,12 @@ 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. @@ -471,7 +471,7 @@ testTimes | parser | parser := $a asParser times: 2. - + self assert: parser fail: ''. self assert: parser fail: 'a'. self assert: parser parse: 'aa' to: #($a $a). @@ -482,13 +482,13 @@ | parser | parser := $a asParser token. self assert: parser tokenClass = PPToken. - self assert: parser parse: 'a' toToken: 1 stop: 1. + 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 parse: 'a' toToken: 1 stop: 1. self assert: parser fail: ''. self assert: parser fail: 'b' ! @@ -497,25 +497,25 @@ | parser | parser := $a asParser token trim. self assert: parser trim = parser. - + 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 + 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: 2 stop: 2. self assert: parser parse: ' a' toToken: 5 stop: 5. - self assert: parser parse: ' + 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: 2. self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 3. - + self assert: parser fail: ''. self assert: parser fail: 'b' ! @@ -523,21 +523,21 @@ 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: 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: 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: 2. self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 3. - + self assert: parser fail: ''. self assert: parser fail: ' '. @@ -549,25 +549,25 @@ 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 + 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: 2 stop: 2. self assert: parser parse: ' a' toToken: 5 stop: 5. - self assert: parser parse: ' + 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: 2. self assert: parser parse: 'a a' toToken: 1 stop: 1 end: 3. - + self assert: parser fail: ''. self assert: parser fail: 'b' ! @@ -575,12 +575,12 @@ 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 ! @@ -588,26 +588,26 @@ 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) ! testWrapping | parser result | - parser := #digit asParser plus >=> [ :stream :cc | - Array - with: stream position - with: cc value + 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. @@ -618,21 +618,21 @@ | 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' @@ -644,31 +644,31 @@ | 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 includesSubString: 'PPParser'). - - parser := PPParser named: 'choice'. - self assert: (parser printString includesSubString: 'PPParser(choice'). - - parser := PPLiteralObjectParser on: $a. + | parser | + parser := PPParser new. + self assert: (parser printString includesSubString: 'PPParser'). + + parser := PPParser named: 'choice'. + self assert: (parser printString includesSubString: 'PPParser(choice'). + + parser := PPLiteralObjectParser on: $a. "/ self assert: (parser printString includesSubString: '$a'). - self assert: (parser printString includesSubString: 'a'). - - parser := PPFailingParser message: 'error'. - self assert: (parser printString includesSubString: 'error'). - - parser := PPPredicateObjectParser on: [ :c | true ] message: 'error'. - self assert: (parser printString includesSubString: 'error') + self assert: (parser printString includesSubString: 'a'). + + parser := PPFailingParser message: 'error'. + self assert: (parser printString includesSubString: 'error'). + + parser := PPPredicateObjectParser on: [ :c | true ] message: 'error'. + self assert: (parser printString includesSubString: 'error') "Modified: / 19-12-2010 / 18:30:54 / Jan Kurs " ! ! @@ -682,15 +682,15 @@ 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' @@ -700,7 +700,7 @@ | 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. @@ -714,16 +714,16 @@ p1 := $a asParser. p2 := p1 , $b asParser. p3 := p1 , $c asParser. - - self assert: p1 parse: 'a'. + + 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 fail: 'a'. self assert: p2 parse: 'ab'. self assert: p2 fail: 'ac'. - self assert: p3 fail: 'a'. + self assert: p3 fail: 'a'. self assert: p3 fail: 'ab'. self assert: p3 parse: 'ac' ! ! @@ -803,7 +803,7 @@ testFailure | failure | failure := PPFailure message: 'Error' at: 3. - + self assert: failure message = 'Error'. self assert: failure position = 3. self assert: failure isPetitFailure. @@ -817,7 +817,7 @@ 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 @@ -826,10 +826,10 @@ 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) ! @@ -837,12 +837,12 @@ 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. @@ -854,7 +854,7 @@ | parser result | parser := [ :stream | stream position ] asParser. - + result := parser matchesIn: '123'. self assert: result asArray = #(0 1 2 3) ! @@ -864,7 +864,7 @@ | parser result | parser := #digit asParser , #digit asParser. - + result := parser matchesIn: 'a123b'. self assert: result size = 2. self assert: result first = #($1 $2). @@ -881,24 +881,24 @@ ! testParse - | parser result | - parser := $a asParser. - - self assert: (parser parse: 'a') = $a. - self assert: (result := parser parse: 'b') isPetitFailure. - "is it Character printString differs: we return only 'a', not '$a'" - self breakPoint: #petitparser. + | parser result | + parser := $a asParser. + + self assert: (parser parse: 'a') = $a. + self assert: (result := parser parse: 'b') isPetitFailure. + "is it Character printString differs: we return only 'a', not '$a'" + self breakPoint: #petitparser. "/ self assert: (result message includesSubString: '$a'). - self assert: (result message includesSubString: 'a'). - self assert: (result message includesSubString: 'expected'). - self assert: (result position = 0). - - self assert: (parser parse: 'a' readStream) = $a. - self assert: (result := parser parse: 'b' readStream) isPetitFailure. + self assert: (result message includesSubString: 'a'). + self assert: (result message includesSubString: 'expected'). + self assert: (result position = 0). + + self assert: (parser parse: 'a' readStream) = $a. + self assert: (result := parser parse: 'b' readStream) isPetitFailure. "/ self assert: (result message includesSubString: '$a'). - self assert: (result message includesSubString: 'a'). - self assert: (result message includesSubString: 'expected'). - self assert: (result position = 0) + self assert: (result message includesSubString: 'a'). + self assert: (result message includesSubString: 'expected'). + self assert: (result position = 0) "Modified: / 18-12-2010 / 17:05:13 / Jan Kurs " ! @@ -916,41 +916,41 @@ ! 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). - "We don't use $ in ST/X for Characters" - self assert: (failure message includesSubString: 'a'). + | 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). + "We don't use $ in ST/X for Characters" + self assert: (failure message includesSubString: 'a'). "/ self assert: (failure message includesSubString: '$a'). - self assert: (failure message includesSubString: 'expected'). - seen := true ]. - self assert: result. - self assert: seen + self assert: (failure message includesSubString: 'expected'). + seen := true ]. + self assert: result. + self assert: seen "Modified: / 19-12-2010 / 18:18:01 / Jan Kurs " ! testParseOnError2 - | parser result seen | - parser := $a asParser. - - result := parser parse: 'a' onError: [ self signalFailure: 'Not supposed to report an error' ]. - self assert: result = $a. + | 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 | - "We don't use $ in ST/X for Characters" - self assert: (msg includesSubString: 'a'). + result := parser parse: 'b' onError: [ :msg :pos | + "We don't use $ in ST/X for Characters" + self assert: (msg includesSubString: 'a'). "/ self assert: (msg includesSubString: '$a'). - self assert: (msg includesSubString: 'expected'). - self assert: pos = 0. - seen := true ]. - self assert: result. - self assert: seen + self assert: (msg includesSubString: 'expected'). + self assert: pos = 0. + seen := true ]. + self assert: result. + self assert: seen "Modified: / 19-12-2010 / 18:18:31 / Jan Kurs " ! @@ -958,7 +958,7 @@ testParser | parser | parser := PPParser new. - + self assert: parser isPetitParser. self deny: 4 isPetitParser. @@ -968,5 +968,5 @@ !PPParserTest class methodsFor:'documentation'! version_SVN - ^ '$Id: PPParserTest.st,v 1.1 2011-08-18 18:56:17 cg Exp $' + ^ '$Id: PPParserTest.st,v 1.2 2012-01-13 11:22:50 cg Exp $' ! !