From 05eedb5e3a66ceb7681b6ba6802aa5d2556d0e60 Mon Sep 17 00:00:00 2001 From: Todd Ditchendorf Date: Mon, 25 Jan 2010 20:42:34 -0800 Subject: [PATCH] initial add --- .gitignore | 5 + English.lproj/.svn/all-wcprops | 11 + English.lproj/.svn/entries | 69 + .../.svn/prop-base/InfoPlist.strings.svn-base | 5 + .../.svn/text-base/InfoPlist.strings.svn-base | Bin 0 -> 202 bytes English.lproj/InfoPlist.strings | Bin 0 -> 202 bytes Info.plist | 26 + JSParseKit-Info.plist | 20 + License.txt | 175 + ParseKit.xcodeproj/.svn/all-wcprops | 11 + ParseKit.xcodeproj/.svn/dir-prop-base | 12 + ParseKit.xcodeproj/.svn/entries | 69 + .../.svn/text-base/project.pbxproj.svn-base | 3720 +++++++ .../.svn/tmp/project.pbxproj.tmp | 3720 +++++++ ParseKit.xcodeproj/project.pbxproj | 3720 +++++++ ParseKitMobile_Prefix.pch | 5 + ParseKit_Prefix.pch | 14 + README.txt | 0 debugapp/.svn/all-wcprops | 47 + debugapp/.svn/entries | 273 + .../text-base/DebugApp-Info.plist.svn-base | 24 + .../text-base/DebugAppDelegate.h.svn-base | 17 + .../text-base/DebugAppDelegate.m.svn-base | 510 + .../text-base/DebugAppMainMenu.xib.svn-base | 3529 +++++++ .../.svn/text-base/JSONAssembler.h.svn-base | 36 + .../.svn/text-base/JSONAssembler.m.svn-base | 163 + debugapp/.svn/text-base/main.m.svn-base | 13 + debugapp/.svn/tmp/tempfile.tmp | 433 + debugapp/DebugApp-Info.plist | 24 + debugapp/DebugAppDelegate.h | 23 + debugapp/DebugAppDelegate.m | 516 + debugapp/DebugAppMainMenu.xib | 3529 +++++++ debugapp/JSONAssembler.h | 42 + debugapp/JSONAssembler.m | 169 + debugapp/main.m | 13 + demoapp/.svn/all-wcprops | 107 + demoapp/.svn/entries | 613 ++ .../text-base/DemoApp-Info.plist.svn-base | 24 + .../.svn/text-base/DemoAppDelegate.h.svn-base | 23 + .../.svn/text-base/DemoAppDelegate.m.svn-base | 35 + .../text-base/DemoAppMainMenu.xib.svn-base | 2268 ++++ .../DemoTokensViewController.h.svn-base | 32 + .../DemoTokensViewController.m.svn-base | 119 + .../DemoTreesViewController.h.svn-base | 29 + .../DemoTreesViewController.m.svn-base | 157 + .../.svn/text-base/PKParseTreeView.h.svn-base | 21 + .../.svn/text-base/PKParseTreeView.m.svn-base | 184 + .../.svn/text-base/TDGutterView.h.svn-base | 25 + .../.svn/text-base/TDGutterView.m.svn-base | 92 + .../text-base/TDSourceCodeTextView.h.svn-base | 21 + .../text-base/TDSourceCodeTextView.m.svn-base | 116 + .../.svn/text-base/TokensView.xib.svn-base | 939 ++ demoapp/.svn/text-base/TreesView.xib.svn-base | 1391 +++ demoapp/.svn/text-base/main.m.svn-base | 13 + demoapp/DemoApp-Info.plist | 24 + demoapp/DemoAppDelegate.h | 29 + demoapp/DemoAppDelegate.m | 41 + demoapp/DemoAppMainMenu.xib | 2268 ++++ demoapp/DemoTokensViewController.h | 38 + demoapp/DemoTokensViewController.m | 125 + demoapp/DemoTreesViewController.h | 35 + demoapp/DemoTreesViewController.m | 163 + demoapp/PKParseTreeView.h | 27 + demoapp/PKParseTreeView.m | 190 + demoapp/TDGutterView.h | 25 + demoapp/TDGutterView.m | 92 + demoapp/TDSourceCodeTextView.h | 21 + demoapp/TDSourceCodeTextView.m | 116 + demoapp/TokensView.xib | 939 ++ demoapp/TreesView.xib | 1391 +++ demoapp/main.m | 13 + docs/.svn/all-wcprops | 17 + docs/.svn/dir-prop-base | 6 + docs/.svn/entries | 106 + docs/.svn/prop-base/ParseKit.key.svn-base | 5 + docs/.svn/text-base/Doxyfile.svn-base | 291 + docs/.svn/text-base/ParseKit.key.svn-base | Bin 0 -> 557092 bytes docs/.svn/tmp/tempfile.2.tmp | 1546 +++ docs/Doxyfile | 291 + docs/web/.svn/all-wcprops | 53 + docs/web/.svn/entries | 346 + .../.svn/text-base/common-footer.inc.svn-base | 11 + .../.svn/text-base/common-header.inc.svn-base | 6 + .../.svn/text-base/common-nav.inc.svn-base | 16 + .../web/.svn/text-base/grammars.html.svn-base | 167 + docs/web/.svn/text-base/htaccess.svn-base | 5 + docs/web/.svn/text-base/index.html.svn-base | 257 + docs/web/.svn/text-base/iphone.html.svn-base | 59 + .../.svn/text-base/tokenization.html.svn-base | 366 + docs/web/common-footer.inc | 11 + docs/web/common-header.inc | 6 + docs/web/common-nav.inc | 16 + docs/web/css/.svn/all-wcprops | 5 + docs/web/css/.svn/entries | 62 + .../css/.svn/text-base/master.css.svn-base | 88 + docs/web/css/master.css | 88 + docs/web/grammars.html | 167 + docs/web/htaccess | 5 + docs/web/img/.svn/all-wcprops | 5 + docs/web/img/.svn/entries | 538 + .../img/.svn/prop-base/step1a.png.svn-base | 5 + .../img/.svn/prop-base/step1a.psd.svn-base | 5 + .../img/.svn/prop-base/step1b.png.svn-base | 5 + .../img/.svn/prop-base/step1b.psd.svn-base | 5 + .../img/.svn/prop-base/step2a.png.svn-base | 5 + .../img/.svn/prop-base/step2a.psd.svn-base | 5 + .../img/.svn/prop-base/step3a.png.svn-base | 5 + .../img/.svn/prop-base/step3a.psd.svn-base | 5 + .../img/.svn/prop-base/step4a.png.svn-base | 5 + .../img/.svn/prop-base/step4a.psd.svn-base | 5 + .../img/.svn/prop-base/step4b.png.svn-base | 5 + .../img/.svn/prop-base/step4b.psd.svn-base | 5 + .../img/.svn/prop-base/step5a.png.svn-base | 5 + .../img/.svn/prop-base/step6a.png.svn-base | 5 + .../img/.svn/prop-base/step7a.png.svn-base | 5 + .../img/.svn/text-base/step1a.png.svn-base | Bin 0 -> 57243 bytes .../img/.svn/text-base/step1a.psd.svn-base | Bin 0 -> 146999 bytes .../img/.svn/text-base/step1b.png.svn-base | Bin 0 -> 59744 bytes .../img/.svn/text-base/step1b.psd.svn-base | Bin 0 -> 144527 bytes .../img/.svn/text-base/step2a.png.svn-base | Bin 0 -> 79730 bytes .../img/.svn/text-base/step2a.psd.svn-base | Bin 0 -> 166898 bytes .../img/.svn/text-base/step3a.png.svn-base | Bin 0 -> 66069 bytes .../img/.svn/text-base/step3a.psd.svn-base | Bin 0 -> 164750 bytes .../img/.svn/text-base/step4a.png.svn-base | Bin 0 -> 65076 bytes .../img/.svn/text-base/step4a.psd.svn-base | Bin 0 -> 203007 bytes .../img/.svn/text-base/step4b.png.svn-base | Bin 0 -> 25070 bytes .../img/.svn/text-base/step4b.psd.svn-base | Bin 0 -> 85694 bytes .../img/.svn/text-base/step5a.png.svn-base | Bin 0 -> 45296 bytes .../img/.svn/text-base/step6a.png.svn-base | Bin 0 -> 49927 bytes .../img/.svn/text-base/step7a.png.svn-base | Bin 0 -> 41304 bytes docs/web/img/step1a.png | Bin 0 -> 57243 bytes docs/web/img/step1a.psd | Bin 0 -> 146999 bytes docs/web/img/step1b.png | Bin 0 -> 59744 bytes docs/web/img/step1b.psd | Bin 0 -> 144527 bytes docs/web/img/step2a.png | Bin 0 -> 79730 bytes docs/web/img/step2a.psd | Bin 0 -> 166898 bytes docs/web/img/step3a.png | Bin 0 -> 66069 bytes docs/web/img/step3a.psd | Bin 0 -> 164750 bytes docs/web/img/step4a.png | Bin 0 -> 65076 bytes docs/web/img/step4a.psd | Bin 0 -> 203007 bytes docs/web/img/step4b.png | Bin 0 -> 25070 bytes docs/web/img/step4b.psd | Bin 0 -> 85694 bytes docs/web/img/step5a.png | Bin 0 -> 45296 bytes docs/web/img/step6a.png | Bin 0 -> 49927 bytes docs/web/img/step7a.png | Bin 0 -> 41304 bytes docs/web/index.html | 257 + docs/web/iphone.html | 59 + docs/web/tokenization.html | 366 + frameworks/.svn/all-wcprops | 5 + frameworks/.svn/entries | 31 + frameworks/OCMock.framework/.svn/all-wcprops | 23 + frameworks/OCMock.framework/.svn/entries | 133 + .../.svn/prop-base/Headers.svn-base | 5 + .../.svn/prop-base/OCMock.svn-base | 5 + .../.svn/prop-base/Resources.svn-base | 5 + .../.svn/text-base/Headers.svn-base | 1 + .../.svn/text-base/OCMock.svn-base | 1 + .../.svn/text-base/Resources.svn-base | 1 + frameworks/OCMock.framework/Headers | 1 + frameworks/OCMock.framework/OCMock | 1 + frameworks/OCMock.framework/Resources | 1 + .../Versions/.svn/all-wcprops | 11 + .../OCMock.framework/Versions/.svn/entries | 65 + .../Versions/.svn/prop-base/Current.svn-base | 5 + .../Versions/.svn/text-base/Current.svn-base | 1 + .../Versions/A/.svn/all-wcprops | 11 + .../OCMock.framework/Versions/A/.svn/entries | 68 + .../Versions/A/.svn/prop-base/OCMock.svn-base | 9 + .../Versions/A/.svn/text-base/OCMock.svn-base | Bin 0 -> 182272 bytes .../Versions/A/Headers/.svn/all-wcprops | 29 + .../Versions/A/Headers/.svn/entries | 164 + .../.svn/text-base/OCMConstraint.h.svn-base | 28 + .../Headers/.svn/text-base/OCMock.h.svn-base | 8 + .../.svn/text-base/OCMockObject.h.svn-base | 29 + .../.svn/text-base/OCMockRecorder.h.svn-base | 33 + .../Versions/A/Headers/OCMConstraint.h | 28 + .../Versions/A/Headers/OCMock.h | 8 + .../Versions/A/Headers/OCMockObject.h | 29 + .../Versions/A/Headers/OCMockRecorder.h | 33 + frameworks/OCMock.framework/Versions/A/OCMock | Bin 0 -> 182272 bytes .../Versions/A/Resources/.svn/all-wcprops | 17 + .../Versions/A/Resources/.svn/entries | 99 + .../.svn/text-base/Info.plist.svn-base | 20 + .../.svn/text-base/License.txt.svn-base | 15 + .../Resources/English.lproj/.svn/all-wcprops | 11 + .../A/Resources/English.lproj/.svn/entries | 62 + .../.svn/prop-base/InfoPlist.strings.svn-base | 5 + .../.svn/text-base/InfoPlist.strings.svn-base | Bin 0 -> 534 bytes .../Resources/English.lproj/InfoPlist.strings | Bin 0 -> 534 bytes .../Versions/A/Resources/Info.plist | 20 + .../Versions/A/Resources/License.txt | 15 + frameworks/OCMock.framework/Versions/Current | 1 + include/.svn/all-wcprops | 5 + include/.svn/entries | 38 + include/ParseKit/.svn/all-wcprops | 311 + include/ParseKit/.svn/entries | 1769 ++++ .../.svn/prop-base/PKAlternation.h.svn-base | 5 + .../.svn/prop-base/PKAssembly.h.svn-base | 5 + .../PKCaseInsensitiveLiteral.h.svn-base | 5 + .../ParseKit/.svn/prop-base/PKChar.h.svn-base | 5 + .../prop-base/PKCharacterAssembly.h.svn-base | 5 + .../prop-base/PKCollectionParser.h.svn-base | 5 + .../.svn/prop-base/PKDigit.h.svn-base | 5 + .../.svn/prop-base/PKEmpty.h.svn-base | 5 + .../.svn/prop-base/PKLetter.h.svn-base | 5 + .../.svn/prop-base/PKLiteral.h.svn-base | 5 + .../.svn/prop-base/PKLowercaseWord.h.svn-base | 5 + .../.svn/prop-base/PKNumberState.h.svn-base | 5 + .../.svn/prop-base/PKParser.h.svn-base | 5 + .../.svn/prop-base/PKParserFactory.h.svn-base | 5 + .../.svn/prop-base/PKQuoteState.h.svn-base | 5 + .../.svn/prop-base/PKQuotedString.h.svn-base | 5 + .../.svn/prop-base/PKReader.h.svn-base | 5 + .../.svn/prop-base/PKRepetition.h.svn-base | 5 + .../.svn/prop-base/PKSequence.h.svn-base | 5 + .../.svn/prop-base/PKSpecificChar.h.svn-base | 5 + .../.svn/prop-base/PKSymbol.h.svn-base | 5 + .../.svn/prop-base/PKSymbolNode.h.svn-base | 5 + .../prop-base/PKSymbolRootNode.h.svn-base | 5 + .../.svn/prop-base/PKSymbolState.h.svn-base | 5 + .../.svn/prop-base/PKTerminal.h.svn-base | 5 + .../.svn/prop-base/PKToken.h.svn-base | 5 + .../prop-base/PKTokenArraySource.h.svn-base | 5 + .../.svn/prop-base/PKTokenAssembly.h.svn-base | 5 + .../.svn/prop-base/PKTokenizer.h.svn-base | 5 + .../prop-base/PKTokenizerState.h.svn-base | 5 + .../.svn/prop-base/PKTrack.h.svn-base | 5 + .../.svn/prop-base/PKUppercaseWord.h.svn-base | 5 + .../prop-base/PKWhitespaceState.h.svn-base | 5 + .../ParseKit/.svn/prop-base/PKWord.h.svn-base | 5 + .../.svn/prop-base/PKWordState.h.svn-base | 5 + .../.svn/prop-base/ParseKit.h.svn-base | 5 + .../.svn/text-base/PKAlternation.h.svn-base | 27 + .../ParseKit/.svn/text-base/PKAny.h.svn-base | 25 + .../.svn/text-base/PKAssembly.h.svn-base | 80 + .../PKCaseInsensitiveLiteral.h.svn-base | 20 + .../ParseKit/.svn/text-base/PKChar.h.svn-base | 25 + .../text-base/PKCharacterAssembly.h.svn-base | 19 + .../text-base/PKCollectionParser.h.svn-base | 38 + .../.svn/text-base/PKComment.h.svn-base | 25 + .../.svn/text-base/PKCommentState.h.svn-base | 71 + .../.svn/text-base/PKDelimitState.h.svn-base | 51 + .../text-base/PKDelimitedString.h.svn-base | 30 + .../.svn/text-base/PKDifference.h.svn-base | 57 + .../.svn/text-base/PKDigit.h.svn-base | 25 + .../.svn/text-base/PKEmpty.h.svn-base | 26 + .../.svn/text-base/PKIntersection.h.svn-base | 35 + .../.svn/text-base/PKLetter.h.svn-base | 25 + .../.svn/text-base/PKLiteral.h.svn-base | 28 + .../.svn/text-base/PKLowercaseWord.h.svn-base | 16 + .../PKMultiLineCommentState.h.svn-base | 18 + .../.svn/text-base/PKNegation.h.svn-base | 46 + .../.svn/text-base/PKNumber.h.svn-base | 25 + .../.svn/text-base/PKNumberState.h.svn-base | 65 + .../.svn/text-base/PKParser.h.svn-base | 167 + .../.svn/text-base/PKParserFactory.h.svn-base | 47 + .../.svn/text-base/PKPattern.h.svn-base | 32 + .../.svn/text-base/PKQuoteState.h.svn-base | 26 + .../.svn/text-base/PKQuotedString.h.svn-base | 25 + .../.svn/text-base/PKReader.h.svn-base | 60 + .../.svn/text-base/PKRepetition.h.svn-base | 40 + .../.svn/text-base/PKSequence.h.svn-base | 27 + .../PKSingleLineCommentState.h.svn-base | 17 + .../.svn/text-base/PKSpecificChar.h.svn-base | 34 + .../.svn/text-base/PKSymbol.h.svn-base | 34 + .../.svn/text-base/PKSymbolNode.h.svn-base | 38 + .../text-base/PKSymbolRootNode.h.svn-base | 42 + .../.svn/text-base/PKSymbolState.h.svn-base | 38 + .../.svn/text-base/PKTerminal.h.svn-base | 43 + .../.svn/text-base/PKToken.h.svn-base | 166 + .../text-base/PKTokenArraySource.h.svn-base | 62 + .../.svn/text-base/PKTokenAssembly.h.svn-base | 57 + .../.svn/text-base/PKTokenizer.h.svn-base | 150 + .../text-base/PKTokenizerState.h.svn-base | 50 + .../.svn/text-base/PKTrack.h.svn-base | 28 + .../text-base/PKTrackException.h.svn-base | 25 + .../.svn/text-base/PKTypes.h.svn-base | 13 + .../.svn/text-base/PKUppercaseWord.h.svn-base | 16 + .../.svn/text-base/PKWhitespace.h.svn-base | 25 + .../text-base/PKWhitespaceState.h.svn-base | 42 + .../ParseKit/.svn/text-base/PKWord.h.svn-base | 25 + .../.svn/text-base/PKWordState.h.svn-base | 43 + .../.svn/text-base/ParseKit.h.svn-base | 82 + include/ParseKit/PKAlternation.h | 33 + include/ParseKit/PKAny.h | 31 + include/ParseKit/PKAssembly.h | 86 + include/ParseKit/PKCaseInsensitiveLiteral.h | 26 + include/ParseKit/PKChar.h | 31 + include/ParseKit/PKCharacterAssembly.h | 25 + include/ParseKit/PKCollectionParser.h | 44 + include/ParseKit/PKComment.h | 31 + include/ParseKit/PKCommentState.h | 77 + include/ParseKit/PKDelimitState.h | 57 + include/ParseKit/PKDelimitedString.h | 36 + include/ParseKit/PKDifference.h | 63 + include/ParseKit/PKDigit.h | 31 + include/ParseKit/PKEmpty.h | 32 + include/ParseKit/PKIntersection.h | 41 + include/ParseKit/PKLetter.h | 31 + include/ParseKit/PKLiteral.h | 34 + include/ParseKit/PKLowercaseWord.h | 22 + include/ParseKit/PKMultiLineCommentState.h | 24 + include/ParseKit/PKNegation.h | 52 + include/ParseKit/PKNumber.h | 31 + include/ParseKit/PKNumberState.h | 71 + include/ParseKit/PKParser.h | 173 + include/ParseKit/PKParserFactory.h | 47 + include/ParseKit/PKPattern.h | 38 + include/ParseKit/PKQuoteState.h | 32 + include/ParseKit/PKQuotedString.h | 31 + include/ParseKit/PKReader.h | 66 + include/ParseKit/PKRepetition.h | 46 + include/ParseKit/PKSequence.h | 33 + include/ParseKit/PKSingleLineCommentState.h | 23 + include/ParseKit/PKSpecificChar.h | 40 + include/ParseKit/PKSymbol.h | 40 + include/ParseKit/PKSymbolNode.h | 44 + include/ParseKit/PKSymbolRootNode.h | 48 + include/ParseKit/PKSymbolState.h | 44 + include/ParseKit/PKTerminal.h | 49 + include/ParseKit/PKToken.h | 172 + include/ParseKit/PKTokenArraySource.h | 68 + include/ParseKit/PKTokenAssembly.h | 63 + include/ParseKit/PKTokenizer.h | 156 + include/ParseKit/PKTokenizerState.h | 56 + include/ParseKit/PKTrack.h | 34 + include/ParseKit/PKTrackException.h | 31 + include/ParseKit/PKTypes.h | 18 + include/ParseKit/PKUppercaseWord.h | 22 + include/ParseKit/PKWhitespace.h | 31 + include/ParseKit/PKWhitespaceState.h | 48 + include/ParseKit/PKWord.h | 31 + include/ParseKit/PKWordState.h | 49 + include/ParseKit/ParseKit.h | 88 + jsdemoapp/.svn/all-wcprops | 53 + jsdemoapp/.svn/entries | 300 + .../prop-base/JSDemoAppMainMenu.xib.svn-base | 5 + .../text-base/DefaultValues.plist.svn-base | 15 + .../text-base/JSDemoApp-Info.plist.svn-base | 24 + .../text-base/JSDemoAppDelegate.h.svn-base | 24 + .../text-base/JSDemoAppDelegate.m.svn-base | 135 + .../text-base/JSDemoAppMainMenu.xib.svn-base | 3802 +++++++ .../.svn/text-base/ParserTest.html.svn-base | 25 + jsdemoapp/.svn/text-base/Test.html.svn-base | 35 + jsdemoapp/.svn/text-base/main.m.svn-base | 14 + jsdemoapp/DefaultValues.plist | 15 + jsdemoapp/JSDemoApp-Info.plist | 24 + jsdemoapp/JSDemoAppDelegate.h | 30 + jsdemoapp/JSDemoAppDelegate.m | 141 + jsdemoapp/JSDemoAppMainMenu.xib | 3802 +++++++ jsdemoapp/ParserTest.html | 25 + jsdemoapp/Test.html | 35 + jsdemoapp/main.m | 14 + jssrc/.svn/all-wcprops | 455 + jssrc/.svn/entries | 2578 +++++ jssrc/.svn/prop-base/JSParseKit.h.svn-base | 5 + jssrc/.svn/prop-base/JSParseKit.m.svn-base | 5 + jssrc/.svn/prop-base/PKJSAssembly.h.svn-base | 5 + jssrc/.svn/prop-base/PKJSAssembly.m.svn-base | 5 + .../prop-base/PKJSCollectionParser.h.svn-base | 5 + .../prop-base/PKJSCollectionParser.m.svn-base | 5 + .../prop-base/PKJSCommentState.h.svn-base | 5 + .../prop-base/PKJSCommentState.m.svn-base | 5 + .../.svn/prop-base/PKJSNumberState.h.svn-base | 5 + .../.svn/prop-base/PKJSNumberState.m.svn-base | 5 + .../.svn/prop-base/PKJSQuoteState.h.svn-base | 5 + .../.svn/prop-base/PKJSQuoteState.m.svn-base | 5 + .../.svn/prop-base/PKJSSymbolState.h.svn-base | 5 + .../.svn/prop-base/PKJSSymbolState.m.svn-base | 5 + jssrc/.svn/prop-base/PKJSToken.h.svn-base | 5 + jssrc/.svn/prop-base/PKJSToken.m.svn-base | 5 + .../prop-base/PKJSTokenAssembly.h.svn-base | 5 + .../prop-base/PKJSTokenAssembly.m.svn-base | 5 + jssrc/.svn/prop-base/PKJSTokenizer.h.svn-base | 5 + jssrc/.svn/prop-base/PKJSTokenizer.m.svn-base | 5 + .../prop-base/PKJSTokenizerState.h.svn-base | 5 + .../prop-base/PKJSTokenizerState.m.svn-base | 5 + jssrc/.svn/prop-base/PKJSUtils.h.svn-base | 5 + jssrc/.svn/prop-base/PKJSUtils.m.svn-base | 5 + .../.svn/prop-base/PKJSValueHolder.h.svn-base | 5 + .../.svn/prop-base/PKJSValueHolder.m.svn-base | 5 + .../prop-base/PKJSWhitespaceState.h.svn-base | 5 + .../prop-base/PKJSWhitespaceState.m.svn-base | 5 + jssrc/.svn/prop-base/PKJSWordState.h.svn-base | 5 + jssrc/.svn/prop-base/PKJSWordState.m.svn-base | 5 + jssrc/.svn/text-base/JSParseKit.h.svn-base | 12 + jssrc/.svn/text-base/JSParseKit.m.svn-base | 116 + .../.svn/text-base/PKJSAlternation.h.svn-base | 13 + .../.svn/text-base/PKJSAlternation.m.svn-base | 63 + jssrc/.svn/text-base/PKJSAny.h.svn-base | 13 + jssrc/.svn/text-base/PKJSAny.m.svn-base | 63 + .../text-base/PKJSAssemblerAdapter.h.svn-base | 22 + .../text-base/PKJSAssemblerAdapter.m.svn-base | 74 + jssrc/.svn/text-base/PKJSAssembly.h.svn-base | 12 + jssrc/.svn/text-base/PKJSAssembly.m.svn-base | 136 + .../PKJSCaseInsensitiveLiteral.h.svn-base | 13 + .../PKJSCaseInsensitiveLiteral.m.svn-base | 67 + .../PKJSCharacterAssembly.h.svn-base | 13 + .../PKJSCharacterAssembly.m.svn-base | 123 + .../text-base/PKJSCollectionParser.h.svn-base | 12 + .../text-base/PKJSCollectionParser.m.svn-base | 71 + jssrc/.svn/text-base/PKJSComment.h.svn-base | 13 + jssrc/.svn/text-base/PKJSComment.m.svn-base | 63 + .../text-base/PKJSCommentState.h.svn-base | 13 + .../text-base/PKJSCommentState.m.svn-base | 147 + .../text-base/PKJSDelimitState.h.svn-base | 13 + .../text-base/PKJSDelimitState.m.svn-base | 102 + .../text-base/PKJSDelimitedString.h.svn-base | 13 + .../text-base/PKJSDelimitedString.m.svn-base | 67 + jssrc/.svn/text-base/PKJSEmpty.h.svn-base | 13 + jssrc/.svn/text-base/PKJSEmpty.m.svn-base | 63 + jssrc/.svn/text-base/PKJSLiteral.h.svn-base | 13 + jssrc/.svn/text-base/PKJSLiteral.m.svn-base | 67 + .../text-base/PKJSLowercaseWord.h.svn-base | 13 + .../text-base/PKJSLowercaseWord.m.svn-base | 67 + jssrc/.svn/text-base/PKJSNum.h.svn-base | 13 + jssrc/.svn/text-base/PKJSNum.m.svn-base | 63 + .../.svn/text-base/PKJSNumberState.h.svn-base | 13 + .../.svn/text-base/PKJSNumberState.m.svn-base | 81 + jssrc/.svn/text-base/PKJSParser.h.svn-base | 12 + jssrc/.svn/text-base/PKJSParser.m.svn-base | 154 + jssrc/.svn/text-base/PKJSPattern.h.svn-base | 13 + jssrc/.svn/text-base/PKJSPattern.m.svn-base | 80 + .../.svn/text-base/PKJSQuoteState.h.svn-base | 13 + .../.svn/text-base/PKJSQuoteState.m.svn-base | 81 + .../text-base/PKJSQuotedString.h.svn-base | 13 + .../text-base/PKJSQuotedString.m.svn-base | 63 + .../.svn/text-base/PKJSRepetition.h.svn-base | 13 + .../.svn/text-base/PKJSRepetition.m.svn-base | 72 + jssrc/.svn/text-base/PKJSSequence.h.svn-base | 13 + jssrc/.svn/text-base/PKJSSequence.m.svn-base | 63 + jssrc/.svn/text-base/PKJSSymbol.h.svn-base | 13 + jssrc/.svn/text-base/PKJSSymbol.m.svn-base | 69 + .../.svn/text-base/PKJSSymbolState.h.svn-base | 13 + .../.svn/text-base/PKJSSymbolState.m.svn-base | 95 + jssrc/.svn/text-base/PKJSTerminal.h.svn-base | 12 + jssrc/.svn/text-base/PKJSTerminal.m.svn-base | 67 + jssrc/.svn/text-base/PKJSToken.h.svn-base | 19 + jssrc/.svn/text-base/PKJSToken.m.svn-base | 159 + .../text-base/PKJSTokenAssembly.h.svn-base | 13 + .../text-base/PKJSTokenAssembly.m.svn-base | 121 + jssrc/.svn/text-base/PKJSTokenizer.h.svn-base | 13 + jssrc/.svn/text-base/PKJSTokenizer.m.svn-base | 215 + .../text-base/PKJSTokenizerState.h.svn-base | 12 + .../text-base/PKJSTokenizerState.m.svn-base | 59 + jssrc/.svn/text-base/PKJSTrack.h.svn-base | 13 + jssrc/.svn/text-base/PKJSTrack.m.svn-base | 63 + .../text-base/PKJSUppercaseWord.h.svn-base | 13 + .../text-base/PKJSUppercaseWord.m.svn-base | 67 + jssrc/.svn/text-base/PKJSUtils.h.svn-base | 32 + jssrc/.svn/text-base/PKJSUtils.m.svn-base | 236 + .../text-base/PKJSUtils_macros.h.svn-base | 33 + .../.svn/text-base/PKJSValueHolder.h.svn-base | 20 + .../.svn/text-base/PKJSValueHolder.m.svn-base | 29 + .../text-base/PKJSWhitespaceState.h.svn-base | 13 + .../text-base/PKJSWhitespaceState.m.svn-base | 109 + jssrc/.svn/text-base/PKJSWord.h.svn-base | 13 + jssrc/.svn/text-base/PKJSWord.m.svn-base | 63 + jssrc/.svn/text-base/PKJSWordState.h.svn-base | 13 + jssrc/.svn/text-base/PKJSWordState.m.svn-base | 97 + jssrc/JSParseKit.h | 18 + jssrc/JSParseKit.m | 122 + jssrc/PKJSAlternation.h | 19 + jssrc/PKJSAlternation.m | 69 + jssrc/PKJSAny.h | 19 + jssrc/PKJSAny.m | 69 + jssrc/PKJSAssemblerAdapter.h | 28 + jssrc/PKJSAssemblerAdapter.m | 80 + jssrc/PKJSAssembly.h | 18 + jssrc/PKJSAssembly.m | 142 + jssrc/PKJSCaseInsensitiveLiteral.h | 19 + jssrc/PKJSCaseInsensitiveLiteral.m | 73 + jssrc/PKJSCharacterAssembly.h | 19 + jssrc/PKJSCharacterAssembly.m | 129 + jssrc/PKJSCollectionParser.h | 18 + jssrc/PKJSCollectionParser.m | 77 + jssrc/PKJSComment.h | 19 + jssrc/PKJSComment.m | 69 + jssrc/PKJSCommentState.h | 19 + jssrc/PKJSCommentState.m | 153 + jssrc/PKJSDelimitState.h | 19 + jssrc/PKJSDelimitState.m | 108 + jssrc/PKJSDelimitedString.h | 19 + jssrc/PKJSDelimitedString.m | 73 + jssrc/PKJSEmpty.h | 19 + jssrc/PKJSEmpty.m | 69 + jssrc/PKJSLiteral.h | 19 + jssrc/PKJSLiteral.m | 73 + jssrc/PKJSLowercaseWord.h | 19 + jssrc/PKJSLowercaseWord.m | 73 + jssrc/PKJSNum.h | 19 + jssrc/PKJSNum.m | 69 + jssrc/PKJSNumberState.h | 19 + jssrc/PKJSNumberState.m | 87 + jssrc/PKJSParser.h | 18 + jssrc/PKJSParser.m | 160 + jssrc/PKJSPattern.h | 19 + jssrc/PKJSPattern.m | 86 + jssrc/PKJSQuoteState.h | 19 + jssrc/PKJSQuoteState.m | 87 + jssrc/PKJSQuotedString.h | 19 + jssrc/PKJSQuotedString.m | 69 + jssrc/PKJSRepetition.h | 19 + jssrc/PKJSRepetition.m | 78 + jssrc/PKJSSequence.h | 19 + jssrc/PKJSSequence.m | 69 + jssrc/PKJSSymbol.h | 19 + jssrc/PKJSSymbol.m | 75 + jssrc/PKJSSymbolState.h | 19 + jssrc/PKJSSymbolState.m | 101 + jssrc/PKJSTerminal.h | 18 + jssrc/PKJSTerminal.m | 73 + jssrc/PKJSToken.h | 25 + jssrc/PKJSToken.m | 165 + jssrc/PKJSTokenAssembly.h | 19 + jssrc/PKJSTokenAssembly.m | 127 + jssrc/PKJSTokenizer.h | 19 + jssrc/PKJSTokenizer.m | 221 + jssrc/PKJSTokenizerState.h | 18 + jssrc/PKJSTokenizerState.m | 65 + jssrc/PKJSTrack.h | 19 + jssrc/PKJSTrack.m | 69 + jssrc/PKJSUppercaseWord.h | 19 + jssrc/PKJSUppercaseWord.m | 73 + jssrc/PKJSUtils.h | 38 + jssrc/PKJSUtils.m | 242 + jssrc/PKJSUtils_macros.h | 33 + jssrc/PKJSValueHolder.h | 26 + jssrc/PKJSValueHolder.m | 35 + jssrc/PKJSWhitespaceState.h | 19 + jssrc/PKJSWhitespaceState.m | 115 + jssrc/PKJSWord.h | 19 + jssrc/PKJSWord.m | 69 + jssrc/PKJSWordState.h | 19 + jssrc/PKJSWordState.m | 103 + res/.svn/all-wcprops | 251 + res/.svn/entries | 1429 +++ res/.svn/prop-base/example1.srgs.svn-base | 5 + res/.svn/prop-base/mini_css.grammar.svn-base | 5 + res/.svn/prop-base/nyt.html.svn-base | 5 + res/.svn/prop-base/yahoo-small.json.svn-base | 5 + res/.svn/text-base/SRGSGrammar.txt.svn-base | 218 + res/.svn/text-base/apple-boss.json.svn-base | 80 + res/.svn/text-base/apple-boss.xml.svn-base | 96 + .../text-base/arithmetic.grammar.svn-base | 10 + res/.svn/text-base/c.grammar.svn-base | 314 + res/.svn/text-base/css.css.svn-base | 71 + res/.svn/text-base/css.grammar.svn-base | 44 + res/.svn/text-base/css2_1.grammar.svn-base | 203 + res/.svn/text-base/date.grammar.svn-base | 40 + res/.svn/text-base/erb.grammar.svn-base | 15 + res/.svn/text-base/example.css.svn-base | 54 + res/.svn/text-base/example.html.svn-base | 28 + res/.svn/text-base/example1.srgs.svn-base | 24 + res/.svn/text-base/html.css.svn-base | 63 + res/.svn/text-base/html.grammar.svn-base | 41 + .../text-base/javascript.grammar.svn-base | 430 + res/.svn/text-base/javascript_ll.txt.svn-base | 133 + res/.svn/text-base/json-old.grammar.svn-base | 26 + res/.svn/text-base/json.css.svn-base | 43 + res/.svn/text-base/json.grammar.svn-base | 60 + .../text-base/json_with_comments.css.svn-base | 50 + .../json_with_comments.grammar.svn-base | 67 + .../json_with_discards.grammar.svn-base | 39 + res/.svn/text-base/mini_css.grammar.svn-base | 18 + res/.svn/text-base/nasty.html.svn-base | 68 + res/.svn/text-base/nonascii.html.svn-base | 1 + .../text-base/nspredicate.grammar.svn-base | 121 + res/.svn/text-base/nyt.html.svn-base | 1843 ++++ res/.svn/text-base/objc.grammar.svn-base | 236 + res/.svn/text-base/proto.grammar.svn-base | 93 + res/.svn/text-base/rubyhash.grammar.svn-base | 35 + .../text-base/small-xml-file.xml.svn-base | 6 + res/.svn/text-base/stuff.txt.svn-base | 8 + res/.svn/text-base/svn-commands.txt.svn-base | 23 + res/.svn/text-base/xml.grammar.svn-base | 388 + res/.svn/text-base/xml_grammar.txt.svn-base | 78 + res/.svn/text-base/xpath1_0.grammar.svn-base | 80 + res/.svn/text-base/xpath_grammar.txt.svn-base | 88 + res/.svn/text-base/yahoo-small.json.svn-base | 18 + res/.svn/text-base/yahoo.json.svn-base | 370 + .../yahoo_with_comments.json.svn-base | 370 + res/.svn/tmp/tempfile.2.tmp | 240 + res/.svn/tmp/tempfile.3.tmp | 266 + res/.svn/tmp/tempfile.tmp | 108 + res/SRGSGrammar.txt | 218 + res/apple-boss.json | 80 + res/apple-boss.xml | 96 + res/arithmetic.grammar | 10 + res/c.grammar | 314 + res/css.css | 71 + res/css.grammar | 44 + res/css2_1.grammar | 203 + res/date.grammar | 40 + res/erb.grammar | 15 + res/example.css | 54 + res/example.html | 28 + res/example1.srgs | 24 + res/html.css | 63 + res/html.grammar | 41 + res/javascript.grammar | 430 + res/javascript_ll.txt | 133 + res/json-old.grammar | 26 + res/json.css | 43 + res/json.grammar | 60 + res/json_with_comments.css | 50 + res/json_with_comments.grammar | 67 + res/json_with_discards.grammar | 39 + res/mini_css.grammar | 18 + res/nasty.html | 68 + res/nonascii.html | 1 + res/nspredicate.grammar | 121 + res/nyt.html | 1843 ++++ res/objc.grammar | 236 + res/proto.grammar | 93 + res/rubyhash.grammar | 35 + res/small-xml-file.xml | 6 + res/stuff.txt | 8 + res/svn-commands.txt | 23 + res/xml.grammar | 388 + res/xml_grammar.txt | 78 + res/xpath1_0.grammar | 80 + res/xpath_grammar.txt | 88 + res/yahoo-small.json | 18 + res/yahoo.json | 370 + res/yahoo_with_comments.json | 370 + src/.svn/all-wcprops | 347 + src/.svn/entries | 1966 ++++ src/.svn/prop-base/PKAlternation.m.svn-base | 5 + src/.svn/prop-base/PKAssembly.m.svn-base | 5 + .../PKCaseInsensitiveLiteral.m.svn-base | 5 + src/.svn/prop-base/PKChar.m.svn-base | 5 + .../prop-base/PKCharacterAssembly.m.svn-base | 5 + .../prop-base/PKCollectionParser.m.svn-base | 5 + src/.svn/prop-base/PKDigit.m.svn-base | 5 + src/.svn/prop-base/PKEmpty.m.svn-base | 5 + src/.svn/prop-base/PKLetter.m.svn-base | 5 + src/.svn/prop-base/PKLiteral.m.svn-base | 5 + src/.svn/prop-base/PKLowercaseWord.m.svn-base | 5 + src/.svn/prop-base/PKNumberState.m.svn-base | 5 + src/.svn/prop-base/PKParser.m.svn-base | 5 + src/.svn/prop-base/PKParserFactory.m.svn-base | 5 + src/.svn/prop-base/PKQuoteState.m.svn-base | 5 + src/.svn/prop-base/PKQuotedString.m.svn-base | 5 + src/.svn/prop-base/PKReader.m.svn-base | 5 + src/.svn/prop-base/PKRepetition.m.svn-base | 5 + src/.svn/prop-base/PKSequence.m.svn-base | 5 + src/.svn/prop-base/PKSpecificChar.m.svn-base | 5 + src/.svn/prop-base/PKSymbol.m.svn-base | 5 + src/.svn/prop-base/PKSymbolNode.m.svn-base | 5 + .../prop-base/PKSymbolRootNode.m.svn-base | 5 + src/.svn/prop-base/PKSymbolState.m.svn-base | 5 + src/.svn/prop-base/PKTerminal.m.svn-base | 5 + src/.svn/prop-base/PKToken.m.svn-base | 5 + .../prop-base/PKTokenArraySource.m.svn-base | 5 + src/.svn/prop-base/PKTokenAssembly.m.svn-base | 5 + src/.svn/prop-base/PKTokenizer.m.svn-base | 5 + .../prop-base/PKTokenizerState.m.svn-base | 5 + src/.svn/prop-base/PKTrack.m.svn-base | 5 + src/.svn/prop-base/PKUppercaseWord.m.svn-base | 5 + .../prop-base/PKWhitespaceState.m.svn-base | 5 + src/.svn/prop-base/PKWord.m.svn-base | 5 + src/.svn/prop-base/PKWordState.m.svn-base | 5 + .../NSArray+ParseKitAdditions.h.svn-base | 14 + .../NSArray+ParseKitAdditions.m.svn-base | 26 + .../NSString+ParseKitAdditions.h.svn-base | 13 + .../NSString+ParseKitAdditions.m.svn-base | 38 + src/.svn/text-base/PKAlternation.m.svn-base | 48 + src/.svn/text-base/PKAny.m.svn-base | 23 + src/.svn/text-base/PKAssembly.m.svn-base | 225 + .../PKCaseInsensitiveLiteral.m.svn-base | 19 + src/.svn/text-base/PKChar.m.svn-base | 22 + .../text-base/PKCharacterAssembly.m.svn-base | 121 + .../text-base/PKCollectionParser.m.svn-base | 98 + src/.svn/text-base/PKComment.m.svn-base | 24 + src/.svn/text-base/PKCommentState.m.svn-base | 141 + src/.svn/text-base/PKDelimitState.m.svn-base | 208 + .../text-base/PKDelimitedString.m.svn-base | 58 + src/.svn/text-base/PKDifference.m.svn-base | 98 + src/.svn/text-base/PKDigit.m.svn-base | 24 + src/.svn/text-base/PKEmpty.m.svn-base | 24 + src/.svn/text-base/PKGrammarParser.h.svn-base | 77 + src/.svn/text-base/PKGrammarParser.m.svn-base | 640 ++ src/.svn/text-base/PKIntersection.m.svn-base | 76 + src/.svn/text-base/PKLetter.m.svn-base | 24 + src/.svn/text-base/PKLiteral.m.svn-base | 55 + src/.svn/text-base/PKLowercaseWord.m.svn-base | 24 + .../PKMultiLineCommentState.m.svn-base | 146 + src/.svn/text-base/PKNegation.m.svn-base | 63 + src/.svn/text-base/PKNumber.m.svn-base | 24 + src/.svn/text-base/PKNumberState.m.svn-base | 258 + src/.svn/text-base/PKParser.m.svn-base | 197 + src/.svn/text-base/PKParserFactory.m.svn-base | 979 ++ src/.svn/text-base/PKPattern.m.svn-base | 45 + src/.svn/text-base/PKQuoteState.m.svn-base | 56 + src/.svn/text-base/PKQuotedString.m.svn-base | 24 + src/.svn/text-base/PKReader.m.svn-base | 69 + src/.svn/text-base/PKRepetition.m.svn-base | 71 + src/.svn/text-base/PKSequence.m.svn-base | 50 + .../PKSingleLineCommentState.m.svn-base | 101 + src/.svn/text-base/PKSpecificChar.m.svn-base | 32 + src/.svn/text-base/PKSymbol.m.svn-base | 73 + src/.svn/text-base/PKSymbolNode.m.svn-base | 76 + .../text-base/PKSymbolRootNode.m.svn-base | 147 + src/.svn/text-base/PKSymbolState.m.svn-base | 107 + src/.svn/text-base/PKTerminal.m.svn-base | 95 + src/.svn/text-base/PKToken.m.svn-base | 233 + .../text-base/PKTokenArraySource.m.svn-base | 79 + src/.svn/text-base/PKTokenAssembly.m.svn-base | 198 + src/.svn/text-base/PKTokenizer.m.svn-base | 233 + .../text-base/PKTokenizerState.m.svn-base | 113 + src/.svn/text-base/PKTrack.m.svn-base | 91 + .../text-base/PKTrackException.m.svn-base | 15 + src/.svn/text-base/PKUppercaseWord.m.svn-base | 24 + src/.svn/text-base/PKWhitespace.m.svn-base | 24 + .../text-base/PKWhitespaceState.m.svn-base | 106 + src/.svn/text-base/PKWord.m.svn-base | 24 + src/.svn/text-base/PKWordState.m.svn-base | 120 + src/.svn/text-base/Reader.h.svn-base | 60 + src/.svn/text-base/RegexKitLite.h.svn-base | 220 + src/.svn/text-base/RegexKitLite.m.svn-base | 1634 +++ src/.svn/text-base/TAssembly.h.svn-base | 138 + src/NSArray+ParseKitAdditions.h | 14 + src/NSArray+ParseKitAdditions.m | 26 + src/NSString+ParseKitAdditions.h | 13 + src/NSString+ParseKitAdditions.m | 38 + src/PKAlternation.m | 54 + src/PKAny.m | 29 + src/PKAssembly.m | 231 + src/PKCaseInsensitiveLiteral.m | 25 + src/PKChar.m | 28 + src/PKCharacterAssembly.m | 127 + src/PKCollectionParser.m | 104 + src/PKComment.m | 30 + src/PKCommentState.m | 147 + src/PKDelimitState.m | 214 + src/PKDelimitedString.m | 64 + src/PKDifference.m | 104 + src/PKDigit.m | 30 + src/PKEmpty.m | 30 + src/PKGrammarParser.h | 83 + src/PKGrammarParser.m | 646 ++ src/PKIntersection.m | 82 + src/PKLetter.m | 30 + src/PKLiteral.m | 61 + src/PKLowercaseWord.m | 30 + src/PKMultiLineCommentState.m | 152 + src/PKNegation.m | 69 + src/PKNumber.m | 30 + src/PKNumberState.m | 264 + src/PKParser.m | 203 + src/PKParserFactory.m | 979 ++ src/PKPattern.m | 51 + src/PKQuoteState.m | 62 + src/PKQuotedString.m | 30 + src/PKReader.m | 75 + src/PKRepetition.m | 77 + src/PKSequence.m | 56 + src/PKSingleLineCommentState.m | 107 + src/PKSpecificChar.m | 38 + src/PKSymbol.m | 79 + src/PKSymbolNode.m | 82 + src/PKSymbolRootNode.m | 153 + src/PKSymbolState.m | 113 + src/PKTerminal.m | 101 + src/PKToken.m | 239 + src/PKTokenArraySource.m | 85 + src/PKTokenAssembly.m | 204 + src/PKTokenizer.m | 239 + src/PKTokenizerState.m | 119 + src/PKTrack.m | 97 + src/PKTrackException.m | 21 + src/PKUppercaseWord.m | 30 + src/PKWhitespace.m | 30 + src/PKWhitespaceState.m | 112 + src/PKWord.m | 30 + src/PKWordState.m | 126 + src/RegexKitLite.h | 220 + src/RegexKitLite.m | 1634 +++ test/.svn/all-wcprops | 1619 +++ test/.svn/entries | 9174 +++++++++++++++++ .../prop-base/TDAlternationTest.h.svn-base | 5 + .../prop-base/TDAlternationTest.m.svn-base | 5 + test/.svn/prop-base/TDCharTest.h.svn-base | 5 + test/.svn/prop-base/TDCharTest.m.svn-base | 5 + .../TDCharacterAssemblyTest.h.svn-base | 5 + .../TDCharacterAssemblyTest.m.svn-base | 5 + test/.svn/prop-base/TDDigitTest.h.svn-base | 5 + test/.svn/prop-base/TDDigitTest.m.svn-base | 5 + .../prop-base/TDFastJsonParser.h.svn-base | 5 + .../prop-base/TDFastJsonParser.m.svn-base | 5 + .../prop-base/TDFastJsonParserTest.h.svn-base | 5 + .../prop-base/TDFastJsonParserTest.m.svn-base | 5 + .../TDHtmlSyntaxHighlighter.h.svn-base | 5 + .../TDHtmlSyntaxHighlighter.m.svn-base | 5 + test/.svn/prop-base/TDJsonParser.h.svn-base | 5 + test/.svn/prop-base/TDJsonParser.m.svn-base | 5 + .../prop-base/TDJsonParserTest.h.svn-base | 5 + .../prop-base/TDJsonParserTest.m.svn-base | 5 + test/.svn/prop-base/TDLetterTest.h.svn-base | 5 + test/.svn/prop-base/TDLetterTest.m.svn-base | 5 + test/.svn/prop-base/TDLiteralTest.h.svn-base | 5 + test/.svn/prop-base/TDLiteralTest.m.svn-base | 5 + .../prop-base/TDLowercaseWordTest.h.svn-base | 5 + .../prop-base/TDLowercaseWordTest.m.svn-base | 5 + .../prop-base/TDMiniCSSAssembler.h.svn-base | 5 + .../prop-base/TDMiniCSSAssembler.m.svn-base | 5 + .../TDMiniCSSAssemblerTest.h.svn-base | 5 + .../TDMiniCSSAssemblerTest.m.svn-base | 5 + test/.svn/prop-base/TDNCName.h.svn-base | 5 + test/.svn/prop-base/TDNCName.m.svn-base | 5 + test/.svn/prop-base/TDNCNameState.h.svn-base | 5 + test/.svn/prop-base/TDNCNameState.m.svn-base | 5 + .../prop-base/TDNonReservedWord.h.svn-base | 5 + .../prop-base/TDNonReservedWord.m.svn-base | 5 + .../prop-base/TDNumberStateTest.h.svn-base | 5 + .../prop-base/TDNumberStateTest.m.svn-base | 5 + .../prop-base/TDParserFactoryTest.h.svn-base | 5 + .../prop-base/TDParserFactoryTest.m.svn-base | 5 + test/.svn/prop-base/TDParserTest.h.svn-base | 5 + test/.svn/prop-base/TDParserTest.m.svn-base | 5 + .../prop-base/TDQuoteStateTest.h.svn-base | 5 + .../prop-base/TDQuoteStateTest.m.svn-base | 5 + test/.svn/prop-base/TDReaderTest.h.svn-base | 5 + test/.svn/prop-base/TDReaderTest.m.svn-base | 5 + .../.svn/prop-base/TDRegularParser.h.svn-base | 5 + .../.svn/prop-base/TDRegularParser.m.svn-base | 5 + .../prop-base/TDRegularParserTest.h.svn-base | 5 + .../prop-base/TDRegularParserTest.m.svn-base | 5 + .../prop-base/TDRepetitionTest.h.svn-base | 5 + .../prop-base/TDRepetitionTest.m.svn-base | 5 + test/.svn/prop-base/TDReservedWord.h.svn-base | 5 + test/.svn/prop-base/TDReservedWord.m.svn-base | 5 + .../prop-base/TDReservedWordTest.h.svn-base | 5 + .../prop-base/TDReservedWordTest.m.svn-base | 5 + .../prop-base/TDRobotCommandTest.h.svn-base | 5 + .../prop-base/TDRobotCommandTest.m.svn-base | 5 + test/.svn/prop-base/TDSequenceTest.h.svn-base | 5 + test/.svn/prop-base/TDSequenceTest.m.svn-base | 5 + .../TDSignificantWhitespaceState.h.svn-base | 5 + .../TDSignificantWhitespaceState.m.svn-base | 5 + ...DSignificantWhitespaceStateTest.h.svn-base | 5 + ...DSignificantWhitespaceStateTest.m.svn-base | 5 + .../prop-base/TDSlashSlashState.h.svn-base | 5 + .../prop-base/TDSlashSlashState.m.svn-base | 5 + .../prop-base/TDSlashStarState.h.svn-base | 5 + .../prop-base/TDSlashStarState.m.svn-base | 5 + test/.svn/prop-base/TDSlashState.h.svn-base | 5 + test/.svn/prop-base/TDSlashState.m.svn-base | 5 + .../prop-base/TDSlashStateTest.h.svn-base | 5 + .../prop-base/TDSlashStateTest.m.svn-base | 5 + .../prop-base/TDSpecificCharTest.h.svn-base | 5 + .../prop-base/TDSpecificCharTest.m.svn-base | 5 + .../prop-base/TDSymbolStateTest.h.svn-base | 5 + .../prop-base/TDSymbolStateTest.m.svn-base | 5 + test/.svn/prop-base/TDSymbolTest.h.svn-base | 5 + test/.svn/prop-base/TDSymbolTest.m.svn-base | 5 + .../prop-base/TDSyntaxHighlighter.h.svn-base | 5 + .../prop-base/TDSyntaxHighlighter.m.svn-base | 5 + test/.svn/prop-base/TDTestScaffold.h.svn-base | 5 + test/.svn/prop-base/TDTestScaffold.m.svn-base | 5 + .../TDTokenArraySourceTest.h.svn-base | 5 + .../TDTokenArraySourceTest.m.svn-base | 5 + .../prop-base/TDTokenAssemblyTest.h.svn-base | 5 + .../prop-base/TDTokenAssemblyTest.m.svn-base | 5 + .../.svn/prop-base/TDTokenizerTest.h.svn-base | 5 + .../.svn/prop-base/TDTokenizerTest.m.svn-base | 5 + test/.svn/prop-base/TDTrackTest.h.svn-base | 5 + test/.svn/prop-base/TDTrackTest.m.svn-base | 5 + .../prop-base/TDUppercaseWordTest.h.svn-base | 5 + .../prop-base/TDUppercaseWordTest.m.svn-base | 5 + .../TDWhitespaceStateTest.h.svn-base | 5 + .../TDWhitespaceStateTest.m.svn-base | 5 + .../TDWordOrReservedState.h.svn-base | 5 + .../TDWordOrReservedState.m.svn-base | 5 + .../.svn/prop-base/TDWordStateTest.h.svn-base | 5 + .../.svn/prop-base/TDWordStateTest.m.svn-base | 5 + test/.svn/prop-base/TDXmlAttribute.h.svn-base | 5 + test/.svn/prop-base/TDXmlAttribute.m.svn-base | 5 + test/.svn/prop-base/TDXmlCdata.h.svn-base | 5 + test/.svn/prop-base/TDXmlCdata.m.svn-base | 5 + test/.svn/prop-base/TDXmlComment.h.svn-base | 5 + test/.svn/prop-base/TDXmlComment.m.svn-base | 5 + test/.svn/prop-base/TDXmlDecl.h.svn-base | 5 + test/.svn/prop-base/TDXmlDecl.m.svn-base | 5 + test/.svn/prop-base/TDXmlDoctype.h.svn-base | 5 + test/.svn/prop-base/TDXmlDoctype.m.svn-base | 5 + test/.svn/prop-base/TDXmlDocument.h.svn-base | 5 + test/.svn/prop-base/TDXmlDocument.m.svn-base | 5 + test/.svn/prop-base/TDXmlEndEntity.h.svn-base | 5 + test/.svn/prop-base/TDXmlEndEntity.m.svn-base | 5 + test/.svn/prop-base/TDXmlEndTag.h.svn-base | 5 + test/.svn/prop-base/TDXmlEndTag.m.svn-base | 5 + test/.svn/prop-base/TDXmlEntity.h.svn-base | 5 + test/.svn/prop-base/TDXmlEntity.m.svn-base | 5 + test/.svn/prop-base/TDXmlEntityRef.h.svn-base | 5 + test/.svn/prop-base/TDXmlEntityRef.m.svn-base | 5 + test/.svn/prop-base/TDXmlFragment.h.svn-base | 5 + test/.svn/prop-base/TDXmlFragment.m.svn-base | 5 + test/.svn/prop-base/TDXmlName.h.svn-base | 5 + test/.svn/prop-base/TDXmlName.m.svn-base | 5 + test/.svn/prop-base/TDXmlNameState.h.svn-base | 5 + test/.svn/prop-base/TDXmlNameState.m.svn-base | 5 + test/.svn/prop-base/TDXmlNameTest.h.svn-base | 5 + test/.svn/prop-base/TDXmlNameTest.m.svn-base | 5 + test/.svn/prop-base/TDXmlNmtoken.h.svn-base | 5 + test/.svn/prop-base/TDXmlNmtoken.m.svn-base | 5 + .../prop-base/TDXmlNmtokenState.h.svn-base | 5 + .../prop-base/TDXmlNmtokenState.m.svn-base | 5 + test/.svn/prop-base/TDXmlNotation.h.svn-base | 5 + test/.svn/prop-base/TDXmlNotation.m.svn-base | 5 + .../TDXmlProcessingInstruction.h.svn-base | 5 + .../TDXmlProcessingInstruction.m.svn-base | 5 + .../TDXmlSignificantWhitespace.h.svn-base | 5 + .../TDXmlSignificantWhitespace.m.svn-base | 5 + test/.svn/prop-base/TDXmlStartTag.h.svn-base | 5 + test/.svn/prop-base/TDXmlStartTag.m.svn-base | 5 + test/.svn/prop-base/TDXmlTerminal.h.svn-base | 5 + test/.svn/prop-base/TDXmlTerminal.m.svn-base | 5 + test/.svn/prop-base/TDXmlText.h.svn-base | 5 + test/.svn/prop-base/TDXmlText.m.svn-base | 5 + test/.svn/prop-base/TDXmlToken.h.svn-base | 5 + test/.svn/prop-base/TDXmlToken.m.svn-base | 5 + .../prop-base/TDXmlTokenAssembly.h.svn-base | 5 + .../prop-base/TDXmlTokenAssembly.m.svn-base | 5 + test/.svn/prop-base/TDXmlTokenizer.h.svn-base | 5 + test/.svn/prop-base/TDXmlTokenizer.m.svn-base | 5 + .../prop-base/TDXmlTokenizerTest.h.svn-base | 5 + .../prop-base/TDXmlTokenizerTest.m.svn-base | 5 + .../.svn/prop-base/TDXmlWhitespace.h.svn-base | 5 + .../.svn/prop-base/TDXmlWhitespace.m.svn-base | 5 + test/.svn/prop-base/XMLReader.h.svn-base | 9 + test/.svn/prop-base/XMLReader.m.svn-base | 9 + test/.svn/prop-base/XMLReaderTest.h.svn-base | 5 + test/.svn/prop-base/XMLReaderTest.m.svn-base | 5 + test/.svn/text-base/EBNFParser.h.svn-base | 45 + test/.svn/text-base/EBNFParser.m.svn-base | 427 + test/.svn/text-base/EBNFParserTest.h.svn-base | 15 + test/.svn/text-base/EBNFParserTest.m.svn-base | 37 + test/.svn/text-base/ERBTest.h.svn-base | 22 + test/.svn/text-base/ERBTest.m.svn-base | 66 + test/.svn/text-base/PKAST.h.svn-base | 27 + test/.svn/text-base/PKAST.m.svn-base | 96 + test/.svn/text-base/PKExclusion.h.svn-base | 16 + test/.svn/text-base/PKExclusion.m.svn-base | 76 + test/.svn/text-base/PKNumberState.h.svn-base | 32 + test/.svn/text-base/PKNumberState.m.svn-base | 145 + test/.svn/text-base/PKParseTree.h.svn-base | 31 + test/.svn/text-base/PKParseTree.m.svn-base | 90 + .../text-base/PKParseTreeAssembler.h.svn-base | 18 + .../text-base/PKParseTreeAssembler.m.svn-base | 175 + test/.svn/text-base/PKRuleNode.h.svn-base | 21 + test/.svn/text-base/PKRuleNode.m.svn-base | 48 + .../PKScientificNumberState.h.svn-base | 24 + .../PKScientificNumberState.m.svn-base | 93 + test/.svn/text-base/PKTokenNode.h.svn-base | 23 + test/.svn/text-base/PKTokenNode.m.svn-base | 49 + test/.svn/text-base/RelaxParser.h.svn-base | 15 + test/.svn/text-base/RelaxParser.m.svn-base | 618 ++ test/.svn/text-base/SAXAssembler.h.svn-base | 15 + test/.svn/text-base/SAXAssembler.m.svn-base | 18 + test/.svn/text-base/SAXTest.h.svn-base | 21 + test/.svn/text-base/SAXTest.m.svn-base | 27 + test/.svn/text-base/SRGSParser.h.svn-base | 88 + test/.svn/text-base/SRGSParser.m.svn-base | 786 ++ test/.svn/text-base/SRGSParserTest.h.svn-base | 20 + test/.svn/text-base/SRGSParserTest.m.svn-base | 196 + .../text-base/TDAlternationTest.h.svn-base | 17 + .../text-base/TDAlternationTest.m.svn-base | 97 + .../TDArithmeticAssembler.h.svn-base | 15 + .../TDArithmeticAssembler.m.svn-base | 58 + .../text-base/TDArithmeticParser.h.svn-base | 33 + .../text-base/TDArithmeticParser.m.svn-base | 247 + .../TDArithmeticParserTest.h.svn-base | 18 + .../TDArithmeticParserTest.m.svn-base | 342 + test/.svn/text-base/TDBlob.h.svn-base | 17 + test/.svn/text-base/TDBlob.m.svn-base | 34 + test/.svn/text-base/TDBlobState.h.svn-base | 15 + test/.svn/text-base/TDBlobState.m.svn-base | 45 + test/.svn/text-base/TDCharTest.h.svn-base | 19 + test/.svn/text-base/TDCharTest.m.svn-base | 59 + .../TDCharacterAssemblyTest.h.svn-base | 18 + .../TDCharacterAssemblyTest.m.svn-base | 59 + .../text-base/TDCommentStateTest.h.svn-base | 19 + .../text-base/TDCommentStateTest.m.svn-base | 486 + .../text-base/TDDelimitStateTest.h.svn-base | 18 + .../text-base/TDDelimitStateTest.m.svn-base | 824 ++ .../text-base/TDDifferenceTest.h.svn-base | 20 + .../text-base/TDDifferenceTest.m.svn-base | 122 + test/.svn/text-base/TDDigitTest.h.svn-base | 19 + test/.svn/text-base/TDDigitTest.m.svn-base | 59 + .../.svn/text-base/TDExclusionTest.h.svn-base | 18 + .../.svn/text-base/TDExclusionTest.m.svn-base | 39 + .../text-base/TDFastJsonParser.h.svn-base | 21 + .../text-base/TDFastJsonParser.m.svn-base | 135 + .../text-base/TDFastJsonParserTest.h.svn-base | 16 + .../text-base/TDFastJsonParserTest.m.svn-base | 33 + .../text-base/TDGenericAssembler.h.svn-base | 25 + .../text-base/TDGenericAssembler.m.svn-base | 169 + .../TDGenericAssemblerTest.h.svn-base | 25 + .../TDGenericAssemblerTest.m.svn-base | 66 + .../TDHtmlSyntaxHighlighter.h.svn-base | 54 + .../TDHtmlSyntaxHighlighter.m.svn-base | 577 ++ .../text-base/TDJavaScriptParser.h.svn-base | 344 + .../text-base/TDJavaScriptParser.m.svn-base | 2392 +++++ .../TDJavaScriptParserTest.h.svn-base | 19 + .../TDJavaScriptParserTest.m.svn-base | 742 ++ test/.svn/text-base/TDJsonParser.h.svn-base | 42 + test/.svn/text-base/TDJsonParser.m.svn-base | 316 + .../text-base/TDJsonParserTest.h.svn-base | 20 + .../text-base/TDJsonParserTest.m.svn-base | 537 + test/.svn/text-base/TDLetterTest.h.svn-base | 19 + test/.svn/text-base/TDLetterTest.m.svn-base | 59 + test/.svn/text-base/TDLiteralTest.h.svn-base | 17 + test/.svn/text-base/TDLiteralTest.m.svn-base | 91 + .../text-base/TDLowercaseWordTest.h.svn-base | 15 + .../text-base/TDLowercaseWordTest.m.svn-base | 57 + .../text-base/TDMiniCSSAssembler.h.svn-base | 21 + .../text-base/TDMiniCSSAssembler.m.svn-base | 184 + .../TDMiniCSSAssemblerTest.h.svn-base | 23 + .../TDMiniCSSAssemblerTest.m.svn-base | 233 + test/.svn/text-base/TDNCName.h.svn-base | 22 + test/.svn/text-base/TDNCName.m.svn-base | 33 + test/.svn/text-base/TDNCNameState.h.svn-base | 15 + test/.svn/text-base/TDNCNameState.m.svn-base | 79 + .../text-base/TDNSPredicateBuilder.h.svn-base | 76 + .../text-base/TDNSPredicateBuilder.m.svn-base | 587 ++ .../TDNSPredicateBuilderTest.h.svn-base | 18 + .../TDNSPredicateBuilderTest.m.svn-base | 213 + .../TDNSPredicateEvaluator.h.svn-base | 28 + .../TDNSPredicateEvaluator.m.svn-base | 224 + .../TDNSPredicateEvaluatorTest.h.svn-base | 22 + .../TDNSPredicateEvaluatorTest.m.svn-base | 272 + test/.svn/text-base/TDNegationTest.h.svn-base | 19 + test/.svn/text-base/TDNegationTest.m.svn-base | 60 + .../text-base/TDNonReservedWord.h.svn-base | 16 + .../text-base/TDNonReservedWord.m.svn-base | 29 + .../text-base/TDNumberStateTest.h.svn-base | 17 + .../text-base/TDNumberStateTest.m.svn-base | 662 ++ .../.svn/text-base/TDParseTreeTest.h.svn-base | 28 + .../.svn/text-base/TDParseTreeTest.m.svn-base | 164 + .../text-base/TDParserBlocksTest.h.svn-base | 17 + .../text-base/TDParserBlocksTest.m.svn-base | 84 + .../TDParserFactoryPatternTest.h.svn-base | 22 + .../TDParserFactoryPatternTest.m.svn-base | 84 + .../text-base/TDParserFactoryTest.h.svn-base | 23 + .../text-base/TDParserFactoryTest.m.svn-base | 1256 +++ .../text-base/TDParserFactoryTest2.h.svn-base | 23 + .../text-base/TDParserFactoryTest2.m.svn-base | 704 ++ .../text-base/TDParserFactoryTest3.h.svn-base | 22 + .../text-base/TDParserFactoryTest3.m.svn-base | 176 + test/.svn/text-base/TDParserTest.h.svn-base | 17 + test/.svn/text-base/TDParserTest.m.svn-base | 177 + test/.svn/text-base/TDPatternTest.h.svn-base | 19 + test/.svn/text-base/TDPatternTest.m.svn-base | 239 + test/.svn/text-base/TDPlistParser.h.svn-base | 35 + test/.svn/text-base/TDPlistParser.m.svn-base | 316 + .../text-base/TDPlistParserTest.h.svn-base | 19 + .../text-base/TDPlistParserTest.m.svn-base | 465 + .../text-base/TDPredicateEvaluator.h.svn-base | 83 + .../text-base/TDPredicateEvaluator.m.svn-base | 656 ++ .../TDPredicateEvaluatorTest.h.svn-base | 20 + .../TDPredicateEvaluatorTest.m.svn-base | 303 + .../text-base/TDQuoteStateTest.h.svn-base | 17 + .../text-base/TDQuoteStateTest.m.svn-base | 104 + test/.svn/text-base/TDReaderTest.h.svn-base | 16 + test/.svn/text-base/TDReaderTest.m.svn-base | 78 + .../.svn/text-base/TDRegularParser.h.svn-base | 35 + .../.svn/text-base/TDRegularParser.m.svn-base | 315 + .../text-base/TDRegularParserTest.h.svn-base | 19 + .../text-base/TDRegularParserTest.m.svn-base | 401 + .../text-base/TDRepetitionTest.h.svn-base | 17 + .../text-base/TDRepetitionTest.m.svn-base | 222 + test/.svn/text-base/TDReservedWord.h.svn-base | 17 + test/.svn/text-base/TDReservedWord.m.svn-base | 43 + .../text-base/TDReservedWordTest.h.svn-base | 15 + .../text-base/TDReservedWordTest.m.svn-base | 41 + .../text-base/TDRobotCommandTest.h.svn-base | 15 + .../text-base/TDRobotCommandTest.m.svn-base | 177 + .../TDScientificNumberStateTest.h.svn-base | 18 + .../TDScientificNumberStateTest.m.svn-base | 1223 +++ test/.svn/text-base/TDSequenceTest.h.svn-base | 17 + test/.svn/text-base/TDSequenceTest.m.svn-base | 251 + .../TDSignificantWhitespaceState.h.svn-base | 24 + .../TDSignificantWhitespaceState.m.svn-base | 69 + ...DSignificantWhitespaceStateTest.h.svn-base | 18 + ...DSignificantWhitespaceStateTest.m.svn-base | 164 + .../text-base/TDSlashSlashState.h.svn-base | 20 + .../text-base/TDSlashSlashState.m.svn-base | 53 + .../text-base/TDSlashStarState.h.svn-base | 20 + .../text-base/TDSlashStarState.m.svn-base | 72 + test/.svn/text-base/TDSlashState.h.svn-base | 27 + test/.svn/text-base/TDSlashState.m.svn-base | 59 + .../text-base/TDSlashStateTest.h.svn-base | 17 + .../text-base/TDSlashStateTest.m.svn-base | 390 + .../text-base/TDSpecificCharTest.h.svn-base | 19 + .../text-base/TDSpecificCharTest.m.svn-base | 59 + .../text-base/TDSymbolStateTest.h.svn-base | 16 + .../text-base/TDSymbolStateTest.m.svn-base | 572 + test/.svn/text-base/TDSymbolTest.h.svn-base | 17 + test/.svn/text-base/TDSymbolTest.m.svn-base | 66 + .../text-base/TDSyntaxHighlighter.h.svn-base | 29 + .../text-base/TDSyntaxHighlighter.m.svn-base | 168 + test/.svn/text-base/TDTestScaffold.h.svn-base | 18 + test/.svn/text-base/TDTestScaffold.m.svn-base | 153 + test/.svn/text-base/TDToken+Blob.h.svn-base | 16 + test/.svn/text-base/TDToken+Blob.m.svn-base | 20 + .../TDTokenArraySourceTest.h.svn-base | 18 + .../TDTokenArraySourceTest.m.svn-base | 51 + .../text-base/TDTokenAssemblyTest.h.svn-base | 17 + .../text-base/TDTokenAssemblyTest.m.svn-base | 292 + test/.svn/text-base/TDTokenTest.h.svn-base | 15 + test/.svn/text-base/TDTokenTest.m.svn-base | 88 + .../TDTokenizer+BlobState.h.svn-base | 15 + .../TDTokenizer+BlobState.m.svn-base | 36 + .../TDTokenizerBlocksTest.h.svn-base | 18 + .../TDTokenizerBlocksTest.m.svn-base | 38 + .../text-base/TDTokenizerStateTest.h.svn-base | 17 + .../text-base/TDTokenizerStateTest.m.svn-base | 172 + .../.svn/text-base/TDTokenizerTest.h.svn-base | 18 + .../.svn/text-base/TDTokenizerTest.m.svn-base | 621 ++ test/.svn/text-base/TDTrackTest.h.svn-base | 15 + test/.svn/text-base/TDTrackTest.m.svn-base | 112 + .../text-base/TDUppercaseWordTest.h.svn-base | 15 + .../text-base/TDUppercaseWordTest.m.svn-base | 58 + .../TDWhitespaceStateTest.h.svn-base | 16 + .../TDWhitespaceStateTest.m.svn-base | 324 + .../TDWordOrReservedState.h.svn-base | 25 + .../TDWordOrReservedState.m.svn-base | 42 + .../.svn/text-base/TDWordStateTest.h.svn-base | 16 + .../.svn/text-base/TDWordStateTest.m.svn-base | 112 + test/.svn/text-base/TDXMLParser.h.svn-base | 15 + test/.svn/text-base/TDXMLParser.m.svn-base | 15 + .../.svn/text-base/TDXMLParserTest.h.svn-base | 21 + .../.svn/text-base/TDXMLParserTest.m.svn-base | 423 + test/.svn/text-base/TDXmlAttribute.h.svn-base | 16 + test/.svn/text-base/TDXmlAttribute.m.svn-base | 48 + test/.svn/text-base/TDXmlCdata.h.svn-base | 16 + test/.svn/text-base/TDXmlCdata.m.svn-base | 48 + test/.svn/text-base/TDXmlComment.h.svn-base | 16 + test/.svn/text-base/TDXmlComment.m.svn-base | 48 + test/.svn/text-base/TDXmlDecl.h.svn-base | 16 + test/.svn/text-base/TDXmlDecl.m.svn-base | 48 + test/.svn/text-base/TDXmlDoctype.h.svn-base | 16 + test/.svn/text-base/TDXmlDoctype.m.svn-base | 48 + test/.svn/text-base/TDXmlDocument.h.svn-base | 16 + test/.svn/text-base/TDXmlDocument.m.svn-base | 48 + test/.svn/text-base/TDXmlEndEntity.h.svn-base | 16 + test/.svn/text-base/TDXmlEndEntity.m.svn-base | 48 + test/.svn/text-base/TDXmlEndTag.h.svn-base | 16 + test/.svn/text-base/TDXmlEndTag.m.svn-base | 48 + test/.svn/text-base/TDXmlEntity.h.svn-base | 16 + test/.svn/text-base/TDXmlEntity.m.svn-base | 48 + test/.svn/text-base/TDXmlEntityRef.h.svn-base | 16 + test/.svn/text-base/TDXmlEntityRef.m.svn-base | 48 + test/.svn/text-base/TDXmlFragment.h.svn-base | 16 + test/.svn/text-base/TDXmlFragment.m.svn-base | 48 + test/.svn/text-base/TDXmlName.h.svn-base | 15 + test/.svn/text-base/TDXmlName.m.svn-base | 33 + test/.svn/text-base/TDXmlNameState.h.svn-base | 15 + test/.svn/text-base/TDXmlNameState.m.svn-base | 81 + test/.svn/text-base/TDXmlNameTest.h.svn-base | 16 + test/.svn/text-base/TDXmlNameTest.m.svn-base | 62 + test/.svn/text-base/TDXmlNmtoken.h.svn-base | 15 + test/.svn/text-base/TDXmlNmtoken.m.svn-base | 24 + .../text-base/TDXmlNmtokenState.h.svn-base | 15 + .../text-base/TDXmlNmtokenState.m.svn-base | 59 + test/.svn/text-base/TDXmlNotation.h.svn-base | 16 + test/.svn/text-base/TDXmlNotation.m.svn-base | 48 + .../TDXmlProcessingInstruction.h.svn-base | 16 + .../TDXmlProcessingInstruction.m.svn-base | 48 + .../TDXmlSignificantWhitespace.h.svn-base | 16 + .../TDXmlSignificantWhitespace.m.svn-base | 48 + test/.svn/text-base/TDXmlStartTag.h.svn-base | 16 + test/.svn/text-base/TDXmlStartTag.m.svn-base | 48 + test/.svn/text-base/TDXmlTerminal.h.svn-base | 17 + test/.svn/text-base/TDXmlTerminal.m.svn-base | 20 + test/.svn/text-base/TDXmlText.h.svn-base | 16 + test/.svn/text-base/TDXmlText.m.svn-base | 51 + test/.svn/text-base/TDXmlToken.h.svn-base | 89 + test/.svn/text-base/TDXmlToken.m.svn-base | 203 + .../text-base/TDXmlTokenAssembly.h.svn-base | 18 + .../text-base/TDXmlTokenAssembly.m.svn-base | 150 + test/.svn/text-base/TDXmlTokenizer.h.svn-base | 21 + test/.svn/text-base/TDXmlTokenizer.m.svn-base | 63 + .../text-base/TDXmlTokenizerTest.h.svn-base | 17 + .../text-base/TDXmlTokenizerTest.m.svn-base | 51 + .../.svn/text-base/TDXmlWhitespace.h.svn-base | 16 + .../.svn/text-base/TDXmlWhitespace.m.svn-base | 48 + test/.svn/text-base/Tests-Info.plist.svn-base | 22 + test/.svn/text-base/XMLReader.h.svn-base | 245 + test/.svn/text-base/XMLReader.m.svn-base | 425 + test/.svn/text-base/XMLReaderTest.h.svn-base | 16 + test/.svn/text-base/XMLReaderTest.m.svn-base | 27 + test/.svn/text-base/XPathAssembler.h.svn-base | 19 + test/.svn/text-base/XPathAssembler.m.svn-base | 59 + test/.svn/text-base/XPathContext.h.svn-base | 29 + test/.svn/text-base/XPathContext.m.svn-base | 37 + test/.svn/text-base/XPathParser.h.svn-base | 96 + test/.svn/text-base/XPathParser.m.svn-base | 973 ++ .../XPathParserGrammarTest.h.svn-base | 20 + .../XPathParserGrammarTest.m.svn-base | 286 + .../.svn/text-base/XPathParserTest.h.svn-base | 20 + .../.svn/text-base/XPathParserTest.m.svn-base | 303 + test/.svn/tmp/tempfile.2.tmp | 2392 +++++ test/.svn/tmp/tempfile.3.tmp | 1183 +++ test/.svn/tmp/tempfile.tmp | 130 + test/EBNFParser.h | 51 + test/EBNFParser.m | 433 + test/EBNFParserTest.h | 21 + test/EBNFParserTest.m | 43 + test/ERBTest.h | 28 + test/ERBTest.m | 72 + test/PKAST.h | 33 + test/PKAST.m | 102 + test/PKExclusion.h | 22 + test/PKExclusion.m | 82 + test/PKNumberState.h | 38 + test/PKNumberState.m | 151 + test/PKParseTree.h | 37 + test/PKParseTree.m | 96 + test/PKParseTreeAssembler.h | 24 + test/PKParseTreeAssembler.m | 181 + test/PKRuleNode.h | 27 + test/PKRuleNode.m | 54 + test/PKScientificNumberState.h | 30 + test/PKScientificNumberState.m | 99 + test/PKTokenNode.h | 29 + test/PKTokenNode.m | 55 + test/RelaxParser.h | 21 + test/RelaxParser.m | 624 ++ test/SAXAssembler.h | 21 + test/SAXAssembler.m | 24 + test/SAXTest.h | 27 + test/SAXTest.m | 33 + test/SRGSParser.h | 94 + test/SRGSParser.m | 792 ++ test/SRGSParserTest.h | 26 + test/SRGSParserTest.m | 202 + test/TDAlternationTest.h | 23 + test/TDAlternationTest.m | 103 + test/TDArithmeticAssembler.h | 21 + test/TDArithmeticAssembler.m | 64 + test/TDArithmeticParser.h | 39 + test/TDArithmeticParser.m | 253 + test/TDArithmeticParserTest.h | 24 + test/TDArithmeticParserTest.m | 348 + test/TDBlob.h | 23 + test/TDBlob.m | 40 + test/TDBlobState.h | 21 + test/TDBlobState.m | 51 + test/TDCharTest.h | 25 + test/TDCharTest.m | 65 + test/TDCharacterAssemblyTest.h | 24 + test/TDCharacterAssemblyTest.m | 65 + test/TDCommentStateTest.h | 25 + test/TDCommentStateTest.m | 492 + test/TDDelimitStateTest.h | 24 + test/TDDelimitStateTest.m | 830 ++ test/TDDifferenceTest.h | 26 + test/TDDifferenceTest.m | 128 + test/TDDigitTest.h | 25 + test/TDDigitTest.m | 65 + test/TDExclusionTest.h | 24 + test/TDExclusionTest.m | 45 + test/TDFastJsonParser.h | 27 + test/TDFastJsonParser.m | 141 + test/TDFastJsonParserTest.h | 22 + test/TDFastJsonParserTest.m | 39 + test/TDGenericAssembler.h | 31 + test/TDGenericAssembler.m | 175 + test/TDGenericAssemblerTest.h | 31 + test/TDGenericAssemblerTest.m | 72 + test/TDHtmlSyntaxHighlighter.h | 60 + test/TDHtmlSyntaxHighlighter.m | 583 ++ test/TDJavaScriptParser.h | 350 + test/TDJavaScriptParser.m | 2398 +++++ test/TDJavaScriptParserTest.h | 25 + test/TDJavaScriptParserTest.m | 748 ++ test/TDJsonParser.h | 48 + test/TDJsonParser.m | 322 + test/TDJsonParserTest.h | 26 + test/TDJsonParserTest.m | 543 + test/TDLetterTest.h | 25 + test/TDLetterTest.m | 65 + test/TDLiteralTest.h | 23 + test/TDLiteralTest.m | 97 + test/TDLowercaseWordTest.h | 21 + test/TDLowercaseWordTest.m | 63 + test/TDMiniCSSAssembler.h | 27 + test/TDMiniCSSAssembler.m | 190 + test/TDMiniCSSAssemblerTest.h | 29 + test/TDMiniCSSAssemblerTest.m | 239 + test/TDNCName.h | 28 + test/TDNCName.m | 39 + test/TDNCNameState.h | 21 + test/TDNCNameState.m | 85 + test/TDNSPredicateBuilder.h | 82 + test/TDNSPredicateBuilder.m | 593 ++ test/TDNSPredicateBuilderTest.h | 24 + test/TDNSPredicateBuilderTest.m | 219 + test/TDNSPredicateEvaluator.h | 34 + test/TDNSPredicateEvaluator.m | 230 + test/TDNSPredicateEvaluatorTest.h | 28 + test/TDNSPredicateEvaluatorTest.m | 278 + test/TDNegationTest.h | 25 + test/TDNegationTest.m | 66 + test/TDNonReservedWord.h | 22 + test/TDNonReservedWord.m | 35 + test/TDNumberStateTest.h | 23 + test/TDNumberStateTest.m | 668 ++ test/TDParseTreeTest.h | 34 + test/TDParseTreeTest.m | 170 + test/TDParserBlocksTest.h | 23 + test/TDParserBlocksTest.m | 90 + test/TDParserFactoryPatternTest.h | 28 + test/TDParserFactoryPatternTest.m | 90 + test/TDParserFactoryTest.h | 23 + test/TDParserFactoryTest.m | 1256 +++ test/TDParserFactoryTest2.h | 29 + test/TDParserFactoryTest2.m | 710 ++ test/TDParserFactoryTest3.h | 28 + test/TDParserFactoryTest3.m | 182 + test/TDParserTest.h | 23 + test/TDParserTest.m | 183 + test/TDPatternTest.h | 25 + test/TDPatternTest.m | 245 + test/TDPlistParser.h | 41 + test/TDPlistParser.m | 322 + test/TDPlistParserTest.h | 25 + test/TDPlistParserTest.m | 471 + test/TDPredicateEvaluator.h | 89 + test/TDPredicateEvaluator.m | 662 ++ test/TDPredicateEvaluatorTest.h | 26 + test/TDPredicateEvaluatorTest.m | 309 + test/TDQuoteStateTest.h | 23 + test/TDQuoteStateTest.m | 110 + test/TDReaderTest.h | 22 + test/TDReaderTest.m | 84 + test/TDRegularParser.h | 41 + test/TDRegularParser.m | 321 + test/TDRegularParserTest.h | 25 + test/TDRegularParserTest.m | 407 + test/TDRepetitionTest.h | 23 + test/TDRepetitionTest.m | 228 + test/TDReservedWord.h | 23 + test/TDReservedWord.m | 49 + test/TDReservedWordTest.h | 21 + test/TDReservedWordTest.m | 47 + test/TDRobotCommandTest.h | 21 + test/TDRobotCommandTest.m | 183 + test/TDScientificNumberStateTest.h | 24 + test/TDScientificNumberStateTest.m | 1229 +++ test/TDSequenceTest.h | 23 + test/TDSequenceTest.m | 257 + test/TDSignificantWhitespaceState.h | 30 + test/TDSignificantWhitespaceState.m | 75 + test/TDSignificantWhitespaceStateTest.h | 24 + test/TDSignificantWhitespaceStateTest.m | 170 + test/TDSlashSlashState.h | 26 + test/TDSlashSlashState.m | 59 + test/TDSlashStarState.h | 26 + test/TDSlashStarState.m | 78 + test/TDSlashState.h | 33 + test/TDSlashState.m | 65 + test/TDSlashStateTest.h | 23 + test/TDSlashStateTest.m | 396 + test/TDSpecificCharTest.h | 25 + test/TDSpecificCharTest.m | 65 + test/TDSymbolStateTest.h | 22 + test/TDSymbolStateTest.m | 578 ++ test/TDSymbolTest.h | 23 + test/TDSymbolTest.m | 72 + test/TDSyntaxHighlighter.h | 35 + test/TDSyntaxHighlighter.m | 174 + test/TDTestScaffold.h | 24 + test/TDTestScaffold.m | 159 + test/TDToken+Blob.h | 16 + test/TDToken+Blob.m | 20 + test/TDTokenArraySourceTest.h | 24 + test/TDTokenArraySourceTest.m | 57 + test/TDTokenAssemblyTest.h | 23 + test/TDTokenAssemblyTest.m | 298 + test/TDTokenTest.h | 21 + test/TDTokenTest.m | 94 + test/TDTokenizer+BlobState.h | 15 + test/TDTokenizer+BlobState.m | 36 + test/TDTokenizerBlocksTest.h | 24 + test/TDTokenizerBlocksTest.m | 44 + test/TDTokenizerStateTest.h | 23 + test/TDTokenizerStateTest.m | 178 + test/TDTokenizerTest.h | 24 + test/TDTokenizerTest.m | 627 ++ test/TDTrackTest.h | 21 + test/TDTrackTest.m | 118 + test/TDUppercaseWordTest.h | 21 + test/TDUppercaseWordTest.m | 64 + test/TDWhitespaceStateTest.h | 22 + test/TDWhitespaceStateTest.m | 330 + test/TDWordOrReservedState.h | 31 + test/TDWordOrReservedState.m | 48 + test/TDWordStateTest.h | 22 + test/TDWordStateTest.m | 118 + test/TDXMLParser.h | 21 + test/TDXMLParser.m | 21 + test/TDXMLParserTest.h | 27 + test/TDXMLParserTest.m | 429 + test/TDXmlAttribute.h | 22 + test/TDXmlAttribute.m | 54 + test/TDXmlCdata.h | 22 + test/TDXmlCdata.m | 54 + test/TDXmlComment.h | 22 + test/TDXmlComment.m | 54 + test/TDXmlDecl.h | 22 + test/TDXmlDecl.m | 54 + test/TDXmlDoctype.h | 22 + test/TDXmlDoctype.m | 54 + test/TDXmlDocument.h | 22 + test/TDXmlDocument.m | 54 + test/TDXmlEndEntity.h | 22 + test/TDXmlEndEntity.m | 54 + test/TDXmlEndTag.h | 22 + test/TDXmlEndTag.m | 54 + test/TDXmlEntity.h | 22 + test/TDXmlEntity.m | 54 + test/TDXmlEntityRef.h | 22 + test/TDXmlEntityRef.m | 54 + test/TDXmlFragment.h | 22 + test/TDXmlFragment.m | 54 + test/TDXmlName.h | 21 + test/TDXmlName.m | 39 + test/TDXmlNameState.h | 21 + test/TDXmlNameState.m | 87 + test/TDXmlNameTest.h | 22 + test/TDXmlNameTest.m | 68 + test/TDXmlNmtoken.h | 21 + test/TDXmlNmtoken.m | 30 + test/TDXmlNmtokenState.h | 21 + test/TDXmlNmtokenState.m | 65 + test/TDXmlNotation.h | 22 + test/TDXmlNotation.m | 54 + test/TDXmlProcessingInstruction.h | 22 + test/TDXmlProcessingInstruction.m | 54 + test/TDXmlSignificantWhitespace.h | 22 + test/TDXmlSignificantWhitespace.m | 54 + test/TDXmlStartTag.h | 22 + test/TDXmlStartTag.m | 54 + test/TDXmlTerminal.h | 23 + test/TDXmlTerminal.m | 26 + test/TDXmlText.h | 22 + test/TDXmlText.m | 57 + test/TDXmlToken.h | 95 + test/TDXmlToken.m | 209 + test/TDXmlTokenAssembly.h | 24 + test/TDXmlTokenAssembly.m | 156 + test/TDXmlTokenizer.h | 27 + test/TDXmlTokenizer.m | 69 + test/TDXmlTokenizerTest.h | 23 + test/TDXmlTokenizerTest.m | 57 + test/TDXmlWhitespace.h | 22 + test/TDXmlWhitespace.m | 54 + test/Tests-Info.plist | 22 + test/XMLReader.h | 251 + test/XMLReader.m | 425 + test/XMLReaderTest.h | 22 + test/XMLReaderTest.m | 33 + test/XPathAssembler.h | 25 + test/XPathAssembler.m | 65 + test/XPathContext.h | 35 + test/XPathContext.m | 43 + test/XPathParser.h | 102 + test/XPathParser.m | 979 ++ test/XPathParserGrammarTest.h | 26 + test/XPathParserGrammarTest.m | 292 + test/XPathParserTest.h | 26 + test/XPathParserTest.m | 309 + 1476 files changed, 180135 insertions(+) create mode 100644 .gitignore create mode 100644 English.lproj/.svn/all-wcprops create mode 100644 English.lproj/.svn/entries create mode 100644 English.lproj/.svn/prop-base/InfoPlist.strings.svn-base create mode 100644 English.lproj/.svn/text-base/InfoPlist.strings.svn-base create mode 100644 English.lproj/InfoPlist.strings create mode 100644 Info.plist create mode 100644 JSParseKit-Info.plist create mode 100644 License.txt create mode 100644 ParseKit.xcodeproj/.svn/all-wcprops create mode 100644 ParseKit.xcodeproj/.svn/dir-prop-base create mode 100644 ParseKit.xcodeproj/.svn/entries create mode 100644 ParseKit.xcodeproj/.svn/text-base/project.pbxproj.svn-base create mode 100644 ParseKit.xcodeproj/.svn/tmp/project.pbxproj.tmp create mode 100644 ParseKit.xcodeproj/project.pbxproj create mode 100644 ParseKitMobile_Prefix.pch create mode 100644 ParseKit_Prefix.pch create mode 100644 README.txt create mode 100644 debugapp/.svn/all-wcprops create mode 100644 debugapp/.svn/entries create mode 100644 debugapp/.svn/text-base/DebugApp-Info.plist.svn-base create mode 100644 debugapp/.svn/text-base/DebugAppDelegate.h.svn-base create mode 100644 debugapp/.svn/text-base/DebugAppDelegate.m.svn-base create mode 100644 debugapp/.svn/text-base/DebugAppMainMenu.xib.svn-base create mode 100644 debugapp/.svn/text-base/JSONAssembler.h.svn-base create mode 100644 debugapp/.svn/text-base/JSONAssembler.m.svn-base create mode 100644 debugapp/.svn/text-base/main.m.svn-base create mode 100644 debugapp/.svn/tmp/tempfile.tmp create mode 100644 debugapp/DebugApp-Info.plist create mode 100644 debugapp/DebugAppDelegate.h create mode 100644 debugapp/DebugAppDelegate.m create mode 100644 debugapp/DebugAppMainMenu.xib create mode 100644 debugapp/JSONAssembler.h create mode 100644 debugapp/JSONAssembler.m create mode 100644 debugapp/main.m create mode 100644 demoapp/.svn/all-wcprops create mode 100644 demoapp/.svn/entries create mode 100644 demoapp/.svn/text-base/DemoApp-Info.plist.svn-base create mode 100644 demoapp/.svn/text-base/DemoAppDelegate.h.svn-base create mode 100644 demoapp/.svn/text-base/DemoAppDelegate.m.svn-base create mode 100644 demoapp/.svn/text-base/DemoAppMainMenu.xib.svn-base create mode 100644 demoapp/.svn/text-base/DemoTokensViewController.h.svn-base create mode 100644 demoapp/.svn/text-base/DemoTokensViewController.m.svn-base create mode 100644 demoapp/.svn/text-base/DemoTreesViewController.h.svn-base create mode 100644 demoapp/.svn/text-base/DemoTreesViewController.m.svn-base create mode 100644 demoapp/.svn/text-base/PKParseTreeView.h.svn-base create mode 100644 demoapp/.svn/text-base/PKParseTreeView.m.svn-base create mode 100644 demoapp/.svn/text-base/TDGutterView.h.svn-base create mode 100644 demoapp/.svn/text-base/TDGutterView.m.svn-base create mode 100644 demoapp/.svn/text-base/TDSourceCodeTextView.h.svn-base create mode 100644 demoapp/.svn/text-base/TDSourceCodeTextView.m.svn-base create mode 100644 demoapp/.svn/text-base/TokensView.xib.svn-base create mode 100644 demoapp/.svn/text-base/TreesView.xib.svn-base create mode 100644 demoapp/.svn/text-base/main.m.svn-base create mode 100644 demoapp/DemoApp-Info.plist create mode 100644 demoapp/DemoAppDelegate.h create mode 100644 demoapp/DemoAppDelegate.m create mode 100644 demoapp/DemoAppMainMenu.xib create mode 100644 demoapp/DemoTokensViewController.h create mode 100644 demoapp/DemoTokensViewController.m create mode 100644 demoapp/DemoTreesViewController.h create mode 100644 demoapp/DemoTreesViewController.m create mode 100644 demoapp/PKParseTreeView.h create mode 100644 demoapp/PKParseTreeView.m create mode 100644 demoapp/TDGutterView.h create mode 100644 demoapp/TDGutterView.m create mode 100644 demoapp/TDSourceCodeTextView.h create mode 100644 demoapp/TDSourceCodeTextView.m create mode 100644 demoapp/TokensView.xib create mode 100644 demoapp/TreesView.xib create mode 100644 demoapp/main.m create mode 100644 docs/.svn/all-wcprops create mode 100644 docs/.svn/dir-prop-base create mode 100644 docs/.svn/entries create mode 100644 docs/.svn/prop-base/ParseKit.key.svn-base create mode 100644 docs/.svn/text-base/Doxyfile.svn-base create mode 100644 docs/.svn/text-base/ParseKit.key.svn-base create mode 100644 docs/.svn/tmp/tempfile.2.tmp create mode 100644 docs/Doxyfile create mode 100644 docs/web/.svn/all-wcprops create mode 100644 docs/web/.svn/entries create mode 100644 docs/web/.svn/text-base/common-footer.inc.svn-base create mode 100644 docs/web/.svn/text-base/common-header.inc.svn-base create mode 100644 docs/web/.svn/text-base/common-nav.inc.svn-base create mode 100644 docs/web/.svn/text-base/grammars.html.svn-base create mode 100644 docs/web/.svn/text-base/htaccess.svn-base create mode 100644 docs/web/.svn/text-base/index.html.svn-base create mode 100644 docs/web/.svn/text-base/iphone.html.svn-base create mode 100644 docs/web/.svn/text-base/tokenization.html.svn-base create mode 100644 docs/web/common-footer.inc create mode 100644 docs/web/common-header.inc create mode 100644 docs/web/common-nav.inc create mode 100644 docs/web/css/.svn/all-wcprops create mode 100644 docs/web/css/.svn/entries create mode 100644 docs/web/css/.svn/text-base/master.css.svn-base create mode 100644 docs/web/css/master.css create mode 100644 docs/web/grammars.html create mode 100644 docs/web/htaccess create mode 100644 docs/web/img/.svn/all-wcprops create mode 100644 docs/web/img/.svn/entries create mode 100644 docs/web/img/.svn/prop-base/step1a.png.svn-base create mode 100644 docs/web/img/.svn/prop-base/step1a.psd.svn-base create mode 100644 docs/web/img/.svn/prop-base/step1b.png.svn-base create mode 100644 docs/web/img/.svn/prop-base/step1b.psd.svn-base create mode 100644 docs/web/img/.svn/prop-base/step2a.png.svn-base create mode 100644 docs/web/img/.svn/prop-base/step2a.psd.svn-base create mode 100644 docs/web/img/.svn/prop-base/step3a.png.svn-base create mode 100644 docs/web/img/.svn/prop-base/step3a.psd.svn-base create mode 100644 docs/web/img/.svn/prop-base/step4a.png.svn-base create mode 100644 docs/web/img/.svn/prop-base/step4a.psd.svn-base create mode 100644 docs/web/img/.svn/prop-base/step4b.png.svn-base create mode 100644 docs/web/img/.svn/prop-base/step4b.psd.svn-base create mode 100644 docs/web/img/.svn/prop-base/step5a.png.svn-base create mode 100644 docs/web/img/.svn/prop-base/step6a.png.svn-base create mode 100644 docs/web/img/.svn/prop-base/step7a.png.svn-base create mode 100644 docs/web/img/.svn/text-base/step1a.png.svn-base create mode 100644 docs/web/img/.svn/text-base/step1a.psd.svn-base create mode 100644 docs/web/img/.svn/text-base/step1b.png.svn-base create mode 100644 docs/web/img/.svn/text-base/step1b.psd.svn-base create mode 100644 docs/web/img/.svn/text-base/step2a.png.svn-base create mode 100644 docs/web/img/.svn/text-base/step2a.psd.svn-base create mode 100644 docs/web/img/.svn/text-base/step3a.png.svn-base create mode 100644 docs/web/img/.svn/text-base/step3a.psd.svn-base create mode 100644 docs/web/img/.svn/text-base/step4a.png.svn-base create mode 100644 docs/web/img/.svn/text-base/step4a.psd.svn-base create mode 100644 docs/web/img/.svn/text-base/step4b.png.svn-base create mode 100644 docs/web/img/.svn/text-base/step4b.psd.svn-base create mode 100644 docs/web/img/.svn/text-base/step5a.png.svn-base create mode 100644 docs/web/img/.svn/text-base/step6a.png.svn-base create mode 100644 docs/web/img/.svn/text-base/step7a.png.svn-base create mode 100644 docs/web/img/step1a.png create mode 100644 docs/web/img/step1a.psd create mode 100644 docs/web/img/step1b.png create mode 100644 docs/web/img/step1b.psd create mode 100644 docs/web/img/step2a.png create mode 100644 docs/web/img/step2a.psd create mode 100644 docs/web/img/step3a.png create mode 100644 docs/web/img/step3a.psd create mode 100644 docs/web/img/step4a.png create mode 100644 docs/web/img/step4a.psd create mode 100644 docs/web/img/step4b.png create mode 100644 docs/web/img/step4b.psd create mode 100644 docs/web/img/step5a.png create mode 100644 docs/web/img/step6a.png create mode 100644 docs/web/img/step7a.png create mode 100644 docs/web/index.html create mode 100644 docs/web/iphone.html create mode 100644 docs/web/tokenization.html create mode 100644 frameworks/.svn/all-wcprops create mode 100644 frameworks/.svn/entries create mode 100644 frameworks/OCMock.framework/.svn/all-wcprops create mode 100644 frameworks/OCMock.framework/.svn/entries create mode 100644 frameworks/OCMock.framework/.svn/prop-base/Headers.svn-base create mode 100644 frameworks/OCMock.framework/.svn/prop-base/OCMock.svn-base create mode 100644 frameworks/OCMock.framework/.svn/prop-base/Resources.svn-base create mode 100644 frameworks/OCMock.framework/.svn/text-base/Headers.svn-base create mode 100644 frameworks/OCMock.framework/.svn/text-base/OCMock.svn-base create mode 100644 frameworks/OCMock.framework/.svn/text-base/Resources.svn-base create mode 120000 frameworks/OCMock.framework/Headers create mode 120000 frameworks/OCMock.framework/OCMock create mode 120000 frameworks/OCMock.framework/Resources create mode 100644 frameworks/OCMock.framework/Versions/.svn/all-wcprops create mode 100644 frameworks/OCMock.framework/Versions/.svn/entries create mode 100644 frameworks/OCMock.framework/Versions/.svn/prop-base/Current.svn-base create mode 100644 frameworks/OCMock.framework/Versions/.svn/text-base/Current.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/.svn/all-wcprops create mode 100644 frameworks/OCMock.framework/Versions/A/.svn/entries create mode 100644 frameworks/OCMock.framework/Versions/A/.svn/prop-base/OCMock.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/.svn/text-base/OCMock.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/.svn/all-wcprops create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/.svn/entries create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMConstraint.h.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMock.h.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMockObject.h.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMockRecorder.h.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/OCMConstraint.h create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/OCMock.h create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/OCMockObject.h create mode 100644 frameworks/OCMock.framework/Versions/A/Headers/OCMockRecorder.h create mode 100755 frameworks/OCMock.framework/Versions/A/OCMock create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/.svn/all-wcprops create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/.svn/entries create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/.svn/text-base/Info.plist.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/.svn/text-base/License.txt.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/all-wcprops create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/entries create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/prop-base/InfoPlist.strings.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/text-base/InfoPlist.strings.svn-base create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/English.lproj/InfoPlist.strings create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/Info.plist create mode 100644 frameworks/OCMock.framework/Versions/A/Resources/License.txt create mode 120000 frameworks/OCMock.framework/Versions/Current create mode 100644 include/.svn/all-wcprops create mode 100644 include/.svn/entries create mode 100644 include/ParseKit/.svn/all-wcprops create mode 100644 include/ParseKit/.svn/entries create mode 100644 include/ParseKit/.svn/prop-base/PKAlternation.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKAssembly.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKCaseInsensitiveLiteral.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKChar.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKCharacterAssembly.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKCollectionParser.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKDigit.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKEmpty.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKLetter.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKLiteral.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKLowercaseWord.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKNumberState.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKParser.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKParserFactory.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKQuoteState.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKQuotedString.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKReader.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKRepetition.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKSequence.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKSpecificChar.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKSymbol.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKSymbolNode.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKSymbolRootNode.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKSymbolState.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKTerminal.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKToken.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKTokenArraySource.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKTokenAssembly.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKTokenizer.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKTokenizerState.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKTrack.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKUppercaseWord.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKWhitespaceState.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKWord.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/PKWordState.h.svn-base create mode 100644 include/ParseKit/.svn/prop-base/ParseKit.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKAlternation.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKAny.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKAssembly.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKCaseInsensitiveLiteral.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKChar.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKCharacterAssembly.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKCollectionParser.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKComment.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKCommentState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKDelimitState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKDelimitedString.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKDifference.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKDigit.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKEmpty.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKIntersection.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKLetter.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKLiteral.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKLowercaseWord.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKMultiLineCommentState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKNegation.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKNumber.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKNumberState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKParser.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKParserFactory.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKPattern.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKQuoteState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKQuotedString.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKReader.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKRepetition.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKSequence.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKSingleLineCommentState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKSpecificChar.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKSymbol.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKSymbolNode.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKSymbolRootNode.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKSymbolState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKTerminal.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKToken.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKTokenArraySource.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKTokenAssembly.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKTokenizer.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKTokenizerState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKTrack.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKTrackException.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKTypes.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKUppercaseWord.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKWhitespace.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKWhitespaceState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKWord.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/PKWordState.h.svn-base create mode 100644 include/ParseKit/.svn/text-base/ParseKit.h.svn-base create mode 100644 include/ParseKit/PKAlternation.h create mode 100644 include/ParseKit/PKAny.h create mode 100644 include/ParseKit/PKAssembly.h create mode 100644 include/ParseKit/PKCaseInsensitiveLiteral.h create mode 100644 include/ParseKit/PKChar.h create mode 100644 include/ParseKit/PKCharacterAssembly.h create mode 100644 include/ParseKit/PKCollectionParser.h create mode 100644 include/ParseKit/PKComment.h create mode 100644 include/ParseKit/PKCommentState.h create mode 100644 include/ParseKit/PKDelimitState.h create mode 100644 include/ParseKit/PKDelimitedString.h create mode 100644 include/ParseKit/PKDifference.h create mode 100644 include/ParseKit/PKDigit.h create mode 100644 include/ParseKit/PKEmpty.h create mode 100644 include/ParseKit/PKIntersection.h create mode 100644 include/ParseKit/PKLetter.h create mode 100644 include/ParseKit/PKLiteral.h create mode 100644 include/ParseKit/PKLowercaseWord.h create mode 100644 include/ParseKit/PKMultiLineCommentState.h create mode 100644 include/ParseKit/PKNegation.h create mode 100644 include/ParseKit/PKNumber.h create mode 100644 include/ParseKit/PKNumberState.h create mode 100644 include/ParseKit/PKParser.h create mode 100644 include/ParseKit/PKParserFactory.h create mode 100644 include/ParseKit/PKPattern.h create mode 100644 include/ParseKit/PKQuoteState.h create mode 100644 include/ParseKit/PKQuotedString.h create mode 100644 include/ParseKit/PKReader.h create mode 100644 include/ParseKit/PKRepetition.h create mode 100644 include/ParseKit/PKSequence.h create mode 100644 include/ParseKit/PKSingleLineCommentState.h create mode 100644 include/ParseKit/PKSpecificChar.h create mode 100644 include/ParseKit/PKSymbol.h create mode 100644 include/ParseKit/PKSymbolNode.h create mode 100644 include/ParseKit/PKSymbolRootNode.h create mode 100644 include/ParseKit/PKSymbolState.h create mode 100644 include/ParseKit/PKTerminal.h create mode 100644 include/ParseKit/PKToken.h create mode 100644 include/ParseKit/PKTokenArraySource.h create mode 100644 include/ParseKit/PKTokenAssembly.h create mode 100644 include/ParseKit/PKTokenizer.h create mode 100644 include/ParseKit/PKTokenizerState.h create mode 100644 include/ParseKit/PKTrack.h create mode 100644 include/ParseKit/PKTrackException.h create mode 100644 include/ParseKit/PKTypes.h create mode 100644 include/ParseKit/PKUppercaseWord.h create mode 100644 include/ParseKit/PKWhitespace.h create mode 100644 include/ParseKit/PKWhitespaceState.h create mode 100644 include/ParseKit/PKWord.h create mode 100644 include/ParseKit/PKWordState.h create mode 100644 include/ParseKit/ParseKit.h create mode 100644 jsdemoapp/.svn/all-wcprops create mode 100644 jsdemoapp/.svn/entries create mode 100644 jsdemoapp/.svn/prop-base/JSDemoAppMainMenu.xib.svn-base create mode 100644 jsdemoapp/.svn/text-base/DefaultValues.plist.svn-base create mode 100644 jsdemoapp/.svn/text-base/JSDemoApp-Info.plist.svn-base create mode 100644 jsdemoapp/.svn/text-base/JSDemoAppDelegate.h.svn-base create mode 100644 jsdemoapp/.svn/text-base/JSDemoAppDelegate.m.svn-base create mode 100644 jsdemoapp/.svn/text-base/JSDemoAppMainMenu.xib.svn-base create mode 100644 jsdemoapp/.svn/text-base/ParserTest.html.svn-base create mode 100644 jsdemoapp/.svn/text-base/Test.html.svn-base create mode 100644 jsdemoapp/.svn/text-base/main.m.svn-base create mode 100644 jsdemoapp/DefaultValues.plist create mode 100644 jsdemoapp/JSDemoApp-Info.plist create mode 100644 jsdemoapp/JSDemoAppDelegate.h create mode 100644 jsdemoapp/JSDemoAppDelegate.m create mode 100644 jsdemoapp/JSDemoAppMainMenu.xib create mode 100644 jsdemoapp/ParserTest.html create mode 100644 jsdemoapp/Test.html create mode 100644 jsdemoapp/main.m create mode 100644 jssrc/.svn/all-wcprops create mode 100644 jssrc/.svn/entries create mode 100644 jssrc/.svn/prop-base/JSParseKit.h.svn-base create mode 100644 jssrc/.svn/prop-base/JSParseKit.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSAssembly.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSAssembly.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSCollectionParser.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSCollectionParser.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSCommentState.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSCommentState.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSNumberState.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSNumberState.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSQuoteState.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSQuoteState.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSSymbolState.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSSymbolState.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSToken.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSToken.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSTokenAssembly.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSTokenAssembly.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSTokenizer.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSTokenizer.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSTokenizerState.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSTokenizerState.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSUtils.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSUtils.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSValueHolder.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSValueHolder.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSWhitespaceState.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSWhitespaceState.m.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSWordState.h.svn-base create mode 100644 jssrc/.svn/prop-base/PKJSWordState.m.svn-base create mode 100644 jssrc/.svn/text-base/JSParseKit.h.svn-base create mode 100644 jssrc/.svn/text-base/JSParseKit.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSAlternation.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSAlternation.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSAny.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSAny.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSAssemblerAdapter.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSAssemblerAdapter.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSAssembly.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSAssembly.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSCaseInsensitiveLiteral.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSCaseInsensitiveLiteral.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSCharacterAssembly.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSCharacterAssembly.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSCollectionParser.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSCollectionParser.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSComment.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSComment.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSCommentState.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSCommentState.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSDelimitState.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSDelimitState.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSDelimitedString.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSDelimitedString.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSEmpty.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSEmpty.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSLiteral.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSLiteral.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSLowercaseWord.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSLowercaseWord.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSNum.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSNum.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSNumberState.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSNumberState.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSParser.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSParser.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSPattern.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSPattern.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSQuoteState.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSQuoteState.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSQuotedString.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSQuotedString.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSRepetition.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSRepetition.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSSequence.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSSequence.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSSymbol.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSSymbol.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSSymbolState.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSSymbolState.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTerminal.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTerminal.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSToken.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSToken.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTokenAssembly.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTokenAssembly.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTokenizer.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTokenizer.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTokenizerState.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTokenizerState.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTrack.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSTrack.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSUppercaseWord.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSUppercaseWord.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSUtils.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSUtils.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSUtils_macros.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSValueHolder.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSValueHolder.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSWhitespaceState.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSWhitespaceState.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSWord.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSWord.m.svn-base create mode 100644 jssrc/.svn/text-base/PKJSWordState.h.svn-base create mode 100644 jssrc/.svn/text-base/PKJSWordState.m.svn-base create mode 100644 jssrc/JSParseKit.h create mode 100644 jssrc/JSParseKit.m create mode 100644 jssrc/PKJSAlternation.h create mode 100644 jssrc/PKJSAlternation.m create mode 100644 jssrc/PKJSAny.h create mode 100644 jssrc/PKJSAny.m create mode 100644 jssrc/PKJSAssemblerAdapter.h create mode 100644 jssrc/PKJSAssemblerAdapter.m create mode 100644 jssrc/PKJSAssembly.h create mode 100644 jssrc/PKJSAssembly.m create mode 100644 jssrc/PKJSCaseInsensitiveLiteral.h create mode 100644 jssrc/PKJSCaseInsensitiveLiteral.m create mode 100644 jssrc/PKJSCharacterAssembly.h create mode 100644 jssrc/PKJSCharacterAssembly.m create mode 100644 jssrc/PKJSCollectionParser.h create mode 100644 jssrc/PKJSCollectionParser.m create mode 100644 jssrc/PKJSComment.h create mode 100644 jssrc/PKJSComment.m create mode 100644 jssrc/PKJSCommentState.h create mode 100644 jssrc/PKJSCommentState.m create mode 100644 jssrc/PKJSDelimitState.h create mode 100644 jssrc/PKJSDelimitState.m create mode 100644 jssrc/PKJSDelimitedString.h create mode 100644 jssrc/PKJSDelimitedString.m create mode 100644 jssrc/PKJSEmpty.h create mode 100644 jssrc/PKJSEmpty.m create mode 100644 jssrc/PKJSLiteral.h create mode 100644 jssrc/PKJSLiteral.m create mode 100644 jssrc/PKJSLowercaseWord.h create mode 100644 jssrc/PKJSLowercaseWord.m create mode 100644 jssrc/PKJSNum.h create mode 100644 jssrc/PKJSNum.m create mode 100644 jssrc/PKJSNumberState.h create mode 100644 jssrc/PKJSNumberState.m create mode 100644 jssrc/PKJSParser.h create mode 100644 jssrc/PKJSParser.m create mode 100644 jssrc/PKJSPattern.h create mode 100644 jssrc/PKJSPattern.m create mode 100644 jssrc/PKJSQuoteState.h create mode 100644 jssrc/PKJSQuoteState.m create mode 100644 jssrc/PKJSQuotedString.h create mode 100644 jssrc/PKJSQuotedString.m create mode 100644 jssrc/PKJSRepetition.h create mode 100644 jssrc/PKJSRepetition.m create mode 100644 jssrc/PKJSSequence.h create mode 100644 jssrc/PKJSSequence.m create mode 100644 jssrc/PKJSSymbol.h create mode 100644 jssrc/PKJSSymbol.m create mode 100644 jssrc/PKJSSymbolState.h create mode 100644 jssrc/PKJSSymbolState.m create mode 100644 jssrc/PKJSTerminal.h create mode 100644 jssrc/PKJSTerminal.m create mode 100644 jssrc/PKJSToken.h create mode 100644 jssrc/PKJSToken.m create mode 100644 jssrc/PKJSTokenAssembly.h create mode 100644 jssrc/PKJSTokenAssembly.m create mode 100644 jssrc/PKJSTokenizer.h create mode 100644 jssrc/PKJSTokenizer.m create mode 100644 jssrc/PKJSTokenizerState.h create mode 100644 jssrc/PKJSTokenizerState.m create mode 100644 jssrc/PKJSTrack.h create mode 100644 jssrc/PKJSTrack.m create mode 100644 jssrc/PKJSUppercaseWord.h create mode 100644 jssrc/PKJSUppercaseWord.m create mode 100644 jssrc/PKJSUtils.h create mode 100644 jssrc/PKJSUtils.m create mode 100644 jssrc/PKJSUtils_macros.h create mode 100644 jssrc/PKJSValueHolder.h create mode 100644 jssrc/PKJSValueHolder.m create mode 100644 jssrc/PKJSWhitespaceState.h create mode 100644 jssrc/PKJSWhitespaceState.m create mode 100644 jssrc/PKJSWord.h create mode 100644 jssrc/PKJSWord.m create mode 100644 jssrc/PKJSWordState.h create mode 100644 jssrc/PKJSWordState.m create mode 100644 res/.svn/all-wcprops create mode 100644 res/.svn/entries create mode 100644 res/.svn/prop-base/example1.srgs.svn-base create mode 100644 res/.svn/prop-base/mini_css.grammar.svn-base create mode 100644 res/.svn/prop-base/nyt.html.svn-base create mode 100644 res/.svn/prop-base/yahoo-small.json.svn-base create mode 100644 res/.svn/text-base/SRGSGrammar.txt.svn-base create mode 100644 res/.svn/text-base/apple-boss.json.svn-base create mode 100644 res/.svn/text-base/apple-boss.xml.svn-base create mode 100644 res/.svn/text-base/arithmetic.grammar.svn-base create mode 100644 res/.svn/text-base/c.grammar.svn-base create mode 100644 res/.svn/text-base/css.css.svn-base create mode 100644 res/.svn/text-base/css.grammar.svn-base create mode 100644 res/.svn/text-base/css2_1.grammar.svn-base create mode 100644 res/.svn/text-base/date.grammar.svn-base create mode 100644 res/.svn/text-base/erb.grammar.svn-base create mode 100644 res/.svn/text-base/example.css.svn-base create mode 100644 res/.svn/text-base/example.html.svn-base create mode 100644 res/.svn/text-base/example1.srgs.svn-base create mode 100644 res/.svn/text-base/html.css.svn-base create mode 100644 res/.svn/text-base/html.grammar.svn-base create mode 100644 res/.svn/text-base/javascript.grammar.svn-base create mode 100644 res/.svn/text-base/javascript_ll.txt.svn-base create mode 100644 res/.svn/text-base/json-old.grammar.svn-base create mode 100644 res/.svn/text-base/json.css.svn-base create mode 100644 res/.svn/text-base/json.grammar.svn-base create mode 100644 res/.svn/text-base/json_with_comments.css.svn-base create mode 100644 res/.svn/text-base/json_with_comments.grammar.svn-base create mode 100644 res/.svn/text-base/json_with_discards.grammar.svn-base create mode 100644 res/.svn/text-base/mini_css.grammar.svn-base create mode 100644 res/.svn/text-base/nasty.html.svn-base create mode 100644 res/.svn/text-base/nonascii.html.svn-base create mode 100644 res/.svn/text-base/nspredicate.grammar.svn-base create mode 100644 res/.svn/text-base/nyt.html.svn-base create mode 100644 res/.svn/text-base/objc.grammar.svn-base create mode 100644 res/.svn/text-base/proto.grammar.svn-base create mode 100644 res/.svn/text-base/rubyhash.grammar.svn-base create mode 100644 res/.svn/text-base/small-xml-file.xml.svn-base create mode 100644 res/.svn/text-base/stuff.txt.svn-base create mode 100644 res/.svn/text-base/svn-commands.txt.svn-base create mode 100644 res/.svn/text-base/xml.grammar.svn-base create mode 100644 res/.svn/text-base/xml_grammar.txt.svn-base create mode 100644 res/.svn/text-base/xpath1_0.grammar.svn-base create mode 100644 res/.svn/text-base/xpath_grammar.txt.svn-base create mode 100644 res/.svn/text-base/yahoo-small.json.svn-base create mode 100644 res/.svn/text-base/yahoo.json.svn-base create mode 100644 res/.svn/text-base/yahoo_with_comments.json.svn-base create mode 100644 res/.svn/tmp/tempfile.2.tmp create mode 100644 res/.svn/tmp/tempfile.3.tmp create mode 100644 res/.svn/tmp/tempfile.tmp create mode 100644 res/SRGSGrammar.txt create mode 100644 res/apple-boss.json create mode 100644 res/apple-boss.xml create mode 100644 res/arithmetic.grammar create mode 100644 res/c.grammar create mode 100644 res/css.css create mode 100644 res/css.grammar create mode 100644 res/css2_1.grammar create mode 100644 res/date.grammar create mode 100644 res/erb.grammar create mode 100644 res/example.css create mode 100644 res/example.html create mode 100644 res/example1.srgs create mode 100644 res/html.css create mode 100644 res/html.grammar create mode 100644 res/javascript.grammar create mode 100644 res/javascript_ll.txt create mode 100644 res/json-old.grammar create mode 100644 res/json.css create mode 100644 res/json.grammar create mode 100644 res/json_with_comments.css create mode 100644 res/json_with_comments.grammar create mode 100644 res/json_with_discards.grammar create mode 100644 res/mini_css.grammar create mode 100644 res/nasty.html create mode 100644 res/nonascii.html create mode 100644 res/nspredicate.grammar create mode 100644 res/nyt.html create mode 100644 res/objc.grammar create mode 100644 res/proto.grammar create mode 100644 res/rubyhash.grammar create mode 100644 res/small-xml-file.xml create mode 100644 res/stuff.txt create mode 100644 res/svn-commands.txt create mode 100644 res/xml.grammar create mode 100644 res/xml_grammar.txt create mode 100644 res/xpath1_0.grammar create mode 100644 res/xpath_grammar.txt create mode 100755 res/yahoo-small.json create mode 100644 res/yahoo.json create mode 100644 res/yahoo_with_comments.json create mode 100644 src/.svn/all-wcprops create mode 100644 src/.svn/entries create mode 100644 src/.svn/prop-base/PKAlternation.m.svn-base create mode 100644 src/.svn/prop-base/PKAssembly.m.svn-base create mode 100644 src/.svn/prop-base/PKCaseInsensitiveLiteral.m.svn-base create mode 100644 src/.svn/prop-base/PKChar.m.svn-base create mode 100644 src/.svn/prop-base/PKCharacterAssembly.m.svn-base create mode 100644 src/.svn/prop-base/PKCollectionParser.m.svn-base create mode 100644 src/.svn/prop-base/PKDigit.m.svn-base create mode 100644 src/.svn/prop-base/PKEmpty.m.svn-base create mode 100644 src/.svn/prop-base/PKLetter.m.svn-base create mode 100644 src/.svn/prop-base/PKLiteral.m.svn-base create mode 100644 src/.svn/prop-base/PKLowercaseWord.m.svn-base create mode 100644 src/.svn/prop-base/PKNumberState.m.svn-base create mode 100644 src/.svn/prop-base/PKParser.m.svn-base create mode 100644 src/.svn/prop-base/PKParserFactory.m.svn-base create mode 100644 src/.svn/prop-base/PKQuoteState.m.svn-base create mode 100644 src/.svn/prop-base/PKQuotedString.m.svn-base create mode 100644 src/.svn/prop-base/PKReader.m.svn-base create mode 100644 src/.svn/prop-base/PKRepetition.m.svn-base create mode 100644 src/.svn/prop-base/PKSequence.m.svn-base create mode 100644 src/.svn/prop-base/PKSpecificChar.m.svn-base create mode 100644 src/.svn/prop-base/PKSymbol.m.svn-base create mode 100644 src/.svn/prop-base/PKSymbolNode.m.svn-base create mode 100644 src/.svn/prop-base/PKSymbolRootNode.m.svn-base create mode 100644 src/.svn/prop-base/PKSymbolState.m.svn-base create mode 100644 src/.svn/prop-base/PKTerminal.m.svn-base create mode 100644 src/.svn/prop-base/PKToken.m.svn-base create mode 100644 src/.svn/prop-base/PKTokenArraySource.m.svn-base create mode 100644 src/.svn/prop-base/PKTokenAssembly.m.svn-base create mode 100644 src/.svn/prop-base/PKTokenizer.m.svn-base create mode 100644 src/.svn/prop-base/PKTokenizerState.m.svn-base create mode 100644 src/.svn/prop-base/PKTrack.m.svn-base create mode 100644 src/.svn/prop-base/PKUppercaseWord.m.svn-base create mode 100644 src/.svn/prop-base/PKWhitespaceState.m.svn-base create mode 100644 src/.svn/prop-base/PKWord.m.svn-base create mode 100644 src/.svn/prop-base/PKWordState.m.svn-base create mode 100644 src/.svn/text-base/NSArray+ParseKitAdditions.h.svn-base create mode 100644 src/.svn/text-base/NSArray+ParseKitAdditions.m.svn-base create mode 100644 src/.svn/text-base/NSString+ParseKitAdditions.h.svn-base create mode 100644 src/.svn/text-base/NSString+ParseKitAdditions.m.svn-base create mode 100644 src/.svn/text-base/PKAlternation.m.svn-base create mode 100644 src/.svn/text-base/PKAny.m.svn-base create mode 100644 src/.svn/text-base/PKAssembly.m.svn-base create mode 100644 src/.svn/text-base/PKCaseInsensitiveLiteral.m.svn-base create mode 100644 src/.svn/text-base/PKChar.m.svn-base create mode 100644 src/.svn/text-base/PKCharacterAssembly.m.svn-base create mode 100644 src/.svn/text-base/PKCollectionParser.m.svn-base create mode 100644 src/.svn/text-base/PKComment.m.svn-base create mode 100644 src/.svn/text-base/PKCommentState.m.svn-base create mode 100644 src/.svn/text-base/PKDelimitState.m.svn-base create mode 100644 src/.svn/text-base/PKDelimitedString.m.svn-base create mode 100644 src/.svn/text-base/PKDifference.m.svn-base create mode 100644 src/.svn/text-base/PKDigit.m.svn-base create mode 100644 src/.svn/text-base/PKEmpty.m.svn-base create mode 100644 src/.svn/text-base/PKGrammarParser.h.svn-base create mode 100644 src/.svn/text-base/PKGrammarParser.m.svn-base create mode 100644 src/.svn/text-base/PKIntersection.m.svn-base create mode 100644 src/.svn/text-base/PKLetter.m.svn-base create mode 100644 src/.svn/text-base/PKLiteral.m.svn-base create mode 100644 src/.svn/text-base/PKLowercaseWord.m.svn-base create mode 100644 src/.svn/text-base/PKMultiLineCommentState.m.svn-base create mode 100644 src/.svn/text-base/PKNegation.m.svn-base create mode 100644 src/.svn/text-base/PKNumber.m.svn-base create mode 100644 src/.svn/text-base/PKNumberState.m.svn-base create mode 100644 src/.svn/text-base/PKParser.m.svn-base create mode 100644 src/.svn/text-base/PKParserFactory.m.svn-base create mode 100644 src/.svn/text-base/PKPattern.m.svn-base create mode 100644 src/.svn/text-base/PKQuoteState.m.svn-base create mode 100644 src/.svn/text-base/PKQuotedString.m.svn-base create mode 100644 src/.svn/text-base/PKReader.m.svn-base create mode 100644 src/.svn/text-base/PKRepetition.m.svn-base create mode 100644 src/.svn/text-base/PKSequence.m.svn-base create mode 100644 src/.svn/text-base/PKSingleLineCommentState.m.svn-base create mode 100644 src/.svn/text-base/PKSpecificChar.m.svn-base create mode 100644 src/.svn/text-base/PKSymbol.m.svn-base create mode 100644 src/.svn/text-base/PKSymbolNode.m.svn-base create mode 100644 src/.svn/text-base/PKSymbolRootNode.m.svn-base create mode 100644 src/.svn/text-base/PKSymbolState.m.svn-base create mode 100644 src/.svn/text-base/PKTerminal.m.svn-base create mode 100644 src/.svn/text-base/PKToken.m.svn-base create mode 100644 src/.svn/text-base/PKTokenArraySource.m.svn-base create mode 100644 src/.svn/text-base/PKTokenAssembly.m.svn-base create mode 100644 src/.svn/text-base/PKTokenizer.m.svn-base create mode 100644 src/.svn/text-base/PKTokenizerState.m.svn-base create mode 100644 src/.svn/text-base/PKTrack.m.svn-base create mode 100644 src/.svn/text-base/PKTrackException.m.svn-base create mode 100644 src/.svn/text-base/PKUppercaseWord.m.svn-base create mode 100644 src/.svn/text-base/PKWhitespace.m.svn-base create mode 100644 src/.svn/text-base/PKWhitespaceState.m.svn-base create mode 100644 src/.svn/text-base/PKWord.m.svn-base create mode 100644 src/.svn/text-base/PKWordState.m.svn-base create mode 100644 src/.svn/text-base/Reader.h.svn-base create mode 100644 src/.svn/text-base/RegexKitLite.h.svn-base create mode 100644 src/.svn/text-base/RegexKitLite.m.svn-base create mode 100644 src/.svn/text-base/TAssembly.h.svn-base create mode 100644 src/NSArray+ParseKitAdditions.h create mode 100644 src/NSArray+ParseKitAdditions.m create mode 100644 src/NSString+ParseKitAdditions.h create mode 100644 src/NSString+ParseKitAdditions.m create mode 100644 src/PKAlternation.m create mode 100644 src/PKAny.m create mode 100644 src/PKAssembly.m create mode 100644 src/PKCaseInsensitiveLiteral.m create mode 100644 src/PKChar.m create mode 100644 src/PKCharacterAssembly.m create mode 100644 src/PKCollectionParser.m create mode 100644 src/PKComment.m create mode 100644 src/PKCommentState.m create mode 100644 src/PKDelimitState.m create mode 100644 src/PKDelimitedString.m create mode 100644 src/PKDifference.m create mode 100644 src/PKDigit.m create mode 100644 src/PKEmpty.m create mode 100644 src/PKGrammarParser.h create mode 100644 src/PKGrammarParser.m create mode 100644 src/PKIntersection.m create mode 100644 src/PKLetter.m create mode 100644 src/PKLiteral.m create mode 100644 src/PKLowercaseWord.m create mode 100644 src/PKMultiLineCommentState.m create mode 100644 src/PKNegation.m create mode 100644 src/PKNumber.m create mode 100644 src/PKNumberState.m create mode 100644 src/PKParser.m create mode 100644 src/PKParserFactory.m create mode 100644 src/PKPattern.m create mode 100644 src/PKQuoteState.m create mode 100644 src/PKQuotedString.m create mode 100644 src/PKReader.m create mode 100644 src/PKRepetition.m create mode 100644 src/PKSequence.m create mode 100644 src/PKSingleLineCommentState.m create mode 100644 src/PKSpecificChar.m create mode 100644 src/PKSymbol.m create mode 100644 src/PKSymbolNode.m create mode 100644 src/PKSymbolRootNode.m create mode 100644 src/PKSymbolState.m create mode 100644 src/PKTerminal.m create mode 100644 src/PKToken.m create mode 100644 src/PKTokenArraySource.m create mode 100644 src/PKTokenAssembly.m create mode 100644 src/PKTokenizer.m create mode 100644 src/PKTokenizerState.m create mode 100644 src/PKTrack.m create mode 100644 src/PKTrackException.m create mode 100644 src/PKUppercaseWord.m create mode 100644 src/PKWhitespace.m create mode 100644 src/PKWhitespaceState.m create mode 100644 src/PKWord.m create mode 100644 src/PKWordState.m create mode 100644 src/RegexKitLite.h create mode 100644 src/RegexKitLite.m create mode 100644 test/.svn/all-wcprops create mode 100644 test/.svn/entries create mode 100644 test/.svn/prop-base/TDAlternationTest.h.svn-base create mode 100644 test/.svn/prop-base/TDAlternationTest.m.svn-base create mode 100644 test/.svn/prop-base/TDCharTest.h.svn-base create mode 100644 test/.svn/prop-base/TDCharTest.m.svn-base create mode 100644 test/.svn/prop-base/TDCharacterAssemblyTest.h.svn-base create mode 100644 test/.svn/prop-base/TDCharacterAssemblyTest.m.svn-base create mode 100644 test/.svn/prop-base/TDDigitTest.h.svn-base create mode 100644 test/.svn/prop-base/TDDigitTest.m.svn-base create mode 100644 test/.svn/prop-base/TDFastJsonParser.h.svn-base create mode 100644 test/.svn/prop-base/TDFastJsonParser.m.svn-base create mode 100644 test/.svn/prop-base/TDFastJsonParserTest.h.svn-base create mode 100644 test/.svn/prop-base/TDFastJsonParserTest.m.svn-base create mode 100644 test/.svn/prop-base/TDHtmlSyntaxHighlighter.h.svn-base create mode 100644 test/.svn/prop-base/TDHtmlSyntaxHighlighter.m.svn-base create mode 100644 test/.svn/prop-base/TDJsonParser.h.svn-base create mode 100644 test/.svn/prop-base/TDJsonParser.m.svn-base create mode 100644 test/.svn/prop-base/TDJsonParserTest.h.svn-base create mode 100644 test/.svn/prop-base/TDJsonParserTest.m.svn-base create mode 100644 test/.svn/prop-base/TDLetterTest.h.svn-base create mode 100644 test/.svn/prop-base/TDLetterTest.m.svn-base create mode 100644 test/.svn/prop-base/TDLiteralTest.h.svn-base create mode 100644 test/.svn/prop-base/TDLiteralTest.m.svn-base create mode 100644 test/.svn/prop-base/TDLowercaseWordTest.h.svn-base create mode 100644 test/.svn/prop-base/TDLowercaseWordTest.m.svn-base create mode 100644 test/.svn/prop-base/TDMiniCSSAssembler.h.svn-base create mode 100644 test/.svn/prop-base/TDMiniCSSAssembler.m.svn-base create mode 100644 test/.svn/prop-base/TDMiniCSSAssemblerTest.h.svn-base create mode 100644 test/.svn/prop-base/TDMiniCSSAssemblerTest.m.svn-base create mode 100644 test/.svn/prop-base/TDNCName.h.svn-base create mode 100644 test/.svn/prop-base/TDNCName.m.svn-base create mode 100644 test/.svn/prop-base/TDNCNameState.h.svn-base create mode 100644 test/.svn/prop-base/TDNCNameState.m.svn-base create mode 100644 test/.svn/prop-base/TDNonReservedWord.h.svn-base create mode 100644 test/.svn/prop-base/TDNonReservedWord.m.svn-base create mode 100644 test/.svn/prop-base/TDNumberStateTest.h.svn-base create mode 100644 test/.svn/prop-base/TDNumberStateTest.m.svn-base create mode 100644 test/.svn/prop-base/TDParserFactoryTest.h.svn-base create mode 100644 test/.svn/prop-base/TDParserFactoryTest.m.svn-base create mode 100644 test/.svn/prop-base/TDParserTest.h.svn-base create mode 100644 test/.svn/prop-base/TDParserTest.m.svn-base create mode 100644 test/.svn/prop-base/TDQuoteStateTest.h.svn-base create mode 100644 test/.svn/prop-base/TDQuoteStateTest.m.svn-base create mode 100644 test/.svn/prop-base/TDReaderTest.h.svn-base create mode 100644 test/.svn/prop-base/TDReaderTest.m.svn-base create mode 100644 test/.svn/prop-base/TDRegularParser.h.svn-base create mode 100644 test/.svn/prop-base/TDRegularParser.m.svn-base create mode 100644 test/.svn/prop-base/TDRegularParserTest.h.svn-base create mode 100644 test/.svn/prop-base/TDRegularParserTest.m.svn-base create mode 100644 test/.svn/prop-base/TDRepetitionTest.h.svn-base create mode 100644 test/.svn/prop-base/TDRepetitionTest.m.svn-base create mode 100644 test/.svn/prop-base/TDReservedWord.h.svn-base create mode 100644 test/.svn/prop-base/TDReservedWord.m.svn-base create mode 100644 test/.svn/prop-base/TDReservedWordTest.h.svn-base create mode 100644 test/.svn/prop-base/TDReservedWordTest.m.svn-base create mode 100644 test/.svn/prop-base/TDRobotCommandTest.h.svn-base create mode 100644 test/.svn/prop-base/TDRobotCommandTest.m.svn-base create mode 100644 test/.svn/prop-base/TDSequenceTest.h.svn-base create mode 100644 test/.svn/prop-base/TDSequenceTest.m.svn-base create mode 100644 test/.svn/prop-base/TDSignificantWhitespaceState.h.svn-base create mode 100644 test/.svn/prop-base/TDSignificantWhitespaceState.m.svn-base create mode 100644 test/.svn/prop-base/TDSignificantWhitespaceStateTest.h.svn-base create mode 100644 test/.svn/prop-base/TDSignificantWhitespaceStateTest.m.svn-base create mode 100644 test/.svn/prop-base/TDSlashSlashState.h.svn-base create mode 100644 test/.svn/prop-base/TDSlashSlashState.m.svn-base create mode 100644 test/.svn/prop-base/TDSlashStarState.h.svn-base create mode 100644 test/.svn/prop-base/TDSlashStarState.m.svn-base create mode 100644 test/.svn/prop-base/TDSlashState.h.svn-base create mode 100644 test/.svn/prop-base/TDSlashState.m.svn-base create mode 100644 test/.svn/prop-base/TDSlashStateTest.h.svn-base create mode 100644 test/.svn/prop-base/TDSlashStateTest.m.svn-base create mode 100644 test/.svn/prop-base/TDSpecificCharTest.h.svn-base create mode 100644 test/.svn/prop-base/TDSpecificCharTest.m.svn-base create mode 100644 test/.svn/prop-base/TDSymbolStateTest.h.svn-base create mode 100644 test/.svn/prop-base/TDSymbolStateTest.m.svn-base create mode 100644 test/.svn/prop-base/TDSymbolTest.h.svn-base create mode 100644 test/.svn/prop-base/TDSymbolTest.m.svn-base create mode 100644 test/.svn/prop-base/TDSyntaxHighlighter.h.svn-base create mode 100644 test/.svn/prop-base/TDSyntaxHighlighter.m.svn-base create mode 100644 test/.svn/prop-base/TDTestScaffold.h.svn-base create mode 100644 test/.svn/prop-base/TDTestScaffold.m.svn-base create mode 100644 test/.svn/prop-base/TDTokenArraySourceTest.h.svn-base create mode 100644 test/.svn/prop-base/TDTokenArraySourceTest.m.svn-base create mode 100644 test/.svn/prop-base/TDTokenAssemblyTest.h.svn-base create mode 100644 test/.svn/prop-base/TDTokenAssemblyTest.m.svn-base create mode 100644 test/.svn/prop-base/TDTokenizerTest.h.svn-base create mode 100644 test/.svn/prop-base/TDTokenizerTest.m.svn-base create mode 100644 test/.svn/prop-base/TDTrackTest.h.svn-base create mode 100644 test/.svn/prop-base/TDTrackTest.m.svn-base create mode 100644 test/.svn/prop-base/TDUppercaseWordTest.h.svn-base create mode 100644 test/.svn/prop-base/TDUppercaseWordTest.m.svn-base create mode 100644 test/.svn/prop-base/TDWhitespaceStateTest.h.svn-base create mode 100644 test/.svn/prop-base/TDWhitespaceStateTest.m.svn-base create mode 100644 test/.svn/prop-base/TDWordOrReservedState.h.svn-base create mode 100644 test/.svn/prop-base/TDWordOrReservedState.m.svn-base create mode 100644 test/.svn/prop-base/TDWordStateTest.h.svn-base create mode 100644 test/.svn/prop-base/TDWordStateTest.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlAttribute.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlAttribute.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlCdata.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlCdata.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlComment.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlComment.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlDecl.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlDecl.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlDoctype.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlDoctype.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlDocument.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlDocument.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlEndEntity.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlEndEntity.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlEndTag.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlEndTag.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlEntity.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlEntity.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlEntityRef.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlEntityRef.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlFragment.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlFragment.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlName.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlName.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlNameState.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlNameState.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlNameTest.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlNameTest.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlNmtoken.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlNmtoken.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlNmtokenState.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlNmtokenState.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlNotation.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlNotation.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlProcessingInstruction.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlProcessingInstruction.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlSignificantWhitespace.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlSignificantWhitespace.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlStartTag.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlStartTag.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlTerminal.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlTerminal.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlText.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlText.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlToken.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlToken.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlTokenAssembly.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlTokenAssembly.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlTokenizer.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlTokenizer.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlTokenizerTest.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlTokenizerTest.m.svn-base create mode 100644 test/.svn/prop-base/TDXmlWhitespace.h.svn-base create mode 100644 test/.svn/prop-base/TDXmlWhitespace.m.svn-base create mode 100644 test/.svn/prop-base/XMLReader.h.svn-base create mode 100644 test/.svn/prop-base/XMLReader.m.svn-base create mode 100644 test/.svn/prop-base/XMLReaderTest.h.svn-base create mode 100644 test/.svn/prop-base/XMLReaderTest.m.svn-base create mode 100644 test/.svn/text-base/EBNFParser.h.svn-base create mode 100644 test/.svn/text-base/EBNFParser.m.svn-base create mode 100644 test/.svn/text-base/EBNFParserTest.h.svn-base create mode 100644 test/.svn/text-base/EBNFParserTest.m.svn-base create mode 100644 test/.svn/text-base/ERBTest.h.svn-base create mode 100644 test/.svn/text-base/ERBTest.m.svn-base create mode 100644 test/.svn/text-base/PKAST.h.svn-base create mode 100644 test/.svn/text-base/PKAST.m.svn-base create mode 100644 test/.svn/text-base/PKExclusion.h.svn-base create mode 100644 test/.svn/text-base/PKExclusion.m.svn-base create mode 100644 test/.svn/text-base/PKNumberState.h.svn-base create mode 100644 test/.svn/text-base/PKNumberState.m.svn-base create mode 100644 test/.svn/text-base/PKParseTree.h.svn-base create mode 100644 test/.svn/text-base/PKParseTree.m.svn-base create mode 100644 test/.svn/text-base/PKParseTreeAssembler.h.svn-base create mode 100644 test/.svn/text-base/PKParseTreeAssembler.m.svn-base create mode 100644 test/.svn/text-base/PKRuleNode.h.svn-base create mode 100644 test/.svn/text-base/PKRuleNode.m.svn-base create mode 100644 test/.svn/text-base/PKScientificNumberState.h.svn-base create mode 100644 test/.svn/text-base/PKScientificNumberState.m.svn-base create mode 100644 test/.svn/text-base/PKTokenNode.h.svn-base create mode 100644 test/.svn/text-base/PKTokenNode.m.svn-base create mode 100644 test/.svn/text-base/RelaxParser.h.svn-base create mode 100644 test/.svn/text-base/RelaxParser.m.svn-base create mode 100644 test/.svn/text-base/SAXAssembler.h.svn-base create mode 100644 test/.svn/text-base/SAXAssembler.m.svn-base create mode 100644 test/.svn/text-base/SAXTest.h.svn-base create mode 100644 test/.svn/text-base/SAXTest.m.svn-base create mode 100644 test/.svn/text-base/SRGSParser.h.svn-base create mode 100644 test/.svn/text-base/SRGSParser.m.svn-base create mode 100644 test/.svn/text-base/SRGSParserTest.h.svn-base create mode 100644 test/.svn/text-base/SRGSParserTest.m.svn-base create mode 100644 test/.svn/text-base/TDAlternationTest.h.svn-base create mode 100644 test/.svn/text-base/TDAlternationTest.m.svn-base create mode 100644 test/.svn/text-base/TDArithmeticAssembler.h.svn-base create mode 100644 test/.svn/text-base/TDArithmeticAssembler.m.svn-base create mode 100644 test/.svn/text-base/TDArithmeticParser.h.svn-base create mode 100644 test/.svn/text-base/TDArithmeticParser.m.svn-base create mode 100644 test/.svn/text-base/TDArithmeticParserTest.h.svn-base create mode 100644 test/.svn/text-base/TDArithmeticParserTest.m.svn-base create mode 100644 test/.svn/text-base/TDBlob.h.svn-base create mode 100644 test/.svn/text-base/TDBlob.m.svn-base create mode 100644 test/.svn/text-base/TDBlobState.h.svn-base create mode 100644 test/.svn/text-base/TDBlobState.m.svn-base create mode 100644 test/.svn/text-base/TDCharTest.h.svn-base create mode 100644 test/.svn/text-base/TDCharTest.m.svn-base create mode 100644 test/.svn/text-base/TDCharacterAssemblyTest.h.svn-base create mode 100644 test/.svn/text-base/TDCharacterAssemblyTest.m.svn-base create mode 100644 test/.svn/text-base/TDCommentStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDCommentStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDDelimitStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDDelimitStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDDifferenceTest.h.svn-base create mode 100644 test/.svn/text-base/TDDifferenceTest.m.svn-base create mode 100644 test/.svn/text-base/TDDigitTest.h.svn-base create mode 100644 test/.svn/text-base/TDDigitTest.m.svn-base create mode 100644 test/.svn/text-base/TDExclusionTest.h.svn-base create mode 100644 test/.svn/text-base/TDExclusionTest.m.svn-base create mode 100644 test/.svn/text-base/TDFastJsonParser.h.svn-base create mode 100644 test/.svn/text-base/TDFastJsonParser.m.svn-base create mode 100644 test/.svn/text-base/TDFastJsonParserTest.h.svn-base create mode 100644 test/.svn/text-base/TDFastJsonParserTest.m.svn-base create mode 100644 test/.svn/text-base/TDGenericAssembler.h.svn-base create mode 100644 test/.svn/text-base/TDGenericAssembler.m.svn-base create mode 100644 test/.svn/text-base/TDGenericAssemblerTest.h.svn-base create mode 100644 test/.svn/text-base/TDGenericAssemblerTest.m.svn-base create mode 100644 test/.svn/text-base/TDHtmlSyntaxHighlighter.h.svn-base create mode 100644 test/.svn/text-base/TDHtmlSyntaxHighlighter.m.svn-base create mode 100644 test/.svn/text-base/TDJavaScriptParser.h.svn-base create mode 100644 test/.svn/text-base/TDJavaScriptParser.m.svn-base create mode 100644 test/.svn/text-base/TDJavaScriptParserTest.h.svn-base create mode 100644 test/.svn/text-base/TDJavaScriptParserTest.m.svn-base create mode 100644 test/.svn/text-base/TDJsonParser.h.svn-base create mode 100644 test/.svn/text-base/TDJsonParser.m.svn-base create mode 100644 test/.svn/text-base/TDJsonParserTest.h.svn-base create mode 100644 test/.svn/text-base/TDJsonParserTest.m.svn-base create mode 100644 test/.svn/text-base/TDLetterTest.h.svn-base create mode 100644 test/.svn/text-base/TDLetterTest.m.svn-base create mode 100644 test/.svn/text-base/TDLiteralTest.h.svn-base create mode 100644 test/.svn/text-base/TDLiteralTest.m.svn-base create mode 100644 test/.svn/text-base/TDLowercaseWordTest.h.svn-base create mode 100644 test/.svn/text-base/TDLowercaseWordTest.m.svn-base create mode 100644 test/.svn/text-base/TDMiniCSSAssembler.h.svn-base create mode 100644 test/.svn/text-base/TDMiniCSSAssembler.m.svn-base create mode 100644 test/.svn/text-base/TDMiniCSSAssemblerTest.h.svn-base create mode 100644 test/.svn/text-base/TDMiniCSSAssemblerTest.m.svn-base create mode 100644 test/.svn/text-base/TDNCName.h.svn-base create mode 100644 test/.svn/text-base/TDNCName.m.svn-base create mode 100644 test/.svn/text-base/TDNCNameState.h.svn-base create mode 100644 test/.svn/text-base/TDNCNameState.m.svn-base create mode 100644 test/.svn/text-base/TDNSPredicateBuilder.h.svn-base create mode 100644 test/.svn/text-base/TDNSPredicateBuilder.m.svn-base create mode 100644 test/.svn/text-base/TDNSPredicateBuilderTest.h.svn-base create mode 100644 test/.svn/text-base/TDNSPredicateBuilderTest.m.svn-base create mode 100644 test/.svn/text-base/TDNSPredicateEvaluator.h.svn-base create mode 100644 test/.svn/text-base/TDNSPredicateEvaluator.m.svn-base create mode 100644 test/.svn/text-base/TDNSPredicateEvaluatorTest.h.svn-base create mode 100644 test/.svn/text-base/TDNSPredicateEvaluatorTest.m.svn-base create mode 100644 test/.svn/text-base/TDNegationTest.h.svn-base create mode 100644 test/.svn/text-base/TDNegationTest.m.svn-base create mode 100644 test/.svn/text-base/TDNonReservedWord.h.svn-base create mode 100644 test/.svn/text-base/TDNonReservedWord.m.svn-base create mode 100644 test/.svn/text-base/TDNumberStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDNumberStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDParseTreeTest.h.svn-base create mode 100644 test/.svn/text-base/TDParseTreeTest.m.svn-base create mode 100644 test/.svn/text-base/TDParserBlocksTest.h.svn-base create mode 100644 test/.svn/text-base/TDParserBlocksTest.m.svn-base create mode 100644 test/.svn/text-base/TDParserFactoryPatternTest.h.svn-base create mode 100644 test/.svn/text-base/TDParserFactoryPatternTest.m.svn-base create mode 100644 test/.svn/text-base/TDParserFactoryTest.h.svn-base create mode 100644 test/.svn/text-base/TDParserFactoryTest.m.svn-base create mode 100644 test/.svn/text-base/TDParserFactoryTest2.h.svn-base create mode 100644 test/.svn/text-base/TDParserFactoryTest2.m.svn-base create mode 100644 test/.svn/text-base/TDParserFactoryTest3.h.svn-base create mode 100644 test/.svn/text-base/TDParserFactoryTest3.m.svn-base create mode 100644 test/.svn/text-base/TDParserTest.h.svn-base create mode 100644 test/.svn/text-base/TDParserTest.m.svn-base create mode 100644 test/.svn/text-base/TDPatternTest.h.svn-base create mode 100644 test/.svn/text-base/TDPatternTest.m.svn-base create mode 100644 test/.svn/text-base/TDPlistParser.h.svn-base create mode 100644 test/.svn/text-base/TDPlistParser.m.svn-base create mode 100644 test/.svn/text-base/TDPlistParserTest.h.svn-base create mode 100644 test/.svn/text-base/TDPlistParserTest.m.svn-base create mode 100644 test/.svn/text-base/TDPredicateEvaluator.h.svn-base create mode 100644 test/.svn/text-base/TDPredicateEvaluator.m.svn-base create mode 100644 test/.svn/text-base/TDPredicateEvaluatorTest.h.svn-base create mode 100644 test/.svn/text-base/TDPredicateEvaluatorTest.m.svn-base create mode 100644 test/.svn/text-base/TDQuoteStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDQuoteStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDReaderTest.h.svn-base create mode 100644 test/.svn/text-base/TDReaderTest.m.svn-base create mode 100644 test/.svn/text-base/TDRegularParser.h.svn-base create mode 100644 test/.svn/text-base/TDRegularParser.m.svn-base create mode 100644 test/.svn/text-base/TDRegularParserTest.h.svn-base create mode 100644 test/.svn/text-base/TDRegularParserTest.m.svn-base create mode 100644 test/.svn/text-base/TDRepetitionTest.h.svn-base create mode 100644 test/.svn/text-base/TDRepetitionTest.m.svn-base create mode 100644 test/.svn/text-base/TDReservedWord.h.svn-base create mode 100644 test/.svn/text-base/TDReservedWord.m.svn-base create mode 100644 test/.svn/text-base/TDReservedWordTest.h.svn-base create mode 100644 test/.svn/text-base/TDReservedWordTest.m.svn-base create mode 100644 test/.svn/text-base/TDRobotCommandTest.h.svn-base create mode 100644 test/.svn/text-base/TDRobotCommandTest.m.svn-base create mode 100644 test/.svn/text-base/TDScientificNumberStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDScientificNumberStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDSequenceTest.h.svn-base create mode 100644 test/.svn/text-base/TDSequenceTest.m.svn-base create mode 100644 test/.svn/text-base/TDSignificantWhitespaceState.h.svn-base create mode 100644 test/.svn/text-base/TDSignificantWhitespaceState.m.svn-base create mode 100644 test/.svn/text-base/TDSignificantWhitespaceStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDSignificantWhitespaceStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDSlashSlashState.h.svn-base create mode 100644 test/.svn/text-base/TDSlashSlashState.m.svn-base create mode 100644 test/.svn/text-base/TDSlashStarState.h.svn-base create mode 100644 test/.svn/text-base/TDSlashStarState.m.svn-base create mode 100644 test/.svn/text-base/TDSlashState.h.svn-base create mode 100644 test/.svn/text-base/TDSlashState.m.svn-base create mode 100644 test/.svn/text-base/TDSlashStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDSlashStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDSpecificCharTest.h.svn-base create mode 100644 test/.svn/text-base/TDSpecificCharTest.m.svn-base create mode 100644 test/.svn/text-base/TDSymbolStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDSymbolStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDSymbolTest.h.svn-base create mode 100644 test/.svn/text-base/TDSymbolTest.m.svn-base create mode 100644 test/.svn/text-base/TDSyntaxHighlighter.h.svn-base create mode 100644 test/.svn/text-base/TDSyntaxHighlighter.m.svn-base create mode 100644 test/.svn/text-base/TDTestScaffold.h.svn-base create mode 100644 test/.svn/text-base/TDTestScaffold.m.svn-base create mode 100644 test/.svn/text-base/TDToken+Blob.h.svn-base create mode 100644 test/.svn/text-base/TDToken+Blob.m.svn-base create mode 100644 test/.svn/text-base/TDTokenArraySourceTest.h.svn-base create mode 100644 test/.svn/text-base/TDTokenArraySourceTest.m.svn-base create mode 100644 test/.svn/text-base/TDTokenAssemblyTest.h.svn-base create mode 100644 test/.svn/text-base/TDTokenAssemblyTest.m.svn-base create mode 100644 test/.svn/text-base/TDTokenTest.h.svn-base create mode 100644 test/.svn/text-base/TDTokenTest.m.svn-base create mode 100644 test/.svn/text-base/TDTokenizer+BlobState.h.svn-base create mode 100644 test/.svn/text-base/TDTokenizer+BlobState.m.svn-base create mode 100644 test/.svn/text-base/TDTokenizerBlocksTest.h.svn-base create mode 100644 test/.svn/text-base/TDTokenizerBlocksTest.m.svn-base create mode 100644 test/.svn/text-base/TDTokenizerStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDTokenizerStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDTokenizerTest.h.svn-base create mode 100644 test/.svn/text-base/TDTokenizerTest.m.svn-base create mode 100644 test/.svn/text-base/TDTrackTest.h.svn-base create mode 100644 test/.svn/text-base/TDTrackTest.m.svn-base create mode 100644 test/.svn/text-base/TDUppercaseWordTest.h.svn-base create mode 100644 test/.svn/text-base/TDUppercaseWordTest.m.svn-base create mode 100644 test/.svn/text-base/TDWhitespaceStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDWhitespaceStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDWordOrReservedState.h.svn-base create mode 100644 test/.svn/text-base/TDWordOrReservedState.m.svn-base create mode 100644 test/.svn/text-base/TDWordStateTest.h.svn-base create mode 100644 test/.svn/text-base/TDWordStateTest.m.svn-base create mode 100644 test/.svn/text-base/TDXMLParser.h.svn-base create mode 100644 test/.svn/text-base/TDXMLParser.m.svn-base create mode 100644 test/.svn/text-base/TDXMLParserTest.h.svn-base create mode 100644 test/.svn/text-base/TDXMLParserTest.m.svn-base create mode 100644 test/.svn/text-base/TDXmlAttribute.h.svn-base create mode 100644 test/.svn/text-base/TDXmlAttribute.m.svn-base create mode 100644 test/.svn/text-base/TDXmlCdata.h.svn-base create mode 100644 test/.svn/text-base/TDXmlCdata.m.svn-base create mode 100644 test/.svn/text-base/TDXmlComment.h.svn-base create mode 100644 test/.svn/text-base/TDXmlComment.m.svn-base create mode 100644 test/.svn/text-base/TDXmlDecl.h.svn-base create mode 100644 test/.svn/text-base/TDXmlDecl.m.svn-base create mode 100644 test/.svn/text-base/TDXmlDoctype.h.svn-base create mode 100644 test/.svn/text-base/TDXmlDoctype.m.svn-base create mode 100644 test/.svn/text-base/TDXmlDocument.h.svn-base create mode 100644 test/.svn/text-base/TDXmlDocument.m.svn-base create mode 100644 test/.svn/text-base/TDXmlEndEntity.h.svn-base create mode 100644 test/.svn/text-base/TDXmlEndEntity.m.svn-base create mode 100644 test/.svn/text-base/TDXmlEndTag.h.svn-base create mode 100644 test/.svn/text-base/TDXmlEndTag.m.svn-base create mode 100644 test/.svn/text-base/TDXmlEntity.h.svn-base create mode 100644 test/.svn/text-base/TDXmlEntity.m.svn-base create mode 100644 test/.svn/text-base/TDXmlEntityRef.h.svn-base create mode 100644 test/.svn/text-base/TDXmlEntityRef.m.svn-base create mode 100644 test/.svn/text-base/TDXmlFragment.h.svn-base create mode 100644 test/.svn/text-base/TDXmlFragment.m.svn-base create mode 100644 test/.svn/text-base/TDXmlName.h.svn-base create mode 100644 test/.svn/text-base/TDXmlName.m.svn-base create mode 100644 test/.svn/text-base/TDXmlNameState.h.svn-base create mode 100644 test/.svn/text-base/TDXmlNameState.m.svn-base create mode 100644 test/.svn/text-base/TDXmlNameTest.h.svn-base create mode 100644 test/.svn/text-base/TDXmlNameTest.m.svn-base create mode 100644 test/.svn/text-base/TDXmlNmtoken.h.svn-base create mode 100644 test/.svn/text-base/TDXmlNmtoken.m.svn-base create mode 100644 test/.svn/text-base/TDXmlNmtokenState.h.svn-base create mode 100644 test/.svn/text-base/TDXmlNmtokenState.m.svn-base create mode 100644 test/.svn/text-base/TDXmlNotation.h.svn-base create mode 100644 test/.svn/text-base/TDXmlNotation.m.svn-base create mode 100644 test/.svn/text-base/TDXmlProcessingInstruction.h.svn-base create mode 100644 test/.svn/text-base/TDXmlProcessingInstruction.m.svn-base create mode 100644 test/.svn/text-base/TDXmlSignificantWhitespace.h.svn-base create mode 100644 test/.svn/text-base/TDXmlSignificantWhitespace.m.svn-base create mode 100644 test/.svn/text-base/TDXmlStartTag.h.svn-base create mode 100644 test/.svn/text-base/TDXmlStartTag.m.svn-base create mode 100644 test/.svn/text-base/TDXmlTerminal.h.svn-base create mode 100644 test/.svn/text-base/TDXmlTerminal.m.svn-base create mode 100644 test/.svn/text-base/TDXmlText.h.svn-base create mode 100644 test/.svn/text-base/TDXmlText.m.svn-base create mode 100644 test/.svn/text-base/TDXmlToken.h.svn-base create mode 100644 test/.svn/text-base/TDXmlToken.m.svn-base create mode 100644 test/.svn/text-base/TDXmlTokenAssembly.h.svn-base create mode 100644 test/.svn/text-base/TDXmlTokenAssembly.m.svn-base create mode 100644 test/.svn/text-base/TDXmlTokenizer.h.svn-base create mode 100644 test/.svn/text-base/TDXmlTokenizer.m.svn-base create mode 100644 test/.svn/text-base/TDXmlTokenizerTest.h.svn-base create mode 100644 test/.svn/text-base/TDXmlTokenizerTest.m.svn-base create mode 100644 test/.svn/text-base/TDXmlWhitespace.h.svn-base create mode 100644 test/.svn/text-base/TDXmlWhitespace.m.svn-base create mode 100644 test/.svn/text-base/Tests-Info.plist.svn-base create mode 100644 test/.svn/text-base/XMLReader.h.svn-base create mode 100644 test/.svn/text-base/XMLReader.m.svn-base create mode 100644 test/.svn/text-base/XMLReaderTest.h.svn-base create mode 100644 test/.svn/text-base/XMLReaderTest.m.svn-base create mode 100644 test/.svn/text-base/XPathAssembler.h.svn-base create mode 100644 test/.svn/text-base/XPathAssembler.m.svn-base create mode 100644 test/.svn/text-base/XPathContext.h.svn-base create mode 100644 test/.svn/text-base/XPathContext.m.svn-base create mode 100644 test/.svn/text-base/XPathParser.h.svn-base create mode 100644 test/.svn/text-base/XPathParser.m.svn-base create mode 100644 test/.svn/text-base/XPathParserGrammarTest.h.svn-base create mode 100644 test/.svn/text-base/XPathParserGrammarTest.m.svn-base create mode 100644 test/.svn/text-base/XPathParserTest.h.svn-base create mode 100644 test/.svn/text-base/XPathParserTest.m.svn-base create mode 100644 test/.svn/tmp/tempfile.2.tmp create mode 100644 test/.svn/tmp/tempfile.3.tmp create mode 100644 test/.svn/tmp/tempfile.tmp create mode 100644 test/EBNFParser.h create mode 100644 test/EBNFParser.m create mode 100644 test/EBNFParserTest.h create mode 100644 test/EBNFParserTest.m create mode 100644 test/ERBTest.h create mode 100644 test/ERBTest.m create mode 100644 test/PKAST.h create mode 100644 test/PKAST.m create mode 100644 test/PKExclusion.h create mode 100644 test/PKExclusion.m create mode 100644 test/PKNumberState.h create mode 100644 test/PKNumberState.m create mode 100644 test/PKParseTree.h create mode 100644 test/PKParseTree.m create mode 100644 test/PKParseTreeAssembler.h create mode 100644 test/PKParseTreeAssembler.m create mode 100644 test/PKRuleNode.h create mode 100644 test/PKRuleNode.m create mode 100644 test/PKScientificNumberState.h create mode 100644 test/PKScientificNumberState.m create mode 100644 test/PKTokenNode.h create mode 100644 test/PKTokenNode.m create mode 100644 test/RelaxParser.h create mode 100644 test/RelaxParser.m create mode 100644 test/SAXAssembler.h create mode 100644 test/SAXAssembler.m create mode 100644 test/SAXTest.h create mode 100644 test/SAXTest.m create mode 100644 test/SRGSParser.h create mode 100644 test/SRGSParser.m create mode 100644 test/SRGSParserTest.h create mode 100644 test/SRGSParserTest.m create mode 100644 test/TDAlternationTest.h create mode 100644 test/TDAlternationTest.m create mode 100644 test/TDArithmeticAssembler.h create mode 100644 test/TDArithmeticAssembler.m create mode 100644 test/TDArithmeticParser.h create mode 100644 test/TDArithmeticParser.m create mode 100644 test/TDArithmeticParserTest.h create mode 100644 test/TDArithmeticParserTest.m create mode 100644 test/TDBlob.h create mode 100644 test/TDBlob.m create mode 100644 test/TDBlobState.h create mode 100644 test/TDBlobState.m create mode 100644 test/TDCharTest.h create mode 100644 test/TDCharTest.m create mode 100644 test/TDCharacterAssemblyTest.h create mode 100644 test/TDCharacterAssemblyTest.m create mode 100644 test/TDCommentStateTest.h create mode 100644 test/TDCommentStateTest.m create mode 100644 test/TDDelimitStateTest.h create mode 100644 test/TDDelimitStateTest.m create mode 100644 test/TDDifferenceTest.h create mode 100644 test/TDDifferenceTest.m create mode 100644 test/TDDigitTest.h create mode 100644 test/TDDigitTest.m create mode 100644 test/TDExclusionTest.h create mode 100644 test/TDExclusionTest.m create mode 100644 test/TDFastJsonParser.h create mode 100644 test/TDFastJsonParser.m create mode 100644 test/TDFastJsonParserTest.h create mode 100644 test/TDFastJsonParserTest.m create mode 100644 test/TDGenericAssembler.h create mode 100644 test/TDGenericAssembler.m create mode 100644 test/TDGenericAssemblerTest.h create mode 100644 test/TDGenericAssemblerTest.m create mode 100644 test/TDHtmlSyntaxHighlighter.h create mode 100644 test/TDHtmlSyntaxHighlighter.m create mode 100644 test/TDJavaScriptParser.h create mode 100644 test/TDJavaScriptParser.m create mode 100644 test/TDJavaScriptParserTest.h create mode 100644 test/TDJavaScriptParserTest.m create mode 100644 test/TDJsonParser.h create mode 100644 test/TDJsonParser.m create mode 100644 test/TDJsonParserTest.h create mode 100644 test/TDJsonParserTest.m create mode 100644 test/TDLetterTest.h create mode 100644 test/TDLetterTest.m create mode 100644 test/TDLiteralTest.h create mode 100644 test/TDLiteralTest.m create mode 100644 test/TDLowercaseWordTest.h create mode 100644 test/TDLowercaseWordTest.m create mode 100644 test/TDMiniCSSAssembler.h create mode 100644 test/TDMiniCSSAssembler.m create mode 100644 test/TDMiniCSSAssemblerTest.h create mode 100644 test/TDMiniCSSAssemblerTest.m create mode 100644 test/TDNCName.h create mode 100644 test/TDNCName.m create mode 100644 test/TDNCNameState.h create mode 100644 test/TDNCNameState.m create mode 100644 test/TDNSPredicateBuilder.h create mode 100644 test/TDNSPredicateBuilder.m create mode 100644 test/TDNSPredicateBuilderTest.h create mode 100644 test/TDNSPredicateBuilderTest.m create mode 100644 test/TDNSPredicateEvaluator.h create mode 100644 test/TDNSPredicateEvaluator.m create mode 100644 test/TDNSPredicateEvaluatorTest.h create mode 100644 test/TDNSPredicateEvaluatorTest.m create mode 100644 test/TDNegationTest.h create mode 100644 test/TDNegationTest.m create mode 100644 test/TDNonReservedWord.h create mode 100644 test/TDNonReservedWord.m create mode 100644 test/TDNumberStateTest.h create mode 100644 test/TDNumberStateTest.m create mode 100644 test/TDParseTreeTest.h create mode 100644 test/TDParseTreeTest.m create mode 100644 test/TDParserBlocksTest.h create mode 100644 test/TDParserBlocksTest.m create mode 100644 test/TDParserFactoryPatternTest.h create mode 100644 test/TDParserFactoryPatternTest.m create mode 100644 test/TDParserFactoryTest.h create mode 100644 test/TDParserFactoryTest.m create mode 100644 test/TDParserFactoryTest2.h create mode 100644 test/TDParserFactoryTest2.m create mode 100644 test/TDParserFactoryTest3.h create mode 100644 test/TDParserFactoryTest3.m create mode 100644 test/TDParserTest.h create mode 100644 test/TDParserTest.m create mode 100644 test/TDPatternTest.h create mode 100644 test/TDPatternTest.m create mode 100644 test/TDPlistParser.h create mode 100644 test/TDPlistParser.m create mode 100644 test/TDPlistParserTest.h create mode 100644 test/TDPlistParserTest.m create mode 100644 test/TDPredicateEvaluator.h create mode 100644 test/TDPredicateEvaluator.m create mode 100644 test/TDPredicateEvaluatorTest.h create mode 100644 test/TDPredicateEvaluatorTest.m create mode 100644 test/TDQuoteStateTest.h create mode 100644 test/TDQuoteStateTest.m create mode 100644 test/TDReaderTest.h create mode 100644 test/TDReaderTest.m create mode 100644 test/TDRegularParser.h create mode 100644 test/TDRegularParser.m create mode 100644 test/TDRegularParserTest.h create mode 100644 test/TDRegularParserTest.m create mode 100644 test/TDRepetitionTest.h create mode 100644 test/TDRepetitionTest.m create mode 100644 test/TDReservedWord.h create mode 100644 test/TDReservedWord.m create mode 100644 test/TDReservedWordTest.h create mode 100644 test/TDReservedWordTest.m create mode 100644 test/TDRobotCommandTest.h create mode 100644 test/TDRobotCommandTest.m create mode 100644 test/TDScientificNumberStateTest.h create mode 100644 test/TDScientificNumberStateTest.m create mode 100644 test/TDSequenceTest.h create mode 100644 test/TDSequenceTest.m create mode 100644 test/TDSignificantWhitespaceState.h create mode 100644 test/TDSignificantWhitespaceState.m create mode 100644 test/TDSignificantWhitespaceStateTest.h create mode 100644 test/TDSignificantWhitespaceStateTest.m create mode 100644 test/TDSlashSlashState.h create mode 100644 test/TDSlashSlashState.m create mode 100644 test/TDSlashStarState.h create mode 100644 test/TDSlashStarState.m create mode 100644 test/TDSlashState.h create mode 100644 test/TDSlashState.m create mode 100644 test/TDSlashStateTest.h create mode 100644 test/TDSlashStateTest.m create mode 100644 test/TDSpecificCharTest.h create mode 100644 test/TDSpecificCharTest.m create mode 100644 test/TDSymbolStateTest.h create mode 100644 test/TDSymbolStateTest.m create mode 100644 test/TDSymbolTest.h create mode 100644 test/TDSymbolTest.m create mode 100644 test/TDSyntaxHighlighter.h create mode 100644 test/TDSyntaxHighlighter.m create mode 100644 test/TDTestScaffold.h create mode 100644 test/TDTestScaffold.m create mode 100644 test/TDToken+Blob.h create mode 100644 test/TDToken+Blob.m create mode 100644 test/TDTokenArraySourceTest.h create mode 100644 test/TDTokenArraySourceTest.m create mode 100644 test/TDTokenAssemblyTest.h create mode 100644 test/TDTokenAssemblyTest.m create mode 100644 test/TDTokenTest.h create mode 100644 test/TDTokenTest.m create mode 100644 test/TDTokenizer+BlobState.h create mode 100644 test/TDTokenizer+BlobState.m create mode 100644 test/TDTokenizerBlocksTest.h create mode 100644 test/TDTokenizerBlocksTest.m create mode 100644 test/TDTokenizerStateTest.h create mode 100644 test/TDTokenizerStateTest.m create mode 100644 test/TDTokenizerTest.h create mode 100644 test/TDTokenizerTest.m create mode 100644 test/TDTrackTest.h create mode 100644 test/TDTrackTest.m create mode 100644 test/TDUppercaseWordTest.h create mode 100644 test/TDUppercaseWordTest.m create mode 100644 test/TDWhitespaceStateTest.h create mode 100644 test/TDWhitespaceStateTest.m create mode 100644 test/TDWordOrReservedState.h create mode 100644 test/TDWordOrReservedState.m create mode 100644 test/TDWordStateTest.h create mode 100644 test/TDWordStateTest.m create mode 100644 test/TDXMLParser.h create mode 100644 test/TDXMLParser.m create mode 100644 test/TDXMLParserTest.h create mode 100644 test/TDXMLParserTest.m create mode 100644 test/TDXmlAttribute.h create mode 100644 test/TDXmlAttribute.m create mode 100644 test/TDXmlCdata.h create mode 100644 test/TDXmlCdata.m create mode 100644 test/TDXmlComment.h create mode 100644 test/TDXmlComment.m create mode 100644 test/TDXmlDecl.h create mode 100644 test/TDXmlDecl.m create mode 100644 test/TDXmlDoctype.h create mode 100644 test/TDXmlDoctype.m create mode 100644 test/TDXmlDocument.h create mode 100644 test/TDXmlDocument.m create mode 100644 test/TDXmlEndEntity.h create mode 100644 test/TDXmlEndEntity.m create mode 100644 test/TDXmlEndTag.h create mode 100644 test/TDXmlEndTag.m create mode 100644 test/TDXmlEntity.h create mode 100644 test/TDXmlEntity.m create mode 100644 test/TDXmlEntityRef.h create mode 100644 test/TDXmlEntityRef.m create mode 100644 test/TDXmlFragment.h create mode 100644 test/TDXmlFragment.m create mode 100644 test/TDXmlName.h create mode 100644 test/TDXmlName.m create mode 100644 test/TDXmlNameState.h create mode 100644 test/TDXmlNameState.m create mode 100644 test/TDXmlNameTest.h create mode 100644 test/TDXmlNameTest.m create mode 100644 test/TDXmlNmtoken.h create mode 100644 test/TDXmlNmtoken.m create mode 100644 test/TDXmlNmtokenState.h create mode 100644 test/TDXmlNmtokenState.m create mode 100644 test/TDXmlNotation.h create mode 100644 test/TDXmlNotation.m create mode 100644 test/TDXmlProcessingInstruction.h create mode 100644 test/TDXmlProcessingInstruction.m create mode 100644 test/TDXmlSignificantWhitespace.h create mode 100644 test/TDXmlSignificantWhitespace.m create mode 100644 test/TDXmlStartTag.h create mode 100644 test/TDXmlStartTag.m create mode 100644 test/TDXmlTerminal.h create mode 100644 test/TDXmlTerminal.m create mode 100644 test/TDXmlText.h create mode 100644 test/TDXmlText.m create mode 100644 test/TDXmlToken.h create mode 100644 test/TDXmlToken.m create mode 100644 test/TDXmlTokenAssembly.h create mode 100644 test/TDXmlTokenAssembly.m create mode 100644 test/TDXmlTokenizer.h create mode 100644 test/TDXmlTokenizer.m create mode 100644 test/TDXmlTokenizerTest.h create mode 100644 test/TDXmlTokenizerTest.m create mode 100644 test/TDXmlWhitespace.h create mode 100644 test/TDXmlWhitespace.m create mode 100644 test/Tests-Info.plist create mode 100755 test/XMLReader.h create mode 100755 test/XMLReader.m create mode 100644 test/XMLReaderTest.h create mode 100644 test/XMLReaderTest.m create mode 100644 test/XPathAssembler.h create mode 100644 test/XPathAssembler.m create mode 100644 test/XPathContext.h create mode 100644 test/XPathContext.m create mode 100644 test/XPathParser.h create mode 100644 test/XPathParser.m create mode 100644 test/XPathParserGrammarTest.h create mode 100644 test/XPathParserGrammarTest.m create mode 100644 test/XPathParserTest.h create mode 100644 test/XPathParserTest.m diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..29b8ac0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 \ No newline at end of file diff --git a/English.lproj/.svn/all-wcprops b/English.lproj/.svn/all-wcprops new file mode 100644 index 0000000..d4dd167 --- /dev/null +++ b/English.lproj/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/483/trunk/English.lproj +END +InfoPlist.strings +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/483/trunk/English.lproj/InfoPlist.strings +END diff --git a/English.lproj/.svn/entries b/English.lproj/.svn/entries new file mode 100644 index 0000000..d7aa4af --- /dev/null +++ b/English.lproj/.svn/entries @@ -0,0 +1,69 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/English.lproj +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2008-12-27T08:01:40.325565Z +483 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + + + + + + +0 + +InfoPlist.strings +file + + + + +2009-07-03T20:42:39.000000Z +47eff3f1530a2a5635a1327e8c5330a4 +2008-12-27T08:01:40.325565Z +483 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +202 + diff --git a/English.lproj/.svn/prop-base/InfoPlist.strings.svn-base b/English.lproj/.svn/prop-base/InfoPlist.strings.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/English.lproj/.svn/prop-base/InfoPlist.strings.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/English.lproj/.svn/text-base/InfoPlist.strings.svn-base b/English.lproj/.svn/text-base/InfoPlist.strings.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..c62f8380e310e762dfee5819c16cb881c4f5197a GIT binary patch literal 202 zcmW-b!4APt5Jk_rUm=!_Aa){FEJ(xxKTz7Lpl#Zc@JD_UCohxCym#l`lllG_5z}Ks z#fgL)7v5x~YENfFt5Q)qd(Pax_Lut}QU`xar+U@>3a(gYWNq2A;=x^R$2%6FCDt6UNrm#Ej?<4=*EW literal 0 HcmV?d00001 diff --git a/English.lproj/InfoPlist.strings b/English.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..c62f8380e310e762dfee5819c16cb881c4f5197a GIT binary patch literal 202 zcmW-b!4APt5Jk_rUm=!_Aa){FEJ(xxKTz7Lpl#Zc@JD_UCohxCym#l`lllG_5z}Ks z#fgL)7v5x~YENfFt5Q)qd(Pax_Lut}QU`xar+U@>3a(gYWNq2A;=x^R$2%6FCDt6UNrm#Ej?<4=*EW literal 0 HcmV?d00001 diff --git a/Info.plist b/Info.plist new file mode 100644 index 0000000..0f226c6 --- /dev/null +++ b/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleName + ${PRODUCT_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.parsekit.ParseKit + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.6b + NSPrincipalClass + + + diff --git a/JSParseKit-Info.plist b/JSParseKit-Info.plist new file mode 100644 index 0000000..4d4add1 --- /dev/null +++ b/JSParseKit-Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + JSParseKit + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..a28d09f --- /dev/null +++ b/License.txt @@ -0,0 +1,175 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. \ No newline at end of file diff --git a/ParseKit.xcodeproj/.svn/all-wcprops b/ParseKit.xcodeproj/.svn/all-wcprops new file mode 100644 index 0000000..ad082e4 --- /dev/null +++ b/ParseKit.xcodeproj/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1402/trunk/ParseKit.xcodeproj +END +project.pbxproj +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1402/trunk/ParseKit.xcodeproj/project.pbxproj +END diff --git a/ParseKit.xcodeproj/.svn/dir-prop-base b/ParseKit.xcodeproj/.svn/dir-prop-base new file mode 100644 index 0000000..e05192c --- /dev/null +++ b/ParseKit.xcodeproj/.svn/dir-prop-base @@ -0,0 +1,12 @@ +K 10 +svn:ignore +V 36 +*.pbxuser +*.mode1v3 +*.perspectivev3 + +K 13 +svn:mergeinfo +V 0 + +END diff --git a/ParseKit.xcodeproj/.svn/entries b/ParseKit.xcodeproj/.svn/entries new file mode 100644 index 0000000..0a758ca --- /dev/null +++ b/ParseKit.xcodeproj/.svn/entries @@ -0,0 +1,69 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/ParseKit.xcodeproj +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-09-26T04:05:15.940742Z +1402 +todd.ditchendorf +has-props + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + + + + + + +0 + +project.pbxproj +file + + + + +2009-09-26T04:04:56.000000Z +a219b667fef5cb9d730c2de94b36d330 +2009-09-26T04:05:15.940742Z +1402 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +309408 + diff --git a/ParseKit.xcodeproj/.svn/text-base/project.pbxproj.svn-base b/ParseKit.xcodeproj/.svn/text-base/project.pbxproj.svn-base new file mode 100644 index 0000000..382638b --- /dev/null +++ b/ParseKit.xcodeproj/.svn/text-base/project.pbxproj.svn-base @@ -0,0 +1,3720 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; }; + D302C69D0EF044810090E714 /* TDPlistParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36568A60EEF9FE900226554 /* TDPlistParser.m */; }; + D3126D060FFD9BA700CBF4C4 /* PKNegation.m in Sources */ = {isa = PBXBuildFile; fileRef = D3126D040FFD9BA700CBF4C4 /* PKNegation.m */; }; + D3126D0B0FFD9E4B00CBF4C4 /* TDNegationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3126D0A0FFD9E4B00CBF4C4 /* TDNegationTest.m */; }; + D3126DEC0FFDBC1D00CBF4C4 /* PKNegation.m in Sources */ = {isa = PBXBuildFile; fileRef = D3126D040FFD9BA700CBF4C4 /* PKNegation.m */; }; + D315DF720FEF59B600D876C8 /* date.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D315DF710FEF59B600D876C8 /* date.grammar */; }; + D315DF730FEF59B600D876C8 /* date.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D315DF710FEF59B600D876C8 /* date.grammar */; }; + D319E42A106D8A1F008C63DD /* arithmetic.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D319E429106D8A1F008C63DD /* arithmetic.grammar */; }; + D319E42B106D8A1F008C63DD /* arithmetic.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D319E429106D8A1F008C63DD /* arithmetic.grammar */; }; + D319E42E106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */; }; + D319E42F106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */; }; + D31A15260F6DE449002AFDF1 /* javascript.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D31A15250F6DE449002AFDF1 /* javascript.grammar */; }; + D31A15270F6DE449002AFDF1 /* javascript.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D31A15250F6DE449002AFDF1 /* javascript.grammar */; }; + D31A16520F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */; }; + D31A16530F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */; }; + D31FE54C0E60E46100A0803E /* TDTestScaffold.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE54B0E60E46100A0803E /* TDTestScaffold.m */; }; + D31FE5630E60E50800A0803E /* TDAlternationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE54E0E60E50800A0803E /* TDAlternationTest.m */; }; + D31FE5640E60E50800A0803E /* TDLiteralTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5500E60E50800A0803E /* TDLiteralTest.m */; }; + D31FE5650E60E50800A0803E /* TDParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5520E60E50800A0803E /* TDParserTest.m */; }; + D31FE5660E60E50800A0803E /* TDRepetitionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5540E60E50800A0803E /* TDRepetitionTest.m */; }; + D31FE5680E60E50800A0803E /* TDRobotCommandTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5580E60E50800A0803E /* TDRobotCommandTest.m */; }; + D31FE5690E60E50800A0803E /* TDSequenceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE55A0E60E50800A0803E /* TDSequenceTest.m */; }; + D31FE56A0E60E50800A0803E /* TDSymbolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE55C0E60E50800A0803E /* TDSymbolTest.m */; }; + D31FE56B0E60E50800A0803E /* TDTokenAssemblyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE55E0E60E50800A0803E /* TDTokenAssemblyTest.m */; }; + D31FE56C0E60E50800A0803E /* TDTrackTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5600E60E50800A0803E /* TDTrackTest.m */; }; + D31FE56D0E60E50800A0803E /* TDUppercaseWordTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5620E60E50800A0803E /* TDUppercaseWordTest.m */; }; + D31FE5750E60E55700A0803E /* TDReaderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5720E60E55700A0803E /* TDReaderTest.m */; }; + D31FE5760E60E55700A0803E /* TDTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5740E60E55700A0803E /* TDTokenizerTest.m */; }; + D31FE5850E60E58C00A0803E /* TDNumberStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5780E60E58C00A0803E /* TDNumberStateTest.m */; }; + D31FE5860E60E58C00A0803E /* TDQuoteStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE57A0E60E58C00A0803E /* TDQuoteStateTest.m */; }; + D31FE5890E60E58C00A0803E /* TDSymbolStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5800E60E58C00A0803E /* TDSymbolStateTest.m */; }; + D31FE58A0E60E58C00A0803E /* TDWhitespaceStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5820E60E58C00A0803E /* TDWhitespaceStateTest.m */; }; + D31FE58B0E60E58C00A0803E /* TDWordStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5840E60E58C00A0803E /* TDWordStateTest.m */; }; + D31FE5960E60E5AC00A0803E /* TDCharacterAssemblyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE58D0E60E5AC00A0803E /* TDCharacterAssemblyTest.m */; }; + D31FE5970E60E5AC00A0803E /* TDCharTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE58F0E60E5AC00A0803E /* TDCharTest.m */; }; + D31FE5980E60E5AC00A0803E /* TDDigitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5910E60E5AC00A0803E /* TDDigitTest.m */; }; + D31FE5990E60E5AC00A0803E /* TDLetterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5930E60E5AC00A0803E /* TDLetterTest.m */; }; + D31FE59A0E60E5AC00A0803E /* TDSpecificCharTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5950E60E5AC00A0803E /* TDSpecificCharTest.m */; }; + D31FE59F0E60E5C000A0803E /* TDRegularParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE59C0E60E5C000A0803E /* TDRegularParser.m */; }; + D31FE5A00E60E5C000A0803E /* TDRegularParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE59E0E60E5C000A0803E /* TDRegularParserTest.m */; }; + D31FE5A90E60E5D500A0803E /* TDFastJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */; }; + D31FE5AA0E60E5D500A0803E /* TDFastJsonParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5A40E60E5D500A0803E /* TDFastJsonParserTest.m */; }; + D31FE5B10E60E64900A0803E /* TDXmlTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5AE0E60E64900A0803E /* TDXmlTokenAssembly.m */; }; + D31FE5B20E60E64900A0803E /* TDXmlTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5B00E60E64900A0803E /* TDXmlTokenizerTest.m */; }; + D31FE5B70E60E66600A0803E /* TDXmlToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5B40E60E66600A0803E /* TDXmlToken.m */; }; + D31FE5B80E60E66600A0803E /* TDXmlTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5B60E60E66600A0803E /* TDXmlTokenizer.m */; }; + D31FE5DD0E60E69E00A0803E /* TDXmlAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5BA0E60E69E00A0803E /* TDXmlAttribute.m */; }; + D31FE5DE0E60E69E00A0803E /* TDXmlCdata.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5BC0E60E69E00A0803E /* TDXmlCdata.m */; }; + D31FE5DF0E60E69E00A0803E /* TDXmlComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5BE0E60E69E00A0803E /* TDXmlComment.m */; }; + D31FE5E00E60E69E00A0803E /* TDXmlDecl.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C00E60E69E00A0803E /* TDXmlDecl.m */; }; + D31FE5E10E60E69E00A0803E /* TDXmlDoctype.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C20E60E69E00A0803E /* TDXmlDoctype.m */; }; + D31FE5E20E60E69E00A0803E /* TDXmlDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C40E60E69E00A0803E /* TDXmlDocument.m */; }; + D31FE5E30E60E69E00A0803E /* TDXmlEndEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C60E60E69E00A0803E /* TDXmlEndEntity.m */; }; + D31FE5E40E60E69E00A0803E /* TDXmlEndTag.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C80E60E69E00A0803E /* TDXmlEndTag.m */; }; + D31FE5E50E60E69E00A0803E /* TDXmlEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5CA0E60E69E00A0803E /* TDXmlEntity.m */; }; + D31FE5E60E60E69E00A0803E /* TDXmlEntityRef.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5CC0E60E69E00A0803E /* TDXmlEntityRef.m */; }; + D31FE5E70E60E69E00A0803E /* TDXmlFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5CE0E60E69E00A0803E /* TDXmlFragment.m */; }; + D31FE5E80E60E69E00A0803E /* TDXmlNotation.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D00E60E69E00A0803E /* TDXmlNotation.m */; }; + D31FE5E90E60E69E00A0803E /* TDXmlProcessingInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D20E60E69E00A0803E /* TDXmlProcessingInstruction.m */; }; + D31FE5EA0E60E69E00A0803E /* TDXmlSignificantWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D40E60E69E00A0803E /* TDXmlSignificantWhitespace.m */; }; + D31FE5EB0E60E69E00A0803E /* TDXmlStartTag.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D60E60E69E00A0803E /* TDXmlStartTag.m */; }; + D31FE5EC0E60E69E00A0803E /* TDXmlTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D80E60E69E00A0803E /* TDXmlTerminal.m */; }; + D31FE5ED0E60E69E00A0803E /* TDXmlText.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5DA0E60E69E00A0803E /* TDXmlText.m */; }; + D31FE5EE0E60E69E00A0803E /* TDXmlWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5DC0E60E69E00A0803E /* TDXmlWhitespace.m */; }; + D31FE5FC0E60E6B500A0803E /* TDNCNameState.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F10E60E6B500A0803E /* TDNCNameState.m */; }; + D31FE5FD0E60E6B500A0803E /* TDXmlName.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F30E60E6B500A0803E /* TDXmlName.m */; }; + D31FE5FE0E60E6B500A0803E /* TDXmlNameState.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F50E60E6B500A0803E /* TDXmlNameState.m */; }; + D31FE5FF0E60E6B500A0803E /* TDXmlNameTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F70E60E6B500A0803E /* TDXmlNameTest.m */; }; + D31FE6000E60E6B500A0803E /* TDXmlNmtoken.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F90E60E6B500A0803E /* TDXmlNmtoken.m */; }; + D31FE6010E60E6B500A0803E /* TDXmlNmtokenState.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5FB0E60E6B500A0803E /* TDXmlNmtokenState.m */; }; + D31FE6E00E60EE2500A0803E /* TDNCName.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE6DF0E60EE2500A0803E /* TDNCName.m */; }; + D31FE7300E60F31E00A0803E /* TDFastJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */; }; + D31FE7320E60F33000A0803E /* EBNFParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E78A160E574C99008C7D61 /* EBNFParser.m */; }; + D31FE7330E60F33C00A0803E /* XMLReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D3521F530E5FA1B0009681F9 /* XMLReader.m */; }; + D31FE7340E60F34600A0803E /* XPathParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E95450E578ECC00496BD3 /* XPathParser.m */; }; + D31FE7380E60F36600A0803E /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D36E9F860E5A795400496BD3 /* libxml2.dylib */; }; + D31FE7400E60F40300A0803E /* XPathAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */; }; + D31FE7420E60F40900A0803E /* XPathContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98210E58A3A800496BD3 /* XPathContext.m */; }; + D3252F7B0FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3252F790FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m */; }; + D3252F7E0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */; }; + D3252F7F0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */; }; + D3305C4F102F5BAE00DC4F75 /* TDGutterView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3305C4C102F5BAD00DC4F75 /* TDGutterView.m */; }; + D3305C50102F5BAE00DC4F75 /* TDSourceCodeTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3305C4E102F5BAE00DC4F75 /* TDSourceCodeTextView.m */; }; + D33494720E29670B00406085 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D3376D5910093A1600E4602E /* PKGrammarParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3376D5710093A1600E4602E /* PKGrammarParser.h */; }; + D3376D5A10093A1600E4602E /* PKGrammarParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D5810093A1600E4602E /* PKGrammarParser.m */; }; + D3376D8E10096C0700E4602E /* PKAST.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D8D10096C0700E4602E /* PKAST.m */; }; + D3376D8F10096C0700E4602E /* PKAST.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D8D10096C0700E4602E /* PKAST.m */; }; + D3385FD90FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */; }; + D3385FDA0FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */; }; + D3385FDE0FCFB227003BF729 /* TDPredicateEvaluatorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3385FDC0FCFB227003BF729 /* TDPredicateEvaluatorTest.m */; }; + D338E5BB0FF5DDCB003DE6AA /* TDDifferenceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D338E5BA0FF5DDCB003DE6AA /* TDDifferenceTest.m */; }; + D341850C0E520D640081B0DC /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D34BAC230FF87F8600D7773A /* TDParserFactoryTest3.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAC220FF87F8600D7773A /* TDParserFactoryTest3.m */; }; + D34BAC4B0FF892C200D7773A /* XPathParserGrammarTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAC4A0FF892C200D7773A /* XPathParserGrammarTest.m */; }; + D34BAC9A0FF8A9AD00D7773A /* xpath1_0.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741430EF8E96A00559B9F /* xpath1_0.grammar */; }; + D34BAD18100A9B7900996341 /* TDTokenizerStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAD17100A9B7900996341 /* TDTokenizerStateTest.m */; }; + D34BAD640FF9C6AE00D7773A /* ParseKit_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = D34BAD630FF9C6AE00D7773A /* ParseKit_Prefix.pch */; }; + D34BAD9D0FF9C95800D7773A /* PKReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAD9B0FF9C95800D7773A /* PKReader.m */; }; + D34BADA20FF9C9B000D7773A /* PKAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADA00FF9C9B000D7773A /* PKAssembly.m */; }; + D34BADD80FF9CBFB00D7773A /* PKParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADD60FF9CBFB00D7773A /* PKParser.m */; }; + D34BAE030FF9CCAE00D7773A /* PKCollectionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */; }; + D34BAE1D0FF9CE0E00D7773A /* PKAlternation.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */; }; + D34BAE1F0FF9CE0E00D7773A /* PKEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */; }; + D34BAE210FF9CE0E00D7773A /* PKDifference.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */; }; + D34BAE230FF9CE0E00D7773A /* PKIntersection.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE110FF9CE0E00D7773A /* PKIntersection.m */; }; + D34BAE250FF9CE0E00D7773A /* PKRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE130FF9CE0E00D7773A /* PKRepetition.m */; }; + D34BAE270FF9CE0E00D7773A /* PKSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE150FF9CE0E00D7773A /* PKSequence.m */; }; + D34BAE290FF9CE0E00D7773A /* PKTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE170FF9CE0E00D7773A /* PKTerminal.m */; }; + D34BAE2B0FF9CE0E00D7773A /* PKTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE190FF9CE0E00D7773A /* PKTrack.m */; }; + D34BAE2D0FF9CE0E00D7773A /* PKTrackException.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */; }; + D34BAE310FF9CE6000D7773A /* PKAny.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE2F0FF9CE6000D7773A /* PKAny.m */; }; + D34BAE8D0FF9D15100D7773A /* PKTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */; }; + D34BAE9D0FF9D20900D7773A /* PKToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE950FF9D20900D7773A /* PKToken.m */; }; + D34BAE9F0FF9D20900D7773A /* PKTokenArraySource.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */; }; + D34BAEA10FF9D20900D7773A /* PKTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE990FF9D20900D7773A /* PKTokenizer.m */; }; + D34BAEA30FF9D20900D7773A /* PKTokenizerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */; }; + D34BAED80FF9D56400D7773A /* PKCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC40FF9D56400D7773A /* PKCommentState.m */; }; + D34BAEDA0FF9D56400D7773A /* PKDelimitState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC60FF9D56400D7773A /* PKDelimitState.m */; }; + D34BAEDC0FF9D56400D7773A /* PKMultiLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */; }; + D34BAEDE0FF9D56400D7773A /* PKNumberState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECA0FF9D56400D7773A /* PKNumberState.m */; }; + D34BAEE00FF9D56400D7773A /* PKQuoteState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECC0FF9D56400D7773A /* PKQuoteState.m */; }; + D34BAEE20FF9D56400D7773A /* PKSingleLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */; }; + D34BAEE40FF9D56400D7773A /* PKSymbolState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED00FF9D56400D7773A /* PKSymbolState.m */; }; + D34BAEE60FF9D56400D7773A /* PKWhitespaceState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */; }; + D34BAEE80FF9D56400D7773A /* PKWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED40FF9D56400D7773A /* PKWord.m */; }; + D34BAEEA0FF9D56400D7773A /* PKWordState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED60FF9D56400D7773A /* PKWordState.m */; }; + D34BAF280FF9DF9900D7773A /* PKSymbolNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */; }; + D34BAF2A0FF9DF9900D7773A /* PKSymbolRootNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */; }; + D34BAF3A0FF9E18300D7773A /* PKPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF380FF9E18300D7773A /* PKPattern.m */; }; + D34BAF4C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */; }; + D34BAF4E0FF9E19700D7773A /* PKComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3E0FF9E19700D7773A /* PKComment.m */; }; + D34BAF500FF9E19700D7773A /* PKDelimitedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF400FF9E19700D7773A /* PKDelimitedString.m */; }; + D34BAF520FF9E19700D7773A /* PKLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF420FF9E19700D7773A /* PKLiteral.m */; }; + D34BAF540FF9E19700D7773A /* PKNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF440FF9E19700D7773A /* PKNumber.m */; }; + D34BAF560FF9E19700D7773A /* PKQuotedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF460FF9E19700D7773A /* PKQuotedString.m */; }; + D34BAF580FF9E19700D7773A /* PKSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF480FF9E19700D7773A /* PKSymbol.m */; }; + D34BAF5A0FF9E19700D7773A /* PKWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */; }; + D34BAF9D0FF9E6D100D7773A /* PKLowercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */; }; + D34BAF9F0FF9E6D100D7773A /* PKUppercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */; }; + D34BAFB20FF9E7F300D7773A /* PKCharacterAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */; }; + D34BAFBC0FF9E80300D7773A /* PKChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB40FF9E80300D7773A /* PKChar.m */; }; + D34BAFBE0FF9E80300D7773A /* PKDigit.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB60FF9E80300D7773A /* PKDigit.m */; }; + D34BAFC00FF9E80300D7773A /* PKLetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB80FF9E80300D7773A /* PKLetter.m */; }; + D34BAFC20FF9E80300D7773A /* PKSpecificChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */; }; + D34BAFDA0FF9E95500D7773A /* NSArray+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */; }; + D34BAFDC0FF9E95500D7773A /* NSString+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */; }; + D34BAFDE0FF9E95500D7773A /* PKParserFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD80FF9E95500D7773A /* PKParserFactory.m */; }; + D34BB0680FF9EDDF00D7773A /* JSParseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0660FF9EDDF00D7773A /* JSParseKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0690FF9EDDF00D7773A /* JSParseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0670FF9EDDF00D7773A /* JSParseKit.m */; }; + D34BB0710FF9EE4000D7773A /* PKJSAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06A0FF9EE4000D7773A /* PKJSAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0720FF9EE4000D7773A /* PKJSAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB06B0FF9EE4000D7773A /* PKJSAssembly.m */; }; + D34BB0730FF9EE4000D7773A /* PKJSUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06C0FF9EE4000D7773A /* PKJSUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0740FF9EE4000D7773A /* PKJSUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB06D0FF9EE4000D7773A /* PKJSUtils.m */; }; + D34BB0750FF9EE4000D7773A /* PKJSUtils_macros.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06E0FF9EE4000D7773A /* PKJSUtils_macros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0760FF9EE4000D7773A /* PKJSValueHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06F0FF9EE4000D7773A /* PKJSValueHolder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0770FF9EE4000D7773A /* PKJSValueHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0700FF9EE4000D7773A /* PKJSValueHolder.m */; }; + D34BB08F0FF9EF9D00D7773A /* PKJSCharacterAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB08D0FF9EF9D00D7773A /* PKJSCharacterAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0900FF9EF9D00D7773A /* PKJSCharacterAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB08E0FF9EF9D00D7773A /* PKJSCharacterAssembly.m */; }; + D34BB0A90FF9F14B00D7773A /* PKJSCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0930FF9F14B00D7773A /* PKJSCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0AA0FF9F14B00D7773A /* PKJSCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0940FF9F14B00D7773A /* PKJSCommentState.m */; }; + D34BB0AB0FF9F14B00D7773A /* PKJSDelimitState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0950FF9F14B00D7773A /* PKJSDelimitState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0AC0FF9F14B00D7773A /* PKJSDelimitState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0960FF9F14B00D7773A /* PKJSDelimitState.m */; }; + D34BB0AD0FF9F14B00D7773A /* PKJSNumberState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0970FF9F14B00D7773A /* PKJSNumberState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0AE0FF9F14B00D7773A /* PKJSNumberState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0980FF9F14B00D7773A /* PKJSNumberState.m */; }; + D34BB0AF0FF9F14B00D7773A /* PKJSQuoteState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0990FF9F14B00D7773A /* PKJSQuoteState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B00FF9F14B00D7773A /* PKJSQuoteState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB09A0FF9F14B00D7773A /* PKJSQuoteState.m */; }; + D34BB0B10FF9F14B00D7773A /* PKJSSymbolState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB09B0FF9F14B00D7773A /* PKJSSymbolState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B20FF9F14B00D7773A /* PKJSSymbolState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB09C0FF9F14B00D7773A /* PKJSSymbolState.m */; }; + D34BB0B30FF9F14B00D7773A /* PKJSToken.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB09D0FF9F14B00D7773A /* PKJSToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B40FF9F14B00D7773A /* PKJSToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB09E0FF9F14B00D7773A /* PKJSToken.m */; }; + D34BB0B50FF9F14B00D7773A /* PKJSTokenAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB09F0FF9F14B00D7773A /* PKJSTokenAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B60FF9F14B00D7773A /* PKJSTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A00FF9F14B00D7773A /* PKJSTokenAssembly.m */; }; + D34BB0B70FF9F14B00D7773A /* PKJSTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A10FF9F14B00D7773A /* PKJSTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B80FF9F14B00D7773A /* PKJSTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A20FF9F14B00D7773A /* PKJSTokenizer.m */; }; + D34BB0B90FF9F14B00D7773A /* PKJSTokenizerState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A30FF9F14B00D7773A /* PKJSTokenizerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0BA0FF9F14B00D7773A /* PKJSTokenizerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A40FF9F14B00D7773A /* PKJSTokenizerState.m */; }; + D34BB0BB0FF9F14B00D7773A /* PKJSWhitespaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A50FF9F14B00D7773A /* PKJSWhitespaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0BC0FF9F14B00D7773A /* PKJSWhitespaceState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A60FF9F14B00D7773A /* PKJSWhitespaceState.m */; }; + D34BB0BD0FF9F14B00D7773A /* PKJSWordState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A70FF9F14B00D7773A /* PKJSWordState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0BE0FF9F14B00D7773A /* PKJSWordState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A80FF9F14B00D7773A /* PKJSWordState.m */; }; + D34BB0E60FF9F28000D7773A /* PKJSAlternation.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D20FF9F28000D7773A /* PKJSAlternation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0E70FF9F28000D7773A /* PKJSAlternation.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D30FF9F28000D7773A /* PKJSAlternation.m */; }; + D34BB0E80FF9F28000D7773A /* PKJSAny.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D40FF9F28000D7773A /* PKJSAny.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0E90FF9F28000D7773A /* PKJSAny.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D50FF9F28000D7773A /* PKJSAny.m */; }; + D34BB0EA0FF9F28000D7773A /* PKJSAssemblerAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D60FF9F28000D7773A /* PKJSAssemblerAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0EB0FF9F28000D7773A /* PKJSAssemblerAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D70FF9F28000D7773A /* PKJSAssemblerAdapter.m */; }; + D34BB0EC0FF9F28000D7773A /* PKJSCollectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D80FF9F28000D7773A /* PKJSCollectionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0ED0FF9F28000D7773A /* PKJSCollectionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D90FF9F28000D7773A /* PKJSCollectionParser.m */; }; + D34BB0EE0FF9F28000D7773A /* PKJSEmpty.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0DA0FF9F28000D7773A /* PKJSEmpty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0EF0FF9F28000D7773A /* PKJSEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0DB0FF9F28000D7773A /* PKJSEmpty.m */; }; + D34BB0F00FF9F28000D7773A /* PKJSParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0DC0FF9F28000D7773A /* PKJSParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F10FF9F28000D7773A /* PKJSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0DD0FF9F28000D7773A /* PKJSParser.m */; }; + D34BB0F20FF9F28000D7773A /* PKJSRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0DE0FF9F28000D7773A /* PKJSRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F30FF9F28000D7773A /* PKJSRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0DF0FF9F28000D7773A /* PKJSRepetition.m */; }; + D34BB0F40FF9F28000D7773A /* PKJSSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0E00FF9F28000D7773A /* PKJSSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F50FF9F28000D7773A /* PKJSSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0E10FF9F28000D7773A /* PKJSSequence.m */; }; + D34BB0F60FF9F28000D7773A /* PKJSTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0E20FF9F28000D7773A /* PKJSTerminal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F70FF9F28000D7773A /* PKJSTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0E30FF9F28000D7773A /* PKJSTerminal.m */; }; + D34BB0F80FF9F28000D7773A /* PKJSTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0E40FF9F28000D7773A /* PKJSTrack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F90FF9F28000D7773A /* PKJSTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0E50FF9F28000D7773A /* PKJSTrack.m */; }; + D34BB1140FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0FE0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1150FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0FF0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m */; }; + D34BB1160FF9F36200D7773A /* PKJSComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1000FF9F36200D7773A /* PKJSComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1170FF9F36200D7773A /* PKJSComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1010FF9F36200D7773A /* PKJSComment.m */; }; + D34BB1180FF9F36200D7773A /* PKJSDelimitedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1020FF9F36200D7773A /* PKJSDelimitedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1190FF9F36200D7773A /* PKJSDelimitedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1030FF9F36200D7773A /* PKJSDelimitedString.m */; }; + D34BB11A0FF9F36200D7773A /* PKJSLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1040FF9F36200D7773A /* PKJSLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB11B0FF9F36200D7773A /* PKJSLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1050FF9F36200D7773A /* PKJSLiteral.m */; }; + D34BB11C0FF9F36200D7773A /* PKJSLowercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1060FF9F36200D7773A /* PKJSLowercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB11D0FF9F36200D7773A /* PKJSLowercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1070FF9F36200D7773A /* PKJSLowercaseWord.m */; }; + D34BB11E0FF9F36200D7773A /* PKJSNum.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1080FF9F36200D7773A /* PKJSNum.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB11F0FF9F36200D7773A /* PKJSNum.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1090FF9F36200D7773A /* PKJSNum.m */; }; + D34BB1200FF9F36200D7773A /* PKJSPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB10A0FF9F36200D7773A /* PKJSPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1210FF9F36200D7773A /* PKJSPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB10B0FF9F36200D7773A /* PKJSPattern.m */; }; + D34BB1220FF9F36200D7773A /* PKJSQuotedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB10C0FF9F36200D7773A /* PKJSQuotedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1230FF9F36200D7773A /* PKJSQuotedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB10D0FF9F36200D7773A /* PKJSQuotedString.m */; }; + D34BB1240FF9F36200D7773A /* PKJSSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB10E0FF9F36200D7773A /* PKJSSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1250FF9F36200D7773A /* PKJSSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB10F0FF9F36200D7773A /* PKJSSymbol.m */; }; + D34BB1260FF9F36200D7773A /* PKJSUppercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1100FF9F36200D7773A /* PKJSUppercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1270FF9F36200D7773A /* PKJSUppercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1110FF9F36200D7773A /* PKJSUppercaseWord.m */; }; + D34BB1280FF9F36200D7773A /* PKJSWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1120FF9F36200D7773A /* PKJSWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1290FF9F36200D7773A /* PKJSWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1130FF9F36200D7773A /* PKJSWord.m */; }; + D3521F560E5FA1B0009681F9 /* XMLReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D3521F530E5FA1B0009681F9 /* XMLReader.m */; }; + D3521F570E5FA1B0009681F9 /* XMLReaderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3521F550E5FA1B0009681F9 /* XMLReaderTest.m */; }; + D35384ED0FE9691100926552 /* nspredicate.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D35384EC0FE9691100926552 /* nspredicate.grammar */; }; + D353899C0FEAC94400926552 /* c.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D353899B0FEAC94400926552 /* c.grammar */; }; + D353899E0FEAC96B00926552 /* objc.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D353899D0FEAC96B00926552 /* objc.grammar */; }; + D355C62D0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */; }; + D355C62E0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */; }; + D355C6310FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D355C6300FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m */; }; + D355C6A70FE9F704006A91A4 /* nspredicate.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D35384EC0FE9691100926552 /* nspredicate.grammar */; }; + D355C8810FEB36A1006A91A4 /* xml.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D355C8800FEB36A1006A91A4 /* xml.grammar */; }; + D355C8840FEB4B94006A91A4 /* proto.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D355C8830FEB4B94006A91A4 /* proto.grammar */; }; + D3587EAF0FE83EC900DDD023 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D36568A70EEF9FE900226554 /* TDPlistParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36568A60EEF9FE900226554 /* TDPlistParser.m */; }; + D36568AA0EEFA05300226554 /* TDPlistParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D36568A90EEFA05300226554 /* TDPlistParserTest.m */; }; + D3656DFE0EF2620E00226554 /* TDTokenArraySourceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3656DFD0EF2620E00226554 /* TDTokenArraySourceTest.m */; }; + D3668292101D2BFA0008632C /* erb.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3668291101D2BFA0008632C /* erb.grammar */; }; + D3668293101D2C000008632C /* erb.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3668291101D2BFA0008632C /* erb.grammar */; }; + D3668296101D2C200008632C /* ERBTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3668295101D2C200008632C /* ERBTest.m */; }; + D369345D1038DE5300527AF3 /* PKParseTree.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934561038DE5300527AF3 /* PKParseTree.m */; }; + D369345E1038DE5300527AF3 /* PKParseTreeAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */; }; + D369345F1038DE5300527AF3 /* PKRuleNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345A1038DE5300527AF3 /* PKRuleNode.m */; }; + D36934601038DE5300527AF3 /* PKTokenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345C1038DE5300527AF3 /* PKTokenNode.m */; }; + D36934721038E28300527AF3 /* PKParseTree.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934561038DE5300527AF3 /* PKParseTree.m */; }; + D36934731038E28700527AF3 /* PKParseTreeAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */; }; + D36934741038E28B00527AF3 /* PKRuleNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345A1038DE5300527AF3 /* PKRuleNode.m */; }; + D36934751038E28F00527AF3 /* PKTokenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345C1038DE5300527AF3 /* PKTokenNode.m */; }; + D36C53790FD27F1300141CB7 /* TDParserFactoryTest2.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C53780FD27F1300141CB7 /* TDParserFactoryTest2.m */; }; + D36C55FF0FD3617B00141CB7 /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */; }; + D36C560C0FD363D500141CB7 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D36C560B0FD363D500141CB7 /* libicucore.dylib */; }; + D36C562B0FD365DB00141CB7 /* TDPatternTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C562A0FD365DB00141CB7 /* TDPatternTest.m */; }; + D36E95460E578ECC00496BD3 /* XPathParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E95450E578ECC00496BD3 /* XPathParser.m */; }; + D36E95D80E57B08400496BD3 /* XPathParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E95D70E57B08400496BD3 /* XPathParserTest.m */; }; + D36E97B00E589DAE00496BD3 /* XPathAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */; }; + D36E98220E58A3A800496BD3 /* XPathContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98210E58A3A800496BD3 /* XPathContext.m */; }; + D36E98E00E58C12800496BD3 /* DebugAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98DD0E58C12800496BD3 /* DebugAppDelegate.m */; }; + D36E98E10E58C12800496BD3 /* DebugAppMainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D36E98DE0E58C12800496BD3 /* DebugAppMainMenu.xib */; }; + D36E98E20E58C12800496BD3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98DF0E58C12800496BD3 /* main.m */; }; + D36E98E70E58C14000496BD3 /* DemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98E40E58C14000496BD3 /* DemoAppDelegate.m */; }; + D36E98E80E58C14000496BD3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98E50E58C14000496BD3 /* main.m */; }; + D36E98F80E58C1A000496BD3 /* DemoAppMainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D36E98F70E58C1A000496BD3 /* DemoAppMainMenu.xib */; }; + D36E9F870E5A795400496BD3 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D36E9F860E5A795400496BD3 /* libxml2.dylib */; }; + D36E9FB50E5A944A00496BD3 /* apple-boss.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36E9FB40E5A944A00496BD3 /* apple-boss.xml */; }; + D36E9FE50E5BA0FC00496BD3 /* SRGSGrammar.txt in Resources */ = {isa = PBXBuildFile; fileRef = D36E9FE40E5BA0FC00496BD3 /* SRGSGrammar.txt */; }; + D36EA3B00E5EA67E00496BD3 /* small-xml-file.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */; }; + D37A28671013942300E936B7 /* PKGrammarParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D5810093A1600E4602E /* PKGrammarParser.m */; }; + D37A28681013942A00E936B7 /* PKGrammarParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3376D5710093A1600E4602E /* PKGrammarParser.h */; }; + D37D3A000FE77A71008C2E4D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D37D3A010FE77A72008C2E4D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D37D3A020FE77A77008C2E4D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D380AFBD0F0C54B60009EC13 /* html.css in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBB0F0C54B60009EC13 /* html.css */; }; + D380AFBE0F0C54B60009EC13 /* html.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBC0F0C54B60009EC13 /* html.grammar */; }; + D380AFBF0F0C54B60009EC13 /* html.css in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBB0F0C54B60009EC13 /* html.css */; }; + D380AFC00F0C54B60009EC13 /* html.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBC0F0C54B60009EC13 /* html.grammar */; }; + D380AFC30F0C56000009EC13 /* example.html in Resources */ = {isa = PBXBuildFile; fileRef = D380AFC20F0C56000009EC13 /* example.html */; }; + D380AFC40F0C56000009EC13 /* example.html in Resources */ = {isa = PBXBuildFile; fileRef = D380AFC20F0C56000009EC13 /* example.html */; }; + D380B3230F0CC0800009EC13 /* nyt.html in Resources */ = {isa = PBXBuildFile; fileRef = D38DD9E70EC29F260070BC4D /* nyt.html */; }; + D380B5090F0D71A90009EC13 /* css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380B5080F0D71A90009EC13 /* css.grammar */; }; + D380B50A0F0D71B00009EC13 /* css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380B5080F0D71A90009EC13 /* css.grammar */; }; + D380B5380F0D7DDE0009EC13 /* css.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5370F0D7DDE0009EC13 /* css.css */; }; + D380B5390F0D7DE30009EC13 /* css.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5370F0D7DDE0009EC13 /* css.css */; }; + D380B5940F0D82F60009EC13 /* example.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5930F0D82F60009EC13 /* example.css */; }; + D380B5950F0D82F90009EC13 /* example.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5930F0D82F60009EC13 /* example.css */; }; + D380B9800F0EF3860009EC13 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D380BA620F0F06CD0009EC13 /* TDParserFactoryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D380BA600F0F06CD0009EC13 /* TDParserFactoryTest.m */; }; + D380BAA30F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D380BAA40F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D38205BE0EEE48EE004340DD /* TDTokenTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D38205BD0EEE48EE004340DD /* TDTokenTest.m */; }; + D383498B0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */; }; + D383498C0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */; }; + D38349BC0F0C0D910055E4E0 /* json_with_comments.css in Resources */ = {isa = PBXBuildFile; fileRef = D38349BB0F0C0D910055E4E0 /* json_with_comments.css */; }; + D38349BD0F0C0D910055E4E0 /* json_with_comments.css in Resources */ = {isa = PBXBuildFile; fileRef = D38349BB0F0C0D910055E4E0 /* json_with_comments.css */; }; + D3834A480F0C14B60055E4E0 /* yahoo_with_comments.json in Resources */ = {isa = PBXBuildFile; fileRef = D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */; }; + D3834A490F0C14C00055E4E0 /* yahoo_with_comments.json in Resources */ = {isa = PBXBuildFile; fileRef = D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */; }; + D385F98C0F046FE900DB2946 /* TDGenericAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385F9890F046FE900DB2946 /* TDGenericAssembler.m */; }; + D385F98E0F046FE900DB2946 /* TDGenericAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385F9890F046FE900DB2946 /* TDGenericAssembler.m */; }; + D385FA230F04971400DB2946 /* TDGenericAssemblerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FA220F04971400DB2946 /* TDGenericAssemblerTest.m */; }; + D385FA250F04993500DB2946 /* json.css in Resources */ = {isa = PBXBuildFile; fileRef = D385FA240F04993500DB2946 /* json.css */; }; + D385FA260F04993500DB2946 /* json.css in Resources */ = {isa = PBXBuildFile; fileRef = D385FA240F04993500DB2946 /* json.css */; }; + D385FD440F05A88C00DB2946 /* TDMiniCSSAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */; }; + D385FD460F05A89100DB2946 /* TDMiniCSSAssemblerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FD430F05A88C00DB2946 /* TDMiniCSSAssemblerTest.m */; }; + D385FD490F05A8C900DB2946 /* TDMiniCSSAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */; }; + D385FD6C0F05A99900DB2946 /* mini_css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D385FD6B0F05A99900DB2946 /* mini_css.grammar */; }; + D385FD6D0F05A99900DB2946 /* mini_css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D385FD6B0F05A99900DB2946 /* mini_css.grammar */; }; + D389F1D50F19666500558235 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D389F20B0F196A9200558235 /* JSParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D389F1CE0F1965E600558235 /* JSParseKit.framework */; }; + D389F20C0F196A9200558235 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D389F20E0F196A9200558235 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D389F20D0F196A9200558235 /* WebKit.framework */; }; + D389F2E40F196CAE00558235 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F2E30F196CAE00558235 /* main.m */; }; + D389F3430F197DDC00558235 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D389F34E0F197DF500558235 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D389F37A0F197E8000558235 /* JSDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F2E90F196F5B00558235 /* JSDemoAppDelegate.m */; }; + D389F38F0F19800400558235 /* DefaultValues.plist in Resources */ = {isa = PBXBuildFile; fileRef = D389F38E0F19800400558235 /* DefaultValues.plist */; }; + D389F4620F198A8800558235 /* Test.html in Resources */ = {isa = PBXBuildFile; fileRef = D389F4610F198A8800558235 /* Test.html */; }; + D389F5590F19B7BC00558235 /* JSDemoAppMainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D389F5580F19B7BC00558235 /* JSDemoAppMainMenu.xib */; }; + D389F5B60F19C76A00558235 /* TDJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F5B30F19C76A00558235 /* TDJsonParser.m */; }; + D389F5B70F19C76A00558235 /* TDJsonParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F5B50F19C76A00558235 /* TDJsonParserTest.m */; }; + D389F5B80F19C76A00558235 /* TDJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F5B30F19C76A00558235 /* TDJsonParser.m */; }; + D389FBCD0F1B25E200558235 /* ParserTest.html in Resources */ = {isa = PBXBuildFile; fileRef = D389FBCC0F1B25E200558235 /* ParserTest.html */; }; + D38DD9E80EC29F260070BC4D /* nyt.html in Resources */ = {isa = PBXBuildFile; fileRef = D38DD9E70EC29F260070BC4D /* nyt.html */; }; + D38E97CC1061CF6500739C39 /* TDTokenizerBlocksTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D38E97CB1061CF6500739C39 /* TDTokenizerBlocksTest.m */; }; + D38E98D81062C5BA00739C39 /* TDParserBlocksTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D38E98D71062C5BA00739C39 /* TDParserBlocksTest.m */; }; + D398E20E0E60F86D00A1C877 /* yahoo.json in Resources */ = {isa = PBXBuildFile; fileRef = D3B473840E48C9CF008AFBDD /* yahoo.json */; }; + D39E01340FEF02DA00150FC3 /* TDXMLParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3BBBC970FEC9722007DF30D /* TDXMLParserTest.m */; }; + D3AF49780FDB122E0032F4DC /* TDParserFactoryPatternTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3AF49770FDB122E0032F4DC /* TDParserFactoryPatternTest.m */; }; + D3B43FB80F76E99C0072AF40 /* TDJavaScriptParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3B43FB60F76E99C0072AF40 /* TDJavaScriptParserTest.m */; }; + D3B473850E48C9CF008AFBDD /* yahoo.json in Resources */ = {isa = PBXBuildFile; fileRef = D3B473840E48C9CF008AFBDD /* yahoo.json */; }; + D3B69D320E80249900D70C41 /* nonascii.html in Resources */ = {isa = PBXBuildFile; fileRef = D3B69D310E80249900D70C41 /* nonascii.html */; }; + D3B69D330E80249900D70C41 /* nonascii.html in Resources */ = {isa = PBXBuildFile; fileRef = D3B69D310E80249900D70C41 /* nonascii.html */; }; + D3BBBC9D0FEC9756007DF30D /* TDXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */; }; + D3BBBC9E0FEC9756007DF30D /* TDXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */; }; + D3BBBCC10FECD477007DF30D /* xml.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D355C8800FEB36A1006A91A4 /* xml.grammar */; }; + D3C031ED0EF38D2D00C5ABEB /* TDLowercaseWordTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C031EC0EF38D2D00C5ABEB /* TDLowercaseWordTest.m */; }; + D3C221920FFE8B8C004514FE /* ParseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221900FFE8B8C004514FE /* ParseKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221930FFE8B8C004514FE /* PKTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221910FFE8B8C004514FE /* PKTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221940FFE8B8C004514FE /* ParseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221900FFE8B8C004514FE /* ParseKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221950FFE8B8C004514FE /* PKTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221910FFE8B8C004514FE /* PKTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221970FFE8B95004514FE /* PKReader.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221960FFE8B95004514FE /* PKReader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221980FFE8B95004514FE /* PKReader.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221960FFE8B95004514FE /* PKReader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219A0FFE8B9D004514FE /* PKAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221990FFE8B9D004514FE /* PKAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219B0FFE8B9D004514FE /* PKAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221990FFE8B9D004514FE /* PKAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219D0FFE8BA6004514FE /* PKParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219C0FFE8BA6004514FE /* PKParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219E0FFE8BA6004514FE /* PKParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219C0FFE8BA6004514FE /* PKParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A00FFE8BAE004514FE /* PKRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219F0FFE8BAE004514FE /* PKRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A10FFE8BAE004514FE /* PKRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219F0FFE8BAE004514FE /* PKRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A30FFE8BBA004514FE /* PKCollectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A40FFE8BBA004514FE /* PKCollectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A60FFE8BC1004514FE /* PKAlternation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A50FFE8BC1004514FE /* PKAlternation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A70FFE8BC1004514FE /* PKAlternation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A50FFE8BC1004514FE /* PKAlternation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A90FFE8BC9004514FE /* PKSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A80FFE8BC9004514FE /* PKSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AA0FFE8BC9004514FE /* PKSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A80FFE8BC9004514FE /* PKSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AC0FFE8BCF004514FE /* PKTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AB0FFE8BCF004514FE /* PKTrack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AD0FFE8BCF004514FE /* PKTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AB0FFE8BCF004514FE /* PKTrack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AF0FFE8BD4004514FE /* PKTrackException.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AE0FFE8BD4004514FE /* PKTrackException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B00FFE8BD4004514FE /* PKTrackException.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AE0FFE8BD4004514FE /* PKTrackException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B20FFE8BDB004514FE /* PKIntersection.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B10FFE8BDB004514FE /* PKIntersection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B30FFE8BDB004514FE /* PKIntersection.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B10FFE8BDB004514FE /* PKIntersection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B50FFE8BE2004514FE /* PKDifference.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B40FFE8BE2004514FE /* PKDifference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B60FFE8BE2004514FE /* PKDifference.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B40FFE8BE2004514FE /* PKDifference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B80FFE8BE8004514FE /* PKNegation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B70FFE8BE8004514FE /* PKNegation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B90FFE8BE8004514FE /* PKNegation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B70FFE8BE8004514FE /* PKNegation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BB0FFE8BEF004514FE /* PKTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BA0FFE8BEF004514FE /* PKTerminal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BC0FFE8BEF004514FE /* PKTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BA0FFE8BEF004514FE /* PKTerminal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BE0FFE8BF7004514FE /* PKEmpty.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BD0FFE8BF7004514FE /* PKEmpty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BF0FFE8BF7004514FE /* PKEmpty.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BD0FFE8BF7004514FE /* PKEmpty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C10FFE8BFF004514FE /* PKTokenAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C20FFE8BFF004514FE /* PKTokenAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C40FFE8C07004514FE /* PKToken.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C30FFE8C07004514FE /* PKToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C50FFE8C07004514FE /* PKToken.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C30FFE8C07004514FE /* PKToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C70FFE8C0D004514FE /* PKTokenArraySource.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C80FFE8C0D004514FE /* PKTokenArraySource.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CA0FFE8C15004514FE /* PKTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C90FFE8C15004514FE /* PKTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CB0FFE8C15004514FE /* PKTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C90FFE8C15004514FE /* PKTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CD0FFE8C1B004514FE /* PKTokenizerState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CE0FFE8C1B004514FE /* PKTokenizerState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D00FFE8C24004514FE /* PKNumberState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CF0FFE8C24004514FE /* PKNumberState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D10FFE8C24004514FE /* PKNumberState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CF0FFE8C24004514FE /* PKNumberState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D60FFE8C35004514FE /* PKSymbolState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D50FFE8C35004514FE /* PKSymbolState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D70FFE8C35004514FE /* PKSymbolState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D50FFE8C35004514FE /* PKSymbolState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D90FFE8C3D004514FE /* PKWordState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D80FFE8C3D004514FE /* PKWordState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DA0FFE8C3D004514FE /* PKWordState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D80FFE8C3D004514FE /* PKWordState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DC0FFE8C43004514FE /* PKWhitespaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DD0FFE8C43004514FE /* PKWhitespaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DF0FFE8C49004514FE /* PKDelimitState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DE0FFE8C49004514FE /* PKDelimitState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E00FFE8C49004514FE /* PKDelimitState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DE0FFE8C49004514FE /* PKDelimitState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E20FFE8C4E004514FE /* PKCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E10FFE8C4E004514FE /* PKCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E30FFE8C4E004514FE /* PKCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E10FFE8C4E004514FE /* PKCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E50FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E60FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E80FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E90FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EB0FFE8C69004514FE /* PKSymbolNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EC0FFE8C69004514FE /* PKSymbolNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EE0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EF0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F10FFE8C7A004514FE /* PKPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F00FFE8C7A004514FE /* PKPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F20FFE8C7A004514FE /* PKPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F00FFE8C7A004514FE /* PKPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F40FFE8C87004514FE /* PKWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F30FFE8C87004514FE /* PKWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F50FFE8C87004514FE /* PKWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F30FFE8C87004514FE /* PKWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F70FFE8C8E004514FE /* PKNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F60FFE8C8E004514FE /* PKNumber.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FA0FFE8C97004514FE /* PKQuotedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F90FFE8C97004514FE /* PKQuotedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FB0FFE8C97004514FE /* PKQuotedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F90FFE8C97004514FE /* PKQuotedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FD0FFE8CB2004514FE /* PKSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FC0FFE8CB2004514FE /* PKSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FE0FFE8CB2004514FE /* PKSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FC0FFE8CB2004514FE /* PKSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222000FFE8CB9004514FE /* PKLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FF0FFE8CB9004514FE /* PKLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222010FFE8CB9004514FE /* PKLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FF0FFE8CB9004514FE /* PKLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222030FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222040FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222060FFE8CCA004514FE /* PKWhitespace.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222050FFE8CCA004514FE /* PKWhitespace.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222070FFE8CCA004514FE /* PKWhitespace.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222050FFE8CCA004514FE /* PKWhitespace.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222090FFE8CD1004514FE /* PKComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222080FFE8CD1004514FE /* PKComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220A0FFE8CD1004514FE /* PKComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222080FFE8CD1004514FE /* PKComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220C0FFE8CD8004514FE /* PKDelimitedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220D0FFE8CD8004514FE /* PKDelimitedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220F0FFE8CDF004514FE /* PKAny.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220E0FFE8CDF004514FE /* PKAny.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222100FFE8CDF004514FE /* PKAny.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220E0FFE8CDF004514FE /* PKAny.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222150FFE8D01004514FE /* PKLowercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222140FFE8D01004514FE /* PKLowercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222160FFE8D01004514FE /* PKLowercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222140FFE8D01004514FE /* PKLowercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222180FFE8D11004514FE /* PKUppercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222170FFE8D11004514FE /* PKUppercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222190FFE8D11004514FE /* PKUppercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222170FFE8D11004514FE /* PKUppercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221B0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221C0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221E0FFE8D3B004514FE /* PKChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221D0FFE8D3B004514FE /* PKChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221F0FFE8D3B004514FE /* PKChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221D0FFE8D3B004514FE /* PKChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222210FFE8D42004514FE /* PKDigit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222200FFE8D42004514FE /* PKDigit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222220FFE8D42004514FE /* PKDigit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222200FFE8D42004514FE /* PKDigit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222240FFE8D49004514FE /* PKLetter.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222230FFE8D49004514FE /* PKLetter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222250FFE8D49004514FE /* PKLetter.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222230FFE8D49004514FE /* PKLetter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222270FFE8D6B004514FE /* PKSpecificChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222260FFE8D6B004514FE /* PKSpecificChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222280FFE8D6B004514FE /* PKSpecificChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222260FFE8D6B004514FE /* PKSpecificChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2222A0FFE8DAC004514FE /* PKParserFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222290FFE8DAC004514FE /* PKParserFactory.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2222B0FFE8DAC004514FE /* PKParserFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222290FFE8DAC004514FE /* PKParserFactory.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2222D0FFE8DE9004514FE /* NSArray+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */; }; + D3C2222E0FFE8DEE004514FE /* NSString+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */; }; + D3C2222F0FFE8DEF004514FE /* NSString+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */; }; + D3C222300FFE8DF3004514FE /* NSArray+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */; }; + D3C7D9DA0A412874005DD154 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D3C85C7B0E63B438000445FD /* TDArithmeticParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C85C7A0E63B438000445FD /* TDArithmeticParser.m */; }; + D3C85C800E63B9E9000445FD /* TDArithmeticParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C85C7F0E63B9E9000445FD /* TDArithmeticParserTest.m */; }; + D3C85D450E63D1BF000445FD /* TDScientificNumberStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C85D440E63D1BF000445FD /* TDScientificNumberStateTest.m */; }; + D3D01CAA0EFDB89900C24DDE /* json_with_discards.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */; }; + D3D01CAB0EFDB8A000C24DDE /* json_with_discards.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */; }; + D3D01CAC0EFDB8A100C24DDE /* json_with_discards.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */; }; + D3D1BF2810394420003656E5 /* SAXAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D1BF2710394420003656E5 /* SAXAssembler.m */; }; + D3D1BF2B1039445C003656E5 /* SAXTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D1BF2A1039445C003656E5 /* SAXTest.m */; }; + D3DCB3730EF5E5D600DE5110 /* OCMock.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D3DCB37D0EF5E5E400DE5110 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D3DCB4C30EF6015300DE5110 /* json.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3DCB4C20EF6015300DE5110 /* json.grammar */; }; + D3DCB4C40EF6015C00DE5110 /* json.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3DCB4C20EF6015300DE5110 /* json.grammar */; }; + D3DCB4C50EF6015C00DE5110 /* json.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3DCB4C20EF6015300DE5110 /* json.grammar */; }; + D3DDDA870F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */; }; + D3DDDA880F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */; }; + D3DDDAFE0F083C9700A58000 /* TDCommentStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3DDDAFD0F083C9700A58000 /* TDCommentStateTest.m */; }; + D3DDDCAD0F0880D800A58000 /* example1.srgs in Resources */ = {isa = PBXBuildFile; fileRef = D3DDDCAC0F0880D800A58000 /* example1.srgs */; }; + D3DDDCAE0F0880D800A58000 /* example1.srgs in Resources */ = {isa = PBXBuildFile; fileRef = D3DDDCAC0F0880D800A58000 /* example1.srgs */; }; + D3E27A320E741DD20078CC2C /* small-xml-file.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */; }; + D3E27A330E741DD20078CC2C /* apple-boss.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36E9FB40E5A944A00496BD3 /* apple-boss.xml */; }; + D3E39C3F0FC5FFD10022DAB9 /* TDDelimitStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E39C3E0FC5FFD10022DAB9 /* TDDelimitStateTest.m */; }; + D3E784BD0E53DA28008C7D61 /* apple-boss.json in Resources */ = {isa = PBXBuildFile; fileRef = D3E784BC0E53DA28008C7D61 /* apple-boss.json */; }; + D3E785560E53FB54008C7D61 /* apple-boss.json in Resources */ = {isa = PBXBuildFile; fileRef = D3E784BC0E53DA28008C7D61 /* apple-boss.json */; }; + D3E787A30E5661A9008C7D61 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; + D3E788930E567DFD008C7D61 /* SRGSParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E788920E567DFD008C7D61 /* SRGSParserTest.m */; }; + D3E788960E567E0A008C7D61 /* SRGSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E788950E567E0A008C7D61 /* SRGSParser.m */; }; + D3E78A190E574C99008C7D61 /* EBNFParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E78A160E574C99008C7D61 /* EBNFParser.m */; }; + D3E78A1A0E574C99008C7D61 /* EBNFParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E78A180E574C99008C7D61 /* EBNFParserTest.m */; }; + D3EAC7EC0F2690620043D6A9 /* OCMock.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D3EADD800E75E9CC00F78584 /* nasty.html in Resources */ = {isa = PBXBuildFile; fileRef = D3EADD7F0E75E9CC00F78584 /* nasty.html */; }; + D3EADD810E75E9CC00F78584 /* nasty.html in Resources */ = {isa = PBXBuildFile; fileRef = D3EADD7F0E75E9CC00F78584 /* nasty.html */; }; + D3EADD8E0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */; }; + D3EADD8F0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */; }; + D3F0E2480FFE8EB900C9DF74 /* PKQuoteState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3F0E2490FFE8EB900C9DF74 /* PKQuoteState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3F0E3CB0FFEB70100C9DF74 /* PKNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F60FFE8C8E004514FE /* PKNumber.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3F0E3CC0FFEB70700C9DF74 /* PKNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF440FF9E19700D7773A /* PKNumber.m */; }; + D3F55F611025737D00DD6DB1 /* TDParseTreeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F55F601025737D00DD6DB1 /* TDParseTreeTest.m */; }; + D3F5629A10266CFC00DD6DB1 /* PKParseTreeView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F5629910266CFC00DD6DB1 /* PKParseTreeView.m */; }; + D3F562A010266DFB00DD6DB1 /* DemoTokensViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F5629F10266DFB00DD6DB1 /* DemoTokensViewController.m */; }; + D3F562A210266E5300DD6DB1 /* TokensView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3F562A110266E5300DD6DB1 /* TokensView.xib */; }; + D3F562A410266E6300DD6DB1 /* TreesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3F562A310266E6300DD6DB1 /* TreesView.xib */; }; + D3F562A710266E8D00DD6DB1 /* DemoTreesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F562A610266E8D00DD6DB1 /* DemoTreesViewController.m */; }; + D3F740B70EF8C38A00559B9F /* JSONAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F740B60EF8C38A00559B9F /* JSONAssembler.m */; }; + D3F741440EF8E96A00559B9F /* xpath1_0.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741430EF8E96A00559B9F /* xpath1_0.grammar */; }; + D3F741BE0EF9F28D00559B9F /* css2_1.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741BD0EF9F28D00559B9F /* css2_1.grammar */; }; + D3F741BF0EF9F29400559B9F /* css2_1.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741BD0EF9F28D00559B9F /* css2_1.grammar */; }; + D3F741C00EF9F29500559B9F /* css2_1.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741BD0EF9F28D00559B9F /* css2_1.grammar */; }; + D3FD79200F4CC86800BAD816 /* rubyhash.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */; }; + D3FD79210F4CC87900BAD816 /* rubyhash.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */; }; + D3FDC4A50FFB3B2A00F1F797 /* RegexKitLite.h in Headers */ = {isa = PBXBuildFile; fileRef = D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */; }; + D3FDC6DA0FFC4C8C00F1F797 /* RegexKitLite.h in Headers */ = {isa = PBXBuildFile; fileRef = D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */; }; + D3FDC6EE0FFC4C9E00F1F797 /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */; }; + D3FDC6EF0FFC4C9E00F1F797 /* PKReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAD9B0FF9C95800D7773A /* PKReader.m */; }; + D3FDC6F00FFC4C9E00F1F797 /* PKAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADA00FF9C9B000D7773A /* PKAssembly.m */; }; + D3FDC6F10FFC4C9E00F1F797 /* PKParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADD60FF9CBFB00D7773A /* PKParser.m */; }; + D3FDC6F20FFC4C9E00F1F797 /* PKRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE130FF9CE0E00D7773A /* PKRepetition.m */; }; + D3FDC6F30FFC4C9E00F1F797 /* PKCollectionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */; }; + D3FDC6F40FFC4C9E00F1F797 /* PKAlternation.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */; }; + D3FDC6F50FFC4C9E00F1F797 /* PKSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE150FF9CE0E00D7773A /* PKSequence.m */; }; + D3FDC6F60FFC4C9E00F1F797 /* PKTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE190FF9CE0E00D7773A /* PKTrack.m */; }; + D3FDC6F70FFC4C9E00F1F797 /* PKTrackException.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */; }; + D3FDC6F80FFC4C9E00F1F797 /* PKDifference.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */; }; + D3FDC6F90FFC4C9E00F1F797 /* PKIntersection.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE110FF9CE0E00D7773A /* PKIntersection.m */; }; + D3FDC6FA0FFC4C9E00F1F797 /* PKTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE170FF9CE0E00D7773A /* PKTerminal.m */; }; + D3FDC6FB0FFC4C9E00F1F797 /* PKEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */; }; + D3FDC6FC0FFC4C9E00F1F797 /* PKTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */; }; + D3FDC6FD0FFC4C9E00F1F797 /* PKToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE950FF9D20900D7773A /* PKToken.m */; }; + D3FDC6FE0FFC4C9E00F1F797 /* PKTokenArraySource.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */; }; + D3FDC6FF0FFC4C9E00F1F797 /* PKTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE990FF9D20900D7773A /* PKTokenizer.m */; }; + D3FDC7000FFC4C9E00F1F797 /* PKTokenizerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */; }; + D3FDC7010FFC4C9E00F1F797 /* PKNumberState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECA0FF9D56400D7773A /* PKNumberState.m */; }; + D3FDC7020FFC4C9E00F1F797 /* PKQuoteState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECC0FF9D56400D7773A /* PKQuoteState.m */; }; + D3FDC7030FFC4C9E00F1F797 /* PKSymbolState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED00FF9D56400D7773A /* PKSymbolState.m */; }; + D3FDC7040FFC4C9E00F1F797 /* PKWordState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED60FF9D56400D7773A /* PKWordState.m */; }; + D3FDC7050FFC4C9E00F1F797 /* PKWhitespaceState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */; }; + D3FDC7060FFC4C9E00F1F797 /* PKDelimitState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC60FF9D56400D7773A /* PKDelimitState.m */; }; + D3FDC7070FFC4C9E00F1F797 /* PKCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC40FF9D56400D7773A /* PKCommentState.m */; }; + D3FDC7080FFC4C9E00F1F797 /* PKSingleLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */; }; + D3FDC7090FFC4C9E00F1F797 /* PKMultiLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */; }; + D3FDC70A0FFC4C9E00F1F797 /* PKSymbolNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */; }; + D3FDC70B0FFC4C9E00F1F797 /* PKSymbolRootNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */; }; + D3FDC70C0FFC4C9E00F1F797 /* PKPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF380FF9E18300D7773A /* PKPattern.m */; }; + D3FDC70D0FFC4C9E00F1F797 /* PKWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED40FF9D56400D7773A /* PKWord.m */; }; + D3FDC70F0FFC4C9E00F1F797 /* PKQuotedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF460FF9E19700D7773A /* PKQuotedString.m */; }; + D3FDC7100FFC4C9E00F1F797 /* PKSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF480FF9E19700D7773A /* PKSymbol.m */; }; + D3FDC7110FFC4C9E00F1F797 /* PKLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF420FF9E19700D7773A /* PKLiteral.m */; }; + D3FDC7120FFC4C9E00F1F797 /* PKCaseInsensitiveLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */; }; + D3FDC7130FFC4C9E00F1F797 /* PKWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */; }; + D3FDC7140FFC4C9E00F1F797 /* PKComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3E0FF9E19700D7773A /* PKComment.m */; }; + D3FDC7150FFC4C9E00F1F797 /* PKDelimitedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF400FF9E19700D7773A /* PKDelimitedString.m */; }; + D3FDC7160FFC4C9E00F1F797 /* PKAny.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE2F0FF9CE6000D7773A /* PKAny.m */; }; + D3FDC7180FFC4C9E00F1F797 /* PKLowercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */; }; + D3FDC7190FFC4C9E00F1F797 /* PKUppercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */; }; + D3FDC71A0FFC4C9E00F1F797 /* PKCharacterAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */; }; + D3FDC71B0FFC4C9E00F1F797 /* PKChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB40FF9E80300D7773A /* PKChar.m */; }; + D3FDC71C0FFC4C9E00F1F797 /* PKDigit.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB60FF9E80300D7773A /* PKDigit.m */; }; + D3FDC71D0FFC4C9E00F1F797 /* PKLetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB80FF9E80300D7773A /* PKLetter.m */; }; + D3FDC71E0FFC4C9E00F1F797 /* PKSpecificChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */; }; + D3FDC71F0FFC4C9E00F1F797 /* PKParserFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD80FF9E95500D7773A /* PKParserFactory.m */; }; + D3FDC7200FFC4C9E00F1F797 /* NSArray+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */; }; + D3FDC7210FFC4C9E00F1F797 /* NSString+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */; }; + D3FDC7370FFC4D6100F1F797 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3FDC7360FFC4D6100F1F797 /* Foundation.framework */; }; + D3FDC7390FFC4D6100F1F797 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D3FDC7380FFC4D6100F1F797 /* libicucore.dylib */; }; + D3FDC74C0FFC4DAC00F1F797 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3FDC74B0FFC4DAC00F1F797 /* CoreGraphics.framework */; }; + D3FDC8DC0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = D3FDC8DB0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + D31FE7170E60F24700A0803E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TDParseKit; + }; + D334949F0E296AA900406085 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TODParseKit; + }; + D341850F0E520D6F0081B0DC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TODParseKit; + }; + D389F1D30F19665C00558235 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TDParseKit; + }; + D389F2090F196A8000558235 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D389F1CD0F1965E600558235; + remoteInfo = TDJSParseKit; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + D380B9A10F0EF3DC0009EC13 /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(BUILT_PRODUCTS_DIR)"; + dstSubfolderSpec = 0; + files = ( + D3EAC7EC0F2690620043D6A9 /* OCMock.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + D3DCB3880EF5E65100DE5110 /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(BUILT_PRODUCTS_DIR)"; + dstSubfolderSpec = 0; + files = ( + D3DCB3730EF5E5D600DE5110 /* OCMock.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 8DC2EF5B0486A6940098B216 /* ParseKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ParseKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D3126D040FFD9BA700CBF4C4 /* PKNegation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKNegation.m; path = src/PKNegation.m; sourceTree = ""; }; + D3126D090FFD9E4B00CBF4C4 /* TDNegationTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNegationTest.h; path = test/TDNegationTest.h; sourceTree = ""; }; + D3126D0A0FFD9E4B00CBF4C4 /* TDNegationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNegationTest.m; path = test/TDNegationTest.m; sourceTree = ""; }; + D3126D410FFDB4C600CBF4C4 /* TDExclusionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDExclusionTest.h; path = test/TDExclusionTest.h; sourceTree = ""; }; + D3126D420FFDB4C600CBF4C4 /* TDExclusionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDExclusionTest.m; path = test/TDExclusionTest.m; sourceTree = ""; }; + D31270F80FFE898300CBF4C4 /* PKExclusion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKExclusion.m; path = test/PKExclusion.m; sourceTree = ""; }; + D315DF710FEF59B600D876C8 /* date.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = date.grammar; path = res/date.grammar; sourceTree = ""; }; + D319E429106D8A1F008C63DD /* arithmetic.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = arithmetic.grammar; path = res/arithmetic.grammar; sourceTree = ""; }; + D319E42C106D8A31008C63DD /* TDArithmeticAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDArithmeticAssembler.h; path = test/TDArithmeticAssembler.h; sourceTree = ""; }; + D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDArithmeticAssembler.m; path = test/TDArithmeticAssembler.m; sourceTree = ""; }; + D31A15250F6DE449002AFDF1 /* javascript.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = javascript.grammar; path = res/javascript.grammar; sourceTree = ""; }; + D31A16500F7038C2002AFDF1 /* TDJavaScriptParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJavaScriptParser.h; path = test/TDJavaScriptParser.h; sourceTree = ""; }; + D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJavaScriptParser.m; path = test/TDJavaScriptParser.m; sourceTree = ""; }; + D31FE54A0E60E46100A0803E /* TDTestScaffold.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTestScaffold.h; path = test/TDTestScaffold.h; sourceTree = ""; }; + D31FE54B0E60E46100A0803E /* TDTestScaffold.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTestScaffold.m; path = test/TDTestScaffold.m; sourceTree = ""; }; + D31FE54D0E60E50800A0803E /* TDAlternationTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDAlternationTest.h; path = test/TDAlternationTest.h; sourceTree = ""; }; + D31FE54E0E60E50800A0803E /* TDAlternationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDAlternationTest.m; path = test/TDAlternationTest.m; sourceTree = ""; }; + D31FE54F0E60E50800A0803E /* TDLiteralTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDLiteralTest.h; path = test/TDLiteralTest.h; sourceTree = ""; }; + D31FE5500E60E50800A0803E /* TDLiteralTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDLiteralTest.m; path = test/TDLiteralTest.m; sourceTree = ""; }; + D31FE5510E60E50800A0803E /* TDParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserTest.h; path = test/TDParserTest.h; sourceTree = ""; }; + D31FE5520E60E50800A0803E /* TDParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserTest.m; path = test/TDParserTest.m; sourceTree = ""; }; + D31FE5530E60E50800A0803E /* TDRepetitionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRepetitionTest.h; path = test/TDRepetitionTest.h; sourceTree = ""; }; + D31FE5540E60E50800A0803E /* TDRepetitionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRepetitionTest.m; path = test/TDRepetitionTest.m; sourceTree = ""; }; + D31FE5550E60E50800A0803E /* TDReservedWordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDReservedWordTest.h; path = test/TDReservedWordTest.h; sourceTree = ""; }; + D31FE5560E60E50800A0803E /* TDReservedWordTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDReservedWordTest.m; path = test/TDReservedWordTest.m; sourceTree = ""; }; + D31FE5570E60E50800A0803E /* TDRobotCommandTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRobotCommandTest.h; path = test/TDRobotCommandTest.h; sourceTree = ""; }; + D31FE5580E60E50800A0803E /* TDRobotCommandTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRobotCommandTest.m; path = test/TDRobotCommandTest.m; sourceTree = ""; }; + D31FE5590E60E50800A0803E /* TDSequenceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSequenceTest.h; path = test/TDSequenceTest.h; sourceTree = ""; }; + D31FE55A0E60E50800A0803E /* TDSequenceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSequenceTest.m; path = test/TDSequenceTest.m; sourceTree = ""; }; + D31FE55B0E60E50800A0803E /* TDSymbolTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSymbolTest.h; path = test/TDSymbolTest.h; sourceTree = ""; }; + D31FE55C0E60E50800A0803E /* TDSymbolTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSymbolTest.m; path = test/TDSymbolTest.m; sourceTree = ""; }; + D31FE55D0E60E50800A0803E /* TDTokenAssemblyTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenAssemblyTest.h; path = test/TDTokenAssemblyTest.h; sourceTree = ""; }; + D31FE55E0E60E50800A0803E /* TDTokenAssemblyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenAssemblyTest.m; path = test/TDTokenAssemblyTest.m; sourceTree = ""; }; + D31FE55F0E60E50800A0803E /* TDTrackTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTrackTest.h; path = test/TDTrackTest.h; sourceTree = ""; }; + D31FE5600E60E50800A0803E /* TDTrackTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTrackTest.m; path = test/TDTrackTest.m; sourceTree = ""; }; + D31FE5610E60E50800A0803E /* TDUppercaseWordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDUppercaseWordTest.h; path = test/TDUppercaseWordTest.h; sourceTree = ""; }; + D31FE5620E60E50800A0803E /* TDUppercaseWordTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDUppercaseWordTest.m; path = test/TDUppercaseWordTest.m; sourceTree = ""; }; + D31FE5710E60E55700A0803E /* TDReaderTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDReaderTest.h; path = test/TDReaderTest.h; sourceTree = ""; }; + D31FE5720E60E55700A0803E /* TDReaderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDReaderTest.m; path = test/TDReaderTest.m; sourceTree = ""; }; + D31FE5730E60E55700A0803E /* TDTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenizerTest.h; path = test/TDTokenizerTest.h; sourceTree = ""; }; + D31FE5740E60E55700A0803E /* TDTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenizerTest.m; path = test/TDTokenizerTest.m; sourceTree = ""; }; + D31FE5770E60E58C00A0803E /* TDNumberStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNumberStateTest.h; path = test/TDNumberStateTest.h; sourceTree = ""; }; + D31FE5780E60E58C00A0803E /* TDNumberStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNumberStateTest.m; path = test/TDNumberStateTest.m; sourceTree = ""; }; + D31FE5790E60E58C00A0803E /* TDQuoteStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDQuoteStateTest.h; path = test/TDQuoteStateTest.h; sourceTree = ""; }; + D31FE57A0E60E58C00A0803E /* TDQuoteStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDQuoteStateTest.m; path = test/TDQuoteStateTest.m; sourceTree = ""; }; + D31FE57B0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSignificantWhitespaceStateTest.h; path = test/TDSignificantWhitespaceStateTest.h; sourceTree = ""; }; + D31FE57C0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSignificantWhitespaceStateTest.m; path = test/TDSignificantWhitespaceStateTest.m; sourceTree = ""; }; + D31FE57D0E60E58C00A0803E /* TDSlashStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashStateTest.h; path = test/TDSlashStateTest.h; sourceTree = ""; }; + D31FE57E0E60E58C00A0803E /* TDSlashStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashStateTest.m; path = test/TDSlashStateTest.m; sourceTree = ""; }; + D31FE57F0E60E58C00A0803E /* TDSymbolStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSymbolStateTest.h; path = test/TDSymbolStateTest.h; sourceTree = ""; }; + D31FE5800E60E58C00A0803E /* TDSymbolStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSymbolStateTest.m; path = test/TDSymbolStateTest.m; sourceTree = ""; }; + D31FE5810E60E58C00A0803E /* TDWhitespaceStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDWhitespaceStateTest.h; path = test/TDWhitespaceStateTest.h; sourceTree = ""; }; + D31FE5820E60E58C00A0803E /* TDWhitespaceStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDWhitespaceStateTest.m; path = test/TDWhitespaceStateTest.m; sourceTree = ""; }; + D31FE5830E60E58C00A0803E /* TDWordStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDWordStateTest.h; path = test/TDWordStateTest.h; sourceTree = ""; }; + D31FE5840E60E58C00A0803E /* TDWordStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDWordStateTest.m; path = test/TDWordStateTest.m; sourceTree = ""; }; + D31FE58C0E60E5AC00A0803E /* TDCharacterAssemblyTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDCharacterAssemblyTest.h; path = test/TDCharacterAssemblyTest.h; sourceTree = ""; }; + D31FE58D0E60E5AC00A0803E /* TDCharacterAssemblyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDCharacterAssemblyTest.m; path = test/TDCharacterAssemblyTest.m; sourceTree = ""; }; + D31FE58E0E60E5AC00A0803E /* TDCharTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDCharTest.h; path = test/TDCharTest.h; sourceTree = ""; }; + D31FE58F0E60E5AC00A0803E /* TDCharTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDCharTest.m; path = test/TDCharTest.m; sourceTree = ""; }; + D31FE5900E60E5AC00A0803E /* TDDigitTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDDigitTest.h; path = test/TDDigitTest.h; sourceTree = ""; }; + D31FE5910E60E5AC00A0803E /* TDDigitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDDigitTest.m; path = test/TDDigitTest.m; sourceTree = ""; }; + D31FE5920E60E5AC00A0803E /* TDLetterTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDLetterTest.h; path = test/TDLetterTest.h; sourceTree = ""; }; + D31FE5930E60E5AC00A0803E /* TDLetterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDLetterTest.m; path = test/TDLetterTest.m; sourceTree = ""; }; + D31FE5940E60E5AC00A0803E /* TDSpecificCharTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSpecificCharTest.h; path = test/TDSpecificCharTest.h; sourceTree = ""; }; + D31FE5950E60E5AC00A0803E /* TDSpecificCharTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSpecificCharTest.m; path = test/TDSpecificCharTest.m; sourceTree = ""; }; + D31FE59B0E60E5C000A0803E /* TDRegularParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRegularParser.h; path = test/TDRegularParser.h; sourceTree = ""; }; + D31FE59C0E60E5C000A0803E /* TDRegularParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRegularParser.m; path = test/TDRegularParser.m; sourceTree = ""; }; + D31FE59D0E60E5C000A0803E /* TDRegularParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRegularParserTest.h; path = test/TDRegularParserTest.h; sourceTree = ""; }; + D31FE59E0E60E5C000A0803E /* TDRegularParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRegularParserTest.m; path = test/TDRegularParserTest.m; sourceTree = ""; }; + D31FE5A10E60E5D500A0803E /* TDFastJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDFastJsonParser.h; path = test/TDFastJsonParser.h; sourceTree = ""; }; + D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDFastJsonParser.m; path = test/TDFastJsonParser.m; sourceTree = ""; }; + D31FE5A30E60E5D500A0803E /* TDFastJsonParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDFastJsonParserTest.h; path = test/TDFastJsonParserTest.h; sourceTree = ""; }; + D31FE5A40E60E5D500A0803E /* TDFastJsonParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDFastJsonParserTest.m; path = test/TDFastJsonParserTest.m; sourceTree = ""; }; + D31FE5AD0E60E64900A0803E /* TDXmlTokenAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTokenAssembly.h; path = test/TDXmlTokenAssembly.h; sourceTree = ""; }; + D31FE5AE0E60E64900A0803E /* TDXmlTokenAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTokenAssembly.m; path = test/TDXmlTokenAssembly.m; sourceTree = ""; }; + D31FE5AF0E60E64900A0803E /* TDXmlTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTokenizerTest.h; path = test/TDXmlTokenizerTest.h; sourceTree = ""; }; + D31FE5B00E60E64900A0803E /* TDXmlTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTokenizerTest.m; path = test/TDXmlTokenizerTest.m; sourceTree = ""; }; + D31FE5B30E60E66600A0803E /* TDXmlToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlToken.h; path = test/TDXmlToken.h; sourceTree = ""; }; + D31FE5B40E60E66600A0803E /* TDXmlToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlToken.m; path = test/TDXmlToken.m; sourceTree = ""; }; + D31FE5B50E60E66600A0803E /* TDXmlTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTokenizer.h; path = test/TDXmlTokenizer.h; sourceTree = ""; }; + D31FE5B60E60E66600A0803E /* TDXmlTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTokenizer.m; path = test/TDXmlTokenizer.m; sourceTree = ""; }; + D31FE5B90E60E69E00A0803E /* TDXmlAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlAttribute.h; path = test/TDXmlAttribute.h; sourceTree = ""; }; + D31FE5BA0E60E69E00A0803E /* TDXmlAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlAttribute.m; path = test/TDXmlAttribute.m; sourceTree = ""; }; + D31FE5BB0E60E69E00A0803E /* TDXmlCdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlCdata.h; path = test/TDXmlCdata.h; sourceTree = ""; }; + D31FE5BC0E60E69E00A0803E /* TDXmlCdata.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlCdata.m; path = test/TDXmlCdata.m; sourceTree = ""; }; + D31FE5BD0E60E69E00A0803E /* TDXmlComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlComment.h; path = test/TDXmlComment.h; sourceTree = ""; }; + D31FE5BE0E60E69E00A0803E /* TDXmlComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlComment.m; path = test/TDXmlComment.m; sourceTree = ""; }; + D31FE5BF0E60E69E00A0803E /* TDXmlDecl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlDecl.h; path = test/TDXmlDecl.h; sourceTree = ""; }; + D31FE5C00E60E69E00A0803E /* TDXmlDecl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlDecl.m; path = test/TDXmlDecl.m; sourceTree = ""; }; + D31FE5C10E60E69E00A0803E /* TDXmlDoctype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlDoctype.h; path = test/TDXmlDoctype.h; sourceTree = ""; }; + D31FE5C20E60E69E00A0803E /* TDXmlDoctype.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlDoctype.m; path = test/TDXmlDoctype.m; sourceTree = ""; }; + D31FE5C30E60E69E00A0803E /* TDXmlDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlDocument.h; path = test/TDXmlDocument.h; sourceTree = ""; }; + D31FE5C40E60E69E00A0803E /* TDXmlDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlDocument.m; path = test/TDXmlDocument.m; sourceTree = ""; }; + D31FE5C50E60E69E00A0803E /* TDXmlEndEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEndEntity.h; path = test/TDXmlEndEntity.h; sourceTree = ""; }; + D31FE5C60E60E69E00A0803E /* TDXmlEndEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEndEntity.m; path = test/TDXmlEndEntity.m; sourceTree = ""; }; + D31FE5C70E60E69E00A0803E /* TDXmlEndTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEndTag.h; path = test/TDXmlEndTag.h; sourceTree = ""; }; + D31FE5C80E60E69E00A0803E /* TDXmlEndTag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEndTag.m; path = test/TDXmlEndTag.m; sourceTree = ""; }; + D31FE5C90E60E69E00A0803E /* TDXmlEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEntity.h; path = test/TDXmlEntity.h; sourceTree = ""; }; + D31FE5CA0E60E69E00A0803E /* TDXmlEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEntity.m; path = test/TDXmlEntity.m; sourceTree = ""; }; + D31FE5CB0E60E69E00A0803E /* TDXmlEntityRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEntityRef.h; path = test/TDXmlEntityRef.h; sourceTree = ""; }; + D31FE5CC0E60E69E00A0803E /* TDXmlEntityRef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEntityRef.m; path = test/TDXmlEntityRef.m; sourceTree = ""; }; + D31FE5CD0E60E69E00A0803E /* TDXmlFragment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlFragment.h; path = test/TDXmlFragment.h; sourceTree = ""; }; + D31FE5CE0E60E69E00A0803E /* TDXmlFragment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlFragment.m; path = test/TDXmlFragment.m; sourceTree = ""; }; + D31FE5CF0E60E69E00A0803E /* TDXmlNotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNotation.h; path = test/TDXmlNotation.h; sourceTree = ""; }; + D31FE5D00E60E69E00A0803E /* TDXmlNotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNotation.m; path = test/TDXmlNotation.m; sourceTree = ""; }; + D31FE5D10E60E69E00A0803E /* TDXmlProcessingInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlProcessingInstruction.h; path = test/TDXmlProcessingInstruction.h; sourceTree = ""; }; + D31FE5D20E60E69E00A0803E /* TDXmlProcessingInstruction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlProcessingInstruction.m; path = test/TDXmlProcessingInstruction.m; sourceTree = ""; }; + D31FE5D30E60E69E00A0803E /* TDXmlSignificantWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlSignificantWhitespace.h; path = test/TDXmlSignificantWhitespace.h; sourceTree = ""; }; + D31FE5D40E60E69E00A0803E /* TDXmlSignificantWhitespace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlSignificantWhitespace.m; path = test/TDXmlSignificantWhitespace.m; sourceTree = ""; }; + D31FE5D50E60E69E00A0803E /* TDXmlStartTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlStartTag.h; path = test/TDXmlStartTag.h; sourceTree = ""; }; + D31FE5D60E60E69E00A0803E /* TDXmlStartTag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlStartTag.m; path = test/TDXmlStartTag.m; sourceTree = ""; }; + D31FE5D70E60E69E00A0803E /* TDXmlTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTerminal.h; path = test/TDXmlTerminal.h; sourceTree = ""; }; + D31FE5D80E60E69E00A0803E /* TDXmlTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTerminal.m; path = test/TDXmlTerminal.m; sourceTree = ""; }; + D31FE5D90E60E69E00A0803E /* TDXmlText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlText.h; path = test/TDXmlText.h; sourceTree = ""; }; + D31FE5DA0E60E69E00A0803E /* TDXmlText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlText.m; path = test/TDXmlText.m; sourceTree = ""; }; + D31FE5DB0E60E69E00A0803E /* TDXmlWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlWhitespace.h; path = test/TDXmlWhitespace.h; sourceTree = ""; }; + D31FE5DC0E60E69E00A0803E /* TDXmlWhitespace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlWhitespace.m; path = test/TDXmlWhitespace.m; sourceTree = ""; }; + D31FE5EF0E60E6B500A0803E /* TDNCName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNCName.h; path = test/TDNCName.h; sourceTree = ""; }; + D31FE5F00E60E6B500A0803E /* TDNCNameState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNCNameState.h; path = test/TDNCNameState.h; sourceTree = ""; }; + D31FE5F10E60E6B500A0803E /* TDNCNameState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNCNameState.m; path = test/TDNCNameState.m; sourceTree = ""; }; + D31FE5F20E60E6B500A0803E /* TDXmlName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlName.h; path = test/TDXmlName.h; sourceTree = ""; }; + D31FE5F30E60E6B500A0803E /* TDXmlName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlName.m; path = test/TDXmlName.m; sourceTree = ""; }; + D31FE5F40E60E6B500A0803E /* TDXmlNameState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNameState.h; path = test/TDXmlNameState.h; sourceTree = ""; }; + D31FE5F50E60E6B500A0803E /* TDXmlNameState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNameState.m; path = test/TDXmlNameState.m; sourceTree = ""; }; + D31FE5F60E60E6B500A0803E /* TDXmlNameTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNameTest.h; path = test/TDXmlNameTest.h; sourceTree = ""; }; + D31FE5F70E60E6B500A0803E /* TDXmlNameTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNameTest.m; path = test/TDXmlNameTest.m; sourceTree = ""; }; + D31FE5F80E60E6B500A0803E /* TDXmlNmtoken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNmtoken.h; path = test/TDXmlNmtoken.h; sourceTree = ""; }; + D31FE5F90E60E6B500A0803E /* TDXmlNmtoken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNmtoken.m; path = test/TDXmlNmtoken.m; sourceTree = ""; }; + D31FE5FA0E60E6B500A0803E /* TDXmlNmtokenState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNmtokenState.h; path = test/TDXmlNmtokenState.h; sourceTree = ""; }; + D31FE5FB0E60E6B500A0803E /* TDXmlNmtokenState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNmtokenState.m; path = test/TDXmlNmtokenState.m; sourceTree = ""; }; + D31FE6DF0E60EE2500A0803E /* TDNCName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNCName.m; path = test/TDNCName.m; sourceTree = ""; }; + D3252F780FCE1A7E005EF059 /* TDNSPredicateBuilderTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateBuilderTest.h; path = test/TDNSPredicateBuilderTest.h; sourceTree = ""; }; + D3252F790FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateBuilderTest.m; path = test/TDNSPredicateBuilderTest.m; sourceTree = ""; }; + D3252F7C0FCE1A87005EF059 /* TDNSPredicateBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateBuilder.h; path = test/TDNSPredicateBuilder.h; sourceTree = ""; }; + D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateBuilder.m; path = test/TDNSPredicateBuilder.m; sourceTree = ""; }; + D3305C4B102F5BAD00DC4F75 /* TDGutterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDGutterView.h; path = demoapp/TDGutterView.h; sourceTree = ""; }; + D3305C4C102F5BAD00DC4F75 /* TDGutterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDGutterView.m; path = demoapp/TDGutterView.m; sourceTree = ""; }; + D3305C4D102F5BAE00DC4F75 /* TDSourceCodeTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSourceCodeTextView.h; path = demoapp/TDSourceCodeTextView.h; sourceTree = ""; }; + D3305C4E102F5BAE00DC4F75 /* TDSourceCodeTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSourceCodeTextView.m; path = demoapp/TDSourceCodeTextView.m; sourceTree = ""; }; + D33494100E2963FD00406085 /* DemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D3376D5710093A1600E4602E /* PKGrammarParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKGrammarParser.h; path = src/PKGrammarParser.h; sourceTree = ""; }; + D3376D5810093A1600E4602E /* PKGrammarParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKGrammarParser.m; path = src/PKGrammarParser.m; sourceTree = ""; }; + D3376D8C10096C0700E4602E /* PKAST.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAST.h; path = test/PKAST.h; sourceTree = ""; }; + D3376D8D10096C0700E4602E /* PKAST.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAST.m; path = test/PKAST.m; sourceTree = ""; }; + D3385FD70FCFB1FF003BF729 /* TDPredicateEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPredicateEvaluator.h; path = test/TDPredicateEvaluator.h; sourceTree = ""; }; + D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPredicateEvaluator.m; path = test/TDPredicateEvaluator.m; sourceTree = ""; }; + D3385FDB0FCFB227003BF729 /* TDPredicateEvaluatorTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPredicateEvaluatorTest.h; path = test/TDPredicateEvaluatorTest.h; sourceTree = ""; }; + D3385FDC0FCFB227003BF729 /* TDPredicateEvaluatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPredicateEvaluatorTest.m; path = test/TDPredicateEvaluatorTest.m; sourceTree = ""; }; + D338E5B90FF5DDCB003DE6AA /* TDDifferenceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDDifferenceTest.h; path = test/TDDifferenceTest.h; sourceTree = ""; }; + D338E5BA0FF5DDCB003DE6AA /* TDDifferenceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDDifferenceTest.m; path = test/TDDifferenceTest.m; sourceTree = ""; }; + D34185040E520D3F0081B0DC /* DebugApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DebugApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D34BAC210FF87F8600D7773A /* TDParserFactoryTest3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryTest3.h; path = test/TDParserFactoryTest3.h; sourceTree = ""; }; + D34BAC220FF87F8600D7773A /* TDParserFactoryTest3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryTest3.m; path = test/TDParserFactoryTest3.m; sourceTree = ""; }; + D34BAC490FF892C200D7773A /* XPathParserGrammarTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathParserGrammarTest.h; path = test/XPathParserGrammarTest.h; sourceTree = ""; }; + D34BAC4A0FF892C200D7773A /* XPathParserGrammarTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathParserGrammarTest.m; path = test/XPathParserGrammarTest.m; sourceTree = ""; }; + D34BAD16100A9B7900996341 /* TDTokenizerStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenizerStateTest.h; path = test/TDTokenizerStateTest.h; sourceTree = ""; }; + D34BAD17100A9B7900996341 /* TDTokenizerStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenizerStateTest.m; path = test/TDTokenizerStateTest.m; sourceTree = ""; }; + D34BAD630FF9C6AE00D7773A /* ParseKit_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseKit_Prefix.pch; sourceTree = ""; }; + D34BAD9B0FF9C95800D7773A /* PKReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKReader.m; path = src/PKReader.m; sourceTree = ""; }; + D34BADA00FF9C9B000D7773A /* PKAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAssembly.m; path = src/PKAssembly.m; sourceTree = ""; }; + D34BADD60FF9CBFB00D7773A /* PKParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParser.m; path = src/PKParser.m; sourceTree = ""; }; + D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCollectionParser.m; path = src/PKCollectionParser.m; sourceTree = ""; }; + D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAlternation.m; path = src/PKAlternation.m; sourceTree = ""; }; + D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKEmpty.m; path = src/PKEmpty.m; sourceTree = ""; }; + D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDifference.m; path = src/PKDifference.m; sourceTree = ""; }; + D34BAE110FF9CE0E00D7773A /* PKIntersection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKIntersection.m; path = src/PKIntersection.m; sourceTree = ""; }; + D34BAE130FF9CE0E00D7773A /* PKRepetition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKRepetition.m; path = src/PKRepetition.m; sourceTree = ""; }; + D34BAE150FF9CE0E00D7773A /* PKSequence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSequence.m; path = src/PKSequence.m; sourceTree = ""; }; + D34BAE170FF9CE0E00D7773A /* PKTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTerminal.m; path = src/PKTerminal.m; sourceTree = ""; }; + D34BAE190FF9CE0E00D7773A /* PKTrack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTrack.m; path = src/PKTrack.m; sourceTree = ""; }; + D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTrackException.m; path = src/PKTrackException.m; sourceTree = ""; }; + D34BAE2F0FF9CE6000D7773A /* PKAny.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAny.m; path = src/PKAny.m; sourceTree = ""; }; + D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenAssembly.m; path = src/PKTokenAssembly.m; sourceTree = ""; }; + D34BAE950FF9D20900D7773A /* PKToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKToken.m; path = src/PKToken.m; sourceTree = ""; }; + D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenArraySource.m; path = src/PKTokenArraySource.m; sourceTree = ""; }; + D34BAE990FF9D20900D7773A /* PKTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenizer.m; path = src/PKTokenizer.m; sourceTree = ""; }; + D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenizerState.m; path = src/PKTokenizerState.m; sourceTree = ""; }; + D34BAEC40FF9D56400D7773A /* PKCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCommentState.m; path = src/PKCommentState.m; sourceTree = ""; }; + D34BAEC60FF9D56400D7773A /* PKDelimitState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDelimitState.m; path = src/PKDelimitState.m; sourceTree = ""; }; + D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKMultiLineCommentState.m; path = src/PKMultiLineCommentState.m; sourceTree = ""; }; + D34BAECA0FF9D56400D7773A /* PKNumberState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKNumberState.m; path = src/PKNumberState.m; sourceTree = ""; }; + D34BAECC0FF9D56400D7773A /* PKQuoteState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKQuoteState.m; path = src/PKQuoteState.m; sourceTree = ""; }; + D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSingleLineCommentState.m; path = src/PKSingleLineCommentState.m; sourceTree = ""; }; + D34BAED00FF9D56400D7773A /* PKSymbolState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbolState.m; path = src/PKSymbolState.m; sourceTree = ""; }; + D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWhitespaceState.m; path = src/PKWhitespaceState.m; sourceTree = ""; }; + D34BAED40FF9D56400D7773A /* PKWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWord.m; path = src/PKWord.m; sourceTree = ""; }; + D34BAED60FF9D56400D7773A /* PKWordState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWordState.m; path = src/PKWordState.m; sourceTree = ""; }; + D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbolNode.m; path = src/PKSymbolNode.m; sourceTree = ""; }; + D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbolRootNode.m; path = src/PKSymbolRootNode.m; sourceTree = ""; }; + D34BAF380FF9E18300D7773A /* PKPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKPattern.m; path = src/PKPattern.m; sourceTree = ""; }; + D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCaseInsensitiveLiteral.m; path = src/PKCaseInsensitiveLiteral.m; sourceTree = ""; }; + D34BAF3E0FF9E19700D7773A /* PKComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKComment.m; path = src/PKComment.m; sourceTree = ""; }; + D34BAF400FF9E19700D7773A /* PKDelimitedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDelimitedString.m; path = src/PKDelimitedString.m; sourceTree = ""; }; + D34BAF420FF9E19700D7773A /* PKLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKLiteral.m; path = src/PKLiteral.m; sourceTree = ""; }; + D34BAF440FF9E19700D7773A /* PKNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKNumber.m; path = src/PKNumber.m; sourceTree = ""; }; + D34BAF460FF9E19700D7773A /* PKQuotedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKQuotedString.m; path = src/PKQuotedString.m; sourceTree = ""; }; + D34BAF480FF9E19700D7773A /* PKSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbol.m; path = src/PKSymbol.m; sourceTree = ""; }; + D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWhitespace.m; path = src/PKWhitespace.m; sourceTree = ""; }; + D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKLowercaseWord.m; path = src/PKLowercaseWord.m; sourceTree = ""; }; + D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKUppercaseWord.m; path = src/PKUppercaseWord.m; sourceTree = ""; }; + D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCharacterAssembly.m; path = src/PKCharacterAssembly.m; sourceTree = ""; }; + D34BAFB40FF9E80300D7773A /* PKChar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKChar.m; path = src/PKChar.m; sourceTree = ""; }; + D34BAFB60FF9E80300D7773A /* PKDigit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDigit.m; path = src/PKDigit.m; sourceTree = ""; }; + D34BAFB80FF9E80300D7773A /* PKLetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKLetter.m; path = src/PKLetter.m; sourceTree = ""; }; + D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSpecificChar.m; path = src/PKSpecificChar.m; sourceTree = ""; }; + D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+ParseKitAdditions.h"; path = "src/NSArray+ParseKitAdditions.h"; sourceTree = ""; }; + D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+ParseKitAdditions.m"; path = "src/NSArray+ParseKitAdditions.m"; sourceTree = ""; }; + D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+ParseKitAdditions.h"; path = "src/NSString+ParseKitAdditions.h"; sourceTree = ""; }; + D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+ParseKitAdditions.m"; path = "src/NSString+ParseKitAdditions.m"; sourceTree = ""; }; + D34BAFD80FF9E95500D7773A /* PKParserFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParserFactory.m; path = src/PKParserFactory.m; sourceTree = ""; }; + D34BB04E0FF9EC4E00D7773A /* JSParseKit-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "JSParseKit-Info.plist"; sourceTree = ""; }; + D34BB0660FF9EDDF00D7773A /* JSParseKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSParseKit.h; path = jssrc/JSParseKit.h; sourceTree = ""; }; + D34BB0670FF9EDDF00D7773A /* JSParseKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSParseKit.m; path = jssrc/JSParseKit.m; sourceTree = ""; }; + D34BB06A0FF9EE4000D7773A /* PKJSAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAssembly.h; path = jssrc/PKJSAssembly.h; sourceTree = ""; }; + D34BB06B0FF9EE4000D7773A /* PKJSAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAssembly.m; path = jssrc/PKJSAssembly.m; sourceTree = ""; }; + D34BB06C0FF9EE4000D7773A /* PKJSUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSUtils.h; path = jssrc/PKJSUtils.h; sourceTree = ""; }; + D34BB06D0FF9EE4000D7773A /* PKJSUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSUtils.m; path = jssrc/PKJSUtils.m; sourceTree = ""; }; + D34BB06E0FF9EE4000D7773A /* PKJSUtils_macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSUtils_macros.h; path = jssrc/PKJSUtils_macros.h; sourceTree = ""; }; + D34BB06F0FF9EE4000D7773A /* PKJSValueHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSValueHolder.h; path = jssrc/PKJSValueHolder.h; sourceTree = ""; }; + D34BB0700FF9EE4000D7773A /* PKJSValueHolder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSValueHolder.m; path = jssrc/PKJSValueHolder.m; sourceTree = ""; }; + D34BB08D0FF9EF9D00D7773A /* PKJSCharacterAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCharacterAssembly.h; path = jssrc/PKJSCharacterAssembly.h; sourceTree = ""; }; + D34BB08E0FF9EF9D00D7773A /* PKJSCharacterAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCharacterAssembly.m; path = jssrc/PKJSCharacterAssembly.m; sourceTree = ""; }; + D34BB0930FF9F14B00D7773A /* PKJSCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCommentState.h; path = jssrc/PKJSCommentState.h; sourceTree = ""; }; + D34BB0940FF9F14B00D7773A /* PKJSCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCommentState.m; path = jssrc/PKJSCommentState.m; sourceTree = ""; }; + D34BB0950FF9F14B00D7773A /* PKJSDelimitState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSDelimitState.h; path = jssrc/PKJSDelimitState.h; sourceTree = ""; }; + D34BB0960FF9F14B00D7773A /* PKJSDelimitState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSDelimitState.m; path = jssrc/PKJSDelimitState.m; sourceTree = ""; }; + D34BB0970FF9F14B00D7773A /* PKJSNumberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSNumberState.h; path = jssrc/PKJSNumberState.h; sourceTree = ""; }; + D34BB0980FF9F14B00D7773A /* PKJSNumberState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSNumberState.m; path = jssrc/PKJSNumberState.m; sourceTree = ""; }; + D34BB0990FF9F14B00D7773A /* PKJSQuoteState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSQuoteState.h; path = jssrc/PKJSQuoteState.h; sourceTree = ""; }; + D34BB09A0FF9F14B00D7773A /* PKJSQuoteState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSQuoteState.m; path = jssrc/PKJSQuoteState.m; sourceTree = ""; }; + D34BB09B0FF9F14B00D7773A /* PKJSSymbolState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSSymbolState.h; path = jssrc/PKJSSymbolState.h; sourceTree = ""; }; + D34BB09C0FF9F14B00D7773A /* PKJSSymbolState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSSymbolState.m; path = jssrc/PKJSSymbolState.m; sourceTree = ""; }; + D34BB09D0FF9F14B00D7773A /* PKJSToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSToken.h; path = jssrc/PKJSToken.h; sourceTree = ""; }; + D34BB09E0FF9F14B00D7773A /* PKJSToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSToken.m; path = jssrc/PKJSToken.m; sourceTree = ""; }; + D34BB09F0FF9F14B00D7773A /* PKJSTokenAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTokenAssembly.h; path = jssrc/PKJSTokenAssembly.h; sourceTree = ""; }; + D34BB0A00FF9F14B00D7773A /* PKJSTokenAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTokenAssembly.m; path = jssrc/PKJSTokenAssembly.m; sourceTree = ""; }; + D34BB0A10FF9F14B00D7773A /* PKJSTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTokenizer.h; path = jssrc/PKJSTokenizer.h; sourceTree = ""; }; + D34BB0A20FF9F14B00D7773A /* PKJSTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTokenizer.m; path = jssrc/PKJSTokenizer.m; sourceTree = ""; }; + D34BB0A30FF9F14B00D7773A /* PKJSTokenizerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTokenizerState.h; path = jssrc/PKJSTokenizerState.h; sourceTree = ""; }; + D34BB0A40FF9F14B00D7773A /* PKJSTokenizerState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTokenizerState.m; path = jssrc/PKJSTokenizerState.m; sourceTree = ""; }; + D34BB0A50FF9F14B00D7773A /* PKJSWhitespaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSWhitespaceState.h; path = jssrc/PKJSWhitespaceState.h; sourceTree = ""; }; + D34BB0A60FF9F14B00D7773A /* PKJSWhitespaceState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSWhitespaceState.m; path = jssrc/PKJSWhitespaceState.m; sourceTree = ""; }; + D34BB0A70FF9F14B00D7773A /* PKJSWordState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSWordState.h; path = jssrc/PKJSWordState.h; sourceTree = ""; }; + D34BB0A80FF9F14B00D7773A /* PKJSWordState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSWordState.m; path = jssrc/PKJSWordState.m; sourceTree = ""; }; + D34BB0D20FF9F28000D7773A /* PKJSAlternation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAlternation.h; path = jssrc/PKJSAlternation.h; sourceTree = ""; }; + D34BB0D30FF9F28000D7773A /* PKJSAlternation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAlternation.m; path = jssrc/PKJSAlternation.m; sourceTree = ""; }; + D34BB0D40FF9F28000D7773A /* PKJSAny.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAny.h; path = jssrc/PKJSAny.h; sourceTree = ""; }; + D34BB0D50FF9F28000D7773A /* PKJSAny.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAny.m; path = jssrc/PKJSAny.m; sourceTree = ""; }; + D34BB0D60FF9F28000D7773A /* PKJSAssemblerAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAssemblerAdapter.h; path = jssrc/PKJSAssemblerAdapter.h; sourceTree = ""; }; + D34BB0D70FF9F28000D7773A /* PKJSAssemblerAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAssemblerAdapter.m; path = jssrc/PKJSAssemblerAdapter.m; sourceTree = ""; }; + D34BB0D80FF9F28000D7773A /* PKJSCollectionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCollectionParser.h; path = jssrc/PKJSCollectionParser.h; sourceTree = ""; }; + D34BB0D90FF9F28000D7773A /* PKJSCollectionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCollectionParser.m; path = jssrc/PKJSCollectionParser.m; sourceTree = ""; }; + D34BB0DA0FF9F28000D7773A /* PKJSEmpty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSEmpty.h; path = jssrc/PKJSEmpty.h; sourceTree = ""; }; + D34BB0DB0FF9F28000D7773A /* PKJSEmpty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSEmpty.m; path = jssrc/PKJSEmpty.m; sourceTree = ""; }; + D34BB0DC0FF9F28000D7773A /* PKJSParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSParser.h; path = jssrc/PKJSParser.h; sourceTree = ""; }; + D34BB0DD0FF9F28000D7773A /* PKJSParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSParser.m; path = jssrc/PKJSParser.m; sourceTree = ""; }; + D34BB0DE0FF9F28000D7773A /* PKJSRepetition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSRepetition.h; path = jssrc/PKJSRepetition.h; sourceTree = ""; }; + D34BB0DF0FF9F28000D7773A /* PKJSRepetition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSRepetition.m; path = jssrc/PKJSRepetition.m; sourceTree = ""; }; + D34BB0E00FF9F28000D7773A /* PKJSSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSSequence.h; path = jssrc/PKJSSequence.h; sourceTree = ""; }; + D34BB0E10FF9F28000D7773A /* PKJSSequence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSSequence.m; path = jssrc/PKJSSequence.m; sourceTree = ""; }; + D34BB0E20FF9F28000D7773A /* PKJSTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTerminal.h; path = jssrc/PKJSTerminal.h; sourceTree = ""; }; + D34BB0E30FF9F28000D7773A /* PKJSTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTerminal.m; path = jssrc/PKJSTerminal.m; sourceTree = ""; }; + D34BB0E40FF9F28000D7773A /* PKJSTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTrack.h; path = jssrc/PKJSTrack.h; sourceTree = ""; }; + D34BB0E50FF9F28000D7773A /* PKJSTrack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTrack.m; path = jssrc/PKJSTrack.m; sourceTree = ""; }; + D34BB0FE0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCaseInsensitiveLiteral.h; path = jssrc/PKJSCaseInsensitiveLiteral.h; sourceTree = ""; }; + D34BB0FF0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCaseInsensitiveLiteral.m; path = jssrc/PKJSCaseInsensitiveLiteral.m; sourceTree = ""; }; + D34BB1000FF9F36200D7773A /* PKJSComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSComment.h; path = jssrc/PKJSComment.h; sourceTree = ""; }; + D34BB1010FF9F36200D7773A /* PKJSComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSComment.m; path = jssrc/PKJSComment.m; sourceTree = ""; }; + D34BB1020FF9F36200D7773A /* PKJSDelimitedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSDelimitedString.h; path = jssrc/PKJSDelimitedString.h; sourceTree = ""; }; + D34BB1030FF9F36200D7773A /* PKJSDelimitedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSDelimitedString.m; path = jssrc/PKJSDelimitedString.m; sourceTree = ""; }; + D34BB1040FF9F36200D7773A /* PKJSLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSLiteral.h; path = jssrc/PKJSLiteral.h; sourceTree = ""; }; + D34BB1050FF9F36200D7773A /* PKJSLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSLiteral.m; path = jssrc/PKJSLiteral.m; sourceTree = ""; }; + D34BB1060FF9F36200D7773A /* PKJSLowercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSLowercaseWord.h; path = jssrc/PKJSLowercaseWord.h; sourceTree = ""; }; + D34BB1070FF9F36200D7773A /* PKJSLowercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSLowercaseWord.m; path = jssrc/PKJSLowercaseWord.m; sourceTree = ""; }; + D34BB1080FF9F36200D7773A /* PKJSNum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSNum.h; path = jssrc/PKJSNum.h; sourceTree = ""; }; + D34BB1090FF9F36200D7773A /* PKJSNum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSNum.m; path = jssrc/PKJSNum.m; sourceTree = ""; }; + D34BB10A0FF9F36200D7773A /* PKJSPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSPattern.h; path = jssrc/PKJSPattern.h; sourceTree = ""; }; + D34BB10B0FF9F36200D7773A /* PKJSPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSPattern.m; path = jssrc/PKJSPattern.m; sourceTree = ""; }; + D34BB10C0FF9F36200D7773A /* PKJSQuotedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSQuotedString.h; path = jssrc/PKJSQuotedString.h; sourceTree = ""; }; + D34BB10D0FF9F36200D7773A /* PKJSQuotedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSQuotedString.m; path = jssrc/PKJSQuotedString.m; sourceTree = ""; }; + D34BB10E0FF9F36200D7773A /* PKJSSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSSymbol.h; path = jssrc/PKJSSymbol.h; sourceTree = ""; }; + D34BB10F0FF9F36200D7773A /* PKJSSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSSymbol.m; path = jssrc/PKJSSymbol.m; sourceTree = ""; }; + D34BB1100FF9F36200D7773A /* PKJSUppercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSUppercaseWord.h; path = jssrc/PKJSUppercaseWord.h; sourceTree = ""; }; + D34BB1110FF9F36200D7773A /* PKJSUppercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSUppercaseWord.m; path = jssrc/PKJSUppercaseWord.m; sourceTree = ""; }; + D34BB1120FF9F36200D7773A /* PKJSWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSWord.h; path = jssrc/PKJSWord.h; sourceTree = ""; }; + D34BB1130FF9F36200D7773A /* PKJSWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSWord.m; path = jssrc/PKJSWord.m; sourceTree = ""; }; + D3521F520E5FA1B0009681F9 /* XMLReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMLReader.h; path = test/XMLReader.h; sourceTree = ""; }; + D3521F530E5FA1B0009681F9 /* XMLReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMLReader.m; path = test/XMLReader.m; sourceTree = ""; }; + D3521F540E5FA1B0009681F9 /* XMLReaderTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMLReaderTest.h; path = test/XMLReaderTest.h; sourceTree = ""; }; + D3521F550E5FA1B0009681F9 /* XMLReaderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMLReaderTest.m; path = test/XMLReaderTest.m; sourceTree = ""; }; + D35384EC0FE9691100926552 /* nspredicate.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = nspredicate.grammar; path = res/nspredicate.grammar; sourceTree = ""; }; + D353899B0FEAC94400926552 /* c.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = c.grammar; path = res/c.grammar; sourceTree = ""; }; + D353899D0FEAC96B00926552 /* objc.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = objc.grammar; path = res/objc.grammar; sourceTree = ""; }; + D355C62B0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateEvaluator.h; path = test/TDNSPredicateEvaluator.h; sourceTree = ""; }; + D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateEvaluator.m; path = test/TDNSPredicateEvaluator.m; sourceTree = ""; }; + D355C62F0FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateEvaluatorTest.h; path = test/TDNSPredicateEvaluatorTest.h; sourceTree = ""; }; + D355C6300FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateEvaluatorTest.m; path = test/TDNSPredicateEvaluatorTest.m; sourceTree = ""; }; + D355C8800FEB36A1006A91A4 /* xml.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = xml.grammar; path = res/xml.grammar; sourceTree = ""; }; + D355C8830FEB4B94006A91A4 /* proto.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = proto.grammar; path = res/proto.grammar; sourceTree = ""; }; + D36568A50EEF9FE900226554 /* TDPlistParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPlistParser.h; path = test/TDPlistParser.h; sourceTree = ""; }; + D36568A60EEF9FE900226554 /* TDPlistParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPlistParser.m; path = test/TDPlistParser.m; sourceTree = ""; }; + D36568A80EEFA05300226554 /* TDPlistParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPlistParserTest.h; path = test/TDPlistParserTest.h; sourceTree = ""; }; + D36568A90EEFA05300226554 /* TDPlistParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPlistParserTest.m; path = test/TDPlistParserTest.m; sourceTree = ""; }; + D3656DFC0EF2620E00226554 /* TDTokenArraySourceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenArraySourceTest.h; path = test/TDTokenArraySourceTest.h; sourceTree = ""; }; + D3656DFD0EF2620E00226554 /* TDTokenArraySourceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenArraySourceTest.m; path = test/TDTokenArraySourceTest.m; sourceTree = ""; }; + D3668291101D2BFA0008632C /* erb.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = erb.grammar; path = res/erb.grammar; sourceTree = ""; }; + D3668294101D2C200008632C /* ERBTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ERBTest.h; path = test/ERBTest.h; sourceTree = ""; }; + D3668295101D2C200008632C /* ERBTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ERBTest.m; path = test/ERBTest.m; sourceTree = ""; }; + D36934551038DE5300527AF3 /* PKParseTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParseTree.h; path = test/PKParseTree.h; sourceTree = ""; }; + D36934561038DE5300527AF3 /* PKParseTree.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParseTree.m; path = test/PKParseTree.m; sourceTree = ""; }; + D36934571038DE5300527AF3 /* PKParseTreeAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParseTreeAssembler.h; path = test/PKParseTreeAssembler.h; sourceTree = ""; }; + D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParseTreeAssembler.m; path = test/PKParseTreeAssembler.m; sourceTree = ""; }; + D36934591038DE5300527AF3 /* PKRuleNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKRuleNode.h; path = test/PKRuleNode.h; sourceTree = ""; }; + D369345A1038DE5300527AF3 /* PKRuleNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKRuleNode.m; path = test/PKRuleNode.m; sourceTree = ""; }; + D369345B1038DE5300527AF3 /* PKTokenNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenNode.h; path = test/PKTokenNode.h; sourceTree = ""; }; + D369345C1038DE5300527AF3 /* PKTokenNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenNode.m; path = test/PKTokenNode.m; sourceTree = ""; }; + D36C53770FD27F1300141CB7 /* TDParserFactoryTest2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryTest2.h; path = test/TDParserFactoryTest2.h; sourceTree = ""; }; + D36C53780FD27F1300141CB7 /* TDParserFactoryTest2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryTest2.m; path = test/TDParserFactoryTest2.m; sourceTree = ""; }; + D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegexKitLite.h; path = src/RegexKitLite.h; sourceTree = ""; }; + D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RegexKitLite.m; path = src/RegexKitLite.m; sourceTree = ""; }; + D36C560B0FD363D500141CB7 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = /usr/lib/libicucore.dylib; sourceTree = ""; }; + D36C56290FD365DB00141CB7 /* TDPatternTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPatternTest.h; path = test/TDPatternTest.h; sourceTree = ""; }; + D36C562A0FD365DB00141CB7 /* TDPatternTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPatternTest.m; path = test/TDPatternTest.m; sourceTree = ""; }; + D36E95440E578ECC00496BD3 /* XPathParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathParser.h; path = test/XPathParser.h; sourceTree = ""; }; + D36E95450E578ECC00496BD3 /* XPathParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathParser.m; path = test/XPathParser.m; sourceTree = ""; }; + D36E95D60E57B08400496BD3 /* XPathParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathParserTest.h; path = test/XPathParserTest.h; sourceTree = ""; }; + D36E95D70E57B08400496BD3 /* XPathParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathParserTest.m; path = test/XPathParserTest.m; sourceTree = ""; }; + D36E97AE0E589DAE00496BD3 /* XPathAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathAssembler.h; path = test/XPathAssembler.h; sourceTree = ""; }; + D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathAssembler.m; path = test/XPathAssembler.m; sourceTree = ""; }; + D36E98200E58A3A800496BD3 /* XPathContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathContext.h; path = test/XPathContext.h; sourceTree = ""; }; + D36E98210E58A3A800496BD3 /* XPathContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathContext.m; path = test/XPathContext.m; sourceTree = ""; }; + D36E98DC0E58C12800496BD3 /* DebugAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugAppDelegate.h; sourceTree = ""; }; + D36E98DD0E58C12800496BD3 /* DebugAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugAppDelegate.m; sourceTree = ""; }; + D36E98DE0E58C12800496BD3 /* DebugAppMainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DebugAppMainMenu.xib; sourceTree = ""; }; + D36E98DF0E58C12800496BD3 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + D36E98E30E58C14000496BD3 /* DemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DemoAppDelegate.h; path = demoapp/DemoAppDelegate.h; sourceTree = ""; }; + D36E98E40E58C14000496BD3 /* DemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DemoAppDelegate.m; path = demoapp/DemoAppDelegate.m; sourceTree = ""; }; + D36E98E50E58C14000496BD3 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = demoapp/main.m; sourceTree = ""; }; + D36E98F70E58C1A000496BD3 /* DemoAppMainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DemoAppMainMenu.xib; path = demoapp/DemoAppMainMenu.xib; sourceTree = ""; }; + D36E9F860E5A795400496BD3 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = /usr/lib/libxml2.dylib; sourceTree = ""; }; + D36E9FB40E5A944A00496BD3 /* apple-boss.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "apple-boss.xml"; path = "res/apple-boss.xml"; sourceTree = ""; }; + D36E9FE40E5BA0FC00496BD3 /* SRGSGrammar.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = SRGSGrammar.txt; path = res/SRGSGrammar.txt; sourceTree = ""; }; + D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "small-xml-file.xml"; path = "res/small-xml-file.xml"; sourceTree = ""; }; + D380AFBB0F0C54B60009EC13 /* html.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = html.css; path = res/html.css; sourceTree = ""; }; + D380AFBC0F0C54B60009EC13 /* html.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = html.grammar; path = res/html.grammar; sourceTree = ""; }; + D380AFC20F0C56000009EC13 /* example.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = example.html; path = res/example.html; sourceTree = ""; }; + D380B5080F0D71A90009EC13 /* css.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = css.grammar; path = res/css.grammar; sourceTree = ""; }; + D380B5370F0D7DDE0009EC13 /* css.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = css.css; path = res/css.css; sourceTree = ""; }; + D380B5930F0D82F60009EC13 /* example.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = example.css; path = res/example.css; sourceTree = ""; }; + D380BA5F0F0F06CD0009EC13 /* TDParserFactoryTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryTest.h; path = test/TDParserFactoryTest.h; sourceTree = ""; }; + D380BA600F0F06CD0009EC13 /* TDParserFactoryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryTest.m; path = test/TDParserFactoryTest.m; sourceTree = ""; }; + D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = /System/Library/Frameworks/JavaScriptCore.framework; sourceTree = ""; }; + D38205BC0EEE48EE004340DD /* TDTokenTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenTest.h; path = test/TDTokenTest.h; sourceTree = ""; }; + D38205BD0EEE48EE004340DD /* TDTokenTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenTest.m; path = test/TDTokenTest.m; sourceTree = ""; }; + D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json_with_comments.grammar; path = res/json_with_comments.grammar; sourceTree = ""; }; + D38349BB0F0C0D910055E4E0 /* json_with_comments.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = json_with_comments.css; path = res/json_with_comments.css; sourceTree = ""; }; + D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = yahoo_with_comments.json; path = res/yahoo_with_comments.json; sourceTree = ""; }; + D385F9880F046FE900DB2946 /* TDGenericAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDGenericAssembler.h; path = test/TDGenericAssembler.h; sourceTree = ""; }; + D385F9890F046FE900DB2946 /* TDGenericAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDGenericAssembler.m; path = test/TDGenericAssembler.m; sourceTree = ""; }; + D385FA210F04971400DB2946 /* TDGenericAssemblerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDGenericAssemblerTest.h; path = test/TDGenericAssemblerTest.h; sourceTree = ""; }; + D385FA220F04971400DB2946 /* TDGenericAssemblerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDGenericAssemblerTest.m; path = test/TDGenericAssemblerTest.m; sourceTree = ""; }; + D385FA240F04993500DB2946 /* json.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = json.css; path = res/json.css; sourceTree = ""; }; + D385FD400F05A88C00DB2946 /* TDMiniCSSAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDMiniCSSAssembler.h; path = test/TDMiniCSSAssembler.h; sourceTree = ""; }; + D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDMiniCSSAssembler.m; path = test/TDMiniCSSAssembler.m; sourceTree = ""; }; + D385FD420F05A88C00DB2946 /* TDMiniCSSAssemblerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDMiniCSSAssemblerTest.h; path = test/TDMiniCSSAssemblerTest.h; sourceTree = ""; }; + D385FD430F05A88C00DB2946 /* TDMiniCSSAssemblerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDMiniCSSAssemblerTest.m; path = test/TDMiniCSSAssemblerTest.m; sourceTree = ""; }; + D385FD6B0F05A99900DB2946 /* mini_css.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mini_css.grammar; path = res/mini_css.grammar; sourceTree = ""; }; + D389A0B00F1FCC99003B43BD /* RelaxParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RelaxParser.h; path = test/RelaxParser.h; sourceTree = ""; }; + D389A0B10F1FCC99003B43BD /* RelaxParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RelaxParser.m; path = test/RelaxParser.m; sourceTree = ""; }; + D389F1CE0F1965E600558235 /* JSParseKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSParseKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D389F2030F196A7500558235 /* JSDemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSDemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D389F20D0F196A9200558235 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + D389F2E30F196CAE00558235 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = jsdemoapp/main.m; sourceTree = ""; }; + D389F2E80F196F5B00558235 /* JSDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSDemoAppDelegate.h; path = jsdemoapp/JSDemoAppDelegate.h; sourceTree = ""; }; + D389F2E90F196F5B00558235 /* JSDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSDemoAppDelegate.m; path = jsdemoapp/JSDemoAppDelegate.m; sourceTree = ""; }; + D389F38E0F19800400558235 /* DefaultValues.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = DefaultValues.plist; path = jsdemoapp/DefaultValues.plist; sourceTree = ""; }; + D389F4610F198A8800558235 /* Test.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = Test.html; path = jsdemoapp/Test.html; sourceTree = ""; }; + D389F5580F19B7BC00558235 /* JSDemoAppMainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = JSDemoAppMainMenu.xib; path = jsdemoapp/JSDemoAppMainMenu.xib; sourceTree = ""; }; + D389F5B20F19C76A00558235 /* TDJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJsonParser.h; path = test/TDJsonParser.h; sourceTree = ""; }; + D389F5B30F19C76A00558235 /* TDJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJsonParser.m; path = test/TDJsonParser.m; sourceTree = ""; }; + D389F5B40F19C76A00558235 /* TDJsonParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJsonParserTest.h; path = test/TDJsonParserTest.h; sourceTree = ""; }; + D389F5B50F19C76A00558235 /* TDJsonParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJsonParserTest.m; path = test/TDJsonParserTest.m; sourceTree = ""; }; + D389FBCC0F1B25E200558235 /* ParserTest.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = ParserTest.html; path = jsdemoapp/ParserTest.html; sourceTree = ""; }; + D38DD9E70EC29F260070BC4D /* nyt.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = nyt.html; path = res/nyt.html; sourceTree = ""; }; + D38E97CA1061CF6500739C39 /* TDTokenizerBlocksTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenizerBlocksTest.h; path = test/TDTokenizerBlocksTest.h; sourceTree = ""; }; + D38E97CB1061CF6500739C39 /* TDTokenizerBlocksTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenizerBlocksTest.m; path = test/TDTokenizerBlocksTest.m; sourceTree = ""; }; + D38E98D61062C5BA00739C39 /* TDParserBlocksTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserBlocksTest.h; path = test/TDParserBlocksTest.h; sourceTree = ""; }; + D38E98D71062C5BA00739C39 /* TDParserBlocksTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserBlocksTest.m; path = test/TDParserBlocksTest.m; sourceTree = ""; }; + D3AF49760FDB122E0032F4DC /* TDParserFactoryPatternTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryPatternTest.h; path = test/TDParserFactoryPatternTest.h; sourceTree = ""; }; + D3AF49770FDB122E0032F4DC /* TDParserFactoryPatternTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryPatternTest.m; path = test/TDParserFactoryPatternTest.m; sourceTree = ""; }; + D3AF4BE80FDC3DD50032F4DC /* TDBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDBlob.h; path = test/TDBlob.h; sourceTree = ""; }; + D3AF4BE90FDC3DD50032F4DC /* TDBlob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDBlob.m; path = test/TDBlob.m; sourceTree = ""; }; + D3AF4BF50FDC40050032F4DC /* TDToken+Blob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TDToken+Blob.h"; path = "test/TDToken+Blob.h"; sourceTree = ""; }; + D3AF4BF60FDC40050032F4DC /* TDToken+Blob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "TDToken+Blob.m"; path = "test/TDToken+Blob.m"; sourceTree = ""; }; + D3AF4BFB0FDC41190032F4DC /* TDTokenizer+BlobState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TDTokenizer+BlobState.h"; path = "test/TDTokenizer+BlobState.h"; sourceTree = ""; }; + D3AF4BFC0FDC41190032F4DC /* TDTokenizer+BlobState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "TDTokenizer+BlobState.m"; path = "test/TDTokenizer+BlobState.m"; sourceTree = ""; }; + D3AF4C190FDC568F0032F4DC /* TDBlobState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDBlobState.h; path = test/TDBlobState.h; sourceTree = ""; }; + D3AF4C1A0FDC568F0032F4DC /* TDBlobState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDBlobState.m; path = test/TDBlobState.m; sourceTree = ""; }; + D3AF4CBF0FDC740A0032F4DC /* TDNonReservedWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNonReservedWord.h; path = test/TDNonReservedWord.h; sourceTree = ""; }; + D3AF4CC00FDC740A0032F4DC /* TDNonReservedWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNonReservedWord.m; path = test/TDNonReservedWord.m; sourceTree = ""; }; + D3AF4CC10FDC740A0032F4DC /* TDReservedWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDReservedWord.h; path = test/TDReservedWord.h; sourceTree = ""; }; + D3AF4CC20FDC740A0032F4DC /* TDReservedWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDReservedWord.m; path = test/TDReservedWord.m; sourceTree = ""; }; + D3AF4CC30FDC740A0032F4DC /* TDSignificantWhitespaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSignificantWhitespaceState.h; path = test/TDSignificantWhitespaceState.h; sourceTree = ""; }; + D3AF4CC40FDC740A0032F4DC /* TDSignificantWhitespaceState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSignificantWhitespaceState.m; path = test/TDSignificantWhitespaceState.m; sourceTree = ""; }; + D3AF4CC50FDC740A0032F4DC /* TDWordOrReservedState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDWordOrReservedState.h; path = test/TDWordOrReservedState.h; sourceTree = ""; }; + D3AF4CC60FDC740A0032F4DC /* TDWordOrReservedState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDWordOrReservedState.m; path = test/TDWordOrReservedState.m; sourceTree = ""; }; + D3B43FB50F76E99C0072AF40 /* TDJavaScriptParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJavaScriptParserTest.h; path = test/TDJavaScriptParserTest.h; sourceTree = ""; }; + D3B43FB60F76E99C0072AF40 /* TDJavaScriptParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJavaScriptParserTest.m; path = test/TDJavaScriptParserTest.m; sourceTree = ""; }; + D3B473840E48C9CF008AFBDD /* yahoo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = yahoo.json; path = res/yahoo.json; sourceTree = ""; }; + D3B69D310E80249900D70C41 /* nonascii.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = nonascii.html; path = res/nonascii.html; sourceTree = ""; }; + D3BBBC960FEC9722007DF30D /* TDXMLParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXMLParserTest.h; path = test/TDXMLParserTest.h; sourceTree = ""; }; + D3BBBC970FEC9722007DF30D /* TDXMLParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXMLParserTest.m; path = test/TDXMLParserTest.m; sourceTree = ""; }; + D3BBBC9B0FEC9756007DF30D /* TDXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXMLParser.h; path = test/TDXMLParser.h; sourceTree = ""; }; + D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXMLParser.m; path = test/TDXMLParser.m; sourceTree = ""; }; + D3C031EB0EF38D2D00C5ABEB /* TDLowercaseWordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDLowercaseWordTest.h; path = test/TDLowercaseWordTest.h; sourceTree = ""; }; + D3C031EC0EF38D2D00C5ABEB /* TDLowercaseWordTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDLowercaseWordTest.m; path = test/TDLowercaseWordTest.m; sourceTree = ""; }; + D3C2216D0FFE8A86004514FE /* PKExclusion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKExclusion.h; path = test/PKExclusion.h; sourceTree = ""; }; + D3C221900FFE8B8C004514FE /* ParseKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ParseKit.h; path = include/ParseKit/ParseKit.h; sourceTree = ""; }; + D3C221910FFE8B8C004514FE /* PKTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTypes.h; path = include/ParseKit/PKTypes.h; sourceTree = ""; }; + D3C221960FFE8B95004514FE /* PKReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKReader.h; path = include/ParseKit/PKReader.h; sourceTree = ""; }; + D3C221990FFE8B9D004514FE /* PKAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAssembly.h; path = include/ParseKit/PKAssembly.h; sourceTree = ""; }; + D3C2219C0FFE8BA6004514FE /* PKParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParser.h; path = include/ParseKit/PKParser.h; sourceTree = ""; }; + D3C2219F0FFE8BAE004514FE /* PKRepetition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKRepetition.h; path = include/ParseKit/PKRepetition.h; sourceTree = ""; }; + D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCollectionParser.h; path = include/ParseKit/PKCollectionParser.h; sourceTree = ""; }; + D3C221A50FFE8BC1004514FE /* PKAlternation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAlternation.h; path = include/ParseKit/PKAlternation.h; sourceTree = ""; }; + D3C221A80FFE8BC9004514FE /* PKSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSequence.h; path = include/ParseKit/PKSequence.h; sourceTree = ""; }; + D3C221AB0FFE8BCF004514FE /* PKTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTrack.h; path = include/ParseKit/PKTrack.h; sourceTree = ""; }; + D3C221AE0FFE8BD4004514FE /* PKTrackException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTrackException.h; path = include/ParseKit/PKTrackException.h; sourceTree = ""; }; + D3C221B10FFE8BDB004514FE /* PKIntersection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKIntersection.h; path = include/ParseKit/PKIntersection.h; sourceTree = ""; }; + D3C221B40FFE8BE2004514FE /* PKDifference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDifference.h; path = include/ParseKit/PKDifference.h; sourceTree = ""; }; + D3C221B70FFE8BE8004514FE /* PKNegation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKNegation.h; path = include/ParseKit/PKNegation.h; sourceTree = ""; }; + D3C221BA0FFE8BEF004514FE /* PKTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTerminal.h; path = include/ParseKit/PKTerminal.h; sourceTree = ""; }; + D3C221BD0FFE8BF7004514FE /* PKEmpty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKEmpty.h; path = include/ParseKit/PKEmpty.h; sourceTree = ""; }; + D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenAssembly.h; path = include/ParseKit/PKTokenAssembly.h; sourceTree = ""; }; + D3C221C30FFE8C07004514FE /* PKToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKToken.h; path = include/ParseKit/PKToken.h; sourceTree = ""; }; + D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenArraySource.h; path = include/ParseKit/PKTokenArraySource.h; sourceTree = ""; }; + D3C221C90FFE8C15004514FE /* PKTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenizer.h; path = include/ParseKit/PKTokenizer.h; sourceTree = ""; }; + D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenizerState.h; path = include/ParseKit/PKTokenizerState.h; sourceTree = ""; }; + D3C221CF0FFE8C24004514FE /* PKNumberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKNumberState.h; path = include/ParseKit/PKNumberState.h; sourceTree = ""; }; + D3C221D50FFE8C35004514FE /* PKSymbolState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbolState.h; path = include/ParseKit/PKSymbolState.h; sourceTree = ""; }; + D3C221D80FFE8C3D004514FE /* PKWordState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWordState.h; path = include/ParseKit/PKWordState.h; sourceTree = ""; }; + D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWhitespaceState.h; path = include/ParseKit/PKWhitespaceState.h; sourceTree = ""; }; + D3C221DE0FFE8C49004514FE /* PKDelimitState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDelimitState.h; path = include/ParseKit/PKDelimitState.h; sourceTree = ""; }; + D3C221E10FFE8C4E004514FE /* PKCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCommentState.h; path = include/ParseKit/PKCommentState.h; sourceTree = ""; }; + D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSingleLineCommentState.h; path = include/ParseKit/PKSingleLineCommentState.h; sourceTree = ""; }; + D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKMultiLineCommentState.h; path = include/ParseKit/PKMultiLineCommentState.h; sourceTree = ""; }; + D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbolNode.h; path = include/ParseKit/PKSymbolNode.h; sourceTree = ""; }; + D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbolRootNode.h; path = include/ParseKit/PKSymbolRootNode.h; sourceTree = ""; }; + D3C221F00FFE8C7A004514FE /* PKPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKPattern.h; path = include/ParseKit/PKPattern.h; sourceTree = ""; }; + D3C221F30FFE8C87004514FE /* PKWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWord.h; path = include/ParseKit/PKWord.h; sourceTree = ""; }; + D3C221F60FFE8C8E004514FE /* PKNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKNumber.h; path = include/ParseKit/PKNumber.h; sourceTree = ""; }; + D3C221F90FFE8C97004514FE /* PKQuotedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKQuotedString.h; path = include/ParseKit/PKQuotedString.h; sourceTree = ""; }; + D3C221FC0FFE8CB2004514FE /* PKSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbol.h; path = include/ParseKit/PKSymbol.h; sourceTree = ""; }; + D3C221FF0FFE8CB9004514FE /* PKLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKLiteral.h; path = include/ParseKit/PKLiteral.h; sourceTree = ""; }; + D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCaseInsensitiveLiteral.h; path = include/ParseKit/PKCaseInsensitiveLiteral.h; sourceTree = ""; }; + D3C222050FFE8CCA004514FE /* PKWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWhitespace.h; path = include/ParseKit/PKWhitespace.h; sourceTree = ""; }; + D3C222080FFE8CD1004514FE /* PKComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKComment.h; path = include/ParseKit/PKComment.h; sourceTree = ""; }; + D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDelimitedString.h; path = include/ParseKit/PKDelimitedString.h; sourceTree = ""; }; + D3C2220E0FFE8CDF004514FE /* PKAny.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAny.h; path = include/ParseKit/PKAny.h; sourceTree = ""; }; + D3C222140FFE8D01004514FE /* PKLowercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKLowercaseWord.h; path = include/ParseKit/PKLowercaseWord.h; sourceTree = ""; }; + D3C222170FFE8D11004514FE /* PKUppercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKUppercaseWord.h; path = include/ParseKit/PKUppercaseWord.h; sourceTree = ""; }; + D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCharacterAssembly.h; path = include/ParseKit/PKCharacterAssembly.h; sourceTree = ""; }; + D3C2221D0FFE8D3B004514FE /* PKChar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKChar.h; path = include/ParseKit/PKChar.h; sourceTree = ""; }; + D3C222200FFE8D42004514FE /* PKDigit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDigit.h; path = include/ParseKit/PKDigit.h; sourceTree = ""; }; + D3C222230FFE8D49004514FE /* PKLetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKLetter.h; path = include/ParseKit/PKLetter.h; sourceTree = ""; }; + D3C222260FFE8D6B004514FE /* PKSpecificChar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSpecificChar.h; path = include/ParseKit/PKSpecificChar.h; sourceTree = ""; }; + D3C222290FFE8DAC004514FE /* PKParserFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParserFactory.h; path = include/ParseKit/PKParserFactory.h; sourceTree = ""; }; + D3C7D87A0A411FBF005DD154 /* Tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; + D3C85C790E63B438000445FD /* TDArithmeticParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDArithmeticParser.h; path = test/TDArithmeticParser.h; sourceTree = ""; }; + D3C85C7A0E63B438000445FD /* TDArithmeticParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDArithmeticParser.m; path = test/TDArithmeticParser.m; sourceTree = ""; }; + D3C85C7E0E63B9E9000445FD /* TDArithmeticParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDArithmeticParserTest.h; path = test/TDArithmeticParserTest.h; sourceTree = ""; }; + D3C85C7F0E63B9E9000445FD /* TDArithmeticParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDArithmeticParserTest.m; path = test/TDArithmeticParserTest.m; sourceTree = ""; }; + D3C85D430E63D1BF000445FD /* TDScientificNumberStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDScientificNumberStateTest.h; path = test/TDScientificNumberStateTest.h; sourceTree = ""; }; + D3C85D440E63D1BF000445FD /* TDScientificNumberStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDScientificNumberStateTest.m; path = test/TDScientificNumberStateTest.m; sourceTree = ""; }; + D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json_with_discards.grammar; path = res/json_with_discards.grammar; sourceTree = ""; }; + D3D1BF2610394420003656E5 /* SAXAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SAXAssembler.h; path = test/SAXAssembler.h; sourceTree = ""; }; + D3D1BF2710394420003656E5 /* SAXAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SAXAssembler.m; path = test/SAXAssembler.m; sourceTree = ""; }; + D3D1BF291039445C003656E5 /* SAXTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SAXTest.h; path = test/SAXTest.h; sourceTree = ""; }; + D3D1BF2A1039445C003656E5 /* SAXTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SAXTest.m; path = test/SAXTest.m; sourceTree = ""; }; + D3DCB35C0EF5E52500DE5110 /* OCMock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OCMock.framework; path = frameworks/OCMock.framework; sourceTree = ""; }; + D3DCB4C20EF6015300DE5110 /* json.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json.grammar; path = res/json.grammar; sourceTree = ""; }; + D3DDDA850F0779FD00A58000 /* TDSyntaxHighlighter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSyntaxHighlighter.h; path = test/TDSyntaxHighlighter.h; sourceTree = ""; }; + D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSyntaxHighlighter.m; path = test/TDSyntaxHighlighter.m; sourceTree = ""; }; + D3DDDAFC0F083C9700A58000 /* TDCommentStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDCommentStateTest.h; path = test/TDCommentStateTest.h; sourceTree = ""; }; + D3DDDAFD0F083C9700A58000 /* TDCommentStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDCommentStateTest.m; path = test/TDCommentStateTest.m; sourceTree = ""; }; + D3DDDC230F085C5400A58000 /* TDSlashSlashState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashSlashState.h; path = test/TDSlashSlashState.h; sourceTree = ""; }; + D3DDDC240F085C5400A58000 /* TDSlashSlashState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashSlashState.m; path = test/TDSlashSlashState.m; sourceTree = ""; }; + D3DDDC250F085C5400A58000 /* TDSlashStarState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashStarState.h; path = test/TDSlashStarState.h; sourceTree = ""; }; + D3DDDC260F085C5400A58000 /* TDSlashStarState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashStarState.m; path = test/TDSlashStarState.m; sourceTree = ""; }; + D3DDDC270F085C5400A58000 /* TDSlashState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashState.h; path = test/TDSlashState.h; sourceTree = ""; }; + D3DDDC280F085C5400A58000 /* TDSlashState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashState.m; path = test/TDSlashState.m; sourceTree = ""; }; + D3DDDCAC0F0880D800A58000 /* example1.srgs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = example1.srgs; path = res/example1.srgs; sourceTree = ""; }; + D3E39C3D0FC5FFD10022DAB9 /* TDDelimitStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDDelimitStateTest.h; path = test/TDDelimitStateTest.h; sourceTree = ""; }; + D3E39C3E0FC5FFD10022DAB9 /* TDDelimitStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDDelimitStateTest.m; path = test/TDDelimitStateTest.m; sourceTree = ""; }; + D3E784BC0E53DA28008C7D61 /* apple-boss.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "apple-boss.json"; path = "res/apple-boss.json"; sourceTree = ""; }; + D3E788910E567DFD008C7D61 /* SRGSParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SRGSParserTest.h; path = test/SRGSParserTest.h; sourceTree = ""; }; + D3E788920E567DFD008C7D61 /* SRGSParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SRGSParserTest.m; path = test/SRGSParserTest.m; sourceTree = ""; }; + D3E788940E567E0A008C7D61 /* SRGSParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SRGSParser.h; path = test/SRGSParser.h; sourceTree = ""; }; + D3E788950E567E0A008C7D61 /* SRGSParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SRGSParser.m; path = test/SRGSParser.m; sourceTree = ""; }; + D3E78A150E574C99008C7D61 /* EBNFParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EBNFParser.h; path = test/EBNFParser.h; sourceTree = ""; }; + D3E78A160E574C99008C7D61 /* EBNFParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EBNFParser.m; path = test/EBNFParser.m; sourceTree = ""; }; + D3E78A170E574C99008C7D61 /* EBNFParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EBNFParserTest.h; path = test/EBNFParserTest.h; sourceTree = ""; }; + D3E78A180E574C99008C7D61 /* EBNFParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EBNFParserTest.m; path = test/EBNFParserTest.m; sourceTree = ""; }; + D3EADD7F0E75E9CC00F78584 /* nasty.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = nasty.html; path = res/nasty.html; sourceTree = ""; }; + D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDHtmlSyntaxHighlighter.m; path = test/TDHtmlSyntaxHighlighter.m; sourceTree = ""; }; + D3EADD8D0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDHtmlSyntaxHighlighter.h; path = test/TDHtmlSyntaxHighlighter.h; sourceTree = ""; }; + D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKQuoteState.h; path = include/ParseKit/PKQuoteState.h; sourceTree = ""; }; + D3F0E3290FFEA1E200C9DF74 /* DebugApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "DebugApp-Info.plist"; sourceTree = ""; }; + D3F0E3600FFEA2B500C9DF74 /* DemoApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "DemoApp-Info.plist"; path = "demoapp/DemoApp-Info.plist"; sourceTree = ""; }; + D3F0E36C0FFEA33700C9DF74 /* Tests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Tests-Info.plist"; path = "test/Tests-Info.plist"; sourceTree = ""; }; + D3F0E37A0FFEA39000C9DF74 /* JSDemoApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "JSDemoApp-Info.plist"; path = "jsdemoapp/JSDemoApp-Info.plist"; sourceTree = ""; }; + D3F55F5F1025737D00DD6DB1 /* TDParseTreeTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParseTreeTest.h; path = test/TDParseTreeTest.h; sourceTree = ""; }; + D3F55F601025737D00DD6DB1 /* TDParseTreeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParseTreeTest.m; path = test/TDParseTreeTest.m; sourceTree = ""; }; + D3F5629810266CFC00DD6DB1 /* PKParseTreeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParseTreeView.h; path = demoapp/PKParseTreeView.h; sourceTree = ""; }; + D3F5629910266CFC00DD6DB1 /* PKParseTreeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParseTreeView.m; path = demoapp/PKParseTreeView.m; sourceTree = ""; }; + D3F5629E10266DFB00DD6DB1 /* DemoTokensViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DemoTokensViewController.h; path = demoapp/DemoTokensViewController.h; sourceTree = ""; }; + D3F5629F10266DFB00DD6DB1 /* DemoTokensViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DemoTokensViewController.m; path = demoapp/DemoTokensViewController.m; sourceTree = ""; }; + D3F562A110266E5300DD6DB1 /* TokensView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = TokensView.xib; path = demoapp/TokensView.xib; sourceTree = ""; }; + D3F562A310266E6300DD6DB1 /* TreesView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = TreesView.xib; path = demoapp/TreesView.xib; sourceTree = ""; }; + D3F562A510266E8D00DD6DB1 /* DemoTreesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DemoTreesViewController.h; path = demoapp/DemoTreesViewController.h; sourceTree = ""; }; + D3F562A610266E8D00DD6DB1 /* DemoTreesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DemoTreesViewController.m; path = demoapp/DemoTreesViewController.m; sourceTree = ""; }; + D3F740B50EF8C38A00559B9F /* JSONAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONAssembler.h; sourceTree = ""; }; + D3F740B60EF8C38A00559B9F /* JSONAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONAssembler.m; sourceTree = ""; }; + D3F741430EF8E96A00559B9F /* xpath1_0.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = xpath1_0.grammar; path = res/xpath1_0.grammar; sourceTree = ""; }; + D3F741BD0EF9F28D00559B9F /* css2_1.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = css2_1.grammar; path = res/css2_1.grammar; sourceTree = ""; }; + D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = rubyhash.grammar; path = res/rubyhash.grammar; sourceTree = ""; }; + D3FDC5830FFC4BFC00F1F797 /* libparsekit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libparsekit.a; sourceTree = BUILT_PRODUCTS_DIR; }; + D3FDC7360FFC4D6100F1F797 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + D3FDC7380FFC4D6100F1F797 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; }; + D3FDC74B0FFC4DAC00F1F797 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + D3FDC8DB0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseKitMobile_Prefix.pch; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DC2EF560486A6940098B216 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3E787A30E5661A9008C7D61 /* Foundation.framework in Frameworks */, + D36C560C0FD363D500141CB7 /* libicucore.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D334940E0E2963FD00406085 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D33494720E29670B00406085 /* ParseKit.framework in Frameworks */, + D37D3A000FE77A71008C2E4D /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D34185020E520D3F0081B0DC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D31FE7380E60F36600A0803E /* libxml2.dylib in Frameworks */, + D341850C0E520D640081B0DC /* ParseKit.framework in Frameworks */, + D380B9800F0EF3860009EC13 /* OCMock.framework in Frameworks */, + D380BAA30F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */, + D37D3A010FE77A72008C2E4D /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1CC0F1965E600558235 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F34E0F197DF500558235 /* JavaScriptCore.framework in Frameworks */, + D389F1D50F19666500558235 /* ParseKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F2010F196A7500558235 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F3430F197DDC00558235 /* JavaScriptCore.framework in Frameworks */, + D389F20E0F196A9200558235 /* WebKit.framework in Frameworks */, + D389F20C0F196A9200558235 /* ParseKit.framework in Frameworks */, + D389F20B0F196A9200558235 /* JSParseKit.framework in Frameworks */, + D37D3A020FE77A77008C2E4D /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3C7D8770A411FBF005DD154 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3DCB37D0EF5E5E400DE5110 /* OCMock.framework in Frameworks */, + D3C7D9DA0A412874005DD154 /* ParseKit.framework in Frameworks */, + D36E9F870E5A795400496BD3 /* libxml2.dylib in Frameworks */, + D380BAA40F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */, + D3587EAF0FE83EC900DDD023 /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3FDC5810FFC4BFC00F1F797 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3FDC7370FFC4D6100F1F797 /* Foundation.framework in Frameworks */, + D3FDC7390FFC4D6100F1F797 /* libicucore.dylib in Frameworks */, + D3FDC74C0FFC4DAC00F1F797 /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 034768DFFF38A50411DB9C8B /* Products */ = { + isa = PBXGroup; + children = ( + 8DC2EF5B0486A6940098B216 /* ParseKit.framework */, + D389F1CE0F1965E600558235 /* JSParseKit.framework */, + D3C7D87A0A411FBF005DD154 /* Tests.octest */, + D33494100E2963FD00406085 /* DemoApp.app */, + D34185040E520D3F0081B0DC /* DebugApp.app */, + D389F2030F196A7500558235 /* JSDemoApp.app */, + D3FDC5830FFC4BFC00F1F797 /* libparsekit.a */, + ); + name = Products; + sourceTree = ""; + }; + 0867D691FE84028FC02AAC07 /* TODParseKit */ = { + isa = PBXGroup; + children = ( + 08FB77AEFE84172EC02AAC07 /* ParseKit Framework */, + D3C7D8220A411F31005DD154 /* ParseKit Tests */, + D36E98CB0E58C08F00496BD3 /* DebugApp */, + D334941B0E29641300406085 /* DemoApp */, + D380BA950F0F1C450009EC13 /* JSParseKit Framework */, + D389F2CA0F196ACF00558235 /* JSDemoApp */, + D3AF4C8E0FDC738B0032F4DC /* Other Sources */, + 32C88DFF0371C24200C91783 /* Other Sources (not used) */, + 089C1665FE841158C02AAC07 /* Resources */, + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */, + 034768DFFF38A50411DB9C8B /* Products */, + ); + name = TODParseKit; + sourceTree = ""; + }; + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + D3FDC8EF0FFC52CD00F1F797 /* Mobile Frameworks */, + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */, + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 089C1665FE841158C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + 8DC2EF5A0486A6940098B216 /* Info.plist */, + 089C1666FE841158C02AAC07 /* InfoPlist.strings */, + ); + name = Resources; + sourceTree = ""; + }; + 08FB77AEFE84172EC02AAC07 /* ParseKit Framework */ = { + isa = PBXGroup; + children = ( + D3C221900FFE8B8C004514FE /* ParseKit.h */, + D3C221910FFE8B8C004514FE /* PKTypes.h */, + D3C7D8710A411F6B005DD154 /* io */, + D3C7D8720A411F81005DD154 /* parse */, + D3C7D8740A411F8E005DD154 /* tokens */, + D3E785F10E550F63008C7D61 /* chars */, + D34BAC0F0FF87ED200D7773A /* grammar */, + ); + name = "ParseKit Framework"; + sourceTree = ""; + }; + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + D389F20D0F196A9200558235 /* WebKit.framework */, + D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */, + D3DCB35C0EF5E52500DE5110 /* OCMock.framework */, + D36E9F860E5A795400496BD3 /* libxml2.dylib */, + D36C560B0FD363D500141CB7 /* libicucore.dylib */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 0867D6A5FE840307C02AAC07 /* AppKit.framework */, + 0867D69BFE84028FC02AAC07 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 32C88DFF0371C24200C91783 /* Other Sources (not used) */ = { + isa = PBXGroup; + children = ( + D3C2216D0FFE8A86004514FE /* PKExclusion.h */, + D31270F80FFE898300CBF4C4 /* PKExclusion.m */, + D3AF4CCB0FDC74540032F4DC /* Whitespace */, + D3AF4CCA0FDC74490032F4DC /* Slash */, + D3AF4CC90FDC743C0032F4DC /* ReservedWord */, + D3AF4CC80FDC74320032F4DC /* Blob */, + ); + name = "Other Sources (not used)"; + sourceTree = ""; + }; + D318EAE30E2FD5B6009F47DF /* json */ = { + isa = PBXGroup; + children = ( + D3E784BC0E53DA28008C7D61 /* apple-boss.json */, + D3B473840E48C9CF008AFBDD /* yahoo.json */, + D389F5B20F19C76A00558235 /* TDJsonParser.h */, + D389F5B30F19C76A00558235 /* TDJsonParser.m */, + D389F5B40F19C76A00558235 /* TDJsonParserTest.h */, + D389F5B50F19C76A00558235 /* TDJsonParserTest.m */, + D31FE5A10E60E5D500A0803E /* TDFastJsonParser.h */, + D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */, + D31FE5A30E60E5D500A0803E /* TDFastJsonParserTest.h */, + D31FE5A40E60E5D500A0803E /* TDFastJsonParserTest.m */, + ); + name = json; + sourceTree = ""; + }; + D31A164F0F703899002AFDF1 /* javascript */ = { + isa = PBXGroup; + children = ( + D31A16500F7038C2002AFDF1 /* TDJavaScriptParser.h */, + D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */, + D3B43FB50F76E99C0072AF40 /* TDJavaScriptParserTest.h */, + D3B43FB60F76E99C0072AF40 /* TDJavaScriptParserTest.m */, + ); + name = javascript; + sourceTree = ""; + }; + D3252F670FCE171D005EF059 /* predicate */ = { + isa = PBXGroup; + children = ( + D355C62B0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.h */, + D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */, + D355C62F0FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.h */, + D355C6300FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m */, + D35384EC0FE9691100926552 /* nspredicate.grammar */, + D3252F7C0FCE1A87005EF059 /* TDNSPredicateBuilder.h */, + D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */, + D3252F780FCE1A7E005EF059 /* TDNSPredicateBuilderTest.h */, + D3252F790FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m */, + D3385FD70FCFB1FF003BF729 /* TDPredicateEvaluator.h */, + D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */, + D3385FDB0FCFB227003BF729 /* TDPredicateEvaluatorTest.h */, + D3385FDC0FCFB227003BF729 /* TDPredicateEvaluatorTest.m */, + ); + name = predicate; + sourceTree = ""; + }; + D3305C52102F5BB300DC4F75 /* Trees */ = { + isa = PBXGroup; + children = ( + D3F562A310266E6300DD6DB1 /* TreesView.xib */, + D3F562A510266E8D00DD6DB1 /* DemoTreesViewController.h */, + D3F562A610266E8D00DD6DB1 /* DemoTreesViewController.m */, + D3F5629810266CFC00DD6DB1 /* PKParseTreeView.h */, + D3F5629910266CFC00DD6DB1 /* PKParseTreeView.m */, + D3305C53102F5BC500DC4F75 /* SourceCodeView */, + ); + name = Trees; + sourceTree = ""; + }; + D3305C53102F5BC500DC4F75 /* SourceCodeView */ = { + isa = PBXGroup; + children = ( + D3305C4B102F5BAD00DC4F75 /* TDGutterView.h */, + D3305C4C102F5BAD00DC4F75 /* TDGutterView.m */, + D3305C4D102F5BAE00DC4F75 /* TDSourceCodeTextView.h */, + D3305C4E102F5BAE00DC4F75 /* TDSourceCodeTextView.m */, + ); + name = SourceCodeView; + sourceTree = ""; + }; + D3305C54102F5BE500DC4F75 /* Tokens */ = { + isa = PBXGroup; + children = ( + D3F562A110266E5300DD6DB1 /* TokensView.xib */, + D3F5629E10266DFB00DD6DB1 /* DemoTokensViewController.h */, + D3F5629F10266DFB00DD6DB1 /* DemoTokensViewController.m */, + ); + name = Tokens; + sourceTree = ""; + }; + D334941B0E29641300406085 /* DemoApp */ = { + isa = PBXGroup; + children = ( + D3F0E3600FFEA2B500C9DF74 /* DemoApp-Info.plist */, + D36E98F70E58C1A000496BD3 /* DemoAppMainMenu.xib */, + D36E98E50E58C14000496BD3 /* main.m */, + D36E98E30E58C14000496BD3 /* DemoAppDelegate.h */, + D36E98E40E58C14000496BD3 /* DemoAppDelegate.m */, + D3305C54102F5BE500DC4F75 /* Tokens */, + D3305C52102F5BB300DC4F75 /* Trees */, + ); + name = DemoApp; + sourceTree = ""; + }; + D3376D1110091C6C00E4602E /* ParseTree */ = { + isa = PBXGroup; + children = ( + D3F55F5F1025737D00DD6DB1 /* TDParseTreeTest.h */, + D3F55F601025737D00DD6DB1 /* TDParseTreeTest.m */, + ); + name = ParseTree; + sourceTree = ""; + }; + D3376D7710096BDE00E4602E /* IR */ = { + isa = PBXGroup; + children = ( + D3F5619C1026374400DD6DB1 /* ir */, + D3376D1110091C6C00E4602E /* ParseTree */, + D3376D8B10096BEF00E4602E /* Homo */, + ); + name = IR; + sourceTree = ""; + }; + D3376D8B10096BEF00E4602E /* Homo */ = { + isa = PBXGroup; + children = ( + D3376D8C10096C0700E4602E /* PKAST.h */, + D3376D8D10096C0700E4602E /* PKAST.m */, + ); + name = Homo; + sourceTree = ""; + }; + D341846A0E5209A60081B0DC /* tokenizer */ = { + isa = PBXGroup; + children = ( + D3C221C30FFE8C07004514FE /* PKToken.h */, + D34BAE950FF9D20900D7773A /* PKToken.m */, + D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */, + D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */, + D3C221C90FFE8C15004514FE /* PKTokenizer.h */, + D34BAE990FF9D20900D7773A /* PKTokenizer.m */, + D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */, + D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */, + ); + name = tokenizer; + sourceTree = ""; + }; + D34A20080E55FD5F00A4A0BF /* chars */ = { + isa = PBXGroup; + children = ( + D31FE58C0E60E5AC00A0803E /* TDCharacterAssemblyTest.h */, + D31FE58D0E60E5AC00A0803E /* TDCharacterAssemblyTest.m */, + D31FE58E0E60E5AC00A0803E /* TDCharTest.h */, + D31FE58F0E60E5AC00A0803E /* TDCharTest.m */, + D31FE5900E60E5AC00A0803E /* TDDigitTest.h */, + D31FE5910E60E5AC00A0803E /* TDDigitTest.m */, + D31FE5920E60E5AC00A0803E /* TDLetterTest.h */, + D31FE5930E60E5AC00A0803E /* TDLetterTest.m */, + D31FE5940E60E5AC00A0803E /* TDSpecificCharTest.h */, + D31FE5950E60E5AC00A0803E /* TDSpecificCharTest.m */, + ); + name = chars; + sourceTree = ""; + }; + D34BAC0F0FF87ED200D7773A /* grammar */ = { + isa = PBXGroup; + children = ( + D3C222290FFE8DAC004514FE /* PKParserFactory.h */, + D34BAFD80FF9E95500D7773A /* PKParserFactory.m */, + D3376D5710093A1600E4602E /* PKGrammarParser.h */, + D3376D5810093A1600E4602E /* PKGrammarParser.m */, + D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */, + D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */, + D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */, + D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */, + ); + name = grammar; + sourceTree = ""; + }; + D3541F870DFB105900429B4F /* states */ = { + isa = PBXGroup; + children = ( + D3C221CF0FFE8C24004514FE /* PKNumberState.h */, + D34BAECA0FF9D56400D7773A /* PKNumberState.m */, + D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */, + D34BAECC0FF9D56400D7773A /* PKQuoteState.m */, + D3C221D50FFE8C35004514FE /* PKSymbolState.h */, + D34BAED00FF9D56400D7773A /* PKSymbolState.m */, + D3C221D80FFE8C3D004514FE /* PKWordState.h */, + D34BAED60FF9D56400D7773A /* PKWordState.m */, + D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */, + D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */, + D3C221DE0FFE8C49004514FE /* PKDelimitState.h */, + D34BAEC60FF9D56400D7773A /* PKDelimitState.m */, + D3C221E10FFE8C4E004514FE /* PKCommentState.h */, + D34BAEC40FF9D56400D7773A /* PKCommentState.m */, + D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */, + D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */, + D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */, + D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */, + D3541F890DFB108300429B4F /* symbol */, + ); + name = states; + sourceTree = ""; + }; + D3541F890DFB108300429B4F /* symbol */ = { + isa = PBXGroup; + children = ( + D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */, + D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */, + D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */, + D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */, + ); + name = symbol; + sourceTree = ""; + }; + D35420EC0DFB275400429B4F /* tokenizer states */ = { + isa = PBXGroup; + children = ( + D34BAD16100A9B7900996341 /* TDTokenizerStateTest.h */, + D34BAD17100A9B7900996341 /* TDTokenizerStateTest.m */, + D31FE5770E60E58C00A0803E /* TDNumberStateTest.h */, + D31FE5780E60E58C00A0803E /* TDNumberStateTest.m */, + D31FE5790E60E58C00A0803E /* TDQuoteStateTest.h */, + D31FE57A0E60E58C00A0803E /* TDQuoteStateTest.m */, + D31FE57F0E60E58C00A0803E /* TDSymbolStateTest.h */, + D31FE5800E60E58C00A0803E /* TDSymbolStateTest.m */, + D31FE5810E60E58C00A0803E /* TDWhitespaceStateTest.h */, + D31FE5820E60E58C00A0803E /* TDWhitespaceStateTest.m */, + D31FE5830E60E58C00A0803E /* TDWordStateTest.h */, + D31FE5840E60E58C00A0803E /* TDWordStateTest.m */, + D3C85D430E63D1BF000445FD /* TDScientificNumberStateTest.h */, + D3C85D440E63D1BF000445FD /* TDScientificNumberStateTest.m */, + D3DDDAFC0F083C9700A58000 /* TDCommentStateTest.h */, + D3DDDAFD0F083C9700A58000 /* TDCommentStateTest.m */, + D3E39C3D0FC5FFD10022DAB9 /* TDDelimitStateTest.h */, + D3E39C3E0FC5FFD10022DAB9 /* TDDelimitStateTest.m */, + ); + name = "tokenizer states"; + sourceTree = ""; + }; + D36568A40EEF9FB600226554 /* plist */ = { + isa = PBXGroup; + children = ( + D36568A50EEF9FE900226554 /* TDPlistParser.h */, + D36568A60EEF9FE900226554 /* TDPlistParser.m */, + D36568A80EEFA05300226554 /* TDPlistParserTest.h */, + D36568A90EEFA05300226554 /* TDPlistParserTest.m */, + ); + name = plist; + sourceTree = ""; + }; + D3668290101D2BAC0008632C /* erb */ = { + isa = PBXGroup; + children = ( + D3668291101D2BFA0008632C /* erb.grammar */, + D3668294101D2C200008632C /* ERBTest.h */, + D3668295101D2C200008632C /* ERBTest.m */, + ); + name = erb; + sourceTree = ""; + }; + D36C55FB0FD3616200141CB7 /* regex */ = { + isa = PBXGroup; + children = ( + D3C221F00FFE8C7A004514FE /* PKPattern.h */, + D34BAF380FF9E18300D7773A /* PKPattern.m */, + D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */, + D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */, + ); + name = regex; + sourceTree = ""; + }; + D36E94F40E57865500496BD3 /* xpath */ = { + isa = PBXGroup; + children = ( + D34BAC490FF892C200D7773A /* XPathParserGrammarTest.h */, + D34BAC4A0FF892C200D7773A /* XPathParserGrammarTest.m */, + D31FE5EF0E60E6B500A0803E /* TDNCName.h */, + D31FE6DF0E60EE2500A0803E /* TDNCName.m */, + D31FE5F00E60E6B500A0803E /* TDNCNameState.h */, + D31FE5F10E60E6B500A0803E /* TDNCNameState.m */, + D36E95440E578ECC00496BD3 /* XPathParser.h */, + D36E95450E578ECC00496BD3 /* XPathParser.m */, + D36E97AE0E589DAE00496BD3 /* XPathAssembler.h */, + D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */, + D36E98200E58A3A800496BD3 /* XPathContext.h */, + D36E98210E58A3A800496BD3 /* XPathContext.m */, + D36E95D60E57B08400496BD3 /* XPathParserTest.h */, + D36E95D70E57B08400496BD3 /* XPathParserTest.m */, + ); + name = xpath; + sourceTree = ""; + }; + D36E98CB0E58C08F00496BD3 /* DebugApp */ = { + isa = PBXGroup; + children = ( + D3F0E3290FFEA1E200C9DF74 /* DebugApp-Info.plist */, + D36E98DF0E58C12800496BD3 /* main.m */, + D36E98DC0E58C12800496BD3 /* DebugAppDelegate.h */, + D36E98DD0E58C12800496BD3 /* DebugAppDelegate.m */, + D3F740B50EF8C38A00559B9F /* JSONAssembler.h */, + D3F740B60EF8C38A00559B9F /* JSONAssembler.m */, + D36E98DE0E58C12800496BD3 /* DebugAppMainMenu.xib */, + ); + name = DebugApp; + path = debugapp; + sourceTree = ""; + }; + D36EA1400E5CF19F00496BD3 /* xml token terminals */ = { + isa = PBXGroup; + children = ( + D31FE5B90E60E69E00A0803E /* TDXmlAttribute.h */, + D31FE5BA0E60E69E00A0803E /* TDXmlAttribute.m */, + D31FE5BB0E60E69E00A0803E /* TDXmlCdata.h */, + D31FE5BC0E60E69E00A0803E /* TDXmlCdata.m */, + D31FE5BD0E60E69E00A0803E /* TDXmlComment.h */, + D31FE5BE0E60E69E00A0803E /* TDXmlComment.m */, + D31FE5BF0E60E69E00A0803E /* TDXmlDecl.h */, + D31FE5C00E60E69E00A0803E /* TDXmlDecl.m */, + D31FE5C10E60E69E00A0803E /* TDXmlDoctype.h */, + D31FE5C20E60E69E00A0803E /* TDXmlDoctype.m */, + D31FE5C30E60E69E00A0803E /* TDXmlDocument.h */, + D31FE5C40E60E69E00A0803E /* TDXmlDocument.m */, + D31FE5C50E60E69E00A0803E /* TDXmlEndEntity.h */, + D31FE5C60E60E69E00A0803E /* TDXmlEndEntity.m */, + D31FE5C70E60E69E00A0803E /* TDXmlEndTag.h */, + D31FE5C80E60E69E00A0803E /* TDXmlEndTag.m */, + D31FE5C90E60E69E00A0803E /* TDXmlEntity.h */, + D31FE5CA0E60E69E00A0803E /* TDXmlEntity.m */, + D31FE5CB0E60E69E00A0803E /* TDXmlEntityRef.h */, + D31FE5CC0E60E69E00A0803E /* TDXmlEntityRef.m */, + D31FE5CD0E60E69E00A0803E /* TDXmlFragment.h */, + D31FE5CE0E60E69E00A0803E /* TDXmlFragment.m */, + D31FE5CF0E60E69E00A0803E /* TDXmlNotation.h */, + D31FE5D00E60E69E00A0803E /* TDXmlNotation.m */, + D31FE5D10E60E69E00A0803E /* TDXmlProcessingInstruction.h */, + D31FE5D20E60E69E00A0803E /* TDXmlProcessingInstruction.m */, + D31FE5D30E60E69E00A0803E /* TDXmlSignificantWhitespace.h */, + D31FE5D40E60E69E00A0803E /* TDXmlSignificantWhitespace.m */, + D31FE5D50E60E69E00A0803E /* TDXmlStartTag.h */, + D31FE5D60E60E69E00A0803E /* TDXmlStartTag.m */, + D31FE5D70E60E69E00A0803E /* TDXmlTerminal.h */, + D31FE5D80E60E69E00A0803E /* TDXmlTerminal.m */, + D31FE5D90E60E69E00A0803E /* TDXmlText.h */, + D31FE5DA0E60E69E00A0803E /* TDXmlText.m */, + D31FE5DB0E60E69E00A0803E /* TDXmlWhitespace.h */, + D31FE5DC0E60E69E00A0803E /* TDXmlWhitespace.m */, + ); + name = "xml token terminals"; + sourceTree = ""; + }; + D36EA1440E5CF38100496BD3 /* tokenizer */ = { + isa = PBXGroup; + children = ( + D31FE5B30E60E66600A0803E /* TDXmlToken.h */, + D31FE5B40E60E66600A0803E /* TDXmlToken.m */, + D31FE5B50E60E66600A0803E /* TDXmlTokenizer.h */, + D31FE5B60E60E66600A0803E /* TDXmlTokenizer.m */, + ); + name = tokenizer; + sourceTree = ""; + }; + D380BA950F0F1C450009EC13 /* JSParseKit Framework */ = { + isa = PBXGroup; + children = ( + D34BB04E0FF9EC4E00D7773A /* JSParseKit-Info.plist */, + D34BB0660FF9EDDF00D7773A /* JSParseKit.h */, + D34BB0670FF9EDDF00D7773A /* JSParseKit.m */, + D34BB06C0FF9EE4000D7773A /* PKJSUtils.h */, + D34BB06D0FF9EE4000D7773A /* PKJSUtils.m */, + D34BB06E0FF9EE4000D7773A /* PKJSUtils_macros.h */, + D34BB06F0FF9EE4000D7773A /* PKJSValueHolder.h */, + D34BB0700FF9EE4000D7773A /* PKJSValueHolder.m */, + D34BB06A0FF9EE4000D7773A /* PKJSAssembly.h */, + D34BB06B0FF9EE4000D7773A /* PKJSAssembly.m */, + D389F8C40F1AC89A00558235 /* Chars */, + D389F59A0F19BBAE00558235 /* Tokens */, + D389F59B0F19BBD300558235 /* Parse */, + ); + name = "JSParseKit Framework"; + sourceTree = ""; + }; + D389A0AE0F1FCC7A003B43BD /* relaxng */ = { + isa = PBXGroup; + children = ( + D389A0B00F1FCC99003B43BD /* RelaxParser.h */, + D389A0B10F1FCC99003B43BD /* RelaxParser.m */, + ); + name = relaxng; + sourceTree = ""; + }; + D389F2CA0F196ACF00558235 /* JSDemoApp */ = { + isa = PBXGroup; + children = ( + D3F0E37A0FFEA39000C9DF74 /* JSDemoApp-Info.plist */, + D389F2E30F196CAE00558235 /* main.m */, + D389F2E80F196F5B00558235 /* JSDemoAppDelegate.h */, + D389F2E90F196F5B00558235 /* JSDemoAppDelegate.m */, + D389F38E0F19800400558235 /* DefaultValues.plist */, + D389F4610F198A8800558235 /* Test.html */, + D389FBCC0F1B25E200558235 /* ParserTest.html */, + D389F5580F19B7BC00558235 /* JSDemoAppMainMenu.xib */, + ); + name = JSDemoApp; + sourceTree = ""; + }; + D389F59A0F19BBAE00558235 /* Tokens */ = { + isa = PBXGroup; + children = ( + D34BB0930FF9F14B00D7773A /* PKJSCommentState.h */, + D34BB0940FF9F14B00D7773A /* PKJSCommentState.m */, + D34BB0950FF9F14B00D7773A /* PKJSDelimitState.h */, + D34BB0960FF9F14B00D7773A /* PKJSDelimitState.m */, + D34BB0970FF9F14B00D7773A /* PKJSNumberState.h */, + D34BB0980FF9F14B00D7773A /* PKJSNumberState.m */, + D34BB0990FF9F14B00D7773A /* PKJSQuoteState.h */, + D34BB09A0FF9F14B00D7773A /* PKJSQuoteState.m */, + D34BB09B0FF9F14B00D7773A /* PKJSSymbolState.h */, + D34BB09C0FF9F14B00D7773A /* PKJSSymbolState.m */, + D34BB09D0FF9F14B00D7773A /* PKJSToken.h */, + D34BB09E0FF9F14B00D7773A /* PKJSToken.m */, + D34BB09F0FF9F14B00D7773A /* PKJSTokenAssembly.h */, + D34BB0A00FF9F14B00D7773A /* PKJSTokenAssembly.m */, + D34BB0A10FF9F14B00D7773A /* PKJSTokenizer.h */, + D34BB0A20FF9F14B00D7773A /* PKJSTokenizer.m */, + D34BB0A30FF9F14B00D7773A /* PKJSTokenizerState.h */, + D34BB0A40FF9F14B00D7773A /* PKJSTokenizerState.m */, + D34BB0A50FF9F14B00D7773A /* PKJSWhitespaceState.h */, + D34BB0A60FF9F14B00D7773A /* PKJSWhitespaceState.m */, + D34BB0A70FF9F14B00D7773A /* PKJSWordState.h */, + D34BB0A80FF9F14B00D7773A /* PKJSWordState.m */, + ); + name = Tokens; + sourceTree = ""; + }; + D389F59B0F19BBD300558235 /* Parse */ = { + isa = PBXGroup; + children = ( + D34BB0D20FF9F28000D7773A /* PKJSAlternation.h */, + D34BB0D30FF9F28000D7773A /* PKJSAlternation.m */, + D34BB0D40FF9F28000D7773A /* PKJSAny.h */, + D34BB0D50FF9F28000D7773A /* PKJSAny.m */, + D34BB0D60FF9F28000D7773A /* PKJSAssemblerAdapter.h */, + D34BB0D70FF9F28000D7773A /* PKJSAssemblerAdapter.m */, + D34BB0D80FF9F28000D7773A /* PKJSCollectionParser.h */, + D34BB0D90FF9F28000D7773A /* PKJSCollectionParser.m */, + D34BB0DA0FF9F28000D7773A /* PKJSEmpty.h */, + D34BB0DB0FF9F28000D7773A /* PKJSEmpty.m */, + D34BB0DC0FF9F28000D7773A /* PKJSParser.h */, + D34BB0DD0FF9F28000D7773A /* PKJSParser.m */, + D34BB0DE0FF9F28000D7773A /* PKJSRepetition.h */, + D34BB0DF0FF9F28000D7773A /* PKJSRepetition.m */, + D34BB0E00FF9F28000D7773A /* PKJSSequence.h */, + D34BB0E10FF9F28000D7773A /* PKJSSequence.m */, + D34BB0E20FF9F28000D7773A /* PKJSTerminal.h */, + D34BB0E30FF9F28000D7773A /* PKJSTerminal.m */, + D34BB0E40FF9F28000D7773A /* PKJSTrack.h */, + D34BB0E50FF9F28000D7773A /* PKJSTrack.m */, + D389FAE30F1B1B8F00558235 /* Char Terminals */, + D389FAE20F1B1B7200558235 /* Token Terminals */, + ); + name = Parse; + sourceTree = ""; + }; + D389F8C40F1AC89A00558235 /* Chars */ = { + isa = PBXGroup; + children = ( + D34BB08D0FF9EF9D00D7773A /* PKJSCharacterAssembly.h */, + D34BB08E0FF9EF9D00D7773A /* PKJSCharacterAssembly.m */, + ); + name = Chars; + sourceTree = ""; + }; + D389FAE20F1B1B7200558235 /* Token Terminals */ = { + isa = PBXGroup; + children = ( + D34BB0FE0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h */, + D34BB0FF0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m */, + D34BB1000FF9F36200D7773A /* PKJSComment.h */, + D34BB1010FF9F36200D7773A /* PKJSComment.m */, + D34BB1020FF9F36200D7773A /* PKJSDelimitedString.h */, + D34BB1030FF9F36200D7773A /* PKJSDelimitedString.m */, + D34BB1040FF9F36200D7773A /* PKJSLiteral.h */, + D34BB1050FF9F36200D7773A /* PKJSLiteral.m */, + D34BB1060FF9F36200D7773A /* PKJSLowercaseWord.h */, + D34BB1070FF9F36200D7773A /* PKJSLowercaseWord.m */, + D34BB1080FF9F36200D7773A /* PKJSNum.h */, + D34BB1090FF9F36200D7773A /* PKJSNum.m */, + D34BB10A0FF9F36200D7773A /* PKJSPattern.h */, + D34BB10B0FF9F36200D7773A /* PKJSPattern.m */, + D34BB10C0FF9F36200D7773A /* PKJSQuotedString.h */, + D34BB10D0FF9F36200D7773A /* PKJSQuotedString.m */, + D34BB10E0FF9F36200D7773A /* PKJSSymbol.h */, + D34BB10F0FF9F36200D7773A /* PKJSSymbol.m */, + D34BB1100FF9F36200D7773A /* PKJSUppercaseWord.h */, + D34BB1110FF9F36200D7773A /* PKJSUppercaseWord.m */, + D34BB1120FF9F36200D7773A /* PKJSWord.h */, + D34BB1130FF9F36200D7773A /* PKJSWord.m */, + ); + name = "Token Terminals"; + sourceTree = ""; + }; + D389FAE30F1B1B8F00558235 /* Char Terminals */ = { + isa = PBXGroup; + children = ( + ); + name = "Char Terminals"; + sourceTree = ""; + }; + D3AF4C8E0FDC738B0032F4DC /* Other Sources */ = { + isa = PBXGroup; + children = ( + D34BAD630FF9C6AE00D7773A /* ParseKit_Prefix.pch */, + D3FDC8DB0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + D3AF4CC80FDC74320032F4DC /* Blob */ = { + isa = PBXGroup; + children = ( + D3AF4BF50FDC40050032F4DC /* TDToken+Blob.h */, + D3AF4BF60FDC40050032F4DC /* TDToken+Blob.m */, + D3AF4BFB0FDC41190032F4DC /* TDTokenizer+BlobState.h */, + D3AF4BFC0FDC41190032F4DC /* TDTokenizer+BlobState.m */, + D3AF4C190FDC568F0032F4DC /* TDBlobState.h */, + D3AF4C1A0FDC568F0032F4DC /* TDBlobState.m */, + D3AF4BE80FDC3DD50032F4DC /* TDBlob.h */, + D3AF4BE90FDC3DD50032F4DC /* TDBlob.m */, + ); + name = Blob; + sourceTree = ""; + }; + D3AF4CC90FDC743C0032F4DC /* ReservedWord */ = { + isa = PBXGroup; + children = ( + D3AF4CC50FDC740A0032F4DC /* TDWordOrReservedState.h */, + D3AF4CC60FDC740A0032F4DC /* TDWordOrReservedState.m */, + D3AF4CBF0FDC740A0032F4DC /* TDNonReservedWord.h */, + D3AF4CC00FDC740A0032F4DC /* TDNonReservedWord.m */, + D3AF4CC10FDC740A0032F4DC /* TDReservedWord.h */, + D3AF4CC20FDC740A0032F4DC /* TDReservedWord.m */, + ); + name = ReservedWord; + sourceTree = ""; + }; + D3AF4CCA0FDC74490032F4DC /* Slash */ = { + isa = PBXGroup; + children = ( + D3DDDC230F085C5400A58000 /* TDSlashSlashState.h */, + D3DDDC240F085C5400A58000 /* TDSlashSlashState.m */, + D3DDDC250F085C5400A58000 /* TDSlashStarState.h */, + D3DDDC260F085C5400A58000 /* TDSlashStarState.m */, + D3DDDC270F085C5400A58000 /* TDSlashState.h */, + D3DDDC280F085C5400A58000 /* TDSlashState.m */, + D31FE57D0E60E58C00A0803E /* TDSlashStateTest.h */, + D31FE57E0E60E58C00A0803E /* TDSlashStateTest.m */, + ); + name = Slash; + sourceTree = ""; + }; + D3AF4CCB0FDC74540032F4DC /* Whitespace */ = { + isa = PBXGroup; + children = ( + D3AF4CC30FDC740A0032F4DC /* TDSignificantWhitespaceState.h */, + D3AF4CC40FDC740A0032F4DC /* TDSignificantWhitespaceState.m */, + D31FE57B0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.h */, + D31FE57C0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.m */, + ); + name = Whitespace; + sourceTree = ""; + }; + D3BBBC9A0FEC9739007DF30D /* old */ = { + isa = PBXGroup; + children = ( + D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */, + D36E9FB40E5A944A00496BD3 /* apple-boss.xml */, + D31FE5AD0E60E64900A0803E /* TDXmlTokenAssembly.h */, + D31FE5AE0E60E64900A0803E /* TDXmlTokenAssembly.m */, + D31FE5AF0E60E64900A0803E /* TDXmlTokenizerTest.h */, + D31FE5B00E60E64900A0803E /* TDXmlTokenizerTest.m */, + D36EA1440E5CF38100496BD3 /* tokenizer */, + D36EA1400E5CF19F00496BD3 /* xml token terminals */, + D3521F520E5FA1B0009681F9 /* XMLReader.h */, + D3521F530E5FA1B0009681F9 /* XMLReader.m */, + D3521F540E5FA1B0009681F9 /* XMLReaderTest.h */, + D3521F550E5FA1B0009681F9 /* XMLReaderTest.m */, + D31FE5F20E60E6B500A0803E /* TDXmlName.h */, + D31FE5F30E60E6B500A0803E /* TDXmlName.m */, + D31FE5F40E60E6B500A0803E /* TDXmlNameState.h */, + D31FE5F50E60E6B500A0803E /* TDXmlNameState.m */, + D31FE5F60E60E6B500A0803E /* TDXmlNameTest.h */, + D31FE5F70E60E6B500A0803E /* TDXmlNameTest.m */, + D31FE5F80E60E6B500A0803E /* TDXmlNmtoken.h */, + D31FE5F90E60E6B500A0803E /* TDXmlNmtoken.m */, + D31FE5FA0E60E6B500A0803E /* TDXmlNmtokenState.h */, + D31FE5FB0E60E6B500A0803E /* TDXmlNmtokenState.m */, + ); + name = old; + sourceTree = ""; + }; + D3C0309C0EF34DD200C5ABEB /* grammar */ = { + isa = PBXGroup; + children = ( + D380B5370F0D7DDE0009EC13 /* css.css */, + D380B5080F0D71A90009EC13 /* css.grammar */, + D380B5930F0D82F60009EC13 /* example.css */, + D380AFBB0F0C54B60009EC13 /* html.css */, + D380AFBC0F0C54B60009EC13 /* html.grammar */, + D385FD6B0F05A99900DB2946 /* mini_css.grammar */, + D3DCB4C20EF6015300DE5110 /* json.grammar */, + D385FA240F04993500DB2946 /* json.css */, + D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */, + D38349BB0F0C0D910055E4E0 /* json_with_comments.css */, + D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */, + D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */, + D380AFC20F0C56000009EC13 /* example.html */, + D3F741BD0EF9F28D00559B9F /* css2_1.grammar */, + D3F741430EF8E96A00559B9F /* xpath1_0.grammar */, + D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */, + D31A15250F6DE449002AFDF1 /* javascript.grammar */, + D385FD400F05A88C00DB2946 /* TDMiniCSSAssembler.h */, + D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */, + D385FD420F05A88C00DB2946 /* TDMiniCSSAssemblerTest.h */, + D385FD430F05A88C00DB2946 /* TDMiniCSSAssemblerTest.m */, + D385F9880F046FE900DB2946 /* TDGenericAssembler.h */, + D385F9890F046FE900DB2946 /* TDGenericAssembler.m */, + D385FA210F04971400DB2946 /* TDGenericAssemblerTest.h */, + D385FA220F04971400DB2946 /* TDGenericAssemblerTest.m */, + D3DDDA850F0779FD00A58000 /* TDSyntaxHighlighter.h */, + D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */, + D353899B0FEAC94400926552 /* c.grammar */, + D353899D0FEAC96B00926552 /* objc.grammar */, + D355C8830FEB4B94006A91A4 /* proto.grammar */, + ); + name = grammar; + sourceTree = ""; + }; + D3C7D8220A411F31005DD154 /* ParseKit Tests */ = { + isa = PBXGroup; + children = ( + D3F0E36C0FFEA33700C9DF74 /* Tests-Info.plist */, + D31FE54A0E60E46100A0803E /* TDTestScaffold.h */, + D31FE54B0E60E46100A0803E /* TDTestScaffold.m */, + D3376D7710096BDE00E4602E /* IR */, + D3F823560F57859900B7DC48 /* factory */, + D3C0309C0EF34DD200C5ABEB /* grammar */, + D3252F670FCE171D005EF059 /* predicate */, + D31A164F0F703899002AFDF1 /* javascript */, + D3D63F570E2A8548009BF5CD /* parse */, + D3D63F560E2A8538009BF5CD /* tokens */, + D34A20080E55FD5F00A4A0BF /* chars */, + D3C85C770E63B400000445FD /* arithmetic */, + D3E786030E5510AE008C7D61 /* regex */, + D3E788890E567B6D008C7D61 /* ebnf */, + D36568A40EEF9FB600226554 /* plist */, + D318EAE30E2FD5B6009F47DF /* json */, + D3D647CE0E2C7569009BF5CD /* xml */, + D36E94F40E57865500496BD3 /* xpath */, + D3E788900E567DDA008C7D61 /* srgs */, + D389A0AE0F1FCC7A003B43BD /* relaxng */, + D3C863240E67C249000445FD /* syntax highlight */, + D3668290101D2BAC0008632C /* erb */, + ); + name = "ParseKit Tests"; + sourceTree = ""; + }; + D3C7D8710A411F6B005DD154 /* io */ = { + isa = PBXGroup; + children = ( + D3C221960FFE8B95004514FE /* PKReader.h */, + D34BAD9B0FF9C95800D7773A /* PKReader.m */, + ); + name = io; + sourceTree = ""; + }; + D3C7D8720A411F81005DD154 /* parse */ = { + isa = PBXGroup; + children = ( + D3C221990FFE8B9D004514FE /* PKAssembly.h */, + D34BADA00FF9C9B000D7773A /* PKAssembly.m */, + D3D63EA90E2A7A5C009BF5CD /* parsers */, + ); + name = parse; + sourceTree = ""; + }; + D3C7D8740A411F8E005DD154 /* tokens */ = { + isa = PBXGroup; + children = ( + D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */, + D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */, + D341846A0E5209A60081B0DC /* tokenizer */, + D3541F870DFB105900429B4F /* states */, + D3D642270E2AC426009BF5CD /* token terminals */, + ); + name = tokens; + sourceTree = ""; + }; + D3C85C770E63B400000445FD /* arithmetic */ = { + isa = PBXGroup; + children = ( + D319E429106D8A1F008C63DD /* arithmetic.grammar */, + D319E42C106D8A31008C63DD /* TDArithmeticAssembler.h */, + D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */, + D3C85C790E63B438000445FD /* TDArithmeticParser.h */, + D3C85C7A0E63B438000445FD /* TDArithmeticParser.m */, + D3C85C7E0E63B9E9000445FD /* TDArithmeticParserTest.h */, + D3C85C7F0E63B9E9000445FD /* TDArithmeticParserTest.m */, + ); + name = arithmetic; + sourceTree = ""; + }; + D3C863240E67C249000445FD /* syntax highlight */ = { + isa = PBXGroup; + children = ( + D3C863250E67C255000445FD /* html */, + ); + name = "syntax highlight"; + sourceTree = ""; + }; + D3C863250E67C255000445FD /* html */ = { + isa = PBXGroup; + children = ( + D38DD9E70EC29F260070BC4D /* nyt.html */, + D3B69D310E80249900D70C41 /* nonascii.html */, + D3EADD7F0E75E9CC00F78584 /* nasty.html */, + D3EADD8D0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.h */, + D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */, + ); + name = html; + sourceTree = ""; + }; + D3D63EA90E2A7A5C009BF5CD /* parsers */ = { + isa = PBXGroup; + children = ( + D3C2219C0FFE8BA6004514FE /* PKParser.h */, + D34BADD60FF9CBFB00D7773A /* PKParser.m */, + D3C2219F0FFE8BAE004514FE /* PKRepetition.h */, + D34BAE130FF9CE0E00D7773A /* PKRepetition.m */, + D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */, + D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */, + D3C221A50FFE8BC1004514FE /* PKAlternation.h */, + D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */, + D3C221A80FFE8BC9004514FE /* PKSequence.h */, + D34BAE150FF9CE0E00D7773A /* PKSequence.m */, + D3C221AB0FFE8BCF004514FE /* PKTrack.h */, + D34BAE190FF9CE0E00D7773A /* PKTrack.m */, + D3C221AE0FFE8BD4004514FE /* PKTrackException.h */, + D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */, + D3C221B10FFE8BDB004514FE /* PKIntersection.h */, + D34BAE110FF9CE0E00D7773A /* PKIntersection.m */, + D3C221B40FFE8BE2004514FE /* PKDifference.h */, + D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */, + D3C221B70FFE8BE8004514FE /* PKNegation.h */, + D3126D040FFD9BA700CBF4C4 /* PKNegation.m */, + D3C221BA0FFE8BEF004514FE /* PKTerminal.h */, + D34BAE170FF9CE0E00D7773A /* PKTerminal.m */, + D3C221BD0FFE8BF7004514FE /* PKEmpty.h */, + D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */, + ); + name = parsers; + sourceTree = ""; + }; + D3D63F560E2A8538009BF5CD /* tokens */ = { + isa = PBXGroup; + children = ( + D31FE5710E60E55700A0803E /* TDReaderTest.h */, + D31FE5720E60E55700A0803E /* TDReaderTest.m */, + D31FE5730E60E55700A0803E /* TDTokenizerTest.h */, + D31FE5740E60E55700A0803E /* TDTokenizerTest.m */, + D38E97CA1061CF6500739C39 /* TDTokenizerBlocksTest.h */, + D38E97CB1061CF6500739C39 /* TDTokenizerBlocksTest.m */, + D38205BC0EEE48EE004340DD /* TDTokenTest.h */, + D38205BD0EEE48EE004340DD /* TDTokenTest.m */, + D3656DFC0EF2620E00226554 /* TDTokenArraySourceTest.h */, + D3656DFD0EF2620E00226554 /* TDTokenArraySourceTest.m */, + D35420EC0DFB275400429B4F /* tokenizer states */, + ); + name = tokens; + sourceTree = ""; + }; + D3D63F570E2A8548009BF5CD /* parse */ = { + isa = PBXGroup; + children = ( + D31FE54D0E60E50800A0803E /* TDAlternationTest.h */, + D31FE54E0E60E50800A0803E /* TDAlternationTest.m */, + D31FE54F0E60E50800A0803E /* TDLiteralTest.h */, + D31FE5500E60E50800A0803E /* TDLiteralTest.m */, + D31FE5510E60E50800A0803E /* TDParserTest.h */, + D31FE5520E60E50800A0803E /* TDParserTest.m */, + D38E98D61062C5BA00739C39 /* TDParserBlocksTest.h */, + D38E98D71062C5BA00739C39 /* TDParserBlocksTest.m */, + D31FE5530E60E50800A0803E /* TDRepetitionTest.h */, + D31FE5540E60E50800A0803E /* TDRepetitionTest.m */, + D31FE5550E60E50800A0803E /* TDReservedWordTest.h */, + D31FE5560E60E50800A0803E /* TDReservedWordTest.m */, + D31FE5570E60E50800A0803E /* TDRobotCommandTest.h */, + D31FE5580E60E50800A0803E /* TDRobotCommandTest.m */, + D31FE5590E60E50800A0803E /* TDSequenceTest.h */, + D31FE55A0E60E50800A0803E /* TDSequenceTest.m */, + D31FE55B0E60E50800A0803E /* TDSymbolTest.h */, + D31FE55C0E60E50800A0803E /* TDSymbolTest.m */, + D31FE55D0E60E50800A0803E /* TDTokenAssemblyTest.h */, + D31FE55E0E60E50800A0803E /* TDTokenAssemblyTest.m */, + D31FE55F0E60E50800A0803E /* TDTrackTest.h */, + D31FE5600E60E50800A0803E /* TDTrackTest.m */, + D31FE5610E60E50800A0803E /* TDUppercaseWordTest.h */, + D31FE5620E60E50800A0803E /* TDUppercaseWordTest.m */, + D3C031EB0EF38D2D00C5ABEB /* TDLowercaseWordTest.h */, + D3C031EC0EF38D2D00C5ABEB /* TDLowercaseWordTest.m */, + D3126D410FFDB4C600CBF4C4 /* TDExclusionTest.h */, + D3126D420FFDB4C600CBF4C4 /* TDExclusionTest.m */, + D36C56290FD365DB00141CB7 /* TDPatternTest.h */, + D36C562A0FD365DB00141CB7 /* TDPatternTest.m */, + D338E5B90FF5DDCB003DE6AA /* TDDifferenceTest.h */, + D338E5BA0FF5DDCB003DE6AA /* TDDifferenceTest.m */, + D3126D090FFD9E4B00CBF4C4 /* TDNegationTest.h */, + D3126D0A0FFD9E4B00CBF4C4 /* TDNegationTest.m */, + ); + name = parse; + sourceTree = ""; + }; + D3D642270E2AC426009BF5CD /* token terminals */ = { + isa = PBXGroup; + children = ( + D36C55FB0FD3616200141CB7 /* regex */, + D3C221F30FFE8C87004514FE /* PKWord.h */, + D34BAED40FF9D56400D7773A /* PKWord.m */, + D3C222140FFE8D01004514FE /* PKLowercaseWord.h */, + D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */, + D3C222170FFE8D11004514FE /* PKUppercaseWord.h */, + D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */, + D3C221F60FFE8C8E004514FE /* PKNumber.h */, + D34BAF440FF9E19700D7773A /* PKNumber.m */, + D3C221F90FFE8C97004514FE /* PKQuotedString.h */, + D34BAF460FF9E19700D7773A /* PKQuotedString.m */, + D3C221FC0FFE8CB2004514FE /* PKSymbol.h */, + D34BAF480FF9E19700D7773A /* PKSymbol.m */, + D3C221FF0FFE8CB9004514FE /* PKLiteral.h */, + D34BAF420FF9E19700D7773A /* PKLiteral.m */, + D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */, + D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */, + D3C222050FFE8CCA004514FE /* PKWhitespace.h */, + D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */, + D3C222080FFE8CD1004514FE /* PKComment.h */, + D34BAF3E0FF9E19700D7773A /* PKComment.m */, + D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */, + D34BAF400FF9E19700D7773A /* PKDelimitedString.m */, + D3C2220E0FFE8CDF004514FE /* PKAny.h */, + D34BAE2F0FF9CE6000D7773A /* PKAny.m */, + ); + name = "token terminals"; + sourceTree = ""; + }; + D3D647CE0E2C7569009BF5CD /* xml */ = { + isa = PBXGroup; + children = ( + D3D1BF291039445C003656E5 /* SAXTest.h */, + D3D1BF2A1039445C003656E5 /* SAXTest.m */, + D3D1BF2610394420003656E5 /* SAXAssembler.h */, + D3D1BF2710394420003656E5 /* SAXAssembler.m */, + D3BBBC960FEC9722007DF30D /* TDXMLParserTest.h */, + D3BBBC970FEC9722007DF30D /* TDXMLParserTest.m */, + D3BBBC9B0FEC9756007DF30D /* TDXMLParser.h */, + D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */, + D355C8800FEB36A1006A91A4 /* xml.grammar */, + D315DF710FEF59B600D876C8 /* date.grammar */, + D3BBBC9A0FEC9739007DF30D /* old */, + ); + name = xml; + sourceTree = ""; + }; + D3E785F10E550F63008C7D61 /* chars */ = { + isa = PBXGroup; + children = ( + D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */, + D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */, + D3E7861F0E55363F008C7D61 /* char terminals */, + ); + name = chars; + sourceTree = ""; + }; + D3E786030E5510AE008C7D61 /* regex */ = { + isa = PBXGroup; + children = ( + D31FE59B0E60E5C000A0803E /* TDRegularParser.h */, + D31FE59C0E60E5C000A0803E /* TDRegularParser.m */, + D31FE59D0E60E5C000A0803E /* TDRegularParserTest.h */, + D31FE59E0E60E5C000A0803E /* TDRegularParserTest.m */, + ); + name = regex; + sourceTree = ""; + }; + D3E7861F0E55363F008C7D61 /* char terminals */ = { + isa = PBXGroup; + children = ( + D3C2221D0FFE8D3B004514FE /* PKChar.h */, + D34BAFB40FF9E80300D7773A /* PKChar.m */, + D3C222200FFE8D42004514FE /* PKDigit.h */, + D34BAFB60FF9E80300D7773A /* PKDigit.m */, + D3C222230FFE8D49004514FE /* PKLetter.h */, + D34BAFB80FF9E80300D7773A /* PKLetter.m */, + D3C222260FFE8D6B004514FE /* PKSpecificChar.h */, + D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */, + ); + name = "char terminals"; + sourceTree = ""; + }; + D3E788890E567B6D008C7D61 /* ebnf */ = { + isa = PBXGroup; + children = ( + D3E78A150E574C99008C7D61 /* EBNFParser.h */, + D3E78A160E574C99008C7D61 /* EBNFParser.m */, + D3E78A170E574C99008C7D61 /* EBNFParserTest.h */, + D3E78A180E574C99008C7D61 /* EBNFParserTest.m */, + ); + name = ebnf; + sourceTree = ""; + }; + D3E788900E567DDA008C7D61 /* srgs */ = { + isa = PBXGroup; + children = ( + D3DDDCAC0F0880D800A58000 /* example1.srgs */, + D3E788940E567E0A008C7D61 /* SRGSParser.h */, + D3E788950E567E0A008C7D61 /* SRGSParser.m */, + D3E788910E567DFD008C7D61 /* SRGSParserTest.h */, + D3E788920E567DFD008C7D61 /* SRGSParserTest.m */, + D36E9FE40E5BA0FC00496BD3 /* SRGSGrammar.txt */, + ); + name = srgs; + sourceTree = ""; + }; + D3F5619C1026374400DD6DB1 /* ir */ = { + isa = PBXGroup; + children = ( + D3F5619D1026375100DD6DB1 /* syntax tree */, + D3F561B61026379700DD6DB1 /* ast */, + ); + name = ir; + sourceTree = ""; + }; + D3F5619D1026375100DD6DB1 /* syntax tree */ = { + isa = PBXGroup; + children = ( + D36934551038DE5300527AF3 /* PKParseTree.h */, + D36934561038DE5300527AF3 /* PKParseTree.m */, + D36934571038DE5300527AF3 /* PKParseTreeAssembler.h */, + D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */, + D36934591038DE5300527AF3 /* PKRuleNode.h */, + D369345A1038DE5300527AF3 /* PKRuleNode.m */, + D369345B1038DE5300527AF3 /* PKTokenNode.h */, + D369345C1038DE5300527AF3 /* PKTokenNode.m */, + ); + name = "syntax tree"; + sourceTree = ""; + }; + D3F561B61026379700DD6DB1 /* ast */ = { + isa = PBXGroup; + children = ( + ); + name = ast; + sourceTree = ""; + }; + D3F823560F57859900B7DC48 /* factory */ = { + isa = PBXGroup; + children = ( + D34BAC210FF87F8600D7773A /* TDParserFactoryTest3.h */, + D34BAC220FF87F8600D7773A /* TDParserFactoryTest3.m */, + D380BA5F0F0F06CD0009EC13 /* TDParserFactoryTest.h */, + D380BA600F0F06CD0009EC13 /* TDParserFactoryTest.m */, + D36C53770FD27F1300141CB7 /* TDParserFactoryTest2.h */, + D36C53780FD27F1300141CB7 /* TDParserFactoryTest2.m */, + D3AF49760FDB122E0032F4DC /* TDParserFactoryPatternTest.h */, + D3AF49770FDB122E0032F4DC /* TDParserFactoryPatternTest.m */, + ); + name = factory; + sourceTree = ""; + }; + D3FDC8EF0FFC52CD00F1F797 /* Mobile Frameworks */ = { + isa = PBXGroup; + children = ( + D3FDC74B0FFC4DAC00F1F797 /* CoreGraphics.framework */, + D3FDC7380FFC4D6100F1F797 /* libicucore.dylib */, + D3FDC7360FFC4D6100F1F797 /* Foundation.framework */, + ); + name = "Mobile Frameworks"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 8DC2EF500486A6940098B216 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D34BAD640FF9C6AE00D7773A /* ParseKit_Prefix.pch in Headers */, + D3FDC4A50FFB3B2A00F1F797 /* RegexKitLite.h in Headers */, + D3C221920FFE8B8C004514FE /* ParseKit.h in Headers */, + D3C221930FFE8B8C004514FE /* PKTypes.h in Headers */, + D3C221970FFE8B95004514FE /* PKReader.h in Headers */, + D3C2219A0FFE8B9D004514FE /* PKAssembly.h in Headers */, + D3C2219D0FFE8BA6004514FE /* PKParser.h in Headers */, + D3C221A00FFE8BAE004514FE /* PKRepetition.h in Headers */, + D3C221A30FFE8BBA004514FE /* PKCollectionParser.h in Headers */, + D3C221A60FFE8BC1004514FE /* PKAlternation.h in Headers */, + D3C221A90FFE8BC9004514FE /* PKSequence.h in Headers */, + D3C221AC0FFE8BCF004514FE /* PKTrack.h in Headers */, + D3C221AF0FFE8BD4004514FE /* PKTrackException.h in Headers */, + D3C221B20FFE8BDB004514FE /* PKIntersection.h in Headers */, + D3C221B50FFE8BE2004514FE /* PKDifference.h in Headers */, + D3C221B80FFE8BE8004514FE /* PKNegation.h in Headers */, + D3C221BB0FFE8BEF004514FE /* PKTerminal.h in Headers */, + D3C221BE0FFE8BF7004514FE /* PKEmpty.h in Headers */, + D3C221C10FFE8BFF004514FE /* PKTokenAssembly.h in Headers */, + D3C221C40FFE8C07004514FE /* PKToken.h in Headers */, + D3C221C70FFE8C0D004514FE /* PKTokenArraySource.h in Headers */, + D3C221CA0FFE8C15004514FE /* PKTokenizer.h in Headers */, + D3C221CD0FFE8C1B004514FE /* PKTokenizerState.h in Headers */, + D3C221D00FFE8C24004514FE /* PKNumberState.h in Headers */, + D3C221D60FFE8C35004514FE /* PKSymbolState.h in Headers */, + D3C221D90FFE8C3D004514FE /* PKWordState.h in Headers */, + D3C221DC0FFE8C43004514FE /* PKWhitespaceState.h in Headers */, + D3C221DF0FFE8C49004514FE /* PKDelimitState.h in Headers */, + D3C221E20FFE8C4E004514FE /* PKCommentState.h in Headers */, + D3C221E50FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */, + D3C221E80FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */, + D3C221EB0FFE8C69004514FE /* PKSymbolNode.h in Headers */, + D3C221EE0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */, + D3C221F10FFE8C7A004514FE /* PKPattern.h in Headers */, + D3C221F40FFE8C87004514FE /* PKWord.h in Headers */, + D3C221F70FFE8C8E004514FE /* PKNumber.h in Headers */, + D3C221FA0FFE8C97004514FE /* PKQuotedString.h in Headers */, + D3C221FD0FFE8CB2004514FE /* PKSymbol.h in Headers */, + D3C222000FFE8CB9004514FE /* PKLiteral.h in Headers */, + D3C222030FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */, + D3C222060FFE8CCA004514FE /* PKWhitespace.h in Headers */, + D3C222090FFE8CD1004514FE /* PKComment.h in Headers */, + D3C2220C0FFE8CD8004514FE /* PKDelimitedString.h in Headers */, + D3C2220F0FFE8CDF004514FE /* PKAny.h in Headers */, + D3C222150FFE8D01004514FE /* PKLowercaseWord.h in Headers */, + D3C222180FFE8D11004514FE /* PKUppercaseWord.h in Headers */, + D3C2221B0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */, + D3C2221E0FFE8D3B004514FE /* PKChar.h in Headers */, + D3C222210FFE8D42004514FE /* PKDigit.h in Headers */, + D3C222240FFE8D49004514FE /* PKLetter.h in Headers */, + D3C222270FFE8D6B004514FE /* PKSpecificChar.h in Headers */, + D3C2222A0FFE8DAC004514FE /* PKParserFactory.h in Headers */, + D3C2222D0FFE8DE9004514FE /* NSArray+ParseKitAdditions.h in Headers */, + D3C2222E0FFE8DEE004514FE /* NSString+ParseKitAdditions.h in Headers */, + D3F0E2480FFE8EB900C9DF74 /* PKQuoteState.h in Headers */, + D3376D5910093A1600E4602E /* PKGrammarParser.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1C90F1965E600558235 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D34BB0680FF9EDDF00D7773A /* JSParseKit.h in Headers */, + D34BB0710FF9EE4000D7773A /* PKJSAssembly.h in Headers */, + D34BB0730FF9EE4000D7773A /* PKJSUtils.h in Headers */, + D34BB0750FF9EE4000D7773A /* PKJSUtils_macros.h in Headers */, + D34BB0760FF9EE4000D7773A /* PKJSValueHolder.h in Headers */, + D34BB08F0FF9EF9D00D7773A /* PKJSCharacterAssembly.h in Headers */, + D34BB0A90FF9F14B00D7773A /* PKJSCommentState.h in Headers */, + D34BB0AB0FF9F14B00D7773A /* PKJSDelimitState.h in Headers */, + D34BB0AD0FF9F14B00D7773A /* PKJSNumberState.h in Headers */, + D34BB0AF0FF9F14B00D7773A /* PKJSQuoteState.h in Headers */, + D34BB0B10FF9F14B00D7773A /* PKJSSymbolState.h in Headers */, + D34BB0B30FF9F14B00D7773A /* PKJSToken.h in Headers */, + D34BB0B50FF9F14B00D7773A /* PKJSTokenAssembly.h in Headers */, + D34BB0B70FF9F14B00D7773A /* PKJSTokenizer.h in Headers */, + D34BB0B90FF9F14B00D7773A /* PKJSTokenizerState.h in Headers */, + D34BB0BB0FF9F14B00D7773A /* PKJSWhitespaceState.h in Headers */, + D34BB0BD0FF9F14B00D7773A /* PKJSWordState.h in Headers */, + D34BB0E60FF9F28000D7773A /* PKJSAlternation.h in Headers */, + D34BB0E80FF9F28000D7773A /* PKJSAny.h in Headers */, + D34BB0EA0FF9F28000D7773A /* PKJSAssemblerAdapter.h in Headers */, + D34BB0EC0FF9F28000D7773A /* PKJSCollectionParser.h in Headers */, + D34BB0EE0FF9F28000D7773A /* PKJSEmpty.h in Headers */, + D34BB0F00FF9F28000D7773A /* PKJSParser.h in Headers */, + D34BB0F20FF9F28000D7773A /* PKJSRepetition.h in Headers */, + D34BB0F40FF9F28000D7773A /* PKJSSequence.h in Headers */, + D34BB0F60FF9F28000D7773A /* PKJSTerminal.h in Headers */, + D34BB0F80FF9F28000D7773A /* PKJSTrack.h in Headers */, + D34BB1140FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h in Headers */, + D34BB1160FF9F36200D7773A /* PKJSComment.h in Headers */, + D34BB1180FF9F36200D7773A /* PKJSDelimitedString.h in Headers */, + D34BB11A0FF9F36200D7773A /* PKJSLiteral.h in Headers */, + D34BB11C0FF9F36200D7773A /* PKJSLowercaseWord.h in Headers */, + D34BB11E0FF9F36200D7773A /* PKJSNum.h in Headers */, + D34BB1200FF9F36200D7773A /* PKJSPattern.h in Headers */, + D34BB1220FF9F36200D7773A /* PKJSQuotedString.h in Headers */, + D34BB1240FF9F36200D7773A /* PKJSSymbol.h in Headers */, + D34BB1260FF9F36200D7773A /* PKJSUppercaseWord.h in Headers */, + D34BB1280FF9F36200D7773A /* PKJSWord.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3FDC57F0FFC4BFC00F1F797 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D3FDC6DA0FFC4C8C00F1F797 /* RegexKitLite.h in Headers */, + D3FDC8DC0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch in Headers */, + D3C221940FFE8B8C004514FE /* ParseKit.h in Headers */, + D3C221950FFE8B8C004514FE /* PKTypes.h in Headers */, + D3C221980FFE8B95004514FE /* PKReader.h in Headers */, + D3C2219B0FFE8B9D004514FE /* PKAssembly.h in Headers */, + D3C2219E0FFE8BA6004514FE /* PKParser.h in Headers */, + D3C221A10FFE8BAE004514FE /* PKRepetition.h in Headers */, + D3C221A40FFE8BBA004514FE /* PKCollectionParser.h in Headers */, + D3C221A70FFE8BC1004514FE /* PKAlternation.h in Headers */, + D3C221AA0FFE8BC9004514FE /* PKSequence.h in Headers */, + D3C221AD0FFE8BCF004514FE /* PKTrack.h in Headers */, + D3C221B00FFE8BD4004514FE /* PKTrackException.h in Headers */, + D3C221B30FFE8BDB004514FE /* PKIntersection.h in Headers */, + D3C221B60FFE8BE2004514FE /* PKDifference.h in Headers */, + D3C221B90FFE8BE8004514FE /* PKNegation.h in Headers */, + D3C221BC0FFE8BEF004514FE /* PKTerminal.h in Headers */, + D3C221BF0FFE8BF7004514FE /* PKEmpty.h in Headers */, + D3C221C20FFE8BFF004514FE /* PKTokenAssembly.h in Headers */, + D3C221C50FFE8C07004514FE /* PKToken.h in Headers */, + D3C221C80FFE8C0D004514FE /* PKTokenArraySource.h in Headers */, + D3C221CB0FFE8C15004514FE /* PKTokenizer.h in Headers */, + D3C221CE0FFE8C1B004514FE /* PKTokenizerState.h in Headers */, + D3C221D10FFE8C24004514FE /* PKNumberState.h in Headers */, + D3C221D70FFE8C35004514FE /* PKSymbolState.h in Headers */, + D3C221DA0FFE8C3D004514FE /* PKWordState.h in Headers */, + D3C221DD0FFE8C43004514FE /* PKWhitespaceState.h in Headers */, + D3C221E00FFE8C49004514FE /* PKDelimitState.h in Headers */, + D3C221E30FFE8C4E004514FE /* PKCommentState.h in Headers */, + D3C221E60FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */, + D3C221E90FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */, + D3C221EC0FFE8C69004514FE /* PKSymbolNode.h in Headers */, + D3C221EF0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */, + D3C221F20FFE8C7A004514FE /* PKPattern.h in Headers */, + D3C221F50FFE8C87004514FE /* PKWord.h in Headers */, + D3C221FB0FFE8C97004514FE /* PKQuotedString.h in Headers */, + D3C221FE0FFE8CB2004514FE /* PKSymbol.h in Headers */, + D3C222010FFE8CB9004514FE /* PKLiteral.h in Headers */, + D3C222040FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */, + D3C222070FFE8CCA004514FE /* PKWhitespace.h in Headers */, + D3C2220A0FFE8CD1004514FE /* PKComment.h in Headers */, + D3C2220D0FFE8CD8004514FE /* PKDelimitedString.h in Headers */, + D3C222100FFE8CDF004514FE /* PKAny.h in Headers */, + D3C222160FFE8D01004514FE /* PKLowercaseWord.h in Headers */, + D3C222190FFE8D11004514FE /* PKUppercaseWord.h in Headers */, + D3C2221C0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */, + D3C2221F0FFE8D3B004514FE /* PKChar.h in Headers */, + D3C222220FFE8D42004514FE /* PKDigit.h in Headers */, + D3C222250FFE8D49004514FE /* PKLetter.h in Headers */, + D3C222280FFE8D6B004514FE /* PKSpecificChar.h in Headers */, + D3C2222B0FFE8DAC004514FE /* PKParserFactory.h in Headers */, + D3C2222F0FFE8DEF004514FE /* NSString+ParseKitAdditions.h in Headers */, + D3C222300FFE8DF3004514FE /* NSArray+ParseKitAdditions.h in Headers */, + D3F0E2490FFE8EB900C9DF74 /* PKQuoteState.h in Headers */, + D3F0E3CB0FFEB70100C9DF74 /* PKNumber.h in Headers */, + D37A28681013942A00E936B7 /* PKGrammarParser.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 8DC2EF4F0486A6940098B216 /* ParseKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "ParseKit" */; + buildPhases = ( + 8DC2EF500486A6940098B216 /* Headers */, + 8DC2EF540486A6940098B216 /* Sources */, + 8DC2EF520486A6940098B216 /* Resources */, + 8DC2EF560486A6940098B216 /* Frameworks */, + D36C65E7100ED81B000361A0 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ParseKit; + productInstallPath = "$(HOME)/Library/Frameworks"; + productName = TODParseKit; + productReference = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; + productType = "com.apple.product-type.framework"; + }; + D334940F0E2963FD00406085 /* DemoApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = D33494150E2963FE00406085 /* Build configuration list for PBXNativeTarget "DemoApp" */; + buildPhases = ( + D334940D0E2963FD00406085 /* Sources */, + D334940C0E2963FD00406085 /* Resources */, + D334940E0E2963FD00406085 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D33494A00E296AA900406085 /* PBXTargetDependency */, + ); + name = DemoApp; + productName = DemoApp; + productReference = D33494100E2963FD00406085 /* DemoApp.app */; + productType = "com.apple.product-type.application"; + }; + D34185030E520D3F0081B0DC /* DebugApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = D34185090E520D410081B0DC /* Build configuration list for PBXNativeTarget "DebugApp" */; + buildPhases = ( + D34185010E520D3F0081B0DC /* Sources */, + D34185000E520D3F0081B0DC /* Resources */, + D380B9A10F0EF3DC0009EC13 /* Copy Frameworks */, + D34185020E520D3F0081B0DC /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D34185100E520D6F0081B0DC /* PBXTargetDependency */, + ); + name = DebugApp; + productName = TestApp; + productReference = D34185040E520D3F0081B0DC /* DebugApp.app */; + productType = "com.apple.product-type.application"; + }; + D389F1CD0F1965E600558235 /* JSParseKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = D389F1D20F1965E800558235 /* Build configuration list for PBXNativeTarget "JSParseKit" */; + buildPhases = ( + D389F1C90F1965E600558235 /* Headers */, + D389F1CB0F1965E600558235 /* Sources */, + D389F1CA0F1965E600558235 /* Resources */, + D389F1CC0F1965E600558235 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D389F1D40F19665C00558235 /* PBXTargetDependency */, + ); + name = JSParseKit; + productName = TDJSParseKit; + productReference = D389F1CE0F1965E600558235 /* JSParseKit.framework */; + productType = "com.apple.product-type.framework"; + }; + D389F2020F196A7500558235 /* JSDemoApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = D389F2080F196A7600558235 /* Build configuration list for PBXNativeTarget "JSDemoApp" */; + buildPhases = ( + D389F2000F196A7500558235 /* Sources */, + D389F1FF0F196A7500558235 /* Resources */, + D389F2010F196A7500558235 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D389F20A0F196A8000558235 /* PBXTargetDependency */, + ); + name = JSDemoApp; + productName = JSDemoApp; + productReference = D389F2030F196A7500558235 /* JSDemoApp.app */; + productType = "com.apple.product-type.application"; + }; + D3C7D8790A411FBF005DD154 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D3C7D87C0A411FC0005DD154 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + D3C7D8760A411FBF005DD154 /* Sources */, + D3C7D8750A411FBF005DD154 /* Resources */, + D3DCB3880EF5E65100DE5110 /* Copy Frameworks */, + D3C7D8770A411FBF005DD154 /* Frameworks */, + D3C7D8780A411FBF005DD154 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + D31FE7180E60F24700A0803E /* PBXTargetDependency */, + ); + name = Tests; + productName = Tests; + productReference = D3C7D87A0A411FBF005DD154 /* Tests.octest */; + productType = "com.apple.product-type.bundle"; + }; + D3FDC5820FFC4BFC00F1F797 /* ParseKitMobile */ = { + isa = PBXNativeTarget; + buildConfigurationList = D3FDC62F0FFC4C2000F1F797 /* Build configuration list for PBXNativeTarget "ParseKitMobile" */; + buildPhases = ( + D3FDC57F0FFC4BFC00F1F797 /* Headers */, + D3FDC5800FFC4BFC00F1F797 /* Sources */, + D3FDC5810FFC4BFC00F1F797 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ParseKitMobile; + productName = ParseKitMobile; + productReference = D3FDC5830FFC4BFC00F1F797 /* libparsekit.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0867D690FE84028FC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ParseKit" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 0867D691FE84028FC02AAC07 /* TODParseKit */; + productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DC2EF4F0486A6940098B216 /* ParseKit */, + D389F1CD0F1965E600558235 /* JSParseKit */, + D3FDC5820FFC4BFC00F1F797 /* ParseKitMobile */, + D3C7D8790A411FBF005DD154 /* Tests */, + D334940F0E2963FD00406085 /* DemoApp */, + D34185030E520D3F0081B0DC /* DebugApp */, + D389F2020F196A7500558235 /* JSDemoApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8DC2EF520486A6940098B216 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D334940C0E2963FD00406085 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36E98F80E58C1A000496BD3 /* DemoAppMainMenu.xib in Resources */, + D3DCB4C40EF6015C00DE5110 /* json.grammar in Resources */, + D3F741BF0EF9F29400559B9F /* css2_1.grammar in Resources */, + D3D01CAB0EFDB8A000C24DDE /* json_with_discards.grammar in Resources */, + D3F562A210266E5300DD6DB1 /* TokensView.xib in Resources */, + D3F562A410266E6300DD6DB1 /* TreesView.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D34185000E520D3F0081B0DC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3E27A320E741DD20078CC2C /* small-xml-file.xml in Resources */, + D3E27A330E741DD20078CC2C /* apple-boss.xml in Resources */, + D398E20E0E60F86D00A1C877 /* yahoo.json in Resources */, + D3E785560E53FB54008C7D61 /* apple-boss.json in Resources */, + D36E98E10E58C12800496BD3 /* DebugAppMainMenu.xib in Resources */, + D3EADD810E75E9CC00F78584 /* nasty.html in Resources */, + D3B69D320E80249900D70C41 /* nonascii.html in Resources */, + D3DCB4C50EF6015C00DE5110 /* json.grammar in Resources */, + D3F741C00EF9F29500559B9F /* css2_1.grammar in Resources */, + D3D01CAC0EFDB8A100C24DDE /* json_with_discards.grammar in Resources */, + D385FA260F04993500DB2946 /* json.css in Resources */, + D385FD6C0F05A99900DB2946 /* mini_css.grammar in Resources */, + D3DDDCAE0F0880D800A58000 /* example1.srgs in Resources */, + D383498C0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */, + D38349BD0F0C0D910055E4E0 /* json_with_comments.css in Resources */, + D3834A490F0C14C00055E4E0 /* yahoo_with_comments.json in Resources */, + D380AFBF0F0C54B60009EC13 /* html.css in Resources */, + D380AFC00F0C54B60009EC13 /* html.grammar in Resources */, + D380AFC30F0C56000009EC13 /* example.html in Resources */, + D380B3230F0CC0800009EC13 /* nyt.html in Resources */, + D380B50A0F0D71B00009EC13 /* css.grammar in Resources */, + D380B5390F0D7DE30009EC13 /* css.css in Resources */, + D380B5950F0D82F90009EC13 /* example.css in Resources */, + D3FD79210F4CC87900BAD816 /* rubyhash.grammar in Resources */, + D31A15270F6DE449002AFDF1 /* javascript.grammar in Resources */, + D355C6A70FE9F704006A91A4 /* nspredicate.grammar in Resources */, + D3BBBCC10FECD477007DF30D /* xml.grammar in Resources */, + D315DF730FEF59B600D876C8 /* date.grammar in Resources */, + D34BAC9A0FF8A9AD00D7773A /* xpath1_0.grammar in Resources */, + D3668293101D2C000008632C /* erb.grammar in Resources */, + D319E42B106D8A1F008C63DD /* arithmetic.grammar in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1CA0F1965E600558235 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1FF0F196A7500558235 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F38F0F19800400558235 /* DefaultValues.plist in Resources */, + D389F4620F198A8800558235 /* Test.html in Resources */, + D389F5590F19B7BC00558235 /* JSDemoAppMainMenu.xib in Resources */, + D389FBCD0F1B25E200558235 /* ParserTest.html in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3C7D8750A411FBF005DD154 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3B473850E48C9CF008AFBDD /* yahoo.json in Resources */, + D3E784BD0E53DA28008C7D61 /* apple-boss.json in Resources */, + D36E9FB50E5A944A00496BD3 /* apple-boss.xml in Resources */, + D36E9FE50E5BA0FC00496BD3 /* SRGSGrammar.txt in Resources */, + D36EA3B00E5EA67E00496BD3 /* small-xml-file.xml in Resources */, + D3EADD800E75E9CC00F78584 /* nasty.html in Resources */, + D3B69D330E80249900D70C41 /* nonascii.html in Resources */, + D38DD9E80EC29F260070BC4D /* nyt.html in Resources */, + D3DCB4C30EF6015300DE5110 /* json.grammar in Resources */, + D3F741440EF8E96A00559B9F /* xpath1_0.grammar in Resources */, + D3F741BE0EF9F28D00559B9F /* css2_1.grammar in Resources */, + D3D01CAA0EFDB89900C24DDE /* json_with_discards.grammar in Resources */, + D385FA250F04993500DB2946 /* json.css in Resources */, + D385FD6D0F05A99900DB2946 /* mini_css.grammar in Resources */, + D3DDDCAD0F0880D800A58000 /* example1.srgs in Resources */, + D383498B0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */, + D38349BC0F0C0D910055E4E0 /* json_with_comments.css in Resources */, + D3834A480F0C14B60055E4E0 /* yahoo_with_comments.json in Resources */, + D380AFBD0F0C54B60009EC13 /* html.css in Resources */, + D380AFBE0F0C54B60009EC13 /* html.grammar in Resources */, + D380AFC40F0C56000009EC13 /* example.html in Resources */, + D380B5090F0D71A90009EC13 /* css.grammar in Resources */, + D380B5380F0D7DDE0009EC13 /* css.css in Resources */, + D380B5940F0D82F60009EC13 /* example.css in Resources */, + D3FD79200F4CC86800BAD816 /* rubyhash.grammar in Resources */, + D31A15260F6DE449002AFDF1 /* javascript.grammar in Resources */, + D35384ED0FE9691100926552 /* nspredicate.grammar in Resources */, + D353899C0FEAC94400926552 /* c.grammar in Resources */, + D353899E0FEAC96B00926552 /* objc.grammar in Resources */, + D355C8810FEB36A1006A91A4 /* xml.grammar in Resources */, + D355C8840FEB4B94006A91A4 /* proto.grammar in Resources */, + D315DF720FEF59B600D876C8 /* date.grammar in Resources */, + D3668292101D2BFA0008632C /* erb.grammar in Resources */, + D319E42A106D8A1F008C63DD /* arithmetic.grammar in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + D36C65E7100ED81B000361A0 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#cp -R -f \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\" ${HOME}/Library/Frameworks"; + }; + D3C7D8780A411FBF005DD154 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DC2EF540486A6940098B216 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36C55FF0FD3617B00141CB7 /* RegexKitLite.m in Sources */, + D34BAD9D0FF9C95800D7773A /* PKReader.m in Sources */, + D34BADA20FF9C9B000D7773A /* PKAssembly.m in Sources */, + D34BADD80FF9CBFB00D7773A /* PKParser.m in Sources */, + D34BAE030FF9CCAE00D7773A /* PKCollectionParser.m in Sources */, + D34BAE1D0FF9CE0E00D7773A /* PKAlternation.m in Sources */, + D34BAE1F0FF9CE0E00D7773A /* PKEmpty.m in Sources */, + D34BAE210FF9CE0E00D7773A /* PKDifference.m in Sources */, + D34BAE230FF9CE0E00D7773A /* PKIntersection.m in Sources */, + D34BAE250FF9CE0E00D7773A /* PKRepetition.m in Sources */, + D34BAE270FF9CE0E00D7773A /* PKSequence.m in Sources */, + D34BAE290FF9CE0E00D7773A /* PKTerminal.m in Sources */, + D34BAE2B0FF9CE0E00D7773A /* PKTrack.m in Sources */, + D34BAE2D0FF9CE0E00D7773A /* PKTrackException.m in Sources */, + D34BAE310FF9CE6000D7773A /* PKAny.m in Sources */, + D34BAE8D0FF9D15100D7773A /* PKTokenAssembly.m in Sources */, + D34BAE9D0FF9D20900D7773A /* PKToken.m in Sources */, + D34BAE9F0FF9D20900D7773A /* PKTokenArraySource.m in Sources */, + D34BAEA10FF9D20900D7773A /* PKTokenizer.m in Sources */, + D34BAEA30FF9D20900D7773A /* PKTokenizerState.m in Sources */, + D34BAED80FF9D56400D7773A /* PKCommentState.m in Sources */, + D34BAEDA0FF9D56400D7773A /* PKDelimitState.m in Sources */, + D34BAEDC0FF9D56400D7773A /* PKMultiLineCommentState.m in Sources */, + D34BAEDE0FF9D56400D7773A /* PKNumberState.m in Sources */, + D34BAEE00FF9D56400D7773A /* PKQuoteState.m in Sources */, + D34BAEE20FF9D56400D7773A /* PKSingleLineCommentState.m in Sources */, + D34BAEE40FF9D56400D7773A /* PKSymbolState.m in Sources */, + D34BAEE60FF9D56400D7773A /* PKWhitespaceState.m in Sources */, + D34BAEE80FF9D56400D7773A /* PKWord.m in Sources */, + D34BAEEA0FF9D56400D7773A /* PKWordState.m in Sources */, + D34BAF280FF9DF9900D7773A /* PKSymbolNode.m in Sources */, + D34BAF2A0FF9DF9900D7773A /* PKSymbolRootNode.m in Sources */, + D34BAF3A0FF9E18300D7773A /* PKPattern.m in Sources */, + D34BAF4C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m in Sources */, + D34BAF4E0FF9E19700D7773A /* PKComment.m in Sources */, + D34BAF500FF9E19700D7773A /* PKDelimitedString.m in Sources */, + D34BAF520FF9E19700D7773A /* PKLiteral.m in Sources */, + D34BAF540FF9E19700D7773A /* PKNumber.m in Sources */, + D34BAF560FF9E19700D7773A /* PKQuotedString.m in Sources */, + D34BAF580FF9E19700D7773A /* PKSymbol.m in Sources */, + D34BAF5A0FF9E19700D7773A /* PKWhitespace.m in Sources */, + D34BAF9D0FF9E6D100D7773A /* PKLowercaseWord.m in Sources */, + D34BAF9F0FF9E6D100D7773A /* PKUppercaseWord.m in Sources */, + D34BAFB20FF9E7F300D7773A /* PKCharacterAssembly.m in Sources */, + D34BAFBC0FF9E80300D7773A /* PKChar.m in Sources */, + D34BAFBE0FF9E80300D7773A /* PKDigit.m in Sources */, + D34BAFC00FF9E80300D7773A /* PKLetter.m in Sources */, + D34BAFC20FF9E80300D7773A /* PKSpecificChar.m in Sources */, + D34BAFDA0FF9E95500D7773A /* NSArray+ParseKitAdditions.m in Sources */, + D34BAFDC0FF9E95500D7773A /* NSString+ParseKitAdditions.m in Sources */, + D34BAFDE0FF9E95500D7773A /* PKParserFactory.m in Sources */, + D3126D060FFD9BA700CBF4C4 /* PKNegation.m in Sources */, + D3376D5A10093A1600E4602E /* PKGrammarParser.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D334940D0E2963FD00406085 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36E98E70E58C14000496BD3 /* DemoAppDelegate.m in Sources */, + D36E98E80E58C14000496BD3 /* main.m in Sources */, + D3F5629A10266CFC00DD6DB1 /* PKParseTreeView.m in Sources */, + D3F562A010266DFB00DD6DB1 /* DemoTokensViewController.m in Sources */, + D3F562A710266E8D00DD6DB1 /* DemoTreesViewController.m in Sources */, + D3305C4F102F5BAE00DC4F75 /* TDGutterView.m in Sources */, + D3305C50102F5BAE00DC4F75 /* TDSourceCodeTextView.m in Sources */, + D36934721038E28300527AF3 /* PKParseTree.m in Sources */, + D36934731038E28700527AF3 /* PKParseTreeAssembler.m in Sources */, + D36934741038E28B00527AF3 /* PKRuleNode.m in Sources */, + D36934751038E28F00527AF3 /* PKTokenNode.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D34185010E520D3F0081B0DC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36E98E20E58C12800496BD3 /* main.m in Sources */, + D36E98E00E58C12800496BD3 /* DebugAppDelegate.m in Sources */, + D3EADD8F0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */, + D31FE7420E60F40900A0803E /* XPathContext.m in Sources */, + D31FE7400E60F40300A0803E /* XPathAssembler.m in Sources */, + D31FE7340E60F34600A0803E /* XPathParser.m in Sources */, + D31FE7330E60F33C00A0803E /* XMLReader.m in Sources */, + D31FE7320E60F33000A0803E /* EBNFParser.m in Sources */, + D31FE7300E60F31E00A0803E /* TDFastJsonParser.m in Sources */, + D302C69D0EF044810090E714 /* TDPlistParser.m in Sources */, + D3F740B70EF8C38A00559B9F /* JSONAssembler.m in Sources */, + D385F98C0F046FE900DB2946 /* TDGenericAssembler.m in Sources */, + D385FD440F05A88C00DB2946 /* TDMiniCSSAssembler.m in Sources */, + D3DDDA870F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */, + D389F5B80F19C76A00558235 /* TDJsonParser.m in Sources */, + D31A16530F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */, + D3252F7E0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */, + D3385FDA0FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */, + D355C62E0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */, + D3BBBC9D0FEC9756007DF30D /* TDXMLParser.m in Sources */, + D3376D8F10096C0700E4602E /* PKAST.m in Sources */, + D319E42F106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1CB0F1965E600558235 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D34BB0690FF9EDDF00D7773A /* JSParseKit.m in Sources */, + D34BB0720FF9EE4000D7773A /* PKJSAssembly.m in Sources */, + D34BB0740FF9EE4000D7773A /* PKJSUtils.m in Sources */, + D34BB0770FF9EE4000D7773A /* PKJSValueHolder.m in Sources */, + D34BB0900FF9EF9D00D7773A /* PKJSCharacterAssembly.m in Sources */, + D34BB0AA0FF9F14B00D7773A /* PKJSCommentState.m in Sources */, + D34BB0AC0FF9F14B00D7773A /* PKJSDelimitState.m in Sources */, + D34BB0AE0FF9F14B00D7773A /* PKJSNumberState.m in Sources */, + D34BB0B00FF9F14B00D7773A /* PKJSQuoteState.m in Sources */, + D34BB0B20FF9F14B00D7773A /* PKJSSymbolState.m in Sources */, + D34BB0B40FF9F14B00D7773A /* PKJSToken.m in Sources */, + D34BB0B60FF9F14B00D7773A /* PKJSTokenAssembly.m in Sources */, + D34BB0B80FF9F14B00D7773A /* PKJSTokenizer.m in Sources */, + D34BB0BA0FF9F14B00D7773A /* PKJSTokenizerState.m in Sources */, + D34BB0BC0FF9F14B00D7773A /* PKJSWhitespaceState.m in Sources */, + D34BB0BE0FF9F14B00D7773A /* PKJSWordState.m in Sources */, + D34BB0E70FF9F28000D7773A /* PKJSAlternation.m in Sources */, + D34BB0E90FF9F28000D7773A /* PKJSAny.m in Sources */, + D34BB0EB0FF9F28000D7773A /* PKJSAssemblerAdapter.m in Sources */, + D34BB0ED0FF9F28000D7773A /* PKJSCollectionParser.m in Sources */, + D34BB0EF0FF9F28000D7773A /* PKJSEmpty.m in Sources */, + D34BB0F10FF9F28000D7773A /* PKJSParser.m in Sources */, + D34BB0F30FF9F28000D7773A /* PKJSRepetition.m in Sources */, + D34BB0F50FF9F28000D7773A /* PKJSSequence.m in Sources */, + D34BB0F70FF9F28000D7773A /* PKJSTerminal.m in Sources */, + D34BB0F90FF9F28000D7773A /* PKJSTrack.m in Sources */, + D34BB1150FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m in Sources */, + D34BB1170FF9F36200D7773A /* PKJSComment.m in Sources */, + D34BB1190FF9F36200D7773A /* PKJSDelimitedString.m in Sources */, + D34BB11B0FF9F36200D7773A /* PKJSLiteral.m in Sources */, + D34BB11D0FF9F36200D7773A /* PKJSLowercaseWord.m in Sources */, + D34BB11F0FF9F36200D7773A /* PKJSNum.m in Sources */, + D34BB1210FF9F36200D7773A /* PKJSPattern.m in Sources */, + D34BB1230FF9F36200D7773A /* PKJSQuotedString.m in Sources */, + D34BB1250FF9F36200D7773A /* PKJSSymbol.m in Sources */, + D34BB1270FF9F36200D7773A /* PKJSUppercaseWord.m in Sources */, + D34BB1290FF9F36200D7773A /* PKJSWord.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F2000F196A7500558235 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F2E40F196CAE00558235 /* main.m in Sources */, + D389F37A0F197E8000558235 /* JSDemoAppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3C7D8760A411FBF005DD154 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3E788930E567DFD008C7D61 /* SRGSParserTest.m in Sources */, + D3E788960E567E0A008C7D61 /* SRGSParser.m in Sources */, + D3E78A190E574C99008C7D61 /* EBNFParser.m in Sources */, + D3E78A1A0E574C99008C7D61 /* EBNFParserTest.m in Sources */, + D36E95460E578ECC00496BD3 /* XPathParser.m in Sources */, + D36E95D80E57B08400496BD3 /* XPathParserTest.m in Sources */, + D36E97B00E589DAE00496BD3 /* XPathAssembler.m in Sources */, + D36E98220E58A3A800496BD3 /* XPathContext.m in Sources */, + D3521F560E5FA1B0009681F9 /* XMLReader.m in Sources */, + D3521F570E5FA1B0009681F9 /* XMLReaderTest.m in Sources */, + D31FE54C0E60E46100A0803E /* TDTestScaffold.m in Sources */, + D31FE5630E60E50800A0803E /* TDAlternationTest.m in Sources */, + D31FE5640E60E50800A0803E /* TDLiteralTest.m in Sources */, + D31FE5650E60E50800A0803E /* TDParserTest.m in Sources */, + D31FE5660E60E50800A0803E /* TDRepetitionTest.m in Sources */, + D31FE5680E60E50800A0803E /* TDRobotCommandTest.m in Sources */, + D31FE5690E60E50800A0803E /* TDSequenceTest.m in Sources */, + D31FE56A0E60E50800A0803E /* TDSymbolTest.m in Sources */, + D31FE56B0E60E50800A0803E /* TDTokenAssemblyTest.m in Sources */, + D31FE56C0E60E50800A0803E /* TDTrackTest.m in Sources */, + D31FE56D0E60E50800A0803E /* TDUppercaseWordTest.m in Sources */, + D31FE5750E60E55700A0803E /* TDReaderTest.m in Sources */, + D31FE5760E60E55700A0803E /* TDTokenizerTest.m in Sources */, + D31FE5850E60E58C00A0803E /* TDNumberStateTest.m in Sources */, + D31FE5860E60E58C00A0803E /* TDQuoteStateTest.m in Sources */, + D31FE5890E60E58C00A0803E /* TDSymbolStateTest.m in Sources */, + D31FE58A0E60E58C00A0803E /* TDWhitespaceStateTest.m in Sources */, + D31FE58B0E60E58C00A0803E /* TDWordStateTest.m in Sources */, + D31FE5960E60E5AC00A0803E /* TDCharacterAssemblyTest.m in Sources */, + D31FE5970E60E5AC00A0803E /* TDCharTest.m in Sources */, + D31FE5980E60E5AC00A0803E /* TDDigitTest.m in Sources */, + D31FE5990E60E5AC00A0803E /* TDLetterTest.m in Sources */, + D31FE59A0E60E5AC00A0803E /* TDSpecificCharTest.m in Sources */, + D31FE59F0E60E5C000A0803E /* TDRegularParser.m in Sources */, + D31FE5A00E60E5C000A0803E /* TDRegularParserTest.m in Sources */, + D31FE5A90E60E5D500A0803E /* TDFastJsonParser.m in Sources */, + D31FE5AA0E60E5D500A0803E /* TDFastJsonParserTest.m in Sources */, + D31FE5B10E60E64900A0803E /* TDXmlTokenAssembly.m in Sources */, + D31FE5B20E60E64900A0803E /* TDXmlTokenizerTest.m in Sources */, + D31FE5B70E60E66600A0803E /* TDXmlToken.m in Sources */, + D31FE5B80E60E66600A0803E /* TDXmlTokenizer.m in Sources */, + D31FE5DD0E60E69E00A0803E /* TDXmlAttribute.m in Sources */, + D31FE5DE0E60E69E00A0803E /* TDXmlCdata.m in Sources */, + D31FE5DF0E60E69E00A0803E /* TDXmlComment.m in Sources */, + D31FE5E00E60E69E00A0803E /* TDXmlDecl.m in Sources */, + D31FE5E10E60E69E00A0803E /* TDXmlDoctype.m in Sources */, + D31FE5E20E60E69E00A0803E /* TDXmlDocument.m in Sources */, + D31FE5E30E60E69E00A0803E /* TDXmlEndEntity.m in Sources */, + D31FE5E40E60E69E00A0803E /* TDXmlEndTag.m in Sources */, + D31FE5E50E60E69E00A0803E /* TDXmlEntity.m in Sources */, + D31FE5E60E60E69E00A0803E /* TDXmlEntityRef.m in Sources */, + D31FE5E70E60E69E00A0803E /* TDXmlFragment.m in Sources */, + D31FE5E80E60E69E00A0803E /* TDXmlNotation.m in Sources */, + D31FE5E90E60E69E00A0803E /* TDXmlProcessingInstruction.m in Sources */, + D31FE5EA0E60E69E00A0803E /* TDXmlSignificantWhitespace.m in Sources */, + D31FE5EB0E60E69E00A0803E /* TDXmlStartTag.m in Sources */, + D31FE5EC0E60E69E00A0803E /* TDXmlTerminal.m in Sources */, + D31FE5ED0E60E69E00A0803E /* TDXmlText.m in Sources */, + D31FE5EE0E60E69E00A0803E /* TDXmlWhitespace.m in Sources */, + D31FE5FC0E60E6B500A0803E /* TDNCNameState.m in Sources */, + D31FE5FD0E60E6B500A0803E /* TDXmlName.m in Sources */, + D31FE5FE0E60E6B500A0803E /* TDXmlNameState.m in Sources */, + D31FE5FF0E60E6B500A0803E /* TDXmlNameTest.m in Sources */, + D31FE6000E60E6B500A0803E /* TDXmlNmtoken.m in Sources */, + D31FE6010E60E6B500A0803E /* TDXmlNmtokenState.m in Sources */, + D31FE6E00E60EE2500A0803E /* TDNCName.m in Sources */, + D3C85C7B0E63B438000445FD /* TDArithmeticParser.m in Sources */, + D3C85C800E63B9E9000445FD /* TDArithmeticParserTest.m in Sources */, + D3C85D450E63D1BF000445FD /* TDScientificNumberStateTest.m in Sources */, + D3EADD8E0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */, + D38205BE0EEE48EE004340DD /* TDTokenTest.m in Sources */, + D36568A70EEF9FE900226554 /* TDPlistParser.m in Sources */, + D36568AA0EEFA05300226554 /* TDPlistParserTest.m in Sources */, + D3656DFE0EF2620E00226554 /* TDTokenArraySourceTest.m in Sources */, + D3C031ED0EF38D2D00C5ABEB /* TDLowercaseWordTest.m in Sources */, + D385F98E0F046FE900DB2946 /* TDGenericAssembler.m in Sources */, + D385FA230F04971400DB2946 /* TDGenericAssemblerTest.m in Sources */, + D385FD460F05A89100DB2946 /* TDMiniCSSAssemblerTest.m in Sources */, + D385FD490F05A8C900DB2946 /* TDMiniCSSAssembler.m in Sources */, + D3DDDA880F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */, + D3DDDAFE0F083C9700A58000 /* TDCommentStateTest.m in Sources */, + D380BA620F0F06CD0009EC13 /* TDParserFactoryTest.m in Sources */, + D389F5B60F19C76A00558235 /* TDJsonParser.m in Sources */, + D389F5B70F19C76A00558235 /* TDJsonParserTest.m in Sources */, + D31A16520F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */, + D3B43FB80F76E99C0072AF40 /* TDJavaScriptParserTest.m in Sources */, + D3E39C3F0FC5FFD10022DAB9 /* TDDelimitStateTest.m in Sources */, + D3252F7B0FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m in Sources */, + D3252F7F0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */, + D3385FD90FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */, + D3385FDE0FCFB227003BF729 /* TDPredicateEvaluatorTest.m in Sources */, + D36C53790FD27F1300141CB7 /* TDParserFactoryTest2.m in Sources */, + D36C562B0FD365DB00141CB7 /* TDPatternTest.m in Sources */, + D3AF49780FDB122E0032F4DC /* TDParserFactoryPatternTest.m in Sources */, + D355C62D0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */, + D355C6310FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m in Sources */, + D3BBBC9E0FEC9756007DF30D /* TDXMLParser.m in Sources */, + D39E01340FEF02DA00150FC3 /* TDXMLParserTest.m in Sources */, + D338E5BB0FF5DDCB003DE6AA /* TDDifferenceTest.m in Sources */, + D34BAC230FF87F8600D7773A /* TDParserFactoryTest3.m in Sources */, + D34BAC4B0FF892C200D7773A /* XPathParserGrammarTest.m in Sources */, + D3126D0B0FFD9E4B00CBF4C4 /* TDNegationTest.m in Sources */, + D3376D8E10096C0700E4602E /* PKAST.m in Sources */, + D34BAD18100A9B7900996341 /* TDTokenizerStateTest.m in Sources */, + D3668296101D2C200008632C /* ERBTest.m in Sources */, + D3F55F611025737D00DD6DB1 /* TDParseTreeTest.m in Sources */, + D369345D1038DE5300527AF3 /* PKParseTree.m in Sources */, + D369345E1038DE5300527AF3 /* PKParseTreeAssembler.m in Sources */, + D369345F1038DE5300527AF3 /* PKRuleNode.m in Sources */, + D36934601038DE5300527AF3 /* PKTokenNode.m in Sources */, + D3D1BF2810394420003656E5 /* SAXAssembler.m in Sources */, + D3D1BF2B1039445C003656E5 /* SAXTest.m in Sources */, + D38E97CC1061CF6500739C39 /* TDTokenizerBlocksTest.m in Sources */, + D38E98D81062C5BA00739C39 /* TDParserBlocksTest.m in Sources */, + D319E42E106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3FDC5800FFC4BFC00F1F797 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3FDC6EE0FFC4C9E00F1F797 /* RegexKitLite.m in Sources */, + D3FDC6EF0FFC4C9E00F1F797 /* PKReader.m in Sources */, + D3FDC6F00FFC4C9E00F1F797 /* PKAssembly.m in Sources */, + D3FDC6F10FFC4C9E00F1F797 /* PKParser.m in Sources */, + D3FDC6F20FFC4C9E00F1F797 /* PKRepetition.m in Sources */, + D3FDC6F30FFC4C9E00F1F797 /* PKCollectionParser.m in Sources */, + D3FDC6F40FFC4C9E00F1F797 /* PKAlternation.m in Sources */, + D3FDC6F50FFC4C9E00F1F797 /* PKSequence.m in Sources */, + D3FDC6F60FFC4C9E00F1F797 /* PKTrack.m in Sources */, + D3FDC6F70FFC4C9E00F1F797 /* PKTrackException.m in Sources */, + D3FDC6F80FFC4C9E00F1F797 /* PKDifference.m in Sources */, + D3FDC6F90FFC4C9E00F1F797 /* PKIntersection.m in Sources */, + D3FDC6FA0FFC4C9E00F1F797 /* PKTerminal.m in Sources */, + D3FDC6FB0FFC4C9E00F1F797 /* PKEmpty.m in Sources */, + D3FDC6FC0FFC4C9E00F1F797 /* PKTokenAssembly.m in Sources */, + D3FDC6FD0FFC4C9E00F1F797 /* PKToken.m in Sources */, + D3FDC6FE0FFC4C9E00F1F797 /* PKTokenArraySource.m in Sources */, + D3FDC6FF0FFC4C9E00F1F797 /* PKTokenizer.m in Sources */, + D3FDC7000FFC4C9E00F1F797 /* PKTokenizerState.m in Sources */, + D3FDC7010FFC4C9E00F1F797 /* PKNumberState.m in Sources */, + D3FDC7020FFC4C9E00F1F797 /* PKQuoteState.m in Sources */, + D3FDC7030FFC4C9E00F1F797 /* PKSymbolState.m in Sources */, + D3FDC7040FFC4C9E00F1F797 /* PKWordState.m in Sources */, + D3FDC7050FFC4C9E00F1F797 /* PKWhitespaceState.m in Sources */, + D3FDC7060FFC4C9E00F1F797 /* PKDelimitState.m in Sources */, + D3FDC7070FFC4C9E00F1F797 /* PKCommentState.m in Sources */, + D3FDC7080FFC4C9E00F1F797 /* PKSingleLineCommentState.m in Sources */, + D3FDC7090FFC4C9E00F1F797 /* PKMultiLineCommentState.m in Sources */, + D3FDC70A0FFC4C9E00F1F797 /* PKSymbolNode.m in Sources */, + D3FDC70B0FFC4C9E00F1F797 /* PKSymbolRootNode.m in Sources */, + D3FDC70C0FFC4C9E00F1F797 /* PKPattern.m in Sources */, + D3FDC70D0FFC4C9E00F1F797 /* PKWord.m in Sources */, + D3FDC70F0FFC4C9E00F1F797 /* PKQuotedString.m in Sources */, + D3FDC7100FFC4C9E00F1F797 /* PKSymbol.m in Sources */, + D3FDC7110FFC4C9E00F1F797 /* PKLiteral.m in Sources */, + D3FDC7120FFC4C9E00F1F797 /* PKCaseInsensitiveLiteral.m in Sources */, + D3FDC7130FFC4C9E00F1F797 /* PKWhitespace.m in Sources */, + D3FDC7140FFC4C9E00F1F797 /* PKComment.m in Sources */, + D3FDC7150FFC4C9E00F1F797 /* PKDelimitedString.m in Sources */, + D3FDC7160FFC4C9E00F1F797 /* PKAny.m in Sources */, + D3FDC7180FFC4C9E00F1F797 /* PKLowercaseWord.m in Sources */, + D3FDC7190FFC4C9E00F1F797 /* PKUppercaseWord.m in Sources */, + D3FDC71A0FFC4C9E00F1F797 /* PKCharacterAssembly.m in Sources */, + D3FDC71B0FFC4C9E00F1F797 /* PKChar.m in Sources */, + D3FDC71C0FFC4C9E00F1F797 /* PKDigit.m in Sources */, + D3FDC71D0FFC4C9E00F1F797 /* PKLetter.m in Sources */, + D3FDC71E0FFC4C9E00F1F797 /* PKSpecificChar.m in Sources */, + D3FDC71F0FFC4C9E00F1F797 /* PKParserFactory.m in Sources */, + D3FDC7200FFC4C9E00F1F797 /* NSArray+ParseKitAdditions.m in Sources */, + D3FDC7210FFC4C9E00F1F797 /* NSString+ParseKitAdditions.m in Sources */, + D3126DEC0FFDBC1D00CBF4C4 /* PKNegation.m in Sources */, + D3F0E3CC0FFEB70700C9DF74 /* PKNumber.m in Sources */, + D37A28671013942300E936B7 /* PKGrammarParser.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + D31FE7180E60F24700A0803E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D31FE7170E60F24700A0803E /* PBXContainerItemProxy */; + }; + D33494A00E296AA900406085 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D334949F0E296AA900406085 /* PBXContainerItemProxy */; + }; + D34185100E520D6F0081B0DC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D341850F0E520D6F0081B0DC /* PBXContainerItemProxy */; + }; + D389F1D40F19665C00558235 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D389F1D30F19665C00558235 /* PBXContainerItemProxy */; + }; + D389F20A0F196A8000558235 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D389F1CD0F1965E600558235 /* JSParseKit */; + targetProxy = D389F2090F196A8000558235 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 089C1667FE841158C02AAC07 /* English */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1DEB91AE08733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_TEST_COVERAGE_FILES = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKit_Prefix.pch; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GENERATE_PROFILING_CODE = YES; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(TARGET_BUILD_DIR)"; + LLVM_LTO = NO; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + ); + PRODUCT_NAME = ParseKit; + SDKROOT = ""; + WARNING_CFLAGS = "-Wundeclared-selector"; + WRAPPER_EXTENSION = framework; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB91AF08733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "$(TDPARSEKIT_FRAMEWORK_TARGET_PATH)"; + FRAMEWORK_VERSION = A; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKit_Prefix.pch; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvmgcc42; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(TARGET_BUILD_DIR)"; + LLVM_LTO = YES; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + ); + PRODUCT_NAME = ParseKit; + SDKROOT = ""; + TDPARSEKIT_FRAMEWORK_TARGET_PATH = "@executable_path/../Frameworks"; + WARNING_CFLAGS = "-Wundeclared-selector"; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; + 1DEB91B208733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Debug; + }; + 1DEB91B308733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Release; + }; + D33494130E2963FE00406085 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "demoapp/DemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DemoApp; + SDKROOT = ""; + WRAPPER_EXTENSION = app; + ZERO_LINK = YES; + }; + name = Debug; + }; + D33494140E2963FE00406085 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "demoapp/DemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DemoApp; + SDKROOT = ""; + WRAPPER_EXTENSION = app; + ZERO_LINK = NO; + }; + name = Release; + }; + D34185070E520D410081B0DC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/frameworks\""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_WARN_UNUSED_VARIABLE = NO; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "debugapp/DebugApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DebugApp; + SDKROOT = ""; + }; + name = Debug; + }; + D34185080E520D410081B0DC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/frameworks\""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "debugapp/DebugApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DebugApp; + SDKROOT = ""; + ZERO_LINK = NO; + }; + name = Release; + }; + D389F1D00F1965E800558235 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + INFOPLIST_FILE = "JSParseKit-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Frameworks"; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSParseKit; + SDKROOT = ""; + }; + name = Debug; + }; + D389F1D10F1965E800558235 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_GC = YES; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + INFOPLIST_FILE = "JSParseKit-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Frameworks"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSParseKit; + SDKROOT = ""; + ZERO_LINK = NO; + }; + name = Release; + }; + D389F2060F196A7600558235 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = required; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "jsdemoapp/JSDemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSDemoApp; + SDKROOT = ""; + }; + name = Debug; + }; + D389F2070F196A7600558235 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_GC = required; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "jsdemoapp/JSDemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSDemoApp; + SDKROOT = ""; + ZERO_LINK = NO; + }; + name = Release; + }; + D3C7D87D0A411FC0005DD154 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/frameworks\""; + FRAMEWORK_SEARCH_PATH_DEBUG_BUILD = "\"$(SRCROOT)/build/Debug\""; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "test/Tests-Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; + LIBRARY_SEARCH_PATHS = ""; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + MACOSX_DEPLOYMENT_TARGET = 10.5; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + SenTestingKit, + ); + PREBINDING = NO; + PRODUCT_NAME = Tests; + SDKROOT = ""; + USER_HEADER_SEARCH_PATHS = ""; + WARNING_CFLAGS = ""; + WRAPPER_EXTENSION = octest; + ZERO_LINK = YES; + }; + name = Debug; + }; + D3C7D87E0A411FC0005DD154 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"/Library/Frameworks\""; + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/frameworks\""; + GCC_C_LANGUAGE_STANDARD = "compiler-default"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "test/Tests-Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + SenTestingKit, + ); + PREBINDING = NO; + PRODUCT_NAME = Tests; + SDKROOT = ""; + WARNING_CFLAGS = ""; + WRAPPER_EXTENSION = octest; + ZERO_LINK = NO; + }; + name = Release; + }; + D3FDC5840FFC4BFC00F1F797 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKitMobile_Prefix.pch; + HEADER_SEARCH_PATHS = ""; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + PRODUCT_NAME = parsekit; + SDKROOT = iphoneos3.0; + }; + name = Debug; + }; + D3FDC5850FFC4BFC00F1F797 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + EXECUTABLE_PREFIX = ""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKitMobile_Prefix.pch; + HEADER_SEARCH_PATHS = ""; + OTHER_LDFLAGS = ""; + PREBINDING = NO; + PRODUCT_NAME = parsekit; + SDKROOT = iphoneos3.0; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "ParseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91AE08733DA50010E9CD /* Debug */, + 1DEB91AF08733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ParseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91B208733DA50010E9CD /* Debug */, + 1DEB91B308733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D33494150E2963FE00406085 /* Build configuration list for PBXNativeTarget "DemoApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D33494130E2963FE00406085 /* Debug */, + D33494140E2963FE00406085 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D34185090E520D410081B0DC /* Build configuration list for PBXNativeTarget "DebugApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D34185070E520D410081B0DC /* Debug */, + D34185080E520D410081B0DC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D389F1D20F1965E800558235 /* Build configuration list for PBXNativeTarget "JSParseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D389F1D00F1965E800558235 /* Debug */, + D389F1D10F1965E800558235 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D389F2080F196A7600558235 /* Build configuration list for PBXNativeTarget "JSDemoApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D389F2060F196A7600558235 /* Debug */, + D389F2070F196A7600558235 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D3C7D87C0A411FC0005DD154 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D3C7D87D0A411FC0005DD154 /* Debug */, + D3C7D87E0A411FC0005DD154 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D3FDC62F0FFC4C2000F1F797 /* Build configuration list for PBXNativeTarget "ParseKitMobile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D3FDC5840FFC4BFC00F1F797 /* Debug */, + D3FDC5850FFC4BFC00F1F797 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0867D690FE84028FC02AAC07 /* Project object */; +} diff --git a/ParseKit.xcodeproj/.svn/tmp/project.pbxproj.tmp b/ParseKit.xcodeproj/.svn/tmp/project.pbxproj.tmp new file mode 100644 index 0000000..382638b --- /dev/null +++ b/ParseKit.xcodeproj/.svn/tmp/project.pbxproj.tmp @@ -0,0 +1,3720 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; }; + D302C69D0EF044810090E714 /* TDPlistParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36568A60EEF9FE900226554 /* TDPlistParser.m */; }; + D3126D060FFD9BA700CBF4C4 /* PKNegation.m in Sources */ = {isa = PBXBuildFile; fileRef = D3126D040FFD9BA700CBF4C4 /* PKNegation.m */; }; + D3126D0B0FFD9E4B00CBF4C4 /* TDNegationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3126D0A0FFD9E4B00CBF4C4 /* TDNegationTest.m */; }; + D3126DEC0FFDBC1D00CBF4C4 /* PKNegation.m in Sources */ = {isa = PBXBuildFile; fileRef = D3126D040FFD9BA700CBF4C4 /* PKNegation.m */; }; + D315DF720FEF59B600D876C8 /* date.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D315DF710FEF59B600D876C8 /* date.grammar */; }; + D315DF730FEF59B600D876C8 /* date.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D315DF710FEF59B600D876C8 /* date.grammar */; }; + D319E42A106D8A1F008C63DD /* arithmetic.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D319E429106D8A1F008C63DD /* arithmetic.grammar */; }; + D319E42B106D8A1F008C63DD /* arithmetic.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D319E429106D8A1F008C63DD /* arithmetic.grammar */; }; + D319E42E106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */; }; + D319E42F106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */; }; + D31A15260F6DE449002AFDF1 /* javascript.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D31A15250F6DE449002AFDF1 /* javascript.grammar */; }; + D31A15270F6DE449002AFDF1 /* javascript.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D31A15250F6DE449002AFDF1 /* javascript.grammar */; }; + D31A16520F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */; }; + D31A16530F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */; }; + D31FE54C0E60E46100A0803E /* TDTestScaffold.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE54B0E60E46100A0803E /* TDTestScaffold.m */; }; + D31FE5630E60E50800A0803E /* TDAlternationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE54E0E60E50800A0803E /* TDAlternationTest.m */; }; + D31FE5640E60E50800A0803E /* TDLiteralTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5500E60E50800A0803E /* TDLiteralTest.m */; }; + D31FE5650E60E50800A0803E /* TDParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5520E60E50800A0803E /* TDParserTest.m */; }; + D31FE5660E60E50800A0803E /* TDRepetitionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5540E60E50800A0803E /* TDRepetitionTest.m */; }; + D31FE5680E60E50800A0803E /* TDRobotCommandTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5580E60E50800A0803E /* TDRobotCommandTest.m */; }; + D31FE5690E60E50800A0803E /* TDSequenceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE55A0E60E50800A0803E /* TDSequenceTest.m */; }; + D31FE56A0E60E50800A0803E /* TDSymbolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE55C0E60E50800A0803E /* TDSymbolTest.m */; }; + D31FE56B0E60E50800A0803E /* TDTokenAssemblyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE55E0E60E50800A0803E /* TDTokenAssemblyTest.m */; }; + D31FE56C0E60E50800A0803E /* TDTrackTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5600E60E50800A0803E /* TDTrackTest.m */; }; + D31FE56D0E60E50800A0803E /* TDUppercaseWordTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5620E60E50800A0803E /* TDUppercaseWordTest.m */; }; + D31FE5750E60E55700A0803E /* TDReaderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5720E60E55700A0803E /* TDReaderTest.m */; }; + D31FE5760E60E55700A0803E /* TDTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5740E60E55700A0803E /* TDTokenizerTest.m */; }; + D31FE5850E60E58C00A0803E /* TDNumberStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5780E60E58C00A0803E /* TDNumberStateTest.m */; }; + D31FE5860E60E58C00A0803E /* TDQuoteStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE57A0E60E58C00A0803E /* TDQuoteStateTest.m */; }; + D31FE5890E60E58C00A0803E /* TDSymbolStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5800E60E58C00A0803E /* TDSymbolStateTest.m */; }; + D31FE58A0E60E58C00A0803E /* TDWhitespaceStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5820E60E58C00A0803E /* TDWhitespaceStateTest.m */; }; + D31FE58B0E60E58C00A0803E /* TDWordStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5840E60E58C00A0803E /* TDWordStateTest.m */; }; + D31FE5960E60E5AC00A0803E /* TDCharacterAssemblyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE58D0E60E5AC00A0803E /* TDCharacterAssemblyTest.m */; }; + D31FE5970E60E5AC00A0803E /* TDCharTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE58F0E60E5AC00A0803E /* TDCharTest.m */; }; + D31FE5980E60E5AC00A0803E /* TDDigitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5910E60E5AC00A0803E /* TDDigitTest.m */; }; + D31FE5990E60E5AC00A0803E /* TDLetterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5930E60E5AC00A0803E /* TDLetterTest.m */; }; + D31FE59A0E60E5AC00A0803E /* TDSpecificCharTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5950E60E5AC00A0803E /* TDSpecificCharTest.m */; }; + D31FE59F0E60E5C000A0803E /* TDRegularParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE59C0E60E5C000A0803E /* TDRegularParser.m */; }; + D31FE5A00E60E5C000A0803E /* TDRegularParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE59E0E60E5C000A0803E /* TDRegularParserTest.m */; }; + D31FE5A90E60E5D500A0803E /* TDFastJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */; }; + D31FE5AA0E60E5D500A0803E /* TDFastJsonParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5A40E60E5D500A0803E /* TDFastJsonParserTest.m */; }; + D31FE5B10E60E64900A0803E /* TDXmlTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5AE0E60E64900A0803E /* TDXmlTokenAssembly.m */; }; + D31FE5B20E60E64900A0803E /* TDXmlTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5B00E60E64900A0803E /* TDXmlTokenizerTest.m */; }; + D31FE5B70E60E66600A0803E /* TDXmlToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5B40E60E66600A0803E /* TDXmlToken.m */; }; + D31FE5B80E60E66600A0803E /* TDXmlTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5B60E60E66600A0803E /* TDXmlTokenizer.m */; }; + D31FE5DD0E60E69E00A0803E /* TDXmlAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5BA0E60E69E00A0803E /* TDXmlAttribute.m */; }; + D31FE5DE0E60E69E00A0803E /* TDXmlCdata.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5BC0E60E69E00A0803E /* TDXmlCdata.m */; }; + D31FE5DF0E60E69E00A0803E /* TDXmlComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5BE0E60E69E00A0803E /* TDXmlComment.m */; }; + D31FE5E00E60E69E00A0803E /* TDXmlDecl.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C00E60E69E00A0803E /* TDXmlDecl.m */; }; + D31FE5E10E60E69E00A0803E /* TDXmlDoctype.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C20E60E69E00A0803E /* TDXmlDoctype.m */; }; + D31FE5E20E60E69E00A0803E /* TDXmlDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C40E60E69E00A0803E /* TDXmlDocument.m */; }; + D31FE5E30E60E69E00A0803E /* TDXmlEndEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C60E60E69E00A0803E /* TDXmlEndEntity.m */; }; + D31FE5E40E60E69E00A0803E /* TDXmlEndTag.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C80E60E69E00A0803E /* TDXmlEndTag.m */; }; + D31FE5E50E60E69E00A0803E /* TDXmlEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5CA0E60E69E00A0803E /* TDXmlEntity.m */; }; + D31FE5E60E60E69E00A0803E /* TDXmlEntityRef.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5CC0E60E69E00A0803E /* TDXmlEntityRef.m */; }; + D31FE5E70E60E69E00A0803E /* TDXmlFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5CE0E60E69E00A0803E /* TDXmlFragment.m */; }; + D31FE5E80E60E69E00A0803E /* TDXmlNotation.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D00E60E69E00A0803E /* TDXmlNotation.m */; }; + D31FE5E90E60E69E00A0803E /* TDXmlProcessingInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D20E60E69E00A0803E /* TDXmlProcessingInstruction.m */; }; + D31FE5EA0E60E69E00A0803E /* TDXmlSignificantWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D40E60E69E00A0803E /* TDXmlSignificantWhitespace.m */; }; + D31FE5EB0E60E69E00A0803E /* TDXmlStartTag.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D60E60E69E00A0803E /* TDXmlStartTag.m */; }; + D31FE5EC0E60E69E00A0803E /* TDXmlTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D80E60E69E00A0803E /* TDXmlTerminal.m */; }; + D31FE5ED0E60E69E00A0803E /* TDXmlText.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5DA0E60E69E00A0803E /* TDXmlText.m */; }; + D31FE5EE0E60E69E00A0803E /* TDXmlWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5DC0E60E69E00A0803E /* TDXmlWhitespace.m */; }; + D31FE5FC0E60E6B500A0803E /* TDNCNameState.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F10E60E6B500A0803E /* TDNCNameState.m */; }; + D31FE5FD0E60E6B500A0803E /* TDXmlName.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F30E60E6B500A0803E /* TDXmlName.m */; }; + D31FE5FE0E60E6B500A0803E /* TDXmlNameState.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F50E60E6B500A0803E /* TDXmlNameState.m */; }; + D31FE5FF0E60E6B500A0803E /* TDXmlNameTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F70E60E6B500A0803E /* TDXmlNameTest.m */; }; + D31FE6000E60E6B500A0803E /* TDXmlNmtoken.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F90E60E6B500A0803E /* TDXmlNmtoken.m */; }; + D31FE6010E60E6B500A0803E /* TDXmlNmtokenState.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5FB0E60E6B500A0803E /* TDXmlNmtokenState.m */; }; + D31FE6E00E60EE2500A0803E /* TDNCName.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE6DF0E60EE2500A0803E /* TDNCName.m */; }; + D31FE7300E60F31E00A0803E /* TDFastJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */; }; + D31FE7320E60F33000A0803E /* EBNFParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E78A160E574C99008C7D61 /* EBNFParser.m */; }; + D31FE7330E60F33C00A0803E /* XMLReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D3521F530E5FA1B0009681F9 /* XMLReader.m */; }; + D31FE7340E60F34600A0803E /* XPathParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E95450E578ECC00496BD3 /* XPathParser.m */; }; + D31FE7380E60F36600A0803E /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D36E9F860E5A795400496BD3 /* libxml2.dylib */; }; + D31FE7400E60F40300A0803E /* XPathAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */; }; + D31FE7420E60F40900A0803E /* XPathContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98210E58A3A800496BD3 /* XPathContext.m */; }; + D3252F7B0FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3252F790FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m */; }; + D3252F7E0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */; }; + D3252F7F0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */; }; + D3305C4F102F5BAE00DC4F75 /* TDGutterView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3305C4C102F5BAD00DC4F75 /* TDGutterView.m */; }; + D3305C50102F5BAE00DC4F75 /* TDSourceCodeTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3305C4E102F5BAE00DC4F75 /* TDSourceCodeTextView.m */; }; + D33494720E29670B00406085 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D3376D5910093A1600E4602E /* PKGrammarParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3376D5710093A1600E4602E /* PKGrammarParser.h */; }; + D3376D5A10093A1600E4602E /* PKGrammarParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D5810093A1600E4602E /* PKGrammarParser.m */; }; + D3376D8E10096C0700E4602E /* PKAST.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D8D10096C0700E4602E /* PKAST.m */; }; + D3376D8F10096C0700E4602E /* PKAST.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D8D10096C0700E4602E /* PKAST.m */; }; + D3385FD90FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */; }; + D3385FDA0FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */; }; + D3385FDE0FCFB227003BF729 /* TDPredicateEvaluatorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3385FDC0FCFB227003BF729 /* TDPredicateEvaluatorTest.m */; }; + D338E5BB0FF5DDCB003DE6AA /* TDDifferenceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D338E5BA0FF5DDCB003DE6AA /* TDDifferenceTest.m */; }; + D341850C0E520D640081B0DC /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D34BAC230FF87F8600D7773A /* TDParserFactoryTest3.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAC220FF87F8600D7773A /* TDParserFactoryTest3.m */; }; + D34BAC4B0FF892C200D7773A /* XPathParserGrammarTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAC4A0FF892C200D7773A /* XPathParserGrammarTest.m */; }; + D34BAC9A0FF8A9AD00D7773A /* xpath1_0.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741430EF8E96A00559B9F /* xpath1_0.grammar */; }; + D34BAD18100A9B7900996341 /* TDTokenizerStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAD17100A9B7900996341 /* TDTokenizerStateTest.m */; }; + D34BAD640FF9C6AE00D7773A /* ParseKit_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = D34BAD630FF9C6AE00D7773A /* ParseKit_Prefix.pch */; }; + D34BAD9D0FF9C95800D7773A /* PKReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAD9B0FF9C95800D7773A /* PKReader.m */; }; + D34BADA20FF9C9B000D7773A /* PKAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADA00FF9C9B000D7773A /* PKAssembly.m */; }; + D34BADD80FF9CBFB00D7773A /* PKParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADD60FF9CBFB00D7773A /* PKParser.m */; }; + D34BAE030FF9CCAE00D7773A /* PKCollectionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */; }; + D34BAE1D0FF9CE0E00D7773A /* PKAlternation.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */; }; + D34BAE1F0FF9CE0E00D7773A /* PKEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */; }; + D34BAE210FF9CE0E00D7773A /* PKDifference.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */; }; + D34BAE230FF9CE0E00D7773A /* PKIntersection.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE110FF9CE0E00D7773A /* PKIntersection.m */; }; + D34BAE250FF9CE0E00D7773A /* PKRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE130FF9CE0E00D7773A /* PKRepetition.m */; }; + D34BAE270FF9CE0E00D7773A /* PKSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE150FF9CE0E00D7773A /* PKSequence.m */; }; + D34BAE290FF9CE0E00D7773A /* PKTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE170FF9CE0E00D7773A /* PKTerminal.m */; }; + D34BAE2B0FF9CE0E00D7773A /* PKTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE190FF9CE0E00D7773A /* PKTrack.m */; }; + D34BAE2D0FF9CE0E00D7773A /* PKTrackException.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */; }; + D34BAE310FF9CE6000D7773A /* PKAny.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE2F0FF9CE6000D7773A /* PKAny.m */; }; + D34BAE8D0FF9D15100D7773A /* PKTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */; }; + D34BAE9D0FF9D20900D7773A /* PKToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE950FF9D20900D7773A /* PKToken.m */; }; + D34BAE9F0FF9D20900D7773A /* PKTokenArraySource.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */; }; + D34BAEA10FF9D20900D7773A /* PKTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE990FF9D20900D7773A /* PKTokenizer.m */; }; + D34BAEA30FF9D20900D7773A /* PKTokenizerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */; }; + D34BAED80FF9D56400D7773A /* PKCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC40FF9D56400D7773A /* PKCommentState.m */; }; + D34BAEDA0FF9D56400D7773A /* PKDelimitState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC60FF9D56400D7773A /* PKDelimitState.m */; }; + D34BAEDC0FF9D56400D7773A /* PKMultiLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */; }; + D34BAEDE0FF9D56400D7773A /* PKNumberState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECA0FF9D56400D7773A /* PKNumberState.m */; }; + D34BAEE00FF9D56400D7773A /* PKQuoteState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECC0FF9D56400D7773A /* PKQuoteState.m */; }; + D34BAEE20FF9D56400D7773A /* PKSingleLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */; }; + D34BAEE40FF9D56400D7773A /* PKSymbolState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED00FF9D56400D7773A /* PKSymbolState.m */; }; + D34BAEE60FF9D56400D7773A /* PKWhitespaceState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */; }; + D34BAEE80FF9D56400D7773A /* PKWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED40FF9D56400D7773A /* PKWord.m */; }; + D34BAEEA0FF9D56400D7773A /* PKWordState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED60FF9D56400D7773A /* PKWordState.m */; }; + D34BAF280FF9DF9900D7773A /* PKSymbolNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */; }; + D34BAF2A0FF9DF9900D7773A /* PKSymbolRootNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */; }; + D34BAF3A0FF9E18300D7773A /* PKPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF380FF9E18300D7773A /* PKPattern.m */; }; + D34BAF4C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */; }; + D34BAF4E0FF9E19700D7773A /* PKComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3E0FF9E19700D7773A /* PKComment.m */; }; + D34BAF500FF9E19700D7773A /* PKDelimitedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF400FF9E19700D7773A /* PKDelimitedString.m */; }; + D34BAF520FF9E19700D7773A /* PKLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF420FF9E19700D7773A /* PKLiteral.m */; }; + D34BAF540FF9E19700D7773A /* PKNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF440FF9E19700D7773A /* PKNumber.m */; }; + D34BAF560FF9E19700D7773A /* PKQuotedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF460FF9E19700D7773A /* PKQuotedString.m */; }; + D34BAF580FF9E19700D7773A /* PKSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF480FF9E19700D7773A /* PKSymbol.m */; }; + D34BAF5A0FF9E19700D7773A /* PKWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */; }; + D34BAF9D0FF9E6D100D7773A /* PKLowercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */; }; + D34BAF9F0FF9E6D100D7773A /* PKUppercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */; }; + D34BAFB20FF9E7F300D7773A /* PKCharacterAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */; }; + D34BAFBC0FF9E80300D7773A /* PKChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB40FF9E80300D7773A /* PKChar.m */; }; + D34BAFBE0FF9E80300D7773A /* PKDigit.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB60FF9E80300D7773A /* PKDigit.m */; }; + D34BAFC00FF9E80300D7773A /* PKLetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB80FF9E80300D7773A /* PKLetter.m */; }; + D34BAFC20FF9E80300D7773A /* PKSpecificChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */; }; + D34BAFDA0FF9E95500D7773A /* NSArray+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */; }; + D34BAFDC0FF9E95500D7773A /* NSString+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */; }; + D34BAFDE0FF9E95500D7773A /* PKParserFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD80FF9E95500D7773A /* PKParserFactory.m */; }; + D34BB0680FF9EDDF00D7773A /* JSParseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0660FF9EDDF00D7773A /* JSParseKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0690FF9EDDF00D7773A /* JSParseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0670FF9EDDF00D7773A /* JSParseKit.m */; }; + D34BB0710FF9EE4000D7773A /* PKJSAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06A0FF9EE4000D7773A /* PKJSAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0720FF9EE4000D7773A /* PKJSAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB06B0FF9EE4000D7773A /* PKJSAssembly.m */; }; + D34BB0730FF9EE4000D7773A /* PKJSUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06C0FF9EE4000D7773A /* PKJSUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0740FF9EE4000D7773A /* PKJSUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB06D0FF9EE4000D7773A /* PKJSUtils.m */; }; + D34BB0750FF9EE4000D7773A /* PKJSUtils_macros.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06E0FF9EE4000D7773A /* PKJSUtils_macros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0760FF9EE4000D7773A /* PKJSValueHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06F0FF9EE4000D7773A /* PKJSValueHolder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0770FF9EE4000D7773A /* PKJSValueHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0700FF9EE4000D7773A /* PKJSValueHolder.m */; }; + D34BB08F0FF9EF9D00D7773A /* PKJSCharacterAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB08D0FF9EF9D00D7773A /* PKJSCharacterAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0900FF9EF9D00D7773A /* PKJSCharacterAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB08E0FF9EF9D00D7773A /* PKJSCharacterAssembly.m */; }; + D34BB0A90FF9F14B00D7773A /* PKJSCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0930FF9F14B00D7773A /* PKJSCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0AA0FF9F14B00D7773A /* PKJSCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0940FF9F14B00D7773A /* PKJSCommentState.m */; }; + D34BB0AB0FF9F14B00D7773A /* PKJSDelimitState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0950FF9F14B00D7773A /* PKJSDelimitState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0AC0FF9F14B00D7773A /* PKJSDelimitState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0960FF9F14B00D7773A /* PKJSDelimitState.m */; }; + D34BB0AD0FF9F14B00D7773A /* PKJSNumberState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0970FF9F14B00D7773A /* PKJSNumberState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0AE0FF9F14B00D7773A /* PKJSNumberState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0980FF9F14B00D7773A /* PKJSNumberState.m */; }; + D34BB0AF0FF9F14B00D7773A /* PKJSQuoteState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0990FF9F14B00D7773A /* PKJSQuoteState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B00FF9F14B00D7773A /* PKJSQuoteState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB09A0FF9F14B00D7773A /* PKJSQuoteState.m */; }; + D34BB0B10FF9F14B00D7773A /* PKJSSymbolState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB09B0FF9F14B00D7773A /* PKJSSymbolState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B20FF9F14B00D7773A /* PKJSSymbolState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB09C0FF9F14B00D7773A /* PKJSSymbolState.m */; }; + D34BB0B30FF9F14B00D7773A /* PKJSToken.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB09D0FF9F14B00D7773A /* PKJSToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B40FF9F14B00D7773A /* PKJSToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB09E0FF9F14B00D7773A /* PKJSToken.m */; }; + D34BB0B50FF9F14B00D7773A /* PKJSTokenAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB09F0FF9F14B00D7773A /* PKJSTokenAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B60FF9F14B00D7773A /* PKJSTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A00FF9F14B00D7773A /* PKJSTokenAssembly.m */; }; + D34BB0B70FF9F14B00D7773A /* PKJSTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A10FF9F14B00D7773A /* PKJSTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B80FF9F14B00D7773A /* PKJSTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A20FF9F14B00D7773A /* PKJSTokenizer.m */; }; + D34BB0B90FF9F14B00D7773A /* PKJSTokenizerState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A30FF9F14B00D7773A /* PKJSTokenizerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0BA0FF9F14B00D7773A /* PKJSTokenizerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A40FF9F14B00D7773A /* PKJSTokenizerState.m */; }; + D34BB0BB0FF9F14B00D7773A /* PKJSWhitespaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A50FF9F14B00D7773A /* PKJSWhitespaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0BC0FF9F14B00D7773A /* PKJSWhitespaceState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A60FF9F14B00D7773A /* PKJSWhitespaceState.m */; }; + D34BB0BD0FF9F14B00D7773A /* PKJSWordState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A70FF9F14B00D7773A /* PKJSWordState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0BE0FF9F14B00D7773A /* PKJSWordState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A80FF9F14B00D7773A /* PKJSWordState.m */; }; + D34BB0E60FF9F28000D7773A /* PKJSAlternation.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D20FF9F28000D7773A /* PKJSAlternation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0E70FF9F28000D7773A /* PKJSAlternation.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D30FF9F28000D7773A /* PKJSAlternation.m */; }; + D34BB0E80FF9F28000D7773A /* PKJSAny.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D40FF9F28000D7773A /* PKJSAny.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0E90FF9F28000D7773A /* PKJSAny.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D50FF9F28000D7773A /* PKJSAny.m */; }; + D34BB0EA0FF9F28000D7773A /* PKJSAssemblerAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D60FF9F28000D7773A /* PKJSAssemblerAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0EB0FF9F28000D7773A /* PKJSAssemblerAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D70FF9F28000D7773A /* PKJSAssemblerAdapter.m */; }; + D34BB0EC0FF9F28000D7773A /* PKJSCollectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D80FF9F28000D7773A /* PKJSCollectionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0ED0FF9F28000D7773A /* PKJSCollectionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D90FF9F28000D7773A /* PKJSCollectionParser.m */; }; + D34BB0EE0FF9F28000D7773A /* PKJSEmpty.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0DA0FF9F28000D7773A /* PKJSEmpty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0EF0FF9F28000D7773A /* PKJSEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0DB0FF9F28000D7773A /* PKJSEmpty.m */; }; + D34BB0F00FF9F28000D7773A /* PKJSParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0DC0FF9F28000D7773A /* PKJSParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F10FF9F28000D7773A /* PKJSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0DD0FF9F28000D7773A /* PKJSParser.m */; }; + D34BB0F20FF9F28000D7773A /* PKJSRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0DE0FF9F28000D7773A /* PKJSRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F30FF9F28000D7773A /* PKJSRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0DF0FF9F28000D7773A /* PKJSRepetition.m */; }; + D34BB0F40FF9F28000D7773A /* PKJSSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0E00FF9F28000D7773A /* PKJSSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F50FF9F28000D7773A /* PKJSSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0E10FF9F28000D7773A /* PKJSSequence.m */; }; + D34BB0F60FF9F28000D7773A /* PKJSTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0E20FF9F28000D7773A /* PKJSTerminal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F70FF9F28000D7773A /* PKJSTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0E30FF9F28000D7773A /* PKJSTerminal.m */; }; + D34BB0F80FF9F28000D7773A /* PKJSTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0E40FF9F28000D7773A /* PKJSTrack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F90FF9F28000D7773A /* PKJSTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0E50FF9F28000D7773A /* PKJSTrack.m */; }; + D34BB1140FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0FE0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1150FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0FF0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m */; }; + D34BB1160FF9F36200D7773A /* PKJSComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1000FF9F36200D7773A /* PKJSComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1170FF9F36200D7773A /* PKJSComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1010FF9F36200D7773A /* PKJSComment.m */; }; + D34BB1180FF9F36200D7773A /* PKJSDelimitedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1020FF9F36200D7773A /* PKJSDelimitedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1190FF9F36200D7773A /* PKJSDelimitedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1030FF9F36200D7773A /* PKJSDelimitedString.m */; }; + D34BB11A0FF9F36200D7773A /* PKJSLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1040FF9F36200D7773A /* PKJSLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB11B0FF9F36200D7773A /* PKJSLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1050FF9F36200D7773A /* PKJSLiteral.m */; }; + D34BB11C0FF9F36200D7773A /* PKJSLowercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1060FF9F36200D7773A /* PKJSLowercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB11D0FF9F36200D7773A /* PKJSLowercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1070FF9F36200D7773A /* PKJSLowercaseWord.m */; }; + D34BB11E0FF9F36200D7773A /* PKJSNum.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1080FF9F36200D7773A /* PKJSNum.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB11F0FF9F36200D7773A /* PKJSNum.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1090FF9F36200D7773A /* PKJSNum.m */; }; + D34BB1200FF9F36200D7773A /* PKJSPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB10A0FF9F36200D7773A /* PKJSPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1210FF9F36200D7773A /* PKJSPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB10B0FF9F36200D7773A /* PKJSPattern.m */; }; + D34BB1220FF9F36200D7773A /* PKJSQuotedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB10C0FF9F36200D7773A /* PKJSQuotedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1230FF9F36200D7773A /* PKJSQuotedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB10D0FF9F36200D7773A /* PKJSQuotedString.m */; }; + D34BB1240FF9F36200D7773A /* PKJSSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB10E0FF9F36200D7773A /* PKJSSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1250FF9F36200D7773A /* PKJSSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB10F0FF9F36200D7773A /* PKJSSymbol.m */; }; + D34BB1260FF9F36200D7773A /* PKJSUppercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1100FF9F36200D7773A /* PKJSUppercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1270FF9F36200D7773A /* PKJSUppercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1110FF9F36200D7773A /* PKJSUppercaseWord.m */; }; + D34BB1280FF9F36200D7773A /* PKJSWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1120FF9F36200D7773A /* PKJSWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1290FF9F36200D7773A /* PKJSWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1130FF9F36200D7773A /* PKJSWord.m */; }; + D3521F560E5FA1B0009681F9 /* XMLReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D3521F530E5FA1B0009681F9 /* XMLReader.m */; }; + D3521F570E5FA1B0009681F9 /* XMLReaderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3521F550E5FA1B0009681F9 /* XMLReaderTest.m */; }; + D35384ED0FE9691100926552 /* nspredicate.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D35384EC0FE9691100926552 /* nspredicate.grammar */; }; + D353899C0FEAC94400926552 /* c.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D353899B0FEAC94400926552 /* c.grammar */; }; + D353899E0FEAC96B00926552 /* objc.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D353899D0FEAC96B00926552 /* objc.grammar */; }; + D355C62D0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */; }; + D355C62E0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */; }; + D355C6310FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D355C6300FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m */; }; + D355C6A70FE9F704006A91A4 /* nspredicate.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D35384EC0FE9691100926552 /* nspredicate.grammar */; }; + D355C8810FEB36A1006A91A4 /* xml.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D355C8800FEB36A1006A91A4 /* xml.grammar */; }; + D355C8840FEB4B94006A91A4 /* proto.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D355C8830FEB4B94006A91A4 /* proto.grammar */; }; + D3587EAF0FE83EC900DDD023 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D36568A70EEF9FE900226554 /* TDPlistParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36568A60EEF9FE900226554 /* TDPlistParser.m */; }; + D36568AA0EEFA05300226554 /* TDPlistParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D36568A90EEFA05300226554 /* TDPlistParserTest.m */; }; + D3656DFE0EF2620E00226554 /* TDTokenArraySourceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3656DFD0EF2620E00226554 /* TDTokenArraySourceTest.m */; }; + D3668292101D2BFA0008632C /* erb.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3668291101D2BFA0008632C /* erb.grammar */; }; + D3668293101D2C000008632C /* erb.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3668291101D2BFA0008632C /* erb.grammar */; }; + D3668296101D2C200008632C /* ERBTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3668295101D2C200008632C /* ERBTest.m */; }; + D369345D1038DE5300527AF3 /* PKParseTree.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934561038DE5300527AF3 /* PKParseTree.m */; }; + D369345E1038DE5300527AF3 /* PKParseTreeAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */; }; + D369345F1038DE5300527AF3 /* PKRuleNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345A1038DE5300527AF3 /* PKRuleNode.m */; }; + D36934601038DE5300527AF3 /* PKTokenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345C1038DE5300527AF3 /* PKTokenNode.m */; }; + D36934721038E28300527AF3 /* PKParseTree.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934561038DE5300527AF3 /* PKParseTree.m */; }; + D36934731038E28700527AF3 /* PKParseTreeAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */; }; + D36934741038E28B00527AF3 /* PKRuleNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345A1038DE5300527AF3 /* PKRuleNode.m */; }; + D36934751038E28F00527AF3 /* PKTokenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345C1038DE5300527AF3 /* PKTokenNode.m */; }; + D36C53790FD27F1300141CB7 /* TDParserFactoryTest2.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C53780FD27F1300141CB7 /* TDParserFactoryTest2.m */; }; + D36C55FF0FD3617B00141CB7 /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */; }; + D36C560C0FD363D500141CB7 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D36C560B0FD363D500141CB7 /* libicucore.dylib */; }; + D36C562B0FD365DB00141CB7 /* TDPatternTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C562A0FD365DB00141CB7 /* TDPatternTest.m */; }; + D36E95460E578ECC00496BD3 /* XPathParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E95450E578ECC00496BD3 /* XPathParser.m */; }; + D36E95D80E57B08400496BD3 /* XPathParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E95D70E57B08400496BD3 /* XPathParserTest.m */; }; + D36E97B00E589DAE00496BD3 /* XPathAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */; }; + D36E98220E58A3A800496BD3 /* XPathContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98210E58A3A800496BD3 /* XPathContext.m */; }; + D36E98E00E58C12800496BD3 /* DebugAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98DD0E58C12800496BD3 /* DebugAppDelegate.m */; }; + D36E98E10E58C12800496BD3 /* DebugAppMainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D36E98DE0E58C12800496BD3 /* DebugAppMainMenu.xib */; }; + D36E98E20E58C12800496BD3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98DF0E58C12800496BD3 /* main.m */; }; + D36E98E70E58C14000496BD3 /* DemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98E40E58C14000496BD3 /* DemoAppDelegate.m */; }; + D36E98E80E58C14000496BD3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98E50E58C14000496BD3 /* main.m */; }; + D36E98F80E58C1A000496BD3 /* DemoAppMainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D36E98F70E58C1A000496BD3 /* DemoAppMainMenu.xib */; }; + D36E9F870E5A795400496BD3 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D36E9F860E5A795400496BD3 /* libxml2.dylib */; }; + D36E9FB50E5A944A00496BD3 /* apple-boss.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36E9FB40E5A944A00496BD3 /* apple-boss.xml */; }; + D36E9FE50E5BA0FC00496BD3 /* SRGSGrammar.txt in Resources */ = {isa = PBXBuildFile; fileRef = D36E9FE40E5BA0FC00496BD3 /* SRGSGrammar.txt */; }; + D36EA3B00E5EA67E00496BD3 /* small-xml-file.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */; }; + D37A28671013942300E936B7 /* PKGrammarParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D5810093A1600E4602E /* PKGrammarParser.m */; }; + D37A28681013942A00E936B7 /* PKGrammarParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3376D5710093A1600E4602E /* PKGrammarParser.h */; }; + D37D3A000FE77A71008C2E4D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D37D3A010FE77A72008C2E4D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D37D3A020FE77A77008C2E4D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D380AFBD0F0C54B60009EC13 /* html.css in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBB0F0C54B60009EC13 /* html.css */; }; + D380AFBE0F0C54B60009EC13 /* html.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBC0F0C54B60009EC13 /* html.grammar */; }; + D380AFBF0F0C54B60009EC13 /* html.css in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBB0F0C54B60009EC13 /* html.css */; }; + D380AFC00F0C54B60009EC13 /* html.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBC0F0C54B60009EC13 /* html.grammar */; }; + D380AFC30F0C56000009EC13 /* example.html in Resources */ = {isa = PBXBuildFile; fileRef = D380AFC20F0C56000009EC13 /* example.html */; }; + D380AFC40F0C56000009EC13 /* example.html in Resources */ = {isa = PBXBuildFile; fileRef = D380AFC20F0C56000009EC13 /* example.html */; }; + D380B3230F0CC0800009EC13 /* nyt.html in Resources */ = {isa = PBXBuildFile; fileRef = D38DD9E70EC29F260070BC4D /* nyt.html */; }; + D380B5090F0D71A90009EC13 /* css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380B5080F0D71A90009EC13 /* css.grammar */; }; + D380B50A0F0D71B00009EC13 /* css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380B5080F0D71A90009EC13 /* css.grammar */; }; + D380B5380F0D7DDE0009EC13 /* css.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5370F0D7DDE0009EC13 /* css.css */; }; + D380B5390F0D7DE30009EC13 /* css.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5370F0D7DDE0009EC13 /* css.css */; }; + D380B5940F0D82F60009EC13 /* example.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5930F0D82F60009EC13 /* example.css */; }; + D380B5950F0D82F90009EC13 /* example.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5930F0D82F60009EC13 /* example.css */; }; + D380B9800F0EF3860009EC13 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D380BA620F0F06CD0009EC13 /* TDParserFactoryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D380BA600F0F06CD0009EC13 /* TDParserFactoryTest.m */; }; + D380BAA30F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D380BAA40F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D38205BE0EEE48EE004340DD /* TDTokenTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D38205BD0EEE48EE004340DD /* TDTokenTest.m */; }; + D383498B0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */; }; + D383498C0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */; }; + D38349BC0F0C0D910055E4E0 /* json_with_comments.css in Resources */ = {isa = PBXBuildFile; fileRef = D38349BB0F0C0D910055E4E0 /* json_with_comments.css */; }; + D38349BD0F0C0D910055E4E0 /* json_with_comments.css in Resources */ = {isa = PBXBuildFile; fileRef = D38349BB0F0C0D910055E4E0 /* json_with_comments.css */; }; + D3834A480F0C14B60055E4E0 /* yahoo_with_comments.json in Resources */ = {isa = PBXBuildFile; fileRef = D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */; }; + D3834A490F0C14C00055E4E0 /* yahoo_with_comments.json in Resources */ = {isa = PBXBuildFile; fileRef = D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */; }; + D385F98C0F046FE900DB2946 /* TDGenericAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385F9890F046FE900DB2946 /* TDGenericAssembler.m */; }; + D385F98E0F046FE900DB2946 /* TDGenericAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385F9890F046FE900DB2946 /* TDGenericAssembler.m */; }; + D385FA230F04971400DB2946 /* TDGenericAssemblerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FA220F04971400DB2946 /* TDGenericAssemblerTest.m */; }; + D385FA250F04993500DB2946 /* json.css in Resources */ = {isa = PBXBuildFile; fileRef = D385FA240F04993500DB2946 /* json.css */; }; + D385FA260F04993500DB2946 /* json.css in Resources */ = {isa = PBXBuildFile; fileRef = D385FA240F04993500DB2946 /* json.css */; }; + D385FD440F05A88C00DB2946 /* TDMiniCSSAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */; }; + D385FD460F05A89100DB2946 /* TDMiniCSSAssemblerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FD430F05A88C00DB2946 /* TDMiniCSSAssemblerTest.m */; }; + D385FD490F05A8C900DB2946 /* TDMiniCSSAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */; }; + D385FD6C0F05A99900DB2946 /* mini_css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D385FD6B0F05A99900DB2946 /* mini_css.grammar */; }; + D385FD6D0F05A99900DB2946 /* mini_css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D385FD6B0F05A99900DB2946 /* mini_css.grammar */; }; + D389F1D50F19666500558235 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D389F20B0F196A9200558235 /* JSParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D389F1CE0F1965E600558235 /* JSParseKit.framework */; }; + D389F20C0F196A9200558235 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D389F20E0F196A9200558235 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D389F20D0F196A9200558235 /* WebKit.framework */; }; + D389F2E40F196CAE00558235 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F2E30F196CAE00558235 /* main.m */; }; + D389F3430F197DDC00558235 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D389F34E0F197DF500558235 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D389F37A0F197E8000558235 /* JSDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F2E90F196F5B00558235 /* JSDemoAppDelegate.m */; }; + D389F38F0F19800400558235 /* DefaultValues.plist in Resources */ = {isa = PBXBuildFile; fileRef = D389F38E0F19800400558235 /* DefaultValues.plist */; }; + D389F4620F198A8800558235 /* Test.html in Resources */ = {isa = PBXBuildFile; fileRef = D389F4610F198A8800558235 /* Test.html */; }; + D389F5590F19B7BC00558235 /* JSDemoAppMainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D389F5580F19B7BC00558235 /* JSDemoAppMainMenu.xib */; }; + D389F5B60F19C76A00558235 /* TDJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F5B30F19C76A00558235 /* TDJsonParser.m */; }; + D389F5B70F19C76A00558235 /* TDJsonParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F5B50F19C76A00558235 /* TDJsonParserTest.m */; }; + D389F5B80F19C76A00558235 /* TDJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F5B30F19C76A00558235 /* TDJsonParser.m */; }; + D389FBCD0F1B25E200558235 /* ParserTest.html in Resources */ = {isa = PBXBuildFile; fileRef = D389FBCC0F1B25E200558235 /* ParserTest.html */; }; + D38DD9E80EC29F260070BC4D /* nyt.html in Resources */ = {isa = PBXBuildFile; fileRef = D38DD9E70EC29F260070BC4D /* nyt.html */; }; + D38E97CC1061CF6500739C39 /* TDTokenizerBlocksTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D38E97CB1061CF6500739C39 /* TDTokenizerBlocksTest.m */; }; + D38E98D81062C5BA00739C39 /* TDParserBlocksTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D38E98D71062C5BA00739C39 /* TDParserBlocksTest.m */; }; + D398E20E0E60F86D00A1C877 /* yahoo.json in Resources */ = {isa = PBXBuildFile; fileRef = D3B473840E48C9CF008AFBDD /* yahoo.json */; }; + D39E01340FEF02DA00150FC3 /* TDXMLParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3BBBC970FEC9722007DF30D /* TDXMLParserTest.m */; }; + D3AF49780FDB122E0032F4DC /* TDParserFactoryPatternTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3AF49770FDB122E0032F4DC /* TDParserFactoryPatternTest.m */; }; + D3B43FB80F76E99C0072AF40 /* TDJavaScriptParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3B43FB60F76E99C0072AF40 /* TDJavaScriptParserTest.m */; }; + D3B473850E48C9CF008AFBDD /* yahoo.json in Resources */ = {isa = PBXBuildFile; fileRef = D3B473840E48C9CF008AFBDD /* yahoo.json */; }; + D3B69D320E80249900D70C41 /* nonascii.html in Resources */ = {isa = PBXBuildFile; fileRef = D3B69D310E80249900D70C41 /* nonascii.html */; }; + D3B69D330E80249900D70C41 /* nonascii.html in Resources */ = {isa = PBXBuildFile; fileRef = D3B69D310E80249900D70C41 /* nonascii.html */; }; + D3BBBC9D0FEC9756007DF30D /* TDXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */; }; + D3BBBC9E0FEC9756007DF30D /* TDXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */; }; + D3BBBCC10FECD477007DF30D /* xml.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D355C8800FEB36A1006A91A4 /* xml.grammar */; }; + D3C031ED0EF38D2D00C5ABEB /* TDLowercaseWordTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C031EC0EF38D2D00C5ABEB /* TDLowercaseWordTest.m */; }; + D3C221920FFE8B8C004514FE /* ParseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221900FFE8B8C004514FE /* ParseKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221930FFE8B8C004514FE /* PKTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221910FFE8B8C004514FE /* PKTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221940FFE8B8C004514FE /* ParseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221900FFE8B8C004514FE /* ParseKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221950FFE8B8C004514FE /* PKTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221910FFE8B8C004514FE /* PKTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221970FFE8B95004514FE /* PKReader.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221960FFE8B95004514FE /* PKReader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221980FFE8B95004514FE /* PKReader.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221960FFE8B95004514FE /* PKReader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219A0FFE8B9D004514FE /* PKAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221990FFE8B9D004514FE /* PKAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219B0FFE8B9D004514FE /* PKAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221990FFE8B9D004514FE /* PKAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219D0FFE8BA6004514FE /* PKParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219C0FFE8BA6004514FE /* PKParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219E0FFE8BA6004514FE /* PKParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219C0FFE8BA6004514FE /* PKParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A00FFE8BAE004514FE /* PKRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219F0FFE8BAE004514FE /* PKRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A10FFE8BAE004514FE /* PKRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219F0FFE8BAE004514FE /* PKRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A30FFE8BBA004514FE /* PKCollectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A40FFE8BBA004514FE /* PKCollectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A60FFE8BC1004514FE /* PKAlternation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A50FFE8BC1004514FE /* PKAlternation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A70FFE8BC1004514FE /* PKAlternation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A50FFE8BC1004514FE /* PKAlternation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A90FFE8BC9004514FE /* PKSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A80FFE8BC9004514FE /* PKSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AA0FFE8BC9004514FE /* PKSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A80FFE8BC9004514FE /* PKSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AC0FFE8BCF004514FE /* PKTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AB0FFE8BCF004514FE /* PKTrack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AD0FFE8BCF004514FE /* PKTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AB0FFE8BCF004514FE /* PKTrack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AF0FFE8BD4004514FE /* PKTrackException.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AE0FFE8BD4004514FE /* PKTrackException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B00FFE8BD4004514FE /* PKTrackException.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AE0FFE8BD4004514FE /* PKTrackException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B20FFE8BDB004514FE /* PKIntersection.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B10FFE8BDB004514FE /* PKIntersection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B30FFE8BDB004514FE /* PKIntersection.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B10FFE8BDB004514FE /* PKIntersection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B50FFE8BE2004514FE /* PKDifference.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B40FFE8BE2004514FE /* PKDifference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B60FFE8BE2004514FE /* PKDifference.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B40FFE8BE2004514FE /* PKDifference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B80FFE8BE8004514FE /* PKNegation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B70FFE8BE8004514FE /* PKNegation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B90FFE8BE8004514FE /* PKNegation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B70FFE8BE8004514FE /* PKNegation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BB0FFE8BEF004514FE /* PKTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BA0FFE8BEF004514FE /* PKTerminal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BC0FFE8BEF004514FE /* PKTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BA0FFE8BEF004514FE /* PKTerminal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BE0FFE8BF7004514FE /* PKEmpty.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BD0FFE8BF7004514FE /* PKEmpty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BF0FFE8BF7004514FE /* PKEmpty.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BD0FFE8BF7004514FE /* PKEmpty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C10FFE8BFF004514FE /* PKTokenAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C20FFE8BFF004514FE /* PKTokenAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C40FFE8C07004514FE /* PKToken.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C30FFE8C07004514FE /* PKToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C50FFE8C07004514FE /* PKToken.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C30FFE8C07004514FE /* PKToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C70FFE8C0D004514FE /* PKTokenArraySource.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C80FFE8C0D004514FE /* PKTokenArraySource.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CA0FFE8C15004514FE /* PKTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C90FFE8C15004514FE /* PKTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CB0FFE8C15004514FE /* PKTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C90FFE8C15004514FE /* PKTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CD0FFE8C1B004514FE /* PKTokenizerState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CE0FFE8C1B004514FE /* PKTokenizerState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D00FFE8C24004514FE /* PKNumberState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CF0FFE8C24004514FE /* PKNumberState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D10FFE8C24004514FE /* PKNumberState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CF0FFE8C24004514FE /* PKNumberState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D60FFE8C35004514FE /* PKSymbolState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D50FFE8C35004514FE /* PKSymbolState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D70FFE8C35004514FE /* PKSymbolState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D50FFE8C35004514FE /* PKSymbolState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D90FFE8C3D004514FE /* PKWordState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D80FFE8C3D004514FE /* PKWordState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DA0FFE8C3D004514FE /* PKWordState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D80FFE8C3D004514FE /* PKWordState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DC0FFE8C43004514FE /* PKWhitespaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DD0FFE8C43004514FE /* PKWhitespaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DF0FFE8C49004514FE /* PKDelimitState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DE0FFE8C49004514FE /* PKDelimitState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E00FFE8C49004514FE /* PKDelimitState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DE0FFE8C49004514FE /* PKDelimitState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E20FFE8C4E004514FE /* PKCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E10FFE8C4E004514FE /* PKCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E30FFE8C4E004514FE /* PKCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E10FFE8C4E004514FE /* PKCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E50FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E60FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E80FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E90FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EB0FFE8C69004514FE /* PKSymbolNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EC0FFE8C69004514FE /* PKSymbolNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EE0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EF0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F10FFE8C7A004514FE /* PKPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F00FFE8C7A004514FE /* PKPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F20FFE8C7A004514FE /* PKPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F00FFE8C7A004514FE /* PKPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F40FFE8C87004514FE /* PKWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F30FFE8C87004514FE /* PKWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F50FFE8C87004514FE /* PKWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F30FFE8C87004514FE /* PKWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F70FFE8C8E004514FE /* PKNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F60FFE8C8E004514FE /* PKNumber.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FA0FFE8C97004514FE /* PKQuotedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F90FFE8C97004514FE /* PKQuotedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FB0FFE8C97004514FE /* PKQuotedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F90FFE8C97004514FE /* PKQuotedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FD0FFE8CB2004514FE /* PKSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FC0FFE8CB2004514FE /* PKSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FE0FFE8CB2004514FE /* PKSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FC0FFE8CB2004514FE /* PKSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222000FFE8CB9004514FE /* PKLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FF0FFE8CB9004514FE /* PKLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222010FFE8CB9004514FE /* PKLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FF0FFE8CB9004514FE /* PKLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222030FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222040FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222060FFE8CCA004514FE /* PKWhitespace.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222050FFE8CCA004514FE /* PKWhitespace.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222070FFE8CCA004514FE /* PKWhitespace.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222050FFE8CCA004514FE /* PKWhitespace.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222090FFE8CD1004514FE /* PKComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222080FFE8CD1004514FE /* PKComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220A0FFE8CD1004514FE /* PKComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222080FFE8CD1004514FE /* PKComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220C0FFE8CD8004514FE /* PKDelimitedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220D0FFE8CD8004514FE /* PKDelimitedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220F0FFE8CDF004514FE /* PKAny.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220E0FFE8CDF004514FE /* PKAny.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222100FFE8CDF004514FE /* PKAny.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220E0FFE8CDF004514FE /* PKAny.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222150FFE8D01004514FE /* PKLowercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222140FFE8D01004514FE /* PKLowercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222160FFE8D01004514FE /* PKLowercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222140FFE8D01004514FE /* PKLowercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222180FFE8D11004514FE /* PKUppercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222170FFE8D11004514FE /* PKUppercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222190FFE8D11004514FE /* PKUppercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222170FFE8D11004514FE /* PKUppercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221B0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221C0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221E0FFE8D3B004514FE /* PKChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221D0FFE8D3B004514FE /* PKChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221F0FFE8D3B004514FE /* PKChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221D0FFE8D3B004514FE /* PKChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222210FFE8D42004514FE /* PKDigit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222200FFE8D42004514FE /* PKDigit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222220FFE8D42004514FE /* PKDigit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222200FFE8D42004514FE /* PKDigit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222240FFE8D49004514FE /* PKLetter.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222230FFE8D49004514FE /* PKLetter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222250FFE8D49004514FE /* PKLetter.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222230FFE8D49004514FE /* PKLetter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222270FFE8D6B004514FE /* PKSpecificChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222260FFE8D6B004514FE /* PKSpecificChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222280FFE8D6B004514FE /* PKSpecificChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222260FFE8D6B004514FE /* PKSpecificChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2222A0FFE8DAC004514FE /* PKParserFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222290FFE8DAC004514FE /* PKParserFactory.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2222B0FFE8DAC004514FE /* PKParserFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222290FFE8DAC004514FE /* PKParserFactory.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2222D0FFE8DE9004514FE /* NSArray+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */; }; + D3C2222E0FFE8DEE004514FE /* NSString+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */; }; + D3C2222F0FFE8DEF004514FE /* NSString+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */; }; + D3C222300FFE8DF3004514FE /* NSArray+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */; }; + D3C7D9DA0A412874005DD154 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D3C85C7B0E63B438000445FD /* TDArithmeticParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C85C7A0E63B438000445FD /* TDArithmeticParser.m */; }; + D3C85C800E63B9E9000445FD /* TDArithmeticParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C85C7F0E63B9E9000445FD /* TDArithmeticParserTest.m */; }; + D3C85D450E63D1BF000445FD /* TDScientificNumberStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C85D440E63D1BF000445FD /* TDScientificNumberStateTest.m */; }; + D3D01CAA0EFDB89900C24DDE /* json_with_discards.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */; }; + D3D01CAB0EFDB8A000C24DDE /* json_with_discards.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */; }; + D3D01CAC0EFDB8A100C24DDE /* json_with_discards.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */; }; + D3D1BF2810394420003656E5 /* SAXAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D1BF2710394420003656E5 /* SAXAssembler.m */; }; + D3D1BF2B1039445C003656E5 /* SAXTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D1BF2A1039445C003656E5 /* SAXTest.m */; }; + D3DCB3730EF5E5D600DE5110 /* OCMock.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D3DCB37D0EF5E5E400DE5110 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D3DCB4C30EF6015300DE5110 /* json.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3DCB4C20EF6015300DE5110 /* json.grammar */; }; + D3DCB4C40EF6015C00DE5110 /* json.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3DCB4C20EF6015300DE5110 /* json.grammar */; }; + D3DCB4C50EF6015C00DE5110 /* json.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3DCB4C20EF6015300DE5110 /* json.grammar */; }; + D3DDDA870F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */; }; + D3DDDA880F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */; }; + D3DDDAFE0F083C9700A58000 /* TDCommentStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3DDDAFD0F083C9700A58000 /* TDCommentStateTest.m */; }; + D3DDDCAD0F0880D800A58000 /* example1.srgs in Resources */ = {isa = PBXBuildFile; fileRef = D3DDDCAC0F0880D800A58000 /* example1.srgs */; }; + D3DDDCAE0F0880D800A58000 /* example1.srgs in Resources */ = {isa = PBXBuildFile; fileRef = D3DDDCAC0F0880D800A58000 /* example1.srgs */; }; + D3E27A320E741DD20078CC2C /* small-xml-file.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */; }; + D3E27A330E741DD20078CC2C /* apple-boss.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36E9FB40E5A944A00496BD3 /* apple-boss.xml */; }; + D3E39C3F0FC5FFD10022DAB9 /* TDDelimitStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E39C3E0FC5FFD10022DAB9 /* TDDelimitStateTest.m */; }; + D3E784BD0E53DA28008C7D61 /* apple-boss.json in Resources */ = {isa = PBXBuildFile; fileRef = D3E784BC0E53DA28008C7D61 /* apple-boss.json */; }; + D3E785560E53FB54008C7D61 /* apple-boss.json in Resources */ = {isa = PBXBuildFile; fileRef = D3E784BC0E53DA28008C7D61 /* apple-boss.json */; }; + D3E787A30E5661A9008C7D61 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; + D3E788930E567DFD008C7D61 /* SRGSParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E788920E567DFD008C7D61 /* SRGSParserTest.m */; }; + D3E788960E567E0A008C7D61 /* SRGSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E788950E567E0A008C7D61 /* SRGSParser.m */; }; + D3E78A190E574C99008C7D61 /* EBNFParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E78A160E574C99008C7D61 /* EBNFParser.m */; }; + D3E78A1A0E574C99008C7D61 /* EBNFParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E78A180E574C99008C7D61 /* EBNFParserTest.m */; }; + D3EAC7EC0F2690620043D6A9 /* OCMock.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D3EADD800E75E9CC00F78584 /* nasty.html in Resources */ = {isa = PBXBuildFile; fileRef = D3EADD7F0E75E9CC00F78584 /* nasty.html */; }; + D3EADD810E75E9CC00F78584 /* nasty.html in Resources */ = {isa = PBXBuildFile; fileRef = D3EADD7F0E75E9CC00F78584 /* nasty.html */; }; + D3EADD8E0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */; }; + D3EADD8F0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */; }; + D3F0E2480FFE8EB900C9DF74 /* PKQuoteState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3F0E2490FFE8EB900C9DF74 /* PKQuoteState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3F0E3CB0FFEB70100C9DF74 /* PKNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F60FFE8C8E004514FE /* PKNumber.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3F0E3CC0FFEB70700C9DF74 /* PKNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF440FF9E19700D7773A /* PKNumber.m */; }; + D3F55F611025737D00DD6DB1 /* TDParseTreeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F55F601025737D00DD6DB1 /* TDParseTreeTest.m */; }; + D3F5629A10266CFC00DD6DB1 /* PKParseTreeView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F5629910266CFC00DD6DB1 /* PKParseTreeView.m */; }; + D3F562A010266DFB00DD6DB1 /* DemoTokensViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F5629F10266DFB00DD6DB1 /* DemoTokensViewController.m */; }; + D3F562A210266E5300DD6DB1 /* TokensView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3F562A110266E5300DD6DB1 /* TokensView.xib */; }; + D3F562A410266E6300DD6DB1 /* TreesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3F562A310266E6300DD6DB1 /* TreesView.xib */; }; + D3F562A710266E8D00DD6DB1 /* DemoTreesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F562A610266E8D00DD6DB1 /* DemoTreesViewController.m */; }; + D3F740B70EF8C38A00559B9F /* JSONAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F740B60EF8C38A00559B9F /* JSONAssembler.m */; }; + D3F741440EF8E96A00559B9F /* xpath1_0.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741430EF8E96A00559B9F /* xpath1_0.grammar */; }; + D3F741BE0EF9F28D00559B9F /* css2_1.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741BD0EF9F28D00559B9F /* css2_1.grammar */; }; + D3F741BF0EF9F29400559B9F /* css2_1.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741BD0EF9F28D00559B9F /* css2_1.grammar */; }; + D3F741C00EF9F29500559B9F /* css2_1.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741BD0EF9F28D00559B9F /* css2_1.grammar */; }; + D3FD79200F4CC86800BAD816 /* rubyhash.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */; }; + D3FD79210F4CC87900BAD816 /* rubyhash.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */; }; + D3FDC4A50FFB3B2A00F1F797 /* RegexKitLite.h in Headers */ = {isa = PBXBuildFile; fileRef = D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */; }; + D3FDC6DA0FFC4C8C00F1F797 /* RegexKitLite.h in Headers */ = {isa = PBXBuildFile; fileRef = D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */; }; + D3FDC6EE0FFC4C9E00F1F797 /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */; }; + D3FDC6EF0FFC4C9E00F1F797 /* PKReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAD9B0FF9C95800D7773A /* PKReader.m */; }; + D3FDC6F00FFC4C9E00F1F797 /* PKAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADA00FF9C9B000D7773A /* PKAssembly.m */; }; + D3FDC6F10FFC4C9E00F1F797 /* PKParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADD60FF9CBFB00D7773A /* PKParser.m */; }; + D3FDC6F20FFC4C9E00F1F797 /* PKRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE130FF9CE0E00D7773A /* PKRepetition.m */; }; + D3FDC6F30FFC4C9E00F1F797 /* PKCollectionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */; }; + D3FDC6F40FFC4C9E00F1F797 /* PKAlternation.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */; }; + D3FDC6F50FFC4C9E00F1F797 /* PKSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE150FF9CE0E00D7773A /* PKSequence.m */; }; + D3FDC6F60FFC4C9E00F1F797 /* PKTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE190FF9CE0E00D7773A /* PKTrack.m */; }; + D3FDC6F70FFC4C9E00F1F797 /* PKTrackException.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */; }; + D3FDC6F80FFC4C9E00F1F797 /* PKDifference.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */; }; + D3FDC6F90FFC4C9E00F1F797 /* PKIntersection.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE110FF9CE0E00D7773A /* PKIntersection.m */; }; + D3FDC6FA0FFC4C9E00F1F797 /* PKTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE170FF9CE0E00D7773A /* PKTerminal.m */; }; + D3FDC6FB0FFC4C9E00F1F797 /* PKEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */; }; + D3FDC6FC0FFC4C9E00F1F797 /* PKTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */; }; + D3FDC6FD0FFC4C9E00F1F797 /* PKToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE950FF9D20900D7773A /* PKToken.m */; }; + D3FDC6FE0FFC4C9E00F1F797 /* PKTokenArraySource.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */; }; + D3FDC6FF0FFC4C9E00F1F797 /* PKTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE990FF9D20900D7773A /* PKTokenizer.m */; }; + D3FDC7000FFC4C9E00F1F797 /* PKTokenizerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */; }; + D3FDC7010FFC4C9E00F1F797 /* PKNumberState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECA0FF9D56400D7773A /* PKNumberState.m */; }; + D3FDC7020FFC4C9E00F1F797 /* PKQuoteState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECC0FF9D56400D7773A /* PKQuoteState.m */; }; + D3FDC7030FFC4C9E00F1F797 /* PKSymbolState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED00FF9D56400D7773A /* PKSymbolState.m */; }; + D3FDC7040FFC4C9E00F1F797 /* PKWordState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED60FF9D56400D7773A /* PKWordState.m */; }; + D3FDC7050FFC4C9E00F1F797 /* PKWhitespaceState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */; }; + D3FDC7060FFC4C9E00F1F797 /* PKDelimitState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC60FF9D56400D7773A /* PKDelimitState.m */; }; + D3FDC7070FFC4C9E00F1F797 /* PKCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC40FF9D56400D7773A /* PKCommentState.m */; }; + D3FDC7080FFC4C9E00F1F797 /* PKSingleLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */; }; + D3FDC7090FFC4C9E00F1F797 /* PKMultiLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */; }; + D3FDC70A0FFC4C9E00F1F797 /* PKSymbolNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */; }; + D3FDC70B0FFC4C9E00F1F797 /* PKSymbolRootNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */; }; + D3FDC70C0FFC4C9E00F1F797 /* PKPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF380FF9E18300D7773A /* PKPattern.m */; }; + D3FDC70D0FFC4C9E00F1F797 /* PKWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED40FF9D56400D7773A /* PKWord.m */; }; + D3FDC70F0FFC4C9E00F1F797 /* PKQuotedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF460FF9E19700D7773A /* PKQuotedString.m */; }; + D3FDC7100FFC4C9E00F1F797 /* PKSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF480FF9E19700D7773A /* PKSymbol.m */; }; + D3FDC7110FFC4C9E00F1F797 /* PKLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF420FF9E19700D7773A /* PKLiteral.m */; }; + D3FDC7120FFC4C9E00F1F797 /* PKCaseInsensitiveLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */; }; + D3FDC7130FFC4C9E00F1F797 /* PKWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */; }; + D3FDC7140FFC4C9E00F1F797 /* PKComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3E0FF9E19700D7773A /* PKComment.m */; }; + D3FDC7150FFC4C9E00F1F797 /* PKDelimitedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF400FF9E19700D7773A /* PKDelimitedString.m */; }; + D3FDC7160FFC4C9E00F1F797 /* PKAny.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE2F0FF9CE6000D7773A /* PKAny.m */; }; + D3FDC7180FFC4C9E00F1F797 /* PKLowercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */; }; + D3FDC7190FFC4C9E00F1F797 /* PKUppercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */; }; + D3FDC71A0FFC4C9E00F1F797 /* PKCharacterAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */; }; + D3FDC71B0FFC4C9E00F1F797 /* PKChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB40FF9E80300D7773A /* PKChar.m */; }; + D3FDC71C0FFC4C9E00F1F797 /* PKDigit.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB60FF9E80300D7773A /* PKDigit.m */; }; + D3FDC71D0FFC4C9E00F1F797 /* PKLetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB80FF9E80300D7773A /* PKLetter.m */; }; + D3FDC71E0FFC4C9E00F1F797 /* PKSpecificChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */; }; + D3FDC71F0FFC4C9E00F1F797 /* PKParserFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD80FF9E95500D7773A /* PKParserFactory.m */; }; + D3FDC7200FFC4C9E00F1F797 /* NSArray+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */; }; + D3FDC7210FFC4C9E00F1F797 /* NSString+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */; }; + D3FDC7370FFC4D6100F1F797 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3FDC7360FFC4D6100F1F797 /* Foundation.framework */; }; + D3FDC7390FFC4D6100F1F797 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D3FDC7380FFC4D6100F1F797 /* libicucore.dylib */; }; + D3FDC74C0FFC4DAC00F1F797 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3FDC74B0FFC4DAC00F1F797 /* CoreGraphics.framework */; }; + D3FDC8DC0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = D3FDC8DB0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + D31FE7170E60F24700A0803E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TDParseKit; + }; + D334949F0E296AA900406085 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TODParseKit; + }; + D341850F0E520D6F0081B0DC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TODParseKit; + }; + D389F1D30F19665C00558235 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TDParseKit; + }; + D389F2090F196A8000558235 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D389F1CD0F1965E600558235; + remoteInfo = TDJSParseKit; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + D380B9A10F0EF3DC0009EC13 /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(BUILT_PRODUCTS_DIR)"; + dstSubfolderSpec = 0; + files = ( + D3EAC7EC0F2690620043D6A9 /* OCMock.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + D3DCB3880EF5E65100DE5110 /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(BUILT_PRODUCTS_DIR)"; + dstSubfolderSpec = 0; + files = ( + D3DCB3730EF5E5D600DE5110 /* OCMock.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 8DC2EF5B0486A6940098B216 /* ParseKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ParseKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D3126D040FFD9BA700CBF4C4 /* PKNegation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKNegation.m; path = src/PKNegation.m; sourceTree = ""; }; + D3126D090FFD9E4B00CBF4C4 /* TDNegationTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNegationTest.h; path = test/TDNegationTest.h; sourceTree = ""; }; + D3126D0A0FFD9E4B00CBF4C4 /* TDNegationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNegationTest.m; path = test/TDNegationTest.m; sourceTree = ""; }; + D3126D410FFDB4C600CBF4C4 /* TDExclusionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDExclusionTest.h; path = test/TDExclusionTest.h; sourceTree = ""; }; + D3126D420FFDB4C600CBF4C4 /* TDExclusionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDExclusionTest.m; path = test/TDExclusionTest.m; sourceTree = ""; }; + D31270F80FFE898300CBF4C4 /* PKExclusion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKExclusion.m; path = test/PKExclusion.m; sourceTree = ""; }; + D315DF710FEF59B600D876C8 /* date.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = date.grammar; path = res/date.grammar; sourceTree = ""; }; + D319E429106D8A1F008C63DD /* arithmetic.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = arithmetic.grammar; path = res/arithmetic.grammar; sourceTree = ""; }; + D319E42C106D8A31008C63DD /* TDArithmeticAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDArithmeticAssembler.h; path = test/TDArithmeticAssembler.h; sourceTree = ""; }; + D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDArithmeticAssembler.m; path = test/TDArithmeticAssembler.m; sourceTree = ""; }; + D31A15250F6DE449002AFDF1 /* javascript.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = javascript.grammar; path = res/javascript.grammar; sourceTree = ""; }; + D31A16500F7038C2002AFDF1 /* TDJavaScriptParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJavaScriptParser.h; path = test/TDJavaScriptParser.h; sourceTree = ""; }; + D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJavaScriptParser.m; path = test/TDJavaScriptParser.m; sourceTree = ""; }; + D31FE54A0E60E46100A0803E /* TDTestScaffold.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTestScaffold.h; path = test/TDTestScaffold.h; sourceTree = ""; }; + D31FE54B0E60E46100A0803E /* TDTestScaffold.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTestScaffold.m; path = test/TDTestScaffold.m; sourceTree = ""; }; + D31FE54D0E60E50800A0803E /* TDAlternationTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDAlternationTest.h; path = test/TDAlternationTest.h; sourceTree = ""; }; + D31FE54E0E60E50800A0803E /* TDAlternationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDAlternationTest.m; path = test/TDAlternationTest.m; sourceTree = ""; }; + D31FE54F0E60E50800A0803E /* TDLiteralTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDLiteralTest.h; path = test/TDLiteralTest.h; sourceTree = ""; }; + D31FE5500E60E50800A0803E /* TDLiteralTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDLiteralTest.m; path = test/TDLiteralTest.m; sourceTree = ""; }; + D31FE5510E60E50800A0803E /* TDParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserTest.h; path = test/TDParserTest.h; sourceTree = ""; }; + D31FE5520E60E50800A0803E /* TDParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserTest.m; path = test/TDParserTest.m; sourceTree = ""; }; + D31FE5530E60E50800A0803E /* TDRepetitionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRepetitionTest.h; path = test/TDRepetitionTest.h; sourceTree = ""; }; + D31FE5540E60E50800A0803E /* TDRepetitionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRepetitionTest.m; path = test/TDRepetitionTest.m; sourceTree = ""; }; + D31FE5550E60E50800A0803E /* TDReservedWordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDReservedWordTest.h; path = test/TDReservedWordTest.h; sourceTree = ""; }; + D31FE5560E60E50800A0803E /* TDReservedWordTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDReservedWordTest.m; path = test/TDReservedWordTest.m; sourceTree = ""; }; + D31FE5570E60E50800A0803E /* TDRobotCommandTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRobotCommandTest.h; path = test/TDRobotCommandTest.h; sourceTree = ""; }; + D31FE5580E60E50800A0803E /* TDRobotCommandTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRobotCommandTest.m; path = test/TDRobotCommandTest.m; sourceTree = ""; }; + D31FE5590E60E50800A0803E /* TDSequenceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSequenceTest.h; path = test/TDSequenceTest.h; sourceTree = ""; }; + D31FE55A0E60E50800A0803E /* TDSequenceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSequenceTest.m; path = test/TDSequenceTest.m; sourceTree = ""; }; + D31FE55B0E60E50800A0803E /* TDSymbolTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSymbolTest.h; path = test/TDSymbolTest.h; sourceTree = ""; }; + D31FE55C0E60E50800A0803E /* TDSymbolTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSymbolTest.m; path = test/TDSymbolTest.m; sourceTree = ""; }; + D31FE55D0E60E50800A0803E /* TDTokenAssemblyTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenAssemblyTest.h; path = test/TDTokenAssemblyTest.h; sourceTree = ""; }; + D31FE55E0E60E50800A0803E /* TDTokenAssemblyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenAssemblyTest.m; path = test/TDTokenAssemblyTest.m; sourceTree = ""; }; + D31FE55F0E60E50800A0803E /* TDTrackTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTrackTest.h; path = test/TDTrackTest.h; sourceTree = ""; }; + D31FE5600E60E50800A0803E /* TDTrackTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTrackTest.m; path = test/TDTrackTest.m; sourceTree = ""; }; + D31FE5610E60E50800A0803E /* TDUppercaseWordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDUppercaseWordTest.h; path = test/TDUppercaseWordTest.h; sourceTree = ""; }; + D31FE5620E60E50800A0803E /* TDUppercaseWordTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDUppercaseWordTest.m; path = test/TDUppercaseWordTest.m; sourceTree = ""; }; + D31FE5710E60E55700A0803E /* TDReaderTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDReaderTest.h; path = test/TDReaderTest.h; sourceTree = ""; }; + D31FE5720E60E55700A0803E /* TDReaderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDReaderTest.m; path = test/TDReaderTest.m; sourceTree = ""; }; + D31FE5730E60E55700A0803E /* TDTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenizerTest.h; path = test/TDTokenizerTest.h; sourceTree = ""; }; + D31FE5740E60E55700A0803E /* TDTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenizerTest.m; path = test/TDTokenizerTest.m; sourceTree = ""; }; + D31FE5770E60E58C00A0803E /* TDNumberStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNumberStateTest.h; path = test/TDNumberStateTest.h; sourceTree = ""; }; + D31FE5780E60E58C00A0803E /* TDNumberStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNumberStateTest.m; path = test/TDNumberStateTest.m; sourceTree = ""; }; + D31FE5790E60E58C00A0803E /* TDQuoteStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDQuoteStateTest.h; path = test/TDQuoteStateTest.h; sourceTree = ""; }; + D31FE57A0E60E58C00A0803E /* TDQuoteStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDQuoteStateTest.m; path = test/TDQuoteStateTest.m; sourceTree = ""; }; + D31FE57B0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSignificantWhitespaceStateTest.h; path = test/TDSignificantWhitespaceStateTest.h; sourceTree = ""; }; + D31FE57C0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSignificantWhitespaceStateTest.m; path = test/TDSignificantWhitespaceStateTest.m; sourceTree = ""; }; + D31FE57D0E60E58C00A0803E /* TDSlashStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashStateTest.h; path = test/TDSlashStateTest.h; sourceTree = ""; }; + D31FE57E0E60E58C00A0803E /* TDSlashStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashStateTest.m; path = test/TDSlashStateTest.m; sourceTree = ""; }; + D31FE57F0E60E58C00A0803E /* TDSymbolStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSymbolStateTest.h; path = test/TDSymbolStateTest.h; sourceTree = ""; }; + D31FE5800E60E58C00A0803E /* TDSymbolStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSymbolStateTest.m; path = test/TDSymbolStateTest.m; sourceTree = ""; }; + D31FE5810E60E58C00A0803E /* TDWhitespaceStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDWhitespaceStateTest.h; path = test/TDWhitespaceStateTest.h; sourceTree = ""; }; + D31FE5820E60E58C00A0803E /* TDWhitespaceStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDWhitespaceStateTest.m; path = test/TDWhitespaceStateTest.m; sourceTree = ""; }; + D31FE5830E60E58C00A0803E /* TDWordStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDWordStateTest.h; path = test/TDWordStateTest.h; sourceTree = ""; }; + D31FE5840E60E58C00A0803E /* TDWordStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDWordStateTest.m; path = test/TDWordStateTest.m; sourceTree = ""; }; + D31FE58C0E60E5AC00A0803E /* TDCharacterAssemblyTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDCharacterAssemblyTest.h; path = test/TDCharacterAssemblyTest.h; sourceTree = ""; }; + D31FE58D0E60E5AC00A0803E /* TDCharacterAssemblyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDCharacterAssemblyTest.m; path = test/TDCharacterAssemblyTest.m; sourceTree = ""; }; + D31FE58E0E60E5AC00A0803E /* TDCharTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDCharTest.h; path = test/TDCharTest.h; sourceTree = ""; }; + D31FE58F0E60E5AC00A0803E /* TDCharTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDCharTest.m; path = test/TDCharTest.m; sourceTree = ""; }; + D31FE5900E60E5AC00A0803E /* TDDigitTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDDigitTest.h; path = test/TDDigitTest.h; sourceTree = ""; }; + D31FE5910E60E5AC00A0803E /* TDDigitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDDigitTest.m; path = test/TDDigitTest.m; sourceTree = ""; }; + D31FE5920E60E5AC00A0803E /* TDLetterTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDLetterTest.h; path = test/TDLetterTest.h; sourceTree = ""; }; + D31FE5930E60E5AC00A0803E /* TDLetterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDLetterTest.m; path = test/TDLetterTest.m; sourceTree = ""; }; + D31FE5940E60E5AC00A0803E /* TDSpecificCharTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSpecificCharTest.h; path = test/TDSpecificCharTest.h; sourceTree = ""; }; + D31FE5950E60E5AC00A0803E /* TDSpecificCharTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSpecificCharTest.m; path = test/TDSpecificCharTest.m; sourceTree = ""; }; + D31FE59B0E60E5C000A0803E /* TDRegularParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRegularParser.h; path = test/TDRegularParser.h; sourceTree = ""; }; + D31FE59C0E60E5C000A0803E /* TDRegularParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRegularParser.m; path = test/TDRegularParser.m; sourceTree = ""; }; + D31FE59D0E60E5C000A0803E /* TDRegularParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRegularParserTest.h; path = test/TDRegularParserTest.h; sourceTree = ""; }; + D31FE59E0E60E5C000A0803E /* TDRegularParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRegularParserTest.m; path = test/TDRegularParserTest.m; sourceTree = ""; }; + D31FE5A10E60E5D500A0803E /* TDFastJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDFastJsonParser.h; path = test/TDFastJsonParser.h; sourceTree = ""; }; + D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDFastJsonParser.m; path = test/TDFastJsonParser.m; sourceTree = ""; }; + D31FE5A30E60E5D500A0803E /* TDFastJsonParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDFastJsonParserTest.h; path = test/TDFastJsonParserTest.h; sourceTree = ""; }; + D31FE5A40E60E5D500A0803E /* TDFastJsonParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDFastJsonParserTest.m; path = test/TDFastJsonParserTest.m; sourceTree = ""; }; + D31FE5AD0E60E64900A0803E /* TDXmlTokenAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTokenAssembly.h; path = test/TDXmlTokenAssembly.h; sourceTree = ""; }; + D31FE5AE0E60E64900A0803E /* TDXmlTokenAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTokenAssembly.m; path = test/TDXmlTokenAssembly.m; sourceTree = ""; }; + D31FE5AF0E60E64900A0803E /* TDXmlTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTokenizerTest.h; path = test/TDXmlTokenizerTest.h; sourceTree = ""; }; + D31FE5B00E60E64900A0803E /* TDXmlTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTokenizerTest.m; path = test/TDXmlTokenizerTest.m; sourceTree = ""; }; + D31FE5B30E60E66600A0803E /* TDXmlToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlToken.h; path = test/TDXmlToken.h; sourceTree = ""; }; + D31FE5B40E60E66600A0803E /* TDXmlToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlToken.m; path = test/TDXmlToken.m; sourceTree = ""; }; + D31FE5B50E60E66600A0803E /* TDXmlTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTokenizer.h; path = test/TDXmlTokenizer.h; sourceTree = ""; }; + D31FE5B60E60E66600A0803E /* TDXmlTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTokenizer.m; path = test/TDXmlTokenizer.m; sourceTree = ""; }; + D31FE5B90E60E69E00A0803E /* TDXmlAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlAttribute.h; path = test/TDXmlAttribute.h; sourceTree = ""; }; + D31FE5BA0E60E69E00A0803E /* TDXmlAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlAttribute.m; path = test/TDXmlAttribute.m; sourceTree = ""; }; + D31FE5BB0E60E69E00A0803E /* TDXmlCdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlCdata.h; path = test/TDXmlCdata.h; sourceTree = ""; }; + D31FE5BC0E60E69E00A0803E /* TDXmlCdata.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlCdata.m; path = test/TDXmlCdata.m; sourceTree = ""; }; + D31FE5BD0E60E69E00A0803E /* TDXmlComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlComment.h; path = test/TDXmlComment.h; sourceTree = ""; }; + D31FE5BE0E60E69E00A0803E /* TDXmlComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlComment.m; path = test/TDXmlComment.m; sourceTree = ""; }; + D31FE5BF0E60E69E00A0803E /* TDXmlDecl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlDecl.h; path = test/TDXmlDecl.h; sourceTree = ""; }; + D31FE5C00E60E69E00A0803E /* TDXmlDecl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlDecl.m; path = test/TDXmlDecl.m; sourceTree = ""; }; + D31FE5C10E60E69E00A0803E /* TDXmlDoctype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlDoctype.h; path = test/TDXmlDoctype.h; sourceTree = ""; }; + D31FE5C20E60E69E00A0803E /* TDXmlDoctype.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlDoctype.m; path = test/TDXmlDoctype.m; sourceTree = ""; }; + D31FE5C30E60E69E00A0803E /* TDXmlDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlDocument.h; path = test/TDXmlDocument.h; sourceTree = ""; }; + D31FE5C40E60E69E00A0803E /* TDXmlDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlDocument.m; path = test/TDXmlDocument.m; sourceTree = ""; }; + D31FE5C50E60E69E00A0803E /* TDXmlEndEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEndEntity.h; path = test/TDXmlEndEntity.h; sourceTree = ""; }; + D31FE5C60E60E69E00A0803E /* TDXmlEndEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEndEntity.m; path = test/TDXmlEndEntity.m; sourceTree = ""; }; + D31FE5C70E60E69E00A0803E /* TDXmlEndTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEndTag.h; path = test/TDXmlEndTag.h; sourceTree = ""; }; + D31FE5C80E60E69E00A0803E /* TDXmlEndTag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEndTag.m; path = test/TDXmlEndTag.m; sourceTree = ""; }; + D31FE5C90E60E69E00A0803E /* TDXmlEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEntity.h; path = test/TDXmlEntity.h; sourceTree = ""; }; + D31FE5CA0E60E69E00A0803E /* TDXmlEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEntity.m; path = test/TDXmlEntity.m; sourceTree = ""; }; + D31FE5CB0E60E69E00A0803E /* TDXmlEntityRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEntityRef.h; path = test/TDXmlEntityRef.h; sourceTree = ""; }; + D31FE5CC0E60E69E00A0803E /* TDXmlEntityRef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEntityRef.m; path = test/TDXmlEntityRef.m; sourceTree = ""; }; + D31FE5CD0E60E69E00A0803E /* TDXmlFragment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlFragment.h; path = test/TDXmlFragment.h; sourceTree = ""; }; + D31FE5CE0E60E69E00A0803E /* TDXmlFragment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlFragment.m; path = test/TDXmlFragment.m; sourceTree = ""; }; + D31FE5CF0E60E69E00A0803E /* TDXmlNotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNotation.h; path = test/TDXmlNotation.h; sourceTree = ""; }; + D31FE5D00E60E69E00A0803E /* TDXmlNotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNotation.m; path = test/TDXmlNotation.m; sourceTree = ""; }; + D31FE5D10E60E69E00A0803E /* TDXmlProcessingInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlProcessingInstruction.h; path = test/TDXmlProcessingInstruction.h; sourceTree = ""; }; + D31FE5D20E60E69E00A0803E /* TDXmlProcessingInstruction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlProcessingInstruction.m; path = test/TDXmlProcessingInstruction.m; sourceTree = ""; }; + D31FE5D30E60E69E00A0803E /* TDXmlSignificantWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlSignificantWhitespace.h; path = test/TDXmlSignificantWhitespace.h; sourceTree = ""; }; + D31FE5D40E60E69E00A0803E /* TDXmlSignificantWhitespace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlSignificantWhitespace.m; path = test/TDXmlSignificantWhitespace.m; sourceTree = ""; }; + D31FE5D50E60E69E00A0803E /* TDXmlStartTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlStartTag.h; path = test/TDXmlStartTag.h; sourceTree = ""; }; + D31FE5D60E60E69E00A0803E /* TDXmlStartTag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlStartTag.m; path = test/TDXmlStartTag.m; sourceTree = ""; }; + D31FE5D70E60E69E00A0803E /* TDXmlTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTerminal.h; path = test/TDXmlTerminal.h; sourceTree = ""; }; + D31FE5D80E60E69E00A0803E /* TDXmlTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTerminal.m; path = test/TDXmlTerminal.m; sourceTree = ""; }; + D31FE5D90E60E69E00A0803E /* TDXmlText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlText.h; path = test/TDXmlText.h; sourceTree = ""; }; + D31FE5DA0E60E69E00A0803E /* TDXmlText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlText.m; path = test/TDXmlText.m; sourceTree = ""; }; + D31FE5DB0E60E69E00A0803E /* TDXmlWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlWhitespace.h; path = test/TDXmlWhitespace.h; sourceTree = ""; }; + D31FE5DC0E60E69E00A0803E /* TDXmlWhitespace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlWhitespace.m; path = test/TDXmlWhitespace.m; sourceTree = ""; }; + D31FE5EF0E60E6B500A0803E /* TDNCName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNCName.h; path = test/TDNCName.h; sourceTree = ""; }; + D31FE5F00E60E6B500A0803E /* TDNCNameState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNCNameState.h; path = test/TDNCNameState.h; sourceTree = ""; }; + D31FE5F10E60E6B500A0803E /* TDNCNameState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNCNameState.m; path = test/TDNCNameState.m; sourceTree = ""; }; + D31FE5F20E60E6B500A0803E /* TDXmlName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlName.h; path = test/TDXmlName.h; sourceTree = ""; }; + D31FE5F30E60E6B500A0803E /* TDXmlName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlName.m; path = test/TDXmlName.m; sourceTree = ""; }; + D31FE5F40E60E6B500A0803E /* TDXmlNameState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNameState.h; path = test/TDXmlNameState.h; sourceTree = ""; }; + D31FE5F50E60E6B500A0803E /* TDXmlNameState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNameState.m; path = test/TDXmlNameState.m; sourceTree = ""; }; + D31FE5F60E60E6B500A0803E /* TDXmlNameTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNameTest.h; path = test/TDXmlNameTest.h; sourceTree = ""; }; + D31FE5F70E60E6B500A0803E /* TDXmlNameTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNameTest.m; path = test/TDXmlNameTest.m; sourceTree = ""; }; + D31FE5F80E60E6B500A0803E /* TDXmlNmtoken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNmtoken.h; path = test/TDXmlNmtoken.h; sourceTree = ""; }; + D31FE5F90E60E6B500A0803E /* TDXmlNmtoken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNmtoken.m; path = test/TDXmlNmtoken.m; sourceTree = ""; }; + D31FE5FA0E60E6B500A0803E /* TDXmlNmtokenState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNmtokenState.h; path = test/TDXmlNmtokenState.h; sourceTree = ""; }; + D31FE5FB0E60E6B500A0803E /* TDXmlNmtokenState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNmtokenState.m; path = test/TDXmlNmtokenState.m; sourceTree = ""; }; + D31FE6DF0E60EE2500A0803E /* TDNCName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNCName.m; path = test/TDNCName.m; sourceTree = ""; }; + D3252F780FCE1A7E005EF059 /* TDNSPredicateBuilderTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateBuilderTest.h; path = test/TDNSPredicateBuilderTest.h; sourceTree = ""; }; + D3252F790FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateBuilderTest.m; path = test/TDNSPredicateBuilderTest.m; sourceTree = ""; }; + D3252F7C0FCE1A87005EF059 /* TDNSPredicateBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateBuilder.h; path = test/TDNSPredicateBuilder.h; sourceTree = ""; }; + D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateBuilder.m; path = test/TDNSPredicateBuilder.m; sourceTree = ""; }; + D3305C4B102F5BAD00DC4F75 /* TDGutterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDGutterView.h; path = demoapp/TDGutterView.h; sourceTree = ""; }; + D3305C4C102F5BAD00DC4F75 /* TDGutterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDGutterView.m; path = demoapp/TDGutterView.m; sourceTree = ""; }; + D3305C4D102F5BAE00DC4F75 /* TDSourceCodeTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSourceCodeTextView.h; path = demoapp/TDSourceCodeTextView.h; sourceTree = ""; }; + D3305C4E102F5BAE00DC4F75 /* TDSourceCodeTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSourceCodeTextView.m; path = demoapp/TDSourceCodeTextView.m; sourceTree = ""; }; + D33494100E2963FD00406085 /* DemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D3376D5710093A1600E4602E /* PKGrammarParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKGrammarParser.h; path = src/PKGrammarParser.h; sourceTree = ""; }; + D3376D5810093A1600E4602E /* PKGrammarParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKGrammarParser.m; path = src/PKGrammarParser.m; sourceTree = ""; }; + D3376D8C10096C0700E4602E /* PKAST.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAST.h; path = test/PKAST.h; sourceTree = ""; }; + D3376D8D10096C0700E4602E /* PKAST.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAST.m; path = test/PKAST.m; sourceTree = ""; }; + D3385FD70FCFB1FF003BF729 /* TDPredicateEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPredicateEvaluator.h; path = test/TDPredicateEvaluator.h; sourceTree = ""; }; + D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPredicateEvaluator.m; path = test/TDPredicateEvaluator.m; sourceTree = ""; }; + D3385FDB0FCFB227003BF729 /* TDPredicateEvaluatorTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPredicateEvaluatorTest.h; path = test/TDPredicateEvaluatorTest.h; sourceTree = ""; }; + D3385FDC0FCFB227003BF729 /* TDPredicateEvaluatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPredicateEvaluatorTest.m; path = test/TDPredicateEvaluatorTest.m; sourceTree = ""; }; + D338E5B90FF5DDCB003DE6AA /* TDDifferenceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDDifferenceTest.h; path = test/TDDifferenceTest.h; sourceTree = ""; }; + D338E5BA0FF5DDCB003DE6AA /* TDDifferenceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDDifferenceTest.m; path = test/TDDifferenceTest.m; sourceTree = ""; }; + D34185040E520D3F0081B0DC /* DebugApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DebugApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D34BAC210FF87F8600D7773A /* TDParserFactoryTest3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryTest3.h; path = test/TDParserFactoryTest3.h; sourceTree = ""; }; + D34BAC220FF87F8600D7773A /* TDParserFactoryTest3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryTest3.m; path = test/TDParserFactoryTest3.m; sourceTree = ""; }; + D34BAC490FF892C200D7773A /* XPathParserGrammarTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathParserGrammarTest.h; path = test/XPathParserGrammarTest.h; sourceTree = ""; }; + D34BAC4A0FF892C200D7773A /* XPathParserGrammarTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathParserGrammarTest.m; path = test/XPathParserGrammarTest.m; sourceTree = ""; }; + D34BAD16100A9B7900996341 /* TDTokenizerStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenizerStateTest.h; path = test/TDTokenizerStateTest.h; sourceTree = ""; }; + D34BAD17100A9B7900996341 /* TDTokenizerStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenizerStateTest.m; path = test/TDTokenizerStateTest.m; sourceTree = ""; }; + D34BAD630FF9C6AE00D7773A /* ParseKit_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseKit_Prefix.pch; sourceTree = ""; }; + D34BAD9B0FF9C95800D7773A /* PKReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKReader.m; path = src/PKReader.m; sourceTree = ""; }; + D34BADA00FF9C9B000D7773A /* PKAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAssembly.m; path = src/PKAssembly.m; sourceTree = ""; }; + D34BADD60FF9CBFB00D7773A /* PKParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParser.m; path = src/PKParser.m; sourceTree = ""; }; + D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCollectionParser.m; path = src/PKCollectionParser.m; sourceTree = ""; }; + D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAlternation.m; path = src/PKAlternation.m; sourceTree = ""; }; + D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKEmpty.m; path = src/PKEmpty.m; sourceTree = ""; }; + D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDifference.m; path = src/PKDifference.m; sourceTree = ""; }; + D34BAE110FF9CE0E00D7773A /* PKIntersection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKIntersection.m; path = src/PKIntersection.m; sourceTree = ""; }; + D34BAE130FF9CE0E00D7773A /* PKRepetition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKRepetition.m; path = src/PKRepetition.m; sourceTree = ""; }; + D34BAE150FF9CE0E00D7773A /* PKSequence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSequence.m; path = src/PKSequence.m; sourceTree = ""; }; + D34BAE170FF9CE0E00D7773A /* PKTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTerminal.m; path = src/PKTerminal.m; sourceTree = ""; }; + D34BAE190FF9CE0E00D7773A /* PKTrack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTrack.m; path = src/PKTrack.m; sourceTree = ""; }; + D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTrackException.m; path = src/PKTrackException.m; sourceTree = ""; }; + D34BAE2F0FF9CE6000D7773A /* PKAny.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAny.m; path = src/PKAny.m; sourceTree = ""; }; + D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenAssembly.m; path = src/PKTokenAssembly.m; sourceTree = ""; }; + D34BAE950FF9D20900D7773A /* PKToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKToken.m; path = src/PKToken.m; sourceTree = ""; }; + D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenArraySource.m; path = src/PKTokenArraySource.m; sourceTree = ""; }; + D34BAE990FF9D20900D7773A /* PKTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenizer.m; path = src/PKTokenizer.m; sourceTree = ""; }; + D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenizerState.m; path = src/PKTokenizerState.m; sourceTree = ""; }; + D34BAEC40FF9D56400D7773A /* PKCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCommentState.m; path = src/PKCommentState.m; sourceTree = ""; }; + D34BAEC60FF9D56400D7773A /* PKDelimitState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDelimitState.m; path = src/PKDelimitState.m; sourceTree = ""; }; + D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKMultiLineCommentState.m; path = src/PKMultiLineCommentState.m; sourceTree = ""; }; + D34BAECA0FF9D56400D7773A /* PKNumberState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKNumberState.m; path = src/PKNumberState.m; sourceTree = ""; }; + D34BAECC0FF9D56400D7773A /* PKQuoteState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKQuoteState.m; path = src/PKQuoteState.m; sourceTree = ""; }; + D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSingleLineCommentState.m; path = src/PKSingleLineCommentState.m; sourceTree = ""; }; + D34BAED00FF9D56400D7773A /* PKSymbolState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbolState.m; path = src/PKSymbolState.m; sourceTree = ""; }; + D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWhitespaceState.m; path = src/PKWhitespaceState.m; sourceTree = ""; }; + D34BAED40FF9D56400D7773A /* PKWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWord.m; path = src/PKWord.m; sourceTree = ""; }; + D34BAED60FF9D56400D7773A /* PKWordState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWordState.m; path = src/PKWordState.m; sourceTree = ""; }; + D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbolNode.m; path = src/PKSymbolNode.m; sourceTree = ""; }; + D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbolRootNode.m; path = src/PKSymbolRootNode.m; sourceTree = ""; }; + D34BAF380FF9E18300D7773A /* PKPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKPattern.m; path = src/PKPattern.m; sourceTree = ""; }; + D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCaseInsensitiveLiteral.m; path = src/PKCaseInsensitiveLiteral.m; sourceTree = ""; }; + D34BAF3E0FF9E19700D7773A /* PKComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKComment.m; path = src/PKComment.m; sourceTree = ""; }; + D34BAF400FF9E19700D7773A /* PKDelimitedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDelimitedString.m; path = src/PKDelimitedString.m; sourceTree = ""; }; + D34BAF420FF9E19700D7773A /* PKLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKLiteral.m; path = src/PKLiteral.m; sourceTree = ""; }; + D34BAF440FF9E19700D7773A /* PKNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKNumber.m; path = src/PKNumber.m; sourceTree = ""; }; + D34BAF460FF9E19700D7773A /* PKQuotedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKQuotedString.m; path = src/PKQuotedString.m; sourceTree = ""; }; + D34BAF480FF9E19700D7773A /* PKSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbol.m; path = src/PKSymbol.m; sourceTree = ""; }; + D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWhitespace.m; path = src/PKWhitespace.m; sourceTree = ""; }; + D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKLowercaseWord.m; path = src/PKLowercaseWord.m; sourceTree = ""; }; + D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKUppercaseWord.m; path = src/PKUppercaseWord.m; sourceTree = ""; }; + D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCharacterAssembly.m; path = src/PKCharacterAssembly.m; sourceTree = ""; }; + D34BAFB40FF9E80300D7773A /* PKChar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKChar.m; path = src/PKChar.m; sourceTree = ""; }; + D34BAFB60FF9E80300D7773A /* PKDigit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDigit.m; path = src/PKDigit.m; sourceTree = ""; }; + D34BAFB80FF9E80300D7773A /* PKLetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKLetter.m; path = src/PKLetter.m; sourceTree = ""; }; + D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSpecificChar.m; path = src/PKSpecificChar.m; sourceTree = ""; }; + D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+ParseKitAdditions.h"; path = "src/NSArray+ParseKitAdditions.h"; sourceTree = ""; }; + D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+ParseKitAdditions.m"; path = "src/NSArray+ParseKitAdditions.m"; sourceTree = ""; }; + D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+ParseKitAdditions.h"; path = "src/NSString+ParseKitAdditions.h"; sourceTree = ""; }; + D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+ParseKitAdditions.m"; path = "src/NSString+ParseKitAdditions.m"; sourceTree = ""; }; + D34BAFD80FF9E95500D7773A /* PKParserFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParserFactory.m; path = src/PKParserFactory.m; sourceTree = ""; }; + D34BB04E0FF9EC4E00D7773A /* JSParseKit-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "JSParseKit-Info.plist"; sourceTree = ""; }; + D34BB0660FF9EDDF00D7773A /* JSParseKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSParseKit.h; path = jssrc/JSParseKit.h; sourceTree = ""; }; + D34BB0670FF9EDDF00D7773A /* JSParseKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSParseKit.m; path = jssrc/JSParseKit.m; sourceTree = ""; }; + D34BB06A0FF9EE4000D7773A /* PKJSAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAssembly.h; path = jssrc/PKJSAssembly.h; sourceTree = ""; }; + D34BB06B0FF9EE4000D7773A /* PKJSAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAssembly.m; path = jssrc/PKJSAssembly.m; sourceTree = ""; }; + D34BB06C0FF9EE4000D7773A /* PKJSUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSUtils.h; path = jssrc/PKJSUtils.h; sourceTree = ""; }; + D34BB06D0FF9EE4000D7773A /* PKJSUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSUtils.m; path = jssrc/PKJSUtils.m; sourceTree = ""; }; + D34BB06E0FF9EE4000D7773A /* PKJSUtils_macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSUtils_macros.h; path = jssrc/PKJSUtils_macros.h; sourceTree = ""; }; + D34BB06F0FF9EE4000D7773A /* PKJSValueHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSValueHolder.h; path = jssrc/PKJSValueHolder.h; sourceTree = ""; }; + D34BB0700FF9EE4000D7773A /* PKJSValueHolder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSValueHolder.m; path = jssrc/PKJSValueHolder.m; sourceTree = ""; }; + D34BB08D0FF9EF9D00D7773A /* PKJSCharacterAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCharacterAssembly.h; path = jssrc/PKJSCharacterAssembly.h; sourceTree = ""; }; + D34BB08E0FF9EF9D00D7773A /* PKJSCharacterAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCharacterAssembly.m; path = jssrc/PKJSCharacterAssembly.m; sourceTree = ""; }; + D34BB0930FF9F14B00D7773A /* PKJSCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCommentState.h; path = jssrc/PKJSCommentState.h; sourceTree = ""; }; + D34BB0940FF9F14B00D7773A /* PKJSCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCommentState.m; path = jssrc/PKJSCommentState.m; sourceTree = ""; }; + D34BB0950FF9F14B00D7773A /* PKJSDelimitState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSDelimitState.h; path = jssrc/PKJSDelimitState.h; sourceTree = ""; }; + D34BB0960FF9F14B00D7773A /* PKJSDelimitState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSDelimitState.m; path = jssrc/PKJSDelimitState.m; sourceTree = ""; }; + D34BB0970FF9F14B00D7773A /* PKJSNumberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSNumberState.h; path = jssrc/PKJSNumberState.h; sourceTree = ""; }; + D34BB0980FF9F14B00D7773A /* PKJSNumberState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSNumberState.m; path = jssrc/PKJSNumberState.m; sourceTree = ""; }; + D34BB0990FF9F14B00D7773A /* PKJSQuoteState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSQuoteState.h; path = jssrc/PKJSQuoteState.h; sourceTree = ""; }; + D34BB09A0FF9F14B00D7773A /* PKJSQuoteState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSQuoteState.m; path = jssrc/PKJSQuoteState.m; sourceTree = ""; }; + D34BB09B0FF9F14B00D7773A /* PKJSSymbolState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSSymbolState.h; path = jssrc/PKJSSymbolState.h; sourceTree = ""; }; + D34BB09C0FF9F14B00D7773A /* PKJSSymbolState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSSymbolState.m; path = jssrc/PKJSSymbolState.m; sourceTree = ""; }; + D34BB09D0FF9F14B00D7773A /* PKJSToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSToken.h; path = jssrc/PKJSToken.h; sourceTree = ""; }; + D34BB09E0FF9F14B00D7773A /* PKJSToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSToken.m; path = jssrc/PKJSToken.m; sourceTree = ""; }; + D34BB09F0FF9F14B00D7773A /* PKJSTokenAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTokenAssembly.h; path = jssrc/PKJSTokenAssembly.h; sourceTree = ""; }; + D34BB0A00FF9F14B00D7773A /* PKJSTokenAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTokenAssembly.m; path = jssrc/PKJSTokenAssembly.m; sourceTree = ""; }; + D34BB0A10FF9F14B00D7773A /* PKJSTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTokenizer.h; path = jssrc/PKJSTokenizer.h; sourceTree = ""; }; + D34BB0A20FF9F14B00D7773A /* PKJSTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTokenizer.m; path = jssrc/PKJSTokenizer.m; sourceTree = ""; }; + D34BB0A30FF9F14B00D7773A /* PKJSTokenizerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTokenizerState.h; path = jssrc/PKJSTokenizerState.h; sourceTree = ""; }; + D34BB0A40FF9F14B00D7773A /* PKJSTokenizerState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTokenizerState.m; path = jssrc/PKJSTokenizerState.m; sourceTree = ""; }; + D34BB0A50FF9F14B00D7773A /* PKJSWhitespaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSWhitespaceState.h; path = jssrc/PKJSWhitespaceState.h; sourceTree = ""; }; + D34BB0A60FF9F14B00D7773A /* PKJSWhitespaceState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSWhitespaceState.m; path = jssrc/PKJSWhitespaceState.m; sourceTree = ""; }; + D34BB0A70FF9F14B00D7773A /* PKJSWordState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSWordState.h; path = jssrc/PKJSWordState.h; sourceTree = ""; }; + D34BB0A80FF9F14B00D7773A /* PKJSWordState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSWordState.m; path = jssrc/PKJSWordState.m; sourceTree = ""; }; + D34BB0D20FF9F28000D7773A /* PKJSAlternation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAlternation.h; path = jssrc/PKJSAlternation.h; sourceTree = ""; }; + D34BB0D30FF9F28000D7773A /* PKJSAlternation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAlternation.m; path = jssrc/PKJSAlternation.m; sourceTree = ""; }; + D34BB0D40FF9F28000D7773A /* PKJSAny.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAny.h; path = jssrc/PKJSAny.h; sourceTree = ""; }; + D34BB0D50FF9F28000D7773A /* PKJSAny.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAny.m; path = jssrc/PKJSAny.m; sourceTree = ""; }; + D34BB0D60FF9F28000D7773A /* PKJSAssemblerAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAssemblerAdapter.h; path = jssrc/PKJSAssemblerAdapter.h; sourceTree = ""; }; + D34BB0D70FF9F28000D7773A /* PKJSAssemblerAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAssemblerAdapter.m; path = jssrc/PKJSAssemblerAdapter.m; sourceTree = ""; }; + D34BB0D80FF9F28000D7773A /* PKJSCollectionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCollectionParser.h; path = jssrc/PKJSCollectionParser.h; sourceTree = ""; }; + D34BB0D90FF9F28000D7773A /* PKJSCollectionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCollectionParser.m; path = jssrc/PKJSCollectionParser.m; sourceTree = ""; }; + D34BB0DA0FF9F28000D7773A /* PKJSEmpty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSEmpty.h; path = jssrc/PKJSEmpty.h; sourceTree = ""; }; + D34BB0DB0FF9F28000D7773A /* PKJSEmpty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSEmpty.m; path = jssrc/PKJSEmpty.m; sourceTree = ""; }; + D34BB0DC0FF9F28000D7773A /* PKJSParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSParser.h; path = jssrc/PKJSParser.h; sourceTree = ""; }; + D34BB0DD0FF9F28000D7773A /* PKJSParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSParser.m; path = jssrc/PKJSParser.m; sourceTree = ""; }; + D34BB0DE0FF9F28000D7773A /* PKJSRepetition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSRepetition.h; path = jssrc/PKJSRepetition.h; sourceTree = ""; }; + D34BB0DF0FF9F28000D7773A /* PKJSRepetition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSRepetition.m; path = jssrc/PKJSRepetition.m; sourceTree = ""; }; + D34BB0E00FF9F28000D7773A /* PKJSSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSSequence.h; path = jssrc/PKJSSequence.h; sourceTree = ""; }; + D34BB0E10FF9F28000D7773A /* PKJSSequence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSSequence.m; path = jssrc/PKJSSequence.m; sourceTree = ""; }; + D34BB0E20FF9F28000D7773A /* PKJSTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTerminal.h; path = jssrc/PKJSTerminal.h; sourceTree = ""; }; + D34BB0E30FF9F28000D7773A /* PKJSTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTerminal.m; path = jssrc/PKJSTerminal.m; sourceTree = ""; }; + D34BB0E40FF9F28000D7773A /* PKJSTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTrack.h; path = jssrc/PKJSTrack.h; sourceTree = ""; }; + D34BB0E50FF9F28000D7773A /* PKJSTrack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTrack.m; path = jssrc/PKJSTrack.m; sourceTree = ""; }; + D34BB0FE0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCaseInsensitiveLiteral.h; path = jssrc/PKJSCaseInsensitiveLiteral.h; sourceTree = ""; }; + D34BB0FF0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCaseInsensitiveLiteral.m; path = jssrc/PKJSCaseInsensitiveLiteral.m; sourceTree = ""; }; + D34BB1000FF9F36200D7773A /* PKJSComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSComment.h; path = jssrc/PKJSComment.h; sourceTree = ""; }; + D34BB1010FF9F36200D7773A /* PKJSComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSComment.m; path = jssrc/PKJSComment.m; sourceTree = ""; }; + D34BB1020FF9F36200D7773A /* PKJSDelimitedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSDelimitedString.h; path = jssrc/PKJSDelimitedString.h; sourceTree = ""; }; + D34BB1030FF9F36200D7773A /* PKJSDelimitedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSDelimitedString.m; path = jssrc/PKJSDelimitedString.m; sourceTree = ""; }; + D34BB1040FF9F36200D7773A /* PKJSLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSLiteral.h; path = jssrc/PKJSLiteral.h; sourceTree = ""; }; + D34BB1050FF9F36200D7773A /* PKJSLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSLiteral.m; path = jssrc/PKJSLiteral.m; sourceTree = ""; }; + D34BB1060FF9F36200D7773A /* PKJSLowercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSLowercaseWord.h; path = jssrc/PKJSLowercaseWord.h; sourceTree = ""; }; + D34BB1070FF9F36200D7773A /* PKJSLowercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSLowercaseWord.m; path = jssrc/PKJSLowercaseWord.m; sourceTree = ""; }; + D34BB1080FF9F36200D7773A /* PKJSNum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSNum.h; path = jssrc/PKJSNum.h; sourceTree = ""; }; + D34BB1090FF9F36200D7773A /* PKJSNum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSNum.m; path = jssrc/PKJSNum.m; sourceTree = ""; }; + D34BB10A0FF9F36200D7773A /* PKJSPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSPattern.h; path = jssrc/PKJSPattern.h; sourceTree = ""; }; + D34BB10B0FF9F36200D7773A /* PKJSPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSPattern.m; path = jssrc/PKJSPattern.m; sourceTree = ""; }; + D34BB10C0FF9F36200D7773A /* PKJSQuotedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSQuotedString.h; path = jssrc/PKJSQuotedString.h; sourceTree = ""; }; + D34BB10D0FF9F36200D7773A /* PKJSQuotedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSQuotedString.m; path = jssrc/PKJSQuotedString.m; sourceTree = ""; }; + D34BB10E0FF9F36200D7773A /* PKJSSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSSymbol.h; path = jssrc/PKJSSymbol.h; sourceTree = ""; }; + D34BB10F0FF9F36200D7773A /* PKJSSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSSymbol.m; path = jssrc/PKJSSymbol.m; sourceTree = ""; }; + D34BB1100FF9F36200D7773A /* PKJSUppercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSUppercaseWord.h; path = jssrc/PKJSUppercaseWord.h; sourceTree = ""; }; + D34BB1110FF9F36200D7773A /* PKJSUppercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSUppercaseWord.m; path = jssrc/PKJSUppercaseWord.m; sourceTree = ""; }; + D34BB1120FF9F36200D7773A /* PKJSWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSWord.h; path = jssrc/PKJSWord.h; sourceTree = ""; }; + D34BB1130FF9F36200D7773A /* PKJSWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSWord.m; path = jssrc/PKJSWord.m; sourceTree = ""; }; + D3521F520E5FA1B0009681F9 /* XMLReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMLReader.h; path = test/XMLReader.h; sourceTree = ""; }; + D3521F530E5FA1B0009681F9 /* XMLReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMLReader.m; path = test/XMLReader.m; sourceTree = ""; }; + D3521F540E5FA1B0009681F9 /* XMLReaderTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMLReaderTest.h; path = test/XMLReaderTest.h; sourceTree = ""; }; + D3521F550E5FA1B0009681F9 /* XMLReaderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMLReaderTest.m; path = test/XMLReaderTest.m; sourceTree = ""; }; + D35384EC0FE9691100926552 /* nspredicate.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = nspredicate.grammar; path = res/nspredicate.grammar; sourceTree = ""; }; + D353899B0FEAC94400926552 /* c.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = c.grammar; path = res/c.grammar; sourceTree = ""; }; + D353899D0FEAC96B00926552 /* objc.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = objc.grammar; path = res/objc.grammar; sourceTree = ""; }; + D355C62B0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateEvaluator.h; path = test/TDNSPredicateEvaluator.h; sourceTree = ""; }; + D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateEvaluator.m; path = test/TDNSPredicateEvaluator.m; sourceTree = ""; }; + D355C62F0FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateEvaluatorTest.h; path = test/TDNSPredicateEvaluatorTest.h; sourceTree = ""; }; + D355C6300FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateEvaluatorTest.m; path = test/TDNSPredicateEvaluatorTest.m; sourceTree = ""; }; + D355C8800FEB36A1006A91A4 /* xml.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = xml.grammar; path = res/xml.grammar; sourceTree = ""; }; + D355C8830FEB4B94006A91A4 /* proto.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = proto.grammar; path = res/proto.grammar; sourceTree = ""; }; + D36568A50EEF9FE900226554 /* TDPlistParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPlistParser.h; path = test/TDPlistParser.h; sourceTree = ""; }; + D36568A60EEF9FE900226554 /* TDPlistParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPlistParser.m; path = test/TDPlistParser.m; sourceTree = ""; }; + D36568A80EEFA05300226554 /* TDPlistParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPlistParserTest.h; path = test/TDPlistParserTest.h; sourceTree = ""; }; + D36568A90EEFA05300226554 /* TDPlistParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPlistParserTest.m; path = test/TDPlistParserTest.m; sourceTree = ""; }; + D3656DFC0EF2620E00226554 /* TDTokenArraySourceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenArraySourceTest.h; path = test/TDTokenArraySourceTest.h; sourceTree = ""; }; + D3656DFD0EF2620E00226554 /* TDTokenArraySourceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenArraySourceTest.m; path = test/TDTokenArraySourceTest.m; sourceTree = ""; }; + D3668291101D2BFA0008632C /* erb.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = erb.grammar; path = res/erb.grammar; sourceTree = ""; }; + D3668294101D2C200008632C /* ERBTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ERBTest.h; path = test/ERBTest.h; sourceTree = ""; }; + D3668295101D2C200008632C /* ERBTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ERBTest.m; path = test/ERBTest.m; sourceTree = ""; }; + D36934551038DE5300527AF3 /* PKParseTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParseTree.h; path = test/PKParseTree.h; sourceTree = ""; }; + D36934561038DE5300527AF3 /* PKParseTree.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParseTree.m; path = test/PKParseTree.m; sourceTree = ""; }; + D36934571038DE5300527AF3 /* PKParseTreeAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParseTreeAssembler.h; path = test/PKParseTreeAssembler.h; sourceTree = ""; }; + D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParseTreeAssembler.m; path = test/PKParseTreeAssembler.m; sourceTree = ""; }; + D36934591038DE5300527AF3 /* PKRuleNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKRuleNode.h; path = test/PKRuleNode.h; sourceTree = ""; }; + D369345A1038DE5300527AF3 /* PKRuleNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKRuleNode.m; path = test/PKRuleNode.m; sourceTree = ""; }; + D369345B1038DE5300527AF3 /* PKTokenNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenNode.h; path = test/PKTokenNode.h; sourceTree = ""; }; + D369345C1038DE5300527AF3 /* PKTokenNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenNode.m; path = test/PKTokenNode.m; sourceTree = ""; }; + D36C53770FD27F1300141CB7 /* TDParserFactoryTest2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryTest2.h; path = test/TDParserFactoryTest2.h; sourceTree = ""; }; + D36C53780FD27F1300141CB7 /* TDParserFactoryTest2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryTest2.m; path = test/TDParserFactoryTest2.m; sourceTree = ""; }; + D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegexKitLite.h; path = src/RegexKitLite.h; sourceTree = ""; }; + D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RegexKitLite.m; path = src/RegexKitLite.m; sourceTree = ""; }; + D36C560B0FD363D500141CB7 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = /usr/lib/libicucore.dylib; sourceTree = ""; }; + D36C56290FD365DB00141CB7 /* TDPatternTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPatternTest.h; path = test/TDPatternTest.h; sourceTree = ""; }; + D36C562A0FD365DB00141CB7 /* TDPatternTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPatternTest.m; path = test/TDPatternTest.m; sourceTree = ""; }; + D36E95440E578ECC00496BD3 /* XPathParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathParser.h; path = test/XPathParser.h; sourceTree = ""; }; + D36E95450E578ECC00496BD3 /* XPathParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathParser.m; path = test/XPathParser.m; sourceTree = ""; }; + D36E95D60E57B08400496BD3 /* XPathParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathParserTest.h; path = test/XPathParserTest.h; sourceTree = ""; }; + D36E95D70E57B08400496BD3 /* XPathParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathParserTest.m; path = test/XPathParserTest.m; sourceTree = ""; }; + D36E97AE0E589DAE00496BD3 /* XPathAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathAssembler.h; path = test/XPathAssembler.h; sourceTree = ""; }; + D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathAssembler.m; path = test/XPathAssembler.m; sourceTree = ""; }; + D36E98200E58A3A800496BD3 /* XPathContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathContext.h; path = test/XPathContext.h; sourceTree = ""; }; + D36E98210E58A3A800496BD3 /* XPathContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathContext.m; path = test/XPathContext.m; sourceTree = ""; }; + D36E98DC0E58C12800496BD3 /* DebugAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugAppDelegate.h; sourceTree = ""; }; + D36E98DD0E58C12800496BD3 /* DebugAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugAppDelegate.m; sourceTree = ""; }; + D36E98DE0E58C12800496BD3 /* DebugAppMainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DebugAppMainMenu.xib; sourceTree = ""; }; + D36E98DF0E58C12800496BD3 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + D36E98E30E58C14000496BD3 /* DemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DemoAppDelegate.h; path = demoapp/DemoAppDelegate.h; sourceTree = ""; }; + D36E98E40E58C14000496BD3 /* DemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DemoAppDelegate.m; path = demoapp/DemoAppDelegate.m; sourceTree = ""; }; + D36E98E50E58C14000496BD3 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = demoapp/main.m; sourceTree = ""; }; + D36E98F70E58C1A000496BD3 /* DemoAppMainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DemoAppMainMenu.xib; path = demoapp/DemoAppMainMenu.xib; sourceTree = ""; }; + D36E9F860E5A795400496BD3 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = /usr/lib/libxml2.dylib; sourceTree = ""; }; + D36E9FB40E5A944A00496BD3 /* apple-boss.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "apple-boss.xml"; path = "res/apple-boss.xml"; sourceTree = ""; }; + D36E9FE40E5BA0FC00496BD3 /* SRGSGrammar.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = SRGSGrammar.txt; path = res/SRGSGrammar.txt; sourceTree = ""; }; + D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "small-xml-file.xml"; path = "res/small-xml-file.xml"; sourceTree = ""; }; + D380AFBB0F0C54B60009EC13 /* html.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = html.css; path = res/html.css; sourceTree = ""; }; + D380AFBC0F0C54B60009EC13 /* html.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = html.grammar; path = res/html.grammar; sourceTree = ""; }; + D380AFC20F0C56000009EC13 /* example.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = example.html; path = res/example.html; sourceTree = ""; }; + D380B5080F0D71A90009EC13 /* css.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = css.grammar; path = res/css.grammar; sourceTree = ""; }; + D380B5370F0D7DDE0009EC13 /* css.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = css.css; path = res/css.css; sourceTree = ""; }; + D380B5930F0D82F60009EC13 /* example.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = example.css; path = res/example.css; sourceTree = ""; }; + D380BA5F0F0F06CD0009EC13 /* TDParserFactoryTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryTest.h; path = test/TDParserFactoryTest.h; sourceTree = ""; }; + D380BA600F0F06CD0009EC13 /* TDParserFactoryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryTest.m; path = test/TDParserFactoryTest.m; sourceTree = ""; }; + D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = /System/Library/Frameworks/JavaScriptCore.framework; sourceTree = ""; }; + D38205BC0EEE48EE004340DD /* TDTokenTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenTest.h; path = test/TDTokenTest.h; sourceTree = ""; }; + D38205BD0EEE48EE004340DD /* TDTokenTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenTest.m; path = test/TDTokenTest.m; sourceTree = ""; }; + D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json_with_comments.grammar; path = res/json_with_comments.grammar; sourceTree = ""; }; + D38349BB0F0C0D910055E4E0 /* json_with_comments.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = json_with_comments.css; path = res/json_with_comments.css; sourceTree = ""; }; + D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = yahoo_with_comments.json; path = res/yahoo_with_comments.json; sourceTree = ""; }; + D385F9880F046FE900DB2946 /* TDGenericAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDGenericAssembler.h; path = test/TDGenericAssembler.h; sourceTree = ""; }; + D385F9890F046FE900DB2946 /* TDGenericAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDGenericAssembler.m; path = test/TDGenericAssembler.m; sourceTree = ""; }; + D385FA210F04971400DB2946 /* TDGenericAssemblerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDGenericAssemblerTest.h; path = test/TDGenericAssemblerTest.h; sourceTree = ""; }; + D385FA220F04971400DB2946 /* TDGenericAssemblerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDGenericAssemblerTest.m; path = test/TDGenericAssemblerTest.m; sourceTree = ""; }; + D385FA240F04993500DB2946 /* json.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = json.css; path = res/json.css; sourceTree = ""; }; + D385FD400F05A88C00DB2946 /* TDMiniCSSAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDMiniCSSAssembler.h; path = test/TDMiniCSSAssembler.h; sourceTree = ""; }; + D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDMiniCSSAssembler.m; path = test/TDMiniCSSAssembler.m; sourceTree = ""; }; + D385FD420F05A88C00DB2946 /* TDMiniCSSAssemblerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDMiniCSSAssemblerTest.h; path = test/TDMiniCSSAssemblerTest.h; sourceTree = ""; }; + D385FD430F05A88C00DB2946 /* TDMiniCSSAssemblerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDMiniCSSAssemblerTest.m; path = test/TDMiniCSSAssemblerTest.m; sourceTree = ""; }; + D385FD6B0F05A99900DB2946 /* mini_css.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mini_css.grammar; path = res/mini_css.grammar; sourceTree = ""; }; + D389A0B00F1FCC99003B43BD /* RelaxParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RelaxParser.h; path = test/RelaxParser.h; sourceTree = ""; }; + D389A0B10F1FCC99003B43BD /* RelaxParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RelaxParser.m; path = test/RelaxParser.m; sourceTree = ""; }; + D389F1CE0F1965E600558235 /* JSParseKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSParseKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D389F2030F196A7500558235 /* JSDemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSDemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D389F20D0F196A9200558235 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + D389F2E30F196CAE00558235 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = jsdemoapp/main.m; sourceTree = ""; }; + D389F2E80F196F5B00558235 /* JSDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSDemoAppDelegate.h; path = jsdemoapp/JSDemoAppDelegate.h; sourceTree = ""; }; + D389F2E90F196F5B00558235 /* JSDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSDemoAppDelegate.m; path = jsdemoapp/JSDemoAppDelegate.m; sourceTree = ""; }; + D389F38E0F19800400558235 /* DefaultValues.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = DefaultValues.plist; path = jsdemoapp/DefaultValues.plist; sourceTree = ""; }; + D389F4610F198A8800558235 /* Test.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = Test.html; path = jsdemoapp/Test.html; sourceTree = ""; }; + D389F5580F19B7BC00558235 /* JSDemoAppMainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = JSDemoAppMainMenu.xib; path = jsdemoapp/JSDemoAppMainMenu.xib; sourceTree = ""; }; + D389F5B20F19C76A00558235 /* TDJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJsonParser.h; path = test/TDJsonParser.h; sourceTree = ""; }; + D389F5B30F19C76A00558235 /* TDJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJsonParser.m; path = test/TDJsonParser.m; sourceTree = ""; }; + D389F5B40F19C76A00558235 /* TDJsonParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJsonParserTest.h; path = test/TDJsonParserTest.h; sourceTree = ""; }; + D389F5B50F19C76A00558235 /* TDJsonParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJsonParserTest.m; path = test/TDJsonParserTest.m; sourceTree = ""; }; + D389FBCC0F1B25E200558235 /* ParserTest.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = ParserTest.html; path = jsdemoapp/ParserTest.html; sourceTree = ""; }; + D38DD9E70EC29F260070BC4D /* nyt.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = nyt.html; path = res/nyt.html; sourceTree = ""; }; + D38E97CA1061CF6500739C39 /* TDTokenizerBlocksTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenizerBlocksTest.h; path = test/TDTokenizerBlocksTest.h; sourceTree = ""; }; + D38E97CB1061CF6500739C39 /* TDTokenizerBlocksTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenizerBlocksTest.m; path = test/TDTokenizerBlocksTest.m; sourceTree = ""; }; + D38E98D61062C5BA00739C39 /* TDParserBlocksTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserBlocksTest.h; path = test/TDParserBlocksTest.h; sourceTree = ""; }; + D38E98D71062C5BA00739C39 /* TDParserBlocksTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserBlocksTest.m; path = test/TDParserBlocksTest.m; sourceTree = ""; }; + D3AF49760FDB122E0032F4DC /* TDParserFactoryPatternTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryPatternTest.h; path = test/TDParserFactoryPatternTest.h; sourceTree = ""; }; + D3AF49770FDB122E0032F4DC /* TDParserFactoryPatternTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryPatternTest.m; path = test/TDParserFactoryPatternTest.m; sourceTree = ""; }; + D3AF4BE80FDC3DD50032F4DC /* TDBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDBlob.h; path = test/TDBlob.h; sourceTree = ""; }; + D3AF4BE90FDC3DD50032F4DC /* TDBlob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDBlob.m; path = test/TDBlob.m; sourceTree = ""; }; + D3AF4BF50FDC40050032F4DC /* TDToken+Blob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TDToken+Blob.h"; path = "test/TDToken+Blob.h"; sourceTree = ""; }; + D3AF4BF60FDC40050032F4DC /* TDToken+Blob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "TDToken+Blob.m"; path = "test/TDToken+Blob.m"; sourceTree = ""; }; + D3AF4BFB0FDC41190032F4DC /* TDTokenizer+BlobState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TDTokenizer+BlobState.h"; path = "test/TDTokenizer+BlobState.h"; sourceTree = ""; }; + D3AF4BFC0FDC41190032F4DC /* TDTokenizer+BlobState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "TDTokenizer+BlobState.m"; path = "test/TDTokenizer+BlobState.m"; sourceTree = ""; }; + D3AF4C190FDC568F0032F4DC /* TDBlobState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDBlobState.h; path = test/TDBlobState.h; sourceTree = ""; }; + D3AF4C1A0FDC568F0032F4DC /* TDBlobState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDBlobState.m; path = test/TDBlobState.m; sourceTree = ""; }; + D3AF4CBF0FDC740A0032F4DC /* TDNonReservedWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNonReservedWord.h; path = test/TDNonReservedWord.h; sourceTree = ""; }; + D3AF4CC00FDC740A0032F4DC /* TDNonReservedWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNonReservedWord.m; path = test/TDNonReservedWord.m; sourceTree = ""; }; + D3AF4CC10FDC740A0032F4DC /* TDReservedWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDReservedWord.h; path = test/TDReservedWord.h; sourceTree = ""; }; + D3AF4CC20FDC740A0032F4DC /* TDReservedWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDReservedWord.m; path = test/TDReservedWord.m; sourceTree = ""; }; + D3AF4CC30FDC740A0032F4DC /* TDSignificantWhitespaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSignificantWhitespaceState.h; path = test/TDSignificantWhitespaceState.h; sourceTree = ""; }; + D3AF4CC40FDC740A0032F4DC /* TDSignificantWhitespaceState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSignificantWhitespaceState.m; path = test/TDSignificantWhitespaceState.m; sourceTree = ""; }; + D3AF4CC50FDC740A0032F4DC /* TDWordOrReservedState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDWordOrReservedState.h; path = test/TDWordOrReservedState.h; sourceTree = ""; }; + D3AF4CC60FDC740A0032F4DC /* TDWordOrReservedState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDWordOrReservedState.m; path = test/TDWordOrReservedState.m; sourceTree = ""; }; + D3B43FB50F76E99C0072AF40 /* TDJavaScriptParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJavaScriptParserTest.h; path = test/TDJavaScriptParserTest.h; sourceTree = ""; }; + D3B43FB60F76E99C0072AF40 /* TDJavaScriptParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJavaScriptParserTest.m; path = test/TDJavaScriptParserTest.m; sourceTree = ""; }; + D3B473840E48C9CF008AFBDD /* yahoo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = yahoo.json; path = res/yahoo.json; sourceTree = ""; }; + D3B69D310E80249900D70C41 /* nonascii.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = nonascii.html; path = res/nonascii.html; sourceTree = ""; }; + D3BBBC960FEC9722007DF30D /* TDXMLParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXMLParserTest.h; path = test/TDXMLParserTest.h; sourceTree = ""; }; + D3BBBC970FEC9722007DF30D /* TDXMLParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXMLParserTest.m; path = test/TDXMLParserTest.m; sourceTree = ""; }; + D3BBBC9B0FEC9756007DF30D /* TDXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXMLParser.h; path = test/TDXMLParser.h; sourceTree = ""; }; + D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXMLParser.m; path = test/TDXMLParser.m; sourceTree = ""; }; + D3C031EB0EF38D2D00C5ABEB /* TDLowercaseWordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDLowercaseWordTest.h; path = test/TDLowercaseWordTest.h; sourceTree = ""; }; + D3C031EC0EF38D2D00C5ABEB /* TDLowercaseWordTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDLowercaseWordTest.m; path = test/TDLowercaseWordTest.m; sourceTree = ""; }; + D3C2216D0FFE8A86004514FE /* PKExclusion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKExclusion.h; path = test/PKExclusion.h; sourceTree = ""; }; + D3C221900FFE8B8C004514FE /* ParseKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ParseKit.h; path = include/ParseKit/ParseKit.h; sourceTree = ""; }; + D3C221910FFE8B8C004514FE /* PKTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTypes.h; path = include/ParseKit/PKTypes.h; sourceTree = ""; }; + D3C221960FFE8B95004514FE /* PKReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKReader.h; path = include/ParseKit/PKReader.h; sourceTree = ""; }; + D3C221990FFE8B9D004514FE /* PKAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAssembly.h; path = include/ParseKit/PKAssembly.h; sourceTree = ""; }; + D3C2219C0FFE8BA6004514FE /* PKParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParser.h; path = include/ParseKit/PKParser.h; sourceTree = ""; }; + D3C2219F0FFE8BAE004514FE /* PKRepetition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKRepetition.h; path = include/ParseKit/PKRepetition.h; sourceTree = ""; }; + D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCollectionParser.h; path = include/ParseKit/PKCollectionParser.h; sourceTree = ""; }; + D3C221A50FFE8BC1004514FE /* PKAlternation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAlternation.h; path = include/ParseKit/PKAlternation.h; sourceTree = ""; }; + D3C221A80FFE8BC9004514FE /* PKSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSequence.h; path = include/ParseKit/PKSequence.h; sourceTree = ""; }; + D3C221AB0FFE8BCF004514FE /* PKTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTrack.h; path = include/ParseKit/PKTrack.h; sourceTree = ""; }; + D3C221AE0FFE8BD4004514FE /* PKTrackException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTrackException.h; path = include/ParseKit/PKTrackException.h; sourceTree = ""; }; + D3C221B10FFE8BDB004514FE /* PKIntersection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKIntersection.h; path = include/ParseKit/PKIntersection.h; sourceTree = ""; }; + D3C221B40FFE8BE2004514FE /* PKDifference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDifference.h; path = include/ParseKit/PKDifference.h; sourceTree = ""; }; + D3C221B70FFE8BE8004514FE /* PKNegation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKNegation.h; path = include/ParseKit/PKNegation.h; sourceTree = ""; }; + D3C221BA0FFE8BEF004514FE /* PKTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTerminal.h; path = include/ParseKit/PKTerminal.h; sourceTree = ""; }; + D3C221BD0FFE8BF7004514FE /* PKEmpty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKEmpty.h; path = include/ParseKit/PKEmpty.h; sourceTree = ""; }; + D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenAssembly.h; path = include/ParseKit/PKTokenAssembly.h; sourceTree = ""; }; + D3C221C30FFE8C07004514FE /* PKToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKToken.h; path = include/ParseKit/PKToken.h; sourceTree = ""; }; + D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenArraySource.h; path = include/ParseKit/PKTokenArraySource.h; sourceTree = ""; }; + D3C221C90FFE8C15004514FE /* PKTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenizer.h; path = include/ParseKit/PKTokenizer.h; sourceTree = ""; }; + D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenizerState.h; path = include/ParseKit/PKTokenizerState.h; sourceTree = ""; }; + D3C221CF0FFE8C24004514FE /* PKNumberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKNumberState.h; path = include/ParseKit/PKNumberState.h; sourceTree = ""; }; + D3C221D50FFE8C35004514FE /* PKSymbolState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbolState.h; path = include/ParseKit/PKSymbolState.h; sourceTree = ""; }; + D3C221D80FFE8C3D004514FE /* PKWordState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWordState.h; path = include/ParseKit/PKWordState.h; sourceTree = ""; }; + D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWhitespaceState.h; path = include/ParseKit/PKWhitespaceState.h; sourceTree = ""; }; + D3C221DE0FFE8C49004514FE /* PKDelimitState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDelimitState.h; path = include/ParseKit/PKDelimitState.h; sourceTree = ""; }; + D3C221E10FFE8C4E004514FE /* PKCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCommentState.h; path = include/ParseKit/PKCommentState.h; sourceTree = ""; }; + D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSingleLineCommentState.h; path = include/ParseKit/PKSingleLineCommentState.h; sourceTree = ""; }; + D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKMultiLineCommentState.h; path = include/ParseKit/PKMultiLineCommentState.h; sourceTree = ""; }; + D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbolNode.h; path = include/ParseKit/PKSymbolNode.h; sourceTree = ""; }; + D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbolRootNode.h; path = include/ParseKit/PKSymbolRootNode.h; sourceTree = ""; }; + D3C221F00FFE8C7A004514FE /* PKPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKPattern.h; path = include/ParseKit/PKPattern.h; sourceTree = ""; }; + D3C221F30FFE8C87004514FE /* PKWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWord.h; path = include/ParseKit/PKWord.h; sourceTree = ""; }; + D3C221F60FFE8C8E004514FE /* PKNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKNumber.h; path = include/ParseKit/PKNumber.h; sourceTree = ""; }; + D3C221F90FFE8C97004514FE /* PKQuotedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKQuotedString.h; path = include/ParseKit/PKQuotedString.h; sourceTree = ""; }; + D3C221FC0FFE8CB2004514FE /* PKSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbol.h; path = include/ParseKit/PKSymbol.h; sourceTree = ""; }; + D3C221FF0FFE8CB9004514FE /* PKLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKLiteral.h; path = include/ParseKit/PKLiteral.h; sourceTree = ""; }; + D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCaseInsensitiveLiteral.h; path = include/ParseKit/PKCaseInsensitiveLiteral.h; sourceTree = ""; }; + D3C222050FFE8CCA004514FE /* PKWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWhitespace.h; path = include/ParseKit/PKWhitespace.h; sourceTree = ""; }; + D3C222080FFE8CD1004514FE /* PKComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKComment.h; path = include/ParseKit/PKComment.h; sourceTree = ""; }; + D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDelimitedString.h; path = include/ParseKit/PKDelimitedString.h; sourceTree = ""; }; + D3C2220E0FFE8CDF004514FE /* PKAny.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAny.h; path = include/ParseKit/PKAny.h; sourceTree = ""; }; + D3C222140FFE8D01004514FE /* PKLowercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKLowercaseWord.h; path = include/ParseKit/PKLowercaseWord.h; sourceTree = ""; }; + D3C222170FFE8D11004514FE /* PKUppercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKUppercaseWord.h; path = include/ParseKit/PKUppercaseWord.h; sourceTree = ""; }; + D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCharacterAssembly.h; path = include/ParseKit/PKCharacterAssembly.h; sourceTree = ""; }; + D3C2221D0FFE8D3B004514FE /* PKChar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKChar.h; path = include/ParseKit/PKChar.h; sourceTree = ""; }; + D3C222200FFE8D42004514FE /* PKDigit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDigit.h; path = include/ParseKit/PKDigit.h; sourceTree = ""; }; + D3C222230FFE8D49004514FE /* PKLetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKLetter.h; path = include/ParseKit/PKLetter.h; sourceTree = ""; }; + D3C222260FFE8D6B004514FE /* PKSpecificChar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSpecificChar.h; path = include/ParseKit/PKSpecificChar.h; sourceTree = ""; }; + D3C222290FFE8DAC004514FE /* PKParserFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParserFactory.h; path = include/ParseKit/PKParserFactory.h; sourceTree = ""; }; + D3C7D87A0A411FBF005DD154 /* Tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; + D3C85C790E63B438000445FD /* TDArithmeticParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDArithmeticParser.h; path = test/TDArithmeticParser.h; sourceTree = ""; }; + D3C85C7A0E63B438000445FD /* TDArithmeticParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDArithmeticParser.m; path = test/TDArithmeticParser.m; sourceTree = ""; }; + D3C85C7E0E63B9E9000445FD /* TDArithmeticParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDArithmeticParserTest.h; path = test/TDArithmeticParserTest.h; sourceTree = ""; }; + D3C85C7F0E63B9E9000445FD /* TDArithmeticParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDArithmeticParserTest.m; path = test/TDArithmeticParserTest.m; sourceTree = ""; }; + D3C85D430E63D1BF000445FD /* TDScientificNumberStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDScientificNumberStateTest.h; path = test/TDScientificNumberStateTest.h; sourceTree = ""; }; + D3C85D440E63D1BF000445FD /* TDScientificNumberStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDScientificNumberStateTest.m; path = test/TDScientificNumberStateTest.m; sourceTree = ""; }; + D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json_with_discards.grammar; path = res/json_with_discards.grammar; sourceTree = ""; }; + D3D1BF2610394420003656E5 /* SAXAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SAXAssembler.h; path = test/SAXAssembler.h; sourceTree = ""; }; + D3D1BF2710394420003656E5 /* SAXAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SAXAssembler.m; path = test/SAXAssembler.m; sourceTree = ""; }; + D3D1BF291039445C003656E5 /* SAXTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SAXTest.h; path = test/SAXTest.h; sourceTree = ""; }; + D3D1BF2A1039445C003656E5 /* SAXTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SAXTest.m; path = test/SAXTest.m; sourceTree = ""; }; + D3DCB35C0EF5E52500DE5110 /* OCMock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OCMock.framework; path = frameworks/OCMock.framework; sourceTree = ""; }; + D3DCB4C20EF6015300DE5110 /* json.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json.grammar; path = res/json.grammar; sourceTree = ""; }; + D3DDDA850F0779FD00A58000 /* TDSyntaxHighlighter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSyntaxHighlighter.h; path = test/TDSyntaxHighlighter.h; sourceTree = ""; }; + D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSyntaxHighlighter.m; path = test/TDSyntaxHighlighter.m; sourceTree = ""; }; + D3DDDAFC0F083C9700A58000 /* TDCommentStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDCommentStateTest.h; path = test/TDCommentStateTest.h; sourceTree = ""; }; + D3DDDAFD0F083C9700A58000 /* TDCommentStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDCommentStateTest.m; path = test/TDCommentStateTest.m; sourceTree = ""; }; + D3DDDC230F085C5400A58000 /* TDSlashSlashState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashSlashState.h; path = test/TDSlashSlashState.h; sourceTree = ""; }; + D3DDDC240F085C5400A58000 /* TDSlashSlashState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashSlashState.m; path = test/TDSlashSlashState.m; sourceTree = ""; }; + D3DDDC250F085C5400A58000 /* TDSlashStarState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashStarState.h; path = test/TDSlashStarState.h; sourceTree = ""; }; + D3DDDC260F085C5400A58000 /* TDSlashStarState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashStarState.m; path = test/TDSlashStarState.m; sourceTree = ""; }; + D3DDDC270F085C5400A58000 /* TDSlashState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashState.h; path = test/TDSlashState.h; sourceTree = ""; }; + D3DDDC280F085C5400A58000 /* TDSlashState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashState.m; path = test/TDSlashState.m; sourceTree = ""; }; + D3DDDCAC0F0880D800A58000 /* example1.srgs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = example1.srgs; path = res/example1.srgs; sourceTree = ""; }; + D3E39C3D0FC5FFD10022DAB9 /* TDDelimitStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDDelimitStateTest.h; path = test/TDDelimitStateTest.h; sourceTree = ""; }; + D3E39C3E0FC5FFD10022DAB9 /* TDDelimitStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDDelimitStateTest.m; path = test/TDDelimitStateTest.m; sourceTree = ""; }; + D3E784BC0E53DA28008C7D61 /* apple-boss.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "apple-boss.json"; path = "res/apple-boss.json"; sourceTree = ""; }; + D3E788910E567DFD008C7D61 /* SRGSParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SRGSParserTest.h; path = test/SRGSParserTest.h; sourceTree = ""; }; + D3E788920E567DFD008C7D61 /* SRGSParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SRGSParserTest.m; path = test/SRGSParserTest.m; sourceTree = ""; }; + D3E788940E567E0A008C7D61 /* SRGSParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SRGSParser.h; path = test/SRGSParser.h; sourceTree = ""; }; + D3E788950E567E0A008C7D61 /* SRGSParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SRGSParser.m; path = test/SRGSParser.m; sourceTree = ""; }; + D3E78A150E574C99008C7D61 /* EBNFParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EBNFParser.h; path = test/EBNFParser.h; sourceTree = ""; }; + D3E78A160E574C99008C7D61 /* EBNFParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EBNFParser.m; path = test/EBNFParser.m; sourceTree = ""; }; + D3E78A170E574C99008C7D61 /* EBNFParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EBNFParserTest.h; path = test/EBNFParserTest.h; sourceTree = ""; }; + D3E78A180E574C99008C7D61 /* EBNFParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EBNFParserTest.m; path = test/EBNFParserTest.m; sourceTree = ""; }; + D3EADD7F0E75E9CC00F78584 /* nasty.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = nasty.html; path = res/nasty.html; sourceTree = ""; }; + D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDHtmlSyntaxHighlighter.m; path = test/TDHtmlSyntaxHighlighter.m; sourceTree = ""; }; + D3EADD8D0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDHtmlSyntaxHighlighter.h; path = test/TDHtmlSyntaxHighlighter.h; sourceTree = ""; }; + D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKQuoteState.h; path = include/ParseKit/PKQuoteState.h; sourceTree = ""; }; + D3F0E3290FFEA1E200C9DF74 /* DebugApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "DebugApp-Info.plist"; sourceTree = ""; }; + D3F0E3600FFEA2B500C9DF74 /* DemoApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "DemoApp-Info.plist"; path = "demoapp/DemoApp-Info.plist"; sourceTree = ""; }; + D3F0E36C0FFEA33700C9DF74 /* Tests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Tests-Info.plist"; path = "test/Tests-Info.plist"; sourceTree = ""; }; + D3F0E37A0FFEA39000C9DF74 /* JSDemoApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "JSDemoApp-Info.plist"; path = "jsdemoapp/JSDemoApp-Info.plist"; sourceTree = ""; }; + D3F55F5F1025737D00DD6DB1 /* TDParseTreeTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParseTreeTest.h; path = test/TDParseTreeTest.h; sourceTree = ""; }; + D3F55F601025737D00DD6DB1 /* TDParseTreeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParseTreeTest.m; path = test/TDParseTreeTest.m; sourceTree = ""; }; + D3F5629810266CFC00DD6DB1 /* PKParseTreeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParseTreeView.h; path = demoapp/PKParseTreeView.h; sourceTree = ""; }; + D3F5629910266CFC00DD6DB1 /* PKParseTreeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParseTreeView.m; path = demoapp/PKParseTreeView.m; sourceTree = ""; }; + D3F5629E10266DFB00DD6DB1 /* DemoTokensViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DemoTokensViewController.h; path = demoapp/DemoTokensViewController.h; sourceTree = ""; }; + D3F5629F10266DFB00DD6DB1 /* DemoTokensViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DemoTokensViewController.m; path = demoapp/DemoTokensViewController.m; sourceTree = ""; }; + D3F562A110266E5300DD6DB1 /* TokensView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = TokensView.xib; path = demoapp/TokensView.xib; sourceTree = ""; }; + D3F562A310266E6300DD6DB1 /* TreesView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = TreesView.xib; path = demoapp/TreesView.xib; sourceTree = ""; }; + D3F562A510266E8D00DD6DB1 /* DemoTreesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DemoTreesViewController.h; path = demoapp/DemoTreesViewController.h; sourceTree = ""; }; + D3F562A610266E8D00DD6DB1 /* DemoTreesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DemoTreesViewController.m; path = demoapp/DemoTreesViewController.m; sourceTree = ""; }; + D3F740B50EF8C38A00559B9F /* JSONAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONAssembler.h; sourceTree = ""; }; + D3F740B60EF8C38A00559B9F /* JSONAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONAssembler.m; sourceTree = ""; }; + D3F741430EF8E96A00559B9F /* xpath1_0.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = xpath1_0.grammar; path = res/xpath1_0.grammar; sourceTree = ""; }; + D3F741BD0EF9F28D00559B9F /* css2_1.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = css2_1.grammar; path = res/css2_1.grammar; sourceTree = ""; }; + D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = rubyhash.grammar; path = res/rubyhash.grammar; sourceTree = ""; }; + D3FDC5830FFC4BFC00F1F797 /* libparsekit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libparsekit.a; sourceTree = BUILT_PRODUCTS_DIR; }; + D3FDC7360FFC4D6100F1F797 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + D3FDC7380FFC4D6100F1F797 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; }; + D3FDC74B0FFC4DAC00F1F797 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + D3FDC8DB0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseKitMobile_Prefix.pch; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DC2EF560486A6940098B216 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3E787A30E5661A9008C7D61 /* Foundation.framework in Frameworks */, + D36C560C0FD363D500141CB7 /* libicucore.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D334940E0E2963FD00406085 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D33494720E29670B00406085 /* ParseKit.framework in Frameworks */, + D37D3A000FE77A71008C2E4D /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D34185020E520D3F0081B0DC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D31FE7380E60F36600A0803E /* libxml2.dylib in Frameworks */, + D341850C0E520D640081B0DC /* ParseKit.framework in Frameworks */, + D380B9800F0EF3860009EC13 /* OCMock.framework in Frameworks */, + D380BAA30F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */, + D37D3A010FE77A72008C2E4D /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1CC0F1965E600558235 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F34E0F197DF500558235 /* JavaScriptCore.framework in Frameworks */, + D389F1D50F19666500558235 /* ParseKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F2010F196A7500558235 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F3430F197DDC00558235 /* JavaScriptCore.framework in Frameworks */, + D389F20E0F196A9200558235 /* WebKit.framework in Frameworks */, + D389F20C0F196A9200558235 /* ParseKit.framework in Frameworks */, + D389F20B0F196A9200558235 /* JSParseKit.framework in Frameworks */, + D37D3A020FE77A77008C2E4D /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3C7D8770A411FBF005DD154 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3DCB37D0EF5E5E400DE5110 /* OCMock.framework in Frameworks */, + D3C7D9DA0A412874005DD154 /* ParseKit.framework in Frameworks */, + D36E9F870E5A795400496BD3 /* libxml2.dylib in Frameworks */, + D380BAA40F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */, + D3587EAF0FE83EC900DDD023 /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3FDC5810FFC4BFC00F1F797 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3FDC7370FFC4D6100F1F797 /* Foundation.framework in Frameworks */, + D3FDC7390FFC4D6100F1F797 /* libicucore.dylib in Frameworks */, + D3FDC74C0FFC4DAC00F1F797 /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 034768DFFF38A50411DB9C8B /* Products */ = { + isa = PBXGroup; + children = ( + 8DC2EF5B0486A6940098B216 /* ParseKit.framework */, + D389F1CE0F1965E600558235 /* JSParseKit.framework */, + D3C7D87A0A411FBF005DD154 /* Tests.octest */, + D33494100E2963FD00406085 /* DemoApp.app */, + D34185040E520D3F0081B0DC /* DebugApp.app */, + D389F2030F196A7500558235 /* JSDemoApp.app */, + D3FDC5830FFC4BFC00F1F797 /* libparsekit.a */, + ); + name = Products; + sourceTree = ""; + }; + 0867D691FE84028FC02AAC07 /* TODParseKit */ = { + isa = PBXGroup; + children = ( + 08FB77AEFE84172EC02AAC07 /* ParseKit Framework */, + D3C7D8220A411F31005DD154 /* ParseKit Tests */, + D36E98CB0E58C08F00496BD3 /* DebugApp */, + D334941B0E29641300406085 /* DemoApp */, + D380BA950F0F1C450009EC13 /* JSParseKit Framework */, + D389F2CA0F196ACF00558235 /* JSDemoApp */, + D3AF4C8E0FDC738B0032F4DC /* Other Sources */, + 32C88DFF0371C24200C91783 /* Other Sources (not used) */, + 089C1665FE841158C02AAC07 /* Resources */, + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */, + 034768DFFF38A50411DB9C8B /* Products */, + ); + name = TODParseKit; + sourceTree = ""; + }; + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + D3FDC8EF0FFC52CD00F1F797 /* Mobile Frameworks */, + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */, + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 089C1665FE841158C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + 8DC2EF5A0486A6940098B216 /* Info.plist */, + 089C1666FE841158C02AAC07 /* InfoPlist.strings */, + ); + name = Resources; + sourceTree = ""; + }; + 08FB77AEFE84172EC02AAC07 /* ParseKit Framework */ = { + isa = PBXGroup; + children = ( + D3C221900FFE8B8C004514FE /* ParseKit.h */, + D3C221910FFE8B8C004514FE /* PKTypes.h */, + D3C7D8710A411F6B005DD154 /* io */, + D3C7D8720A411F81005DD154 /* parse */, + D3C7D8740A411F8E005DD154 /* tokens */, + D3E785F10E550F63008C7D61 /* chars */, + D34BAC0F0FF87ED200D7773A /* grammar */, + ); + name = "ParseKit Framework"; + sourceTree = ""; + }; + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + D389F20D0F196A9200558235 /* WebKit.framework */, + D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */, + D3DCB35C0EF5E52500DE5110 /* OCMock.framework */, + D36E9F860E5A795400496BD3 /* libxml2.dylib */, + D36C560B0FD363D500141CB7 /* libicucore.dylib */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 0867D6A5FE840307C02AAC07 /* AppKit.framework */, + 0867D69BFE84028FC02AAC07 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 32C88DFF0371C24200C91783 /* Other Sources (not used) */ = { + isa = PBXGroup; + children = ( + D3C2216D0FFE8A86004514FE /* PKExclusion.h */, + D31270F80FFE898300CBF4C4 /* PKExclusion.m */, + D3AF4CCB0FDC74540032F4DC /* Whitespace */, + D3AF4CCA0FDC74490032F4DC /* Slash */, + D3AF4CC90FDC743C0032F4DC /* ReservedWord */, + D3AF4CC80FDC74320032F4DC /* Blob */, + ); + name = "Other Sources (not used)"; + sourceTree = ""; + }; + D318EAE30E2FD5B6009F47DF /* json */ = { + isa = PBXGroup; + children = ( + D3E784BC0E53DA28008C7D61 /* apple-boss.json */, + D3B473840E48C9CF008AFBDD /* yahoo.json */, + D389F5B20F19C76A00558235 /* TDJsonParser.h */, + D389F5B30F19C76A00558235 /* TDJsonParser.m */, + D389F5B40F19C76A00558235 /* TDJsonParserTest.h */, + D389F5B50F19C76A00558235 /* TDJsonParserTest.m */, + D31FE5A10E60E5D500A0803E /* TDFastJsonParser.h */, + D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */, + D31FE5A30E60E5D500A0803E /* TDFastJsonParserTest.h */, + D31FE5A40E60E5D500A0803E /* TDFastJsonParserTest.m */, + ); + name = json; + sourceTree = ""; + }; + D31A164F0F703899002AFDF1 /* javascript */ = { + isa = PBXGroup; + children = ( + D31A16500F7038C2002AFDF1 /* TDJavaScriptParser.h */, + D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */, + D3B43FB50F76E99C0072AF40 /* TDJavaScriptParserTest.h */, + D3B43FB60F76E99C0072AF40 /* TDJavaScriptParserTest.m */, + ); + name = javascript; + sourceTree = ""; + }; + D3252F670FCE171D005EF059 /* predicate */ = { + isa = PBXGroup; + children = ( + D355C62B0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.h */, + D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */, + D355C62F0FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.h */, + D355C6300FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m */, + D35384EC0FE9691100926552 /* nspredicate.grammar */, + D3252F7C0FCE1A87005EF059 /* TDNSPredicateBuilder.h */, + D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */, + D3252F780FCE1A7E005EF059 /* TDNSPredicateBuilderTest.h */, + D3252F790FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m */, + D3385FD70FCFB1FF003BF729 /* TDPredicateEvaluator.h */, + D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */, + D3385FDB0FCFB227003BF729 /* TDPredicateEvaluatorTest.h */, + D3385FDC0FCFB227003BF729 /* TDPredicateEvaluatorTest.m */, + ); + name = predicate; + sourceTree = ""; + }; + D3305C52102F5BB300DC4F75 /* Trees */ = { + isa = PBXGroup; + children = ( + D3F562A310266E6300DD6DB1 /* TreesView.xib */, + D3F562A510266E8D00DD6DB1 /* DemoTreesViewController.h */, + D3F562A610266E8D00DD6DB1 /* DemoTreesViewController.m */, + D3F5629810266CFC00DD6DB1 /* PKParseTreeView.h */, + D3F5629910266CFC00DD6DB1 /* PKParseTreeView.m */, + D3305C53102F5BC500DC4F75 /* SourceCodeView */, + ); + name = Trees; + sourceTree = ""; + }; + D3305C53102F5BC500DC4F75 /* SourceCodeView */ = { + isa = PBXGroup; + children = ( + D3305C4B102F5BAD00DC4F75 /* TDGutterView.h */, + D3305C4C102F5BAD00DC4F75 /* TDGutterView.m */, + D3305C4D102F5BAE00DC4F75 /* TDSourceCodeTextView.h */, + D3305C4E102F5BAE00DC4F75 /* TDSourceCodeTextView.m */, + ); + name = SourceCodeView; + sourceTree = ""; + }; + D3305C54102F5BE500DC4F75 /* Tokens */ = { + isa = PBXGroup; + children = ( + D3F562A110266E5300DD6DB1 /* TokensView.xib */, + D3F5629E10266DFB00DD6DB1 /* DemoTokensViewController.h */, + D3F5629F10266DFB00DD6DB1 /* DemoTokensViewController.m */, + ); + name = Tokens; + sourceTree = ""; + }; + D334941B0E29641300406085 /* DemoApp */ = { + isa = PBXGroup; + children = ( + D3F0E3600FFEA2B500C9DF74 /* DemoApp-Info.plist */, + D36E98F70E58C1A000496BD3 /* DemoAppMainMenu.xib */, + D36E98E50E58C14000496BD3 /* main.m */, + D36E98E30E58C14000496BD3 /* DemoAppDelegate.h */, + D36E98E40E58C14000496BD3 /* DemoAppDelegate.m */, + D3305C54102F5BE500DC4F75 /* Tokens */, + D3305C52102F5BB300DC4F75 /* Trees */, + ); + name = DemoApp; + sourceTree = ""; + }; + D3376D1110091C6C00E4602E /* ParseTree */ = { + isa = PBXGroup; + children = ( + D3F55F5F1025737D00DD6DB1 /* TDParseTreeTest.h */, + D3F55F601025737D00DD6DB1 /* TDParseTreeTest.m */, + ); + name = ParseTree; + sourceTree = ""; + }; + D3376D7710096BDE00E4602E /* IR */ = { + isa = PBXGroup; + children = ( + D3F5619C1026374400DD6DB1 /* ir */, + D3376D1110091C6C00E4602E /* ParseTree */, + D3376D8B10096BEF00E4602E /* Homo */, + ); + name = IR; + sourceTree = ""; + }; + D3376D8B10096BEF00E4602E /* Homo */ = { + isa = PBXGroup; + children = ( + D3376D8C10096C0700E4602E /* PKAST.h */, + D3376D8D10096C0700E4602E /* PKAST.m */, + ); + name = Homo; + sourceTree = ""; + }; + D341846A0E5209A60081B0DC /* tokenizer */ = { + isa = PBXGroup; + children = ( + D3C221C30FFE8C07004514FE /* PKToken.h */, + D34BAE950FF9D20900D7773A /* PKToken.m */, + D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */, + D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */, + D3C221C90FFE8C15004514FE /* PKTokenizer.h */, + D34BAE990FF9D20900D7773A /* PKTokenizer.m */, + D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */, + D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */, + ); + name = tokenizer; + sourceTree = ""; + }; + D34A20080E55FD5F00A4A0BF /* chars */ = { + isa = PBXGroup; + children = ( + D31FE58C0E60E5AC00A0803E /* TDCharacterAssemblyTest.h */, + D31FE58D0E60E5AC00A0803E /* TDCharacterAssemblyTest.m */, + D31FE58E0E60E5AC00A0803E /* TDCharTest.h */, + D31FE58F0E60E5AC00A0803E /* TDCharTest.m */, + D31FE5900E60E5AC00A0803E /* TDDigitTest.h */, + D31FE5910E60E5AC00A0803E /* TDDigitTest.m */, + D31FE5920E60E5AC00A0803E /* TDLetterTest.h */, + D31FE5930E60E5AC00A0803E /* TDLetterTest.m */, + D31FE5940E60E5AC00A0803E /* TDSpecificCharTest.h */, + D31FE5950E60E5AC00A0803E /* TDSpecificCharTest.m */, + ); + name = chars; + sourceTree = ""; + }; + D34BAC0F0FF87ED200D7773A /* grammar */ = { + isa = PBXGroup; + children = ( + D3C222290FFE8DAC004514FE /* PKParserFactory.h */, + D34BAFD80FF9E95500D7773A /* PKParserFactory.m */, + D3376D5710093A1600E4602E /* PKGrammarParser.h */, + D3376D5810093A1600E4602E /* PKGrammarParser.m */, + D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */, + D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */, + D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */, + D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */, + ); + name = grammar; + sourceTree = ""; + }; + D3541F870DFB105900429B4F /* states */ = { + isa = PBXGroup; + children = ( + D3C221CF0FFE8C24004514FE /* PKNumberState.h */, + D34BAECA0FF9D56400D7773A /* PKNumberState.m */, + D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */, + D34BAECC0FF9D56400D7773A /* PKQuoteState.m */, + D3C221D50FFE8C35004514FE /* PKSymbolState.h */, + D34BAED00FF9D56400D7773A /* PKSymbolState.m */, + D3C221D80FFE8C3D004514FE /* PKWordState.h */, + D34BAED60FF9D56400D7773A /* PKWordState.m */, + D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */, + D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */, + D3C221DE0FFE8C49004514FE /* PKDelimitState.h */, + D34BAEC60FF9D56400D7773A /* PKDelimitState.m */, + D3C221E10FFE8C4E004514FE /* PKCommentState.h */, + D34BAEC40FF9D56400D7773A /* PKCommentState.m */, + D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */, + D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */, + D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */, + D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */, + D3541F890DFB108300429B4F /* symbol */, + ); + name = states; + sourceTree = ""; + }; + D3541F890DFB108300429B4F /* symbol */ = { + isa = PBXGroup; + children = ( + D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */, + D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */, + D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */, + D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */, + ); + name = symbol; + sourceTree = ""; + }; + D35420EC0DFB275400429B4F /* tokenizer states */ = { + isa = PBXGroup; + children = ( + D34BAD16100A9B7900996341 /* TDTokenizerStateTest.h */, + D34BAD17100A9B7900996341 /* TDTokenizerStateTest.m */, + D31FE5770E60E58C00A0803E /* TDNumberStateTest.h */, + D31FE5780E60E58C00A0803E /* TDNumberStateTest.m */, + D31FE5790E60E58C00A0803E /* TDQuoteStateTest.h */, + D31FE57A0E60E58C00A0803E /* TDQuoteStateTest.m */, + D31FE57F0E60E58C00A0803E /* TDSymbolStateTest.h */, + D31FE5800E60E58C00A0803E /* TDSymbolStateTest.m */, + D31FE5810E60E58C00A0803E /* TDWhitespaceStateTest.h */, + D31FE5820E60E58C00A0803E /* TDWhitespaceStateTest.m */, + D31FE5830E60E58C00A0803E /* TDWordStateTest.h */, + D31FE5840E60E58C00A0803E /* TDWordStateTest.m */, + D3C85D430E63D1BF000445FD /* TDScientificNumberStateTest.h */, + D3C85D440E63D1BF000445FD /* TDScientificNumberStateTest.m */, + D3DDDAFC0F083C9700A58000 /* TDCommentStateTest.h */, + D3DDDAFD0F083C9700A58000 /* TDCommentStateTest.m */, + D3E39C3D0FC5FFD10022DAB9 /* TDDelimitStateTest.h */, + D3E39C3E0FC5FFD10022DAB9 /* TDDelimitStateTest.m */, + ); + name = "tokenizer states"; + sourceTree = ""; + }; + D36568A40EEF9FB600226554 /* plist */ = { + isa = PBXGroup; + children = ( + D36568A50EEF9FE900226554 /* TDPlistParser.h */, + D36568A60EEF9FE900226554 /* TDPlistParser.m */, + D36568A80EEFA05300226554 /* TDPlistParserTest.h */, + D36568A90EEFA05300226554 /* TDPlistParserTest.m */, + ); + name = plist; + sourceTree = ""; + }; + D3668290101D2BAC0008632C /* erb */ = { + isa = PBXGroup; + children = ( + D3668291101D2BFA0008632C /* erb.grammar */, + D3668294101D2C200008632C /* ERBTest.h */, + D3668295101D2C200008632C /* ERBTest.m */, + ); + name = erb; + sourceTree = ""; + }; + D36C55FB0FD3616200141CB7 /* regex */ = { + isa = PBXGroup; + children = ( + D3C221F00FFE8C7A004514FE /* PKPattern.h */, + D34BAF380FF9E18300D7773A /* PKPattern.m */, + D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */, + D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */, + ); + name = regex; + sourceTree = ""; + }; + D36E94F40E57865500496BD3 /* xpath */ = { + isa = PBXGroup; + children = ( + D34BAC490FF892C200D7773A /* XPathParserGrammarTest.h */, + D34BAC4A0FF892C200D7773A /* XPathParserGrammarTest.m */, + D31FE5EF0E60E6B500A0803E /* TDNCName.h */, + D31FE6DF0E60EE2500A0803E /* TDNCName.m */, + D31FE5F00E60E6B500A0803E /* TDNCNameState.h */, + D31FE5F10E60E6B500A0803E /* TDNCNameState.m */, + D36E95440E578ECC00496BD3 /* XPathParser.h */, + D36E95450E578ECC00496BD3 /* XPathParser.m */, + D36E97AE0E589DAE00496BD3 /* XPathAssembler.h */, + D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */, + D36E98200E58A3A800496BD3 /* XPathContext.h */, + D36E98210E58A3A800496BD3 /* XPathContext.m */, + D36E95D60E57B08400496BD3 /* XPathParserTest.h */, + D36E95D70E57B08400496BD3 /* XPathParserTest.m */, + ); + name = xpath; + sourceTree = ""; + }; + D36E98CB0E58C08F00496BD3 /* DebugApp */ = { + isa = PBXGroup; + children = ( + D3F0E3290FFEA1E200C9DF74 /* DebugApp-Info.plist */, + D36E98DF0E58C12800496BD3 /* main.m */, + D36E98DC0E58C12800496BD3 /* DebugAppDelegate.h */, + D36E98DD0E58C12800496BD3 /* DebugAppDelegate.m */, + D3F740B50EF8C38A00559B9F /* JSONAssembler.h */, + D3F740B60EF8C38A00559B9F /* JSONAssembler.m */, + D36E98DE0E58C12800496BD3 /* DebugAppMainMenu.xib */, + ); + name = DebugApp; + path = debugapp; + sourceTree = ""; + }; + D36EA1400E5CF19F00496BD3 /* xml token terminals */ = { + isa = PBXGroup; + children = ( + D31FE5B90E60E69E00A0803E /* TDXmlAttribute.h */, + D31FE5BA0E60E69E00A0803E /* TDXmlAttribute.m */, + D31FE5BB0E60E69E00A0803E /* TDXmlCdata.h */, + D31FE5BC0E60E69E00A0803E /* TDXmlCdata.m */, + D31FE5BD0E60E69E00A0803E /* TDXmlComment.h */, + D31FE5BE0E60E69E00A0803E /* TDXmlComment.m */, + D31FE5BF0E60E69E00A0803E /* TDXmlDecl.h */, + D31FE5C00E60E69E00A0803E /* TDXmlDecl.m */, + D31FE5C10E60E69E00A0803E /* TDXmlDoctype.h */, + D31FE5C20E60E69E00A0803E /* TDXmlDoctype.m */, + D31FE5C30E60E69E00A0803E /* TDXmlDocument.h */, + D31FE5C40E60E69E00A0803E /* TDXmlDocument.m */, + D31FE5C50E60E69E00A0803E /* TDXmlEndEntity.h */, + D31FE5C60E60E69E00A0803E /* TDXmlEndEntity.m */, + D31FE5C70E60E69E00A0803E /* TDXmlEndTag.h */, + D31FE5C80E60E69E00A0803E /* TDXmlEndTag.m */, + D31FE5C90E60E69E00A0803E /* TDXmlEntity.h */, + D31FE5CA0E60E69E00A0803E /* TDXmlEntity.m */, + D31FE5CB0E60E69E00A0803E /* TDXmlEntityRef.h */, + D31FE5CC0E60E69E00A0803E /* TDXmlEntityRef.m */, + D31FE5CD0E60E69E00A0803E /* TDXmlFragment.h */, + D31FE5CE0E60E69E00A0803E /* TDXmlFragment.m */, + D31FE5CF0E60E69E00A0803E /* TDXmlNotation.h */, + D31FE5D00E60E69E00A0803E /* TDXmlNotation.m */, + D31FE5D10E60E69E00A0803E /* TDXmlProcessingInstruction.h */, + D31FE5D20E60E69E00A0803E /* TDXmlProcessingInstruction.m */, + D31FE5D30E60E69E00A0803E /* TDXmlSignificantWhitespace.h */, + D31FE5D40E60E69E00A0803E /* TDXmlSignificantWhitespace.m */, + D31FE5D50E60E69E00A0803E /* TDXmlStartTag.h */, + D31FE5D60E60E69E00A0803E /* TDXmlStartTag.m */, + D31FE5D70E60E69E00A0803E /* TDXmlTerminal.h */, + D31FE5D80E60E69E00A0803E /* TDXmlTerminal.m */, + D31FE5D90E60E69E00A0803E /* TDXmlText.h */, + D31FE5DA0E60E69E00A0803E /* TDXmlText.m */, + D31FE5DB0E60E69E00A0803E /* TDXmlWhitespace.h */, + D31FE5DC0E60E69E00A0803E /* TDXmlWhitespace.m */, + ); + name = "xml token terminals"; + sourceTree = ""; + }; + D36EA1440E5CF38100496BD3 /* tokenizer */ = { + isa = PBXGroup; + children = ( + D31FE5B30E60E66600A0803E /* TDXmlToken.h */, + D31FE5B40E60E66600A0803E /* TDXmlToken.m */, + D31FE5B50E60E66600A0803E /* TDXmlTokenizer.h */, + D31FE5B60E60E66600A0803E /* TDXmlTokenizer.m */, + ); + name = tokenizer; + sourceTree = ""; + }; + D380BA950F0F1C450009EC13 /* JSParseKit Framework */ = { + isa = PBXGroup; + children = ( + D34BB04E0FF9EC4E00D7773A /* JSParseKit-Info.plist */, + D34BB0660FF9EDDF00D7773A /* JSParseKit.h */, + D34BB0670FF9EDDF00D7773A /* JSParseKit.m */, + D34BB06C0FF9EE4000D7773A /* PKJSUtils.h */, + D34BB06D0FF9EE4000D7773A /* PKJSUtils.m */, + D34BB06E0FF9EE4000D7773A /* PKJSUtils_macros.h */, + D34BB06F0FF9EE4000D7773A /* PKJSValueHolder.h */, + D34BB0700FF9EE4000D7773A /* PKJSValueHolder.m */, + D34BB06A0FF9EE4000D7773A /* PKJSAssembly.h */, + D34BB06B0FF9EE4000D7773A /* PKJSAssembly.m */, + D389F8C40F1AC89A00558235 /* Chars */, + D389F59A0F19BBAE00558235 /* Tokens */, + D389F59B0F19BBD300558235 /* Parse */, + ); + name = "JSParseKit Framework"; + sourceTree = ""; + }; + D389A0AE0F1FCC7A003B43BD /* relaxng */ = { + isa = PBXGroup; + children = ( + D389A0B00F1FCC99003B43BD /* RelaxParser.h */, + D389A0B10F1FCC99003B43BD /* RelaxParser.m */, + ); + name = relaxng; + sourceTree = ""; + }; + D389F2CA0F196ACF00558235 /* JSDemoApp */ = { + isa = PBXGroup; + children = ( + D3F0E37A0FFEA39000C9DF74 /* JSDemoApp-Info.plist */, + D389F2E30F196CAE00558235 /* main.m */, + D389F2E80F196F5B00558235 /* JSDemoAppDelegate.h */, + D389F2E90F196F5B00558235 /* JSDemoAppDelegate.m */, + D389F38E0F19800400558235 /* DefaultValues.plist */, + D389F4610F198A8800558235 /* Test.html */, + D389FBCC0F1B25E200558235 /* ParserTest.html */, + D389F5580F19B7BC00558235 /* JSDemoAppMainMenu.xib */, + ); + name = JSDemoApp; + sourceTree = ""; + }; + D389F59A0F19BBAE00558235 /* Tokens */ = { + isa = PBXGroup; + children = ( + D34BB0930FF9F14B00D7773A /* PKJSCommentState.h */, + D34BB0940FF9F14B00D7773A /* PKJSCommentState.m */, + D34BB0950FF9F14B00D7773A /* PKJSDelimitState.h */, + D34BB0960FF9F14B00D7773A /* PKJSDelimitState.m */, + D34BB0970FF9F14B00D7773A /* PKJSNumberState.h */, + D34BB0980FF9F14B00D7773A /* PKJSNumberState.m */, + D34BB0990FF9F14B00D7773A /* PKJSQuoteState.h */, + D34BB09A0FF9F14B00D7773A /* PKJSQuoteState.m */, + D34BB09B0FF9F14B00D7773A /* PKJSSymbolState.h */, + D34BB09C0FF9F14B00D7773A /* PKJSSymbolState.m */, + D34BB09D0FF9F14B00D7773A /* PKJSToken.h */, + D34BB09E0FF9F14B00D7773A /* PKJSToken.m */, + D34BB09F0FF9F14B00D7773A /* PKJSTokenAssembly.h */, + D34BB0A00FF9F14B00D7773A /* PKJSTokenAssembly.m */, + D34BB0A10FF9F14B00D7773A /* PKJSTokenizer.h */, + D34BB0A20FF9F14B00D7773A /* PKJSTokenizer.m */, + D34BB0A30FF9F14B00D7773A /* PKJSTokenizerState.h */, + D34BB0A40FF9F14B00D7773A /* PKJSTokenizerState.m */, + D34BB0A50FF9F14B00D7773A /* PKJSWhitespaceState.h */, + D34BB0A60FF9F14B00D7773A /* PKJSWhitespaceState.m */, + D34BB0A70FF9F14B00D7773A /* PKJSWordState.h */, + D34BB0A80FF9F14B00D7773A /* PKJSWordState.m */, + ); + name = Tokens; + sourceTree = ""; + }; + D389F59B0F19BBD300558235 /* Parse */ = { + isa = PBXGroup; + children = ( + D34BB0D20FF9F28000D7773A /* PKJSAlternation.h */, + D34BB0D30FF9F28000D7773A /* PKJSAlternation.m */, + D34BB0D40FF9F28000D7773A /* PKJSAny.h */, + D34BB0D50FF9F28000D7773A /* PKJSAny.m */, + D34BB0D60FF9F28000D7773A /* PKJSAssemblerAdapter.h */, + D34BB0D70FF9F28000D7773A /* PKJSAssemblerAdapter.m */, + D34BB0D80FF9F28000D7773A /* PKJSCollectionParser.h */, + D34BB0D90FF9F28000D7773A /* PKJSCollectionParser.m */, + D34BB0DA0FF9F28000D7773A /* PKJSEmpty.h */, + D34BB0DB0FF9F28000D7773A /* PKJSEmpty.m */, + D34BB0DC0FF9F28000D7773A /* PKJSParser.h */, + D34BB0DD0FF9F28000D7773A /* PKJSParser.m */, + D34BB0DE0FF9F28000D7773A /* PKJSRepetition.h */, + D34BB0DF0FF9F28000D7773A /* PKJSRepetition.m */, + D34BB0E00FF9F28000D7773A /* PKJSSequence.h */, + D34BB0E10FF9F28000D7773A /* PKJSSequence.m */, + D34BB0E20FF9F28000D7773A /* PKJSTerminal.h */, + D34BB0E30FF9F28000D7773A /* PKJSTerminal.m */, + D34BB0E40FF9F28000D7773A /* PKJSTrack.h */, + D34BB0E50FF9F28000D7773A /* PKJSTrack.m */, + D389FAE30F1B1B8F00558235 /* Char Terminals */, + D389FAE20F1B1B7200558235 /* Token Terminals */, + ); + name = Parse; + sourceTree = ""; + }; + D389F8C40F1AC89A00558235 /* Chars */ = { + isa = PBXGroup; + children = ( + D34BB08D0FF9EF9D00D7773A /* PKJSCharacterAssembly.h */, + D34BB08E0FF9EF9D00D7773A /* PKJSCharacterAssembly.m */, + ); + name = Chars; + sourceTree = ""; + }; + D389FAE20F1B1B7200558235 /* Token Terminals */ = { + isa = PBXGroup; + children = ( + D34BB0FE0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h */, + D34BB0FF0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m */, + D34BB1000FF9F36200D7773A /* PKJSComment.h */, + D34BB1010FF9F36200D7773A /* PKJSComment.m */, + D34BB1020FF9F36200D7773A /* PKJSDelimitedString.h */, + D34BB1030FF9F36200D7773A /* PKJSDelimitedString.m */, + D34BB1040FF9F36200D7773A /* PKJSLiteral.h */, + D34BB1050FF9F36200D7773A /* PKJSLiteral.m */, + D34BB1060FF9F36200D7773A /* PKJSLowercaseWord.h */, + D34BB1070FF9F36200D7773A /* PKJSLowercaseWord.m */, + D34BB1080FF9F36200D7773A /* PKJSNum.h */, + D34BB1090FF9F36200D7773A /* PKJSNum.m */, + D34BB10A0FF9F36200D7773A /* PKJSPattern.h */, + D34BB10B0FF9F36200D7773A /* PKJSPattern.m */, + D34BB10C0FF9F36200D7773A /* PKJSQuotedString.h */, + D34BB10D0FF9F36200D7773A /* PKJSQuotedString.m */, + D34BB10E0FF9F36200D7773A /* PKJSSymbol.h */, + D34BB10F0FF9F36200D7773A /* PKJSSymbol.m */, + D34BB1100FF9F36200D7773A /* PKJSUppercaseWord.h */, + D34BB1110FF9F36200D7773A /* PKJSUppercaseWord.m */, + D34BB1120FF9F36200D7773A /* PKJSWord.h */, + D34BB1130FF9F36200D7773A /* PKJSWord.m */, + ); + name = "Token Terminals"; + sourceTree = ""; + }; + D389FAE30F1B1B8F00558235 /* Char Terminals */ = { + isa = PBXGroup; + children = ( + ); + name = "Char Terminals"; + sourceTree = ""; + }; + D3AF4C8E0FDC738B0032F4DC /* Other Sources */ = { + isa = PBXGroup; + children = ( + D34BAD630FF9C6AE00D7773A /* ParseKit_Prefix.pch */, + D3FDC8DB0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + D3AF4CC80FDC74320032F4DC /* Blob */ = { + isa = PBXGroup; + children = ( + D3AF4BF50FDC40050032F4DC /* TDToken+Blob.h */, + D3AF4BF60FDC40050032F4DC /* TDToken+Blob.m */, + D3AF4BFB0FDC41190032F4DC /* TDTokenizer+BlobState.h */, + D3AF4BFC0FDC41190032F4DC /* TDTokenizer+BlobState.m */, + D3AF4C190FDC568F0032F4DC /* TDBlobState.h */, + D3AF4C1A0FDC568F0032F4DC /* TDBlobState.m */, + D3AF4BE80FDC3DD50032F4DC /* TDBlob.h */, + D3AF4BE90FDC3DD50032F4DC /* TDBlob.m */, + ); + name = Blob; + sourceTree = ""; + }; + D3AF4CC90FDC743C0032F4DC /* ReservedWord */ = { + isa = PBXGroup; + children = ( + D3AF4CC50FDC740A0032F4DC /* TDWordOrReservedState.h */, + D3AF4CC60FDC740A0032F4DC /* TDWordOrReservedState.m */, + D3AF4CBF0FDC740A0032F4DC /* TDNonReservedWord.h */, + D3AF4CC00FDC740A0032F4DC /* TDNonReservedWord.m */, + D3AF4CC10FDC740A0032F4DC /* TDReservedWord.h */, + D3AF4CC20FDC740A0032F4DC /* TDReservedWord.m */, + ); + name = ReservedWord; + sourceTree = ""; + }; + D3AF4CCA0FDC74490032F4DC /* Slash */ = { + isa = PBXGroup; + children = ( + D3DDDC230F085C5400A58000 /* TDSlashSlashState.h */, + D3DDDC240F085C5400A58000 /* TDSlashSlashState.m */, + D3DDDC250F085C5400A58000 /* TDSlashStarState.h */, + D3DDDC260F085C5400A58000 /* TDSlashStarState.m */, + D3DDDC270F085C5400A58000 /* TDSlashState.h */, + D3DDDC280F085C5400A58000 /* TDSlashState.m */, + D31FE57D0E60E58C00A0803E /* TDSlashStateTest.h */, + D31FE57E0E60E58C00A0803E /* TDSlashStateTest.m */, + ); + name = Slash; + sourceTree = ""; + }; + D3AF4CCB0FDC74540032F4DC /* Whitespace */ = { + isa = PBXGroup; + children = ( + D3AF4CC30FDC740A0032F4DC /* TDSignificantWhitespaceState.h */, + D3AF4CC40FDC740A0032F4DC /* TDSignificantWhitespaceState.m */, + D31FE57B0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.h */, + D31FE57C0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.m */, + ); + name = Whitespace; + sourceTree = ""; + }; + D3BBBC9A0FEC9739007DF30D /* old */ = { + isa = PBXGroup; + children = ( + D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */, + D36E9FB40E5A944A00496BD3 /* apple-boss.xml */, + D31FE5AD0E60E64900A0803E /* TDXmlTokenAssembly.h */, + D31FE5AE0E60E64900A0803E /* TDXmlTokenAssembly.m */, + D31FE5AF0E60E64900A0803E /* TDXmlTokenizerTest.h */, + D31FE5B00E60E64900A0803E /* TDXmlTokenizerTest.m */, + D36EA1440E5CF38100496BD3 /* tokenizer */, + D36EA1400E5CF19F00496BD3 /* xml token terminals */, + D3521F520E5FA1B0009681F9 /* XMLReader.h */, + D3521F530E5FA1B0009681F9 /* XMLReader.m */, + D3521F540E5FA1B0009681F9 /* XMLReaderTest.h */, + D3521F550E5FA1B0009681F9 /* XMLReaderTest.m */, + D31FE5F20E60E6B500A0803E /* TDXmlName.h */, + D31FE5F30E60E6B500A0803E /* TDXmlName.m */, + D31FE5F40E60E6B500A0803E /* TDXmlNameState.h */, + D31FE5F50E60E6B500A0803E /* TDXmlNameState.m */, + D31FE5F60E60E6B500A0803E /* TDXmlNameTest.h */, + D31FE5F70E60E6B500A0803E /* TDXmlNameTest.m */, + D31FE5F80E60E6B500A0803E /* TDXmlNmtoken.h */, + D31FE5F90E60E6B500A0803E /* TDXmlNmtoken.m */, + D31FE5FA0E60E6B500A0803E /* TDXmlNmtokenState.h */, + D31FE5FB0E60E6B500A0803E /* TDXmlNmtokenState.m */, + ); + name = old; + sourceTree = ""; + }; + D3C0309C0EF34DD200C5ABEB /* grammar */ = { + isa = PBXGroup; + children = ( + D380B5370F0D7DDE0009EC13 /* css.css */, + D380B5080F0D71A90009EC13 /* css.grammar */, + D380B5930F0D82F60009EC13 /* example.css */, + D380AFBB0F0C54B60009EC13 /* html.css */, + D380AFBC0F0C54B60009EC13 /* html.grammar */, + D385FD6B0F05A99900DB2946 /* mini_css.grammar */, + D3DCB4C20EF6015300DE5110 /* json.grammar */, + D385FA240F04993500DB2946 /* json.css */, + D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */, + D38349BB0F0C0D910055E4E0 /* json_with_comments.css */, + D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */, + D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */, + D380AFC20F0C56000009EC13 /* example.html */, + D3F741BD0EF9F28D00559B9F /* css2_1.grammar */, + D3F741430EF8E96A00559B9F /* xpath1_0.grammar */, + D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */, + D31A15250F6DE449002AFDF1 /* javascript.grammar */, + D385FD400F05A88C00DB2946 /* TDMiniCSSAssembler.h */, + D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */, + D385FD420F05A88C00DB2946 /* TDMiniCSSAssemblerTest.h */, + D385FD430F05A88C00DB2946 /* TDMiniCSSAssemblerTest.m */, + D385F9880F046FE900DB2946 /* TDGenericAssembler.h */, + D385F9890F046FE900DB2946 /* TDGenericAssembler.m */, + D385FA210F04971400DB2946 /* TDGenericAssemblerTest.h */, + D385FA220F04971400DB2946 /* TDGenericAssemblerTest.m */, + D3DDDA850F0779FD00A58000 /* TDSyntaxHighlighter.h */, + D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */, + D353899B0FEAC94400926552 /* c.grammar */, + D353899D0FEAC96B00926552 /* objc.grammar */, + D355C8830FEB4B94006A91A4 /* proto.grammar */, + ); + name = grammar; + sourceTree = ""; + }; + D3C7D8220A411F31005DD154 /* ParseKit Tests */ = { + isa = PBXGroup; + children = ( + D3F0E36C0FFEA33700C9DF74 /* Tests-Info.plist */, + D31FE54A0E60E46100A0803E /* TDTestScaffold.h */, + D31FE54B0E60E46100A0803E /* TDTestScaffold.m */, + D3376D7710096BDE00E4602E /* IR */, + D3F823560F57859900B7DC48 /* factory */, + D3C0309C0EF34DD200C5ABEB /* grammar */, + D3252F670FCE171D005EF059 /* predicate */, + D31A164F0F703899002AFDF1 /* javascript */, + D3D63F570E2A8548009BF5CD /* parse */, + D3D63F560E2A8538009BF5CD /* tokens */, + D34A20080E55FD5F00A4A0BF /* chars */, + D3C85C770E63B400000445FD /* arithmetic */, + D3E786030E5510AE008C7D61 /* regex */, + D3E788890E567B6D008C7D61 /* ebnf */, + D36568A40EEF9FB600226554 /* plist */, + D318EAE30E2FD5B6009F47DF /* json */, + D3D647CE0E2C7569009BF5CD /* xml */, + D36E94F40E57865500496BD3 /* xpath */, + D3E788900E567DDA008C7D61 /* srgs */, + D389A0AE0F1FCC7A003B43BD /* relaxng */, + D3C863240E67C249000445FD /* syntax highlight */, + D3668290101D2BAC0008632C /* erb */, + ); + name = "ParseKit Tests"; + sourceTree = ""; + }; + D3C7D8710A411F6B005DD154 /* io */ = { + isa = PBXGroup; + children = ( + D3C221960FFE8B95004514FE /* PKReader.h */, + D34BAD9B0FF9C95800D7773A /* PKReader.m */, + ); + name = io; + sourceTree = ""; + }; + D3C7D8720A411F81005DD154 /* parse */ = { + isa = PBXGroup; + children = ( + D3C221990FFE8B9D004514FE /* PKAssembly.h */, + D34BADA00FF9C9B000D7773A /* PKAssembly.m */, + D3D63EA90E2A7A5C009BF5CD /* parsers */, + ); + name = parse; + sourceTree = ""; + }; + D3C7D8740A411F8E005DD154 /* tokens */ = { + isa = PBXGroup; + children = ( + D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */, + D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */, + D341846A0E5209A60081B0DC /* tokenizer */, + D3541F870DFB105900429B4F /* states */, + D3D642270E2AC426009BF5CD /* token terminals */, + ); + name = tokens; + sourceTree = ""; + }; + D3C85C770E63B400000445FD /* arithmetic */ = { + isa = PBXGroup; + children = ( + D319E429106D8A1F008C63DD /* arithmetic.grammar */, + D319E42C106D8A31008C63DD /* TDArithmeticAssembler.h */, + D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */, + D3C85C790E63B438000445FD /* TDArithmeticParser.h */, + D3C85C7A0E63B438000445FD /* TDArithmeticParser.m */, + D3C85C7E0E63B9E9000445FD /* TDArithmeticParserTest.h */, + D3C85C7F0E63B9E9000445FD /* TDArithmeticParserTest.m */, + ); + name = arithmetic; + sourceTree = ""; + }; + D3C863240E67C249000445FD /* syntax highlight */ = { + isa = PBXGroup; + children = ( + D3C863250E67C255000445FD /* html */, + ); + name = "syntax highlight"; + sourceTree = ""; + }; + D3C863250E67C255000445FD /* html */ = { + isa = PBXGroup; + children = ( + D38DD9E70EC29F260070BC4D /* nyt.html */, + D3B69D310E80249900D70C41 /* nonascii.html */, + D3EADD7F0E75E9CC00F78584 /* nasty.html */, + D3EADD8D0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.h */, + D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */, + ); + name = html; + sourceTree = ""; + }; + D3D63EA90E2A7A5C009BF5CD /* parsers */ = { + isa = PBXGroup; + children = ( + D3C2219C0FFE8BA6004514FE /* PKParser.h */, + D34BADD60FF9CBFB00D7773A /* PKParser.m */, + D3C2219F0FFE8BAE004514FE /* PKRepetition.h */, + D34BAE130FF9CE0E00D7773A /* PKRepetition.m */, + D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */, + D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */, + D3C221A50FFE8BC1004514FE /* PKAlternation.h */, + D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */, + D3C221A80FFE8BC9004514FE /* PKSequence.h */, + D34BAE150FF9CE0E00D7773A /* PKSequence.m */, + D3C221AB0FFE8BCF004514FE /* PKTrack.h */, + D34BAE190FF9CE0E00D7773A /* PKTrack.m */, + D3C221AE0FFE8BD4004514FE /* PKTrackException.h */, + D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */, + D3C221B10FFE8BDB004514FE /* PKIntersection.h */, + D34BAE110FF9CE0E00D7773A /* PKIntersection.m */, + D3C221B40FFE8BE2004514FE /* PKDifference.h */, + D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */, + D3C221B70FFE8BE8004514FE /* PKNegation.h */, + D3126D040FFD9BA700CBF4C4 /* PKNegation.m */, + D3C221BA0FFE8BEF004514FE /* PKTerminal.h */, + D34BAE170FF9CE0E00D7773A /* PKTerminal.m */, + D3C221BD0FFE8BF7004514FE /* PKEmpty.h */, + D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */, + ); + name = parsers; + sourceTree = ""; + }; + D3D63F560E2A8538009BF5CD /* tokens */ = { + isa = PBXGroup; + children = ( + D31FE5710E60E55700A0803E /* TDReaderTest.h */, + D31FE5720E60E55700A0803E /* TDReaderTest.m */, + D31FE5730E60E55700A0803E /* TDTokenizerTest.h */, + D31FE5740E60E55700A0803E /* TDTokenizerTest.m */, + D38E97CA1061CF6500739C39 /* TDTokenizerBlocksTest.h */, + D38E97CB1061CF6500739C39 /* TDTokenizerBlocksTest.m */, + D38205BC0EEE48EE004340DD /* TDTokenTest.h */, + D38205BD0EEE48EE004340DD /* TDTokenTest.m */, + D3656DFC0EF2620E00226554 /* TDTokenArraySourceTest.h */, + D3656DFD0EF2620E00226554 /* TDTokenArraySourceTest.m */, + D35420EC0DFB275400429B4F /* tokenizer states */, + ); + name = tokens; + sourceTree = ""; + }; + D3D63F570E2A8548009BF5CD /* parse */ = { + isa = PBXGroup; + children = ( + D31FE54D0E60E50800A0803E /* TDAlternationTest.h */, + D31FE54E0E60E50800A0803E /* TDAlternationTest.m */, + D31FE54F0E60E50800A0803E /* TDLiteralTest.h */, + D31FE5500E60E50800A0803E /* TDLiteralTest.m */, + D31FE5510E60E50800A0803E /* TDParserTest.h */, + D31FE5520E60E50800A0803E /* TDParserTest.m */, + D38E98D61062C5BA00739C39 /* TDParserBlocksTest.h */, + D38E98D71062C5BA00739C39 /* TDParserBlocksTest.m */, + D31FE5530E60E50800A0803E /* TDRepetitionTest.h */, + D31FE5540E60E50800A0803E /* TDRepetitionTest.m */, + D31FE5550E60E50800A0803E /* TDReservedWordTest.h */, + D31FE5560E60E50800A0803E /* TDReservedWordTest.m */, + D31FE5570E60E50800A0803E /* TDRobotCommandTest.h */, + D31FE5580E60E50800A0803E /* TDRobotCommandTest.m */, + D31FE5590E60E50800A0803E /* TDSequenceTest.h */, + D31FE55A0E60E50800A0803E /* TDSequenceTest.m */, + D31FE55B0E60E50800A0803E /* TDSymbolTest.h */, + D31FE55C0E60E50800A0803E /* TDSymbolTest.m */, + D31FE55D0E60E50800A0803E /* TDTokenAssemblyTest.h */, + D31FE55E0E60E50800A0803E /* TDTokenAssemblyTest.m */, + D31FE55F0E60E50800A0803E /* TDTrackTest.h */, + D31FE5600E60E50800A0803E /* TDTrackTest.m */, + D31FE5610E60E50800A0803E /* TDUppercaseWordTest.h */, + D31FE5620E60E50800A0803E /* TDUppercaseWordTest.m */, + D3C031EB0EF38D2D00C5ABEB /* TDLowercaseWordTest.h */, + D3C031EC0EF38D2D00C5ABEB /* TDLowercaseWordTest.m */, + D3126D410FFDB4C600CBF4C4 /* TDExclusionTest.h */, + D3126D420FFDB4C600CBF4C4 /* TDExclusionTest.m */, + D36C56290FD365DB00141CB7 /* TDPatternTest.h */, + D36C562A0FD365DB00141CB7 /* TDPatternTest.m */, + D338E5B90FF5DDCB003DE6AA /* TDDifferenceTest.h */, + D338E5BA0FF5DDCB003DE6AA /* TDDifferenceTest.m */, + D3126D090FFD9E4B00CBF4C4 /* TDNegationTest.h */, + D3126D0A0FFD9E4B00CBF4C4 /* TDNegationTest.m */, + ); + name = parse; + sourceTree = ""; + }; + D3D642270E2AC426009BF5CD /* token terminals */ = { + isa = PBXGroup; + children = ( + D36C55FB0FD3616200141CB7 /* regex */, + D3C221F30FFE8C87004514FE /* PKWord.h */, + D34BAED40FF9D56400D7773A /* PKWord.m */, + D3C222140FFE8D01004514FE /* PKLowercaseWord.h */, + D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */, + D3C222170FFE8D11004514FE /* PKUppercaseWord.h */, + D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */, + D3C221F60FFE8C8E004514FE /* PKNumber.h */, + D34BAF440FF9E19700D7773A /* PKNumber.m */, + D3C221F90FFE8C97004514FE /* PKQuotedString.h */, + D34BAF460FF9E19700D7773A /* PKQuotedString.m */, + D3C221FC0FFE8CB2004514FE /* PKSymbol.h */, + D34BAF480FF9E19700D7773A /* PKSymbol.m */, + D3C221FF0FFE8CB9004514FE /* PKLiteral.h */, + D34BAF420FF9E19700D7773A /* PKLiteral.m */, + D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */, + D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */, + D3C222050FFE8CCA004514FE /* PKWhitespace.h */, + D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */, + D3C222080FFE8CD1004514FE /* PKComment.h */, + D34BAF3E0FF9E19700D7773A /* PKComment.m */, + D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */, + D34BAF400FF9E19700D7773A /* PKDelimitedString.m */, + D3C2220E0FFE8CDF004514FE /* PKAny.h */, + D34BAE2F0FF9CE6000D7773A /* PKAny.m */, + ); + name = "token terminals"; + sourceTree = ""; + }; + D3D647CE0E2C7569009BF5CD /* xml */ = { + isa = PBXGroup; + children = ( + D3D1BF291039445C003656E5 /* SAXTest.h */, + D3D1BF2A1039445C003656E5 /* SAXTest.m */, + D3D1BF2610394420003656E5 /* SAXAssembler.h */, + D3D1BF2710394420003656E5 /* SAXAssembler.m */, + D3BBBC960FEC9722007DF30D /* TDXMLParserTest.h */, + D3BBBC970FEC9722007DF30D /* TDXMLParserTest.m */, + D3BBBC9B0FEC9756007DF30D /* TDXMLParser.h */, + D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */, + D355C8800FEB36A1006A91A4 /* xml.grammar */, + D315DF710FEF59B600D876C8 /* date.grammar */, + D3BBBC9A0FEC9739007DF30D /* old */, + ); + name = xml; + sourceTree = ""; + }; + D3E785F10E550F63008C7D61 /* chars */ = { + isa = PBXGroup; + children = ( + D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */, + D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */, + D3E7861F0E55363F008C7D61 /* char terminals */, + ); + name = chars; + sourceTree = ""; + }; + D3E786030E5510AE008C7D61 /* regex */ = { + isa = PBXGroup; + children = ( + D31FE59B0E60E5C000A0803E /* TDRegularParser.h */, + D31FE59C0E60E5C000A0803E /* TDRegularParser.m */, + D31FE59D0E60E5C000A0803E /* TDRegularParserTest.h */, + D31FE59E0E60E5C000A0803E /* TDRegularParserTest.m */, + ); + name = regex; + sourceTree = ""; + }; + D3E7861F0E55363F008C7D61 /* char terminals */ = { + isa = PBXGroup; + children = ( + D3C2221D0FFE8D3B004514FE /* PKChar.h */, + D34BAFB40FF9E80300D7773A /* PKChar.m */, + D3C222200FFE8D42004514FE /* PKDigit.h */, + D34BAFB60FF9E80300D7773A /* PKDigit.m */, + D3C222230FFE8D49004514FE /* PKLetter.h */, + D34BAFB80FF9E80300D7773A /* PKLetter.m */, + D3C222260FFE8D6B004514FE /* PKSpecificChar.h */, + D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */, + ); + name = "char terminals"; + sourceTree = ""; + }; + D3E788890E567B6D008C7D61 /* ebnf */ = { + isa = PBXGroup; + children = ( + D3E78A150E574C99008C7D61 /* EBNFParser.h */, + D3E78A160E574C99008C7D61 /* EBNFParser.m */, + D3E78A170E574C99008C7D61 /* EBNFParserTest.h */, + D3E78A180E574C99008C7D61 /* EBNFParserTest.m */, + ); + name = ebnf; + sourceTree = ""; + }; + D3E788900E567DDA008C7D61 /* srgs */ = { + isa = PBXGroup; + children = ( + D3DDDCAC0F0880D800A58000 /* example1.srgs */, + D3E788940E567E0A008C7D61 /* SRGSParser.h */, + D3E788950E567E0A008C7D61 /* SRGSParser.m */, + D3E788910E567DFD008C7D61 /* SRGSParserTest.h */, + D3E788920E567DFD008C7D61 /* SRGSParserTest.m */, + D36E9FE40E5BA0FC00496BD3 /* SRGSGrammar.txt */, + ); + name = srgs; + sourceTree = ""; + }; + D3F5619C1026374400DD6DB1 /* ir */ = { + isa = PBXGroup; + children = ( + D3F5619D1026375100DD6DB1 /* syntax tree */, + D3F561B61026379700DD6DB1 /* ast */, + ); + name = ir; + sourceTree = ""; + }; + D3F5619D1026375100DD6DB1 /* syntax tree */ = { + isa = PBXGroup; + children = ( + D36934551038DE5300527AF3 /* PKParseTree.h */, + D36934561038DE5300527AF3 /* PKParseTree.m */, + D36934571038DE5300527AF3 /* PKParseTreeAssembler.h */, + D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */, + D36934591038DE5300527AF3 /* PKRuleNode.h */, + D369345A1038DE5300527AF3 /* PKRuleNode.m */, + D369345B1038DE5300527AF3 /* PKTokenNode.h */, + D369345C1038DE5300527AF3 /* PKTokenNode.m */, + ); + name = "syntax tree"; + sourceTree = ""; + }; + D3F561B61026379700DD6DB1 /* ast */ = { + isa = PBXGroup; + children = ( + ); + name = ast; + sourceTree = ""; + }; + D3F823560F57859900B7DC48 /* factory */ = { + isa = PBXGroup; + children = ( + D34BAC210FF87F8600D7773A /* TDParserFactoryTest3.h */, + D34BAC220FF87F8600D7773A /* TDParserFactoryTest3.m */, + D380BA5F0F0F06CD0009EC13 /* TDParserFactoryTest.h */, + D380BA600F0F06CD0009EC13 /* TDParserFactoryTest.m */, + D36C53770FD27F1300141CB7 /* TDParserFactoryTest2.h */, + D36C53780FD27F1300141CB7 /* TDParserFactoryTest2.m */, + D3AF49760FDB122E0032F4DC /* TDParserFactoryPatternTest.h */, + D3AF49770FDB122E0032F4DC /* TDParserFactoryPatternTest.m */, + ); + name = factory; + sourceTree = ""; + }; + D3FDC8EF0FFC52CD00F1F797 /* Mobile Frameworks */ = { + isa = PBXGroup; + children = ( + D3FDC74B0FFC4DAC00F1F797 /* CoreGraphics.framework */, + D3FDC7380FFC4D6100F1F797 /* libicucore.dylib */, + D3FDC7360FFC4D6100F1F797 /* Foundation.framework */, + ); + name = "Mobile Frameworks"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 8DC2EF500486A6940098B216 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D34BAD640FF9C6AE00D7773A /* ParseKit_Prefix.pch in Headers */, + D3FDC4A50FFB3B2A00F1F797 /* RegexKitLite.h in Headers */, + D3C221920FFE8B8C004514FE /* ParseKit.h in Headers */, + D3C221930FFE8B8C004514FE /* PKTypes.h in Headers */, + D3C221970FFE8B95004514FE /* PKReader.h in Headers */, + D3C2219A0FFE8B9D004514FE /* PKAssembly.h in Headers */, + D3C2219D0FFE8BA6004514FE /* PKParser.h in Headers */, + D3C221A00FFE8BAE004514FE /* PKRepetition.h in Headers */, + D3C221A30FFE8BBA004514FE /* PKCollectionParser.h in Headers */, + D3C221A60FFE8BC1004514FE /* PKAlternation.h in Headers */, + D3C221A90FFE8BC9004514FE /* PKSequence.h in Headers */, + D3C221AC0FFE8BCF004514FE /* PKTrack.h in Headers */, + D3C221AF0FFE8BD4004514FE /* PKTrackException.h in Headers */, + D3C221B20FFE8BDB004514FE /* PKIntersection.h in Headers */, + D3C221B50FFE8BE2004514FE /* PKDifference.h in Headers */, + D3C221B80FFE8BE8004514FE /* PKNegation.h in Headers */, + D3C221BB0FFE8BEF004514FE /* PKTerminal.h in Headers */, + D3C221BE0FFE8BF7004514FE /* PKEmpty.h in Headers */, + D3C221C10FFE8BFF004514FE /* PKTokenAssembly.h in Headers */, + D3C221C40FFE8C07004514FE /* PKToken.h in Headers */, + D3C221C70FFE8C0D004514FE /* PKTokenArraySource.h in Headers */, + D3C221CA0FFE8C15004514FE /* PKTokenizer.h in Headers */, + D3C221CD0FFE8C1B004514FE /* PKTokenizerState.h in Headers */, + D3C221D00FFE8C24004514FE /* PKNumberState.h in Headers */, + D3C221D60FFE8C35004514FE /* PKSymbolState.h in Headers */, + D3C221D90FFE8C3D004514FE /* PKWordState.h in Headers */, + D3C221DC0FFE8C43004514FE /* PKWhitespaceState.h in Headers */, + D3C221DF0FFE8C49004514FE /* PKDelimitState.h in Headers */, + D3C221E20FFE8C4E004514FE /* PKCommentState.h in Headers */, + D3C221E50FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */, + D3C221E80FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */, + D3C221EB0FFE8C69004514FE /* PKSymbolNode.h in Headers */, + D3C221EE0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */, + D3C221F10FFE8C7A004514FE /* PKPattern.h in Headers */, + D3C221F40FFE8C87004514FE /* PKWord.h in Headers */, + D3C221F70FFE8C8E004514FE /* PKNumber.h in Headers */, + D3C221FA0FFE8C97004514FE /* PKQuotedString.h in Headers */, + D3C221FD0FFE8CB2004514FE /* PKSymbol.h in Headers */, + D3C222000FFE8CB9004514FE /* PKLiteral.h in Headers */, + D3C222030FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */, + D3C222060FFE8CCA004514FE /* PKWhitespace.h in Headers */, + D3C222090FFE8CD1004514FE /* PKComment.h in Headers */, + D3C2220C0FFE8CD8004514FE /* PKDelimitedString.h in Headers */, + D3C2220F0FFE8CDF004514FE /* PKAny.h in Headers */, + D3C222150FFE8D01004514FE /* PKLowercaseWord.h in Headers */, + D3C222180FFE8D11004514FE /* PKUppercaseWord.h in Headers */, + D3C2221B0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */, + D3C2221E0FFE8D3B004514FE /* PKChar.h in Headers */, + D3C222210FFE8D42004514FE /* PKDigit.h in Headers */, + D3C222240FFE8D49004514FE /* PKLetter.h in Headers */, + D3C222270FFE8D6B004514FE /* PKSpecificChar.h in Headers */, + D3C2222A0FFE8DAC004514FE /* PKParserFactory.h in Headers */, + D3C2222D0FFE8DE9004514FE /* NSArray+ParseKitAdditions.h in Headers */, + D3C2222E0FFE8DEE004514FE /* NSString+ParseKitAdditions.h in Headers */, + D3F0E2480FFE8EB900C9DF74 /* PKQuoteState.h in Headers */, + D3376D5910093A1600E4602E /* PKGrammarParser.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1C90F1965E600558235 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D34BB0680FF9EDDF00D7773A /* JSParseKit.h in Headers */, + D34BB0710FF9EE4000D7773A /* PKJSAssembly.h in Headers */, + D34BB0730FF9EE4000D7773A /* PKJSUtils.h in Headers */, + D34BB0750FF9EE4000D7773A /* PKJSUtils_macros.h in Headers */, + D34BB0760FF9EE4000D7773A /* PKJSValueHolder.h in Headers */, + D34BB08F0FF9EF9D00D7773A /* PKJSCharacterAssembly.h in Headers */, + D34BB0A90FF9F14B00D7773A /* PKJSCommentState.h in Headers */, + D34BB0AB0FF9F14B00D7773A /* PKJSDelimitState.h in Headers */, + D34BB0AD0FF9F14B00D7773A /* PKJSNumberState.h in Headers */, + D34BB0AF0FF9F14B00D7773A /* PKJSQuoteState.h in Headers */, + D34BB0B10FF9F14B00D7773A /* PKJSSymbolState.h in Headers */, + D34BB0B30FF9F14B00D7773A /* PKJSToken.h in Headers */, + D34BB0B50FF9F14B00D7773A /* PKJSTokenAssembly.h in Headers */, + D34BB0B70FF9F14B00D7773A /* PKJSTokenizer.h in Headers */, + D34BB0B90FF9F14B00D7773A /* PKJSTokenizerState.h in Headers */, + D34BB0BB0FF9F14B00D7773A /* PKJSWhitespaceState.h in Headers */, + D34BB0BD0FF9F14B00D7773A /* PKJSWordState.h in Headers */, + D34BB0E60FF9F28000D7773A /* PKJSAlternation.h in Headers */, + D34BB0E80FF9F28000D7773A /* PKJSAny.h in Headers */, + D34BB0EA0FF9F28000D7773A /* PKJSAssemblerAdapter.h in Headers */, + D34BB0EC0FF9F28000D7773A /* PKJSCollectionParser.h in Headers */, + D34BB0EE0FF9F28000D7773A /* PKJSEmpty.h in Headers */, + D34BB0F00FF9F28000D7773A /* PKJSParser.h in Headers */, + D34BB0F20FF9F28000D7773A /* PKJSRepetition.h in Headers */, + D34BB0F40FF9F28000D7773A /* PKJSSequence.h in Headers */, + D34BB0F60FF9F28000D7773A /* PKJSTerminal.h in Headers */, + D34BB0F80FF9F28000D7773A /* PKJSTrack.h in Headers */, + D34BB1140FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h in Headers */, + D34BB1160FF9F36200D7773A /* PKJSComment.h in Headers */, + D34BB1180FF9F36200D7773A /* PKJSDelimitedString.h in Headers */, + D34BB11A0FF9F36200D7773A /* PKJSLiteral.h in Headers */, + D34BB11C0FF9F36200D7773A /* PKJSLowercaseWord.h in Headers */, + D34BB11E0FF9F36200D7773A /* PKJSNum.h in Headers */, + D34BB1200FF9F36200D7773A /* PKJSPattern.h in Headers */, + D34BB1220FF9F36200D7773A /* PKJSQuotedString.h in Headers */, + D34BB1240FF9F36200D7773A /* PKJSSymbol.h in Headers */, + D34BB1260FF9F36200D7773A /* PKJSUppercaseWord.h in Headers */, + D34BB1280FF9F36200D7773A /* PKJSWord.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3FDC57F0FFC4BFC00F1F797 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D3FDC6DA0FFC4C8C00F1F797 /* RegexKitLite.h in Headers */, + D3FDC8DC0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch in Headers */, + D3C221940FFE8B8C004514FE /* ParseKit.h in Headers */, + D3C221950FFE8B8C004514FE /* PKTypes.h in Headers */, + D3C221980FFE8B95004514FE /* PKReader.h in Headers */, + D3C2219B0FFE8B9D004514FE /* PKAssembly.h in Headers */, + D3C2219E0FFE8BA6004514FE /* PKParser.h in Headers */, + D3C221A10FFE8BAE004514FE /* PKRepetition.h in Headers */, + D3C221A40FFE8BBA004514FE /* PKCollectionParser.h in Headers */, + D3C221A70FFE8BC1004514FE /* PKAlternation.h in Headers */, + D3C221AA0FFE8BC9004514FE /* PKSequence.h in Headers */, + D3C221AD0FFE8BCF004514FE /* PKTrack.h in Headers */, + D3C221B00FFE8BD4004514FE /* PKTrackException.h in Headers */, + D3C221B30FFE8BDB004514FE /* PKIntersection.h in Headers */, + D3C221B60FFE8BE2004514FE /* PKDifference.h in Headers */, + D3C221B90FFE8BE8004514FE /* PKNegation.h in Headers */, + D3C221BC0FFE8BEF004514FE /* PKTerminal.h in Headers */, + D3C221BF0FFE8BF7004514FE /* PKEmpty.h in Headers */, + D3C221C20FFE8BFF004514FE /* PKTokenAssembly.h in Headers */, + D3C221C50FFE8C07004514FE /* PKToken.h in Headers */, + D3C221C80FFE8C0D004514FE /* PKTokenArraySource.h in Headers */, + D3C221CB0FFE8C15004514FE /* PKTokenizer.h in Headers */, + D3C221CE0FFE8C1B004514FE /* PKTokenizerState.h in Headers */, + D3C221D10FFE8C24004514FE /* PKNumberState.h in Headers */, + D3C221D70FFE8C35004514FE /* PKSymbolState.h in Headers */, + D3C221DA0FFE8C3D004514FE /* PKWordState.h in Headers */, + D3C221DD0FFE8C43004514FE /* PKWhitespaceState.h in Headers */, + D3C221E00FFE8C49004514FE /* PKDelimitState.h in Headers */, + D3C221E30FFE8C4E004514FE /* PKCommentState.h in Headers */, + D3C221E60FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */, + D3C221E90FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */, + D3C221EC0FFE8C69004514FE /* PKSymbolNode.h in Headers */, + D3C221EF0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */, + D3C221F20FFE8C7A004514FE /* PKPattern.h in Headers */, + D3C221F50FFE8C87004514FE /* PKWord.h in Headers */, + D3C221FB0FFE8C97004514FE /* PKQuotedString.h in Headers */, + D3C221FE0FFE8CB2004514FE /* PKSymbol.h in Headers */, + D3C222010FFE8CB9004514FE /* PKLiteral.h in Headers */, + D3C222040FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */, + D3C222070FFE8CCA004514FE /* PKWhitespace.h in Headers */, + D3C2220A0FFE8CD1004514FE /* PKComment.h in Headers */, + D3C2220D0FFE8CD8004514FE /* PKDelimitedString.h in Headers */, + D3C222100FFE8CDF004514FE /* PKAny.h in Headers */, + D3C222160FFE8D01004514FE /* PKLowercaseWord.h in Headers */, + D3C222190FFE8D11004514FE /* PKUppercaseWord.h in Headers */, + D3C2221C0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */, + D3C2221F0FFE8D3B004514FE /* PKChar.h in Headers */, + D3C222220FFE8D42004514FE /* PKDigit.h in Headers */, + D3C222250FFE8D49004514FE /* PKLetter.h in Headers */, + D3C222280FFE8D6B004514FE /* PKSpecificChar.h in Headers */, + D3C2222B0FFE8DAC004514FE /* PKParserFactory.h in Headers */, + D3C2222F0FFE8DEF004514FE /* NSString+ParseKitAdditions.h in Headers */, + D3C222300FFE8DF3004514FE /* NSArray+ParseKitAdditions.h in Headers */, + D3F0E2490FFE8EB900C9DF74 /* PKQuoteState.h in Headers */, + D3F0E3CB0FFEB70100C9DF74 /* PKNumber.h in Headers */, + D37A28681013942A00E936B7 /* PKGrammarParser.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 8DC2EF4F0486A6940098B216 /* ParseKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "ParseKit" */; + buildPhases = ( + 8DC2EF500486A6940098B216 /* Headers */, + 8DC2EF540486A6940098B216 /* Sources */, + 8DC2EF520486A6940098B216 /* Resources */, + 8DC2EF560486A6940098B216 /* Frameworks */, + D36C65E7100ED81B000361A0 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ParseKit; + productInstallPath = "$(HOME)/Library/Frameworks"; + productName = TODParseKit; + productReference = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; + productType = "com.apple.product-type.framework"; + }; + D334940F0E2963FD00406085 /* DemoApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = D33494150E2963FE00406085 /* Build configuration list for PBXNativeTarget "DemoApp" */; + buildPhases = ( + D334940D0E2963FD00406085 /* Sources */, + D334940C0E2963FD00406085 /* Resources */, + D334940E0E2963FD00406085 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D33494A00E296AA900406085 /* PBXTargetDependency */, + ); + name = DemoApp; + productName = DemoApp; + productReference = D33494100E2963FD00406085 /* DemoApp.app */; + productType = "com.apple.product-type.application"; + }; + D34185030E520D3F0081B0DC /* DebugApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = D34185090E520D410081B0DC /* Build configuration list for PBXNativeTarget "DebugApp" */; + buildPhases = ( + D34185010E520D3F0081B0DC /* Sources */, + D34185000E520D3F0081B0DC /* Resources */, + D380B9A10F0EF3DC0009EC13 /* Copy Frameworks */, + D34185020E520D3F0081B0DC /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D34185100E520D6F0081B0DC /* PBXTargetDependency */, + ); + name = DebugApp; + productName = TestApp; + productReference = D34185040E520D3F0081B0DC /* DebugApp.app */; + productType = "com.apple.product-type.application"; + }; + D389F1CD0F1965E600558235 /* JSParseKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = D389F1D20F1965E800558235 /* Build configuration list for PBXNativeTarget "JSParseKit" */; + buildPhases = ( + D389F1C90F1965E600558235 /* Headers */, + D389F1CB0F1965E600558235 /* Sources */, + D389F1CA0F1965E600558235 /* Resources */, + D389F1CC0F1965E600558235 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D389F1D40F19665C00558235 /* PBXTargetDependency */, + ); + name = JSParseKit; + productName = TDJSParseKit; + productReference = D389F1CE0F1965E600558235 /* JSParseKit.framework */; + productType = "com.apple.product-type.framework"; + }; + D389F2020F196A7500558235 /* JSDemoApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = D389F2080F196A7600558235 /* Build configuration list for PBXNativeTarget "JSDemoApp" */; + buildPhases = ( + D389F2000F196A7500558235 /* Sources */, + D389F1FF0F196A7500558235 /* Resources */, + D389F2010F196A7500558235 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D389F20A0F196A8000558235 /* PBXTargetDependency */, + ); + name = JSDemoApp; + productName = JSDemoApp; + productReference = D389F2030F196A7500558235 /* JSDemoApp.app */; + productType = "com.apple.product-type.application"; + }; + D3C7D8790A411FBF005DD154 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D3C7D87C0A411FC0005DD154 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + D3C7D8760A411FBF005DD154 /* Sources */, + D3C7D8750A411FBF005DD154 /* Resources */, + D3DCB3880EF5E65100DE5110 /* Copy Frameworks */, + D3C7D8770A411FBF005DD154 /* Frameworks */, + D3C7D8780A411FBF005DD154 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + D31FE7180E60F24700A0803E /* PBXTargetDependency */, + ); + name = Tests; + productName = Tests; + productReference = D3C7D87A0A411FBF005DD154 /* Tests.octest */; + productType = "com.apple.product-type.bundle"; + }; + D3FDC5820FFC4BFC00F1F797 /* ParseKitMobile */ = { + isa = PBXNativeTarget; + buildConfigurationList = D3FDC62F0FFC4C2000F1F797 /* Build configuration list for PBXNativeTarget "ParseKitMobile" */; + buildPhases = ( + D3FDC57F0FFC4BFC00F1F797 /* Headers */, + D3FDC5800FFC4BFC00F1F797 /* Sources */, + D3FDC5810FFC4BFC00F1F797 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ParseKitMobile; + productName = ParseKitMobile; + productReference = D3FDC5830FFC4BFC00F1F797 /* libparsekit.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0867D690FE84028FC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ParseKit" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 0867D691FE84028FC02AAC07 /* TODParseKit */; + productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DC2EF4F0486A6940098B216 /* ParseKit */, + D389F1CD0F1965E600558235 /* JSParseKit */, + D3FDC5820FFC4BFC00F1F797 /* ParseKitMobile */, + D3C7D8790A411FBF005DD154 /* Tests */, + D334940F0E2963FD00406085 /* DemoApp */, + D34185030E520D3F0081B0DC /* DebugApp */, + D389F2020F196A7500558235 /* JSDemoApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8DC2EF520486A6940098B216 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D334940C0E2963FD00406085 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36E98F80E58C1A000496BD3 /* DemoAppMainMenu.xib in Resources */, + D3DCB4C40EF6015C00DE5110 /* json.grammar in Resources */, + D3F741BF0EF9F29400559B9F /* css2_1.grammar in Resources */, + D3D01CAB0EFDB8A000C24DDE /* json_with_discards.grammar in Resources */, + D3F562A210266E5300DD6DB1 /* TokensView.xib in Resources */, + D3F562A410266E6300DD6DB1 /* TreesView.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D34185000E520D3F0081B0DC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3E27A320E741DD20078CC2C /* small-xml-file.xml in Resources */, + D3E27A330E741DD20078CC2C /* apple-boss.xml in Resources */, + D398E20E0E60F86D00A1C877 /* yahoo.json in Resources */, + D3E785560E53FB54008C7D61 /* apple-boss.json in Resources */, + D36E98E10E58C12800496BD3 /* DebugAppMainMenu.xib in Resources */, + D3EADD810E75E9CC00F78584 /* nasty.html in Resources */, + D3B69D320E80249900D70C41 /* nonascii.html in Resources */, + D3DCB4C50EF6015C00DE5110 /* json.grammar in Resources */, + D3F741C00EF9F29500559B9F /* css2_1.grammar in Resources */, + D3D01CAC0EFDB8A100C24DDE /* json_with_discards.grammar in Resources */, + D385FA260F04993500DB2946 /* json.css in Resources */, + D385FD6C0F05A99900DB2946 /* mini_css.grammar in Resources */, + D3DDDCAE0F0880D800A58000 /* example1.srgs in Resources */, + D383498C0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */, + D38349BD0F0C0D910055E4E0 /* json_with_comments.css in Resources */, + D3834A490F0C14C00055E4E0 /* yahoo_with_comments.json in Resources */, + D380AFBF0F0C54B60009EC13 /* html.css in Resources */, + D380AFC00F0C54B60009EC13 /* html.grammar in Resources */, + D380AFC30F0C56000009EC13 /* example.html in Resources */, + D380B3230F0CC0800009EC13 /* nyt.html in Resources */, + D380B50A0F0D71B00009EC13 /* css.grammar in Resources */, + D380B5390F0D7DE30009EC13 /* css.css in Resources */, + D380B5950F0D82F90009EC13 /* example.css in Resources */, + D3FD79210F4CC87900BAD816 /* rubyhash.grammar in Resources */, + D31A15270F6DE449002AFDF1 /* javascript.grammar in Resources */, + D355C6A70FE9F704006A91A4 /* nspredicate.grammar in Resources */, + D3BBBCC10FECD477007DF30D /* xml.grammar in Resources */, + D315DF730FEF59B600D876C8 /* date.grammar in Resources */, + D34BAC9A0FF8A9AD00D7773A /* xpath1_0.grammar in Resources */, + D3668293101D2C000008632C /* erb.grammar in Resources */, + D319E42B106D8A1F008C63DD /* arithmetic.grammar in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1CA0F1965E600558235 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1FF0F196A7500558235 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F38F0F19800400558235 /* DefaultValues.plist in Resources */, + D389F4620F198A8800558235 /* Test.html in Resources */, + D389F5590F19B7BC00558235 /* JSDemoAppMainMenu.xib in Resources */, + D389FBCD0F1B25E200558235 /* ParserTest.html in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3C7D8750A411FBF005DD154 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3B473850E48C9CF008AFBDD /* yahoo.json in Resources */, + D3E784BD0E53DA28008C7D61 /* apple-boss.json in Resources */, + D36E9FB50E5A944A00496BD3 /* apple-boss.xml in Resources */, + D36E9FE50E5BA0FC00496BD3 /* SRGSGrammar.txt in Resources */, + D36EA3B00E5EA67E00496BD3 /* small-xml-file.xml in Resources */, + D3EADD800E75E9CC00F78584 /* nasty.html in Resources */, + D3B69D330E80249900D70C41 /* nonascii.html in Resources */, + D38DD9E80EC29F260070BC4D /* nyt.html in Resources */, + D3DCB4C30EF6015300DE5110 /* json.grammar in Resources */, + D3F741440EF8E96A00559B9F /* xpath1_0.grammar in Resources */, + D3F741BE0EF9F28D00559B9F /* css2_1.grammar in Resources */, + D3D01CAA0EFDB89900C24DDE /* json_with_discards.grammar in Resources */, + D385FA250F04993500DB2946 /* json.css in Resources */, + D385FD6D0F05A99900DB2946 /* mini_css.grammar in Resources */, + D3DDDCAD0F0880D800A58000 /* example1.srgs in Resources */, + D383498B0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */, + D38349BC0F0C0D910055E4E0 /* json_with_comments.css in Resources */, + D3834A480F0C14B60055E4E0 /* yahoo_with_comments.json in Resources */, + D380AFBD0F0C54B60009EC13 /* html.css in Resources */, + D380AFBE0F0C54B60009EC13 /* html.grammar in Resources */, + D380AFC40F0C56000009EC13 /* example.html in Resources */, + D380B5090F0D71A90009EC13 /* css.grammar in Resources */, + D380B5380F0D7DDE0009EC13 /* css.css in Resources */, + D380B5940F0D82F60009EC13 /* example.css in Resources */, + D3FD79200F4CC86800BAD816 /* rubyhash.grammar in Resources */, + D31A15260F6DE449002AFDF1 /* javascript.grammar in Resources */, + D35384ED0FE9691100926552 /* nspredicate.grammar in Resources */, + D353899C0FEAC94400926552 /* c.grammar in Resources */, + D353899E0FEAC96B00926552 /* objc.grammar in Resources */, + D355C8810FEB36A1006A91A4 /* xml.grammar in Resources */, + D355C8840FEB4B94006A91A4 /* proto.grammar in Resources */, + D315DF720FEF59B600D876C8 /* date.grammar in Resources */, + D3668292101D2BFA0008632C /* erb.grammar in Resources */, + D319E42A106D8A1F008C63DD /* arithmetic.grammar in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + D36C65E7100ED81B000361A0 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#cp -R -f \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\" ${HOME}/Library/Frameworks"; + }; + D3C7D8780A411FBF005DD154 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DC2EF540486A6940098B216 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36C55FF0FD3617B00141CB7 /* RegexKitLite.m in Sources */, + D34BAD9D0FF9C95800D7773A /* PKReader.m in Sources */, + D34BADA20FF9C9B000D7773A /* PKAssembly.m in Sources */, + D34BADD80FF9CBFB00D7773A /* PKParser.m in Sources */, + D34BAE030FF9CCAE00D7773A /* PKCollectionParser.m in Sources */, + D34BAE1D0FF9CE0E00D7773A /* PKAlternation.m in Sources */, + D34BAE1F0FF9CE0E00D7773A /* PKEmpty.m in Sources */, + D34BAE210FF9CE0E00D7773A /* PKDifference.m in Sources */, + D34BAE230FF9CE0E00D7773A /* PKIntersection.m in Sources */, + D34BAE250FF9CE0E00D7773A /* PKRepetition.m in Sources */, + D34BAE270FF9CE0E00D7773A /* PKSequence.m in Sources */, + D34BAE290FF9CE0E00D7773A /* PKTerminal.m in Sources */, + D34BAE2B0FF9CE0E00D7773A /* PKTrack.m in Sources */, + D34BAE2D0FF9CE0E00D7773A /* PKTrackException.m in Sources */, + D34BAE310FF9CE6000D7773A /* PKAny.m in Sources */, + D34BAE8D0FF9D15100D7773A /* PKTokenAssembly.m in Sources */, + D34BAE9D0FF9D20900D7773A /* PKToken.m in Sources */, + D34BAE9F0FF9D20900D7773A /* PKTokenArraySource.m in Sources */, + D34BAEA10FF9D20900D7773A /* PKTokenizer.m in Sources */, + D34BAEA30FF9D20900D7773A /* PKTokenizerState.m in Sources */, + D34BAED80FF9D56400D7773A /* PKCommentState.m in Sources */, + D34BAEDA0FF9D56400D7773A /* PKDelimitState.m in Sources */, + D34BAEDC0FF9D56400D7773A /* PKMultiLineCommentState.m in Sources */, + D34BAEDE0FF9D56400D7773A /* PKNumberState.m in Sources */, + D34BAEE00FF9D56400D7773A /* PKQuoteState.m in Sources */, + D34BAEE20FF9D56400D7773A /* PKSingleLineCommentState.m in Sources */, + D34BAEE40FF9D56400D7773A /* PKSymbolState.m in Sources */, + D34BAEE60FF9D56400D7773A /* PKWhitespaceState.m in Sources */, + D34BAEE80FF9D56400D7773A /* PKWord.m in Sources */, + D34BAEEA0FF9D56400D7773A /* PKWordState.m in Sources */, + D34BAF280FF9DF9900D7773A /* PKSymbolNode.m in Sources */, + D34BAF2A0FF9DF9900D7773A /* PKSymbolRootNode.m in Sources */, + D34BAF3A0FF9E18300D7773A /* PKPattern.m in Sources */, + D34BAF4C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m in Sources */, + D34BAF4E0FF9E19700D7773A /* PKComment.m in Sources */, + D34BAF500FF9E19700D7773A /* PKDelimitedString.m in Sources */, + D34BAF520FF9E19700D7773A /* PKLiteral.m in Sources */, + D34BAF540FF9E19700D7773A /* PKNumber.m in Sources */, + D34BAF560FF9E19700D7773A /* PKQuotedString.m in Sources */, + D34BAF580FF9E19700D7773A /* PKSymbol.m in Sources */, + D34BAF5A0FF9E19700D7773A /* PKWhitespace.m in Sources */, + D34BAF9D0FF9E6D100D7773A /* PKLowercaseWord.m in Sources */, + D34BAF9F0FF9E6D100D7773A /* PKUppercaseWord.m in Sources */, + D34BAFB20FF9E7F300D7773A /* PKCharacterAssembly.m in Sources */, + D34BAFBC0FF9E80300D7773A /* PKChar.m in Sources */, + D34BAFBE0FF9E80300D7773A /* PKDigit.m in Sources */, + D34BAFC00FF9E80300D7773A /* PKLetter.m in Sources */, + D34BAFC20FF9E80300D7773A /* PKSpecificChar.m in Sources */, + D34BAFDA0FF9E95500D7773A /* NSArray+ParseKitAdditions.m in Sources */, + D34BAFDC0FF9E95500D7773A /* NSString+ParseKitAdditions.m in Sources */, + D34BAFDE0FF9E95500D7773A /* PKParserFactory.m in Sources */, + D3126D060FFD9BA700CBF4C4 /* PKNegation.m in Sources */, + D3376D5A10093A1600E4602E /* PKGrammarParser.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D334940D0E2963FD00406085 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36E98E70E58C14000496BD3 /* DemoAppDelegate.m in Sources */, + D36E98E80E58C14000496BD3 /* main.m in Sources */, + D3F5629A10266CFC00DD6DB1 /* PKParseTreeView.m in Sources */, + D3F562A010266DFB00DD6DB1 /* DemoTokensViewController.m in Sources */, + D3F562A710266E8D00DD6DB1 /* DemoTreesViewController.m in Sources */, + D3305C4F102F5BAE00DC4F75 /* TDGutterView.m in Sources */, + D3305C50102F5BAE00DC4F75 /* TDSourceCodeTextView.m in Sources */, + D36934721038E28300527AF3 /* PKParseTree.m in Sources */, + D36934731038E28700527AF3 /* PKParseTreeAssembler.m in Sources */, + D36934741038E28B00527AF3 /* PKRuleNode.m in Sources */, + D36934751038E28F00527AF3 /* PKTokenNode.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D34185010E520D3F0081B0DC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36E98E20E58C12800496BD3 /* main.m in Sources */, + D36E98E00E58C12800496BD3 /* DebugAppDelegate.m in Sources */, + D3EADD8F0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */, + D31FE7420E60F40900A0803E /* XPathContext.m in Sources */, + D31FE7400E60F40300A0803E /* XPathAssembler.m in Sources */, + D31FE7340E60F34600A0803E /* XPathParser.m in Sources */, + D31FE7330E60F33C00A0803E /* XMLReader.m in Sources */, + D31FE7320E60F33000A0803E /* EBNFParser.m in Sources */, + D31FE7300E60F31E00A0803E /* TDFastJsonParser.m in Sources */, + D302C69D0EF044810090E714 /* TDPlistParser.m in Sources */, + D3F740B70EF8C38A00559B9F /* JSONAssembler.m in Sources */, + D385F98C0F046FE900DB2946 /* TDGenericAssembler.m in Sources */, + D385FD440F05A88C00DB2946 /* TDMiniCSSAssembler.m in Sources */, + D3DDDA870F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */, + D389F5B80F19C76A00558235 /* TDJsonParser.m in Sources */, + D31A16530F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */, + D3252F7E0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */, + D3385FDA0FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */, + D355C62E0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */, + D3BBBC9D0FEC9756007DF30D /* TDXMLParser.m in Sources */, + D3376D8F10096C0700E4602E /* PKAST.m in Sources */, + D319E42F106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1CB0F1965E600558235 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D34BB0690FF9EDDF00D7773A /* JSParseKit.m in Sources */, + D34BB0720FF9EE4000D7773A /* PKJSAssembly.m in Sources */, + D34BB0740FF9EE4000D7773A /* PKJSUtils.m in Sources */, + D34BB0770FF9EE4000D7773A /* PKJSValueHolder.m in Sources */, + D34BB0900FF9EF9D00D7773A /* PKJSCharacterAssembly.m in Sources */, + D34BB0AA0FF9F14B00D7773A /* PKJSCommentState.m in Sources */, + D34BB0AC0FF9F14B00D7773A /* PKJSDelimitState.m in Sources */, + D34BB0AE0FF9F14B00D7773A /* PKJSNumberState.m in Sources */, + D34BB0B00FF9F14B00D7773A /* PKJSQuoteState.m in Sources */, + D34BB0B20FF9F14B00D7773A /* PKJSSymbolState.m in Sources */, + D34BB0B40FF9F14B00D7773A /* PKJSToken.m in Sources */, + D34BB0B60FF9F14B00D7773A /* PKJSTokenAssembly.m in Sources */, + D34BB0B80FF9F14B00D7773A /* PKJSTokenizer.m in Sources */, + D34BB0BA0FF9F14B00D7773A /* PKJSTokenizerState.m in Sources */, + D34BB0BC0FF9F14B00D7773A /* PKJSWhitespaceState.m in Sources */, + D34BB0BE0FF9F14B00D7773A /* PKJSWordState.m in Sources */, + D34BB0E70FF9F28000D7773A /* PKJSAlternation.m in Sources */, + D34BB0E90FF9F28000D7773A /* PKJSAny.m in Sources */, + D34BB0EB0FF9F28000D7773A /* PKJSAssemblerAdapter.m in Sources */, + D34BB0ED0FF9F28000D7773A /* PKJSCollectionParser.m in Sources */, + D34BB0EF0FF9F28000D7773A /* PKJSEmpty.m in Sources */, + D34BB0F10FF9F28000D7773A /* PKJSParser.m in Sources */, + D34BB0F30FF9F28000D7773A /* PKJSRepetition.m in Sources */, + D34BB0F50FF9F28000D7773A /* PKJSSequence.m in Sources */, + D34BB0F70FF9F28000D7773A /* PKJSTerminal.m in Sources */, + D34BB0F90FF9F28000D7773A /* PKJSTrack.m in Sources */, + D34BB1150FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m in Sources */, + D34BB1170FF9F36200D7773A /* PKJSComment.m in Sources */, + D34BB1190FF9F36200D7773A /* PKJSDelimitedString.m in Sources */, + D34BB11B0FF9F36200D7773A /* PKJSLiteral.m in Sources */, + D34BB11D0FF9F36200D7773A /* PKJSLowercaseWord.m in Sources */, + D34BB11F0FF9F36200D7773A /* PKJSNum.m in Sources */, + D34BB1210FF9F36200D7773A /* PKJSPattern.m in Sources */, + D34BB1230FF9F36200D7773A /* PKJSQuotedString.m in Sources */, + D34BB1250FF9F36200D7773A /* PKJSSymbol.m in Sources */, + D34BB1270FF9F36200D7773A /* PKJSUppercaseWord.m in Sources */, + D34BB1290FF9F36200D7773A /* PKJSWord.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F2000F196A7500558235 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F2E40F196CAE00558235 /* main.m in Sources */, + D389F37A0F197E8000558235 /* JSDemoAppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3C7D8760A411FBF005DD154 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3E788930E567DFD008C7D61 /* SRGSParserTest.m in Sources */, + D3E788960E567E0A008C7D61 /* SRGSParser.m in Sources */, + D3E78A190E574C99008C7D61 /* EBNFParser.m in Sources */, + D3E78A1A0E574C99008C7D61 /* EBNFParserTest.m in Sources */, + D36E95460E578ECC00496BD3 /* XPathParser.m in Sources */, + D36E95D80E57B08400496BD3 /* XPathParserTest.m in Sources */, + D36E97B00E589DAE00496BD3 /* XPathAssembler.m in Sources */, + D36E98220E58A3A800496BD3 /* XPathContext.m in Sources */, + D3521F560E5FA1B0009681F9 /* XMLReader.m in Sources */, + D3521F570E5FA1B0009681F9 /* XMLReaderTest.m in Sources */, + D31FE54C0E60E46100A0803E /* TDTestScaffold.m in Sources */, + D31FE5630E60E50800A0803E /* TDAlternationTest.m in Sources */, + D31FE5640E60E50800A0803E /* TDLiteralTest.m in Sources */, + D31FE5650E60E50800A0803E /* TDParserTest.m in Sources */, + D31FE5660E60E50800A0803E /* TDRepetitionTest.m in Sources */, + D31FE5680E60E50800A0803E /* TDRobotCommandTest.m in Sources */, + D31FE5690E60E50800A0803E /* TDSequenceTest.m in Sources */, + D31FE56A0E60E50800A0803E /* TDSymbolTest.m in Sources */, + D31FE56B0E60E50800A0803E /* TDTokenAssemblyTest.m in Sources */, + D31FE56C0E60E50800A0803E /* TDTrackTest.m in Sources */, + D31FE56D0E60E50800A0803E /* TDUppercaseWordTest.m in Sources */, + D31FE5750E60E55700A0803E /* TDReaderTest.m in Sources */, + D31FE5760E60E55700A0803E /* TDTokenizerTest.m in Sources */, + D31FE5850E60E58C00A0803E /* TDNumberStateTest.m in Sources */, + D31FE5860E60E58C00A0803E /* TDQuoteStateTest.m in Sources */, + D31FE5890E60E58C00A0803E /* TDSymbolStateTest.m in Sources */, + D31FE58A0E60E58C00A0803E /* TDWhitespaceStateTest.m in Sources */, + D31FE58B0E60E58C00A0803E /* TDWordStateTest.m in Sources */, + D31FE5960E60E5AC00A0803E /* TDCharacterAssemblyTest.m in Sources */, + D31FE5970E60E5AC00A0803E /* TDCharTest.m in Sources */, + D31FE5980E60E5AC00A0803E /* TDDigitTest.m in Sources */, + D31FE5990E60E5AC00A0803E /* TDLetterTest.m in Sources */, + D31FE59A0E60E5AC00A0803E /* TDSpecificCharTest.m in Sources */, + D31FE59F0E60E5C000A0803E /* TDRegularParser.m in Sources */, + D31FE5A00E60E5C000A0803E /* TDRegularParserTest.m in Sources */, + D31FE5A90E60E5D500A0803E /* TDFastJsonParser.m in Sources */, + D31FE5AA0E60E5D500A0803E /* TDFastJsonParserTest.m in Sources */, + D31FE5B10E60E64900A0803E /* TDXmlTokenAssembly.m in Sources */, + D31FE5B20E60E64900A0803E /* TDXmlTokenizerTest.m in Sources */, + D31FE5B70E60E66600A0803E /* TDXmlToken.m in Sources */, + D31FE5B80E60E66600A0803E /* TDXmlTokenizer.m in Sources */, + D31FE5DD0E60E69E00A0803E /* TDXmlAttribute.m in Sources */, + D31FE5DE0E60E69E00A0803E /* TDXmlCdata.m in Sources */, + D31FE5DF0E60E69E00A0803E /* TDXmlComment.m in Sources */, + D31FE5E00E60E69E00A0803E /* TDXmlDecl.m in Sources */, + D31FE5E10E60E69E00A0803E /* TDXmlDoctype.m in Sources */, + D31FE5E20E60E69E00A0803E /* TDXmlDocument.m in Sources */, + D31FE5E30E60E69E00A0803E /* TDXmlEndEntity.m in Sources */, + D31FE5E40E60E69E00A0803E /* TDXmlEndTag.m in Sources */, + D31FE5E50E60E69E00A0803E /* TDXmlEntity.m in Sources */, + D31FE5E60E60E69E00A0803E /* TDXmlEntityRef.m in Sources */, + D31FE5E70E60E69E00A0803E /* TDXmlFragment.m in Sources */, + D31FE5E80E60E69E00A0803E /* TDXmlNotation.m in Sources */, + D31FE5E90E60E69E00A0803E /* TDXmlProcessingInstruction.m in Sources */, + D31FE5EA0E60E69E00A0803E /* TDXmlSignificantWhitespace.m in Sources */, + D31FE5EB0E60E69E00A0803E /* TDXmlStartTag.m in Sources */, + D31FE5EC0E60E69E00A0803E /* TDXmlTerminal.m in Sources */, + D31FE5ED0E60E69E00A0803E /* TDXmlText.m in Sources */, + D31FE5EE0E60E69E00A0803E /* TDXmlWhitespace.m in Sources */, + D31FE5FC0E60E6B500A0803E /* TDNCNameState.m in Sources */, + D31FE5FD0E60E6B500A0803E /* TDXmlName.m in Sources */, + D31FE5FE0E60E6B500A0803E /* TDXmlNameState.m in Sources */, + D31FE5FF0E60E6B500A0803E /* TDXmlNameTest.m in Sources */, + D31FE6000E60E6B500A0803E /* TDXmlNmtoken.m in Sources */, + D31FE6010E60E6B500A0803E /* TDXmlNmtokenState.m in Sources */, + D31FE6E00E60EE2500A0803E /* TDNCName.m in Sources */, + D3C85C7B0E63B438000445FD /* TDArithmeticParser.m in Sources */, + D3C85C800E63B9E9000445FD /* TDArithmeticParserTest.m in Sources */, + D3C85D450E63D1BF000445FD /* TDScientificNumberStateTest.m in Sources */, + D3EADD8E0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */, + D38205BE0EEE48EE004340DD /* TDTokenTest.m in Sources */, + D36568A70EEF9FE900226554 /* TDPlistParser.m in Sources */, + D36568AA0EEFA05300226554 /* TDPlistParserTest.m in Sources */, + D3656DFE0EF2620E00226554 /* TDTokenArraySourceTest.m in Sources */, + D3C031ED0EF38D2D00C5ABEB /* TDLowercaseWordTest.m in Sources */, + D385F98E0F046FE900DB2946 /* TDGenericAssembler.m in Sources */, + D385FA230F04971400DB2946 /* TDGenericAssemblerTest.m in Sources */, + D385FD460F05A89100DB2946 /* TDMiniCSSAssemblerTest.m in Sources */, + D385FD490F05A8C900DB2946 /* TDMiniCSSAssembler.m in Sources */, + D3DDDA880F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */, + D3DDDAFE0F083C9700A58000 /* TDCommentStateTest.m in Sources */, + D380BA620F0F06CD0009EC13 /* TDParserFactoryTest.m in Sources */, + D389F5B60F19C76A00558235 /* TDJsonParser.m in Sources */, + D389F5B70F19C76A00558235 /* TDJsonParserTest.m in Sources */, + D31A16520F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */, + D3B43FB80F76E99C0072AF40 /* TDJavaScriptParserTest.m in Sources */, + D3E39C3F0FC5FFD10022DAB9 /* TDDelimitStateTest.m in Sources */, + D3252F7B0FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m in Sources */, + D3252F7F0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */, + D3385FD90FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */, + D3385FDE0FCFB227003BF729 /* TDPredicateEvaluatorTest.m in Sources */, + D36C53790FD27F1300141CB7 /* TDParserFactoryTest2.m in Sources */, + D36C562B0FD365DB00141CB7 /* TDPatternTest.m in Sources */, + D3AF49780FDB122E0032F4DC /* TDParserFactoryPatternTest.m in Sources */, + D355C62D0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */, + D355C6310FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m in Sources */, + D3BBBC9E0FEC9756007DF30D /* TDXMLParser.m in Sources */, + D39E01340FEF02DA00150FC3 /* TDXMLParserTest.m in Sources */, + D338E5BB0FF5DDCB003DE6AA /* TDDifferenceTest.m in Sources */, + D34BAC230FF87F8600D7773A /* TDParserFactoryTest3.m in Sources */, + D34BAC4B0FF892C200D7773A /* XPathParserGrammarTest.m in Sources */, + D3126D0B0FFD9E4B00CBF4C4 /* TDNegationTest.m in Sources */, + D3376D8E10096C0700E4602E /* PKAST.m in Sources */, + D34BAD18100A9B7900996341 /* TDTokenizerStateTest.m in Sources */, + D3668296101D2C200008632C /* ERBTest.m in Sources */, + D3F55F611025737D00DD6DB1 /* TDParseTreeTest.m in Sources */, + D369345D1038DE5300527AF3 /* PKParseTree.m in Sources */, + D369345E1038DE5300527AF3 /* PKParseTreeAssembler.m in Sources */, + D369345F1038DE5300527AF3 /* PKRuleNode.m in Sources */, + D36934601038DE5300527AF3 /* PKTokenNode.m in Sources */, + D3D1BF2810394420003656E5 /* SAXAssembler.m in Sources */, + D3D1BF2B1039445C003656E5 /* SAXTest.m in Sources */, + D38E97CC1061CF6500739C39 /* TDTokenizerBlocksTest.m in Sources */, + D38E98D81062C5BA00739C39 /* TDParserBlocksTest.m in Sources */, + D319E42E106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3FDC5800FFC4BFC00F1F797 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3FDC6EE0FFC4C9E00F1F797 /* RegexKitLite.m in Sources */, + D3FDC6EF0FFC4C9E00F1F797 /* PKReader.m in Sources */, + D3FDC6F00FFC4C9E00F1F797 /* PKAssembly.m in Sources */, + D3FDC6F10FFC4C9E00F1F797 /* PKParser.m in Sources */, + D3FDC6F20FFC4C9E00F1F797 /* PKRepetition.m in Sources */, + D3FDC6F30FFC4C9E00F1F797 /* PKCollectionParser.m in Sources */, + D3FDC6F40FFC4C9E00F1F797 /* PKAlternation.m in Sources */, + D3FDC6F50FFC4C9E00F1F797 /* PKSequence.m in Sources */, + D3FDC6F60FFC4C9E00F1F797 /* PKTrack.m in Sources */, + D3FDC6F70FFC4C9E00F1F797 /* PKTrackException.m in Sources */, + D3FDC6F80FFC4C9E00F1F797 /* PKDifference.m in Sources */, + D3FDC6F90FFC4C9E00F1F797 /* PKIntersection.m in Sources */, + D3FDC6FA0FFC4C9E00F1F797 /* PKTerminal.m in Sources */, + D3FDC6FB0FFC4C9E00F1F797 /* PKEmpty.m in Sources */, + D3FDC6FC0FFC4C9E00F1F797 /* PKTokenAssembly.m in Sources */, + D3FDC6FD0FFC4C9E00F1F797 /* PKToken.m in Sources */, + D3FDC6FE0FFC4C9E00F1F797 /* PKTokenArraySource.m in Sources */, + D3FDC6FF0FFC4C9E00F1F797 /* PKTokenizer.m in Sources */, + D3FDC7000FFC4C9E00F1F797 /* PKTokenizerState.m in Sources */, + D3FDC7010FFC4C9E00F1F797 /* PKNumberState.m in Sources */, + D3FDC7020FFC4C9E00F1F797 /* PKQuoteState.m in Sources */, + D3FDC7030FFC4C9E00F1F797 /* PKSymbolState.m in Sources */, + D3FDC7040FFC4C9E00F1F797 /* PKWordState.m in Sources */, + D3FDC7050FFC4C9E00F1F797 /* PKWhitespaceState.m in Sources */, + D3FDC7060FFC4C9E00F1F797 /* PKDelimitState.m in Sources */, + D3FDC7070FFC4C9E00F1F797 /* PKCommentState.m in Sources */, + D3FDC7080FFC4C9E00F1F797 /* PKSingleLineCommentState.m in Sources */, + D3FDC7090FFC4C9E00F1F797 /* PKMultiLineCommentState.m in Sources */, + D3FDC70A0FFC4C9E00F1F797 /* PKSymbolNode.m in Sources */, + D3FDC70B0FFC4C9E00F1F797 /* PKSymbolRootNode.m in Sources */, + D3FDC70C0FFC4C9E00F1F797 /* PKPattern.m in Sources */, + D3FDC70D0FFC4C9E00F1F797 /* PKWord.m in Sources */, + D3FDC70F0FFC4C9E00F1F797 /* PKQuotedString.m in Sources */, + D3FDC7100FFC4C9E00F1F797 /* PKSymbol.m in Sources */, + D3FDC7110FFC4C9E00F1F797 /* PKLiteral.m in Sources */, + D3FDC7120FFC4C9E00F1F797 /* PKCaseInsensitiveLiteral.m in Sources */, + D3FDC7130FFC4C9E00F1F797 /* PKWhitespace.m in Sources */, + D3FDC7140FFC4C9E00F1F797 /* PKComment.m in Sources */, + D3FDC7150FFC4C9E00F1F797 /* PKDelimitedString.m in Sources */, + D3FDC7160FFC4C9E00F1F797 /* PKAny.m in Sources */, + D3FDC7180FFC4C9E00F1F797 /* PKLowercaseWord.m in Sources */, + D3FDC7190FFC4C9E00F1F797 /* PKUppercaseWord.m in Sources */, + D3FDC71A0FFC4C9E00F1F797 /* PKCharacterAssembly.m in Sources */, + D3FDC71B0FFC4C9E00F1F797 /* PKChar.m in Sources */, + D3FDC71C0FFC4C9E00F1F797 /* PKDigit.m in Sources */, + D3FDC71D0FFC4C9E00F1F797 /* PKLetter.m in Sources */, + D3FDC71E0FFC4C9E00F1F797 /* PKSpecificChar.m in Sources */, + D3FDC71F0FFC4C9E00F1F797 /* PKParserFactory.m in Sources */, + D3FDC7200FFC4C9E00F1F797 /* NSArray+ParseKitAdditions.m in Sources */, + D3FDC7210FFC4C9E00F1F797 /* NSString+ParseKitAdditions.m in Sources */, + D3126DEC0FFDBC1D00CBF4C4 /* PKNegation.m in Sources */, + D3F0E3CC0FFEB70700C9DF74 /* PKNumber.m in Sources */, + D37A28671013942300E936B7 /* PKGrammarParser.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + D31FE7180E60F24700A0803E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D31FE7170E60F24700A0803E /* PBXContainerItemProxy */; + }; + D33494A00E296AA900406085 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D334949F0E296AA900406085 /* PBXContainerItemProxy */; + }; + D34185100E520D6F0081B0DC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D341850F0E520D6F0081B0DC /* PBXContainerItemProxy */; + }; + D389F1D40F19665C00558235 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D389F1D30F19665C00558235 /* PBXContainerItemProxy */; + }; + D389F20A0F196A8000558235 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D389F1CD0F1965E600558235 /* JSParseKit */; + targetProxy = D389F2090F196A8000558235 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 089C1667FE841158C02AAC07 /* English */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1DEB91AE08733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_TEST_COVERAGE_FILES = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKit_Prefix.pch; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GENERATE_PROFILING_CODE = YES; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(TARGET_BUILD_DIR)"; + LLVM_LTO = NO; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + ); + PRODUCT_NAME = ParseKit; + SDKROOT = ""; + WARNING_CFLAGS = "-Wundeclared-selector"; + WRAPPER_EXTENSION = framework; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB91AF08733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "$(TDPARSEKIT_FRAMEWORK_TARGET_PATH)"; + FRAMEWORK_VERSION = A; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKit_Prefix.pch; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvmgcc42; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(TARGET_BUILD_DIR)"; + LLVM_LTO = YES; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + ); + PRODUCT_NAME = ParseKit; + SDKROOT = ""; + TDPARSEKIT_FRAMEWORK_TARGET_PATH = "@executable_path/../Frameworks"; + WARNING_CFLAGS = "-Wundeclared-selector"; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; + 1DEB91B208733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Debug; + }; + 1DEB91B308733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Release; + }; + D33494130E2963FE00406085 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "demoapp/DemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DemoApp; + SDKROOT = ""; + WRAPPER_EXTENSION = app; + ZERO_LINK = YES; + }; + name = Debug; + }; + D33494140E2963FE00406085 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "demoapp/DemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DemoApp; + SDKROOT = ""; + WRAPPER_EXTENSION = app; + ZERO_LINK = NO; + }; + name = Release; + }; + D34185070E520D410081B0DC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/frameworks\""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_WARN_UNUSED_VARIABLE = NO; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "debugapp/DebugApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DebugApp; + SDKROOT = ""; + }; + name = Debug; + }; + D34185080E520D410081B0DC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/frameworks\""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "debugapp/DebugApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DebugApp; + SDKROOT = ""; + ZERO_LINK = NO; + }; + name = Release; + }; + D389F1D00F1965E800558235 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + INFOPLIST_FILE = "JSParseKit-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Frameworks"; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSParseKit; + SDKROOT = ""; + }; + name = Debug; + }; + D389F1D10F1965E800558235 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_GC = YES; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + INFOPLIST_FILE = "JSParseKit-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Frameworks"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSParseKit; + SDKROOT = ""; + ZERO_LINK = NO; + }; + name = Release; + }; + D389F2060F196A7600558235 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = required; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "jsdemoapp/JSDemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSDemoApp; + SDKROOT = ""; + }; + name = Debug; + }; + D389F2070F196A7600558235 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_GC = required; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "jsdemoapp/JSDemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSDemoApp; + SDKROOT = ""; + ZERO_LINK = NO; + }; + name = Release; + }; + D3C7D87D0A411FC0005DD154 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/frameworks\""; + FRAMEWORK_SEARCH_PATH_DEBUG_BUILD = "\"$(SRCROOT)/build/Debug\""; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "test/Tests-Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; + LIBRARY_SEARCH_PATHS = ""; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + MACOSX_DEPLOYMENT_TARGET = 10.5; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + SenTestingKit, + ); + PREBINDING = NO; + PRODUCT_NAME = Tests; + SDKROOT = ""; + USER_HEADER_SEARCH_PATHS = ""; + WARNING_CFLAGS = ""; + WRAPPER_EXTENSION = octest; + ZERO_LINK = YES; + }; + name = Debug; + }; + D3C7D87E0A411FC0005DD154 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"/Library/Frameworks\""; + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/frameworks\""; + GCC_C_LANGUAGE_STANDARD = "compiler-default"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "test/Tests-Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + SenTestingKit, + ); + PREBINDING = NO; + PRODUCT_NAME = Tests; + SDKROOT = ""; + WARNING_CFLAGS = ""; + WRAPPER_EXTENSION = octest; + ZERO_LINK = NO; + }; + name = Release; + }; + D3FDC5840FFC4BFC00F1F797 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKitMobile_Prefix.pch; + HEADER_SEARCH_PATHS = ""; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + PRODUCT_NAME = parsekit; + SDKROOT = iphoneos3.0; + }; + name = Debug; + }; + D3FDC5850FFC4BFC00F1F797 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + EXECUTABLE_PREFIX = ""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKitMobile_Prefix.pch; + HEADER_SEARCH_PATHS = ""; + OTHER_LDFLAGS = ""; + PREBINDING = NO; + PRODUCT_NAME = parsekit; + SDKROOT = iphoneos3.0; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "ParseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91AE08733DA50010E9CD /* Debug */, + 1DEB91AF08733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ParseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91B208733DA50010E9CD /* Debug */, + 1DEB91B308733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D33494150E2963FE00406085 /* Build configuration list for PBXNativeTarget "DemoApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D33494130E2963FE00406085 /* Debug */, + D33494140E2963FE00406085 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D34185090E520D410081B0DC /* Build configuration list for PBXNativeTarget "DebugApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D34185070E520D410081B0DC /* Debug */, + D34185080E520D410081B0DC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D389F1D20F1965E800558235 /* Build configuration list for PBXNativeTarget "JSParseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D389F1D00F1965E800558235 /* Debug */, + D389F1D10F1965E800558235 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D389F2080F196A7600558235 /* Build configuration list for PBXNativeTarget "JSDemoApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D389F2060F196A7600558235 /* Debug */, + D389F2070F196A7600558235 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D3C7D87C0A411FC0005DD154 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D3C7D87D0A411FC0005DD154 /* Debug */, + D3C7D87E0A411FC0005DD154 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D3FDC62F0FFC4C2000F1F797 /* Build configuration list for PBXNativeTarget "ParseKitMobile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D3FDC5840FFC4BFC00F1F797 /* Debug */, + D3FDC5850FFC4BFC00F1F797 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0867D690FE84028FC02AAC07 /* Project object */; +} diff --git a/ParseKit.xcodeproj/project.pbxproj b/ParseKit.xcodeproj/project.pbxproj new file mode 100644 index 0000000..382638b --- /dev/null +++ b/ParseKit.xcodeproj/project.pbxproj @@ -0,0 +1,3720 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; }; + D302C69D0EF044810090E714 /* TDPlistParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36568A60EEF9FE900226554 /* TDPlistParser.m */; }; + D3126D060FFD9BA700CBF4C4 /* PKNegation.m in Sources */ = {isa = PBXBuildFile; fileRef = D3126D040FFD9BA700CBF4C4 /* PKNegation.m */; }; + D3126D0B0FFD9E4B00CBF4C4 /* TDNegationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3126D0A0FFD9E4B00CBF4C4 /* TDNegationTest.m */; }; + D3126DEC0FFDBC1D00CBF4C4 /* PKNegation.m in Sources */ = {isa = PBXBuildFile; fileRef = D3126D040FFD9BA700CBF4C4 /* PKNegation.m */; }; + D315DF720FEF59B600D876C8 /* date.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D315DF710FEF59B600D876C8 /* date.grammar */; }; + D315DF730FEF59B600D876C8 /* date.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D315DF710FEF59B600D876C8 /* date.grammar */; }; + D319E42A106D8A1F008C63DD /* arithmetic.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D319E429106D8A1F008C63DD /* arithmetic.grammar */; }; + D319E42B106D8A1F008C63DD /* arithmetic.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D319E429106D8A1F008C63DD /* arithmetic.grammar */; }; + D319E42E106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */; }; + D319E42F106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */; }; + D31A15260F6DE449002AFDF1 /* javascript.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D31A15250F6DE449002AFDF1 /* javascript.grammar */; }; + D31A15270F6DE449002AFDF1 /* javascript.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D31A15250F6DE449002AFDF1 /* javascript.grammar */; }; + D31A16520F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */; }; + D31A16530F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */; }; + D31FE54C0E60E46100A0803E /* TDTestScaffold.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE54B0E60E46100A0803E /* TDTestScaffold.m */; }; + D31FE5630E60E50800A0803E /* TDAlternationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE54E0E60E50800A0803E /* TDAlternationTest.m */; }; + D31FE5640E60E50800A0803E /* TDLiteralTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5500E60E50800A0803E /* TDLiteralTest.m */; }; + D31FE5650E60E50800A0803E /* TDParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5520E60E50800A0803E /* TDParserTest.m */; }; + D31FE5660E60E50800A0803E /* TDRepetitionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5540E60E50800A0803E /* TDRepetitionTest.m */; }; + D31FE5680E60E50800A0803E /* TDRobotCommandTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5580E60E50800A0803E /* TDRobotCommandTest.m */; }; + D31FE5690E60E50800A0803E /* TDSequenceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE55A0E60E50800A0803E /* TDSequenceTest.m */; }; + D31FE56A0E60E50800A0803E /* TDSymbolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE55C0E60E50800A0803E /* TDSymbolTest.m */; }; + D31FE56B0E60E50800A0803E /* TDTokenAssemblyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE55E0E60E50800A0803E /* TDTokenAssemblyTest.m */; }; + D31FE56C0E60E50800A0803E /* TDTrackTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5600E60E50800A0803E /* TDTrackTest.m */; }; + D31FE56D0E60E50800A0803E /* TDUppercaseWordTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5620E60E50800A0803E /* TDUppercaseWordTest.m */; }; + D31FE5750E60E55700A0803E /* TDReaderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5720E60E55700A0803E /* TDReaderTest.m */; }; + D31FE5760E60E55700A0803E /* TDTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5740E60E55700A0803E /* TDTokenizerTest.m */; }; + D31FE5850E60E58C00A0803E /* TDNumberStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5780E60E58C00A0803E /* TDNumberStateTest.m */; }; + D31FE5860E60E58C00A0803E /* TDQuoteStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE57A0E60E58C00A0803E /* TDQuoteStateTest.m */; }; + D31FE5890E60E58C00A0803E /* TDSymbolStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5800E60E58C00A0803E /* TDSymbolStateTest.m */; }; + D31FE58A0E60E58C00A0803E /* TDWhitespaceStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5820E60E58C00A0803E /* TDWhitespaceStateTest.m */; }; + D31FE58B0E60E58C00A0803E /* TDWordStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5840E60E58C00A0803E /* TDWordStateTest.m */; }; + D31FE5960E60E5AC00A0803E /* TDCharacterAssemblyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE58D0E60E5AC00A0803E /* TDCharacterAssemblyTest.m */; }; + D31FE5970E60E5AC00A0803E /* TDCharTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE58F0E60E5AC00A0803E /* TDCharTest.m */; }; + D31FE5980E60E5AC00A0803E /* TDDigitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5910E60E5AC00A0803E /* TDDigitTest.m */; }; + D31FE5990E60E5AC00A0803E /* TDLetterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5930E60E5AC00A0803E /* TDLetterTest.m */; }; + D31FE59A0E60E5AC00A0803E /* TDSpecificCharTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5950E60E5AC00A0803E /* TDSpecificCharTest.m */; }; + D31FE59F0E60E5C000A0803E /* TDRegularParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE59C0E60E5C000A0803E /* TDRegularParser.m */; }; + D31FE5A00E60E5C000A0803E /* TDRegularParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE59E0E60E5C000A0803E /* TDRegularParserTest.m */; }; + D31FE5A90E60E5D500A0803E /* TDFastJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */; }; + D31FE5AA0E60E5D500A0803E /* TDFastJsonParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5A40E60E5D500A0803E /* TDFastJsonParserTest.m */; }; + D31FE5B10E60E64900A0803E /* TDXmlTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5AE0E60E64900A0803E /* TDXmlTokenAssembly.m */; }; + D31FE5B20E60E64900A0803E /* TDXmlTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5B00E60E64900A0803E /* TDXmlTokenizerTest.m */; }; + D31FE5B70E60E66600A0803E /* TDXmlToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5B40E60E66600A0803E /* TDXmlToken.m */; }; + D31FE5B80E60E66600A0803E /* TDXmlTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5B60E60E66600A0803E /* TDXmlTokenizer.m */; }; + D31FE5DD0E60E69E00A0803E /* TDXmlAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5BA0E60E69E00A0803E /* TDXmlAttribute.m */; }; + D31FE5DE0E60E69E00A0803E /* TDXmlCdata.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5BC0E60E69E00A0803E /* TDXmlCdata.m */; }; + D31FE5DF0E60E69E00A0803E /* TDXmlComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5BE0E60E69E00A0803E /* TDXmlComment.m */; }; + D31FE5E00E60E69E00A0803E /* TDXmlDecl.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C00E60E69E00A0803E /* TDXmlDecl.m */; }; + D31FE5E10E60E69E00A0803E /* TDXmlDoctype.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C20E60E69E00A0803E /* TDXmlDoctype.m */; }; + D31FE5E20E60E69E00A0803E /* TDXmlDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C40E60E69E00A0803E /* TDXmlDocument.m */; }; + D31FE5E30E60E69E00A0803E /* TDXmlEndEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C60E60E69E00A0803E /* TDXmlEndEntity.m */; }; + D31FE5E40E60E69E00A0803E /* TDXmlEndTag.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5C80E60E69E00A0803E /* TDXmlEndTag.m */; }; + D31FE5E50E60E69E00A0803E /* TDXmlEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5CA0E60E69E00A0803E /* TDXmlEntity.m */; }; + D31FE5E60E60E69E00A0803E /* TDXmlEntityRef.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5CC0E60E69E00A0803E /* TDXmlEntityRef.m */; }; + D31FE5E70E60E69E00A0803E /* TDXmlFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5CE0E60E69E00A0803E /* TDXmlFragment.m */; }; + D31FE5E80E60E69E00A0803E /* TDXmlNotation.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D00E60E69E00A0803E /* TDXmlNotation.m */; }; + D31FE5E90E60E69E00A0803E /* TDXmlProcessingInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D20E60E69E00A0803E /* TDXmlProcessingInstruction.m */; }; + D31FE5EA0E60E69E00A0803E /* TDXmlSignificantWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D40E60E69E00A0803E /* TDXmlSignificantWhitespace.m */; }; + D31FE5EB0E60E69E00A0803E /* TDXmlStartTag.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D60E60E69E00A0803E /* TDXmlStartTag.m */; }; + D31FE5EC0E60E69E00A0803E /* TDXmlTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5D80E60E69E00A0803E /* TDXmlTerminal.m */; }; + D31FE5ED0E60E69E00A0803E /* TDXmlText.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5DA0E60E69E00A0803E /* TDXmlText.m */; }; + D31FE5EE0E60E69E00A0803E /* TDXmlWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5DC0E60E69E00A0803E /* TDXmlWhitespace.m */; }; + D31FE5FC0E60E6B500A0803E /* TDNCNameState.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F10E60E6B500A0803E /* TDNCNameState.m */; }; + D31FE5FD0E60E6B500A0803E /* TDXmlName.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F30E60E6B500A0803E /* TDXmlName.m */; }; + D31FE5FE0E60E6B500A0803E /* TDXmlNameState.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F50E60E6B500A0803E /* TDXmlNameState.m */; }; + D31FE5FF0E60E6B500A0803E /* TDXmlNameTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F70E60E6B500A0803E /* TDXmlNameTest.m */; }; + D31FE6000E60E6B500A0803E /* TDXmlNmtoken.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5F90E60E6B500A0803E /* TDXmlNmtoken.m */; }; + D31FE6010E60E6B500A0803E /* TDXmlNmtokenState.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5FB0E60E6B500A0803E /* TDXmlNmtokenState.m */; }; + D31FE6E00E60EE2500A0803E /* TDNCName.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE6DF0E60EE2500A0803E /* TDNCName.m */; }; + D31FE7300E60F31E00A0803E /* TDFastJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */; }; + D31FE7320E60F33000A0803E /* EBNFParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E78A160E574C99008C7D61 /* EBNFParser.m */; }; + D31FE7330E60F33C00A0803E /* XMLReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D3521F530E5FA1B0009681F9 /* XMLReader.m */; }; + D31FE7340E60F34600A0803E /* XPathParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E95450E578ECC00496BD3 /* XPathParser.m */; }; + D31FE7380E60F36600A0803E /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D36E9F860E5A795400496BD3 /* libxml2.dylib */; }; + D31FE7400E60F40300A0803E /* XPathAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */; }; + D31FE7420E60F40900A0803E /* XPathContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98210E58A3A800496BD3 /* XPathContext.m */; }; + D3252F7B0FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3252F790FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m */; }; + D3252F7E0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */; }; + D3252F7F0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */; }; + D3305C4F102F5BAE00DC4F75 /* TDGutterView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3305C4C102F5BAD00DC4F75 /* TDGutterView.m */; }; + D3305C50102F5BAE00DC4F75 /* TDSourceCodeTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3305C4E102F5BAE00DC4F75 /* TDSourceCodeTextView.m */; }; + D33494720E29670B00406085 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D3376D5910093A1600E4602E /* PKGrammarParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3376D5710093A1600E4602E /* PKGrammarParser.h */; }; + D3376D5A10093A1600E4602E /* PKGrammarParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D5810093A1600E4602E /* PKGrammarParser.m */; }; + D3376D8E10096C0700E4602E /* PKAST.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D8D10096C0700E4602E /* PKAST.m */; }; + D3376D8F10096C0700E4602E /* PKAST.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D8D10096C0700E4602E /* PKAST.m */; }; + D3385FD90FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */; }; + D3385FDA0FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */; }; + D3385FDE0FCFB227003BF729 /* TDPredicateEvaluatorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3385FDC0FCFB227003BF729 /* TDPredicateEvaluatorTest.m */; }; + D338E5BB0FF5DDCB003DE6AA /* TDDifferenceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D338E5BA0FF5DDCB003DE6AA /* TDDifferenceTest.m */; }; + D341850C0E520D640081B0DC /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D34BAC230FF87F8600D7773A /* TDParserFactoryTest3.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAC220FF87F8600D7773A /* TDParserFactoryTest3.m */; }; + D34BAC4B0FF892C200D7773A /* XPathParserGrammarTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAC4A0FF892C200D7773A /* XPathParserGrammarTest.m */; }; + D34BAC9A0FF8A9AD00D7773A /* xpath1_0.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741430EF8E96A00559B9F /* xpath1_0.grammar */; }; + D34BAD18100A9B7900996341 /* TDTokenizerStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAD17100A9B7900996341 /* TDTokenizerStateTest.m */; }; + D34BAD640FF9C6AE00D7773A /* ParseKit_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = D34BAD630FF9C6AE00D7773A /* ParseKit_Prefix.pch */; }; + D34BAD9D0FF9C95800D7773A /* PKReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAD9B0FF9C95800D7773A /* PKReader.m */; }; + D34BADA20FF9C9B000D7773A /* PKAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADA00FF9C9B000D7773A /* PKAssembly.m */; }; + D34BADD80FF9CBFB00D7773A /* PKParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADD60FF9CBFB00D7773A /* PKParser.m */; }; + D34BAE030FF9CCAE00D7773A /* PKCollectionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */; }; + D34BAE1D0FF9CE0E00D7773A /* PKAlternation.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */; }; + D34BAE1F0FF9CE0E00D7773A /* PKEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */; }; + D34BAE210FF9CE0E00D7773A /* PKDifference.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */; }; + D34BAE230FF9CE0E00D7773A /* PKIntersection.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE110FF9CE0E00D7773A /* PKIntersection.m */; }; + D34BAE250FF9CE0E00D7773A /* PKRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE130FF9CE0E00D7773A /* PKRepetition.m */; }; + D34BAE270FF9CE0E00D7773A /* PKSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE150FF9CE0E00D7773A /* PKSequence.m */; }; + D34BAE290FF9CE0E00D7773A /* PKTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE170FF9CE0E00D7773A /* PKTerminal.m */; }; + D34BAE2B0FF9CE0E00D7773A /* PKTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE190FF9CE0E00D7773A /* PKTrack.m */; }; + D34BAE2D0FF9CE0E00D7773A /* PKTrackException.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */; }; + D34BAE310FF9CE6000D7773A /* PKAny.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE2F0FF9CE6000D7773A /* PKAny.m */; }; + D34BAE8D0FF9D15100D7773A /* PKTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */; }; + D34BAE9D0FF9D20900D7773A /* PKToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE950FF9D20900D7773A /* PKToken.m */; }; + D34BAE9F0FF9D20900D7773A /* PKTokenArraySource.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */; }; + D34BAEA10FF9D20900D7773A /* PKTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE990FF9D20900D7773A /* PKTokenizer.m */; }; + D34BAEA30FF9D20900D7773A /* PKTokenizerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */; }; + D34BAED80FF9D56400D7773A /* PKCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC40FF9D56400D7773A /* PKCommentState.m */; }; + D34BAEDA0FF9D56400D7773A /* PKDelimitState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC60FF9D56400D7773A /* PKDelimitState.m */; }; + D34BAEDC0FF9D56400D7773A /* PKMultiLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */; }; + D34BAEDE0FF9D56400D7773A /* PKNumberState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECA0FF9D56400D7773A /* PKNumberState.m */; }; + D34BAEE00FF9D56400D7773A /* PKQuoteState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECC0FF9D56400D7773A /* PKQuoteState.m */; }; + D34BAEE20FF9D56400D7773A /* PKSingleLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */; }; + D34BAEE40FF9D56400D7773A /* PKSymbolState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED00FF9D56400D7773A /* PKSymbolState.m */; }; + D34BAEE60FF9D56400D7773A /* PKWhitespaceState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */; }; + D34BAEE80FF9D56400D7773A /* PKWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED40FF9D56400D7773A /* PKWord.m */; }; + D34BAEEA0FF9D56400D7773A /* PKWordState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED60FF9D56400D7773A /* PKWordState.m */; }; + D34BAF280FF9DF9900D7773A /* PKSymbolNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */; }; + D34BAF2A0FF9DF9900D7773A /* PKSymbolRootNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */; }; + D34BAF3A0FF9E18300D7773A /* PKPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF380FF9E18300D7773A /* PKPattern.m */; }; + D34BAF4C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */; }; + D34BAF4E0FF9E19700D7773A /* PKComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3E0FF9E19700D7773A /* PKComment.m */; }; + D34BAF500FF9E19700D7773A /* PKDelimitedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF400FF9E19700D7773A /* PKDelimitedString.m */; }; + D34BAF520FF9E19700D7773A /* PKLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF420FF9E19700D7773A /* PKLiteral.m */; }; + D34BAF540FF9E19700D7773A /* PKNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF440FF9E19700D7773A /* PKNumber.m */; }; + D34BAF560FF9E19700D7773A /* PKQuotedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF460FF9E19700D7773A /* PKQuotedString.m */; }; + D34BAF580FF9E19700D7773A /* PKSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF480FF9E19700D7773A /* PKSymbol.m */; }; + D34BAF5A0FF9E19700D7773A /* PKWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */; }; + D34BAF9D0FF9E6D100D7773A /* PKLowercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */; }; + D34BAF9F0FF9E6D100D7773A /* PKUppercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */; }; + D34BAFB20FF9E7F300D7773A /* PKCharacterAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */; }; + D34BAFBC0FF9E80300D7773A /* PKChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB40FF9E80300D7773A /* PKChar.m */; }; + D34BAFBE0FF9E80300D7773A /* PKDigit.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB60FF9E80300D7773A /* PKDigit.m */; }; + D34BAFC00FF9E80300D7773A /* PKLetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB80FF9E80300D7773A /* PKLetter.m */; }; + D34BAFC20FF9E80300D7773A /* PKSpecificChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */; }; + D34BAFDA0FF9E95500D7773A /* NSArray+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */; }; + D34BAFDC0FF9E95500D7773A /* NSString+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */; }; + D34BAFDE0FF9E95500D7773A /* PKParserFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD80FF9E95500D7773A /* PKParserFactory.m */; }; + D34BB0680FF9EDDF00D7773A /* JSParseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0660FF9EDDF00D7773A /* JSParseKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0690FF9EDDF00D7773A /* JSParseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0670FF9EDDF00D7773A /* JSParseKit.m */; }; + D34BB0710FF9EE4000D7773A /* PKJSAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06A0FF9EE4000D7773A /* PKJSAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0720FF9EE4000D7773A /* PKJSAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB06B0FF9EE4000D7773A /* PKJSAssembly.m */; }; + D34BB0730FF9EE4000D7773A /* PKJSUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06C0FF9EE4000D7773A /* PKJSUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0740FF9EE4000D7773A /* PKJSUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB06D0FF9EE4000D7773A /* PKJSUtils.m */; }; + D34BB0750FF9EE4000D7773A /* PKJSUtils_macros.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06E0FF9EE4000D7773A /* PKJSUtils_macros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0760FF9EE4000D7773A /* PKJSValueHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB06F0FF9EE4000D7773A /* PKJSValueHolder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0770FF9EE4000D7773A /* PKJSValueHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0700FF9EE4000D7773A /* PKJSValueHolder.m */; }; + D34BB08F0FF9EF9D00D7773A /* PKJSCharacterAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB08D0FF9EF9D00D7773A /* PKJSCharacterAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0900FF9EF9D00D7773A /* PKJSCharacterAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB08E0FF9EF9D00D7773A /* PKJSCharacterAssembly.m */; }; + D34BB0A90FF9F14B00D7773A /* PKJSCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0930FF9F14B00D7773A /* PKJSCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0AA0FF9F14B00D7773A /* PKJSCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0940FF9F14B00D7773A /* PKJSCommentState.m */; }; + D34BB0AB0FF9F14B00D7773A /* PKJSDelimitState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0950FF9F14B00D7773A /* PKJSDelimitState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0AC0FF9F14B00D7773A /* PKJSDelimitState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0960FF9F14B00D7773A /* PKJSDelimitState.m */; }; + D34BB0AD0FF9F14B00D7773A /* PKJSNumberState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0970FF9F14B00D7773A /* PKJSNumberState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0AE0FF9F14B00D7773A /* PKJSNumberState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0980FF9F14B00D7773A /* PKJSNumberState.m */; }; + D34BB0AF0FF9F14B00D7773A /* PKJSQuoteState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0990FF9F14B00D7773A /* PKJSQuoteState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B00FF9F14B00D7773A /* PKJSQuoteState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB09A0FF9F14B00D7773A /* PKJSQuoteState.m */; }; + D34BB0B10FF9F14B00D7773A /* PKJSSymbolState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB09B0FF9F14B00D7773A /* PKJSSymbolState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B20FF9F14B00D7773A /* PKJSSymbolState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB09C0FF9F14B00D7773A /* PKJSSymbolState.m */; }; + D34BB0B30FF9F14B00D7773A /* PKJSToken.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB09D0FF9F14B00D7773A /* PKJSToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B40FF9F14B00D7773A /* PKJSToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB09E0FF9F14B00D7773A /* PKJSToken.m */; }; + D34BB0B50FF9F14B00D7773A /* PKJSTokenAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB09F0FF9F14B00D7773A /* PKJSTokenAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B60FF9F14B00D7773A /* PKJSTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A00FF9F14B00D7773A /* PKJSTokenAssembly.m */; }; + D34BB0B70FF9F14B00D7773A /* PKJSTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A10FF9F14B00D7773A /* PKJSTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0B80FF9F14B00D7773A /* PKJSTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A20FF9F14B00D7773A /* PKJSTokenizer.m */; }; + D34BB0B90FF9F14B00D7773A /* PKJSTokenizerState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A30FF9F14B00D7773A /* PKJSTokenizerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0BA0FF9F14B00D7773A /* PKJSTokenizerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A40FF9F14B00D7773A /* PKJSTokenizerState.m */; }; + D34BB0BB0FF9F14B00D7773A /* PKJSWhitespaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A50FF9F14B00D7773A /* PKJSWhitespaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0BC0FF9F14B00D7773A /* PKJSWhitespaceState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A60FF9F14B00D7773A /* PKJSWhitespaceState.m */; }; + D34BB0BD0FF9F14B00D7773A /* PKJSWordState.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0A70FF9F14B00D7773A /* PKJSWordState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0BE0FF9F14B00D7773A /* PKJSWordState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0A80FF9F14B00D7773A /* PKJSWordState.m */; }; + D34BB0E60FF9F28000D7773A /* PKJSAlternation.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D20FF9F28000D7773A /* PKJSAlternation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0E70FF9F28000D7773A /* PKJSAlternation.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D30FF9F28000D7773A /* PKJSAlternation.m */; }; + D34BB0E80FF9F28000D7773A /* PKJSAny.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D40FF9F28000D7773A /* PKJSAny.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0E90FF9F28000D7773A /* PKJSAny.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D50FF9F28000D7773A /* PKJSAny.m */; }; + D34BB0EA0FF9F28000D7773A /* PKJSAssemblerAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D60FF9F28000D7773A /* PKJSAssemblerAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0EB0FF9F28000D7773A /* PKJSAssemblerAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D70FF9F28000D7773A /* PKJSAssemblerAdapter.m */; }; + D34BB0EC0FF9F28000D7773A /* PKJSCollectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0D80FF9F28000D7773A /* PKJSCollectionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0ED0FF9F28000D7773A /* PKJSCollectionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0D90FF9F28000D7773A /* PKJSCollectionParser.m */; }; + D34BB0EE0FF9F28000D7773A /* PKJSEmpty.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0DA0FF9F28000D7773A /* PKJSEmpty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0EF0FF9F28000D7773A /* PKJSEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0DB0FF9F28000D7773A /* PKJSEmpty.m */; }; + D34BB0F00FF9F28000D7773A /* PKJSParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0DC0FF9F28000D7773A /* PKJSParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F10FF9F28000D7773A /* PKJSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0DD0FF9F28000D7773A /* PKJSParser.m */; }; + D34BB0F20FF9F28000D7773A /* PKJSRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0DE0FF9F28000D7773A /* PKJSRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F30FF9F28000D7773A /* PKJSRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0DF0FF9F28000D7773A /* PKJSRepetition.m */; }; + D34BB0F40FF9F28000D7773A /* PKJSSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0E00FF9F28000D7773A /* PKJSSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F50FF9F28000D7773A /* PKJSSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0E10FF9F28000D7773A /* PKJSSequence.m */; }; + D34BB0F60FF9F28000D7773A /* PKJSTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0E20FF9F28000D7773A /* PKJSTerminal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F70FF9F28000D7773A /* PKJSTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0E30FF9F28000D7773A /* PKJSTerminal.m */; }; + D34BB0F80FF9F28000D7773A /* PKJSTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0E40FF9F28000D7773A /* PKJSTrack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB0F90FF9F28000D7773A /* PKJSTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0E50FF9F28000D7773A /* PKJSTrack.m */; }; + D34BB1140FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB0FE0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1150FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB0FF0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m */; }; + D34BB1160FF9F36200D7773A /* PKJSComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1000FF9F36200D7773A /* PKJSComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1170FF9F36200D7773A /* PKJSComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1010FF9F36200D7773A /* PKJSComment.m */; }; + D34BB1180FF9F36200D7773A /* PKJSDelimitedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1020FF9F36200D7773A /* PKJSDelimitedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1190FF9F36200D7773A /* PKJSDelimitedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1030FF9F36200D7773A /* PKJSDelimitedString.m */; }; + D34BB11A0FF9F36200D7773A /* PKJSLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1040FF9F36200D7773A /* PKJSLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB11B0FF9F36200D7773A /* PKJSLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1050FF9F36200D7773A /* PKJSLiteral.m */; }; + D34BB11C0FF9F36200D7773A /* PKJSLowercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1060FF9F36200D7773A /* PKJSLowercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB11D0FF9F36200D7773A /* PKJSLowercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1070FF9F36200D7773A /* PKJSLowercaseWord.m */; }; + D34BB11E0FF9F36200D7773A /* PKJSNum.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1080FF9F36200D7773A /* PKJSNum.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB11F0FF9F36200D7773A /* PKJSNum.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1090FF9F36200D7773A /* PKJSNum.m */; }; + D34BB1200FF9F36200D7773A /* PKJSPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB10A0FF9F36200D7773A /* PKJSPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1210FF9F36200D7773A /* PKJSPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB10B0FF9F36200D7773A /* PKJSPattern.m */; }; + D34BB1220FF9F36200D7773A /* PKJSQuotedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB10C0FF9F36200D7773A /* PKJSQuotedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1230FF9F36200D7773A /* PKJSQuotedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB10D0FF9F36200D7773A /* PKJSQuotedString.m */; }; + D34BB1240FF9F36200D7773A /* PKJSSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB10E0FF9F36200D7773A /* PKJSSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1250FF9F36200D7773A /* PKJSSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB10F0FF9F36200D7773A /* PKJSSymbol.m */; }; + D34BB1260FF9F36200D7773A /* PKJSUppercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1100FF9F36200D7773A /* PKJSUppercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1270FF9F36200D7773A /* PKJSUppercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1110FF9F36200D7773A /* PKJSUppercaseWord.m */; }; + D34BB1280FF9F36200D7773A /* PKJSWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BB1120FF9F36200D7773A /* PKJSWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D34BB1290FF9F36200D7773A /* PKJSWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BB1130FF9F36200D7773A /* PKJSWord.m */; }; + D3521F560E5FA1B0009681F9 /* XMLReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D3521F530E5FA1B0009681F9 /* XMLReader.m */; }; + D3521F570E5FA1B0009681F9 /* XMLReaderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3521F550E5FA1B0009681F9 /* XMLReaderTest.m */; }; + D35384ED0FE9691100926552 /* nspredicate.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D35384EC0FE9691100926552 /* nspredicate.grammar */; }; + D353899C0FEAC94400926552 /* c.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D353899B0FEAC94400926552 /* c.grammar */; }; + D353899E0FEAC96B00926552 /* objc.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D353899D0FEAC96B00926552 /* objc.grammar */; }; + D355C62D0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */; }; + D355C62E0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */; }; + D355C6310FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D355C6300FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m */; }; + D355C6A70FE9F704006A91A4 /* nspredicate.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D35384EC0FE9691100926552 /* nspredicate.grammar */; }; + D355C8810FEB36A1006A91A4 /* xml.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D355C8800FEB36A1006A91A4 /* xml.grammar */; }; + D355C8840FEB4B94006A91A4 /* proto.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D355C8830FEB4B94006A91A4 /* proto.grammar */; }; + D3587EAF0FE83EC900DDD023 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D36568A70EEF9FE900226554 /* TDPlistParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36568A60EEF9FE900226554 /* TDPlistParser.m */; }; + D36568AA0EEFA05300226554 /* TDPlistParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D36568A90EEFA05300226554 /* TDPlistParserTest.m */; }; + D3656DFE0EF2620E00226554 /* TDTokenArraySourceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3656DFD0EF2620E00226554 /* TDTokenArraySourceTest.m */; }; + D3668292101D2BFA0008632C /* erb.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3668291101D2BFA0008632C /* erb.grammar */; }; + D3668293101D2C000008632C /* erb.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3668291101D2BFA0008632C /* erb.grammar */; }; + D3668296101D2C200008632C /* ERBTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3668295101D2C200008632C /* ERBTest.m */; }; + D369345D1038DE5300527AF3 /* PKParseTree.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934561038DE5300527AF3 /* PKParseTree.m */; }; + D369345E1038DE5300527AF3 /* PKParseTreeAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */; }; + D369345F1038DE5300527AF3 /* PKRuleNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345A1038DE5300527AF3 /* PKRuleNode.m */; }; + D36934601038DE5300527AF3 /* PKTokenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345C1038DE5300527AF3 /* PKTokenNode.m */; }; + D36934721038E28300527AF3 /* PKParseTree.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934561038DE5300527AF3 /* PKParseTree.m */; }; + D36934731038E28700527AF3 /* PKParseTreeAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */; }; + D36934741038E28B00527AF3 /* PKRuleNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345A1038DE5300527AF3 /* PKRuleNode.m */; }; + D36934751038E28F00527AF3 /* PKTokenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D369345C1038DE5300527AF3 /* PKTokenNode.m */; }; + D36C53790FD27F1300141CB7 /* TDParserFactoryTest2.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C53780FD27F1300141CB7 /* TDParserFactoryTest2.m */; }; + D36C55FF0FD3617B00141CB7 /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */; }; + D36C560C0FD363D500141CB7 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D36C560B0FD363D500141CB7 /* libicucore.dylib */; }; + D36C562B0FD365DB00141CB7 /* TDPatternTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C562A0FD365DB00141CB7 /* TDPatternTest.m */; }; + D36E95460E578ECC00496BD3 /* XPathParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E95450E578ECC00496BD3 /* XPathParser.m */; }; + D36E95D80E57B08400496BD3 /* XPathParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E95D70E57B08400496BD3 /* XPathParserTest.m */; }; + D36E97B00E589DAE00496BD3 /* XPathAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */; }; + D36E98220E58A3A800496BD3 /* XPathContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98210E58A3A800496BD3 /* XPathContext.m */; }; + D36E98E00E58C12800496BD3 /* DebugAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98DD0E58C12800496BD3 /* DebugAppDelegate.m */; }; + D36E98E10E58C12800496BD3 /* DebugAppMainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D36E98DE0E58C12800496BD3 /* DebugAppMainMenu.xib */; }; + D36E98E20E58C12800496BD3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98DF0E58C12800496BD3 /* main.m */; }; + D36E98E70E58C14000496BD3 /* DemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98E40E58C14000496BD3 /* DemoAppDelegate.m */; }; + D36E98E80E58C14000496BD3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D36E98E50E58C14000496BD3 /* main.m */; }; + D36E98F80E58C1A000496BD3 /* DemoAppMainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D36E98F70E58C1A000496BD3 /* DemoAppMainMenu.xib */; }; + D36E9F870E5A795400496BD3 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D36E9F860E5A795400496BD3 /* libxml2.dylib */; }; + D36E9FB50E5A944A00496BD3 /* apple-boss.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36E9FB40E5A944A00496BD3 /* apple-boss.xml */; }; + D36E9FE50E5BA0FC00496BD3 /* SRGSGrammar.txt in Resources */ = {isa = PBXBuildFile; fileRef = D36E9FE40E5BA0FC00496BD3 /* SRGSGrammar.txt */; }; + D36EA3B00E5EA67E00496BD3 /* small-xml-file.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */; }; + D37A28671013942300E936B7 /* PKGrammarParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3376D5810093A1600E4602E /* PKGrammarParser.m */; }; + D37A28681013942A00E936B7 /* PKGrammarParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3376D5710093A1600E4602E /* PKGrammarParser.h */; }; + D37D3A000FE77A71008C2E4D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D37D3A010FE77A72008C2E4D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D37D3A020FE77A77008C2E4D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; + D380AFBD0F0C54B60009EC13 /* html.css in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBB0F0C54B60009EC13 /* html.css */; }; + D380AFBE0F0C54B60009EC13 /* html.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBC0F0C54B60009EC13 /* html.grammar */; }; + D380AFBF0F0C54B60009EC13 /* html.css in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBB0F0C54B60009EC13 /* html.css */; }; + D380AFC00F0C54B60009EC13 /* html.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380AFBC0F0C54B60009EC13 /* html.grammar */; }; + D380AFC30F0C56000009EC13 /* example.html in Resources */ = {isa = PBXBuildFile; fileRef = D380AFC20F0C56000009EC13 /* example.html */; }; + D380AFC40F0C56000009EC13 /* example.html in Resources */ = {isa = PBXBuildFile; fileRef = D380AFC20F0C56000009EC13 /* example.html */; }; + D380B3230F0CC0800009EC13 /* nyt.html in Resources */ = {isa = PBXBuildFile; fileRef = D38DD9E70EC29F260070BC4D /* nyt.html */; }; + D380B5090F0D71A90009EC13 /* css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380B5080F0D71A90009EC13 /* css.grammar */; }; + D380B50A0F0D71B00009EC13 /* css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D380B5080F0D71A90009EC13 /* css.grammar */; }; + D380B5380F0D7DDE0009EC13 /* css.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5370F0D7DDE0009EC13 /* css.css */; }; + D380B5390F0D7DE30009EC13 /* css.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5370F0D7DDE0009EC13 /* css.css */; }; + D380B5940F0D82F60009EC13 /* example.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5930F0D82F60009EC13 /* example.css */; }; + D380B5950F0D82F90009EC13 /* example.css in Resources */ = {isa = PBXBuildFile; fileRef = D380B5930F0D82F60009EC13 /* example.css */; }; + D380B9800F0EF3860009EC13 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D380BA620F0F06CD0009EC13 /* TDParserFactoryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D380BA600F0F06CD0009EC13 /* TDParserFactoryTest.m */; }; + D380BAA30F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D380BAA40F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D38205BE0EEE48EE004340DD /* TDTokenTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D38205BD0EEE48EE004340DD /* TDTokenTest.m */; }; + D383498B0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */; }; + D383498C0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */; }; + D38349BC0F0C0D910055E4E0 /* json_with_comments.css in Resources */ = {isa = PBXBuildFile; fileRef = D38349BB0F0C0D910055E4E0 /* json_with_comments.css */; }; + D38349BD0F0C0D910055E4E0 /* json_with_comments.css in Resources */ = {isa = PBXBuildFile; fileRef = D38349BB0F0C0D910055E4E0 /* json_with_comments.css */; }; + D3834A480F0C14B60055E4E0 /* yahoo_with_comments.json in Resources */ = {isa = PBXBuildFile; fileRef = D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */; }; + D3834A490F0C14C00055E4E0 /* yahoo_with_comments.json in Resources */ = {isa = PBXBuildFile; fileRef = D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */; }; + D385F98C0F046FE900DB2946 /* TDGenericAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385F9890F046FE900DB2946 /* TDGenericAssembler.m */; }; + D385F98E0F046FE900DB2946 /* TDGenericAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385F9890F046FE900DB2946 /* TDGenericAssembler.m */; }; + D385FA230F04971400DB2946 /* TDGenericAssemblerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FA220F04971400DB2946 /* TDGenericAssemblerTest.m */; }; + D385FA250F04993500DB2946 /* json.css in Resources */ = {isa = PBXBuildFile; fileRef = D385FA240F04993500DB2946 /* json.css */; }; + D385FA260F04993500DB2946 /* json.css in Resources */ = {isa = PBXBuildFile; fileRef = D385FA240F04993500DB2946 /* json.css */; }; + D385FD440F05A88C00DB2946 /* TDMiniCSSAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */; }; + D385FD460F05A89100DB2946 /* TDMiniCSSAssemblerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FD430F05A88C00DB2946 /* TDMiniCSSAssemblerTest.m */; }; + D385FD490F05A8C900DB2946 /* TDMiniCSSAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */; }; + D385FD6C0F05A99900DB2946 /* mini_css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D385FD6B0F05A99900DB2946 /* mini_css.grammar */; }; + D385FD6D0F05A99900DB2946 /* mini_css.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D385FD6B0F05A99900DB2946 /* mini_css.grammar */; }; + D389F1D50F19666500558235 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D389F20B0F196A9200558235 /* JSParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D389F1CE0F1965E600558235 /* JSParseKit.framework */; }; + D389F20C0F196A9200558235 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D389F20E0F196A9200558235 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D389F20D0F196A9200558235 /* WebKit.framework */; }; + D389F2E40F196CAE00558235 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F2E30F196CAE00558235 /* main.m */; }; + D389F3430F197DDC00558235 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D389F34E0F197DF500558235 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */; }; + D389F37A0F197E8000558235 /* JSDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F2E90F196F5B00558235 /* JSDemoAppDelegate.m */; }; + D389F38F0F19800400558235 /* DefaultValues.plist in Resources */ = {isa = PBXBuildFile; fileRef = D389F38E0F19800400558235 /* DefaultValues.plist */; }; + D389F4620F198A8800558235 /* Test.html in Resources */ = {isa = PBXBuildFile; fileRef = D389F4610F198A8800558235 /* Test.html */; }; + D389F5590F19B7BC00558235 /* JSDemoAppMainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D389F5580F19B7BC00558235 /* JSDemoAppMainMenu.xib */; }; + D389F5B60F19C76A00558235 /* TDJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F5B30F19C76A00558235 /* TDJsonParser.m */; }; + D389F5B70F19C76A00558235 /* TDJsonParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F5B50F19C76A00558235 /* TDJsonParserTest.m */; }; + D389F5B80F19C76A00558235 /* TDJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D389F5B30F19C76A00558235 /* TDJsonParser.m */; }; + D389FBCD0F1B25E200558235 /* ParserTest.html in Resources */ = {isa = PBXBuildFile; fileRef = D389FBCC0F1B25E200558235 /* ParserTest.html */; }; + D38DD9E80EC29F260070BC4D /* nyt.html in Resources */ = {isa = PBXBuildFile; fileRef = D38DD9E70EC29F260070BC4D /* nyt.html */; }; + D38E97CC1061CF6500739C39 /* TDTokenizerBlocksTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D38E97CB1061CF6500739C39 /* TDTokenizerBlocksTest.m */; }; + D38E98D81062C5BA00739C39 /* TDParserBlocksTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D38E98D71062C5BA00739C39 /* TDParserBlocksTest.m */; }; + D398E20E0E60F86D00A1C877 /* yahoo.json in Resources */ = {isa = PBXBuildFile; fileRef = D3B473840E48C9CF008AFBDD /* yahoo.json */; }; + D39E01340FEF02DA00150FC3 /* TDXMLParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3BBBC970FEC9722007DF30D /* TDXMLParserTest.m */; }; + D3AF49780FDB122E0032F4DC /* TDParserFactoryPatternTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3AF49770FDB122E0032F4DC /* TDParserFactoryPatternTest.m */; }; + D3B43FB80F76E99C0072AF40 /* TDJavaScriptParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3B43FB60F76E99C0072AF40 /* TDJavaScriptParserTest.m */; }; + D3B473850E48C9CF008AFBDD /* yahoo.json in Resources */ = {isa = PBXBuildFile; fileRef = D3B473840E48C9CF008AFBDD /* yahoo.json */; }; + D3B69D320E80249900D70C41 /* nonascii.html in Resources */ = {isa = PBXBuildFile; fileRef = D3B69D310E80249900D70C41 /* nonascii.html */; }; + D3B69D330E80249900D70C41 /* nonascii.html in Resources */ = {isa = PBXBuildFile; fileRef = D3B69D310E80249900D70C41 /* nonascii.html */; }; + D3BBBC9D0FEC9756007DF30D /* TDXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */; }; + D3BBBC9E0FEC9756007DF30D /* TDXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */; }; + D3BBBCC10FECD477007DF30D /* xml.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D355C8800FEB36A1006A91A4 /* xml.grammar */; }; + D3C031ED0EF38D2D00C5ABEB /* TDLowercaseWordTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C031EC0EF38D2D00C5ABEB /* TDLowercaseWordTest.m */; }; + D3C221920FFE8B8C004514FE /* ParseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221900FFE8B8C004514FE /* ParseKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221930FFE8B8C004514FE /* PKTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221910FFE8B8C004514FE /* PKTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221940FFE8B8C004514FE /* ParseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221900FFE8B8C004514FE /* ParseKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221950FFE8B8C004514FE /* PKTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221910FFE8B8C004514FE /* PKTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221970FFE8B95004514FE /* PKReader.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221960FFE8B95004514FE /* PKReader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221980FFE8B95004514FE /* PKReader.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221960FFE8B95004514FE /* PKReader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219A0FFE8B9D004514FE /* PKAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221990FFE8B9D004514FE /* PKAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219B0FFE8B9D004514FE /* PKAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221990FFE8B9D004514FE /* PKAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219D0FFE8BA6004514FE /* PKParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219C0FFE8BA6004514FE /* PKParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2219E0FFE8BA6004514FE /* PKParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219C0FFE8BA6004514FE /* PKParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A00FFE8BAE004514FE /* PKRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219F0FFE8BAE004514FE /* PKRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A10FFE8BAE004514FE /* PKRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2219F0FFE8BAE004514FE /* PKRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A30FFE8BBA004514FE /* PKCollectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A40FFE8BBA004514FE /* PKCollectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A60FFE8BC1004514FE /* PKAlternation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A50FFE8BC1004514FE /* PKAlternation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A70FFE8BC1004514FE /* PKAlternation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A50FFE8BC1004514FE /* PKAlternation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221A90FFE8BC9004514FE /* PKSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A80FFE8BC9004514FE /* PKSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AA0FFE8BC9004514FE /* PKSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221A80FFE8BC9004514FE /* PKSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AC0FFE8BCF004514FE /* PKTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AB0FFE8BCF004514FE /* PKTrack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AD0FFE8BCF004514FE /* PKTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AB0FFE8BCF004514FE /* PKTrack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221AF0FFE8BD4004514FE /* PKTrackException.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AE0FFE8BD4004514FE /* PKTrackException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B00FFE8BD4004514FE /* PKTrackException.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221AE0FFE8BD4004514FE /* PKTrackException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B20FFE8BDB004514FE /* PKIntersection.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B10FFE8BDB004514FE /* PKIntersection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B30FFE8BDB004514FE /* PKIntersection.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B10FFE8BDB004514FE /* PKIntersection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B50FFE8BE2004514FE /* PKDifference.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B40FFE8BE2004514FE /* PKDifference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B60FFE8BE2004514FE /* PKDifference.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B40FFE8BE2004514FE /* PKDifference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B80FFE8BE8004514FE /* PKNegation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B70FFE8BE8004514FE /* PKNegation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221B90FFE8BE8004514FE /* PKNegation.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221B70FFE8BE8004514FE /* PKNegation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BB0FFE8BEF004514FE /* PKTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BA0FFE8BEF004514FE /* PKTerminal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BC0FFE8BEF004514FE /* PKTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BA0FFE8BEF004514FE /* PKTerminal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BE0FFE8BF7004514FE /* PKEmpty.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BD0FFE8BF7004514FE /* PKEmpty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221BF0FFE8BF7004514FE /* PKEmpty.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221BD0FFE8BF7004514FE /* PKEmpty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C10FFE8BFF004514FE /* PKTokenAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C20FFE8BFF004514FE /* PKTokenAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C40FFE8C07004514FE /* PKToken.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C30FFE8C07004514FE /* PKToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C50FFE8C07004514FE /* PKToken.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C30FFE8C07004514FE /* PKToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C70FFE8C0D004514FE /* PKTokenArraySource.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221C80FFE8C0D004514FE /* PKTokenArraySource.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CA0FFE8C15004514FE /* PKTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C90FFE8C15004514FE /* PKTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CB0FFE8C15004514FE /* PKTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221C90FFE8C15004514FE /* PKTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CD0FFE8C1B004514FE /* PKTokenizerState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221CE0FFE8C1B004514FE /* PKTokenizerState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D00FFE8C24004514FE /* PKNumberState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CF0FFE8C24004514FE /* PKNumberState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D10FFE8C24004514FE /* PKNumberState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221CF0FFE8C24004514FE /* PKNumberState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D60FFE8C35004514FE /* PKSymbolState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D50FFE8C35004514FE /* PKSymbolState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D70FFE8C35004514FE /* PKSymbolState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D50FFE8C35004514FE /* PKSymbolState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221D90FFE8C3D004514FE /* PKWordState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D80FFE8C3D004514FE /* PKWordState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DA0FFE8C3D004514FE /* PKWordState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221D80FFE8C3D004514FE /* PKWordState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DC0FFE8C43004514FE /* PKWhitespaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DD0FFE8C43004514FE /* PKWhitespaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221DF0FFE8C49004514FE /* PKDelimitState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DE0FFE8C49004514FE /* PKDelimitState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E00FFE8C49004514FE /* PKDelimitState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221DE0FFE8C49004514FE /* PKDelimitState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E20FFE8C4E004514FE /* PKCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E10FFE8C4E004514FE /* PKCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E30FFE8C4E004514FE /* PKCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E10FFE8C4E004514FE /* PKCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E50FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E60FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E80FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221E90FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EB0FFE8C69004514FE /* PKSymbolNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EC0FFE8C69004514FE /* PKSymbolNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EE0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221EF0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F10FFE8C7A004514FE /* PKPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F00FFE8C7A004514FE /* PKPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F20FFE8C7A004514FE /* PKPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F00FFE8C7A004514FE /* PKPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F40FFE8C87004514FE /* PKWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F30FFE8C87004514FE /* PKWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F50FFE8C87004514FE /* PKWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F30FFE8C87004514FE /* PKWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221F70FFE8C8E004514FE /* PKNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F60FFE8C8E004514FE /* PKNumber.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FA0FFE8C97004514FE /* PKQuotedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F90FFE8C97004514FE /* PKQuotedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FB0FFE8C97004514FE /* PKQuotedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F90FFE8C97004514FE /* PKQuotedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FD0FFE8CB2004514FE /* PKSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FC0FFE8CB2004514FE /* PKSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C221FE0FFE8CB2004514FE /* PKSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FC0FFE8CB2004514FE /* PKSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222000FFE8CB9004514FE /* PKLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FF0FFE8CB9004514FE /* PKLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222010FFE8CB9004514FE /* PKLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221FF0FFE8CB9004514FE /* PKLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222030FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222040FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222060FFE8CCA004514FE /* PKWhitespace.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222050FFE8CCA004514FE /* PKWhitespace.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222070FFE8CCA004514FE /* PKWhitespace.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222050FFE8CCA004514FE /* PKWhitespace.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222090FFE8CD1004514FE /* PKComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222080FFE8CD1004514FE /* PKComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220A0FFE8CD1004514FE /* PKComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222080FFE8CD1004514FE /* PKComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220C0FFE8CD8004514FE /* PKDelimitedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220D0FFE8CD8004514FE /* PKDelimitedString.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2220F0FFE8CDF004514FE /* PKAny.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220E0FFE8CDF004514FE /* PKAny.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222100FFE8CDF004514FE /* PKAny.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2220E0FFE8CDF004514FE /* PKAny.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222150FFE8D01004514FE /* PKLowercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222140FFE8D01004514FE /* PKLowercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222160FFE8D01004514FE /* PKLowercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222140FFE8D01004514FE /* PKLowercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222180FFE8D11004514FE /* PKUppercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222170FFE8D11004514FE /* PKUppercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222190FFE8D11004514FE /* PKUppercaseWord.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222170FFE8D11004514FE /* PKUppercaseWord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221B0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221C0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221E0FFE8D3B004514FE /* PKChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221D0FFE8D3B004514FE /* PKChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2221F0FFE8D3B004514FE /* PKChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C2221D0FFE8D3B004514FE /* PKChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222210FFE8D42004514FE /* PKDigit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222200FFE8D42004514FE /* PKDigit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222220FFE8D42004514FE /* PKDigit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222200FFE8D42004514FE /* PKDigit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222240FFE8D49004514FE /* PKLetter.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222230FFE8D49004514FE /* PKLetter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222250FFE8D49004514FE /* PKLetter.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222230FFE8D49004514FE /* PKLetter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222270FFE8D6B004514FE /* PKSpecificChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222260FFE8D6B004514FE /* PKSpecificChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C222280FFE8D6B004514FE /* PKSpecificChar.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222260FFE8D6B004514FE /* PKSpecificChar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2222A0FFE8DAC004514FE /* PKParserFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222290FFE8DAC004514FE /* PKParserFactory.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2222B0FFE8DAC004514FE /* PKParserFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C222290FFE8DAC004514FE /* PKParserFactory.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3C2222D0FFE8DE9004514FE /* NSArray+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */; }; + D3C2222E0FFE8DEE004514FE /* NSString+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */; }; + D3C2222F0FFE8DEF004514FE /* NSString+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */; }; + D3C222300FFE8DF3004514FE /* NSArray+ParseKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */; }; + D3C7D9DA0A412874005DD154 /* ParseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; }; + D3C85C7B0E63B438000445FD /* TDArithmeticParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C85C7A0E63B438000445FD /* TDArithmeticParser.m */; }; + D3C85C800E63B9E9000445FD /* TDArithmeticParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C85C7F0E63B9E9000445FD /* TDArithmeticParserTest.m */; }; + D3C85D450E63D1BF000445FD /* TDScientificNumberStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C85D440E63D1BF000445FD /* TDScientificNumberStateTest.m */; }; + D3D01CAA0EFDB89900C24DDE /* json_with_discards.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */; }; + D3D01CAB0EFDB8A000C24DDE /* json_with_discards.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */; }; + D3D01CAC0EFDB8A100C24DDE /* json_with_discards.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */; }; + D3D1BF2810394420003656E5 /* SAXAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D1BF2710394420003656E5 /* SAXAssembler.m */; }; + D3D1BF2B1039445C003656E5 /* SAXTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D1BF2A1039445C003656E5 /* SAXTest.m */; }; + D3DCB3730EF5E5D600DE5110 /* OCMock.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D3DCB37D0EF5E5E400DE5110 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D3DCB4C30EF6015300DE5110 /* json.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3DCB4C20EF6015300DE5110 /* json.grammar */; }; + D3DCB4C40EF6015C00DE5110 /* json.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3DCB4C20EF6015300DE5110 /* json.grammar */; }; + D3DCB4C50EF6015C00DE5110 /* json.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3DCB4C20EF6015300DE5110 /* json.grammar */; }; + D3DDDA870F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */; }; + D3DDDA880F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */; }; + D3DDDAFE0F083C9700A58000 /* TDCommentStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3DDDAFD0F083C9700A58000 /* TDCommentStateTest.m */; }; + D3DDDCAD0F0880D800A58000 /* example1.srgs in Resources */ = {isa = PBXBuildFile; fileRef = D3DDDCAC0F0880D800A58000 /* example1.srgs */; }; + D3DDDCAE0F0880D800A58000 /* example1.srgs in Resources */ = {isa = PBXBuildFile; fileRef = D3DDDCAC0F0880D800A58000 /* example1.srgs */; }; + D3E27A320E741DD20078CC2C /* small-xml-file.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */; }; + D3E27A330E741DD20078CC2C /* apple-boss.xml in Resources */ = {isa = PBXBuildFile; fileRef = D36E9FB40E5A944A00496BD3 /* apple-boss.xml */; }; + D3E39C3F0FC5FFD10022DAB9 /* TDDelimitStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E39C3E0FC5FFD10022DAB9 /* TDDelimitStateTest.m */; }; + D3E784BD0E53DA28008C7D61 /* apple-boss.json in Resources */ = {isa = PBXBuildFile; fileRef = D3E784BC0E53DA28008C7D61 /* apple-boss.json */; }; + D3E785560E53FB54008C7D61 /* apple-boss.json in Resources */ = {isa = PBXBuildFile; fileRef = D3E784BC0E53DA28008C7D61 /* apple-boss.json */; }; + D3E787A30E5661A9008C7D61 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; + D3E788930E567DFD008C7D61 /* SRGSParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E788920E567DFD008C7D61 /* SRGSParserTest.m */; }; + D3E788960E567E0A008C7D61 /* SRGSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E788950E567E0A008C7D61 /* SRGSParser.m */; }; + D3E78A190E574C99008C7D61 /* EBNFParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E78A160E574C99008C7D61 /* EBNFParser.m */; }; + D3E78A1A0E574C99008C7D61 /* EBNFParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E78A180E574C99008C7D61 /* EBNFParserTest.m */; }; + D3EAC7EC0F2690620043D6A9 /* OCMock.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D3DCB35C0EF5E52500DE5110 /* OCMock.framework */; }; + D3EADD800E75E9CC00F78584 /* nasty.html in Resources */ = {isa = PBXBuildFile; fileRef = D3EADD7F0E75E9CC00F78584 /* nasty.html */; }; + D3EADD810E75E9CC00F78584 /* nasty.html in Resources */ = {isa = PBXBuildFile; fileRef = D3EADD7F0E75E9CC00F78584 /* nasty.html */; }; + D3EADD8E0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */; }; + D3EADD8F0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */; }; + D3F0E2480FFE8EB900C9DF74 /* PKQuoteState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3F0E2490FFE8EB900C9DF74 /* PKQuoteState.h in Headers */ = {isa = PBXBuildFile; fileRef = D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3F0E3CB0FFEB70100C9DF74 /* PKNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C221F60FFE8C8E004514FE /* PKNumber.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D3F0E3CC0FFEB70700C9DF74 /* PKNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF440FF9E19700D7773A /* PKNumber.m */; }; + D3F55F611025737D00DD6DB1 /* TDParseTreeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F55F601025737D00DD6DB1 /* TDParseTreeTest.m */; }; + D3F5629A10266CFC00DD6DB1 /* PKParseTreeView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F5629910266CFC00DD6DB1 /* PKParseTreeView.m */; }; + D3F562A010266DFB00DD6DB1 /* DemoTokensViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F5629F10266DFB00DD6DB1 /* DemoTokensViewController.m */; }; + D3F562A210266E5300DD6DB1 /* TokensView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3F562A110266E5300DD6DB1 /* TokensView.xib */; }; + D3F562A410266E6300DD6DB1 /* TreesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3F562A310266E6300DD6DB1 /* TreesView.xib */; }; + D3F562A710266E8D00DD6DB1 /* DemoTreesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F562A610266E8D00DD6DB1 /* DemoTreesViewController.m */; }; + D3F740B70EF8C38A00559B9F /* JSONAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = D3F740B60EF8C38A00559B9F /* JSONAssembler.m */; }; + D3F741440EF8E96A00559B9F /* xpath1_0.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741430EF8E96A00559B9F /* xpath1_0.grammar */; }; + D3F741BE0EF9F28D00559B9F /* css2_1.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741BD0EF9F28D00559B9F /* css2_1.grammar */; }; + D3F741BF0EF9F29400559B9F /* css2_1.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741BD0EF9F28D00559B9F /* css2_1.grammar */; }; + D3F741C00EF9F29500559B9F /* css2_1.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3F741BD0EF9F28D00559B9F /* css2_1.grammar */; }; + D3FD79200F4CC86800BAD816 /* rubyhash.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */; }; + D3FD79210F4CC87900BAD816 /* rubyhash.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */; }; + D3FDC4A50FFB3B2A00F1F797 /* RegexKitLite.h in Headers */ = {isa = PBXBuildFile; fileRef = D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */; }; + D3FDC6DA0FFC4C8C00F1F797 /* RegexKitLite.h in Headers */ = {isa = PBXBuildFile; fileRef = D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */; }; + D3FDC6EE0FFC4C9E00F1F797 /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */; }; + D3FDC6EF0FFC4C9E00F1F797 /* PKReader.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAD9B0FF9C95800D7773A /* PKReader.m */; }; + D3FDC6F00FFC4C9E00F1F797 /* PKAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADA00FF9C9B000D7773A /* PKAssembly.m */; }; + D3FDC6F10FFC4C9E00F1F797 /* PKParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BADD60FF9CBFB00D7773A /* PKParser.m */; }; + D3FDC6F20FFC4C9E00F1F797 /* PKRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE130FF9CE0E00D7773A /* PKRepetition.m */; }; + D3FDC6F30FFC4C9E00F1F797 /* PKCollectionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */; }; + D3FDC6F40FFC4C9E00F1F797 /* PKAlternation.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */; }; + D3FDC6F50FFC4C9E00F1F797 /* PKSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE150FF9CE0E00D7773A /* PKSequence.m */; }; + D3FDC6F60FFC4C9E00F1F797 /* PKTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE190FF9CE0E00D7773A /* PKTrack.m */; }; + D3FDC6F70FFC4C9E00F1F797 /* PKTrackException.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */; }; + D3FDC6F80FFC4C9E00F1F797 /* PKDifference.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */; }; + D3FDC6F90FFC4C9E00F1F797 /* PKIntersection.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE110FF9CE0E00D7773A /* PKIntersection.m */; }; + D3FDC6FA0FFC4C9E00F1F797 /* PKTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE170FF9CE0E00D7773A /* PKTerminal.m */; }; + D3FDC6FB0FFC4C9E00F1F797 /* PKEmpty.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */; }; + D3FDC6FC0FFC4C9E00F1F797 /* PKTokenAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */; }; + D3FDC6FD0FFC4C9E00F1F797 /* PKToken.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE950FF9D20900D7773A /* PKToken.m */; }; + D3FDC6FE0FFC4C9E00F1F797 /* PKTokenArraySource.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */; }; + D3FDC6FF0FFC4C9E00F1F797 /* PKTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE990FF9D20900D7773A /* PKTokenizer.m */; }; + D3FDC7000FFC4C9E00F1F797 /* PKTokenizerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */; }; + D3FDC7010FFC4C9E00F1F797 /* PKNumberState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECA0FF9D56400D7773A /* PKNumberState.m */; }; + D3FDC7020FFC4C9E00F1F797 /* PKQuoteState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECC0FF9D56400D7773A /* PKQuoteState.m */; }; + D3FDC7030FFC4C9E00F1F797 /* PKSymbolState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED00FF9D56400D7773A /* PKSymbolState.m */; }; + D3FDC7040FFC4C9E00F1F797 /* PKWordState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED60FF9D56400D7773A /* PKWordState.m */; }; + D3FDC7050FFC4C9E00F1F797 /* PKWhitespaceState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */; }; + D3FDC7060FFC4C9E00F1F797 /* PKDelimitState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC60FF9D56400D7773A /* PKDelimitState.m */; }; + D3FDC7070FFC4C9E00F1F797 /* PKCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC40FF9D56400D7773A /* PKCommentState.m */; }; + D3FDC7080FFC4C9E00F1F797 /* PKSingleLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */; }; + D3FDC7090FFC4C9E00F1F797 /* PKMultiLineCommentState.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */; }; + D3FDC70A0FFC4C9E00F1F797 /* PKSymbolNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */; }; + D3FDC70B0FFC4C9E00F1F797 /* PKSymbolRootNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */; }; + D3FDC70C0FFC4C9E00F1F797 /* PKPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF380FF9E18300D7773A /* PKPattern.m */; }; + D3FDC70D0FFC4C9E00F1F797 /* PKWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAED40FF9D56400D7773A /* PKWord.m */; }; + D3FDC70F0FFC4C9E00F1F797 /* PKQuotedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF460FF9E19700D7773A /* PKQuotedString.m */; }; + D3FDC7100FFC4C9E00F1F797 /* PKSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF480FF9E19700D7773A /* PKSymbol.m */; }; + D3FDC7110FFC4C9E00F1F797 /* PKLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF420FF9E19700D7773A /* PKLiteral.m */; }; + D3FDC7120FFC4C9E00F1F797 /* PKCaseInsensitiveLiteral.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */; }; + D3FDC7130FFC4C9E00F1F797 /* PKWhitespace.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */; }; + D3FDC7140FFC4C9E00F1F797 /* PKComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF3E0FF9E19700D7773A /* PKComment.m */; }; + D3FDC7150FFC4C9E00F1F797 /* PKDelimitedString.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF400FF9E19700D7773A /* PKDelimitedString.m */; }; + D3FDC7160FFC4C9E00F1F797 /* PKAny.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAE2F0FF9CE6000D7773A /* PKAny.m */; }; + D3FDC7180FFC4C9E00F1F797 /* PKLowercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */; }; + D3FDC7190FFC4C9E00F1F797 /* PKUppercaseWord.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */; }; + D3FDC71A0FFC4C9E00F1F797 /* PKCharacterAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */; }; + D3FDC71B0FFC4C9E00F1F797 /* PKChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB40FF9E80300D7773A /* PKChar.m */; }; + D3FDC71C0FFC4C9E00F1F797 /* PKDigit.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB60FF9E80300D7773A /* PKDigit.m */; }; + D3FDC71D0FFC4C9E00F1F797 /* PKLetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFB80FF9E80300D7773A /* PKLetter.m */; }; + D3FDC71E0FFC4C9E00F1F797 /* PKSpecificChar.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */; }; + D3FDC71F0FFC4C9E00F1F797 /* PKParserFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD80FF9E95500D7773A /* PKParserFactory.m */; }; + D3FDC7200FFC4C9E00F1F797 /* NSArray+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */; }; + D3FDC7210FFC4C9E00F1F797 /* NSString+ParseKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */; }; + D3FDC7370FFC4D6100F1F797 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3FDC7360FFC4D6100F1F797 /* Foundation.framework */; }; + D3FDC7390FFC4D6100F1F797 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D3FDC7380FFC4D6100F1F797 /* libicucore.dylib */; }; + D3FDC74C0FFC4DAC00F1F797 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3FDC74B0FFC4DAC00F1F797 /* CoreGraphics.framework */; }; + D3FDC8DC0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = D3FDC8DB0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + D31FE7170E60F24700A0803E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TDParseKit; + }; + D334949F0E296AA900406085 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TODParseKit; + }; + D341850F0E520D6F0081B0DC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TODParseKit; + }; + D389F1D30F19665C00558235 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DC2EF4F0486A6940098B216; + remoteInfo = TDParseKit; + }; + D389F2090F196A8000558235 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D389F1CD0F1965E600558235; + remoteInfo = TDJSParseKit; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + D380B9A10F0EF3DC0009EC13 /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(BUILT_PRODUCTS_DIR)"; + dstSubfolderSpec = 0; + files = ( + D3EAC7EC0F2690620043D6A9 /* OCMock.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + D3DCB3880EF5E65100DE5110 /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(BUILT_PRODUCTS_DIR)"; + dstSubfolderSpec = 0; + files = ( + D3DCB3730EF5E5D600DE5110 /* OCMock.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 8DC2EF5B0486A6940098B216 /* ParseKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ParseKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D3126D040FFD9BA700CBF4C4 /* PKNegation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKNegation.m; path = src/PKNegation.m; sourceTree = ""; }; + D3126D090FFD9E4B00CBF4C4 /* TDNegationTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNegationTest.h; path = test/TDNegationTest.h; sourceTree = ""; }; + D3126D0A0FFD9E4B00CBF4C4 /* TDNegationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNegationTest.m; path = test/TDNegationTest.m; sourceTree = ""; }; + D3126D410FFDB4C600CBF4C4 /* TDExclusionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDExclusionTest.h; path = test/TDExclusionTest.h; sourceTree = ""; }; + D3126D420FFDB4C600CBF4C4 /* TDExclusionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDExclusionTest.m; path = test/TDExclusionTest.m; sourceTree = ""; }; + D31270F80FFE898300CBF4C4 /* PKExclusion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKExclusion.m; path = test/PKExclusion.m; sourceTree = ""; }; + D315DF710FEF59B600D876C8 /* date.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = date.grammar; path = res/date.grammar; sourceTree = ""; }; + D319E429106D8A1F008C63DD /* arithmetic.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = arithmetic.grammar; path = res/arithmetic.grammar; sourceTree = ""; }; + D319E42C106D8A31008C63DD /* TDArithmeticAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDArithmeticAssembler.h; path = test/TDArithmeticAssembler.h; sourceTree = ""; }; + D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDArithmeticAssembler.m; path = test/TDArithmeticAssembler.m; sourceTree = ""; }; + D31A15250F6DE449002AFDF1 /* javascript.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = javascript.grammar; path = res/javascript.grammar; sourceTree = ""; }; + D31A16500F7038C2002AFDF1 /* TDJavaScriptParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJavaScriptParser.h; path = test/TDJavaScriptParser.h; sourceTree = ""; }; + D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJavaScriptParser.m; path = test/TDJavaScriptParser.m; sourceTree = ""; }; + D31FE54A0E60E46100A0803E /* TDTestScaffold.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTestScaffold.h; path = test/TDTestScaffold.h; sourceTree = ""; }; + D31FE54B0E60E46100A0803E /* TDTestScaffold.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTestScaffold.m; path = test/TDTestScaffold.m; sourceTree = ""; }; + D31FE54D0E60E50800A0803E /* TDAlternationTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDAlternationTest.h; path = test/TDAlternationTest.h; sourceTree = ""; }; + D31FE54E0E60E50800A0803E /* TDAlternationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDAlternationTest.m; path = test/TDAlternationTest.m; sourceTree = ""; }; + D31FE54F0E60E50800A0803E /* TDLiteralTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDLiteralTest.h; path = test/TDLiteralTest.h; sourceTree = ""; }; + D31FE5500E60E50800A0803E /* TDLiteralTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDLiteralTest.m; path = test/TDLiteralTest.m; sourceTree = ""; }; + D31FE5510E60E50800A0803E /* TDParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserTest.h; path = test/TDParserTest.h; sourceTree = ""; }; + D31FE5520E60E50800A0803E /* TDParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserTest.m; path = test/TDParserTest.m; sourceTree = ""; }; + D31FE5530E60E50800A0803E /* TDRepetitionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRepetitionTest.h; path = test/TDRepetitionTest.h; sourceTree = ""; }; + D31FE5540E60E50800A0803E /* TDRepetitionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRepetitionTest.m; path = test/TDRepetitionTest.m; sourceTree = ""; }; + D31FE5550E60E50800A0803E /* TDReservedWordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDReservedWordTest.h; path = test/TDReservedWordTest.h; sourceTree = ""; }; + D31FE5560E60E50800A0803E /* TDReservedWordTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDReservedWordTest.m; path = test/TDReservedWordTest.m; sourceTree = ""; }; + D31FE5570E60E50800A0803E /* TDRobotCommandTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRobotCommandTest.h; path = test/TDRobotCommandTest.h; sourceTree = ""; }; + D31FE5580E60E50800A0803E /* TDRobotCommandTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRobotCommandTest.m; path = test/TDRobotCommandTest.m; sourceTree = ""; }; + D31FE5590E60E50800A0803E /* TDSequenceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSequenceTest.h; path = test/TDSequenceTest.h; sourceTree = ""; }; + D31FE55A0E60E50800A0803E /* TDSequenceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSequenceTest.m; path = test/TDSequenceTest.m; sourceTree = ""; }; + D31FE55B0E60E50800A0803E /* TDSymbolTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSymbolTest.h; path = test/TDSymbolTest.h; sourceTree = ""; }; + D31FE55C0E60E50800A0803E /* TDSymbolTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSymbolTest.m; path = test/TDSymbolTest.m; sourceTree = ""; }; + D31FE55D0E60E50800A0803E /* TDTokenAssemblyTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenAssemblyTest.h; path = test/TDTokenAssemblyTest.h; sourceTree = ""; }; + D31FE55E0E60E50800A0803E /* TDTokenAssemblyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenAssemblyTest.m; path = test/TDTokenAssemblyTest.m; sourceTree = ""; }; + D31FE55F0E60E50800A0803E /* TDTrackTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTrackTest.h; path = test/TDTrackTest.h; sourceTree = ""; }; + D31FE5600E60E50800A0803E /* TDTrackTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTrackTest.m; path = test/TDTrackTest.m; sourceTree = ""; }; + D31FE5610E60E50800A0803E /* TDUppercaseWordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDUppercaseWordTest.h; path = test/TDUppercaseWordTest.h; sourceTree = ""; }; + D31FE5620E60E50800A0803E /* TDUppercaseWordTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDUppercaseWordTest.m; path = test/TDUppercaseWordTest.m; sourceTree = ""; }; + D31FE5710E60E55700A0803E /* TDReaderTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDReaderTest.h; path = test/TDReaderTest.h; sourceTree = ""; }; + D31FE5720E60E55700A0803E /* TDReaderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDReaderTest.m; path = test/TDReaderTest.m; sourceTree = ""; }; + D31FE5730E60E55700A0803E /* TDTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenizerTest.h; path = test/TDTokenizerTest.h; sourceTree = ""; }; + D31FE5740E60E55700A0803E /* TDTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenizerTest.m; path = test/TDTokenizerTest.m; sourceTree = ""; }; + D31FE5770E60E58C00A0803E /* TDNumberStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNumberStateTest.h; path = test/TDNumberStateTest.h; sourceTree = ""; }; + D31FE5780E60E58C00A0803E /* TDNumberStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNumberStateTest.m; path = test/TDNumberStateTest.m; sourceTree = ""; }; + D31FE5790E60E58C00A0803E /* TDQuoteStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDQuoteStateTest.h; path = test/TDQuoteStateTest.h; sourceTree = ""; }; + D31FE57A0E60E58C00A0803E /* TDQuoteStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDQuoteStateTest.m; path = test/TDQuoteStateTest.m; sourceTree = ""; }; + D31FE57B0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSignificantWhitespaceStateTest.h; path = test/TDSignificantWhitespaceStateTest.h; sourceTree = ""; }; + D31FE57C0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSignificantWhitespaceStateTest.m; path = test/TDSignificantWhitespaceStateTest.m; sourceTree = ""; }; + D31FE57D0E60E58C00A0803E /* TDSlashStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashStateTest.h; path = test/TDSlashStateTest.h; sourceTree = ""; }; + D31FE57E0E60E58C00A0803E /* TDSlashStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashStateTest.m; path = test/TDSlashStateTest.m; sourceTree = ""; }; + D31FE57F0E60E58C00A0803E /* TDSymbolStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSymbolStateTest.h; path = test/TDSymbolStateTest.h; sourceTree = ""; }; + D31FE5800E60E58C00A0803E /* TDSymbolStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSymbolStateTest.m; path = test/TDSymbolStateTest.m; sourceTree = ""; }; + D31FE5810E60E58C00A0803E /* TDWhitespaceStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDWhitespaceStateTest.h; path = test/TDWhitespaceStateTest.h; sourceTree = ""; }; + D31FE5820E60E58C00A0803E /* TDWhitespaceStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDWhitespaceStateTest.m; path = test/TDWhitespaceStateTest.m; sourceTree = ""; }; + D31FE5830E60E58C00A0803E /* TDWordStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDWordStateTest.h; path = test/TDWordStateTest.h; sourceTree = ""; }; + D31FE5840E60E58C00A0803E /* TDWordStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDWordStateTest.m; path = test/TDWordStateTest.m; sourceTree = ""; }; + D31FE58C0E60E5AC00A0803E /* TDCharacterAssemblyTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDCharacterAssemblyTest.h; path = test/TDCharacterAssemblyTest.h; sourceTree = ""; }; + D31FE58D0E60E5AC00A0803E /* TDCharacterAssemblyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDCharacterAssemblyTest.m; path = test/TDCharacterAssemblyTest.m; sourceTree = ""; }; + D31FE58E0E60E5AC00A0803E /* TDCharTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDCharTest.h; path = test/TDCharTest.h; sourceTree = ""; }; + D31FE58F0E60E5AC00A0803E /* TDCharTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDCharTest.m; path = test/TDCharTest.m; sourceTree = ""; }; + D31FE5900E60E5AC00A0803E /* TDDigitTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDDigitTest.h; path = test/TDDigitTest.h; sourceTree = ""; }; + D31FE5910E60E5AC00A0803E /* TDDigitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDDigitTest.m; path = test/TDDigitTest.m; sourceTree = ""; }; + D31FE5920E60E5AC00A0803E /* TDLetterTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDLetterTest.h; path = test/TDLetterTest.h; sourceTree = ""; }; + D31FE5930E60E5AC00A0803E /* TDLetterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDLetterTest.m; path = test/TDLetterTest.m; sourceTree = ""; }; + D31FE5940E60E5AC00A0803E /* TDSpecificCharTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSpecificCharTest.h; path = test/TDSpecificCharTest.h; sourceTree = ""; }; + D31FE5950E60E5AC00A0803E /* TDSpecificCharTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSpecificCharTest.m; path = test/TDSpecificCharTest.m; sourceTree = ""; }; + D31FE59B0E60E5C000A0803E /* TDRegularParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRegularParser.h; path = test/TDRegularParser.h; sourceTree = ""; }; + D31FE59C0E60E5C000A0803E /* TDRegularParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRegularParser.m; path = test/TDRegularParser.m; sourceTree = ""; }; + D31FE59D0E60E5C000A0803E /* TDRegularParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDRegularParserTest.h; path = test/TDRegularParserTest.h; sourceTree = ""; }; + D31FE59E0E60E5C000A0803E /* TDRegularParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDRegularParserTest.m; path = test/TDRegularParserTest.m; sourceTree = ""; }; + D31FE5A10E60E5D500A0803E /* TDFastJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDFastJsonParser.h; path = test/TDFastJsonParser.h; sourceTree = ""; }; + D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDFastJsonParser.m; path = test/TDFastJsonParser.m; sourceTree = ""; }; + D31FE5A30E60E5D500A0803E /* TDFastJsonParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDFastJsonParserTest.h; path = test/TDFastJsonParserTest.h; sourceTree = ""; }; + D31FE5A40E60E5D500A0803E /* TDFastJsonParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDFastJsonParserTest.m; path = test/TDFastJsonParserTest.m; sourceTree = ""; }; + D31FE5AD0E60E64900A0803E /* TDXmlTokenAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTokenAssembly.h; path = test/TDXmlTokenAssembly.h; sourceTree = ""; }; + D31FE5AE0E60E64900A0803E /* TDXmlTokenAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTokenAssembly.m; path = test/TDXmlTokenAssembly.m; sourceTree = ""; }; + D31FE5AF0E60E64900A0803E /* TDXmlTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTokenizerTest.h; path = test/TDXmlTokenizerTest.h; sourceTree = ""; }; + D31FE5B00E60E64900A0803E /* TDXmlTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTokenizerTest.m; path = test/TDXmlTokenizerTest.m; sourceTree = ""; }; + D31FE5B30E60E66600A0803E /* TDXmlToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlToken.h; path = test/TDXmlToken.h; sourceTree = ""; }; + D31FE5B40E60E66600A0803E /* TDXmlToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlToken.m; path = test/TDXmlToken.m; sourceTree = ""; }; + D31FE5B50E60E66600A0803E /* TDXmlTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTokenizer.h; path = test/TDXmlTokenizer.h; sourceTree = ""; }; + D31FE5B60E60E66600A0803E /* TDXmlTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTokenizer.m; path = test/TDXmlTokenizer.m; sourceTree = ""; }; + D31FE5B90E60E69E00A0803E /* TDXmlAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlAttribute.h; path = test/TDXmlAttribute.h; sourceTree = ""; }; + D31FE5BA0E60E69E00A0803E /* TDXmlAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlAttribute.m; path = test/TDXmlAttribute.m; sourceTree = ""; }; + D31FE5BB0E60E69E00A0803E /* TDXmlCdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlCdata.h; path = test/TDXmlCdata.h; sourceTree = ""; }; + D31FE5BC0E60E69E00A0803E /* TDXmlCdata.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlCdata.m; path = test/TDXmlCdata.m; sourceTree = ""; }; + D31FE5BD0E60E69E00A0803E /* TDXmlComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlComment.h; path = test/TDXmlComment.h; sourceTree = ""; }; + D31FE5BE0E60E69E00A0803E /* TDXmlComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlComment.m; path = test/TDXmlComment.m; sourceTree = ""; }; + D31FE5BF0E60E69E00A0803E /* TDXmlDecl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlDecl.h; path = test/TDXmlDecl.h; sourceTree = ""; }; + D31FE5C00E60E69E00A0803E /* TDXmlDecl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlDecl.m; path = test/TDXmlDecl.m; sourceTree = ""; }; + D31FE5C10E60E69E00A0803E /* TDXmlDoctype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlDoctype.h; path = test/TDXmlDoctype.h; sourceTree = ""; }; + D31FE5C20E60E69E00A0803E /* TDXmlDoctype.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlDoctype.m; path = test/TDXmlDoctype.m; sourceTree = ""; }; + D31FE5C30E60E69E00A0803E /* TDXmlDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlDocument.h; path = test/TDXmlDocument.h; sourceTree = ""; }; + D31FE5C40E60E69E00A0803E /* TDXmlDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlDocument.m; path = test/TDXmlDocument.m; sourceTree = ""; }; + D31FE5C50E60E69E00A0803E /* TDXmlEndEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEndEntity.h; path = test/TDXmlEndEntity.h; sourceTree = ""; }; + D31FE5C60E60E69E00A0803E /* TDXmlEndEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEndEntity.m; path = test/TDXmlEndEntity.m; sourceTree = ""; }; + D31FE5C70E60E69E00A0803E /* TDXmlEndTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEndTag.h; path = test/TDXmlEndTag.h; sourceTree = ""; }; + D31FE5C80E60E69E00A0803E /* TDXmlEndTag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEndTag.m; path = test/TDXmlEndTag.m; sourceTree = ""; }; + D31FE5C90E60E69E00A0803E /* TDXmlEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEntity.h; path = test/TDXmlEntity.h; sourceTree = ""; }; + D31FE5CA0E60E69E00A0803E /* TDXmlEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEntity.m; path = test/TDXmlEntity.m; sourceTree = ""; }; + D31FE5CB0E60E69E00A0803E /* TDXmlEntityRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlEntityRef.h; path = test/TDXmlEntityRef.h; sourceTree = ""; }; + D31FE5CC0E60E69E00A0803E /* TDXmlEntityRef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlEntityRef.m; path = test/TDXmlEntityRef.m; sourceTree = ""; }; + D31FE5CD0E60E69E00A0803E /* TDXmlFragment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlFragment.h; path = test/TDXmlFragment.h; sourceTree = ""; }; + D31FE5CE0E60E69E00A0803E /* TDXmlFragment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlFragment.m; path = test/TDXmlFragment.m; sourceTree = ""; }; + D31FE5CF0E60E69E00A0803E /* TDXmlNotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNotation.h; path = test/TDXmlNotation.h; sourceTree = ""; }; + D31FE5D00E60E69E00A0803E /* TDXmlNotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNotation.m; path = test/TDXmlNotation.m; sourceTree = ""; }; + D31FE5D10E60E69E00A0803E /* TDXmlProcessingInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlProcessingInstruction.h; path = test/TDXmlProcessingInstruction.h; sourceTree = ""; }; + D31FE5D20E60E69E00A0803E /* TDXmlProcessingInstruction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlProcessingInstruction.m; path = test/TDXmlProcessingInstruction.m; sourceTree = ""; }; + D31FE5D30E60E69E00A0803E /* TDXmlSignificantWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlSignificantWhitespace.h; path = test/TDXmlSignificantWhitespace.h; sourceTree = ""; }; + D31FE5D40E60E69E00A0803E /* TDXmlSignificantWhitespace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlSignificantWhitespace.m; path = test/TDXmlSignificantWhitespace.m; sourceTree = ""; }; + D31FE5D50E60E69E00A0803E /* TDXmlStartTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlStartTag.h; path = test/TDXmlStartTag.h; sourceTree = ""; }; + D31FE5D60E60E69E00A0803E /* TDXmlStartTag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlStartTag.m; path = test/TDXmlStartTag.m; sourceTree = ""; }; + D31FE5D70E60E69E00A0803E /* TDXmlTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlTerminal.h; path = test/TDXmlTerminal.h; sourceTree = ""; }; + D31FE5D80E60E69E00A0803E /* TDXmlTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlTerminal.m; path = test/TDXmlTerminal.m; sourceTree = ""; }; + D31FE5D90E60E69E00A0803E /* TDXmlText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlText.h; path = test/TDXmlText.h; sourceTree = ""; }; + D31FE5DA0E60E69E00A0803E /* TDXmlText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlText.m; path = test/TDXmlText.m; sourceTree = ""; }; + D31FE5DB0E60E69E00A0803E /* TDXmlWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlWhitespace.h; path = test/TDXmlWhitespace.h; sourceTree = ""; }; + D31FE5DC0E60E69E00A0803E /* TDXmlWhitespace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlWhitespace.m; path = test/TDXmlWhitespace.m; sourceTree = ""; }; + D31FE5EF0E60E6B500A0803E /* TDNCName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNCName.h; path = test/TDNCName.h; sourceTree = ""; }; + D31FE5F00E60E6B500A0803E /* TDNCNameState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNCNameState.h; path = test/TDNCNameState.h; sourceTree = ""; }; + D31FE5F10E60E6B500A0803E /* TDNCNameState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNCNameState.m; path = test/TDNCNameState.m; sourceTree = ""; }; + D31FE5F20E60E6B500A0803E /* TDXmlName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlName.h; path = test/TDXmlName.h; sourceTree = ""; }; + D31FE5F30E60E6B500A0803E /* TDXmlName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlName.m; path = test/TDXmlName.m; sourceTree = ""; }; + D31FE5F40E60E6B500A0803E /* TDXmlNameState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNameState.h; path = test/TDXmlNameState.h; sourceTree = ""; }; + D31FE5F50E60E6B500A0803E /* TDXmlNameState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNameState.m; path = test/TDXmlNameState.m; sourceTree = ""; }; + D31FE5F60E60E6B500A0803E /* TDXmlNameTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNameTest.h; path = test/TDXmlNameTest.h; sourceTree = ""; }; + D31FE5F70E60E6B500A0803E /* TDXmlNameTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNameTest.m; path = test/TDXmlNameTest.m; sourceTree = ""; }; + D31FE5F80E60E6B500A0803E /* TDXmlNmtoken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNmtoken.h; path = test/TDXmlNmtoken.h; sourceTree = ""; }; + D31FE5F90E60E6B500A0803E /* TDXmlNmtoken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNmtoken.m; path = test/TDXmlNmtoken.m; sourceTree = ""; }; + D31FE5FA0E60E6B500A0803E /* TDXmlNmtokenState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXmlNmtokenState.h; path = test/TDXmlNmtokenState.h; sourceTree = ""; }; + D31FE5FB0E60E6B500A0803E /* TDXmlNmtokenState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXmlNmtokenState.m; path = test/TDXmlNmtokenState.m; sourceTree = ""; }; + D31FE6DF0E60EE2500A0803E /* TDNCName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNCName.m; path = test/TDNCName.m; sourceTree = ""; }; + D3252F780FCE1A7E005EF059 /* TDNSPredicateBuilderTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateBuilderTest.h; path = test/TDNSPredicateBuilderTest.h; sourceTree = ""; }; + D3252F790FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateBuilderTest.m; path = test/TDNSPredicateBuilderTest.m; sourceTree = ""; }; + D3252F7C0FCE1A87005EF059 /* TDNSPredicateBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateBuilder.h; path = test/TDNSPredicateBuilder.h; sourceTree = ""; }; + D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateBuilder.m; path = test/TDNSPredicateBuilder.m; sourceTree = ""; }; + D3305C4B102F5BAD00DC4F75 /* TDGutterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDGutterView.h; path = demoapp/TDGutterView.h; sourceTree = ""; }; + D3305C4C102F5BAD00DC4F75 /* TDGutterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDGutterView.m; path = demoapp/TDGutterView.m; sourceTree = ""; }; + D3305C4D102F5BAE00DC4F75 /* TDSourceCodeTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSourceCodeTextView.h; path = demoapp/TDSourceCodeTextView.h; sourceTree = ""; }; + D3305C4E102F5BAE00DC4F75 /* TDSourceCodeTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSourceCodeTextView.m; path = demoapp/TDSourceCodeTextView.m; sourceTree = ""; }; + D33494100E2963FD00406085 /* DemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D3376D5710093A1600E4602E /* PKGrammarParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKGrammarParser.h; path = src/PKGrammarParser.h; sourceTree = ""; }; + D3376D5810093A1600E4602E /* PKGrammarParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKGrammarParser.m; path = src/PKGrammarParser.m; sourceTree = ""; }; + D3376D8C10096C0700E4602E /* PKAST.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAST.h; path = test/PKAST.h; sourceTree = ""; }; + D3376D8D10096C0700E4602E /* PKAST.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAST.m; path = test/PKAST.m; sourceTree = ""; }; + D3385FD70FCFB1FF003BF729 /* TDPredicateEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPredicateEvaluator.h; path = test/TDPredicateEvaluator.h; sourceTree = ""; }; + D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPredicateEvaluator.m; path = test/TDPredicateEvaluator.m; sourceTree = ""; }; + D3385FDB0FCFB227003BF729 /* TDPredicateEvaluatorTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPredicateEvaluatorTest.h; path = test/TDPredicateEvaluatorTest.h; sourceTree = ""; }; + D3385FDC0FCFB227003BF729 /* TDPredicateEvaluatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPredicateEvaluatorTest.m; path = test/TDPredicateEvaluatorTest.m; sourceTree = ""; }; + D338E5B90FF5DDCB003DE6AA /* TDDifferenceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDDifferenceTest.h; path = test/TDDifferenceTest.h; sourceTree = ""; }; + D338E5BA0FF5DDCB003DE6AA /* TDDifferenceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDDifferenceTest.m; path = test/TDDifferenceTest.m; sourceTree = ""; }; + D34185040E520D3F0081B0DC /* DebugApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DebugApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D34BAC210FF87F8600D7773A /* TDParserFactoryTest3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryTest3.h; path = test/TDParserFactoryTest3.h; sourceTree = ""; }; + D34BAC220FF87F8600D7773A /* TDParserFactoryTest3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryTest3.m; path = test/TDParserFactoryTest3.m; sourceTree = ""; }; + D34BAC490FF892C200D7773A /* XPathParserGrammarTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathParserGrammarTest.h; path = test/XPathParserGrammarTest.h; sourceTree = ""; }; + D34BAC4A0FF892C200D7773A /* XPathParserGrammarTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathParserGrammarTest.m; path = test/XPathParserGrammarTest.m; sourceTree = ""; }; + D34BAD16100A9B7900996341 /* TDTokenizerStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenizerStateTest.h; path = test/TDTokenizerStateTest.h; sourceTree = ""; }; + D34BAD17100A9B7900996341 /* TDTokenizerStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenizerStateTest.m; path = test/TDTokenizerStateTest.m; sourceTree = ""; }; + D34BAD630FF9C6AE00D7773A /* ParseKit_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseKit_Prefix.pch; sourceTree = ""; }; + D34BAD9B0FF9C95800D7773A /* PKReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKReader.m; path = src/PKReader.m; sourceTree = ""; }; + D34BADA00FF9C9B000D7773A /* PKAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAssembly.m; path = src/PKAssembly.m; sourceTree = ""; }; + D34BADD60FF9CBFB00D7773A /* PKParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParser.m; path = src/PKParser.m; sourceTree = ""; }; + D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCollectionParser.m; path = src/PKCollectionParser.m; sourceTree = ""; }; + D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAlternation.m; path = src/PKAlternation.m; sourceTree = ""; }; + D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKEmpty.m; path = src/PKEmpty.m; sourceTree = ""; }; + D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDifference.m; path = src/PKDifference.m; sourceTree = ""; }; + D34BAE110FF9CE0E00D7773A /* PKIntersection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKIntersection.m; path = src/PKIntersection.m; sourceTree = ""; }; + D34BAE130FF9CE0E00D7773A /* PKRepetition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKRepetition.m; path = src/PKRepetition.m; sourceTree = ""; }; + D34BAE150FF9CE0E00D7773A /* PKSequence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSequence.m; path = src/PKSequence.m; sourceTree = ""; }; + D34BAE170FF9CE0E00D7773A /* PKTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTerminal.m; path = src/PKTerminal.m; sourceTree = ""; }; + D34BAE190FF9CE0E00D7773A /* PKTrack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTrack.m; path = src/PKTrack.m; sourceTree = ""; }; + D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTrackException.m; path = src/PKTrackException.m; sourceTree = ""; }; + D34BAE2F0FF9CE6000D7773A /* PKAny.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKAny.m; path = src/PKAny.m; sourceTree = ""; }; + D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenAssembly.m; path = src/PKTokenAssembly.m; sourceTree = ""; }; + D34BAE950FF9D20900D7773A /* PKToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKToken.m; path = src/PKToken.m; sourceTree = ""; }; + D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenArraySource.m; path = src/PKTokenArraySource.m; sourceTree = ""; }; + D34BAE990FF9D20900D7773A /* PKTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenizer.m; path = src/PKTokenizer.m; sourceTree = ""; }; + D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenizerState.m; path = src/PKTokenizerState.m; sourceTree = ""; }; + D34BAEC40FF9D56400D7773A /* PKCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCommentState.m; path = src/PKCommentState.m; sourceTree = ""; }; + D34BAEC60FF9D56400D7773A /* PKDelimitState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDelimitState.m; path = src/PKDelimitState.m; sourceTree = ""; }; + D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKMultiLineCommentState.m; path = src/PKMultiLineCommentState.m; sourceTree = ""; }; + D34BAECA0FF9D56400D7773A /* PKNumberState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKNumberState.m; path = src/PKNumberState.m; sourceTree = ""; }; + D34BAECC0FF9D56400D7773A /* PKQuoteState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKQuoteState.m; path = src/PKQuoteState.m; sourceTree = ""; }; + D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSingleLineCommentState.m; path = src/PKSingleLineCommentState.m; sourceTree = ""; }; + D34BAED00FF9D56400D7773A /* PKSymbolState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbolState.m; path = src/PKSymbolState.m; sourceTree = ""; }; + D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWhitespaceState.m; path = src/PKWhitespaceState.m; sourceTree = ""; }; + D34BAED40FF9D56400D7773A /* PKWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWord.m; path = src/PKWord.m; sourceTree = ""; }; + D34BAED60FF9D56400D7773A /* PKWordState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWordState.m; path = src/PKWordState.m; sourceTree = ""; }; + D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbolNode.m; path = src/PKSymbolNode.m; sourceTree = ""; }; + D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbolRootNode.m; path = src/PKSymbolRootNode.m; sourceTree = ""; }; + D34BAF380FF9E18300D7773A /* PKPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKPattern.m; path = src/PKPattern.m; sourceTree = ""; }; + D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCaseInsensitiveLiteral.m; path = src/PKCaseInsensitiveLiteral.m; sourceTree = ""; }; + D34BAF3E0FF9E19700D7773A /* PKComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKComment.m; path = src/PKComment.m; sourceTree = ""; }; + D34BAF400FF9E19700D7773A /* PKDelimitedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDelimitedString.m; path = src/PKDelimitedString.m; sourceTree = ""; }; + D34BAF420FF9E19700D7773A /* PKLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKLiteral.m; path = src/PKLiteral.m; sourceTree = ""; }; + D34BAF440FF9E19700D7773A /* PKNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKNumber.m; path = src/PKNumber.m; sourceTree = ""; }; + D34BAF460FF9E19700D7773A /* PKQuotedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKQuotedString.m; path = src/PKQuotedString.m; sourceTree = ""; }; + D34BAF480FF9E19700D7773A /* PKSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSymbol.m; path = src/PKSymbol.m; sourceTree = ""; }; + D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWhitespace.m; path = src/PKWhitespace.m; sourceTree = ""; }; + D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKLowercaseWord.m; path = src/PKLowercaseWord.m; sourceTree = ""; }; + D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKUppercaseWord.m; path = src/PKUppercaseWord.m; sourceTree = ""; }; + D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKCharacterAssembly.m; path = src/PKCharacterAssembly.m; sourceTree = ""; }; + D34BAFB40FF9E80300D7773A /* PKChar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKChar.m; path = src/PKChar.m; sourceTree = ""; }; + D34BAFB60FF9E80300D7773A /* PKDigit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKDigit.m; path = src/PKDigit.m; sourceTree = ""; }; + D34BAFB80FF9E80300D7773A /* PKLetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKLetter.m; path = src/PKLetter.m; sourceTree = ""; }; + D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKSpecificChar.m; path = src/PKSpecificChar.m; sourceTree = ""; }; + D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+ParseKitAdditions.h"; path = "src/NSArray+ParseKitAdditions.h"; sourceTree = ""; }; + D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+ParseKitAdditions.m"; path = "src/NSArray+ParseKitAdditions.m"; sourceTree = ""; }; + D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+ParseKitAdditions.h"; path = "src/NSString+ParseKitAdditions.h"; sourceTree = ""; }; + D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+ParseKitAdditions.m"; path = "src/NSString+ParseKitAdditions.m"; sourceTree = ""; }; + D34BAFD80FF9E95500D7773A /* PKParserFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParserFactory.m; path = src/PKParserFactory.m; sourceTree = ""; }; + D34BB04E0FF9EC4E00D7773A /* JSParseKit-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "JSParseKit-Info.plist"; sourceTree = ""; }; + D34BB0660FF9EDDF00D7773A /* JSParseKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSParseKit.h; path = jssrc/JSParseKit.h; sourceTree = ""; }; + D34BB0670FF9EDDF00D7773A /* JSParseKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSParseKit.m; path = jssrc/JSParseKit.m; sourceTree = ""; }; + D34BB06A0FF9EE4000D7773A /* PKJSAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAssembly.h; path = jssrc/PKJSAssembly.h; sourceTree = ""; }; + D34BB06B0FF9EE4000D7773A /* PKJSAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAssembly.m; path = jssrc/PKJSAssembly.m; sourceTree = ""; }; + D34BB06C0FF9EE4000D7773A /* PKJSUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSUtils.h; path = jssrc/PKJSUtils.h; sourceTree = ""; }; + D34BB06D0FF9EE4000D7773A /* PKJSUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSUtils.m; path = jssrc/PKJSUtils.m; sourceTree = ""; }; + D34BB06E0FF9EE4000D7773A /* PKJSUtils_macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSUtils_macros.h; path = jssrc/PKJSUtils_macros.h; sourceTree = ""; }; + D34BB06F0FF9EE4000D7773A /* PKJSValueHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSValueHolder.h; path = jssrc/PKJSValueHolder.h; sourceTree = ""; }; + D34BB0700FF9EE4000D7773A /* PKJSValueHolder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSValueHolder.m; path = jssrc/PKJSValueHolder.m; sourceTree = ""; }; + D34BB08D0FF9EF9D00D7773A /* PKJSCharacterAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCharacterAssembly.h; path = jssrc/PKJSCharacterAssembly.h; sourceTree = ""; }; + D34BB08E0FF9EF9D00D7773A /* PKJSCharacterAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCharacterAssembly.m; path = jssrc/PKJSCharacterAssembly.m; sourceTree = ""; }; + D34BB0930FF9F14B00D7773A /* PKJSCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCommentState.h; path = jssrc/PKJSCommentState.h; sourceTree = ""; }; + D34BB0940FF9F14B00D7773A /* PKJSCommentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCommentState.m; path = jssrc/PKJSCommentState.m; sourceTree = ""; }; + D34BB0950FF9F14B00D7773A /* PKJSDelimitState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSDelimitState.h; path = jssrc/PKJSDelimitState.h; sourceTree = ""; }; + D34BB0960FF9F14B00D7773A /* PKJSDelimitState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSDelimitState.m; path = jssrc/PKJSDelimitState.m; sourceTree = ""; }; + D34BB0970FF9F14B00D7773A /* PKJSNumberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSNumberState.h; path = jssrc/PKJSNumberState.h; sourceTree = ""; }; + D34BB0980FF9F14B00D7773A /* PKJSNumberState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSNumberState.m; path = jssrc/PKJSNumberState.m; sourceTree = ""; }; + D34BB0990FF9F14B00D7773A /* PKJSQuoteState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSQuoteState.h; path = jssrc/PKJSQuoteState.h; sourceTree = ""; }; + D34BB09A0FF9F14B00D7773A /* PKJSQuoteState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSQuoteState.m; path = jssrc/PKJSQuoteState.m; sourceTree = ""; }; + D34BB09B0FF9F14B00D7773A /* PKJSSymbolState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSSymbolState.h; path = jssrc/PKJSSymbolState.h; sourceTree = ""; }; + D34BB09C0FF9F14B00D7773A /* PKJSSymbolState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSSymbolState.m; path = jssrc/PKJSSymbolState.m; sourceTree = ""; }; + D34BB09D0FF9F14B00D7773A /* PKJSToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSToken.h; path = jssrc/PKJSToken.h; sourceTree = ""; }; + D34BB09E0FF9F14B00D7773A /* PKJSToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSToken.m; path = jssrc/PKJSToken.m; sourceTree = ""; }; + D34BB09F0FF9F14B00D7773A /* PKJSTokenAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTokenAssembly.h; path = jssrc/PKJSTokenAssembly.h; sourceTree = ""; }; + D34BB0A00FF9F14B00D7773A /* PKJSTokenAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTokenAssembly.m; path = jssrc/PKJSTokenAssembly.m; sourceTree = ""; }; + D34BB0A10FF9F14B00D7773A /* PKJSTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTokenizer.h; path = jssrc/PKJSTokenizer.h; sourceTree = ""; }; + D34BB0A20FF9F14B00D7773A /* PKJSTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTokenizer.m; path = jssrc/PKJSTokenizer.m; sourceTree = ""; }; + D34BB0A30FF9F14B00D7773A /* PKJSTokenizerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTokenizerState.h; path = jssrc/PKJSTokenizerState.h; sourceTree = ""; }; + D34BB0A40FF9F14B00D7773A /* PKJSTokenizerState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTokenizerState.m; path = jssrc/PKJSTokenizerState.m; sourceTree = ""; }; + D34BB0A50FF9F14B00D7773A /* PKJSWhitespaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSWhitespaceState.h; path = jssrc/PKJSWhitespaceState.h; sourceTree = ""; }; + D34BB0A60FF9F14B00D7773A /* PKJSWhitespaceState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSWhitespaceState.m; path = jssrc/PKJSWhitespaceState.m; sourceTree = ""; }; + D34BB0A70FF9F14B00D7773A /* PKJSWordState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSWordState.h; path = jssrc/PKJSWordState.h; sourceTree = ""; }; + D34BB0A80FF9F14B00D7773A /* PKJSWordState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSWordState.m; path = jssrc/PKJSWordState.m; sourceTree = ""; }; + D34BB0D20FF9F28000D7773A /* PKJSAlternation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAlternation.h; path = jssrc/PKJSAlternation.h; sourceTree = ""; }; + D34BB0D30FF9F28000D7773A /* PKJSAlternation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAlternation.m; path = jssrc/PKJSAlternation.m; sourceTree = ""; }; + D34BB0D40FF9F28000D7773A /* PKJSAny.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAny.h; path = jssrc/PKJSAny.h; sourceTree = ""; }; + D34BB0D50FF9F28000D7773A /* PKJSAny.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAny.m; path = jssrc/PKJSAny.m; sourceTree = ""; }; + D34BB0D60FF9F28000D7773A /* PKJSAssemblerAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSAssemblerAdapter.h; path = jssrc/PKJSAssemblerAdapter.h; sourceTree = ""; }; + D34BB0D70FF9F28000D7773A /* PKJSAssemblerAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSAssemblerAdapter.m; path = jssrc/PKJSAssemblerAdapter.m; sourceTree = ""; }; + D34BB0D80FF9F28000D7773A /* PKJSCollectionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCollectionParser.h; path = jssrc/PKJSCollectionParser.h; sourceTree = ""; }; + D34BB0D90FF9F28000D7773A /* PKJSCollectionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCollectionParser.m; path = jssrc/PKJSCollectionParser.m; sourceTree = ""; }; + D34BB0DA0FF9F28000D7773A /* PKJSEmpty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSEmpty.h; path = jssrc/PKJSEmpty.h; sourceTree = ""; }; + D34BB0DB0FF9F28000D7773A /* PKJSEmpty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSEmpty.m; path = jssrc/PKJSEmpty.m; sourceTree = ""; }; + D34BB0DC0FF9F28000D7773A /* PKJSParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSParser.h; path = jssrc/PKJSParser.h; sourceTree = ""; }; + D34BB0DD0FF9F28000D7773A /* PKJSParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSParser.m; path = jssrc/PKJSParser.m; sourceTree = ""; }; + D34BB0DE0FF9F28000D7773A /* PKJSRepetition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSRepetition.h; path = jssrc/PKJSRepetition.h; sourceTree = ""; }; + D34BB0DF0FF9F28000D7773A /* PKJSRepetition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSRepetition.m; path = jssrc/PKJSRepetition.m; sourceTree = ""; }; + D34BB0E00FF9F28000D7773A /* PKJSSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSSequence.h; path = jssrc/PKJSSequence.h; sourceTree = ""; }; + D34BB0E10FF9F28000D7773A /* PKJSSequence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSSequence.m; path = jssrc/PKJSSequence.m; sourceTree = ""; }; + D34BB0E20FF9F28000D7773A /* PKJSTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTerminal.h; path = jssrc/PKJSTerminal.h; sourceTree = ""; }; + D34BB0E30FF9F28000D7773A /* PKJSTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTerminal.m; path = jssrc/PKJSTerminal.m; sourceTree = ""; }; + D34BB0E40FF9F28000D7773A /* PKJSTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSTrack.h; path = jssrc/PKJSTrack.h; sourceTree = ""; }; + D34BB0E50FF9F28000D7773A /* PKJSTrack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSTrack.m; path = jssrc/PKJSTrack.m; sourceTree = ""; }; + D34BB0FE0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSCaseInsensitiveLiteral.h; path = jssrc/PKJSCaseInsensitiveLiteral.h; sourceTree = ""; }; + D34BB0FF0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSCaseInsensitiveLiteral.m; path = jssrc/PKJSCaseInsensitiveLiteral.m; sourceTree = ""; }; + D34BB1000FF9F36200D7773A /* PKJSComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSComment.h; path = jssrc/PKJSComment.h; sourceTree = ""; }; + D34BB1010FF9F36200D7773A /* PKJSComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSComment.m; path = jssrc/PKJSComment.m; sourceTree = ""; }; + D34BB1020FF9F36200D7773A /* PKJSDelimitedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSDelimitedString.h; path = jssrc/PKJSDelimitedString.h; sourceTree = ""; }; + D34BB1030FF9F36200D7773A /* PKJSDelimitedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSDelimitedString.m; path = jssrc/PKJSDelimitedString.m; sourceTree = ""; }; + D34BB1040FF9F36200D7773A /* PKJSLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSLiteral.h; path = jssrc/PKJSLiteral.h; sourceTree = ""; }; + D34BB1050FF9F36200D7773A /* PKJSLiteral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSLiteral.m; path = jssrc/PKJSLiteral.m; sourceTree = ""; }; + D34BB1060FF9F36200D7773A /* PKJSLowercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSLowercaseWord.h; path = jssrc/PKJSLowercaseWord.h; sourceTree = ""; }; + D34BB1070FF9F36200D7773A /* PKJSLowercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSLowercaseWord.m; path = jssrc/PKJSLowercaseWord.m; sourceTree = ""; }; + D34BB1080FF9F36200D7773A /* PKJSNum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSNum.h; path = jssrc/PKJSNum.h; sourceTree = ""; }; + D34BB1090FF9F36200D7773A /* PKJSNum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSNum.m; path = jssrc/PKJSNum.m; sourceTree = ""; }; + D34BB10A0FF9F36200D7773A /* PKJSPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSPattern.h; path = jssrc/PKJSPattern.h; sourceTree = ""; }; + D34BB10B0FF9F36200D7773A /* PKJSPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSPattern.m; path = jssrc/PKJSPattern.m; sourceTree = ""; }; + D34BB10C0FF9F36200D7773A /* PKJSQuotedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSQuotedString.h; path = jssrc/PKJSQuotedString.h; sourceTree = ""; }; + D34BB10D0FF9F36200D7773A /* PKJSQuotedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSQuotedString.m; path = jssrc/PKJSQuotedString.m; sourceTree = ""; }; + D34BB10E0FF9F36200D7773A /* PKJSSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSSymbol.h; path = jssrc/PKJSSymbol.h; sourceTree = ""; }; + D34BB10F0FF9F36200D7773A /* PKJSSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSSymbol.m; path = jssrc/PKJSSymbol.m; sourceTree = ""; }; + D34BB1100FF9F36200D7773A /* PKJSUppercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSUppercaseWord.h; path = jssrc/PKJSUppercaseWord.h; sourceTree = ""; }; + D34BB1110FF9F36200D7773A /* PKJSUppercaseWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSUppercaseWord.m; path = jssrc/PKJSUppercaseWord.m; sourceTree = ""; }; + D34BB1120FF9F36200D7773A /* PKJSWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKJSWord.h; path = jssrc/PKJSWord.h; sourceTree = ""; }; + D34BB1130FF9F36200D7773A /* PKJSWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKJSWord.m; path = jssrc/PKJSWord.m; sourceTree = ""; }; + D3521F520E5FA1B0009681F9 /* XMLReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMLReader.h; path = test/XMLReader.h; sourceTree = ""; }; + D3521F530E5FA1B0009681F9 /* XMLReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMLReader.m; path = test/XMLReader.m; sourceTree = ""; }; + D3521F540E5FA1B0009681F9 /* XMLReaderTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMLReaderTest.h; path = test/XMLReaderTest.h; sourceTree = ""; }; + D3521F550E5FA1B0009681F9 /* XMLReaderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMLReaderTest.m; path = test/XMLReaderTest.m; sourceTree = ""; }; + D35384EC0FE9691100926552 /* nspredicate.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = nspredicate.grammar; path = res/nspredicate.grammar; sourceTree = ""; }; + D353899B0FEAC94400926552 /* c.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = c.grammar; path = res/c.grammar; sourceTree = ""; }; + D353899D0FEAC96B00926552 /* objc.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = objc.grammar; path = res/objc.grammar; sourceTree = ""; }; + D355C62B0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateEvaluator.h; path = test/TDNSPredicateEvaluator.h; sourceTree = ""; }; + D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateEvaluator.m; path = test/TDNSPredicateEvaluator.m; sourceTree = ""; }; + D355C62F0FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNSPredicateEvaluatorTest.h; path = test/TDNSPredicateEvaluatorTest.h; sourceTree = ""; }; + D355C6300FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNSPredicateEvaluatorTest.m; path = test/TDNSPredicateEvaluatorTest.m; sourceTree = ""; }; + D355C8800FEB36A1006A91A4 /* xml.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = xml.grammar; path = res/xml.grammar; sourceTree = ""; }; + D355C8830FEB4B94006A91A4 /* proto.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = proto.grammar; path = res/proto.grammar; sourceTree = ""; }; + D36568A50EEF9FE900226554 /* TDPlistParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPlistParser.h; path = test/TDPlistParser.h; sourceTree = ""; }; + D36568A60EEF9FE900226554 /* TDPlistParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPlistParser.m; path = test/TDPlistParser.m; sourceTree = ""; }; + D36568A80EEFA05300226554 /* TDPlistParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPlistParserTest.h; path = test/TDPlistParserTest.h; sourceTree = ""; }; + D36568A90EEFA05300226554 /* TDPlistParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPlistParserTest.m; path = test/TDPlistParserTest.m; sourceTree = ""; }; + D3656DFC0EF2620E00226554 /* TDTokenArraySourceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenArraySourceTest.h; path = test/TDTokenArraySourceTest.h; sourceTree = ""; }; + D3656DFD0EF2620E00226554 /* TDTokenArraySourceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenArraySourceTest.m; path = test/TDTokenArraySourceTest.m; sourceTree = ""; }; + D3668291101D2BFA0008632C /* erb.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = erb.grammar; path = res/erb.grammar; sourceTree = ""; }; + D3668294101D2C200008632C /* ERBTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ERBTest.h; path = test/ERBTest.h; sourceTree = ""; }; + D3668295101D2C200008632C /* ERBTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ERBTest.m; path = test/ERBTest.m; sourceTree = ""; }; + D36934551038DE5300527AF3 /* PKParseTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParseTree.h; path = test/PKParseTree.h; sourceTree = ""; }; + D36934561038DE5300527AF3 /* PKParseTree.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParseTree.m; path = test/PKParseTree.m; sourceTree = ""; }; + D36934571038DE5300527AF3 /* PKParseTreeAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParseTreeAssembler.h; path = test/PKParseTreeAssembler.h; sourceTree = ""; }; + D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParseTreeAssembler.m; path = test/PKParseTreeAssembler.m; sourceTree = ""; }; + D36934591038DE5300527AF3 /* PKRuleNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKRuleNode.h; path = test/PKRuleNode.h; sourceTree = ""; }; + D369345A1038DE5300527AF3 /* PKRuleNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKRuleNode.m; path = test/PKRuleNode.m; sourceTree = ""; }; + D369345B1038DE5300527AF3 /* PKTokenNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenNode.h; path = test/PKTokenNode.h; sourceTree = ""; }; + D369345C1038DE5300527AF3 /* PKTokenNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKTokenNode.m; path = test/PKTokenNode.m; sourceTree = ""; }; + D36C53770FD27F1300141CB7 /* TDParserFactoryTest2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryTest2.h; path = test/TDParserFactoryTest2.h; sourceTree = ""; }; + D36C53780FD27F1300141CB7 /* TDParserFactoryTest2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryTest2.m; path = test/TDParserFactoryTest2.m; sourceTree = ""; }; + D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegexKitLite.h; path = src/RegexKitLite.h; sourceTree = ""; }; + D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RegexKitLite.m; path = src/RegexKitLite.m; sourceTree = ""; }; + D36C560B0FD363D500141CB7 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = /usr/lib/libicucore.dylib; sourceTree = ""; }; + D36C56290FD365DB00141CB7 /* TDPatternTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDPatternTest.h; path = test/TDPatternTest.h; sourceTree = ""; }; + D36C562A0FD365DB00141CB7 /* TDPatternTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDPatternTest.m; path = test/TDPatternTest.m; sourceTree = ""; }; + D36E95440E578ECC00496BD3 /* XPathParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathParser.h; path = test/XPathParser.h; sourceTree = ""; }; + D36E95450E578ECC00496BD3 /* XPathParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathParser.m; path = test/XPathParser.m; sourceTree = ""; }; + D36E95D60E57B08400496BD3 /* XPathParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathParserTest.h; path = test/XPathParserTest.h; sourceTree = ""; }; + D36E95D70E57B08400496BD3 /* XPathParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathParserTest.m; path = test/XPathParserTest.m; sourceTree = ""; }; + D36E97AE0E589DAE00496BD3 /* XPathAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathAssembler.h; path = test/XPathAssembler.h; sourceTree = ""; }; + D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathAssembler.m; path = test/XPathAssembler.m; sourceTree = ""; }; + D36E98200E58A3A800496BD3 /* XPathContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPathContext.h; path = test/XPathContext.h; sourceTree = ""; }; + D36E98210E58A3A800496BD3 /* XPathContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XPathContext.m; path = test/XPathContext.m; sourceTree = ""; }; + D36E98DC0E58C12800496BD3 /* DebugAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugAppDelegate.h; sourceTree = ""; }; + D36E98DD0E58C12800496BD3 /* DebugAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugAppDelegate.m; sourceTree = ""; }; + D36E98DE0E58C12800496BD3 /* DebugAppMainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DebugAppMainMenu.xib; sourceTree = ""; }; + D36E98DF0E58C12800496BD3 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + D36E98E30E58C14000496BD3 /* DemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DemoAppDelegate.h; path = demoapp/DemoAppDelegate.h; sourceTree = ""; }; + D36E98E40E58C14000496BD3 /* DemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DemoAppDelegate.m; path = demoapp/DemoAppDelegate.m; sourceTree = ""; }; + D36E98E50E58C14000496BD3 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = demoapp/main.m; sourceTree = ""; }; + D36E98F70E58C1A000496BD3 /* DemoAppMainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DemoAppMainMenu.xib; path = demoapp/DemoAppMainMenu.xib; sourceTree = ""; }; + D36E9F860E5A795400496BD3 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = /usr/lib/libxml2.dylib; sourceTree = ""; }; + D36E9FB40E5A944A00496BD3 /* apple-boss.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "apple-boss.xml"; path = "res/apple-boss.xml"; sourceTree = ""; }; + D36E9FE40E5BA0FC00496BD3 /* SRGSGrammar.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = SRGSGrammar.txt; path = res/SRGSGrammar.txt; sourceTree = ""; }; + D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "small-xml-file.xml"; path = "res/small-xml-file.xml"; sourceTree = ""; }; + D380AFBB0F0C54B60009EC13 /* html.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = html.css; path = res/html.css; sourceTree = ""; }; + D380AFBC0F0C54B60009EC13 /* html.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = html.grammar; path = res/html.grammar; sourceTree = ""; }; + D380AFC20F0C56000009EC13 /* example.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = example.html; path = res/example.html; sourceTree = ""; }; + D380B5080F0D71A90009EC13 /* css.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = css.grammar; path = res/css.grammar; sourceTree = ""; }; + D380B5370F0D7DDE0009EC13 /* css.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = css.css; path = res/css.css; sourceTree = ""; }; + D380B5930F0D82F60009EC13 /* example.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = example.css; path = res/example.css; sourceTree = ""; }; + D380BA5F0F0F06CD0009EC13 /* TDParserFactoryTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryTest.h; path = test/TDParserFactoryTest.h; sourceTree = ""; }; + D380BA600F0F06CD0009EC13 /* TDParserFactoryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryTest.m; path = test/TDParserFactoryTest.m; sourceTree = ""; }; + D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = /System/Library/Frameworks/JavaScriptCore.framework; sourceTree = ""; }; + D38205BC0EEE48EE004340DD /* TDTokenTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenTest.h; path = test/TDTokenTest.h; sourceTree = ""; }; + D38205BD0EEE48EE004340DD /* TDTokenTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenTest.m; path = test/TDTokenTest.m; sourceTree = ""; }; + D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json_with_comments.grammar; path = res/json_with_comments.grammar; sourceTree = ""; }; + D38349BB0F0C0D910055E4E0 /* json_with_comments.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = json_with_comments.css; path = res/json_with_comments.css; sourceTree = ""; }; + D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = yahoo_with_comments.json; path = res/yahoo_with_comments.json; sourceTree = ""; }; + D385F9880F046FE900DB2946 /* TDGenericAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDGenericAssembler.h; path = test/TDGenericAssembler.h; sourceTree = ""; }; + D385F9890F046FE900DB2946 /* TDGenericAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDGenericAssembler.m; path = test/TDGenericAssembler.m; sourceTree = ""; }; + D385FA210F04971400DB2946 /* TDGenericAssemblerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDGenericAssemblerTest.h; path = test/TDGenericAssemblerTest.h; sourceTree = ""; }; + D385FA220F04971400DB2946 /* TDGenericAssemblerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDGenericAssemblerTest.m; path = test/TDGenericAssemblerTest.m; sourceTree = ""; }; + D385FA240F04993500DB2946 /* json.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = json.css; path = res/json.css; sourceTree = ""; }; + D385FD400F05A88C00DB2946 /* TDMiniCSSAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDMiniCSSAssembler.h; path = test/TDMiniCSSAssembler.h; sourceTree = ""; }; + D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDMiniCSSAssembler.m; path = test/TDMiniCSSAssembler.m; sourceTree = ""; }; + D385FD420F05A88C00DB2946 /* TDMiniCSSAssemblerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDMiniCSSAssemblerTest.h; path = test/TDMiniCSSAssemblerTest.h; sourceTree = ""; }; + D385FD430F05A88C00DB2946 /* TDMiniCSSAssemblerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDMiniCSSAssemblerTest.m; path = test/TDMiniCSSAssemblerTest.m; sourceTree = ""; }; + D385FD6B0F05A99900DB2946 /* mini_css.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mini_css.grammar; path = res/mini_css.grammar; sourceTree = ""; }; + D389A0B00F1FCC99003B43BD /* RelaxParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RelaxParser.h; path = test/RelaxParser.h; sourceTree = ""; }; + D389A0B10F1FCC99003B43BD /* RelaxParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RelaxParser.m; path = test/RelaxParser.m; sourceTree = ""; }; + D389F1CE0F1965E600558235 /* JSParseKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSParseKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D389F2030F196A7500558235 /* JSDemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSDemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D389F20D0F196A9200558235 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + D389F2E30F196CAE00558235 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = jsdemoapp/main.m; sourceTree = ""; }; + D389F2E80F196F5B00558235 /* JSDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSDemoAppDelegate.h; path = jsdemoapp/JSDemoAppDelegate.h; sourceTree = ""; }; + D389F2E90F196F5B00558235 /* JSDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSDemoAppDelegate.m; path = jsdemoapp/JSDemoAppDelegate.m; sourceTree = ""; }; + D389F38E0F19800400558235 /* DefaultValues.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = DefaultValues.plist; path = jsdemoapp/DefaultValues.plist; sourceTree = ""; }; + D389F4610F198A8800558235 /* Test.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = Test.html; path = jsdemoapp/Test.html; sourceTree = ""; }; + D389F5580F19B7BC00558235 /* JSDemoAppMainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = JSDemoAppMainMenu.xib; path = jsdemoapp/JSDemoAppMainMenu.xib; sourceTree = ""; }; + D389F5B20F19C76A00558235 /* TDJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJsonParser.h; path = test/TDJsonParser.h; sourceTree = ""; }; + D389F5B30F19C76A00558235 /* TDJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJsonParser.m; path = test/TDJsonParser.m; sourceTree = ""; }; + D389F5B40F19C76A00558235 /* TDJsonParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJsonParserTest.h; path = test/TDJsonParserTest.h; sourceTree = ""; }; + D389F5B50F19C76A00558235 /* TDJsonParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJsonParserTest.m; path = test/TDJsonParserTest.m; sourceTree = ""; }; + D389FBCC0F1B25E200558235 /* ParserTest.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = ParserTest.html; path = jsdemoapp/ParserTest.html; sourceTree = ""; }; + D38DD9E70EC29F260070BC4D /* nyt.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = nyt.html; path = res/nyt.html; sourceTree = ""; }; + D38E97CA1061CF6500739C39 /* TDTokenizerBlocksTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDTokenizerBlocksTest.h; path = test/TDTokenizerBlocksTest.h; sourceTree = ""; }; + D38E97CB1061CF6500739C39 /* TDTokenizerBlocksTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDTokenizerBlocksTest.m; path = test/TDTokenizerBlocksTest.m; sourceTree = ""; }; + D38E98D61062C5BA00739C39 /* TDParserBlocksTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserBlocksTest.h; path = test/TDParserBlocksTest.h; sourceTree = ""; }; + D38E98D71062C5BA00739C39 /* TDParserBlocksTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserBlocksTest.m; path = test/TDParserBlocksTest.m; sourceTree = ""; }; + D3AF49760FDB122E0032F4DC /* TDParserFactoryPatternTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParserFactoryPatternTest.h; path = test/TDParserFactoryPatternTest.h; sourceTree = ""; }; + D3AF49770FDB122E0032F4DC /* TDParserFactoryPatternTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParserFactoryPatternTest.m; path = test/TDParserFactoryPatternTest.m; sourceTree = ""; }; + D3AF4BE80FDC3DD50032F4DC /* TDBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDBlob.h; path = test/TDBlob.h; sourceTree = ""; }; + D3AF4BE90FDC3DD50032F4DC /* TDBlob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDBlob.m; path = test/TDBlob.m; sourceTree = ""; }; + D3AF4BF50FDC40050032F4DC /* TDToken+Blob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TDToken+Blob.h"; path = "test/TDToken+Blob.h"; sourceTree = ""; }; + D3AF4BF60FDC40050032F4DC /* TDToken+Blob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "TDToken+Blob.m"; path = "test/TDToken+Blob.m"; sourceTree = ""; }; + D3AF4BFB0FDC41190032F4DC /* TDTokenizer+BlobState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "TDTokenizer+BlobState.h"; path = "test/TDTokenizer+BlobState.h"; sourceTree = ""; }; + D3AF4BFC0FDC41190032F4DC /* TDTokenizer+BlobState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "TDTokenizer+BlobState.m"; path = "test/TDTokenizer+BlobState.m"; sourceTree = ""; }; + D3AF4C190FDC568F0032F4DC /* TDBlobState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDBlobState.h; path = test/TDBlobState.h; sourceTree = ""; }; + D3AF4C1A0FDC568F0032F4DC /* TDBlobState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDBlobState.m; path = test/TDBlobState.m; sourceTree = ""; }; + D3AF4CBF0FDC740A0032F4DC /* TDNonReservedWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDNonReservedWord.h; path = test/TDNonReservedWord.h; sourceTree = ""; }; + D3AF4CC00FDC740A0032F4DC /* TDNonReservedWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDNonReservedWord.m; path = test/TDNonReservedWord.m; sourceTree = ""; }; + D3AF4CC10FDC740A0032F4DC /* TDReservedWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDReservedWord.h; path = test/TDReservedWord.h; sourceTree = ""; }; + D3AF4CC20FDC740A0032F4DC /* TDReservedWord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDReservedWord.m; path = test/TDReservedWord.m; sourceTree = ""; }; + D3AF4CC30FDC740A0032F4DC /* TDSignificantWhitespaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSignificantWhitespaceState.h; path = test/TDSignificantWhitespaceState.h; sourceTree = ""; }; + D3AF4CC40FDC740A0032F4DC /* TDSignificantWhitespaceState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSignificantWhitespaceState.m; path = test/TDSignificantWhitespaceState.m; sourceTree = ""; }; + D3AF4CC50FDC740A0032F4DC /* TDWordOrReservedState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDWordOrReservedState.h; path = test/TDWordOrReservedState.h; sourceTree = ""; }; + D3AF4CC60FDC740A0032F4DC /* TDWordOrReservedState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDWordOrReservedState.m; path = test/TDWordOrReservedState.m; sourceTree = ""; }; + D3B43FB50F76E99C0072AF40 /* TDJavaScriptParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDJavaScriptParserTest.h; path = test/TDJavaScriptParserTest.h; sourceTree = ""; }; + D3B43FB60F76E99C0072AF40 /* TDJavaScriptParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDJavaScriptParserTest.m; path = test/TDJavaScriptParserTest.m; sourceTree = ""; }; + D3B473840E48C9CF008AFBDD /* yahoo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = yahoo.json; path = res/yahoo.json; sourceTree = ""; }; + D3B69D310E80249900D70C41 /* nonascii.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = nonascii.html; path = res/nonascii.html; sourceTree = ""; }; + D3BBBC960FEC9722007DF30D /* TDXMLParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXMLParserTest.h; path = test/TDXMLParserTest.h; sourceTree = ""; }; + D3BBBC970FEC9722007DF30D /* TDXMLParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXMLParserTest.m; path = test/TDXMLParserTest.m; sourceTree = ""; }; + D3BBBC9B0FEC9756007DF30D /* TDXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDXMLParser.h; path = test/TDXMLParser.h; sourceTree = ""; }; + D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDXMLParser.m; path = test/TDXMLParser.m; sourceTree = ""; }; + D3C031EB0EF38D2D00C5ABEB /* TDLowercaseWordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDLowercaseWordTest.h; path = test/TDLowercaseWordTest.h; sourceTree = ""; }; + D3C031EC0EF38D2D00C5ABEB /* TDLowercaseWordTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDLowercaseWordTest.m; path = test/TDLowercaseWordTest.m; sourceTree = ""; }; + D3C2216D0FFE8A86004514FE /* PKExclusion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKExclusion.h; path = test/PKExclusion.h; sourceTree = ""; }; + D3C221900FFE8B8C004514FE /* ParseKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ParseKit.h; path = include/ParseKit/ParseKit.h; sourceTree = ""; }; + D3C221910FFE8B8C004514FE /* PKTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTypes.h; path = include/ParseKit/PKTypes.h; sourceTree = ""; }; + D3C221960FFE8B95004514FE /* PKReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKReader.h; path = include/ParseKit/PKReader.h; sourceTree = ""; }; + D3C221990FFE8B9D004514FE /* PKAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAssembly.h; path = include/ParseKit/PKAssembly.h; sourceTree = ""; }; + D3C2219C0FFE8BA6004514FE /* PKParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParser.h; path = include/ParseKit/PKParser.h; sourceTree = ""; }; + D3C2219F0FFE8BAE004514FE /* PKRepetition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKRepetition.h; path = include/ParseKit/PKRepetition.h; sourceTree = ""; }; + D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCollectionParser.h; path = include/ParseKit/PKCollectionParser.h; sourceTree = ""; }; + D3C221A50FFE8BC1004514FE /* PKAlternation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAlternation.h; path = include/ParseKit/PKAlternation.h; sourceTree = ""; }; + D3C221A80FFE8BC9004514FE /* PKSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSequence.h; path = include/ParseKit/PKSequence.h; sourceTree = ""; }; + D3C221AB0FFE8BCF004514FE /* PKTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTrack.h; path = include/ParseKit/PKTrack.h; sourceTree = ""; }; + D3C221AE0FFE8BD4004514FE /* PKTrackException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTrackException.h; path = include/ParseKit/PKTrackException.h; sourceTree = ""; }; + D3C221B10FFE8BDB004514FE /* PKIntersection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKIntersection.h; path = include/ParseKit/PKIntersection.h; sourceTree = ""; }; + D3C221B40FFE8BE2004514FE /* PKDifference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDifference.h; path = include/ParseKit/PKDifference.h; sourceTree = ""; }; + D3C221B70FFE8BE8004514FE /* PKNegation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKNegation.h; path = include/ParseKit/PKNegation.h; sourceTree = ""; }; + D3C221BA0FFE8BEF004514FE /* PKTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTerminal.h; path = include/ParseKit/PKTerminal.h; sourceTree = ""; }; + D3C221BD0FFE8BF7004514FE /* PKEmpty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKEmpty.h; path = include/ParseKit/PKEmpty.h; sourceTree = ""; }; + D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenAssembly.h; path = include/ParseKit/PKTokenAssembly.h; sourceTree = ""; }; + D3C221C30FFE8C07004514FE /* PKToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKToken.h; path = include/ParseKit/PKToken.h; sourceTree = ""; }; + D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenArraySource.h; path = include/ParseKit/PKTokenArraySource.h; sourceTree = ""; }; + D3C221C90FFE8C15004514FE /* PKTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenizer.h; path = include/ParseKit/PKTokenizer.h; sourceTree = ""; }; + D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKTokenizerState.h; path = include/ParseKit/PKTokenizerState.h; sourceTree = ""; }; + D3C221CF0FFE8C24004514FE /* PKNumberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKNumberState.h; path = include/ParseKit/PKNumberState.h; sourceTree = ""; }; + D3C221D50FFE8C35004514FE /* PKSymbolState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbolState.h; path = include/ParseKit/PKSymbolState.h; sourceTree = ""; }; + D3C221D80FFE8C3D004514FE /* PKWordState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWordState.h; path = include/ParseKit/PKWordState.h; sourceTree = ""; }; + D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWhitespaceState.h; path = include/ParseKit/PKWhitespaceState.h; sourceTree = ""; }; + D3C221DE0FFE8C49004514FE /* PKDelimitState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDelimitState.h; path = include/ParseKit/PKDelimitState.h; sourceTree = ""; }; + D3C221E10FFE8C4E004514FE /* PKCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCommentState.h; path = include/ParseKit/PKCommentState.h; sourceTree = ""; }; + D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSingleLineCommentState.h; path = include/ParseKit/PKSingleLineCommentState.h; sourceTree = ""; }; + D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKMultiLineCommentState.h; path = include/ParseKit/PKMultiLineCommentState.h; sourceTree = ""; }; + D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbolNode.h; path = include/ParseKit/PKSymbolNode.h; sourceTree = ""; }; + D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbolRootNode.h; path = include/ParseKit/PKSymbolRootNode.h; sourceTree = ""; }; + D3C221F00FFE8C7A004514FE /* PKPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKPattern.h; path = include/ParseKit/PKPattern.h; sourceTree = ""; }; + D3C221F30FFE8C87004514FE /* PKWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWord.h; path = include/ParseKit/PKWord.h; sourceTree = ""; }; + D3C221F60FFE8C8E004514FE /* PKNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKNumber.h; path = include/ParseKit/PKNumber.h; sourceTree = ""; }; + D3C221F90FFE8C97004514FE /* PKQuotedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKQuotedString.h; path = include/ParseKit/PKQuotedString.h; sourceTree = ""; }; + D3C221FC0FFE8CB2004514FE /* PKSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSymbol.h; path = include/ParseKit/PKSymbol.h; sourceTree = ""; }; + D3C221FF0FFE8CB9004514FE /* PKLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKLiteral.h; path = include/ParseKit/PKLiteral.h; sourceTree = ""; }; + D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCaseInsensitiveLiteral.h; path = include/ParseKit/PKCaseInsensitiveLiteral.h; sourceTree = ""; }; + D3C222050FFE8CCA004514FE /* PKWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKWhitespace.h; path = include/ParseKit/PKWhitespace.h; sourceTree = ""; }; + D3C222080FFE8CD1004514FE /* PKComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKComment.h; path = include/ParseKit/PKComment.h; sourceTree = ""; }; + D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDelimitedString.h; path = include/ParseKit/PKDelimitedString.h; sourceTree = ""; }; + D3C2220E0FFE8CDF004514FE /* PKAny.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKAny.h; path = include/ParseKit/PKAny.h; sourceTree = ""; }; + D3C222140FFE8D01004514FE /* PKLowercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKLowercaseWord.h; path = include/ParseKit/PKLowercaseWord.h; sourceTree = ""; }; + D3C222170FFE8D11004514FE /* PKUppercaseWord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKUppercaseWord.h; path = include/ParseKit/PKUppercaseWord.h; sourceTree = ""; }; + D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKCharacterAssembly.h; path = include/ParseKit/PKCharacterAssembly.h; sourceTree = ""; }; + D3C2221D0FFE8D3B004514FE /* PKChar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKChar.h; path = include/ParseKit/PKChar.h; sourceTree = ""; }; + D3C222200FFE8D42004514FE /* PKDigit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKDigit.h; path = include/ParseKit/PKDigit.h; sourceTree = ""; }; + D3C222230FFE8D49004514FE /* PKLetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKLetter.h; path = include/ParseKit/PKLetter.h; sourceTree = ""; }; + D3C222260FFE8D6B004514FE /* PKSpecificChar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKSpecificChar.h; path = include/ParseKit/PKSpecificChar.h; sourceTree = ""; }; + D3C222290FFE8DAC004514FE /* PKParserFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParserFactory.h; path = include/ParseKit/PKParserFactory.h; sourceTree = ""; }; + D3C7D87A0A411FBF005DD154 /* Tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; + D3C85C790E63B438000445FD /* TDArithmeticParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDArithmeticParser.h; path = test/TDArithmeticParser.h; sourceTree = ""; }; + D3C85C7A0E63B438000445FD /* TDArithmeticParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDArithmeticParser.m; path = test/TDArithmeticParser.m; sourceTree = ""; }; + D3C85C7E0E63B9E9000445FD /* TDArithmeticParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDArithmeticParserTest.h; path = test/TDArithmeticParserTest.h; sourceTree = ""; }; + D3C85C7F0E63B9E9000445FD /* TDArithmeticParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDArithmeticParserTest.m; path = test/TDArithmeticParserTest.m; sourceTree = ""; }; + D3C85D430E63D1BF000445FD /* TDScientificNumberStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDScientificNumberStateTest.h; path = test/TDScientificNumberStateTest.h; sourceTree = ""; }; + D3C85D440E63D1BF000445FD /* TDScientificNumberStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDScientificNumberStateTest.m; path = test/TDScientificNumberStateTest.m; sourceTree = ""; }; + D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json_with_discards.grammar; path = res/json_with_discards.grammar; sourceTree = ""; }; + D3D1BF2610394420003656E5 /* SAXAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SAXAssembler.h; path = test/SAXAssembler.h; sourceTree = ""; }; + D3D1BF2710394420003656E5 /* SAXAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SAXAssembler.m; path = test/SAXAssembler.m; sourceTree = ""; }; + D3D1BF291039445C003656E5 /* SAXTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SAXTest.h; path = test/SAXTest.h; sourceTree = ""; }; + D3D1BF2A1039445C003656E5 /* SAXTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SAXTest.m; path = test/SAXTest.m; sourceTree = ""; }; + D3DCB35C0EF5E52500DE5110 /* OCMock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OCMock.framework; path = frameworks/OCMock.framework; sourceTree = ""; }; + D3DCB4C20EF6015300DE5110 /* json.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json.grammar; path = res/json.grammar; sourceTree = ""; }; + D3DDDA850F0779FD00A58000 /* TDSyntaxHighlighter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSyntaxHighlighter.h; path = test/TDSyntaxHighlighter.h; sourceTree = ""; }; + D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSyntaxHighlighter.m; path = test/TDSyntaxHighlighter.m; sourceTree = ""; }; + D3DDDAFC0F083C9700A58000 /* TDCommentStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDCommentStateTest.h; path = test/TDCommentStateTest.h; sourceTree = ""; }; + D3DDDAFD0F083C9700A58000 /* TDCommentStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDCommentStateTest.m; path = test/TDCommentStateTest.m; sourceTree = ""; }; + D3DDDC230F085C5400A58000 /* TDSlashSlashState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashSlashState.h; path = test/TDSlashSlashState.h; sourceTree = ""; }; + D3DDDC240F085C5400A58000 /* TDSlashSlashState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashSlashState.m; path = test/TDSlashSlashState.m; sourceTree = ""; }; + D3DDDC250F085C5400A58000 /* TDSlashStarState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashStarState.h; path = test/TDSlashStarState.h; sourceTree = ""; }; + D3DDDC260F085C5400A58000 /* TDSlashStarState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashStarState.m; path = test/TDSlashStarState.m; sourceTree = ""; }; + D3DDDC270F085C5400A58000 /* TDSlashState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDSlashState.h; path = test/TDSlashState.h; sourceTree = ""; }; + D3DDDC280F085C5400A58000 /* TDSlashState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDSlashState.m; path = test/TDSlashState.m; sourceTree = ""; }; + D3DDDCAC0F0880D800A58000 /* example1.srgs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = example1.srgs; path = res/example1.srgs; sourceTree = ""; }; + D3E39C3D0FC5FFD10022DAB9 /* TDDelimitStateTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDDelimitStateTest.h; path = test/TDDelimitStateTest.h; sourceTree = ""; }; + D3E39C3E0FC5FFD10022DAB9 /* TDDelimitStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDDelimitStateTest.m; path = test/TDDelimitStateTest.m; sourceTree = ""; }; + D3E784BC0E53DA28008C7D61 /* apple-boss.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "apple-boss.json"; path = "res/apple-boss.json"; sourceTree = ""; }; + D3E788910E567DFD008C7D61 /* SRGSParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SRGSParserTest.h; path = test/SRGSParserTest.h; sourceTree = ""; }; + D3E788920E567DFD008C7D61 /* SRGSParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SRGSParserTest.m; path = test/SRGSParserTest.m; sourceTree = ""; }; + D3E788940E567E0A008C7D61 /* SRGSParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SRGSParser.h; path = test/SRGSParser.h; sourceTree = ""; }; + D3E788950E567E0A008C7D61 /* SRGSParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SRGSParser.m; path = test/SRGSParser.m; sourceTree = ""; }; + D3E78A150E574C99008C7D61 /* EBNFParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EBNFParser.h; path = test/EBNFParser.h; sourceTree = ""; }; + D3E78A160E574C99008C7D61 /* EBNFParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EBNFParser.m; path = test/EBNFParser.m; sourceTree = ""; }; + D3E78A170E574C99008C7D61 /* EBNFParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EBNFParserTest.h; path = test/EBNFParserTest.h; sourceTree = ""; }; + D3E78A180E574C99008C7D61 /* EBNFParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EBNFParserTest.m; path = test/EBNFParserTest.m; sourceTree = ""; }; + D3EADD7F0E75E9CC00F78584 /* nasty.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = nasty.html; path = res/nasty.html; sourceTree = ""; }; + D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDHtmlSyntaxHighlighter.m; path = test/TDHtmlSyntaxHighlighter.m; sourceTree = ""; }; + D3EADD8D0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDHtmlSyntaxHighlighter.h; path = test/TDHtmlSyntaxHighlighter.h; sourceTree = ""; }; + D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKQuoteState.h; path = include/ParseKit/PKQuoteState.h; sourceTree = ""; }; + D3F0E3290FFEA1E200C9DF74 /* DebugApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "DebugApp-Info.plist"; sourceTree = ""; }; + D3F0E3600FFEA2B500C9DF74 /* DemoApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "DemoApp-Info.plist"; path = "demoapp/DemoApp-Info.plist"; sourceTree = ""; }; + D3F0E36C0FFEA33700C9DF74 /* Tests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Tests-Info.plist"; path = "test/Tests-Info.plist"; sourceTree = ""; }; + D3F0E37A0FFEA39000C9DF74 /* JSDemoApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "JSDemoApp-Info.plist"; path = "jsdemoapp/JSDemoApp-Info.plist"; sourceTree = ""; }; + D3F55F5F1025737D00DD6DB1 /* TDParseTreeTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDParseTreeTest.h; path = test/TDParseTreeTest.h; sourceTree = ""; }; + D3F55F601025737D00DD6DB1 /* TDParseTreeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDParseTreeTest.m; path = test/TDParseTreeTest.m; sourceTree = ""; }; + D3F5629810266CFC00DD6DB1 /* PKParseTreeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKParseTreeView.h; path = demoapp/PKParseTreeView.h; sourceTree = ""; }; + D3F5629910266CFC00DD6DB1 /* PKParseTreeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKParseTreeView.m; path = demoapp/PKParseTreeView.m; sourceTree = ""; }; + D3F5629E10266DFB00DD6DB1 /* DemoTokensViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DemoTokensViewController.h; path = demoapp/DemoTokensViewController.h; sourceTree = ""; }; + D3F5629F10266DFB00DD6DB1 /* DemoTokensViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DemoTokensViewController.m; path = demoapp/DemoTokensViewController.m; sourceTree = ""; }; + D3F562A110266E5300DD6DB1 /* TokensView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = TokensView.xib; path = demoapp/TokensView.xib; sourceTree = ""; }; + D3F562A310266E6300DD6DB1 /* TreesView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = TreesView.xib; path = demoapp/TreesView.xib; sourceTree = ""; }; + D3F562A510266E8D00DD6DB1 /* DemoTreesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DemoTreesViewController.h; path = demoapp/DemoTreesViewController.h; sourceTree = ""; }; + D3F562A610266E8D00DD6DB1 /* DemoTreesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DemoTreesViewController.m; path = demoapp/DemoTreesViewController.m; sourceTree = ""; }; + D3F740B50EF8C38A00559B9F /* JSONAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONAssembler.h; sourceTree = ""; }; + D3F740B60EF8C38A00559B9F /* JSONAssembler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONAssembler.m; sourceTree = ""; }; + D3F741430EF8E96A00559B9F /* xpath1_0.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = xpath1_0.grammar; path = res/xpath1_0.grammar; sourceTree = ""; }; + D3F741BD0EF9F28D00559B9F /* css2_1.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = css2_1.grammar; path = res/css2_1.grammar; sourceTree = ""; }; + D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = rubyhash.grammar; path = res/rubyhash.grammar; sourceTree = ""; }; + D3FDC5830FFC4BFC00F1F797 /* libparsekit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libparsekit.a; sourceTree = BUILT_PRODUCTS_DIR; }; + D3FDC7360FFC4D6100F1F797 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + D3FDC7380FFC4D6100F1F797 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; }; + D3FDC74B0FFC4DAC00F1F797 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + D3FDC8DB0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseKitMobile_Prefix.pch; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DC2EF560486A6940098B216 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3E787A30E5661A9008C7D61 /* Foundation.framework in Frameworks */, + D36C560C0FD363D500141CB7 /* libicucore.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D334940E0E2963FD00406085 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D33494720E29670B00406085 /* ParseKit.framework in Frameworks */, + D37D3A000FE77A71008C2E4D /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D34185020E520D3F0081B0DC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D31FE7380E60F36600A0803E /* libxml2.dylib in Frameworks */, + D341850C0E520D640081B0DC /* ParseKit.framework in Frameworks */, + D380B9800F0EF3860009EC13 /* OCMock.framework in Frameworks */, + D380BAA30F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */, + D37D3A010FE77A72008C2E4D /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1CC0F1965E600558235 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F34E0F197DF500558235 /* JavaScriptCore.framework in Frameworks */, + D389F1D50F19666500558235 /* ParseKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F2010F196A7500558235 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F3430F197DDC00558235 /* JavaScriptCore.framework in Frameworks */, + D389F20E0F196A9200558235 /* WebKit.framework in Frameworks */, + D389F20C0F196A9200558235 /* ParseKit.framework in Frameworks */, + D389F20B0F196A9200558235 /* JSParseKit.framework in Frameworks */, + D37D3A020FE77A77008C2E4D /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3C7D8770A411FBF005DD154 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3DCB37D0EF5E5E400DE5110 /* OCMock.framework in Frameworks */, + D3C7D9DA0A412874005DD154 /* ParseKit.framework in Frameworks */, + D36E9F870E5A795400496BD3 /* libxml2.dylib in Frameworks */, + D380BAA40F0F1D980009EC13 /* JavaScriptCore.framework in Frameworks */, + D3587EAF0FE83EC900DDD023 /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3FDC5810FFC4BFC00F1F797 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3FDC7370FFC4D6100F1F797 /* Foundation.framework in Frameworks */, + D3FDC7390FFC4D6100F1F797 /* libicucore.dylib in Frameworks */, + D3FDC74C0FFC4DAC00F1F797 /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 034768DFFF38A50411DB9C8B /* Products */ = { + isa = PBXGroup; + children = ( + 8DC2EF5B0486A6940098B216 /* ParseKit.framework */, + D389F1CE0F1965E600558235 /* JSParseKit.framework */, + D3C7D87A0A411FBF005DD154 /* Tests.octest */, + D33494100E2963FD00406085 /* DemoApp.app */, + D34185040E520D3F0081B0DC /* DebugApp.app */, + D389F2030F196A7500558235 /* JSDemoApp.app */, + D3FDC5830FFC4BFC00F1F797 /* libparsekit.a */, + ); + name = Products; + sourceTree = ""; + }; + 0867D691FE84028FC02AAC07 /* TODParseKit */ = { + isa = PBXGroup; + children = ( + 08FB77AEFE84172EC02AAC07 /* ParseKit Framework */, + D3C7D8220A411F31005DD154 /* ParseKit Tests */, + D36E98CB0E58C08F00496BD3 /* DebugApp */, + D334941B0E29641300406085 /* DemoApp */, + D380BA950F0F1C450009EC13 /* JSParseKit Framework */, + D389F2CA0F196ACF00558235 /* JSDemoApp */, + D3AF4C8E0FDC738B0032F4DC /* Other Sources */, + 32C88DFF0371C24200C91783 /* Other Sources (not used) */, + 089C1665FE841158C02AAC07 /* Resources */, + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */, + 034768DFFF38A50411DB9C8B /* Products */, + ); + name = TODParseKit; + sourceTree = ""; + }; + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + D3FDC8EF0FFC52CD00F1F797 /* Mobile Frameworks */, + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */, + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 089C1665FE841158C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + 8DC2EF5A0486A6940098B216 /* Info.plist */, + 089C1666FE841158C02AAC07 /* InfoPlist.strings */, + ); + name = Resources; + sourceTree = ""; + }; + 08FB77AEFE84172EC02AAC07 /* ParseKit Framework */ = { + isa = PBXGroup; + children = ( + D3C221900FFE8B8C004514FE /* ParseKit.h */, + D3C221910FFE8B8C004514FE /* PKTypes.h */, + D3C7D8710A411F6B005DD154 /* io */, + D3C7D8720A411F81005DD154 /* parse */, + D3C7D8740A411F8E005DD154 /* tokens */, + D3E785F10E550F63008C7D61 /* chars */, + D34BAC0F0FF87ED200D7773A /* grammar */, + ); + name = "ParseKit Framework"; + sourceTree = ""; + }; + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + D389F20D0F196A9200558235 /* WebKit.framework */, + D380BAA20F0F1D980009EC13 /* JavaScriptCore.framework */, + D3DCB35C0EF5E52500DE5110 /* OCMock.framework */, + D36E9F860E5A795400496BD3 /* libxml2.dylib */, + D36C560B0FD363D500141CB7 /* libicucore.dylib */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 0867D6A5FE840307C02AAC07 /* AppKit.framework */, + 0867D69BFE84028FC02AAC07 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 32C88DFF0371C24200C91783 /* Other Sources (not used) */ = { + isa = PBXGroup; + children = ( + D3C2216D0FFE8A86004514FE /* PKExclusion.h */, + D31270F80FFE898300CBF4C4 /* PKExclusion.m */, + D3AF4CCB0FDC74540032F4DC /* Whitespace */, + D3AF4CCA0FDC74490032F4DC /* Slash */, + D3AF4CC90FDC743C0032F4DC /* ReservedWord */, + D3AF4CC80FDC74320032F4DC /* Blob */, + ); + name = "Other Sources (not used)"; + sourceTree = ""; + }; + D318EAE30E2FD5B6009F47DF /* json */ = { + isa = PBXGroup; + children = ( + D3E784BC0E53DA28008C7D61 /* apple-boss.json */, + D3B473840E48C9CF008AFBDD /* yahoo.json */, + D389F5B20F19C76A00558235 /* TDJsonParser.h */, + D389F5B30F19C76A00558235 /* TDJsonParser.m */, + D389F5B40F19C76A00558235 /* TDJsonParserTest.h */, + D389F5B50F19C76A00558235 /* TDJsonParserTest.m */, + D31FE5A10E60E5D500A0803E /* TDFastJsonParser.h */, + D31FE5A20E60E5D500A0803E /* TDFastJsonParser.m */, + D31FE5A30E60E5D500A0803E /* TDFastJsonParserTest.h */, + D31FE5A40E60E5D500A0803E /* TDFastJsonParserTest.m */, + ); + name = json; + sourceTree = ""; + }; + D31A164F0F703899002AFDF1 /* javascript */ = { + isa = PBXGroup; + children = ( + D31A16500F7038C2002AFDF1 /* TDJavaScriptParser.h */, + D31A16510F7038C2002AFDF1 /* TDJavaScriptParser.m */, + D3B43FB50F76E99C0072AF40 /* TDJavaScriptParserTest.h */, + D3B43FB60F76E99C0072AF40 /* TDJavaScriptParserTest.m */, + ); + name = javascript; + sourceTree = ""; + }; + D3252F670FCE171D005EF059 /* predicate */ = { + isa = PBXGroup; + children = ( + D355C62B0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.h */, + D355C62C0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m */, + D355C62F0FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.h */, + D355C6300FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m */, + D35384EC0FE9691100926552 /* nspredicate.grammar */, + D3252F7C0FCE1A87005EF059 /* TDNSPredicateBuilder.h */, + D3252F7D0FCE1A87005EF059 /* TDNSPredicateBuilder.m */, + D3252F780FCE1A7E005EF059 /* TDNSPredicateBuilderTest.h */, + D3252F790FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m */, + D3385FD70FCFB1FF003BF729 /* TDPredicateEvaluator.h */, + D3385FD80FCFB1FF003BF729 /* TDPredicateEvaluator.m */, + D3385FDB0FCFB227003BF729 /* TDPredicateEvaluatorTest.h */, + D3385FDC0FCFB227003BF729 /* TDPredicateEvaluatorTest.m */, + ); + name = predicate; + sourceTree = ""; + }; + D3305C52102F5BB300DC4F75 /* Trees */ = { + isa = PBXGroup; + children = ( + D3F562A310266E6300DD6DB1 /* TreesView.xib */, + D3F562A510266E8D00DD6DB1 /* DemoTreesViewController.h */, + D3F562A610266E8D00DD6DB1 /* DemoTreesViewController.m */, + D3F5629810266CFC00DD6DB1 /* PKParseTreeView.h */, + D3F5629910266CFC00DD6DB1 /* PKParseTreeView.m */, + D3305C53102F5BC500DC4F75 /* SourceCodeView */, + ); + name = Trees; + sourceTree = ""; + }; + D3305C53102F5BC500DC4F75 /* SourceCodeView */ = { + isa = PBXGroup; + children = ( + D3305C4B102F5BAD00DC4F75 /* TDGutterView.h */, + D3305C4C102F5BAD00DC4F75 /* TDGutterView.m */, + D3305C4D102F5BAE00DC4F75 /* TDSourceCodeTextView.h */, + D3305C4E102F5BAE00DC4F75 /* TDSourceCodeTextView.m */, + ); + name = SourceCodeView; + sourceTree = ""; + }; + D3305C54102F5BE500DC4F75 /* Tokens */ = { + isa = PBXGroup; + children = ( + D3F562A110266E5300DD6DB1 /* TokensView.xib */, + D3F5629E10266DFB00DD6DB1 /* DemoTokensViewController.h */, + D3F5629F10266DFB00DD6DB1 /* DemoTokensViewController.m */, + ); + name = Tokens; + sourceTree = ""; + }; + D334941B0E29641300406085 /* DemoApp */ = { + isa = PBXGroup; + children = ( + D3F0E3600FFEA2B500C9DF74 /* DemoApp-Info.plist */, + D36E98F70E58C1A000496BD3 /* DemoAppMainMenu.xib */, + D36E98E50E58C14000496BD3 /* main.m */, + D36E98E30E58C14000496BD3 /* DemoAppDelegate.h */, + D36E98E40E58C14000496BD3 /* DemoAppDelegate.m */, + D3305C54102F5BE500DC4F75 /* Tokens */, + D3305C52102F5BB300DC4F75 /* Trees */, + ); + name = DemoApp; + sourceTree = ""; + }; + D3376D1110091C6C00E4602E /* ParseTree */ = { + isa = PBXGroup; + children = ( + D3F55F5F1025737D00DD6DB1 /* TDParseTreeTest.h */, + D3F55F601025737D00DD6DB1 /* TDParseTreeTest.m */, + ); + name = ParseTree; + sourceTree = ""; + }; + D3376D7710096BDE00E4602E /* IR */ = { + isa = PBXGroup; + children = ( + D3F5619C1026374400DD6DB1 /* ir */, + D3376D1110091C6C00E4602E /* ParseTree */, + D3376D8B10096BEF00E4602E /* Homo */, + ); + name = IR; + sourceTree = ""; + }; + D3376D8B10096BEF00E4602E /* Homo */ = { + isa = PBXGroup; + children = ( + D3376D8C10096C0700E4602E /* PKAST.h */, + D3376D8D10096C0700E4602E /* PKAST.m */, + ); + name = Homo; + sourceTree = ""; + }; + D341846A0E5209A60081B0DC /* tokenizer */ = { + isa = PBXGroup; + children = ( + D3C221C30FFE8C07004514FE /* PKToken.h */, + D34BAE950FF9D20900D7773A /* PKToken.m */, + D3C221C60FFE8C0D004514FE /* PKTokenArraySource.h */, + D34BAE970FF9D20900D7773A /* PKTokenArraySource.m */, + D3C221C90FFE8C15004514FE /* PKTokenizer.h */, + D34BAE990FF9D20900D7773A /* PKTokenizer.m */, + D3C221CC0FFE8C1B004514FE /* PKTokenizerState.h */, + D34BAE9B0FF9D20900D7773A /* PKTokenizerState.m */, + ); + name = tokenizer; + sourceTree = ""; + }; + D34A20080E55FD5F00A4A0BF /* chars */ = { + isa = PBXGroup; + children = ( + D31FE58C0E60E5AC00A0803E /* TDCharacterAssemblyTest.h */, + D31FE58D0E60E5AC00A0803E /* TDCharacterAssemblyTest.m */, + D31FE58E0E60E5AC00A0803E /* TDCharTest.h */, + D31FE58F0E60E5AC00A0803E /* TDCharTest.m */, + D31FE5900E60E5AC00A0803E /* TDDigitTest.h */, + D31FE5910E60E5AC00A0803E /* TDDigitTest.m */, + D31FE5920E60E5AC00A0803E /* TDLetterTest.h */, + D31FE5930E60E5AC00A0803E /* TDLetterTest.m */, + D31FE5940E60E5AC00A0803E /* TDSpecificCharTest.h */, + D31FE5950E60E5AC00A0803E /* TDSpecificCharTest.m */, + ); + name = chars; + sourceTree = ""; + }; + D34BAC0F0FF87ED200D7773A /* grammar */ = { + isa = PBXGroup; + children = ( + D3C222290FFE8DAC004514FE /* PKParserFactory.h */, + D34BAFD80FF9E95500D7773A /* PKParserFactory.m */, + D3376D5710093A1600E4602E /* PKGrammarParser.h */, + D3376D5810093A1600E4602E /* PKGrammarParser.m */, + D34BAFD30FF9E95500D7773A /* NSArray+ParseKitAdditions.h */, + D34BAFD40FF9E95500D7773A /* NSArray+ParseKitAdditions.m */, + D34BAFD50FF9E95500D7773A /* NSString+ParseKitAdditions.h */, + D34BAFD60FF9E95500D7773A /* NSString+ParseKitAdditions.m */, + ); + name = grammar; + sourceTree = ""; + }; + D3541F870DFB105900429B4F /* states */ = { + isa = PBXGroup; + children = ( + D3C221CF0FFE8C24004514FE /* PKNumberState.h */, + D34BAECA0FF9D56400D7773A /* PKNumberState.m */, + D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */, + D34BAECC0FF9D56400D7773A /* PKQuoteState.m */, + D3C221D50FFE8C35004514FE /* PKSymbolState.h */, + D34BAED00FF9D56400D7773A /* PKSymbolState.m */, + D3C221D80FFE8C3D004514FE /* PKWordState.h */, + D34BAED60FF9D56400D7773A /* PKWordState.m */, + D3C221DB0FFE8C43004514FE /* PKWhitespaceState.h */, + D34BAED20FF9D56400D7773A /* PKWhitespaceState.m */, + D3C221DE0FFE8C49004514FE /* PKDelimitState.h */, + D34BAEC60FF9D56400D7773A /* PKDelimitState.m */, + D3C221E10FFE8C4E004514FE /* PKCommentState.h */, + D34BAEC40FF9D56400D7773A /* PKCommentState.m */, + D3C221E40FFE8C56004514FE /* PKSingleLineCommentState.h */, + D34BAECE0FF9D56400D7773A /* PKSingleLineCommentState.m */, + D3C221E70FFE8C60004514FE /* PKMultiLineCommentState.h */, + D34BAEC80FF9D56400D7773A /* PKMultiLineCommentState.m */, + D3541F890DFB108300429B4F /* symbol */, + ); + name = states; + sourceTree = ""; + }; + D3541F890DFB108300429B4F /* symbol */ = { + isa = PBXGroup; + children = ( + D3C221EA0FFE8C69004514FE /* PKSymbolNode.h */, + D34BAF240FF9DF9900D7773A /* PKSymbolNode.m */, + D3C221ED0FFE8C6F004514FE /* PKSymbolRootNode.h */, + D34BAF260FF9DF9900D7773A /* PKSymbolRootNode.m */, + ); + name = symbol; + sourceTree = ""; + }; + D35420EC0DFB275400429B4F /* tokenizer states */ = { + isa = PBXGroup; + children = ( + D34BAD16100A9B7900996341 /* TDTokenizerStateTest.h */, + D34BAD17100A9B7900996341 /* TDTokenizerStateTest.m */, + D31FE5770E60E58C00A0803E /* TDNumberStateTest.h */, + D31FE5780E60E58C00A0803E /* TDNumberStateTest.m */, + D31FE5790E60E58C00A0803E /* TDQuoteStateTest.h */, + D31FE57A0E60E58C00A0803E /* TDQuoteStateTest.m */, + D31FE57F0E60E58C00A0803E /* TDSymbolStateTest.h */, + D31FE5800E60E58C00A0803E /* TDSymbolStateTest.m */, + D31FE5810E60E58C00A0803E /* TDWhitespaceStateTest.h */, + D31FE5820E60E58C00A0803E /* TDWhitespaceStateTest.m */, + D31FE5830E60E58C00A0803E /* TDWordStateTest.h */, + D31FE5840E60E58C00A0803E /* TDWordStateTest.m */, + D3C85D430E63D1BF000445FD /* TDScientificNumberStateTest.h */, + D3C85D440E63D1BF000445FD /* TDScientificNumberStateTest.m */, + D3DDDAFC0F083C9700A58000 /* TDCommentStateTest.h */, + D3DDDAFD0F083C9700A58000 /* TDCommentStateTest.m */, + D3E39C3D0FC5FFD10022DAB9 /* TDDelimitStateTest.h */, + D3E39C3E0FC5FFD10022DAB9 /* TDDelimitStateTest.m */, + ); + name = "tokenizer states"; + sourceTree = ""; + }; + D36568A40EEF9FB600226554 /* plist */ = { + isa = PBXGroup; + children = ( + D36568A50EEF9FE900226554 /* TDPlistParser.h */, + D36568A60EEF9FE900226554 /* TDPlistParser.m */, + D36568A80EEFA05300226554 /* TDPlistParserTest.h */, + D36568A90EEFA05300226554 /* TDPlistParserTest.m */, + ); + name = plist; + sourceTree = ""; + }; + D3668290101D2BAC0008632C /* erb */ = { + isa = PBXGroup; + children = ( + D3668291101D2BFA0008632C /* erb.grammar */, + D3668294101D2C200008632C /* ERBTest.h */, + D3668295101D2C200008632C /* ERBTest.m */, + ); + name = erb; + sourceTree = ""; + }; + D36C55FB0FD3616200141CB7 /* regex */ = { + isa = PBXGroup; + children = ( + D3C221F00FFE8C7A004514FE /* PKPattern.h */, + D34BAF380FF9E18300D7773A /* PKPattern.m */, + D36C55FC0FD3617B00141CB7 /* RegexKitLite.h */, + D36C55FD0FD3617B00141CB7 /* RegexKitLite.m */, + ); + name = regex; + sourceTree = ""; + }; + D36E94F40E57865500496BD3 /* xpath */ = { + isa = PBXGroup; + children = ( + D34BAC490FF892C200D7773A /* XPathParserGrammarTest.h */, + D34BAC4A0FF892C200D7773A /* XPathParserGrammarTest.m */, + D31FE5EF0E60E6B500A0803E /* TDNCName.h */, + D31FE6DF0E60EE2500A0803E /* TDNCName.m */, + D31FE5F00E60E6B500A0803E /* TDNCNameState.h */, + D31FE5F10E60E6B500A0803E /* TDNCNameState.m */, + D36E95440E578ECC00496BD3 /* XPathParser.h */, + D36E95450E578ECC00496BD3 /* XPathParser.m */, + D36E97AE0E589DAE00496BD3 /* XPathAssembler.h */, + D36E97AF0E589DAE00496BD3 /* XPathAssembler.m */, + D36E98200E58A3A800496BD3 /* XPathContext.h */, + D36E98210E58A3A800496BD3 /* XPathContext.m */, + D36E95D60E57B08400496BD3 /* XPathParserTest.h */, + D36E95D70E57B08400496BD3 /* XPathParserTest.m */, + ); + name = xpath; + sourceTree = ""; + }; + D36E98CB0E58C08F00496BD3 /* DebugApp */ = { + isa = PBXGroup; + children = ( + D3F0E3290FFEA1E200C9DF74 /* DebugApp-Info.plist */, + D36E98DF0E58C12800496BD3 /* main.m */, + D36E98DC0E58C12800496BD3 /* DebugAppDelegate.h */, + D36E98DD0E58C12800496BD3 /* DebugAppDelegate.m */, + D3F740B50EF8C38A00559B9F /* JSONAssembler.h */, + D3F740B60EF8C38A00559B9F /* JSONAssembler.m */, + D36E98DE0E58C12800496BD3 /* DebugAppMainMenu.xib */, + ); + name = DebugApp; + path = debugapp; + sourceTree = ""; + }; + D36EA1400E5CF19F00496BD3 /* xml token terminals */ = { + isa = PBXGroup; + children = ( + D31FE5B90E60E69E00A0803E /* TDXmlAttribute.h */, + D31FE5BA0E60E69E00A0803E /* TDXmlAttribute.m */, + D31FE5BB0E60E69E00A0803E /* TDXmlCdata.h */, + D31FE5BC0E60E69E00A0803E /* TDXmlCdata.m */, + D31FE5BD0E60E69E00A0803E /* TDXmlComment.h */, + D31FE5BE0E60E69E00A0803E /* TDXmlComment.m */, + D31FE5BF0E60E69E00A0803E /* TDXmlDecl.h */, + D31FE5C00E60E69E00A0803E /* TDXmlDecl.m */, + D31FE5C10E60E69E00A0803E /* TDXmlDoctype.h */, + D31FE5C20E60E69E00A0803E /* TDXmlDoctype.m */, + D31FE5C30E60E69E00A0803E /* TDXmlDocument.h */, + D31FE5C40E60E69E00A0803E /* TDXmlDocument.m */, + D31FE5C50E60E69E00A0803E /* TDXmlEndEntity.h */, + D31FE5C60E60E69E00A0803E /* TDXmlEndEntity.m */, + D31FE5C70E60E69E00A0803E /* TDXmlEndTag.h */, + D31FE5C80E60E69E00A0803E /* TDXmlEndTag.m */, + D31FE5C90E60E69E00A0803E /* TDXmlEntity.h */, + D31FE5CA0E60E69E00A0803E /* TDXmlEntity.m */, + D31FE5CB0E60E69E00A0803E /* TDXmlEntityRef.h */, + D31FE5CC0E60E69E00A0803E /* TDXmlEntityRef.m */, + D31FE5CD0E60E69E00A0803E /* TDXmlFragment.h */, + D31FE5CE0E60E69E00A0803E /* TDXmlFragment.m */, + D31FE5CF0E60E69E00A0803E /* TDXmlNotation.h */, + D31FE5D00E60E69E00A0803E /* TDXmlNotation.m */, + D31FE5D10E60E69E00A0803E /* TDXmlProcessingInstruction.h */, + D31FE5D20E60E69E00A0803E /* TDXmlProcessingInstruction.m */, + D31FE5D30E60E69E00A0803E /* TDXmlSignificantWhitespace.h */, + D31FE5D40E60E69E00A0803E /* TDXmlSignificantWhitespace.m */, + D31FE5D50E60E69E00A0803E /* TDXmlStartTag.h */, + D31FE5D60E60E69E00A0803E /* TDXmlStartTag.m */, + D31FE5D70E60E69E00A0803E /* TDXmlTerminal.h */, + D31FE5D80E60E69E00A0803E /* TDXmlTerminal.m */, + D31FE5D90E60E69E00A0803E /* TDXmlText.h */, + D31FE5DA0E60E69E00A0803E /* TDXmlText.m */, + D31FE5DB0E60E69E00A0803E /* TDXmlWhitespace.h */, + D31FE5DC0E60E69E00A0803E /* TDXmlWhitespace.m */, + ); + name = "xml token terminals"; + sourceTree = ""; + }; + D36EA1440E5CF38100496BD3 /* tokenizer */ = { + isa = PBXGroup; + children = ( + D31FE5B30E60E66600A0803E /* TDXmlToken.h */, + D31FE5B40E60E66600A0803E /* TDXmlToken.m */, + D31FE5B50E60E66600A0803E /* TDXmlTokenizer.h */, + D31FE5B60E60E66600A0803E /* TDXmlTokenizer.m */, + ); + name = tokenizer; + sourceTree = ""; + }; + D380BA950F0F1C450009EC13 /* JSParseKit Framework */ = { + isa = PBXGroup; + children = ( + D34BB04E0FF9EC4E00D7773A /* JSParseKit-Info.plist */, + D34BB0660FF9EDDF00D7773A /* JSParseKit.h */, + D34BB0670FF9EDDF00D7773A /* JSParseKit.m */, + D34BB06C0FF9EE4000D7773A /* PKJSUtils.h */, + D34BB06D0FF9EE4000D7773A /* PKJSUtils.m */, + D34BB06E0FF9EE4000D7773A /* PKJSUtils_macros.h */, + D34BB06F0FF9EE4000D7773A /* PKJSValueHolder.h */, + D34BB0700FF9EE4000D7773A /* PKJSValueHolder.m */, + D34BB06A0FF9EE4000D7773A /* PKJSAssembly.h */, + D34BB06B0FF9EE4000D7773A /* PKJSAssembly.m */, + D389F8C40F1AC89A00558235 /* Chars */, + D389F59A0F19BBAE00558235 /* Tokens */, + D389F59B0F19BBD300558235 /* Parse */, + ); + name = "JSParseKit Framework"; + sourceTree = ""; + }; + D389A0AE0F1FCC7A003B43BD /* relaxng */ = { + isa = PBXGroup; + children = ( + D389A0B00F1FCC99003B43BD /* RelaxParser.h */, + D389A0B10F1FCC99003B43BD /* RelaxParser.m */, + ); + name = relaxng; + sourceTree = ""; + }; + D389F2CA0F196ACF00558235 /* JSDemoApp */ = { + isa = PBXGroup; + children = ( + D3F0E37A0FFEA39000C9DF74 /* JSDemoApp-Info.plist */, + D389F2E30F196CAE00558235 /* main.m */, + D389F2E80F196F5B00558235 /* JSDemoAppDelegate.h */, + D389F2E90F196F5B00558235 /* JSDemoAppDelegate.m */, + D389F38E0F19800400558235 /* DefaultValues.plist */, + D389F4610F198A8800558235 /* Test.html */, + D389FBCC0F1B25E200558235 /* ParserTest.html */, + D389F5580F19B7BC00558235 /* JSDemoAppMainMenu.xib */, + ); + name = JSDemoApp; + sourceTree = ""; + }; + D389F59A0F19BBAE00558235 /* Tokens */ = { + isa = PBXGroup; + children = ( + D34BB0930FF9F14B00D7773A /* PKJSCommentState.h */, + D34BB0940FF9F14B00D7773A /* PKJSCommentState.m */, + D34BB0950FF9F14B00D7773A /* PKJSDelimitState.h */, + D34BB0960FF9F14B00D7773A /* PKJSDelimitState.m */, + D34BB0970FF9F14B00D7773A /* PKJSNumberState.h */, + D34BB0980FF9F14B00D7773A /* PKJSNumberState.m */, + D34BB0990FF9F14B00D7773A /* PKJSQuoteState.h */, + D34BB09A0FF9F14B00D7773A /* PKJSQuoteState.m */, + D34BB09B0FF9F14B00D7773A /* PKJSSymbolState.h */, + D34BB09C0FF9F14B00D7773A /* PKJSSymbolState.m */, + D34BB09D0FF9F14B00D7773A /* PKJSToken.h */, + D34BB09E0FF9F14B00D7773A /* PKJSToken.m */, + D34BB09F0FF9F14B00D7773A /* PKJSTokenAssembly.h */, + D34BB0A00FF9F14B00D7773A /* PKJSTokenAssembly.m */, + D34BB0A10FF9F14B00D7773A /* PKJSTokenizer.h */, + D34BB0A20FF9F14B00D7773A /* PKJSTokenizer.m */, + D34BB0A30FF9F14B00D7773A /* PKJSTokenizerState.h */, + D34BB0A40FF9F14B00D7773A /* PKJSTokenizerState.m */, + D34BB0A50FF9F14B00D7773A /* PKJSWhitespaceState.h */, + D34BB0A60FF9F14B00D7773A /* PKJSWhitespaceState.m */, + D34BB0A70FF9F14B00D7773A /* PKJSWordState.h */, + D34BB0A80FF9F14B00D7773A /* PKJSWordState.m */, + ); + name = Tokens; + sourceTree = ""; + }; + D389F59B0F19BBD300558235 /* Parse */ = { + isa = PBXGroup; + children = ( + D34BB0D20FF9F28000D7773A /* PKJSAlternation.h */, + D34BB0D30FF9F28000D7773A /* PKJSAlternation.m */, + D34BB0D40FF9F28000D7773A /* PKJSAny.h */, + D34BB0D50FF9F28000D7773A /* PKJSAny.m */, + D34BB0D60FF9F28000D7773A /* PKJSAssemblerAdapter.h */, + D34BB0D70FF9F28000D7773A /* PKJSAssemblerAdapter.m */, + D34BB0D80FF9F28000D7773A /* PKJSCollectionParser.h */, + D34BB0D90FF9F28000D7773A /* PKJSCollectionParser.m */, + D34BB0DA0FF9F28000D7773A /* PKJSEmpty.h */, + D34BB0DB0FF9F28000D7773A /* PKJSEmpty.m */, + D34BB0DC0FF9F28000D7773A /* PKJSParser.h */, + D34BB0DD0FF9F28000D7773A /* PKJSParser.m */, + D34BB0DE0FF9F28000D7773A /* PKJSRepetition.h */, + D34BB0DF0FF9F28000D7773A /* PKJSRepetition.m */, + D34BB0E00FF9F28000D7773A /* PKJSSequence.h */, + D34BB0E10FF9F28000D7773A /* PKJSSequence.m */, + D34BB0E20FF9F28000D7773A /* PKJSTerminal.h */, + D34BB0E30FF9F28000D7773A /* PKJSTerminal.m */, + D34BB0E40FF9F28000D7773A /* PKJSTrack.h */, + D34BB0E50FF9F28000D7773A /* PKJSTrack.m */, + D389FAE30F1B1B8F00558235 /* Char Terminals */, + D389FAE20F1B1B7200558235 /* Token Terminals */, + ); + name = Parse; + sourceTree = ""; + }; + D389F8C40F1AC89A00558235 /* Chars */ = { + isa = PBXGroup; + children = ( + D34BB08D0FF9EF9D00D7773A /* PKJSCharacterAssembly.h */, + D34BB08E0FF9EF9D00D7773A /* PKJSCharacterAssembly.m */, + ); + name = Chars; + sourceTree = ""; + }; + D389FAE20F1B1B7200558235 /* Token Terminals */ = { + isa = PBXGroup; + children = ( + D34BB0FE0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h */, + D34BB0FF0FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m */, + D34BB1000FF9F36200D7773A /* PKJSComment.h */, + D34BB1010FF9F36200D7773A /* PKJSComment.m */, + D34BB1020FF9F36200D7773A /* PKJSDelimitedString.h */, + D34BB1030FF9F36200D7773A /* PKJSDelimitedString.m */, + D34BB1040FF9F36200D7773A /* PKJSLiteral.h */, + D34BB1050FF9F36200D7773A /* PKJSLiteral.m */, + D34BB1060FF9F36200D7773A /* PKJSLowercaseWord.h */, + D34BB1070FF9F36200D7773A /* PKJSLowercaseWord.m */, + D34BB1080FF9F36200D7773A /* PKJSNum.h */, + D34BB1090FF9F36200D7773A /* PKJSNum.m */, + D34BB10A0FF9F36200D7773A /* PKJSPattern.h */, + D34BB10B0FF9F36200D7773A /* PKJSPattern.m */, + D34BB10C0FF9F36200D7773A /* PKJSQuotedString.h */, + D34BB10D0FF9F36200D7773A /* PKJSQuotedString.m */, + D34BB10E0FF9F36200D7773A /* PKJSSymbol.h */, + D34BB10F0FF9F36200D7773A /* PKJSSymbol.m */, + D34BB1100FF9F36200D7773A /* PKJSUppercaseWord.h */, + D34BB1110FF9F36200D7773A /* PKJSUppercaseWord.m */, + D34BB1120FF9F36200D7773A /* PKJSWord.h */, + D34BB1130FF9F36200D7773A /* PKJSWord.m */, + ); + name = "Token Terminals"; + sourceTree = ""; + }; + D389FAE30F1B1B8F00558235 /* Char Terminals */ = { + isa = PBXGroup; + children = ( + ); + name = "Char Terminals"; + sourceTree = ""; + }; + D3AF4C8E0FDC738B0032F4DC /* Other Sources */ = { + isa = PBXGroup; + children = ( + D34BAD630FF9C6AE00D7773A /* ParseKit_Prefix.pch */, + D3FDC8DB0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + D3AF4CC80FDC74320032F4DC /* Blob */ = { + isa = PBXGroup; + children = ( + D3AF4BF50FDC40050032F4DC /* TDToken+Blob.h */, + D3AF4BF60FDC40050032F4DC /* TDToken+Blob.m */, + D3AF4BFB0FDC41190032F4DC /* TDTokenizer+BlobState.h */, + D3AF4BFC0FDC41190032F4DC /* TDTokenizer+BlobState.m */, + D3AF4C190FDC568F0032F4DC /* TDBlobState.h */, + D3AF4C1A0FDC568F0032F4DC /* TDBlobState.m */, + D3AF4BE80FDC3DD50032F4DC /* TDBlob.h */, + D3AF4BE90FDC3DD50032F4DC /* TDBlob.m */, + ); + name = Blob; + sourceTree = ""; + }; + D3AF4CC90FDC743C0032F4DC /* ReservedWord */ = { + isa = PBXGroup; + children = ( + D3AF4CC50FDC740A0032F4DC /* TDWordOrReservedState.h */, + D3AF4CC60FDC740A0032F4DC /* TDWordOrReservedState.m */, + D3AF4CBF0FDC740A0032F4DC /* TDNonReservedWord.h */, + D3AF4CC00FDC740A0032F4DC /* TDNonReservedWord.m */, + D3AF4CC10FDC740A0032F4DC /* TDReservedWord.h */, + D3AF4CC20FDC740A0032F4DC /* TDReservedWord.m */, + ); + name = ReservedWord; + sourceTree = ""; + }; + D3AF4CCA0FDC74490032F4DC /* Slash */ = { + isa = PBXGroup; + children = ( + D3DDDC230F085C5400A58000 /* TDSlashSlashState.h */, + D3DDDC240F085C5400A58000 /* TDSlashSlashState.m */, + D3DDDC250F085C5400A58000 /* TDSlashStarState.h */, + D3DDDC260F085C5400A58000 /* TDSlashStarState.m */, + D3DDDC270F085C5400A58000 /* TDSlashState.h */, + D3DDDC280F085C5400A58000 /* TDSlashState.m */, + D31FE57D0E60E58C00A0803E /* TDSlashStateTest.h */, + D31FE57E0E60E58C00A0803E /* TDSlashStateTest.m */, + ); + name = Slash; + sourceTree = ""; + }; + D3AF4CCB0FDC74540032F4DC /* Whitespace */ = { + isa = PBXGroup; + children = ( + D3AF4CC30FDC740A0032F4DC /* TDSignificantWhitespaceState.h */, + D3AF4CC40FDC740A0032F4DC /* TDSignificantWhitespaceState.m */, + D31FE57B0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.h */, + D31FE57C0E60E58C00A0803E /* TDSignificantWhitespaceStateTest.m */, + ); + name = Whitespace; + sourceTree = ""; + }; + D3BBBC9A0FEC9739007DF30D /* old */ = { + isa = PBXGroup; + children = ( + D36EA3AF0E5EA67E00496BD3 /* small-xml-file.xml */, + D36E9FB40E5A944A00496BD3 /* apple-boss.xml */, + D31FE5AD0E60E64900A0803E /* TDXmlTokenAssembly.h */, + D31FE5AE0E60E64900A0803E /* TDXmlTokenAssembly.m */, + D31FE5AF0E60E64900A0803E /* TDXmlTokenizerTest.h */, + D31FE5B00E60E64900A0803E /* TDXmlTokenizerTest.m */, + D36EA1440E5CF38100496BD3 /* tokenizer */, + D36EA1400E5CF19F00496BD3 /* xml token terminals */, + D3521F520E5FA1B0009681F9 /* XMLReader.h */, + D3521F530E5FA1B0009681F9 /* XMLReader.m */, + D3521F540E5FA1B0009681F9 /* XMLReaderTest.h */, + D3521F550E5FA1B0009681F9 /* XMLReaderTest.m */, + D31FE5F20E60E6B500A0803E /* TDXmlName.h */, + D31FE5F30E60E6B500A0803E /* TDXmlName.m */, + D31FE5F40E60E6B500A0803E /* TDXmlNameState.h */, + D31FE5F50E60E6B500A0803E /* TDXmlNameState.m */, + D31FE5F60E60E6B500A0803E /* TDXmlNameTest.h */, + D31FE5F70E60E6B500A0803E /* TDXmlNameTest.m */, + D31FE5F80E60E6B500A0803E /* TDXmlNmtoken.h */, + D31FE5F90E60E6B500A0803E /* TDXmlNmtoken.m */, + D31FE5FA0E60E6B500A0803E /* TDXmlNmtokenState.h */, + D31FE5FB0E60E6B500A0803E /* TDXmlNmtokenState.m */, + ); + name = old; + sourceTree = ""; + }; + D3C0309C0EF34DD200C5ABEB /* grammar */ = { + isa = PBXGroup; + children = ( + D380B5370F0D7DDE0009EC13 /* css.css */, + D380B5080F0D71A90009EC13 /* css.grammar */, + D380B5930F0D82F60009EC13 /* example.css */, + D380AFBB0F0C54B60009EC13 /* html.css */, + D380AFBC0F0C54B60009EC13 /* html.grammar */, + D385FD6B0F05A99900DB2946 /* mini_css.grammar */, + D3DCB4C20EF6015300DE5110 /* json.grammar */, + D385FA240F04993500DB2946 /* json.css */, + D383498A0F0C0CF30055E4E0 /* json_with_comments.grammar */, + D38349BB0F0C0D910055E4E0 /* json_with_comments.css */, + D3834A470F0C14B60055E4E0 /* yahoo_with_comments.json */, + D3FD791F0F4CC86800BAD816 /* rubyhash.grammar */, + D380AFC20F0C56000009EC13 /* example.html */, + D3F741BD0EF9F28D00559B9F /* css2_1.grammar */, + D3F741430EF8E96A00559B9F /* xpath1_0.grammar */, + D3D01CA90EFDB89900C24DDE /* json_with_discards.grammar */, + D31A15250F6DE449002AFDF1 /* javascript.grammar */, + D385FD400F05A88C00DB2946 /* TDMiniCSSAssembler.h */, + D385FD410F05A88C00DB2946 /* TDMiniCSSAssembler.m */, + D385FD420F05A88C00DB2946 /* TDMiniCSSAssemblerTest.h */, + D385FD430F05A88C00DB2946 /* TDMiniCSSAssemblerTest.m */, + D385F9880F046FE900DB2946 /* TDGenericAssembler.h */, + D385F9890F046FE900DB2946 /* TDGenericAssembler.m */, + D385FA210F04971400DB2946 /* TDGenericAssemblerTest.h */, + D385FA220F04971400DB2946 /* TDGenericAssemblerTest.m */, + D3DDDA850F0779FD00A58000 /* TDSyntaxHighlighter.h */, + D3DDDA860F0779FD00A58000 /* TDSyntaxHighlighter.m */, + D353899B0FEAC94400926552 /* c.grammar */, + D353899D0FEAC96B00926552 /* objc.grammar */, + D355C8830FEB4B94006A91A4 /* proto.grammar */, + ); + name = grammar; + sourceTree = ""; + }; + D3C7D8220A411F31005DD154 /* ParseKit Tests */ = { + isa = PBXGroup; + children = ( + D3F0E36C0FFEA33700C9DF74 /* Tests-Info.plist */, + D31FE54A0E60E46100A0803E /* TDTestScaffold.h */, + D31FE54B0E60E46100A0803E /* TDTestScaffold.m */, + D3376D7710096BDE00E4602E /* IR */, + D3F823560F57859900B7DC48 /* factory */, + D3C0309C0EF34DD200C5ABEB /* grammar */, + D3252F670FCE171D005EF059 /* predicate */, + D31A164F0F703899002AFDF1 /* javascript */, + D3D63F570E2A8548009BF5CD /* parse */, + D3D63F560E2A8538009BF5CD /* tokens */, + D34A20080E55FD5F00A4A0BF /* chars */, + D3C85C770E63B400000445FD /* arithmetic */, + D3E786030E5510AE008C7D61 /* regex */, + D3E788890E567B6D008C7D61 /* ebnf */, + D36568A40EEF9FB600226554 /* plist */, + D318EAE30E2FD5B6009F47DF /* json */, + D3D647CE0E2C7569009BF5CD /* xml */, + D36E94F40E57865500496BD3 /* xpath */, + D3E788900E567DDA008C7D61 /* srgs */, + D389A0AE0F1FCC7A003B43BD /* relaxng */, + D3C863240E67C249000445FD /* syntax highlight */, + D3668290101D2BAC0008632C /* erb */, + ); + name = "ParseKit Tests"; + sourceTree = ""; + }; + D3C7D8710A411F6B005DD154 /* io */ = { + isa = PBXGroup; + children = ( + D3C221960FFE8B95004514FE /* PKReader.h */, + D34BAD9B0FF9C95800D7773A /* PKReader.m */, + ); + name = io; + sourceTree = ""; + }; + D3C7D8720A411F81005DD154 /* parse */ = { + isa = PBXGroup; + children = ( + D3C221990FFE8B9D004514FE /* PKAssembly.h */, + D34BADA00FF9C9B000D7773A /* PKAssembly.m */, + D3D63EA90E2A7A5C009BF5CD /* parsers */, + ); + name = parse; + sourceTree = ""; + }; + D3C7D8740A411F8E005DD154 /* tokens */ = { + isa = PBXGroup; + children = ( + D3C221C00FFE8BFF004514FE /* PKTokenAssembly.h */, + D34BAE8B0FF9D15100D7773A /* PKTokenAssembly.m */, + D341846A0E5209A60081B0DC /* tokenizer */, + D3541F870DFB105900429B4F /* states */, + D3D642270E2AC426009BF5CD /* token terminals */, + ); + name = tokens; + sourceTree = ""; + }; + D3C85C770E63B400000445FD /* arithmetic */ = { + isa = PBXGroup; + children = ( + D319E429106D8A1F008C63DD /* arithmetic.grammar */, + D319E42C106D8A31008C63DD /* TDArithmeticAssembler.h */, + D319E42D106D8A31008C63DD /* TDArithmeticAssembler.m */, + D3C85C790E63B438000445FD /* TDArithmeticParser.h */, + D3C85C7A0E63B438000445FD /* TDArithmeticParser.m */, + D3C85C7E0E63B9E9000445FD /* TDArithmeticParserTest.h */, + D3C85C7F0E63B9E9000445FD /* TDArithmeticParserTest.m */, + ); + name = arithmetic; + sourceTree = ""; + }; + D3C863240E67C249000445FD /* syntax highlight */ = { + isa = PBXGroup; + children = ( + D3C863250E67C255000445FD /* html */, + ); + name = "syntax highlight"; + sourceTree = ""; + }; + D3C863250E67C255000445FD /* html */ = { + isa = PBXGroup; + children = ( + D38DD9E70EC29F260070BC4D /* nyt.html */, + D3B69D310E80249900D70C41 /* nonascii.html */, + D3EADD7F0E75E9CC00F78584 /* nasty.html */, + D3EADD8D0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.h */, + D3EADD8C0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m */, + ); + name = html; + sourceTree = ""; + }; + D3D63EA90E2A7A5C009BF5CD /* parsers */ = { + isa = PBXGroup; + children = ( + D3C2219C0FFE8BA6004514FE /* PKParser.h */, + D34BADD60FF9CBFB00D7773A /* PKParser.m */, + D3C2219F0FFE8BAE004514FE /* PKRepetition.h */, + D34BAE130FF9CE0E00D7773A /* PKRepetition.m */, + D3C221A20FFE8BBA004514FE /* PKCollectionParser.h */, + D34BAE010FF9CCAE00D7773A /* PKCollectionParser.m */, + D3C221A50FFE8BC1004514FE /* PKAlternation.h */, + D34BAE0B0FF9CE0E00D7773A /* PKAlternation.m */, + D3C221A80FFE8BC9004514FE /* PKSequence.h */, + D34BAE150FF9CE0E00D7773A /* PKSequence.m */, + D3C221AB0FFE8BCF004514FE /* PKTrack.h */, + D34BAE190FF9CE0E00D7773A /* PKTrack.m */, + D3C221AE0FFE8BD4004514FE /* PKTrackException.h */, + D34BAE1B0FF9CE0E00D7773A /* PKTrackException.m */, + D3C221B10FFE8BDB004514FE /* PKIntersection.h */, + D34BAE110FF9CE0E00D7773A /* PKIntersection.m */, + D3C221B40FFE8BE2004514FE /* PKDifference.h */, + D34BAE0F0FF9CE0E00D7773A /* PKDifference.m */, + D3C221B70FFE8BE8004514FE /* PKNegation.h */, + D3126D040FFD9BA700CBF4C4 /* PKNegation.m */, + D3C221BA0FFE8BEF004514FE /* PKTerminal.h */, + D34BAE170FF9CE0E00D7773A /* PKTerminal.m */, + D3C221BD0FFE8BF7004514FE /* PKEmpty.h */, + D34BAE0D0FF9CE0E00D7773A /* PKEmpty.m */, + ); + name = parsers; + sourceTree = ""; + }; + D3D63F560E2A8538009BF5CD /* tokens */ = { + isa = PBXGroup; + children = ( + D31FE5710E60E55700A0803E /* TDReaderTest.h */, + D31FE5720E60E55700A0803E /* TDReaderTest.m */, + D31FE5730E60E55700A0803E /* TDTokenizerTest.h */, + D31FE5740E60E55700A0803E /* TDTokenizerTest.m */, + D38E97CA1061CF6500739C39 /* TDTokenizerBlocksTest.h */, + D38E97CB1061CF6500739C39 /* TDTokenizerBlocksTest.m */, + D38205BC0EEE48EE004340DD /* TDTokenTest.h */, + D38205BD0EEE48EE004340DD /* TDTokenTest.m */, + D3656DFC0EF2620E00226554 /* TDTokenArraySourceTest.h */, + D3656DFD0EF2620E00226554 /* TDTokenArraySourceTest.m */, + D35420EC0DFB275400429B4F /* tokenizer states */, + ); + name = tokens; + sourceTree = ""; + }; + D3D63F570E2A8548009BF5CD /* parse */ = { + isa = PBXGroup; + children = ( + D31FE54D0E60E50800A0803E /* TDAlternationTest.h */, + D31FE54E0E60E50800A0803E /* TDAlternationTest.m */, + D31FE54F0E60E50800A0803E /* TDLiteralTest.h */, + D31FE5500E60E50800A0803E /* TDLiteralTest.m */, + D31FE5510E60E50800A0803E /* TDParserTest.h */, + D31FE5520E60E50800A0803E /* TDParserTest.m */, + D38E98D61062C5BA00739C39 /* TDParserBlocksTest.h */, + D38E98D71062C5BA00739C39 /* TDParserBlocksTest.m */, + D31FE5530E60E50800A0803E /* TDRepetitionTest.h */, + D31FE5540E60E50800A0803E /* TDRepetitionTest.m */, + D31FE5550E60E50800A0803E /* TDReservedWordTest.h */, + D31FE5560E60E50800A0803E /* TDReservedWordTest.m */, + D31FE5570E60E50800A0803E /* TDRobotCommandTest.h */, + D31FE5580E60E50800A0803E /* TDRobotCommandTest.m */, + D31FE5590E60E50800A0803E /* TDSequenceTest.h */, + D31FE55A0E60E50800A0803E /* TDSequenceTest.m */, + D31FE55B0E60E50800A0803E /* TDSymbolTest.h */, + D31FE55C0E60E50800A0803E /* TDSymbolTest.m */, + D31FE55D0E60E50800A0803E /* TDTokenAssemblyTest.h */, + D31FE55E0E60E50800A0803E /* TDTokenAssemblyTest.m */, + D31FE55F0E60E50800A0803E /* TDTrackTest.h */, + D31FE5600E60E50800A0803E /* TDTrackTest.m */, + D31FE5610E60E50800A0803E /* TDUppercaseWordTest.h */, + D31FE5620E60E50800A0803E /* TDUppercaseWordTest.m */, + D3C031EB0EF38D2D00C5ABEB /* TDLowercaseWordTest.h */, + D3C031EC0EF38D2D00C5ABEB /* TDLowercaseWordTest.m */, + D3126D410FFDB4C600CBF4C4 /* TDExclusionTest.h */, + D3126D420FFDB4C600CBF4C4 /* TDExclusionTest.m */, + D36C56290FD365DB00141CB7 /* TDPatternTest.h */, + D36C562A0FD365DB00141CB7 /* TDPatternTest.m */, + D338E5B90FF5DDCB003DE6AA /* TDDifferenceTest.h */, + D338E5BA0FF5DDCB003DE6AA /* TDDifferenceTest.m */, + D3126D090FFD9E4B00CBF4C4 /* TDNegationTest.h */, + D3126D0A0FFD9E4B00CBF4C4 /* TDNegationTest.m */, + ); + name = parse; + sourceTree = ""; + }; + D3D642270E2AC426009BF5CD /* token terminals */ = { + isa = PBXGroup; + children = ( + D36C55FB0FD3616200141CB7 /* regex */, + D3C221F30FFE8C87004514FE /* PKWord.h */, + D34BAED40FF9D56400D7773A /* PKWord.m */, + D3C222140FFE8D01004514FE /* PKLowercaseWord.h */, + D34BAF990FF9E6D100D7773A /* PKLowercaseWord.m */, + D3C222170FFE8D11004514FE /* PKUppercaseWord.h */, + D34BAF9B0FF9E6D100D7773A /* PKUppercaseWord.m */, + D3C221F60FFE8C8E004514FE /* PKNumber.h */, + D34BAF440FF9E19700D7773A /* PKNumber.m */, + D3C221F90FFE8C97004514FE /* PKQuotedString.h */, + D34BAF460FF9E19700D7773A /* PKQuotedString.m */, + D3C221FC0FFE8CB2004514FE /* PKSymbol.h */, + D34BAF480FF9E19700D7773A /* PKSymbol.m */, + D3C221FF0FFE8CB9004514FE /* PKLiteral.h */, + D34BAF420FF9E19700D7773A /* PKLiteral.m */, + D3C222020FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h */, + D34BAF3C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m */, + D3C222050FFE8CCA004514FE /* PKWhitespace.h */, + D34BAF4A0FF9E19700D7773A /* PKWhitespace.m */, + D3C222080FFE8CD1004514FE /* PKComment.h */, + D34BAF3E0FF9E19700D7773A /* PKComment.m */, + D3C2220B0FFE8CD8004514FE /* PKDelimitedString.h */, + D34BAF400FF9E19700D7773A /* PKDelimitedString.m */, + D3C2220E0FFE8CDF004514FE /* PKAny.h */, + D34BAE2F0FF9CE6000D7773A /* PKAny.m */, + ); + name = "token terminals"; + sourceTree = ""; + }; + D3D647CE0E2C7569009BF5CD /* xml */ = { + isa = PBXGroup; + children = ( + D3D1BF291039445C003656E5 /* SAXTest.h */, + D3D1BF2A1039445C003656E5 /* SAXTest.m */, + D3D1BF2610394420003656E5 /* SAXAssembler.h */, + D3D1BF2710394420003656E5 /* SAXAssembler.m */, + D3BBBC960FEC9722007DF30D /* TDXMLParserTest.h */, + D3BBBC970FEC9722007DF30D /* TDXMLParserTest.m */, + D3BBBC9B0FEC9756007DF30D /* TDXMLParser.h */, + D3BBBC9C0FEC9756007DF30D /* TDXMLParser.m */, + D355C8800FEB36A1006A91A4 /* xml.grammar */, + D315DF710FEF59B600D876C8 /* date.grammar */, + D3BBBC9A0FEC9739007DF30D /* old */, + ); + name = xml; + sourceTree = ""; + }; + D3E785F10E550F63008C7D61 /* chars */ = { + isa = PBXGroup; + children = ( + D3C2221A0FFE8D32004514FE /* PKCharacterAssembly.h */, + D34BAFB00FF9E7F300D7773A /* PKCharacterAssembly.m */, + D3E7861F0E55363F008C7D61 /* char terminals */, + ); + name = chars; + sourceTree = ""; + }; + D3E786030E5510AE008C7D61 /* regex */ = { + isa = PBXGroup; + children = ( + D31FE59B0E60E5C000A0803E /* TDRegularParser.h */, + D31FE59C0E60E5C000A0803E /* TDRegularParser.m */, + D31FE59D0E60E5C000A0803E /* TDRegularParserTest.h */, + D31FE59E0E60E5C000A0803E /* TDRegularParserTest.m */, + ); + name = regex; + sourceTree = ""; + }; + D3E7861F0E55363F008C7D61 /* char terminals */ = { + isa = PBXGroup; + children = ( + D3C2221D0FFE8D3B004514FE /* PKChar.h */, + D34BAFB40FF9E80300D7773A /* PKChar.m */, + D3C222200FFE8D42004514FE /* PKDigit.h */, + D34BAFB60FF9E80300D7773A /* PKDigit.m */, + D3C222230FFE8D49004514FE /* PKLetter.h */, + D34BAFB80FF9E80300D7773A /* PKLetter.m */, + D3C222260FFE8D6B004514FE /* PKSpecificChar.h */, + D34BAFBA0FF9E80300D7773A /* PKSpecificChar.m */, + ); + name = "char terminals"; + sourceTree = ""; + }; + D3E788890E567B6D008C7D61 /* ebnf */ = { + isa = PBXGroup; + children = ( + D3E78A150E574C99008C7D61 /* EBNFParser.h */, + D3E78A160E574C99008C7D61 /* EBNFParser.m */, + D3E78A170E574C99008C7D61 /* EBNFParserTest.h */, + D3E78A180E574C99008C7D61 /* EBNFParserTest.m */, + ); + name = ebnf; + sourceTree = ""; + }; + D3E788900E567DDA008C7D61 /* srgs */ = { + isa = PBXGroup; + children = ( + D3DDDCAC0F0880D800A58000 /* example1.srgs */, + D3E788940E567E0A008C7D61 /* SRGSParser.h */, + D3E788950E567E0A008C7D61 /* SRGSParser.m */, + D3E788910E567DFD008C7D61 /* SRGSParserTest.h */, + D3E788920E567DFD008C7D61 /* SRGSParserTest.m */, + D36E9FE40E5BA0FC00496BD3 /* SRGSGrammar.txt */, + ); + name = srgs; + sourceTree = ""; + }; + D3F5619C1026374400DD6DB1 /* ir */ = { + isa = PBXGroup; + children = ( + D3F5619D1026375100DD6DB1 /* syntax tree */, + D3F561B61026379700DD6DB1 /* ast */, + ); + name = ir; + sourceTree = ""; + }; + D3F5619D1026375100DD6DB1 /* syntax tree */ = { + isa = PBXGroup; + children = ( + D36934551038DE5300527AF3 /* PKParseTree.h */, + D36934561038DE5300527AF3 /* PKParseTree.m */, + D36934571038DE5300527AF3 /* PKParseTreeAssembler.h */, + D36934581038DE5300527AF3 /* PKParseTreeAssembler.m */, + D36934591038DE5300527AF3 /* PKRuleNode.h */, + D369345A1038DE5300527AF3 /* PKRuleNode.m */, + D369345B1038DE5300527AF3 /* PKTokenNode.h */, + D369345C1038DE5300527AF3 /* PKTokenNode.m */, + ); + name = "syntax tree"; + sourceTree = ""; + }; + D3F561B61026379700DD6DB1 /* ast */ = { + isa = PBXGroup; + children = ( + ); + name = ast; + sourceTree = ""; + }; + D3F823560F57859900B7DC48 /* factory */ = { + isa = PBXGroup; + children = ( + D34BAC210FF87F8600D7773A /* TDParserFactoryTest3.h */, + D34BAC220FF87F8600D7773A /* TDParserFactoryTest3.m */, + D380BA5F0F0F06CD0009EC13 /* TDParserFactoryTest.h */, + D380BA600F0F06CD0009EC13 /* TDParserFactoryTest.m */, + D36C53770FD27F1300141CB7 /* TDParserFactoryTest2.h */, + D36C53780FD27F1300141CB7 /* TDParserFactoryTest2.m */, + D3AF49760FDB122E0032F4DC /* TDParserFactoryPatternTest.h */, + D3AF49770FDB122E0032F4DC /* TDParserFactoryPatternTest.m */, + ); + name = factory; + sourceTree = ""; + }; + D3FDC8EF0FFC52CD00F1F797 /* Mobile Frameworks */ = { + isa = PBXGroup; + children = ( + D3FDC74B0FFC4DAC00F1F797 /* CoreGraphics.framework */, + D3FDC7380FFC4D6100F1F797 /* libicucore.dylib */, + D3FDC7360FFC4D6100F1F797 /* Foundation.framework */, + ); + name = "Mobile Frameworks"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 8DC2EF500486A6940098B216 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D34BAD640FF9C6AE00D7773A /* ParseKit_Prefix.pch in Headers */, + D3FDC4A50FFB3B2A00F1F797 /* RegexKitLite.h in Headers */, + D3C221920FFE8B8C004514FE /* ParseKit.h in Headers */, + D3C221930FFE8B8C004514FE /* PKTypes.h in Headers */, + D3C221970FFE8B95004514FE /* PKReader.h in Headers */, + D3C2219A0FFE8B9D004514FE /* PKAssembly.h in Headers */, + D3C2219D0FFE8BA6004514FE /* PKParser.h in Headers */, + D3C221A00FFE8BAE004514FE /* PKRepetition.h in Headers */, + D3C221A30FFE8BBA004514FE /* PKCollectionParser.h in Headers */, + D3C221A60FFE8BC1004514FE /* PKAlternation.h in Headers */, + D3C221A90FFE8BC9004514FE /* PKSequence.h in Headers */, + D3C221AC0FFE8BCF004514FE /* PKTrack.h in Headers */, + D3C221AF0FFE8BD4004514FE /* PKTrackException.h in Headers */, + D3C221B20FFE8BDB004514FE /* PKIntersection.h in Headers */, + D3C221B50FFE8BE2004514FE /* PKDifference.h in Headers */, + D3C221B80FFE8BE8004514FE /* PKNegation.h in Headers */, + D3C221BB0FFE8BEF004514FE /* PKTerminal.h in Headers */, + D3C221BE0FFE8BF7004514FE /* PKEmpty.h in Headers */, + D3C221C10FFE8BFF004514FE /* PKTokenAssembly.h in Headers */, + D3C221C40FFE8C07004514FE /* PKToken.h in Headers */, + D3C221C70FFE8C0D004514FE /* PKTokenArraySource.h in Headers */, + D3C221CA0FFE8C15004514FE /* PKTokenizer.h in Headers */, + D3C221CD0FFE8C1B004514FE /* PKTokenizerState.h in Headers */, + D3C221D00FFE8C24004514FE /* PKNumberState.h in Headers */, + D3C221D60FFE8C35004514FE /* PKSymbolState.h in Headers */, + D3C221D90FFE8C3D004514FE /* PKWordState.h in Headers */, + D3C221DC0FFE8C43004514FE /* PKWhitespaceState.h in Headers */, + D3C221DF0FFE8C49004514FE /* PKDelimitState.h in Headers */, + D3C221E20FFE8C4E004514FE /* PKCommentState.h in Headers */, + D3C221E50FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */, + D3C221E80FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */, + D3C221EB0FFE8C69004514FE /* PKSymbolNode.h in Headers */, + D3C221EE0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */, + D3C221F10FFE8C7A004514FE /* PKPattern.h in Headers */, + D3C221F40FFE8C87004514FE /* PKWord.h in Headers */, + D3C221F70FFE8C8E004514FE /* PKNumber.h in Headers */, + D3C221FA0FFE8C97004514FE /* PKQuotedString.h in Headers */, + D3C221FD0FFE8CB2004514FE /* PKSymbol.h in Headers */, + D3C222000FFE8CB9004514FE /* PKLiteral.h in Headers */, + D3C222030FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */, + D3C222060FFE8CCA004514FE /* PKWhitespace.h in Headers */, + D3C222090FFE8CD1004514FE /* PKComment.h in Headers */, + D3C2220C0FFE8CD8004514FE /* PKDelimitedString.h in Headers */, + D3C2220F0FFE8CDF004514FE /* PKAny.h in Headers */, + D3C222150FFE8D01004514FE /* PKLowercaseWord.h in Headers */, + D3C222180FFE8D11004514FE /* PKUppercaseWord.h in Headers */, + D3C2221B0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */, + D3C2221E0FFE8D3B004514FE /* PKChar.h in Headers */, + D3C222210FFE8D42004514FE /* PKDigit.h in Headers */, + D3C222240FFE8D49004514FE /* PKLetter.h in Headers */, + D3C222270FFE8D6B004514FE /* PKSpecificChar.h in Headers */, + D3C2222A0FFE8DAC004514FE /* PKParserFactory.h in Headers */, + D3C2222D0FFE8DE9004514FE /* NSArray+ParseKitAdditions.h in Headers */, + D3C2222E0FFE8DEE004514FE /* NSString+ParseKitAdditions.h in Headers */, + D3F0E2480FFE8EB900C9DF74 /* PKQuoteState.h in Headers */, + D3376D5910093A1600E4602E /* PKGrammarParser.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1C90F1965E600558235 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D34BB0680FF9EDDF00D7773A /* JSParseKit.h in Headers */, + D34BB0710FF9EE4000D7773A /* PKJSAssembly.h in Headers */, + D34BB0730FF9EE4000D7773A /* PKJSUtils.h in Headers */, + D34BB0750FF9EE4000D7773A /* PKJSUtils_macros.h in Headers */, + D34BB0760FF9EE4000D7773A /* PKJSValueHolder.h in Headers */, + D34BB08F0FF9EF9D00D7773A /* PKJSCharacterAssembly.h in Headers */, + D34BB0A90FF9F14B00D7773A /* PKJSCommentState.h in Headers */, + D34BB0AB0FF9F14B00D7773A /* PKJSDelimitState.h in Headers */, + D34BB0AD0FF9F14B00D7773A /* PKJSNumberState.h in Headers */, + D34BB0AF0FF9F14B00D7773A /* PKJSQuoteState.h in Headers */, + D34BB0B10FF9F14B00D7773A /* PKJSSymbolState.h in Headers */, + D34BB0B30FF9F14B00D7773A /* PKJSToken.h in Headers */, + D34BB0B50FF9F14B00D7773A /* PKJSTokenAssembly.h in Headers */, + D34BB0B70FF9F14B00D7773A /* PKJSTokenizer.h in Headers */, + D34BB0B90FF9F14B00D7773A /* PKJSTokenizerState.h in Headers */, + D34BB0BB0FF9F14B00D7773A /* PKJSWhitespaceState.h in Headers */, + D34BB0BD0FF9F14B00D7773A /* PKJSWordState.h in Headers */, + D34BB0E60FF9F28000D7773A /* PKJSAlternation.h in Headers */, + D34BB0E80FF9F28000D7773A /* PKJSAny.h in Headers */, + D34BB0EA0FF9F28000D7773A /* PKJSAssemblerAdapter.h in Headers */, + D34BB0EC0FF9F28000D7773A /* PKJSCollectionParser.h in Headers */, + D34BB0EE0FF9F28000D7773A /* PKJSEmpty.h in Headers */, + D34BB0F00FF9F28000D7773A /* PKJSParser.h in Headers */, + D34BB0F20FF9F28000D7773A /* PKJSRepetition.h in Headers */, + D34BB0F40FF9F28000D7773A /* PKJSSequence.h in Headers */, + D34BB0F60FF9F28000D7773A /* PKJSTerminal.h in Headers */, + D34BB0F80FF9F28000D7773A /* PKJSTrack.h in Headers */, + D34BB1140FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.h in Headers */, + D34BB1160FF9F36200D7773A /* PKJSComment.h in Headers */, + D34BB1180FF9F36200D7773A /* PKJSDelimitedString.h in Headers */, + D34BB11A0FF9F36200D7773A /* PKJSLiteral.h in Headers */, + D34BB11C0FF9F36200D7773A /* PKJSLowercaseWord.h in Headers */, + D34BB11E0FF9F36200D7773A /* PKJSNum.h in Headers */, + D34BB1200FF9F36200D7773A /* PKJSPattern.h in Headers */, + D34BB1220FF9F36200D7773A /* PKJSQuotedString.h in Headers */, + D34BB1240FF9F36200D7773A /* PKJSSymbol.h in Headers */, + D34BB1260FF9F36200D7773A /* PKJSUppercaseWord.h in Headers */, + D34BB1280FF9F36200D7773A /* PKJSWord.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3FDC57F0FFC4BFC00F1F797 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D3FDC6DA0FFC4C8C00F1F797 /* RegexKitLite.h in Headers */, + D3FDC8DC0FFC51F200F1F797 /* ParseKitMobile_Prefix.pch in Headers */, + D3C221940FFE8B8C004514FE /* ParseKit.h in Headers */, + D3C221950FFE8B8C004514FE /* PKTypes.h in Headers */, + D3C221980FFE8B95004514FE /* PKReader.h in Headers */, + D3C2219B0FFE8B9D004514FE /* PKAssembly.h in Headers */, + D3C2219E0FFE8BA6004514FE /* PKParser.h in Headers */, + D3C221A10FFE8BAE004514FE /* PKRepetition.h in Headers */, + D3C221A40FFE8BBA004514FE /* PKCollectionParser.h in Headers */, + D3C221A70FFE8BC1004514FE /* PKAlternation.h in Headers */, + D3C221AA0FFE8BC9004514FE /* PKSequence.h in Headers */, + D3C221AD0FFE8BCF004514FE /* PKTrack.h in Headers */, + D3C221B00FFE8BD4004514FE /* PKTrackException.h in Headers */, + D3C221B30FFE8BDB004514FE /* PKIntersection.h in Headers */, + D3C221B60FFE8BE2004514FE /* PKDifference.h in Headers */, + D3C221B90FFE8BE8004514FE /* PKNegation.h in Headers */, + D3C221BC0FFE8BEF004514FE /* PKTerminal.h in Headers */, + D3C221BF0FFE8BF7004514FE /* PKEmpty.h in Headers */, + D3C221C20FFE8BFF004514FE /* PKTokenAssembly.h in Headers */, + D3C221C50FFE8C07004514FE /* PKToken.h in Headers */, + D3C221C80FFE8C0D004514FE /* PKTokenArraySource.h in Headers */, + D3C221CB0FFE8C15004514FE /* PKTokenizer.h in Headers */, + D3C221CE0FFE8C1B004514FE /* PKTokenizerState.h in Headers */, + D3C221D10FFE8C24004514FE /* PKNumberState.h in Headers */, + D3C221D70FFE8C35004514FE /* PKSymbolState.h in Headers */, + D3C221DA0FFE8C3D004514FE /* PKWordState.h in Headers */, + D3C221DD0FFE8C43004514FE /* PKWhitespaceState.h in Headers */, + D3C221E00FFE8C49004514FE /* PKDelimitState.h in Headers */, + D3C221E30FFE8C4E004514FE /* PKCommentState.h in Headers */, + D3C221E60FFE8C56004514FE /* PKSingleLineCommentState.h in Headers */, + D3C221E90FFE8C60004514FE /* PKMultiLineCommentState.h in Headers */, + D3C221EC0FFE8C69004514FE /* PKSymbolNode.h in Headers */, + D3C221EF0FFE8C6F004514FE /* PKSymbolRootNode.h in Headers */, + D3C221F20FFE8C7A004514FE /* PKPattern.h in Headers */, + D3C221F50FFE8C87004514FE /* PKWord.h in Headers */, + D3C221FB0FFE8C97004514FE /* PKQuotedString.h in Headers */, + D3C221FE0FFE8CB2004514FE /* PKSymbol.h in Headers */, + D3C222010FFE8CB9004514FE /* PKLiteral.h in Headers */, + D3C222040FFE8CC4004514FE /* PKCaseInsensitiveLiteral.h in Headers */, + D3C222070FFE8CCA004514FE /* PKWhitespace.h in Headers */, + D3C2220A0FFE8CD1004514FE /* PKComment.h in Headers */, + D3C2220D0FFE8CD8004514FE /* PKDelimitedString.h in Headers */, + D3C222100FFE8CDF004514FE /* PKAny.h in Headers */, + D3C222160FFE8D01004514FE /* PKLowercaseWord.h in Headers */, + D3C222190FFE8D11004514FE /* PKUppercaseWord.h in Headers */, + D3C2221C0FFE8D32004514FE /* PKCharacterAssembly.h in Headers */, + D3C2221F0FFE8D3B004514FE /* PKChar.h in Headers */, + D3C222220FFE8D42004514FE /* PKDigit.h in Headers */, + D3C222250FFE8D49004514FE /* PKLetter.h in Headers */, + D3C222280FFE8D6B004514FE /* PKSpecificChar.h in Headers */, + D3C2222B0FFE8DAC004514FE /* PKParserFactory.h in Headers */, + D3C2222F0FFE8DEF004514FE /* NSString+ParseKitAdditions.h in Headers */, + D3C222300FFE8DF3004514FE /* NSArray+ParseKitAdditions.h in Headers */, + D3F0E2490FFE8EB900C9DF74 /* PKQuoteState.h in Headers */, + D3F0E3CB0FFEB70100C9DF74 /* PKNumber.h in Headers */, + D37A28681013942A00E936B7 /* PKGrammarParser.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 8DC2EF4F0486A6940098B216 /* ParseKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "ParseKit" */; + buildPhases = ( + 8DC2EF500486A6940098B216 /* Headers */, + 8DC2EF540486A6940098B216 /* Sources */, + 8DC2EF520486A6940098B216 /* Resources */, + 8DC2EF560486A6940098B216 /* Frameworks */, + D36C65E7100ED81B000361A0 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ParseKit; + productInstallPath = "$(HOME)/Library/Frameworks"; + productName = TODParseKit; + productReference = 8DC2EF5B0486A6940098B216 /* ParseKit.framework */; + productType = "com.apple.product-type.framework"; + }; + D334940F0E2963FD00406085 /* DemoApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = D33494150E2963FE00406085 /* Build configuration list for PBXNativeTarget "DemoApp" */; + buildPhases = ( + D334940D0E2963FD00406085 /* Sources */, + D334940C0E2963FD00406085 /* Resources */, + D334940E0E2963FD00406085 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D33494A00E296AA900406085 /* PBXTargetDependency */, + ); + name = DemoApp; + productName = DemoApp; + productReference = D33494100E2963FD00406085 /* DemoApp.app */; + productType = "com.apple.product-type.application"; + }; + D34185030E520D3F0081B0DC /* DebugApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = D34185090E520D410081B0DC /* Build configuration list for PBXNativeTarget "DebugApp" */; + buildPhases = ( + D34185010E520D3F0081B0DC /* Sources */, + D34185000E520D3F0081B0DC /* Resources */, + D380B9A10F0EF3DC0009EC13 /* Copy Frameworks */, + D34185020E520D3F0081B0DC /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D34185100E520D6F0081B0DC /* PBXTargetDependency */, + ); + name = DebugApp; + productName = TestApp; + productReference = D34185040E520D3F0081B0DC /* DebugApp.app */; + productType = "com.apple.product-type.application"; + }; + D389F1CD0F1965E600558235 /* JSParseKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = D389F1D20F1965E800558235 /* Build configuration list for PBXNativeTarget "JSParseKit" */; + buildPhases = ( + D389F1C90F1965E600558235 /* Headers */, + D389F1CB0F1965E600558235 /* Sources */, + D389F1CA0F1965E600558235 /* Resources */, + D389F1CC0F1965E600558235 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D389F1D40F19665C00558235 /* PBXTargetDependency */, + ); + name = JSParseKit; + productName = TDJSParseKit; + productReference = D389F1CE0F1965E600558235 /* JSParseKit.framework */; + productType = "com.apple.product-type.framework"; + }; + D389F2020F196A7500558235 /* JSDemoApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = D389F2080F196A7600558235 /* Build configuration list for PBXNativeTarget "JSDemoApp" */; + buildPhases = ( + D389F2000F196A7500558235 /* Sources */, + D389F1FF0F196A7500558235 /* Resources */, + D389F2010F196A7500558235 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D389F20A0F196A8000558235 /* PBXTargetDependency */, + ); + name = JSDemoApp; + productName = JSDemoApp; + productReference = D389F2030F196A7500558235 /* JSDemoApp.app */; + productType = "com.apple.product-type.application"; + }; + D3C7D8790A411FBF005DD154 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D3C7D87C0A411FC0005DD154 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + D3C7D8760A411FBF005DD154 /* Sources */, + D3C7D8750A411FBF005DD154 /* Resources */, + D3DCB3880EF5E65100DE5110 /* Copy Frameworks */, + D3C7D8770A411FBF005DD154 /* Frameworks */, + D3C7D8780A411FBF005DD154 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + D31FE7180E60F24700A0803E /* PBXTargetDependency */, + ); + name = Tests; + productName = Tests; + productReference = D3C7D87A0A411FBF005DD154 /* Tests.octest */; + productType = "com.apple.product-type.bundle"; + }; + D3FDC5820FFC4BFC00F1F797 /* ParseKitMobile */ = { + isa = PBXNativeTarget; + buildConfigurationList = D3FDC62F0FFC4C2000F1F797 /* Build configuration list for PBXNativeTarget "ParseKitMobile" */; + buildPhases = ( + D3FDC57F0FFC4BFC00F1F797 /* Headers */, + D3FDC5800FFC4BFC00F1F797 /* Sources */, + D3FDC5810FFC4BFC00F1F797 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ParseKitMobile; + productName = ParseKitMobile; + productReference = D3FDC5830FFC4BFC00F1F797 /* libparsekit.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0867D690FE84028FC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ParseKit" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 0867D691FE84028FC02AAC07 /* TODParseKit */; + productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DC2EF4F0486A6940098B216 /* ParseKit */, + D389F1CD0F1965E600558235 /* JSParseKit */, + D3FDC5820FFC4BFC00F1F797 /* ParseKitMobile */, + D3C7D8790A411FBF005DD154 /* Tests */, + D334940F0E2963FD00406085 /* DemoApp */, + D34185030E520D3F0081B0DC /* DebugApp */, + D389F2020F196A7500558235 /* JSDemoApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8DC2EF520486A6940098B216 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D334940C0E2963FD00406085 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36E98F80E58C1A000496BD3 /* DemoAppMainMenu.xib in Resources */, + D3DCB4C40EF6015C00DE5110 /* json.grammar in Resources */, + D3F741BF0EF9F29400559B9F /* css2_1.grammar in Resources */, + D3D01CAB0EFDB8A000C24DDE /* json_with_discards.grammar in Resources */, + D3F562A210266E5300DD6DB1 /* TokensView.xib in Resources */, + D3F562A410266E6300DD6DB1 /* TreesView.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D34185000E520D3F0081B0DC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3E27A320E741DD20078CC2C /* small-xml-file.xml in Resources */, + D3E27A330E741DD20078CC2C /* apple-boss.xml in Resources */, + D398E20E0E60F86D00A1C877 /* yahoo.json in Resources */, + D3E785560E53FB54008C7D61 /* apple-boss.json in Resources */, + D36E98E10E58C12800496BD3 /* DebugAppMainMenu.xib in Resources */, + D3EADD810E75E9CC00F78584 /* nasty.html in Resources */, + D3B69D320E80249900D70C41 /* nonascii.html in Resources */, + D3DCB4C50EF6015C00DE5110 /* json.grammar in Resources */, + D3F741C00EF9F29500559B9F /* css2_1.grammar in Resources */, + D3D01CAC0EFDB8A100C24DDE /* json_with_discards.grammar in Resources */, + D385FA260F04993500DB2946 /* json.css in Resources */, + D385FD6C0F05A99900DB2946 /* mini_css.grammar in Resources */, + D3DDDCAE0F0880D800A58000 /* example1.srgs in Resources */, + D383498C0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */, + D38349BD0F0C0D910055E4E0 /* json_with_comments.css in Resources */, + D3834A490F0C14C00055E4E0 /* yahoo_with_comments.json in Resources */, + D380AFBF0F0C54B60009EC13 /* html.css in Resources */, + D380AFC00F0C54B60009EC13 /* html.grammar in Resources */, + D380AFC30F0C56000009EC13 /* example.html in Resources */, + D380B3230F0CC0800009EC13 /* nyt.html in Resources */, + D380B50A0F0D71B00009EC13 /* css.grammar in Resources */, + D380B5390F0D7DE30009EC13 /* css.css in Resources */, + D380B5950F0D82F90009EC13 /* example.css in Resources */, + D3FD79210F4CC87900BAD816 /* rubyhash.grammar in Resources */, + D31A15270F6DE449002AFDF1 /* javascript.grammar in Resources */, + D355C6A70FE9F704006A91A4 /* nspredicate.grammar in Resources */, + D3BBBCC10FECD477007DF30D /* xml.grammar in Resources */, + D315DF730FEF59B600D876C8 /* date.grammar in Resources */, + D34BAC9A0FF8A9AD00D7773A /* xpath1_0.grammar in Resources */, + D3668293101D2C000008632C /* erb.grammar in Resources */, + D319E42B106D8A1F008C63DD /* arithmetic.grammar in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1CA0F1965E600558235 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1FF0F196A7500558235 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F38F0F19800400558235 /* DefaultValues.plist in Resources */, + D389F4620F198A8800558235 /* Test.html in Resources */, + D389F5590F19B7BC00558235 /* JSDemoAppMainMenu.xib in Resources */, + D389FBCD0F1B25E200558235 /* ParserTest.html in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3C7D8750A411FBF005DD154 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3B473850E48C9CF008AFBDD /* yahoo.json in Resources */, + D3E784BD0E53DA28008C7D61 /* apple-boss.json in Resources */, + D36E9FB50E5A944A00496BD3 /* apple-boss.xml in Resources */, + D36E9FE50E5BA0FC00496BD3 /* SRGSGrammar.txt in Resources */, + D36EA3B00E5EA67E00496BD3 /* small-xml-file.xml in Resources */, + D3EADD800E75E9CC00F78584 /* nasty.html in Resources */, + D3B69D330E80249900D70C41 /* nonascii.html in Resources */, + D38DD9E80EC29F260070BC4D /* nyt.html in Resources */, + D3DCB4C30EF6015300DE5110 /* json.grammar in Resources */, + D3F741440EF8E96A00559B9F /* xpath1_0.grammar in Resources */, + D3F741BE0EF9F28D00559B9F /* css2_1.grammar in Resources */, + D3D01CAA0EFDB89900C24DDE /* json_with_discards.grammar in Resources */, + D385FA250F04993500DB2946 /* json.css in Resources */, + D385FD6D0F05A99900DB2946 /* mini_css.grammar in Resources */, + D3DDDCAD0F0880D800A58000 /* example1.srgs in Resources */, + D383498B0F0C0CF30055E4E0 /* json_with_comments.grammar in Resources */, + D38349BC0F0C0D910055E4E0 /* json_with_comments.css in Resources */, + D3834A480F0C14B60055E4E0 /* yahoo_with_comments.json in Resources */, + D380AFBD0F0C54B60009EC13 /* html.css in Resources */, + D380AFBE0F0C54B60009EC13 /* html.grammar in Resources */, + D380AFC40F0C56000009EC13 /* example.html in Resources */, + D380B5090F0D71A90009EC13 /* css.grammar in Resources */, + D380B5380F0D7DDE0009EC13 /* css.css in Resources */, + D380B5940F0D82F60009EC13 /* example.css in Resources */, + D3FD79200F4CC86800BAD816 /* rubyhash.grammar in Resources */, + D31A15260F6DE449002AFDF1 /* javascript.grammar in Resources */, + D35384ED0FE9691100926552 /* nspredicate.grammar in Resources */, + D353899C0FEAC94400926552 /* c.grammar in Resources */, + D353899E0FEAC96B00926552 /* objc.grammar in Resources */, + D355C8810FEB36A1006A91A4 /* xml.grammar in Resources */, + D355C8840FEB4B94006A91A4 /* proto.grammar in Resources */, + D315DF720FEF59B600D876C8 /* date.grammar in Resources */, + D3668292101D2BFA0008632C /* erb.grammar in Resources */, + D319E42A106D8A1F008C63DD /* arithmetic.grammar in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + D36C65E7100ED81B000361A0 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#cp -R -f \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\" ${HOME}/Library/Frameworks"; + }; + D3C7D8780A411FBF005DD154 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DC2EF540486A6940098B216 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36C55FF0FD3617B00141CB7 /* RegexKitLite.m in Sources */, + D34BAD9D0FF9C95800D7773A /* PKReader.m in Sources */, + D34BADA20FF9C9B000D7773A /* PKAssembly.m in Sources */, + D34BADD80FF9CBFB00D7773A /* PKParser.m in Sources */, + D34BAE030FF9CCAE00D7773A /* PKCollectionParser.m in Sources */, + D34BAE1D0FF9CE0E00D7773A /* PKAlternation.m in Sources */, + D34BAE1F0FF9CE0E00D7773A /* PKEmpty.m in Sources */, + D34BAE210FF9CE0E00D7773A /* PKDifference.m in Sources */, + D34BAE230FF9CE0E00D7773A /* PKIntersection.m in Sources */, + D34BAE250FF9CE0E00D7773A /* PKRepetition.m in Sources */, + D34BAE270FF9CE0E00D7773A /* PKSequence.m in Sources */, + D34BAE290FF9CE0E00D7773A /* PKTerminal.m in Sources */, + D34BAE2B0FF9CE0E00D7773A /* PKTrack.m in Sources */, + D34BAE2D0FF9CE0E00D7773A /* PKTrackException.m in Sources */, + D34BAE310FF9CE6000D7773A /* PKAny.m in Sources */, + D34BAE8D0FF9D15100D7773A /* PKTokenAssembly.m in Sources */, + D34BAE9D0FF9D20900D7773A /* PKToken.m in Sources */, + D34BAE9F0FF9D20900D7773A /* PKTokenArraySource.m in Sources */, + D34BAEA10FF9D20900D7773A /* PKTokenizer.m in Sources */, + D34BAEA30FF9D20900D7773A /* PKTokenizerState.m in Sources */, + D34BAED80FF9D56400D7773A /* PKCommentState.m in Sources */, + D34BAEDA0FF9D56400D7773A /* PKDelimitState.m in Sources */, + D34BAEDC0FF9D56400D7773A /* PKMultiLineCommentState.m in Sources */, + D34BAEDE0FF9D56400D7773A /* PKNumberState.m in Sources */, + D34BAEE00FF9D56400D7773A /* PKQuoteState.m in Sources */, + D34BAEE20FF9D56400D7773A /* PKSingleLineCommentState.m in Sources */, + D34BAEE40FF9D56400D7773A /* PKSymbolState.m in Sources */, + D34BAEE60FF9D56400D7773A /* PKWhitespaceState.m in Sources */, + D34BAEE80FF9D56400D7773A /* PKWord.m in Sources */, + D34BAEEA0FF9D56400D7773A /* PKWordState.m in Sources */, + D34BAF280FF9DF9900D7773A /* PKSymbolNode.m in Sources */, + D34BAF2A0FF9DF9900D7773A /* PKSymbolRootNode.m in Sources */, + D34BAF3A0FF9E18300D7773A /* PKPattern.m in Sources */, + D34BAF4C0FF9E19700D7773A /* PKCaseInsensitiveLiteral.m in Sources */, + D34BAF4E0FF9E19700D7773A /* PKComment.m in Sources */, + D34BAF500FF9E19700D7773A /* PKDelimitedString.m in Sources */, + D34BAF520FF9E19700D7773A /* PKLiteral.m in Sources */, + D34BAF540FF9E19700D7773A /* PKNumber.m in Sources */, + D34BAF560FF9E19700D7773A /* PKQuotedString.m in Sources */, + D34BAF580FF9E19700D7773A /* PKSymbol.m in Sources */, + D34BAF5A0FF9E19700D7773A /* PKWhitespace.m in Sources */, + D34BAF9D0FF9E6D100D7773A /* PKLowercaseWord.m in Sources */, + D34BAF9F0FF9E6D100D7773A /* PKUppercaseWord.m in Sources */, + D34BAFB20FF9E7F300D7773A /* PKCharacterAssembly.m in Sources */, + D34BAFBC0FF9E80300D7773A /* PKChar.m in Sources */, + D34BAFBE0FF9E80300D7773A /* PKDigit.m in Sources */, + D34BAFC00FF9E80300D7773A /* PKLetter.m in Sources */, + D34BAFC20FF9E80300D7773A /* PKSpecificChar.m in Sources */, + D34BAFDA0FF9E95500D7773A /* NSArray+ParseKitAdditions.m in Sources */, + D34BAFDC0FF9E95500D7773A /* NSString+ParseKitAdditions.m in Sources */, + D34BAFDE0FF9E95500D7773A /* PKParserFactory.m in Sources */, + D3126D060FFD9BA700CBF4C4 /* PKNegation.m in Sources */, + D3376D5A10093A1600E4602E /* PKGrammarParser.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D334940D0E2963FD00406085 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36E98E70E58C14000496BD3 /* DemoAppDelegate.m in Sources */, + D36E98E80E58C14000496BD3 /* main.m in Sources */, + D3F5629A10266CFC00DD6DB1 /* PKParseTreeView.m in Sources */, + D3F562A010266DFB00DD6DB1 /* DemoTokensViewController.m in Sources */, + D3F562A710266E8D00DD6DB1 /* DemoTreesViewController.m in Sources */, + D3305C4F102F5BAE00DC4F75 /* TDGutterView.m in Sources */, + D3305C50102F5BAE00DC4F75 /* TDSourceCodeTextView.m in Sources */, + D36934721038E28300527AF3 /* PKParseTree.m in Sources */, + D36934731038E28700527AF3 /* PKParseTreeAssembler.m in Sources */, + D36934741038E28B00527AF3 /* PKRuleNode.m in Sources */, + D36934751038E28F00527AF3 /* PKTokenNode.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D34185010E520D3F0081B0DC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D36E98E20E58C12800496BD3 /* main.m in Sources */, + D36E98E00E58C12800496BD3 /* DebugAppDelegate.m in Sources */, + D3EADD8F0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */, + D31FE7420E60F40900A0803E /* XPathContext.m in Sources */, + D31FE7400E60F40300A0803E /* XPathAssembler.m in Sources */, + D31FE7340E60F34600A0803E /* XPathParser.m in Sources */, + D31FE7330E60F33C00A0803E /* XMLReader.m in Sources */, + D31FE7320E60F33000A0803E /* EBNFParser.m in Sources */, + D31FE7300E60F31E00A0803E /* TDFastJsonParser.m in Sources */, + D302C69D0EF044810090E714 /* TDPlistParser.m in Sources */, + D3F740B70EF8C38A00559B9F /* JSONAssembler.m in Sources */, + D385F98C0F046FE900DB2946 /* TDGenericAssembler.m in Sources */, + D385FD440F05A88C00DB2946 /* TDMiniCSSAssembler.m in Sources */, + D3DDDA870F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */, + D389F5B80F19C76A00558235 /* TDJsonParser.m in Sources */, + D31A16530F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */, + D3252F7E0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */, + D3385FDA0FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */, + D355C62E0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */, + D3BBBC9D0FEC9756007DF30D /* TDXMLParser.m in Sources */, + D3376D8F10096C0700E4602E /* PKAST.m in Sources */, + D319E42F106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F1CB0F1965E600558235 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D34BB0690FF9EDDF00D7773A /* JSParseKit.m in Sources */, + D34BB0720FF9EE4000D7773A /* PKJSAssembly.m in Sources */, + D34BB0740FF9EE4000D7773A /* PKJSUtils.m in Sources */, + D34BB0770FF9EE4000D7773A /* PKJSValueHolder.m in Sources */, + D34BB0900FF9EF9D00D7773A /* PKJSCharacterAssembly.m in Sources */, + D34BB0AA0FF9F14B00D7773A /* PKJSCommentState.m in Sources */, + D34BB0AC0FF9F14B00D7773A /* PKJSDelimitState.m in Sources */, + D34BB0AE0FF9F14B00D7773A /* PKJSNumberState.m in Sources */, + D34BB0B00FF9F14B00D7773A /* PKJSQuoteState.m in Sources */, + D34BB0B20FF9F14B00D7773A /* PKJSSymbolState.m in Sources */, + D34BB0B40FF9F14B00D7773A /* PKJSToken.m in Sources */, + D34BB0B60FF9F14B00D7773A /* PKJSTokenAssembly.m in Sources */, + D34BB0B80FF9F14B00D7773A /* PKJSTokenizer.m in Sources */, + D34BB0BA0FF9F14B00D7773A /* PKJSTokenizerState.m in Sources */, + D34BB0BC0FF9F14B00D7773A /* PKJSWhitespaceState.m in Sources */, + D34BB0BE0FF9F14B00D7773A /* PKJSWordState.m in Sources */, + D34BB0E70FF9F28000D7773A /* PKJSAlternation.m in Sources */, + D34BB0E90FF9F28000D7773A /* PKJSAny.m in Sources */, + D34BB0EB0FF9F28000D7773A /* PKJSAssemblerAdapter.m in Sources */, + D34BB0ED0FF9F28000D7773A /* PKJSCollectionParser.m in Sources */, + D34BB0EF0FF9F28000D7773A /* PKJSEmpty.m in Sources */, + D34BB0F10FF9F28000D7773A /* PKJSParser.m in Sources */, + D34BB0F30FF9F28000D7773A /* PKJSRepetition.m in Sources */, + D34BB0F50FF9F28000D7773A /* PKJSSequence.m in Sources */, + D34BB0F70FF9F28000D7773A /* PKJSTerminal.m in Sources */, + D34BB0F90FF9F28000D7773A /* PKJSTrack.m in Sources */, + D34BB1150FF9F36200D7773A /* PKJSCaseInsensitiveLiteral.m in Sources */, + D34BB1170FF9F36200D7773A /* PKJSComment.m in Sources */, + D34BB1190FF9F36200D7773A /* PKJSDelimitedString.m in Sources */, + D34BB11B0FF9F36200D7773A /* PKJSLiteral.m in Sources */, + D34BB11D0FF9F36200D7773A /* PKJSLowercaseWord.m in Sources */, + D34BB11F0FF9F36200D7773A /* PKJSNum.m in Sources */, + D34BB1210FF9F36200D7773A /* PKJSPattern.m in Sources */, + D34BB1230FF9F36200D7773A /* PKJSQuotedString.m in Sources */, + D34BB1250FF9F36200D7773A /* PKJSSymbol.m in Sources */, + D34BB1270FF9F36200D7773A /* PKJSUppercaseWord.m in Sources */, + D34BB1290FF9F36200D7773A /* PKJSWord.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D389F2000F196A7500558235 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D389F2E40F196CAE00558235 /* main.m in Sources */, + D389F37A0F197E8000558235 /* JSDemoAppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3C7D8760A411FBF005DD154 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3E788930E567DFD008C7D61 /* SRGSParserTest.m in Sources */, + D3E788960E567E0A008C7D61 /* SRGSParser.m in Sources */, + D3E78A190E574C99008C7D61 /* EBNFParser.m in Sources */, + D3E78A1A0E574C99008C7D61 /* EBNFParserTest.m in Sources */, + D36E95460E578ECC00496BD3 /* XPathParser.m in Sources */, + D36E95D80E57B08400496BD3 /* XPathParserTest.m in Sources */, + D36E97B00E589DAE00496BD3 /* XPathAssembler.m in Sources */, + D36E98220E58A3A800496BD3 /* XPathContext.m in Sources */, + D3521F560E5FA1B0009681F9 /* XMLReader.m in Sources */, + D3521F570E5FA1B0009681F9 /* XMLReaderTest.m in Sources */, + D31FE54C0E60E46100A0803E /* TDTestScaffold.m in Sources */, + D31FE5630E60E50800A0803E /* TDAlternationTest.m in Sources */, + D31FE5640E60E50800A0803E /* TDLiteralTest.m in Sources */, + D31FE5650E60E50800A0803E /* TDParserTest.m in Sources */, + D31FE5660E60E50800A0803E /* TDRepetitionTest.m in Sources */, + D31FE5680E60E50800A0803E /* TDRobotCommandTest.m in Sources */, + D31FE5690E60E50800A0803E /* TDSequenceTest.m in Sources */, + D31FE56A0E60E50800A0803E /* TDSymbolTest.m in Sources */, + D31FE56B0E60E50800A0803E /* TDTokenAssemblyTest.m in Sources */, + D31FE56C0E60E50800A0803E /* TDTrackTest.m in Sources */, + D31FE56D0E60E50800A0803E /* TDUppercaseWordTest.m in Sources */, + D31FE5750E60E55700A0803E /* TDReaderTest.m in Sources */, + D31FE5760E60E55700A0803E /* TDTokenizerTest.m in Sources */, + D31FE5850E60E58C00A0803E /* TDNumberStateTest.m in Sources */, + D31FE5860E60E58C00A0803E /* TDQuoteStateTest.m in Sources */, + D31FE5890E60E58C00A0803E /* TDSymbolStateTest.m in Sources */, + D31FE58A0E60E58C00A0803E /* TDWhitespaceStateTest.m in Sources */, + D31FE58B0E60E58C00A0803E /* TDWordStateTest.m in Sources */, + D31FE5960E60E5AC00A0803E /* TDCharacterAssemblyTest.m in Sources */, + D31FE5970E60E5AC00A0803E /* TDCharTest.m in Sources */, + D31FE5980E60E5AC00A0803E /* TDDigitTest.m in Sources */, + D31FE5990E60E5AC00A0803E /* TDLetterTest.m in Sources */, + D31FE59A0E60E5AC00A0803E /* TDSpecificCharTest.m in Sources */, + D31FE59F0E60E5C000A0803E /* TDRegularParser.m in Sources */, + D31FE5A00E60E5C000A0803E /* TDRegularParserTest.m in Sources */, + D31FE5A90E60E5D500A0803E /* TDFastJsonParser.m in Sources */, + D31FE5AA0E60E5D500A0803E /* TDFastJsonParserTest.m in Sources */, + D31FE5B10E60E64900A0803E /* TDXmlTokenAssembly.m in Sources */, + D31FE5B20E60E64900A0803E /* TDXmlTokenizerTest.m in Sources */, + D31FE5B70E60E66600A0803E /* TDXmlToken.m in Sources */, + D31FE5B80E60E66600A0803E /* TDXmlTokenizer.m in Sources */, + D31FE5DD0E60E69E00A0803E /* TDXmlAttribute.m in Sources */, + D31FE5DE0E60E69E00A0803E /* TDXmlCdata.m in Sources */, + D31FE5DF0E60E69E00A0803E /* TDXmlComment.m in Sources */, + D31FE5E00E60E69E00A0803E /* TDXmlDecl.m in Sources */, + D31FE5E10E60E69E00A0803E /* TDXmlDoctype.m in Sources */, + D31FE5E20E60E69E00A0803E /* TDXmlDocument.m in Sources */, + D31FE5E30E60E69E00A0803E /* TDXmlEndEntity.m in Sources */, + D31FE5E40E60E69E00A0803E /* TDXmlEndTag.m in Sources */, + D31FE5E50E60E69E00A0803E /* TDXmlEntity.m in Sources */, + D31FE5E60E60E69E00A0803E /* TDXmlEntityRef.m in Sources */, + D31FE5E70E60E69E00A0803E /* TDXmlFragment.m in Sources */, + D31FE5E80E60E69E00A0803E /* TDXmlNotation.m in Sources */, + D31FE5E90E60E69E00A0803E /* TDXmlProcessingInstruction.m in Sources */, + D31FE5EA0E60E69E00A0803E /* TDXmlSignificantWhitespace.m in Sources */, + D31FE5EB0E60E69E00A0803E /* TDXmlStartTag.m in Sources */, + D31FE5EC0E60E69E00A0803E /* TDXmlTerminal.m in Sources */, + D31FE5ED0E60E69E00A0803E /* TDXmlText.m in Sources */, + D31FE5EE0E60E69E00A0803E /* TDXmlWhitespace.m in Sources */, + D31FE5FC0E60E6B500A0803E /* TDNCNameState.m in Sources */, + D31FE5FD0E60E6B500A0803E /* TDXmlName.m in Sources */, + D31FE5FE0E60E6B500A0803E /* TDXmlNameState.m in Sources */, + D31FE5FF0E60E6B500A0803E /* TDXmlNameTest.m in Sources */, + D31FE6000E60E6B500A0803E /* TDXmlNmtoken.m in Sources */, + D31FE6010E60E6B500A0803E /* TDXmlNmtokenState.m in Sources */, + D31FE6E00E60EE2500A0803E /* TDNCName.m in Sources */, + D3C85C7B0E63B438000445FD /* TDArithmeticParser.m in Sources */, + D3C85C800E63B9E9000445FD /* TDArithmeticParserTest.m in Sources */, + D3C85D450E63D1BF000445FD /* TDScientificNumberStateTest.m in Sources */, + D3EADD8E0E75EAA400F78584 /* TDHtmlSyntaxHighlighter.m in Sources */, + D38205BE0EEE48EE004340DD /* TDTokenTest.m in Sources */, + D36568A70EEF9FE900226554 /* TDPlistParser.m in Sources */, + D36568AA0EEFA05300226554 /* TDPlistParserTest.m in Sources */, + D3656DFE0EF2620E00226554 /* TDTokenArraySourceTest.m in Sources */, + D3C031ED0EF38D2D00C5ABEB /* TDLowercaseWordTest.m in Sources */, + D385F98E0F046FE900DB2946 /* TDGenericAssembler.m in Sources */, + D385FA230F04971400DB2946 /* TDGenericAssemblerTest.m in Sources */, + D385FD460F05A89100DB2946 /* TDMiniCSSAssemblerTest.m in Sources */, + D385FD490F05A8C900DB2946 /* TDMiniCSSAssembler.m in Sources */, + D3DDDA880F0779FD00A58000 /* TDSyntaxHighlighter.m in Sources */, + D3DDDAFE0F083C9700A58000 /* TDCommentStateTest.m in Sources */, + D380BA620F0F06CD0009EC13 /* TDParserFactoryTest.m in Sources */, + D389F5B60F19C76A00558235 /* TDJsonParser.m in Sources */, + D389F5B70F19C76A00558235 /* TDJsonParserTest.m in Sources */, + D31A16520F7038C2002AFDF1 /* TDJavaScriptParser.m in Sources */, + D3B43FB80F76E99C0072AF40 /* TDJavaScriptParserTest.m in Sources */, + D3E39C3F0FC5FFD10022DAB9 /* TDDelimitStateTest.m in Sources */, + D3252F7B0FCE1A7F005EF059 /* TDNSPredicateBuilderTest.m in Sources */, + D3252F7F0FCE1A87005EF059 /* TDNSPredicateBuilder.m in Sources */, + D3385FD90FCFB1FF003BF729 /* TDPredicateEvaluator.m in Sources */, + D3385FDE0FCFB227003BF729 /* TDPredicateEvaluatorTest.m in Sources */, + D36C53790FD27F1300141CB7 /* TDParserFactoryTest2.m in Sources */, + D36C562B0FD365DB00141CB7 /* TDPatternTest.m in Sources */, + D3AF49780FDB122E0032F4DC /* TDParserFactoryPatternTest.m in Sources */, + D355C62D0FE9EFD6006A91A4 /* TDNSPredicateEvaluator.m in Sources */, + D355C6310FE9EFEA006A91A4 /* TDNSPredicateEvaluatorTest.m in Sources */, + D3BBBC9E0FEC9756007DF30D /* TDXMLParser.m in Sources */, + D39E01340FEF02DA00150FC3 /* TDXMLParserTest.m in Sources */, + D338E5BB0FF5DDCB003DE6AA /* TDDifferenceTest.m in Sources */, + D34BAC230FF87F8600D7773A /* TDParserFactoryTest3.m in Sources */, + D34BAC4B0FF892C200D7773A /* XPathParserGrammarTest.m in Sources */, + D3126D0B0FFD9E4B00CBF4C4 /* TDNegationTest.m in Sources */, + D3376D8E10096C0700E4602E /* PKAST.m in Sources */, + D34BAD18100A9B7900996341 /* TDTokenizerStateTest.m in Sources */, + D3668296101D2C200008632C /* ERBTest.m in Sources */, + D3F55F611025737D00DD6DB1 /* TDParseTreeTest.m in Sources */, + D369345D1038DE5300527AF3 /* PKParseTree.m in Sources */, + D369345E1038DE5300527AF3 /* PKParseTreeAssembler.m in Sources */, + D369345F1038DE5300527AF3 /* PKRuleNode.m in Sources */, + D36934601038DE5300527AF3 /* PKTokenNode.m in Sources */, + D3D1BF2810394420003656E5 /* SAXAssembler.m in Sources */, + D3D1BF2B1039445C003656E5 /* SAXTest.m in Sources */, + D38E97CC1061CF6500739C39 /* TDTokenizerBlocksTest.m in Sources */, + D38E98D81062C5BA00739C39 /* TDParserBlocksTest.m in Sources */, + D319E42E106D8A31008C63DD /* TDArithmeticAssembler.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3FDC5800FFC4BFC00F1F797 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3FDC6EE0FFC4C9E00F1F797 /* RegexKitLite.m in Sources */, + D3FDC6EF0FFC4C9E00F1F797 /* PKReader.m in Sources */, + D3FDC6F00FFC4C9E00F1F797 /* PKAssembly.m in Sources */, + D3FDC6F10FFC4C9E00F1F797 /* PKParser.m in Sources */, + D3FDC6F20FFC4C9E00F1F797 /* PKRepetition.m in Sources */, + D3FDC6F30FFC4C9E00F1F797 /* PKCollectionParser.m in Sources */, + D3FDC6F40FFC4C9E00F1F797 /* PKAlternation.m in Sources */, + D3FDC6F50FFC4C9E00F1F797 /* PKSequence.m in Sources */, + D3FDC6F60FFC4C9E00F1F797 /* PKTrack.m in Sources */, + D3FDC6F70FFC4C9E00F1F797 /* PKTrackException.m in Sources */, + D3FDC6F80FFC4C9E00F1F797 /* PKDifference.m in Sources */, + D3FDC6F90FFC4C9E00F1F797 /* PKIntersection.m in Sources */, + D3FDC6FA0FFC4C9E00F1F797 /* PKTerminal.m in Sources */, + D3FDC6FB0FFC4C9E00F1F797 /* PKEmpty.m in Sources */, + D3FDC6FC0FFC4C9E00F1F797 /* PKTokenAssembly.m in Sources */, + D3FDC6FD0FFC4C9E00F1F797 /* PKToken.m in Sources */, + D3FDC6FE0FFC4C9E00F1F797 /* PKTokenArraySource.m in Sources */, + D3FDC6FF0FFC4C9E00F1F797 /* PKTokenizer.m in Sources */, + D3FDC7000FFC4C9E00F1F797 /* PKTokenizerState.m in Sources */, + D3FDC7010FFC4C9E00F1F797 /* PKNumberState.m in Sources */, + D3FDC7020FFC4C9E00F1F797 /* PKQuoteState.m in Sources */, + D3FDC7030FFC4C9E00F1F797 /* PKSymbolState.m in Sources */, + D3FDC7040FFC4C9E00F1F797 /* PKWordState.m in Sources */, + D3FDC7050FFC4C9E00F1F797 /* PKWhitespaceState.m in Sources */, + D3FDC7060FFC4C9E00F1F797 /* PKDelimitState.m in Sources */, + D3FDC7070FFC4C9E00F1F797 /* PKCommentState.m in Sources */, + D3FDC7080FFC4C9E00F1F797 /* PKSingleLineCommentState.m in Sources */, + D3FDC7090FFC4C9E00F1F797 /* PKMultiLineCommentState.m in Sources */, + D3FDC70A0FFC4C9E00F1F797 /* PKSymbolNode.m in Sources */, + D3FDC70B0FFC4C9E00F1F797 /* PKSymbolRootNode.m in Sources */, + D3FDC70C0FFC4C9E00F1F797 /* PKPattern.m in Sources */, + D3FDC70D0FFC4C9E00F1F797 /* PKWord.m in Sources */, + D3FDC70F0FFC4C9E00F1F797 /* PKQuotedString.m in Sources */, + D3FDC7100FFC4C9E00F1F797 /* PKSymbol.m in Sources */, + D3FDC7110FFC4C9E00F1F797 /* PKLiteral.m in Sources */, + D3FDC7120FFC4C9E00F1F797 /* PKCaseInsensitiveLiteral.m in Sources */, + D3FDC7130FFC4C9E00F1F797 /* PKWhitespace.m in Sources */, + D3FDC7140FFC4C9E00F1F797 /* PKComment.m in Sources */, + D3FDC7150FFC4C9E00F1F797 /* PKDelimitedString.m in Sources */, + D3FDC7160FFC4C9E00F1F797 /* PKAny.m in Sources */, + D3FDC7180FFC4C9E00F1F797 /* PKLowercaseWord.m in Sources */, + D3FDC7190FFC4C9E00F1F797 /* PKUppercaseWord.m in Sources */, + D3FDC71A0FFC4C9E00F1F797 /* PKCharacterAssembly.m in Sources */, + D3FDC71B0FFC4C9E00F1F797 /* PKChar.m in Sources */, + D3FDC71C0FFC4C9E00F1F797 /* PKDigit.m in Sources */, + D3FDC71D0FFC4C9E00F1F797 /* PKLetter.m in Sources */, + D3FDC71E0FFC4C9E00F1F797 /* PKSpecificChar.m in Sources */, + D3FDC71F0FFC4C9E00F1F797 /* PKParserFactory.m in Sources */, + D3FDC7200FFC4C9E00F1F797 /* NSArray+ParseKitAdditions.m in Sources */, + D3FDC7210FFC4C9E00F1F797 /* NSString+ParseKitAdditions.m in Sources */, + D3126DEC0FFDBC1D00CBF4C4 /* PKNegation.m in Sources */, + D3F0E3CC0FFEB70700C9DF74 /* PKNumber.m in Sources */, + D37A28671013942300E936B7 /* PKGrammarParser.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + D31FE7180E60F24700A0803E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D31FE7170E60F24700A0803E /* PBXContainerItemProxy */; + }; + D33494A00E296AA900406085 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D334949F0E296AA900406085 /* PBXContainerItemProxy */; + }; + D34185100E520D6F0081B0DC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D341850F0E520D6F0081B0DC /* PBXContainerItemProxy */; + }; + D389F1D40F19665C00558235 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DC2EF4F0486A6940098B216 /* ParseKit */; + targetProxy = D389F1D30F19665C00558235 /* PBXContainerItemProxy */; + }; + D389F20A0F196A8000558235 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D389F1CD0F1965E600558235 /* JSParseKit */; + targetProxy = D389F2090F196A8000558235 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 089C1667FE841158C02AAC07 /* English */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1DEB91AE08733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_TEST_COVERAGE_FILES = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKit_Prefix.pch; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvmgcc42; + GENERATE_PROFILING_CODE = YES; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(TARGET_BUILD_DIR)"; + LLVM_LTO = NO; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + ); + PRODUCT_NAME = ParseKit; + SDKROOT = ""; + WARNING_CFLAGS = "-Wundeclared-selector"; + WRAPPER_EXTENSION = framework; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB91AF08733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "$(TDPARSEKIT_FRAMEWORK_TARGET_PATH)"; + FRAMEWORK_VERSION = A; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKit_Prefix.pch; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvmgcc42; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(TARGET_BUILD_DIR)"; + LLVM_LTO = YES; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + ); + PRODUCT_NAME = ParseKit; + SDKROOT = ""; + TDPARSEKIT_FRAMEWORK_TARGET_PATH = "@executable_path/../Frameworks"; + WARNING_CFLAGS = "-Wundeclared-selector"; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; + 1DEB91B208733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Debug; + }; + 1DEB91B308733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Release; + }; + D33494130E2963FE00406085 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "demoapp/DemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DemoApp; + SDKROOT = ""; + WRAPPER_EXTENSION = app; + ZERO_LINK = YES; + }; + name = Debug; + }; + D33494140E2963FE00406085 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "demoapp/DemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DemoApp; + SDKROOT = ""; + WRAPPER_EXTENSION = app; + ZERO_LINK = NO; + }; + name = Release; + }; + D34185070E520D410081B0DC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/frameworks\""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_WARN_UNUSED_VARIABLE = NO; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "debugapp/DebugApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DebugApp; + SDKROOT = ""; + }; + name = Debug; + }; + D34185080E520D410081B0DC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/frameworks\""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "debugapp/DebugApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = DebugApp; + SDKROOT = ""; + ZERO_LINK = NO; + }; + name = Release; + }; + D389F1D00F1965E800558235 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + INFOPLIST_FILE = "JSParseKit-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Frameworks"; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSParseKit; + SDKROOT = ""; + }; + name = Debug; + }; + D389F1D10F1965E800558235 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_GC = YES; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + INFOPLIST_FILE = "JSParseKit-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Frameworks"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSParseKit; + SDKROOT = ""; + ZERO_LINK = NO; + }; + name = Release; + }; + D389F2060F196A7600558235 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_GC = required; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "jsdemoapp/JSDemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSDemoApp; + SDKROOT = ""; + }; + name = Debug; + }; + D389F2070F196A7600558235 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_GC = required; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "jsdemoapp/JSDemoApp-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = JSDemoApp; + SDKROOT = ""; + ZERO_LINK = NO; + }; + name = Release; + }; + D3C7D87D0A411FC0005DD154 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/frameworks\""; + FRAMEWORK_SEARCH_PATH_DEBUG_BUILD = "\"$(SRCROOT)/build/Debug\""; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "test/Tests-Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; + LIBRARY_SEARCH_PATHS = ""; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + MACOSX_DEPLOYMENT_TARGET = 10.5; + ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + SenTestingKit, + ); + PREBINDING = NO; + PRODUCT_NAME = Tests; + SDKROOT = ""; + USER_HEADER_SEARCH_PATHS = ""; + WARNING_CFLAGS = ""; + WRAPPER_EXTENSION = octest; + ZERO_LINK = YES; + }; + name = Debug; + }; + D3C7D87E0A411FC0005DD154 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc"; + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"/Library/Frameworks\""; + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/frameworks\""; + GCC_C_LANGUAGE_STANDARD = "compiler-default"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_ENABLE_OBJC_GC = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; + GCC_VERSION = com.apple.compilers.llvmgcc42; + HEADER_SEARCH_PATHS = "$(LIBXML_PATH)"; + INFOPLIST_FILE = "test/Tests-Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; + LIBXML_PATH = "\"/usr/include/libxml2/\""; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + SenTestingKit, + ); + PREBINDING = NO; + PRODUCT_NAME = Tests; + SDKROOT = ""; + WARNING_CFLAGS = ""; + WRAPPER_EXTENSION = octest; + ZERO_LINK = NO; + }; + name = Release; + }; + D3FDC5840FFC4BFC00F1F797 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKitMobile_Prefix.pch; + HEADER_SEARCH_PATHS = ""; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + PRODUCT_NAME = parsekit; + SDKROOT = iphoneos3.0; + }; + name = Debug; + }; + D3FDC5850FFC4BFC00F1F797 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + EXECUTABLE_PREFIX = ""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ParseKitMobile_Prefix.pch; + HEADER_SEARCH_PATHS = ""; + OTHER_LDFLAGS = ""; + PREBINDING = NO; + PRODUCT_NAME = parsekit; + SDKROOT = iphoneos3.0; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "ParseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91AE08733DA50010E9CD /* Debug */, + 1DEB91AF08733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ParseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91B208733DA50010E9CD /* Debug */, + 1DEB91B308733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D33494150E2963FE00406085 /* Build configuration list for PBXNativeTarget "DemoApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D33494130E2963FE00406085 /* Debug */, + D33494140E2963FE00406085 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D34185090E520D410081B0DC /* Build configuration list for PBXNativeTarget "DebugApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D34185070E520D410081B0DC /* Debug */, + D34185080E520D410081B0DC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D389F1D20F1965E800558235 /* Build configuration list for PBXNativeTarget "JSParseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D389F1D00F1965E800558235 /* Debug */, + D389F1D10F1965E800558235 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D389F2080F196A7600558235 /* Build configuration list for PBXNativeTarget "JSDemoApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D389F2060F196A7600558235 /* Debug */, + D389F2070F196A7600558235 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D3C7D87C0A411FC0005DD154 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D3C7D87D0A411FC0005DD154 /* Debug */, + D3C7D87E0A411FC0005DD154 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D3FDC62F0FFC4C2000F1F797 /* Build configuration list for PBXNativeTarget "ParseKitMobile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D3FDC5840FFC4BFC00F1F797 /* Debug */, + D3FDC5850FFC4BFC00F1F797 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0867D690FE84028FC02AAC07 /* Project object */; +} diff --git a/ParseKitMobile_Prefix.pch b/ParseKitMobile_Prefix.pch new file mode 100644 index 0000000..60e5b4c --- /dev/null +++ b/ParseKitMobile_Prefix.pch @@ -0,0 +1,5 @@ +#ifdef __OBJC__ + #import + #import + #import +#endif diff --git a/ParseKit_Prefix.pch b/ParseKit_Prefix.pch new file mode 100644 index 0000000..ec631e8 --- /dev/null +++ b/ParseKit_Prefix.pch @@ -0,0 +1,14 @@ +// +// Prefix header for all source files of the 'ParseKit' target in the 'ParseKit' project. +// + +#ifdef __OBJC__ + #import +#endif + +#if defined(MAC_OS_X_VERSION_10_6) && defined(TARGET_OS_MAC) + #define TARGET_OS_SNOW_LEOPARD +#endif + +#define PLATFORM(PK_FEATURE) (defined PK_PLATFORM_##PK_FEATURE && PK_PLATFORM_##PK_FEATURE) + diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..e69de29 diff --git a/debugapp/.svn/all-wcprops b/debugapp/.svn/all-wcprops new file mode 100644 index 0000000..ae14544 --- /dev/null +++ b/debugapp/.svn/all-wcprops @@ -0,0 +1,47 @@ +K 25 +svn:wc:ra_dav:version-url +V 33 +/svn/!svn/ver/1405/trunk/debugapp +END +main.m +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/583/trunk/debugapp/main.m +END +DebugAppMainMenu.xib +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/647/trunk/debugapp/DebugAppMainMenu.xib +END +JSONAssembler.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1405/trunk/debugapp/JSONAssembler.m +END +DebugAppDelegate.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1171/trunk/debugapp/DebugAppDelegate.h +END +DebugApp-Info.plist +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1173/trunk/debugapp/DebugApp-Info.plist +END +DebugAppDelegate.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1365/trunk/debugapp/DebugAppDelegate.m +END +JSONAssembler.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1171/trunk/debugapp/JSONAssembler.h +END diff --git a/debugapp/.svn/entries b/debugapp/.svn/entries new file mode 100644 index 0000000..310e646 --- /dev/null +++ b/debugapp/.svn/entries @@ -0,0 +1,273 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/debugapp +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + + + + + + +0 + +main.m +file + + + + +2009-06-16T06:56:24.000000Z +fb19bae94920d49fd7c1459593d19bf3 +2009-01-11T01:15:32.782160Z +583 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +256 + +DebugAppMainMenu.xib +file + + + + +2009-01-21T20:59:46.000000Z +03ecb4bb9b7274244a359af9e9116fc5 +2009-01-21T19:56:44.943333Z +647 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +153676 + +JSONAssembler.m +file + + + + +2009-11-13T07:14:30.000000Z +875a47aff9e3f18fcc8e97569e1b3bd3 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +6095 + +DebugAppDelegate.h +file + + + + +2009-07-03T19:31:31.000000Z +6613e707e43f42ae0bcd0c50db743bd4 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +343 + +DebugApp-Info.plist +file + + + + +2009-07-03T20:30:15.000000Z +84e79a9792ef7d7c36e888315f843322 +2009-07-03T20:39:51.719779Z +1173 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +756 + +DebugAppDelegate.m +file + + + + +2009-09-04T02:11:38.000000Z +ac89521d384479682eabd8290dc861ee +2009-09-04T02:11:47.318283Z +1365 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +18661 + +JSONAssembler.h +file + + + + +2009-07-03T19:31:30.000000Z +cae2b7069c00d1a5a53c923b1cb9f16d +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +868 + diff --git a/debugapp/.svn/text-base/DebugApp-Info.plist.svn-base b/debugapp/.svn/text-base/DebugApp-Info.plist.svn-base new file mode 100644 index 0000000..9bfec49 --- /dev/null +++ b/debugapp/.svn/text-base/DebugApp-Info.plist.svn-base @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + DebugAppMainMenu + NSPrincipalClass + NSApplication + + diff --git a/debugapp/.svn/text-base/DebugAppDelegate.h.svn-base b/debugapp/.svn/text-base/DebugAppDelegate.h.svn-base new file mode 100644 index 0000000..73ad6d8 --- /dev/null +++ b/debugapp/.svn/text-base/DebugAppDelegate.h.svn-base @@ -0,0 +1,17 @@ +// +// DebugAppDelegate.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/12/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface DebugAppDelegate : NSObject { + NSAttributedString *displayString; +} +- (IBAction)run:(id)sender; + +@property (retain) NSAttributedString *displayString; +@end diff --git a/debugapp/.svn/text-base/DebugAppDelegate.m.svn-base b/debugapp/.svn/text-base/DebugAppDelegate.m.svn-base new file mode 100644 index 0000000..79f7c52 --- /dev/null +++ b/debugapp/.svn/text-base/DebugAppDelegate.m.svn-base @@ -0,0 +1,510 @@ +// +// DebugAppDelegate.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/12/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "DebugAppDelegate.h" +#import +#import "PKParserFactory.h" +#import "TDJsonParser.h" +#import "TDFastJsonParser.h" +#import "TDRegularParser.h" +#import "EBNFParser.h" +#import "TDPlistParser.h" +#import "TDXmlNameState.h" +#import "TDXmlToken.h" +#import "TDHtmlSyntaxHighlighter.h" +#import "JSONAssembler.h" +#import "TDMiniCSSAssembler.h" +#import "TDGenericAssembler.h" +#import "NSArray+ParseKitAdditions.h" +#import "TDSyntaxHighlighter.h" +#import "TDJavaScriptParser.h" +#import "TDNSPredicateEvaluator.h" +#import + +@protocol TDMockAssember +- (void)didMatchFoo:(PKAssembly *)a; +- (void)didMatchBaz:(PKAssembly *)a; +- (void)didMatchStart:(PKAssembly *)a; +- (void)didMatchStart:(PKAssembly *)a; +- (void)didMatch_Start:(PKAssembly *)a; +@end + +@interface PKParserFactory () +- (PKSequence *)parserFromExpression:(NSString *)s; +@property (retain) PKCollectionParser *expressionParser; +@end + +@implementation DebugAppDelegate + +- (void)dealloc { + self.displayString = nil; + [super dealloc]; +} + + +- (void)doPlistParser { + NSString *s = nil; + PKTokenAssembly *a = nil; + PKAssembly *res = nil; + TDPlistParser *p = nil; + + p = [[[TDPlistParser alloc] init] autorelease]; + + s = @"{" + @" 0 = 0;" + @" dictKey = {" + @" bar = foo;" + @" };" + @" 47 = 0;" + @" IntegerKey = 1;" + @" 47.7 = 0;" + @" = ;" + @" ArrayKey = (" + @" \"one one\"," + @" two," + @" three" + @" );" + @" \"Null Key\" = ;" + @" emptyDictKey = {" + @" };" + @" StringKey = String;" + @" \"1.0\" = 1;" + @" YESKey = 1;" + @" \"NO Key\" = 0;" + @"}"; + + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + + id attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSColor whiteColor], NSForegroundColorAttributeName, + [NSFont fontWithName:@"Monaco" size:12.], NSFontAttributeName, + nil]; + id dict = [res pop]; + + p.tokenizer.string = [[[dict description] copy] autorelease]; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser bestMatchFor:a]; + dict = [res pop]; + + p.tokenizer.string = nil; // prevent retain cycle leak + s = [[[dict description] copy] autorelease]; + + self.displayString = [[[NSAttributedString alloc] initWithString:s attributes:attrs] autorelease]; +} + + +- (void)doHtmlSyntaxHighlighter { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"nyt" ofType:@"html"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + //NSString *s = @"ア"; + + TDHtmlSyntaxHighlighter *highlighter = [[TDHtmlSyntaxHighlighter alloc] initWithAttributesForDarkBackground:YES]; + NSAttributedString *o = [highlighter attributedStringForString:s]; + //NSLog(@"o: %@", [o string]); + self.displayString = o; + [highlighter release]; +} + + +- (void)doJsonParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + TDJsonParser *p = [[[TDJsonParser alloc] init] autorelease]; +// TDFastJsonParser *p = [[[TDFastJsonParser alloc] init] autorelease]; + + id result = nil; + + @try { + result = [p parse:s]; + } @catch (NSException *e) { + NSLog(@"\n\n\nexception:\n\n %@", [e reason]); + } + NSLog(@"result %@", result); +} + + +- (void)doEBNFParser { + //NSString *s = @"foo (bar|baz)*;"; + NSString *s = @"$baz = bar; ($baz|foo)*;"; + //NSString *s = @"foo;"; + EBNFParser *p = [[[EBNFParser alloc] init] autorelease]; + + // PKAssembly *a = [p bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + // NSLog(@"a: %@", a); + // NSLog(@"a.target: %@", a.target); + + PKParser *res = [p parse:s]; + // NSLog(@"res: %@", res); + // NSLog(@"res: %@", res.string); + // NSLog(@"res.subparsers: %@", res.subparsers); + // NSLog(@"res.subparsers 0: %@", [[res.subparsers objectAtIndex:0] string]); + // NSLog(@"res.subparsers 1: %@", [[res.subparsers objectAtIndex:1] string]); + + s = @"bar foo bar foo"; + PKAssembly *a = [res completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + NSLog(@"\n\na: %@\n\n", a); +} + + +- (void)doGrammarParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; +// s = @"@start = openCurly closeCurly; openCurly = '{'; closeCurly = '}';"; +// s = @"@start = start*; start = 'bar';"; + + PKParserFactory *factory = [PKParserFactory factory]; + + JSONAssembler *ass = [[[JSONAssembler alloc] init] autorelease]; + PKParser *lp = [factory parserFromGrammar:s assembler:ass]; + + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + +// s = @"bar bar"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; + a.preservesWhitespaceTokens = YES; + //PKAssembly *res = + [lp completeMatchFor:a]; + + self.displayString = ass.displayString; +} + + +- (void)doJavaScriptGrammarParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"javascript" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKParser *p = [[PKParserFactory factory] parserFromGrammar:s assembler:nil]; + //PKParser *plus = [p parserNamed:@"plus"]; + + s = @";"; + p.tokenizer.string = s; + //PKAssembly *a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + //PKAssembly *res = [p bestMatchFor:a]; + // TDEqualObjects(@"[var, foo, =, 'bar', ;]var/foo/=/bar/;^", [res description]); +} + + +- (void)doProf { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json_with_discards" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + NSDate *start = [NSDate date]; + while ((tok = [t nextToken]) != eof) ; + CGFloat ms4tok = -([start timeIntervalSinceNow]); + + PKParserFactory *factory = [PKParserFactory factory]; + TDJsonParser *p = nil; + + p = [[[TDJsonParser alloc] initWithIntentToAssemble:NO] autorelease]; + + //JSONAssembler *assembler = [[[JSONAssembler alloc] init] autorelease]; + start = [NSDate date]; + PKParser *lp = [factory parserFromGrammar:s assembler:p]; + CGFloat ms4grammar = -([start timeIntervalSinceNow]); + + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + start = [NSDate date]; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + a = [lp completeMatchFor:a]; + CGFloat ms4json = -([start timeIntervalSinceNow]); + + PKReleaseSubparserTree(lp); + + p = [[TDJsonParser alloc] initWithIntentToAssemble:NO]; + start = [NSDate date]; + id res = [p parse:s]; + CGFloat ms4json2 = -([start timeIntervalSinceNow]); + [p release]; + + p = [[TDJsonParser alloc] initWithIntentToAssemble:YES]; + start = [NSDate date]; + res = [p parse:s]; + CGFloat ms4json3 = -([start timeIntervalSinceNow]); + [p release]; + + id fp = [[[TDFastJsonParser alloc] init] autorelease]; + start = [NSDate date]; + res = [fp parse:s]; + CGFloat ms4json4 = -([start timeIntervalSinceNow]); + + id attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont fontWithName:@"Monaco" size:14.], NSFontAttributeName, + [NSColor whiteColor], NSForegroundColorAttributeName, + nil]; + + s = [NSString stringWithFormat:@"tokenization: %f \n\ngrammar parse: %f sec\n\nlp json parse: %f sec\n\np json parse (not assembled): %f sec\n\np json parse (assembled): %f sec\n\nfast json parse (assembled): %f sec\n\n %f", ms4tok, ms4grammar, ms4json, ms4json2, ms4json3, ms4json4, (ms4json3/ms4json4)]; + self.displayString = [[[NSMutableAttributedString alloc] initWithString:s attributes:attrs] autorelease]; +} + + +- (void)doTokenize { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + NSDate *start = [NSDate date]; + while ((tok = [t nextToken]) != eof) ; + CGFloat secs = -([start timeIntervalSinceNow]); + + id attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont fontWithName:@"Monaco" size:14.], NSFontAttributeName, + [NSColor whiteColor], NSForegroundColorAttributeName, + nil]; + + s = [NSString stringWithFormat:@"tokenize: %f", secs]; + self.displayString = [[[NSMutableAttributedString alloc] initWithString:s attributes:attrs] autorelease]; +} + + +- (void)doSimpleCSS { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKParserFactory *factory = [PKParserFactory factory]; + + TDMiniCSSAssembler *assembler = [[[TDMiniCSSAssembler alloc] init] autorelease]; + PKParser *lp = [factory parserFromGrammar:s assembler:assembler]; + s = @"foo { color:rgb(111.0, 99.0, 255.0); }"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + a = [lp completeMatchFor:a]; + +} + + +- (void)doSimpleCSS2 { + PKParserFactory *factory = [PKParserFactory factory]; + + // create CSS parser + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + NSString *grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDMiniCSSAssembler *cssAssembler = [[[TDMiniCSSAssembler alloc] init] autorelease]; + PKParser *cssParser = [factory parserFromGrammar:grammarString assembler:cssAssembler]; + + // parse CSS + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"css"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + a = [cssParser bestMatchFor:a]; + + // get attributes from css + id attrs = cssAssembler.attributes; + + // create JSON Parser + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"grammar"]; + grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDGenericAssembler *genericAssembler = [[[TDGenericAssembler alloc] init] autorelease]; + + // give it the attrs from CSS + genericAssembler.attributes = attrs; + PKParser *jsonParser = [factory parserFromGrammar:grammarString assembler:genericAssembler]; + + // parse JSON + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + // take care to preseve the whitespace in the JSON + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + PKTokenAssembly *a1 = [PKTokenAssembly assemblyWithTokenizer:t]; + a1.preservesWhitespaceTokens = YES; +// [jsonParser completeMatchFor:a1]; +// self.displayString = genericAssembler.displayString; + self.displayString = [[jsonParser completeMatchFor:a1] target]; +} + + +- (void)doJSONHighlighting { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDSyntaxHighlighter *shc = [[[TDSyntaxHighlighter alloc] init] autorelease]; + self.displayString = [shc highlightedStringForString:s ofGrammar:@"json"]; +} + + +- (void)doCSSHighlighting { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"example" ofType:@"css"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDSyntaxHighlighter *shc = [[[TDSyntaxHighlighter alloc] init] autorelease]; + self.displayString = [shc highlightedStringForString:s ofGrammar:@"css"]; +} + + +- (void)doHTMLHighlighting { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"example" ofType:@"html"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDSyntaxHighlighter *shc = [[[TDSyntaxHighlighter alloc] init] autorelease]; + self.displayString = [shc highlightedStringForString:s ofGrammar:@"html"]; +} + + +- (void)doMultiLineComment { + NSString *s = @"/* foo */ "; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + t.commentState.reportsCommentTokens = YES; + //PKToken *tok = + [t nextToken]; +} + + +- (void)doRubyHashParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"rubyhash" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKParser *lp = [[PKParserFactory factory] parserFromGrammar:s assembler:nil]; + + s = @"{\"brand\"=>{\"name\"=>\"something\"," + @"\"logo\"=>#," + @"\"summary\"=>\"wee\", \"content\"=>\"woopy doo\"}, \"commit\"=>\"Save\"," + @"\"authenticity_token\"=>\"43a94d60304a7fb13a4ff61a5960461ce714e92b\"," + @"\"action\"=>\"create\", \"controller\"=>\"admin/brands\"}"; + + NSLog(@"%@", [lp parse:s]); +} + + + +- (void)doFactory { +// id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; +// PKParserFactory *factory = [PKParserFactory factory]; +// NSString *s = nil; +// s = @"@start = foo|baz; foo (didMatchFooAssembly:) = 'bar'; baz (didMatchBazAssembly:) = 'bat'"; +// factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnExplicit; +// PKParser *lp = [factory parserFromGrammar:s assembler:mock]; +// +//// [[mock expect] didMatchBazAssembly:OCMOCK_ANY]; +//// NSString *s = @"bar bat"; +//// a = [PKTokenAssembly assemblyWithString:s]; +//// res = [lp completeMatchFor:a]; +//// TDEqualObjects(@"[bar, bat]bar/bat^", [res description]); +//// [mock verify]; + +// NSString *g = @"@delimitState = '$'; @delimitedString = '$' '%' nil; @start = DelimitedString('$', '%');"; +// PKParser *lp = [[PKParserFactory factory] parserFromGrammar:g assembler:nil]; +// +// NSString *s = @"$foo%"; +// PKTokenizer *t = lp.tokenizer; +// t.string = s; +// PKAssembly *res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xpath1_0" ofType:@"grammar"]; + NSString *g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:nil]; + PKTokenizer *t = p.tokenizer; + t.string = @"foo"; + //PKAssembly *res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + +} + + +- (void)doParenStuff { + NSString *s = @"-(ab+5)"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + +// TDTrue(tok.isSymbol); +// TDEqualObjects(tok.stringValue, @"-"); +// TDEquals((CGFloat)0.0, tok.floatValue); + + tok = [t nextToken]; +// TDTrue(tok.isSymbol); +// TDEqualObjects(tok.stringValue, @"("); +// TDEquals((CGFloat)0.0, tok.floatValue); +} + + +- (void)doDelimitedString { + NSString *s = @""; + + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + NSCharacterSet *cs = nil; + + [t setTokenizerState:t.delimitState from:'<' to:'<']; + [t.delimitState addStartMarker:@"" allowedCharacterSet:cs]; + +// PKToken *tok = [t nextToken]; + + //TDTrue(tok.isDelimitedString); + +} + + +- (void)doJSParser { + TDJavaScriptParser *jsp = [TDJavaScriptParser parser]; + NSString *s = @"for( ; true; true) {}"; + jsp.tokenizer.string = s; +// PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; +// id res = [jsp bestMatchFor:a]; + //TDEqualObjects([res description], @"['foo']'foo'^"); + + //TDEqualObjects([res description], @"[for, (, ;, true, ;, true, ), {, }]for/(/;/true/;/true/)/{/}^"); +} + + +- (void)doNSPredicateEvaluator { + //TDNSPredicateEvaluator *eval = [[[TDNSPredicateEvaluator alloc] initWithKeyPathResolver:nil] autorelease]; +} + + +- (void)doXMLParser { +// NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xml" ofType:@"grammar"]; +// NSString *g = [NSString stringWithContentsOfFile:path]; +// PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self]; +// PKTokenizer *t = p.tokenizer; +} + + + + +- (IBAction)run:(id)sender { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + +// [self doPlistParser]; +// [self doHtmlSyntaxHighlighter]; +// [self doJsonParser]; +// [self doRubyHashParser]; + +// [self doJSParser]; + + [self doProf]; + + //[self doJavaScriptGrammarParser]; + + // [self doTokenize]; +// [self doGrammarParser]; +// [self doSimpleCSS]; +// [self doSimpleCSS2]; +// [self doParenStuff]; + +// [self doJSONHighlighting]; +// [self doCSSHighlighting]; +// [self doHTMLHighlighting]; + +// [self doMultiLineComment]; +// [self doDelimitedString]; + +// [self doFactory]; + +// [self doXMLParser]; +// [self doNSPredicateEvaluator]; + + [pool drain]; +} + +@synthesize displayString; +@end diff --git a/debugapp/.svn/text-base/DebugAppMainMenu.xib.svn-base b/debugapp/.svn/text-base/DebugAppMainMenu.xib.svn-base new file mode 100644 index 0000000..b739318 --- /dev/null +++ b/debugapp/.svn/text-base/DebugAppMainMenu.xib.svn-base @@ -0,0 +1,3529 @@ + + + + 1050 + 9G55 + 677 + 949.43 + 353.00 + + YES + + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + NSFontManager + + + AMainMenu + + YES + + + DebugApp + + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + DebugApp + + YES + + + About DebugApp + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Services + + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 2147483647 + + + + + + Hide DebugApp + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Quit DebugApp + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + T3BlbuKApg + o + 1048576 + 2147483647 + + + + + + Open Recent + + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + U2F2ZSBBc+KApg + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + UHJpbnTigKY + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Find + + 2147483647 + + + submenuAction: + + Find + + YES + + + RmluZOKApg + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + U2hvdyBTcGVsbGluZ+KApg + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 2147483647 + + + + + + Check Grammar With Spelling + + 2147483647 + + + + + + + + + Substitutions + + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 2147483647 + + + + + + Stop Speaking + + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Q3VzdG9taXplIFRvb2xiYXLigKY + + 2147483647 + + + + + + + + + Window + + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bring All to Front + + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + NewApplication Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + 15 + 2 + {{479, 251}, {504, 447}} + 611844096 + Window + NSWindow + + {3.40282e+38, 3.40282e+38} + {484, 310} + + + 256 + + YES + + + 266 + {{14, 293}, {476, 32}} + + YES + + 67239424 + 134217728 + Run + + LucidaGrande + 1.300000e+01 + 1044 + + + -2038284033 + 129 + + DQ + 200 + 25 + + + + + 266 + {{17, 342}, {470, 85}} + + YES + + 67239424 + 272629760 + VGhlIHB1cnBvc2Ugb2YgdGhpcyBhcHBsaWNhdGlvbiBpcyBvbmx5IHRvIHJ1biBhcmJ0cmFyeSB0ZXN0 +IGNvZGUgaW4gIkRlYnVnIiBtb2RlIHVzaW5nIEdEQiBhbmQgYnJlYWtwb2ludHMgKHdoaWNoIGRvZXMg +bm90IHNlZW0gdG8gYmUgcG9zc2libGUgZm9tIHRoZSBVbml0VGVzdCBCdW5kbGUpLiBUbyB1c2UsIGNv +cHkgc29tZSB1bml0IHRlc3QgY29kZSBvdmVyIHRvIHRoZSAtW0RlYnVnQXBwRGVsZWdhdGUgcnVuOl0g +YWN0aW9uIG1ldGhvZCB3aGljaCBpcyBleGVjdXRlZCB3aGVuIHRoZSAiUnVuIiBidXR0b24gYmVsb3cg +aXMgY2xpY2tlZC4 + + LucidaGrande + 1.300000e+01 + 16 + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 274 + + YES + + + 2304 + + YES + + + 2322 + {447, 96} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + YES + + YES + + YES + NSFont + NSParagraphStyle + + + YES + + LucidaGrande + 1.000000e+01 + 2843 + + + 3 + + YES + + 0.000000e+00 + + + 5.600000e+01 + + + 1.120000e+02 + + + 1.680000e+02 + + + 2.240000e+02 + + + 2.800000e+02 + + + 3.360000e+02 + + + 3.920000e+02 + + + 4.480000e+02 + + + 5.040000e+02 + + + 5.600000e+02 + + + 6.160000e+02 + + + 6.720000e+02 + + + 7.280000e+02 + + + 7.840000e+02 + + + 8.400000e+02 + + + 8.960000e+02 + + + 9.520000e+02 + + + 1.008000e+03 + + + 1.064000e+03 + + + 1.120000e+03 + + + 1.176000e+03 + + + 1.232000e+03 + + + 1.288000e+03 + + + 1.344000e+03 + + + 1.400000e+03 + + + 1.456000e+03 + + + 1.512000e+03 + + + 1.568000e+03 + + + 1.624000e+03 + + + 1.680000e+03 + + + 1.736000e+03 + + + + + + + YES + + YES + NSFont + NSParagraphStyle + + + YES + + LucidaGrande-Bold + 1.000000e+01 + 16 + + + 3 + + YES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GQAEAQgADAEiAAcBhAQAA + + + + + YES + + + 6 + + + + 4.470000e+02 + 1 + + + 11621 + + 1 + MC4xMTc2NDcwNiAwLjExNzY0NzA2IDAuMTQxMTc2NDgAA + + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + 6 + System + selectedTextBackgroundColor + + + + 6 + System + selectedTextColor + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + 1 + MCAwIDEAA + + + + + + + 6 + {3081, 1e+07} + {223, 0} + + + + {{1, 1}, {447, 259}} + + + + + 3 + MQA + + + {4, -5} + 1 + + 4 + + + + 256 + {{448, 1}, {15, 259}} + + + _doScroller: + 9.843750e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{20, 20}, {464, 261}} + + + 18 + + + + + + {504, 447} + + + {{0, 0}, {1440, 878}} + {484, 332} + {3.40282e+38, 3.40282e+38} + + + DebugAppDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + terminate: + + + + 369 + + + + unhideAllApplications: + + + + 370 + + + + addFontTrait: + + + + 418 + + + + addFontTrait: + + + + 419 + + + + modifyFont: + + + + 420 + + + + orderFrontFontPanel: + + + + 421 + + + + modifyFont: + + + + 422 + + + + raiseBaseline: + + + + 423 + + + + lowerBaseline: + + + + 424 + + + + copyFont: + + + + 425 + + + + subscript: + + + + 426 + + + + superscript: + + + + 427 + + + + tightenKerning: + + + + 428 + + + + underline: + + + + 429 + + + + orderFrontColorPanel: + + + + 430 + + + + useAllLigatures: + + + + 431 + + + + loosenKerning: + + + + 432 + + + + pasteFont: + + + + 433 + + + + unscript: + + + + 434 + + + + useStandardKerning: + + + + 435 + + + + useStandardLigatures: + + + + 436 + + + + turnOffLigatures: + + + + 437 + + + + turnOffKerning: + + + + 438 + + + + alignLeft: + + + + 439 + + + + alignJustified: + + + + 440 + + + + copyRuler: + + + + 441 + + + + alignCenter: + + + + 442 + + + + toggleRuler: + + + + 443 + + + + alignRight: + + + + 444 + + + + pasteRuler: + + + + 445 + + + + run: + + + + 454 + + + + attributedString: displayString + + + + + + attributedString: displayString + attributedString + displayString + + NSContinuouslyUpdatesValue + + + 2 + + + 462 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + 3 + + + 80 + + + 8 + + + 78 + + + 6 + + + 72 + + + + + 82 + + + 9 + + + 124 + + + YES + + + + + + 77 + + + 5 + + + 73 + + + 1 + + + 79 + + + 7 + + + 112 + + + 10 + + + 74 + + + 2 + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + + + 373 + + + YES + + + + + + 374 + + + YES + + + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + 377 + + + YES + + + + + + + + + + + + + 378 + + + + + 379 + + + + + 380 + + + + + 381 + + + + + 382 + + + + + 383 + + + + + 384 + + + + + 385 + + + + + 386 + + + YES + + + + + + + + + + + + + + + + + + + + + 387 + + + + + 388 + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + YES + + + + + + 396 + + + YES + + + + + + 397 + + + YES + + + + + + 398 + + + + + 399 + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + YES + + + + + + + + + + 404 + + + + + 405 + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + YES + + + + + + + + 410 + + + + + 411 + + + + + 412 + + + + + 413 + + + YES + + + + + + + + + 414 + + + + + 415 + + + + + 416 + + + + + 417 + + + + + 446 + + + YES + + + + + + 447 + + + YES + + + + + + + + 448 + + + + + 449 + + + YES + + + + + + 450 + + + + + 452 + + + YES + + + + + + 453 + + + + + 455 + + + YES + + + + + + + + 456 + + + + + 457 + + + + + 458 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBEditorWindowLastContentRect + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBEditorWindowLastContentRect + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 371.IBPluginDependency + 373.IBPluginDependency + 374.IBPluginDependency + 375.IBPluginDependency + 376.IBPluginDependency + 377.IBPluginDependency + 378.IBPluginDependency + 379.IBPluginDependency + 380.IBPluginDependency + 381.IBPluginDependency + 382.IBPluginDependency + 383.IBPluginDependency + 384.IBPluginDependency + 385.IBPluginDependency + 386.IBPluginDependency + 387.IBPluginDependency + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 446.IBEditorWindowLastContentRect + 446.IBWindowTemplateEditedContentRect + 446.NSWindowTemplate.visibleAtLaunch + 446.windowTemplate.hasMinSize + 446.windowTemplate.minSize + 447.IBPluginDependency + 448.IBPluginDependency + 449.IBPluginDependency + 450.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 455.IBPluginDependency + 456.IBPluginDependency + 457.IBPluginDependency + 458.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + {{553, 524}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{596, 852}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{479, 484}, {132, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{565, 284}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{322, 304}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{365, 632}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{565, 284}, {153, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{565, 284}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{798, 236}, {197, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{490, 309}, {440, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 977}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{432, 504}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{565, 284}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{511, 212}, {504, 447}} + {{511, 212}, {504, 447}} + + + {484, 310} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{556, 261}, {211, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{280, 344}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{323, 672}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 462 + + + + YES + + DebugAppDelegate + NSObject + + run: + id + + + IBProjectSource + debugapp/DebugAppDelegate.h + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + + 0 + ../TDParseKit.xcodeproj + 3 + + diff --git a/debugapp/.svn/text-base/JSONAssembler.h.svn-base b/debugapp/.svn/text-base/JSONAssembler.h.svn-base new file mode 100644 index 0000000..7bf1018 --- /dev/null +++ b/debugapp/.svn/text-base/JSONAssembler.h.svn-base @@ -0,0 +1,36 @@ +// +// JSONAssembler.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKToken; + +@interface JSONAssembler : NSObject { + NSMutableAttributedString *displayString; + id defaultAttrs; + id objectAttrs; + id arrayAttrs; + id propertyNameAttrs; + id valueAttrs; + id constantAttrs; + + PKToken *comma; + PKToken *curly; + PKToken *bracket; +} +@property (retain) NSMutableAttributedString *displayString; +@property (retain) id defaultAttrs; +@property (retain) id objectAttrs; +@property (retain) id arrayAttrs; +@property (retain) id propertyNameAttrs; +@property (retain) id valueAttrs; +@property (retain) id constantAttrs; +@property (retain) PKToken *comma; +@property (retain) PKToken *curly; +@property (retain) PKToken *bracket; +@end diff --git a/debugapp/.svn/text-base/JSONAssembler.m.svn-base b/debugapp/.svn/text-base/JSONAssembler.m.svn-base new file mode 100644 index 0000000..19641c4 --- /dev/null +++ b/debugapp/.svn/text-base/JSONAssembler.m.svn-base @@ -0,0 +1,163 @@ +// +// JSONAssembler.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "JSONAssembler.h" +#import "NSArray+ParseKitAdditions.h" +#import + +@implementation JSONAssembler + +- (id)init { + self = [super init]; + if (self != nil) { + NSColor *textColor = [NSColor whiteColor]; + NSColor *tagColor = [NSColor colorWithDeviceRed:.70 green:.14 blue:.53 alpha:1.]; + NSColor *attrNameColor = [NSColor colorWithDeviceRed:.33 green:.45 blue:.48 alpha:1.]; + NSColor *attrValueColor = [NSColor colorWithDeviceRed:.77 green:.18 blue:.20 alpha:1.]; + NSColor *commentColor = [NSColor colorWithDeviceRed:.24 green:.70 blue:.27 alpha:1.]; + NSColor *piColor = [NSColor colorWithDeviceRed:.09 green:.62 blue:.74 alpha:1.]; + + NSFont *monacoFont = [NSFont fontWithName:@"Monaco" size:11.]; + + self.defaultAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + textColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.objectAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + tagColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.propertyNameAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + attrNameColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.valueAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + attrValueColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.constantAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + piColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.arrayAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + commentColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + + self.displayString = [[[NSMutableAttributedString alloc] initWithString:@"" attributes:defaultAttrs] autorelease]; + + self.comma = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"," floatValue:0]; + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0]; + self.bracket = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"[" floatValue:0]; + } + return self; +} + + +- (void)dealloc { + self.displayString = nil; + self.defaultAttrs = nil; + self.objectAttrs = nil; + self.arrayAttrs = nil; + self.propertyNameAttrs = nil; + self.valueAttrs = nil; + self.constantAttrs = nil; + self.comma = nil; + self.curly = nil; + self.bracket = nil; + [super dealloc]; +} + + +- (void)appendAttributedStringForObjects:(NSArray *)objs withAttrs:(id)attrs { + for (id obj in objs) { + NSAttributedString *as = [[NSAttributedString alloc] initWithString:[obj stringValue] attributes:attrs]; + [displayString appendAttributedString:as]; + [as release]; + } +} + + +- (void)consumeWhitespaceFrom:(PKAssembly *)a { + NSMutableArray *whitespaceToks = [NSMutableArray array]; + PKToken *tok = nil; + while (1) { + tok = [a pop]; + if (PKTokenTypeWhitespace == tok.tokenType) { + [whitespaceToks addObject:tok]; + } else { + [a push:tok]; + break; + } + } + + if ([whitespaceToks count]) { + whitespaceToks = [whitespaceToks reversedMutableArray]; + [self appendAttributedStringForObjects:whitespaceToks withAttrs:defaultAttrs]; + } +} + + +- (void)didMatchSymbolChar:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:objectAttrs]; +} + + +- (void)didMatchPropertyName:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:propertyNameAttrs]; +} + + +- (void)didMatchString:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:arrayAttrs]; +} + + +- (void)didMatchNumber:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:valueAttrs]; +} + + +- (void)didMatchConstant:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:constantAttrs]; +} + + +- (void)didMatchNull:(PKAssembly *)a { [self didMatchConstant:a]; } +- (void)didMatchTrue:(PKAssembly *)a { [self didMatchConstant:a]; } +- (void)didMatchFalse:(PKAssembly *)a { [self didMatchConstant:a]; } + +- (void)didMatchColon:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchComma:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchOpenCurly:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchCloseCurly:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchOpenBracket:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchCloseBracket:(PKAssembly *)a { [self didMatchSymbolChar:a]; } + +@synthesize displayString; +@synthesize defaultAttrs; +@synthesize objectAttrs; +@synthesize arrayAttrs; +@synthesize propertyNameAttrs; +@synthesize valueAttrs; +@synthesize constantAttrs; +@synthesize comma; +@synthesize curly; +@synthesize bracket; +@end + diff --git a/debugapp/.svn/text-base/main.m.svn-base b/debugapp/.svn/text-base/main.m.svn-base new file mode 100644 index 0000000..ec133b9 --- /dev/null +++ b/debugapp/.svn/text-base/main.m.svn-base @@ -0,0 +1,13 @@ +// +// main.m +// TestApp +// +// Created by Todd Ditchendorf on 7/12/08. +// Copyright Todd Ditchendorf 2008. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) { + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/debugapp/.svn/tmp/tempfile.tmp b/debugapp/.svn/tmp/tempfile.tmp new file mode 100644 index 0000000..fd75b38 --- /dev/null +++ b/debugapp/.svn/tmp/tempfile.tmp @@ -0,0 +1,433 @@ +// +// DebugAppDelegate.m +// TDParseKit +// +// Created by Todd Ditchendorf on 8/12/08. +// Copyright 2008 Todd Ditchendorf. All rights reserved. +// + +#import "DebugAppDelegate.h" +#import +#import "TDJsonParser.h" +#import "TDFastJsonParser.h" +#import "TDRegularParser.h" +#import "EBNFParser.h" +#import "TDPlistParser.h" +#import "TDXmlNameState.h" +#import "TDXmlToken.h" +#import "TDHtmlSyntaxHighlighter.h" +#import "TDParserFactory.h" +#import "JSONAssembler.h" +#import "TDMiniCSSAssembler.h" +#import "TDGenericAssembler.h" +#import "NSArray+TDParseKitAdditions.h" +#import "TDSyntaxHighlighter.h" +#import + +@protocol TDMockAssember +- (void)workOnFooAssembly:(TDAssembly *)a; +- (void)workOnBazAssembly:(TDAssembly *)a; +- (void)workOnStart:(TDAssembly *)a; +- (void)workOnStartAssembly:(TDAssembly *)a; +- (void)workOn_StartAssembly:(TDAssembly *)a; +@end + +@interface TDParserFactory () +- (TDSequence *)parserFromExpression:(NSString *)s; +@property (retain) TDCollectionParser *expressionParser; +@end + +@implementation DebugAppDelegate + +- (void)dealloc { + self.displayString = nil; + [super dealloc]; +} + + +- (void)doPlistParser { + NSString *s = nil; + TDTokenAssembly *a = nil; + TDAssembly *res = nil; + TDPlistParser *p = nil; + + p = [[[TDPlistParser alloc] init] autorelease]; + + s = @"{" + @" 0 = 0;" + @" dictKey = {" + @" bar = foo;" + @" };" + @" 47 = 0;" + @" IntegerKey = 1;" + @" 47.7 = 0;" + @" = ;" + @" ArrayKey = (" + @" \"one one\"," + @" two," + @" three" + @" );" + @" \"Null Key\" = ;" + @" emptyDictKey = {" + @" };" + @" StringKey = String;" + @" \"1.0\" = 1;" + @" YESKey = 1;" + @" \"NO Key\" = 0;" + @"}"; + + p.tokenizer.string = s; + a = [TDTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + + id attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSColor whiteColor], NSForegroundColorAttributeName, + [NSFont fontWithName:@"Monaco" size:12.], NSFontAttributeName, + nil]; + id dict = [res pop]; + + p.tokenizer.string = [[[dict description] copy] autorelease]; + a = [TDTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser bestMatchFor:a]; + dict = [res pop]; + + p.tokenizer.string = nil; // prevent retain cycle leak + s = [[[dict description] copy] autorelease]; + + self.displayString = [[[NSAttributedString alloc] initWithString:s attributes:attrs] autorelease]; +} + + +- (void)doHtmlSyntaxHighlighter { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"nyt" ofType:@"html"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + //NSString *s = @"ア"; + + TDHtmlSyntaxHighlighter *highlighter = [[TDHtmlSyntaxHighlighter alloc] initWithAttributesForDarkBackground:YES]; + NSAttributedString *o = [highlighter attributedStringForString:s]; + //NSLog(@"o: %@", [o string]); + self.displayString = o; + [highlighter release]; +} + + +- (void)doJsonParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + + TDJsonParser *p = [[[TDJsonParser alloc] init] autorelease]; +// TDFastJsonParser *p = [[[TDFastJsonParser alloc] init] autorelease]; + + id result = nil; + + @try { + result = [p parse:s]; + } @catch (NSException *e) { + NSLog(@"\n\n\nexception:\n\n %@", [e reason]); + } + NSLog(@"result %@", result); +} + + +- (void)doEBNFParser { + //NSString *s = @"foo (bar|baz)*;"; + NSString *s = @"$baz = bar; ($baz|foo)*;"; + //NSString *s = @"foo;"; + EBNFParser *p = [[[EBNFParser alloc] init] autorelease]; + + // TDAssembly *a = [p bestMatchFor:[TDTokenAssembly assemblyWithString:s]]; + // NSLog(@"a: %@", a); + // NSLog(@"a.target: %@", a.target); + + TDParser *res = [p parse:s]; + // NSLog(@"res: %@", res); + // NSLog(@"res: %@", res.string); + // NSLog(@"res.subparsers: %@", res.subparsers); + // NSLog(@"res.subparsers 0: %@", [[res.subparsers objectAtIndex:0] string]); + // NSLog(@"res.subparsers 1: %@", [[res.subparsers objectAtIndex:1] string]); + + s = @"bar foo bar foo"; + TDAssembly *a = [res completeMatchFor:[TDTokenAssembly assemblyWithString:s]]; + NSLog(@"\n\na: %@\n\n", a); +} + + +- (void)doGrammarParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path]; +// s = @"@start = openCurly closeCurly; openCurly = '{'; closeCurly = '}';"; +// s = @"@start = start*; start = 'bar';"; + + TDParserFactory *factory = [TDParserFactory factory]; + + JSONAssembler *ass = [[[JSONAssembler alloc] init] autorelease]; + TDParser *lp = [factory parserFromGrammar:s assembler:ass]; + + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path]; + +// s = @"bar bar"; + TDTokenizer *t = [TDTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + TDTokenAssembly *a = [TDTokenAssembly assemblyWithTokenizer:t]; + a.preservesWhitespaceTokens = YES; + //TDAssembly *res = + [lp completeMatchFor:a]; + + self.displayString = ass.displayString; +} + + +- (void)doProf { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json_with_discards" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + TDTokenizer *t = [TDTokenizer tokenizerWithString:s]; + TDToken *eof = [TDToken EOFToken]; + TDToken *tok = nil; + NSDate *start = [NSDate date]; + while ((tok = [t nextToken]) != eof) ; + CGFloat ms4tok = -([start timeIntervalSinceNow]); + + TDParserFactory *factory = [TDParserFactory factory]; + TDJsonParser *p = nil; + + p = [[[TDJsonParser alloc] initWithIntentToAssemble:NO] autorelease]; + + //JSONAssembler *assembler = [[[JSONAssembler alloc] init] autorelease]; + start = [NSDate date]; + TDParser *lp = [factory parserFromGrammar:s assembler:p]; + CGFloat ms4grammar = -([start timeIntervalSinceNow]); + + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path]; + + start = [NSDate date]; + TDAssembly *a = [TDTokenAssembly assemblyWithString:s]; + a = [lp completeMatchFor:a]; + CGFloat ms4json = -([start timeIntervalSinceNow]); + + p = [[TDJsonParser alloc] initWithIntentToAssemble:NO]; + start = [NSDate date]; + id res = [p parse:s]; + CGFloat ms4json2 = -([start timeIntervalSinceNow]); + [p release]; + + p = [[TDJsonParser alloc] initWithIntentToAssemble:YES]; + start = [NSDate date]; + res = [p parse:s]; + CGFloat ms4json3 = -([start timeIntervalSinceNow]); + [p release]; + + id fp = [[[TDFastJsonParser alloc] init] autorelease]; + start = [NSDate date]; + res = [fp parse:s]; + CGFloat ms4json4 = -([start timeIntervalSinceNow]); + + id attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont fontWithName:@"Monaco" size:14.], NSFontAttributeName, + [NSColor whiteColor], NSForegroundColorAttributeName, + nil]; + + s = [NSString stringWithFormat:@"tokenization: %f \n\ngrammar parse: %f sec\n\nlp json parse: %f sec\n\np json parse (not assembled): %f sec\n\np json parse (assembled): %f sec\n\nfast json parse (assembled): %f sec\n\n %f", ms4tok, ms4grammar, ms4json, ms4json2, ms4json3, ms4json4, (ms4json3/ms4json4)]; + self.displayString = [[[NSMutableAttributedString alloc] initWithString:s attributes:attrs] autorelease]; +} + + +- (void)doTokenize { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + + TDTokenizer *t = [TDTokenizer tokenizerWithString:s]; + TDToken *eof = [TDToken EOFToken]; + TDToken *tok = nil; + + NSDate *start = [NSDate date]; + while ((tok = [t nextToken]) != eof) ; + CGFloat secs = -([start timeIntervalSinceNow]); + + id attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont fontWithName:@"Monaco" size:14.], NSFontAttributeName, + [NSColor whiteColor], NSForegroundColorAttributeName, + nil]; + + s = [NSString stringWithFormat:@"tokenize: %f", secs]; + self.displayString = [[[NSMutableAttributedString alloc] initWithString:s attributes:attrs] autorelease]; +} + + +- (void)doSimpleCSS { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + TDParserFactory *factory = [TDParserFactory factory]; + + TDMiniCSSAssembler *assembler = [[[TDMiniCSSAssembler alloc] init] autorelease]; + TDParser *lp = [factory parserFromGrammar:s assembler:assembler]; + s = @"foo { color:rgb(111.0, 99.0, 255.0); }"; + TDAssembly *a = [TDTokenAssembly assemblyWithString:s]; + a = [lp completeMatchFor:a]; + +} + + +- (void)doSimpleCSS2 { + TDParserFactory *factory = [TDParserFactory factory]; + + // create CSS parser + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + NSString *grammarString = [NSString stringWithContentsOfFile:path]; + TDMiniCSSAssembler *cssAssembler = [[[TDMiniCSSAssembler alloc] init] autorelease]; + TDParser *cssParser = [factory parserFromGrammar:grammarString assembler:cssAssembler]; + + // parse CSS + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"css"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + TDAssembly *a = [TDTokenAssembly assemblyWithString:s]; + a = [cssParser bestMatchFor:a]; + + // get attributes from css + id attrs = cssAssembler.attributes; + + // create JSON Parser + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"grammar"]; + grammarString = [NSString stringWithContentsOfFile:path]; + TDGenericAssembler *genericAssembler = [[[TDGenericAssembler alloc] init] autorelease]; + + // give it the attrs from CSS + genericAssembler.attributes = attrs; + TDParser *jsonParser = [factory parserFromGrammar:grammarString assembler:genericAssembler]; + + // parse JSON + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path]; + + // take care to preseve the whitespace in the JSON + TDTokenizer *t = [TDTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + TDTokenAssembly *a1 = [TDTokenAssembly assemblyWithTokenizer:t]; + a1.preservesWhitespaceTokens = YES; + [jsonParser completeMatchFor:a1]; + + self.displayString = genericAssembler.displayString; +} + + +- (void)doJSONHighlighting { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + TDSyntaxHighlighter *shc = [[[TDSyntaxHighlighter alloc] init] autorelease]; + self.displayString = [shc highlightedStringForString:s ofGrammar:@"json"]; +} + + +- (void)doCSSHighlighting { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"example" ofType:@"css"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + TDSyntaxHighlighter *shc = [[[TDSyntaxHighlighter alloc] init] autorelease]; + self.displayString = [shc highlightedStringForString:s ofGrammar:@"css"]; +} + + +- (void)doHTMLHighlighting { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"example" ofType:@"html"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + TDSyntaxHighlighter *shc = [[[TDSyntaxHighlighter alloc] init] autorelease]; + self.displayString = [shc highlightedStringForString:s ofGrammar:@"html"]; +} + + +- (void)doMultiLineComment { + NSString *s = @"/* foo */ "; + TDTokenizer *t = [TDTokenizer tokenizerWithString:s]; + t.commentState.reportsCommentTokens = YES; + //TDToken *tok = + [t nextToken]; +} + + +- (void)doRubyHashParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"rubyhash" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path]; + TDTokenizer *t = nil; + TDParser *lp = [[TDParserFactory factory] parserFromGrammar:s assembler:nil getTokenizer:&t]; + + s = @"{\"brand\"=>{\"name\"=>\"something\"," + @"\"logo\"=>#," + @"\"summary\"=>\"wee\", \"content\"=>\"woopy doo\"}, \"commit\"=>\"Save\"," + @"\"authenticity_token\"=>\"43a94d60304a7fb13a4ff61a5960461ce714e92b\"," + @"\"action\"=>\"create\", \"controller\"=>\"admin/brands\"}"; + + t.string = s; //@"{\"foo\"=>\"bar\"}"; + t.commentState.reportsCommentTokens = YES; + + TDAssembly *a = [TDTokenAssembly assemblyWithTokenizer:t]; + TDAssembly *res = [lp bestMatchFor:a]; + NSLog(@"%@", res); +} + + + +- (void)doFactory { +// id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; +// TDParserFactory *factory = [TDParserFactory factory]; +// NSString *s = nil; +// s = @"@start = foo|baz; foo (workOnFooAssembly:) = 'bar'; baz (workOnBazAssembly:) = 'bat'"; +// factory.assemblerSettingBehavior = TDParserFactoryAssemblerSettingBehaviorOnExplicit; +// TDParser *lp = [factory parserFromGrammar:s assembler:mock]; +// +//// [[mock expect] workOnBazAssembly:OCMOCK_ANY]; +//// NSString *s = @"bar bat"; +//// a = [TDTokenAssembly assemblyWithString:s]; +//// res = [lp completeMatchFor:a]; +//// TDEqualObjects(@"[bar, bat]bar/bat^", [res description]); +//// [mock verify]; +} + + +- (void)doParenStuff { + NSString *s = @"-(ab+5)"; + TDTokenizer *t = [TDTokenizer tokenizerWithString:s]; + + TDToken *tok = [t nextToken]; + +// TDTrue(tok.isSymbol); +// TDEqualObjects(tok.stringValue, @"-"); +// TDEquals((CGFloat)0.0, tok.floatValue); + + tok = [t nextToken]; +// TDTrue(tok.isSymbol); +// TDEqualObjects(tok.stringValue, @"("); +// TDEquals((CGFloat)0.0, tok.floatValue); +} + + +- (IBAction)run:(id)sender { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + +// [self doPlistParser]; +// [self doHtmlSyntaxHighlighter]; +// [self doJsonParser]; +<<<<<<< .mine +// [self doProf]; +======= + [self doRubyHashParser]; +// [self doProf]; +>>>>>>> .r657 +// [self doTokenize]; +// [self doGrammarParser]; +// [self doSimpleCSS]; +// [self doSimpleCSS2]; +// [self doParenStuff]; + + [self doJSONHighlighting]; +// [self doCSSHighlighting]; +// [self doHTMLHighlighting]; + +// [self doMultiLineComment]; + + [self doFactory]; + + [pool drain]; +} + +@synthesize displayString; +@end diff --git a/debugapp/DebugApp-Info.plist b/debugapp/DebugApp-Info.plist new file mode 100644 index 0000000..9bfec49 --- /dev/null +++ b/debugapp/DebugApp-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + DebugAppMainMenu + NSPrincipalClass + NSApplication + + diff --git a/debugapp/DebugAppDelegate.h b/debugapp/DebugAppDelegate.h new file mode 100644 index 0000000..64494c3 --- /dev/null +++ b/debugapp/DebugAppDelegate.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface DebugAppDelegate : NSObject { + NSAttributedString *displayString; +} +- (IBAction)run:(id)sender; + +@property (retain) NSAttributedString *displayString; +@end diff --git a/debugapp/DebugAppDelegate.m b/debugapp/DebugAppDelegate.m new file mode 100644 index 0000000..aa63730 --- /dev/null +++ b/debugapp/DebugAppDelegate.m @@ -0,0 +1,516 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "DebugAppDelegate.h" +#import +#import "PKParserFactory.h" +#import "TDJsonParser.h" +#import "TDFastJsonParser.h" +#import "TDRegularParser.h" +#import "EBNFParser.h" +#import "TDPlistParser.h" +#import "TDXmlNameState.h" +#import "TDXmlToken.h" +#import "TDHtmlSyntaxHighlighter.h" +#import "JSONAssembler.h" +#import "TDMiniCSSAssembler.h" +#import "TDGenericAssembler.h" +#import "NSArray+ParseKitAdditions.h" +#import "TDSyntaxHighlighter.h" +#import "TDJavaScriptParser.h" +#import "TDNSPredicateEvaluator.h" +#import + +@protocol TDMockAssember +- (void)didMatchFoo:(PKAssembly *)a; +- (void)didMatchBaz:(PKAssembly *)a; +- (void)didMatchStart:(PKAssembly *)a; +- (void)didMatchStart:(PKAssembly *)a; +- (void)didMatch_Start:(PKAssembly *)a; +@end + +@interface PKParserFactory () +- (PKSequence *)parserFromExpression:(NSString *)s; +@property (retain) PKCollectionParser *expressionParser; +@end + +@implementation DebugAppDelegate + +- (void)dealloc { + self.displayString = nil; + [super dealloc]; +} + + +- (void)doPlistParser { + NSString *s = nil; + PKTokenAssembly *a = nil; + PKAssembly *res = nil; + TDPlistParser *p = nil; + + p = [[[TDPlistParser alloc] init] autorelease]; + + s = @"{" + @" 0 = 0;" + @" dictKey = {" + @" bar = foo;" + @" };" + @" 47 = 0;" + @" IntegerKey = 1;" + @" 47.7 = 0;" + @" = ;" + @" ArrayKey = (" + @" \"one one\"," + @" two," + @" three" + @" );" + @" \"Null Key\" = ;" + @" emptyDictKey = {" + @" };" + @" StringKey = String;" + @" \"1.0\" = 1;" + @" YESKey = 1;" + @" \"NO Key\" = 0;" + @"}"; + + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + + id attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSColor whiteColor], NSForegroundColorAttributeName, + [NSFont fontWithName:@"Monaco" size:12.], NSFontAttributeName, + nil]; + id dict = [res pop]; + + p.tokenizer.string = [[[dict description] copy] autorelease]; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser bestMatchFor:a]; + dict = [res pop]; + + p.tokenizer.string = nil; // prevent retain cycle leak + s = [[[dict description] copy] autorelease]; + + self.displayString = [[[NSAttributedString alloc] initWithString:s attributes:attrs] autorelease]; +} + + +- (void)doHtmlSyntaxHighlighter { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"nyt" ofType:@"html"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + //NSString *s = @"ア"; + + TDHtmlSyntaxHighlighter *highlighter = [[TDHtmlSyntaxHighlighter alloc] initWithAttributesForDarkBackground:YES]; + NSAttributedString *o = [highlighter attributedStringForString:s]; + //NSLog(@"o: %@", [o string]); + self.displayString = o; + [highlighter release]; +} + + +- (void)doJsonParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + TDJsonParser *p = [[[TDJsonParser alloc] init] autorelease]; +// TDFastJsonParser *p = [[[TDFastJsonParser alloc] init] autorelease]; + + id result = nil; + + @try { + result = [p parse:s]; + } @catch (NSException *e) { + NSLog(@"\n\n\nexception:\n\n %@", [e reason]); + } + NSLog(@"result %@", result); +} + + +- (void)doEBNFParser { + //NSString *s = @"foo (bar|baz)*;"; + NSString *s = @"$baz = bar; ($baz|foo)*;"; + //NSString *s = @"foo;"; + EBNFParser *p = [[[EBNFParser alloc] init] autorelease]; + + // PKAssembly *a = [p bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + // NSLog(@"a: %@", a); + // NSLog(@"a.target: %@", a.target); + + PKParser *res = [p parse:s]; + // NSLog(@"res: %@", res); + // NSLog(@"res: %@", res.string); + // NSLog(@"res.subparsers: %@", res.subparsers); + // NSLog(@"res.subparsers 0: %@", [[res.subparsers objectAtIndex:0] string]); + // NSLog(@"res.subparsers 1: %@", [[res.subparsers objectAtIndex:1] string]); + + s = @"bar foo bar foo"; + PKAssembly *a = [res completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + NSLog(@"\n\na: %@\n\n", a); +} + + +- (void)doGrammarParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; +// s = @"@start = openCurly closeCurly; openCurly = '{'; closeCurly = '}';"; +// s = @"@start = start*; start = 'bar';"; + + PKParserFactory *factory = [PKParserFactory factory]; + + JSONAssembler *ass = [[[JSONAssembler alloc] init] autorelease]; + PKParser *lp = [factory parserFromGrammar:s assembler:ass]; + + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + +// s = @"bar bar"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; + a.preservesWhitespaceTokens = YES; + //PKAssembly *res = + [lp completeMatchFor:a]; + + self.displayString = ass.displayString; +} + + +- (void)doJavaScriptGrammarParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"javascript" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKParser *p = [[PKParserFactory factory] parserFromGrammar:s assembler:nil]; + //PKParser *plus = [p parserNamed:@"plus"]; + + s = @";"; + p.tokenizer.string = s; + //PKAssembly *a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + //PKAssembly *res = [p bestMatchFor:a]; + // TDEqualObjects(@"[var, foo, =, 'bar', ;]var/foo/=/bar/;^", [res description]); +} + + +- (void)doProf { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json_with_discards" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + NSDate *start = [NSDate date]; + while ((tok = [t nextToken]) != eof) ; + CGFloat ms4tok = -([start timeIntervalSinceNow]); + + PKParserFactory *factory = [PKParserFactory factory]; + TDJsonParser *p = nil; + + p = [[[TDJsonParser alloc] initWithIntentToAssemble:NO] autorelease]; + + //JSONAssembler *assembler = [[[JSONAssembler alloc] init] autorelease]; + start = [NSDate date]; + PKParser *lp = [factory parserFromGrammar:s assembler:p]; + CGFloat ms4grammar = -([start timeIntervalSinceNow]); + + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + start = [NSDate date]; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + a = [lp completeMatchFor:a]; + CGFloat ms4json = -([start timeIntervalSinceNow]); + + PKReleaseSubparserTree(lp); + + p = [[TDJsonParser alloc] initWithIntentToAssemble:NO]; + start = [NSDate date]; + id res = [p parse:s]; + CGFloat ms4json2 = -([start timeIntervalSinceNow]); + [p release]; + + p = [[TDJsonParser alloc] initWithIntentToAssemble:YES]; + start = [NSDate date]; + res = [p parse:s]; + CGFloat ms4json3 = -([start timeIntervalSinceNow]); + [p release]; + + id fp = [[[TDFastJsonParser alloc] init] autorelease]; + start = [NSDate date]; + res = [fp parse:s]; + CGFloat ms4json4 = -([start timeIntervalSinceNow]); + + id attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont fontWithName:@"Monaco" size:14.], NSFontAttributeName, + [NSColor whiteColor], NSForegroundColorAttributeName, + nil]; + + s = [NSString stringWithFormat:@"tokenization: %f \n\ngrammar parse: %f sec\n\nlp json parse: %f sec\n\np json parse (not assembled): %f sec\n\np json parse (assembled): %f sec\n\nfast json parse (assembled): %f sec\n\n %f", ms4tok, ms4grammar, ms4json, ms4json2, ms4json3, ms4json4, (ms4json3/ms4json4)]; + self.displayString = [[[NSMutableAttributedString alloc] initWithString:s attributes:attrs] autorelease]; +} + + +- (void)doTokenize { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + NSDate *start = [NSDate date]; + while ((tok = [t nextToken]) != eof) ; + CGFloat secs = -([start timeIntervalSinceNow]); + + id attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont fontWithName:@"Monaco" size:14.], NSFontAttributeName, + [NSColor whiteColor], NSForegroundColorAttributeName, + nil]; + + s = [NSString stringWithFormat:@"tokenize: %f", secs]; + self.displayString = [[[NSMutableAttributedString alloc] initWithString:s attributes:attrs] autorelease]; +} + + +- (void)doSimpleCSS { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKParserFactory *factory = [PKParserFactory factory]; + + TDMiniCSSAssembler *assembler = [[[TDMiniCSSAssembler alloc] init] autorelease]; + PKParser *lp = [factory parserFromGrammar:s assembler:assembler]; + s = @"foo { color:rgb(111.0, 99.0, 255.0); }"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + a = [lp completeMatchFor:a]; + +} + + +- (void)doSimpleCSS2 { + PKParserFactory *factory = [PKParserFactory factory]; + + // create CSS parser + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + NSString *grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDMiniCSSAssembler *cssAssembler = [[[TDMiniCSSAssembler alloc] init] autorelease]; + PKParser *cssParser = [factory parserFromGrammar:grammarString assembler:cssAssembler]; + + // parse CSS + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"css"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + a = [cssParser bestMatchFor:a]; + + // get attributes from css + id attrs = cssAssembler.attributes; + + // create JSON Parser + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"grammar"]; + grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDGenericAssembler *genericAssembler = [[[TDGenericAssembler alloc] init] autorelease]; + + // give it the attrs from CSS + genericAssembler.attributes = attrs; + PKParser *jsonParser = [factory parserFromGrammar:grammarString assembler:genericAssembler]; + + // parse JSON + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + // take care to preseve the whitespace in the JSON + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + PKTokenAssembly *a1 = [PKTokenAssembly assemblyWithTokenizer:t]; + a1.preservesWhitespaceTokens = YES; +// [jsonParser completeMatchFor:a1]; +// self.displayString = genericAssembler.displayString; + self.displayString = [[jsonParser completeMatchFor:a1] target]; +} + + +- (void)doJSONHighlighting { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDSyntaxHighlighter *shc = [[[TDSyntaxHighlighter alloc] init] autorelease]; + self.displayString = [shc highlightedStringForString:s ofGrammar:@"json"]; +} + + +- (void)doCSSHighlighting { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"example" ofType:@"css"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDSyntaxHighlighter *shc = [[[TDSyntaxHighlighter alloc] init] autorelease]; + self.displayString = [shc highlightedStringForString:s ofGrammar:@"css"]; +} + + +- (void)doHTMLHighlighting { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"example" ofType:@"html"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDSyntaxHighlighter *shc = [[[TDSyntaxHighlighter alloc] init] autorelease]; + self.displayString = [shc highlightedStringForString:s ofGrammar:@"html"]; +} + + +- (void)doMultiLineComment { + NSString *s = @"/* foo */ "; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + t.commentState.reportsCommentTokens = YES; + //PKToken *tok = + [t nextToken]; +} + + +- (void)doRubyHashParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"rubyhash" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKParser *lp = [[PKParserFactory factory] parserFromGrammar:s assembler:nil]; + + s = @"{\"brand\"=>{\"name\"=>\"something\"," + @"\"logo\"=>#," + @"\"summary\"=>\"wee\", \"content\"=>\"woopy doo\"}, \"commit\"=>\"Save\"," + @"\"authenticity_token\"=>\"43a94d60304a7fb13a4ff61a5960461ce714e92b\"," + @"\"action\"=>\"create\", \"controller\"=>\"admin/brands\"}"; + + NSLog(@"%@", [lp parse:s]); +} + + + +- (void)doFactory { +// id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; +// PKParserFactory *factory = [PKParserFactory factory]; +// NSString *s = nil; +// s = @"@start = foo|baz; foo (didMatchFooAssembly:) = 'bar'; baz (didMatchBazAssembly:) = 'bat'"; +// factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnExplicit; +// PKParser *lp = [factory parserFromGrammar:s assembler:mock]; +// +//// [[mock expect] didMatchBazAssembly:OCMOCK_ANY]; +//// NSString *s = @"bar bat"; +//// a = [PKTokenAssembly assemblyWithString:s]; +//// res = [lp completeMatchFor:a]; +//// TDEqualObjects(@"[bar, bat]bar/bat^", [res description]); +//// [mock verify]; + +// NSString *g = @"@delimitState = '$'; @delimitedString = '$' '%' nil; @start = DelimitedString('$', '%');"; +// PKParser *lp = [[PKParserFactory factory] parserFromGrammar:g assembler:nil]; +// +// NSString *s = @"$foo%"; +// PKTokenizer *t = lp.tokenizer; +// t.string = s; +// PKAssembly *res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xpath1_0" ofType:@"grammar"]; + NSString *g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:nil]; + PKTokenizer *t = p.tokenizer; + t.string = @"foo"; + //PKAssembly *res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + +} + + +- (void)doParenStuff { + NSString *s = @"-(ab+5)"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + +// TDTrue(tok.isSymbol); +// TDEqualObjects(tok.stringValue, @"-"); +// TDEquals((CGFloat)0.0, tok.floatValue); + + tok = [t nextToken]; +// TDTrue(tok.isSymbol); +// TDEqualObjects(tok.stringValue, @"("); +// TDEquals((CGFloat)0.0, tok.floatValue); +} + + +- (void)doDelimitedString { + NSString *s = @""; + + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + NSCharacterSet *cs = nil; + + [t setTokenizerState:t.delimitState from:'<' to:'<']; + [t.delimitState addStartMarker:@"" allowedCharacterSet:cs]; + +// PKToken *tok = [t nextToken]; + + //TDTrue(tok.isDelimitedString); + +} + + +- (void)doJSParser { + TDJavaScriptParser *jsp = [TDJavaScriptParser parser]; + NSString *s = @"for( ; true; true) {}"; + jsp.tokenizer.string = s; +// PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; +// id res = [jsp bestMatchFor:a]; + //TDEqualObjects([res description], @"['foo']'foo'^"); + + //TDEqualObjects([res description], @"[for, (, ;, true, ;, true, ), {, }]for/(/;/true/;/true/)/{/}^"); +} + + +- (void)doNSPredicateEvaluator { + //TDNSPredicateEvaluator *eval = [[[TDNSPredicateEvaluator alloc] initWithKeyPathResolver:nil] autorelease]; +} + + +- (void)doXMLParser { +// NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xml" ofType:@"grammar"]; +// NSString *g = [NSString stringWithContentsOfFile:path]; +// PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self]; +// PKTokenizer *t = p.tokenizer; +} + + + + +- (IBAction)run:(id)sender { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + +// [self doPlistParser]; +// [self doHtmlSyntaxHighlighter]; +// [self doJsonParser]; +// [self doRubyHashParser]; + +// [self doJSParser]; + + [self doProf]; + + //[self doJavaScriptGrammarParser]; + + // [self doTokenize]; +// [self doGrammarParser]; +// [self doSimpleCSS]; +// [self doSimpleCSS2]; +// [self doParenStuff]; + +// [self doJSONHighlighting]; +// [self doCSSHighlighting]; +// [self doHTMLHighlighting]; + +// [self doMultiLineComment]; +// [self doDelimitedString]; + +// [self doFactory]; + +// [self doXMLParser]; +// [self doNSPredicateEvaluator]; + + [pool drain]; +} + +@synthesize displayString; +@end diff --git a/debugapp/DebugAppMainMenu.xib b/debugapp/DebugAppMainMenu.xib new file mode 100644 index 0000000..b739318 --- /dev/null +++ b/debugapp/DebugAppMainMenu.xib @@ -0,0 +1,3529 @@ + + + + 1050 + 9G55 + 677 + 949.43 + 353.00 + + YES + + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + NSFontManager + + + AMainMenu + + YES + + + DebugApp + + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + DebugApp + + YES + + + About DebugApp + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Services + + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 2147483647 + + + + + + Hide DebugApp + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Quit DebugApp + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + T3BlbuKApg + o + 1048576 + 2147483647 + + + + + + Open Recent + + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + U2F2ZSBBc+KApg + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + UHJpbnTigKY + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Find + + 2147483647 + + + submenuAction: + + Find + + YES + + + RmluZOKApg + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + U2hvdyBTcGVsbGluZ+KApg + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 2147483647 + + + + + + Check Grammar With Spelling + + 2147483647 + + + + + + + + + Substitutions + + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 2147483647 + + + + + + Stop Speaking + + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Q3VzdG9taXplIFRvb2xiYXLigKY + + 2147483647 + + + + + + + + + Window + + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bring All to Front + + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + NewApplication Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + 15 + 2 + {{479, 251}, {504, 447}} + 611844096 + Window + NSWindow + + {3.40282e+38, 3.40282e+38} + {484, 310} + + + 256 + + YES + + + 266 + {{14, 293}, {476, 32}} + + YES + + 67239424 + 134217728 + Run + + LucidaGrande + 1.300000e+01 + 1044 + + + -2038284033 + 129 + + DQ + 200 + 25 + + + + + 266 + {{17, 342}, {470, 85}} + + YES + + 67239424 + 272629760 + VGhlIHB1cnBvc2Ugb2YgdGhpcyBhcHBsaWNhdGlvbiBpcyBvbmx5IHRvIHJ1biBhcmJ0cmFyeSB0ZXN0 +IGNvZGUgaW4gIkRlYnVnIiBtb2RlIHVzaW5nIEdEQiBhbmQgYnJlYWtwb2ludHMgKHdoaWNoIGRvZXMg +bm90IHNlZW0gdG8gYmUgcG9zc2libGUgZm9tIHRoZSBVbml0VGVzdCBCdW5kbGUpLiBUbyB1c2UsIGNv +cHkgc29tZSB1bml0IHRlc3QgY29kZSBvdmVyIHRvIHRoZSAtW0RlYnVnQXBwRGVsZWdhdGUgcnVuOl0g +YWN0aW9uIG1ldGhvZCB3aGljaCBpcyBleGVjdXRlZCB3aGVuIHRoZSAiUnVuIiBidXR0b24gYmVsb3cg +aXMgY2xpY2tlZC4 + + LucidaGrande + 1.300000e+01 + 16 + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 274 + + YES + + + 2304 + + YES + + + 2322 + {447, 96} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + YES + + YES + + YES + NSFont + NSParagraphStyle + + + YES + + LucidaGrande + 1.000000e+01 + 2843 + + + 3 + + YES + + 0.000000e+00 + + + 5.600000e+01 + + + 1.120000e+02 + + + 1.680000e+02 + + + 2.240000e+02 + + + 2.800000e+02 + + + 3.360000e+02 + + + 3.920000e+02 + + + 4.480000e+02 + + + 5.040000e+02 + + + 5.600000e+02 + + + 6.160000e+02 + + + 6.720000e+02 + + + 7.280000e+02 + + + 7.840000e+02 + + + 8.400000e+02 + + + 8.960000e+02 + + + 9.520000e+02 + + + 1.008000e+03 + + + 1.064000e+03 + + + 1.120000e+03 + + + 1.176000e+03 + + + 1.232000e+03 + + + 1.288000e+03 + + + 1.344000e+03 + + + 1.400000e+03 + + + 1.456000e+03 + + + 1.512000e+03 + + + 1.568000e+03 + + + 1.624000e+03 + + + 1.680000e+03 + + + 1.736000e+03 + + + + + + + YES + + YES + NSFont + NSParagraphStyle + + + YES + + LucidaGrande-Bold + 1.000000e+01 + 16 + + + 3 + + YES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GQAEAQgADAEiAAcBhAQAA + + + + + YES + + + 6 + + + + 4.470000e+02 + 1 + + + 11621 + + 1 + MC4xMTc2NDcwNiAwLjExNzY0NzA2IDAuMTQxMTc2NDgAA + + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + 6 + System + selectedTextBackgroundColor + + + + 6 + System + selectedTextColor + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + 1 + MCAwIDEAA + + + + + + + 6 + {3081, 1e+07} + {223, 0} + + + + {{1, 1}, {447, 259}} + + + + + 3 + MQA + + + {4, -5} + 1 + + 4 + + + + 256 + {{448, 1}, {15, 259}} + + + _doScroller: + 9.843750e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{20, 20}, {464, 261}} + + + 18 + + + + + + {504, 447} + + + {{0, 0}, {1440, 878}} + {484, 332} + {3.40282e+38, 3.40282e+38} + + + DebugAppDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + terminate: + + + + 369 + + + + unhideAllApplications: + + + + 370 + + + + addFontTrait: + + + + 418 + + + + addFontTrait: + + + + 419 + + + + modifyFont: + + + + 420 + + + + orderFrontFontPanel: + + + + 421 + + + + modifyFont: + + + + 422 + + + + raiseBaseline: + + + + 423 + + + + lowerBaseline: + + + + 424 + + + + copyFont: + + + + 425 + + + + subscript: + + + + 426 + + + + superscript: + + + + 427 + + + + tightenKerning: + + + + 428 + + + + underline: + + + + 429 + + + + orderFrontColorPanel: + + + + 430 + + + + useAllLigatures: + + + + 431 + + + + loosenKerning: + + + + 432 + + + + pasteFont: + + + + 433 + + + + unscript: + + + + 434 + + + + useStandardKerning: + + + + 435 + + + + useStandardLigatures: + + + + 436 + + + + turnOffLigatures: + + + + 437 + + + + turnOffKerning: + + + + 438 + + + + alignLeft: + + + + 439 + + + + alignJustified: + + + + 440 + + + + copyRuler: + + + + 441 + + + + alignCenter: + + + + 442 + + + + toggleRuler: + + + + 443 + + + + alignRight: + + + + 444 + + + + pasteRuler: + + + + 445 + + + + run: + + + + 454 + + + + attributedString: displayString + + + + + + attributedString: displayString + attributedString + displayString + + NSContinuouslyUpdatesValue + + + 2 + + + 462 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + 3 + + + 80 + + + 8 + + + 78 + + + 6 + + + 72 + + + + + 82 + + + 9 + + + 124 + + + YES + + + + + + 77 + + + 5 + + + 73 + + + 1 + + + 79 + + + 7 + + + 112 + + + 10 + + + 74 + + + 2 + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + + + 373 + + + YES + + + + + + 374 + + + YES + + + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + 377 + + + YES + + + + + + + + + + + + + 378 + + + + + 379 + + + + + 380 + + + + + 381 + + + + + 382 + + + + + 383 + + + + + 384 + + + + + 385 + + + + + 386 + + + YES + + + + + + + + + + + + + + + + + + + + + 387 + + + + + 388 + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + YES + + + + + + 396 + + + YES + + + + + + 397 + + + YES + + + + + + 398 + + + + + 399 + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + YES + + + + + + + + + + 404 + + + + + 405 + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + YES + + + + + + + + 410 + + + + + 411 + + + + + 412 + + + + + 413 + + + YES + + + + + + + + + 414 + + + + + 415 + + + + + 416 + + + + + 417 + + + + + 446 + + + YES + + + + + + 447 + + + YES + + + + + + + + 448 + + + + + 449 + + + YES + + + + + + 450 + + + + + 452 + + + YES + + + + + + 453 + + + + + 455 + + + YES + + + + + + + + 456 + + + + + 457 + + + + + 458 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBEditorWindowLastContentRect + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBEditorWindowLastContentRect + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 371.IBPluginDependency + 373.IBPluginDependency + 374.IBPluginDependency + 375.IBPluginDependency + 376.IBPluginDependency + 377.IBPluginDependency + 378.IBPluginDependency + 379.IBPluginDependency + 380.IBPluginDependency + 381.IBPluginDependency + 382.IBPluginDependency + 383.IBPluginDependency + 384.IBPluginDependency + 385.IBPluginDependency + 386.IBPluginDependency + 387.IBPluginDependency + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 446.IBEditorWindowLastContentRect + 446.IBWindowTemplateEditedContentRect + 446.NSWindowTemplate.visibleAtLaunch + 446.windowTemplate.hasMinSize + 446.windowTemplate.minSize + 447.IBPluginDependency + 448.IBPluginDependency + 449.IBPluginDependency + 450.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 455.IBPluginDependency + 456.IBPluginDependency + 457.IBPluginDependency + 458.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + {{553, 524}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{596, 852}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{479, 484}, {132, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{565, 284}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{322, 304}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{365, 632}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{565, 284}, {153, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{565, 284}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{798, 236}, {197, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{490, 309}, {440, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 977}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{432, 504}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{565, 284}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{511, 212}, {504, 447}} + {{511, 212}, {504, 447}} + + + {484, 310} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{556, 261}, {211, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{280, 344}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{323, 672}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 462 + + + + YES + + DebugAppDelegate + NSObject + + run: + id + + + IBProjectSource + debugapp/DebugAppDelegate.h + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + + 0 + ../TDParseKit.xcodeproj + 3 + + diff --git a/debugapp/JSONAssembler.h b/debugapp/JSONAssembler.h new file mode 100644 index 0000000..c8bbb7d --- /dev/null +++ b/debugapp/JSONAssembler.h @@ -0,0 +1,42 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKToken; + +@interface JSONAssembler : NSObject { + NSMutableAttributedString *displayString; + id defaultAttrs; + id objectAttrs; + id arrayAttrs; + id propertyNameAttrs; + id valueAttrs; + id constantAttrs; + + PKToken *comma; + PKToken *curly; + PKToken *bracket; +} +@property (retain) NSMutableAttributedString *displayString; +@property (retain) id defaultAttrs; +@property (retain) id objectAttrs; +@property (retain) id arrayAttrs; +@property (retain) id propertyNameAttrs; +@property (retain) id valueAttrs; +@property (retain) id constantAttrs; +@property (retain) PKToken *comma; +@property (retain) PKToken *curly; +@property (retain) PKToken *bracket; +@end diff --git a/debugapp/JSONAssembler.m b/debugapp/JSONAssembler.m new file mode 100644 index 0000000..4064a16 --- /dev/null +++ b/debugapp/JSONAssembler.m @@ -0,0 +1,169 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "JSONAssembler.h" +#import "NSArray+ParseKitAdditions.h" +#import + +@implementation JSONAssembler + +- (id)init { + self = [super init]; + if (self != nil) { + NSColor *textColor = [NSColor whiteColor]; + NSColor *tagColor = [NSColor colorWithDeviceRed:.70 green:.14 blue:.53 alpha:1.]; + NSColor *attrNameColor = [NSColor colorWithDeviceRed:.33 green:.45 blue:.48 alpha:1.]; + NSColor *attrValueColor = [NSColor colorWithDeviceRed:.77 green:.18 blue:.20 alpha:1.]; + NSColor *commentColor = [NSColor colorWithDeviceRed:.24 green:.70 blue:.27 alpha:1.]; + NSColor *piColor = [NSColor colorWithDeviceRed:.09 green:.62 blue:.74 alpha:1.]; + + NSFont *monacoFont = [NSFont fontWithName:@"Monaco" size:11.]; + + self.defaultAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + textColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.objectAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + tagColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.propertyNameAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + attrNameColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.valueAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + attrValueColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.constantAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + piColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.arrayAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + commentColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + + self.displayString = [[[NSMutableAttributedString alloc] initWithString:@"" attributes:defaultAttrs] autorelease]; + + self.comma = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"," floatValue:0]; + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0]; + self.bracket = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"[" floatValue:0]; + } + return self; +} + + +- (void)dealloc { + self.displayString = nil; + self.defaultAttrs = nil; + self.objectAttrs = nil; + self.arrayAttrs = nil; + self.propertyNameAttrs = nil; + self.valueAttrs = nil; + self.constantAttrs = nil; + self.comma = nil; + self.curly = nil; + self.bracket = nil; + [super dealloc]; +} + + +- (void)appendAttributedStringForObjects:(NSArray *)objs withAttrs:(id)attrs { + for (id obj in objs) { + NSAttributedString *as = [[NSAttributedString alloc] initWithString:[obj stringValue] attributes:attrs]; + [displayString appendAttributedString:as]; + [as release]; + } +} + + +- (void)consumeWhitespaceFrom:(PKAssembly *)a { + NSMutableArray *whitespaceToks = [NSMutableArray array]; + PKToken *tok = nil; + while (1) { + tok = [a pop]; + if (PKTokenTypeWhitespace == tok.tokenType) { + [whitespaceToks addObject:tok]; + } else { + [a push:tok]; + break; + } + } + + if ([whitespaceToks count]) { + whitespaceToks = [whitespaceToks reversedMutableArray]; + [self appendAttributedStringForObjects:whitespaceToks withAttrs:defaultAttrs]; + } +} + + +- (void)didMatchSymbolChar:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:objectAttrs]; +} + + +- (void)didMatchPropertyName:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:propertyNameAttrs]; +} + + +- (void)didMatchString:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:arrayAttrs]; +} + + +- (void)didMatchNumber:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:valueAttrs]; +} + + +- (void)didMatchConstant:(PKAssembly *)a { + NSArray *objs = [NSArray arrayWithObject:[a pop]]; + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:objs withAttrs:constantAttrs]; +} + + +- (void)didMatchNull:(PKAssembly *)a { [self didMatchConstant:a]; } +- (void)didMatchTrue:(PKAssembly *)a { [self didMatchConstant:a]; } +- (void)didMatchFalse:(PKAssembly *)a { [self didMatchConstant:a]; } + +- (void)didMatchColon:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchComma:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchOpenCurly:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchCloseCurly:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchOpenBracket:(PKAssembly *)a { [self didMatchSymbolChar:a]; } +- (void)didMatchCloseBracket:(PKAssembly *)a { [self didMatchSymbolChar:a]; } + +@synthesize displayString; +@synthesize defaultAttrs; +@synthesize objectAttrs; +@synthesize arrayAttrs; +@synthesize propertyNameAttrs; +@synthesize valueAttrs; +@synthesize constantAttrs; +@synthesize comma; +@synthesize curly; +@synthesize bracket; +@end + diff --git a/debugapp/main.m b/debugapp/main.m new file mode 100644 index 0000000..ec133b9 --- /dev/null +++ b/debugapp/main.m @@ -0,0 +1,13 @@ +// +// main.m +// TestApp +// +// Created by Todd Ditchendorf on 7/12/08. +// Copyright Todd Ditchendorf 2008. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) { + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/demoapp/.svn/all-wcprops b/demoapp/.svn/all-wcprops new file mode 100644 index 0000000..7974b9e --- /dev/null +++ b/demoapp/.svn/all-wcprops @@ -0,0 +1,107 @@ +K 25 +svn:wc:ra_dav:version-url +V 32 +/svn/!svn/ver/1405/trunk/demoapp +END +TokensView.xib +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1282/trunk/demoapp/TokensView.xib +END +main.m +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/583/trunk/demoapp/main.m +END +DemoTreesViewController.m +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1348/trunk/demoapp/DemoTreesViewController.m +END +TDGutterView.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1322/trunk/demoapp/TDGutterView.h +END +TDGutterView.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1405/trunk/demoapp/TDGutterView.m +END +DemoTokensViewController.h +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1282/trunk/demoapp/DemoTokensViewController.h +END +TreesView.xib +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1330/trunk/demoapp/TreesView.xib +END +DemoAppMainMenu.xib +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1323/trunk/demoapp/DemoAppMainMenu.xib +END +DemoTokensViewController.m +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1284/trunk/demoapp/DemoTokensViewController.m +END +PKParseTreeView.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1295/trunk/demoapp/PKParseTreeView.h +END +DemoAppDelegate.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1282/trunk/demoapp/DemoAppDelegate.h +END +DemoApp-Info.plist +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1173/trunk/demoapp/DemoApp-Info.plist +END +TDSourceCodeTextView.h +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1322/trunk/demoapp/TDSourceCodeTextView.h +END +PKParseTreeView.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1331/trunk/demoapp/PKParseTreeView.m +END +DemoAppDelegate.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1282/trunk/demoapp/DemoAppDelegate.m +END +DemoTreesViewController.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1322/trunk/demoapp/DemoTreesViewController.h +END +TDSourceCodeTextView.m +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1404/trunk/demoapp/TDSourceCodeTextView.m +END diff --git a/demoapp/.svn/entries b/demoapp/.svn/entries new file mode 100644 index 0000000..9b17a06 --- /dev/null +++ b/demoapp/.svn/entries @@ -0,0 +1,613 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/demoapp +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + + + + + + +0 + +TokensView.xib +file + + + + +2009-08-06T04:02:08.000000Z +2cd84f05eb50a266397423d58b777d5e +2009-08-03T01:24:15.042876Z +1282 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +43215 + +main.m +file + + + + +2009-06-16T06:56:28.000000Z +2b8110385b5152f3f87b6005c85a7250 +2009-01-11T01:15:32.782160Z +583 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +256 + +DemoTreesViewController.m +file + + + + +2009-08-23T05:07:14.000000Z +1db3e886ddce5529247489763790cf82 +2009-08-23T05:09:23.531641Z +1348 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +4623 + +TDGutterView.h +file + + + + +2009-08-06T04:02:08.000000Z +4d6ed8fafd8fac0db3399d7691d5304d +2009-08-09T20:08:21.181896Z +1322 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +572 + +TDGutterView.m +file + + + + +2009-11-13T07:14:30.000000Z +3b359cc9f431676758fe8d92590da62e +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2286 + +DemoTokensViewController.h +file + + + + +2009-08-06T04:02:08.000000Z +7aeebbdce1cd91ef2063b91673a8b776 +2009-08-03T01:24:15.042876Z +1282 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +704 + +TreesView.xib +file + + + + +2009-08-10T01:51:17.000000Z +12220e3ebdff009bb5f9bba2ea24c314 +2009-08-10T01:13:31.456566Z +1330 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +67091 + +DemoAppMainMenu.xib +file + + + + +2009-08-06T04:02:08.000000Z +017f7373162ae6b35ec9a85511382012 +2009-08-09T20:12:12.609875Z +1323 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +96408 + +DemoTokensViewController.m +file + + + + +2009-08-06T04:02:08.000000Z +6aa91ee77bf652e9884a4ada976df314 +2009-08-03T01:31:36.760537Z +1284 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2940 + +PKParseTreeView.h +file + + + + +2009-08-06T04:02:08.000000Z +75261580c22338ad475b87e8fa6b3026 +2009-08-08T22:00:40.590419Z +1295 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +446 + +DemoAppDelegate.h +file + + + + +2009-08-06T04:02:08.000000Z +0add112585e0b075f45776740af22712 +2009-08-03T01:24:15.042876Z +1282 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +580 + +DemoApp-Info.plist +file + + + + +2009-07-03T20:33:25.000000Z +bfd7805f8187cf108065bf963dfb9700 +2009-07-03T20:39:51.719779Z +1173 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +736 + +TDSourceCodeTextView.h +file + + + + +2009-08-06T04:02:08.000000Z +e8ad1f0e193a303514c5416b9197ee01 +2009-08-09T20:08:21.181896Z +1322 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +433 + +PKParseTreeView.m +file + + + + +2009-08-17T00:57:16.000000Z +483166fc9aea1e83c8c7e196f1bc9b62 +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +5004 + +DemoAppDelegate.m +file + + + + +2009-08-06T04:02:08.000000Z +9c456063e3452d6b3477d4ebab3cc9f8 +2009-08-03T01:24:15.042876Z +1282 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +870 + +DemoTreesViewController.h +file + + + + +2009-08-06T04:02:08.000000Z +2ae1c78bddbb8adc8f94a90b51eabdb8 +2009-08-09T20:08:21.181896Z +1322 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +652 + +TDSourceCodeTextView.m +file + + + + +2009-11-13T07:14:30.000000Z +4fe67eb74ee9196427a59cccfdff6fd4 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3732 + diff --git a/demoapp/.svn/text-base/DemoApp-Info.plist.svn-base b/demoapp/.svn/text-base/DemoApp-Info.plist.svn-base new file mode 100644 index 0000000..0e08ed6 --- /dev/null +++ b/demoapp/.svn/text-base/DemoApp-Info.plist.svn-base @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.DemoApp + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + DemoAppMainMenu + NSPrincipalClass + NSApplication + + diff --git a/demoapp/.svn/text-base/DemoAppDelegate.h.svn-base b/demoapp/.svn/text-base/DemoAppDelegate.h.svn-base new file mode 100644 index 0000000..1abed1a --- /dev/null +++ b/demoapp/.svn/text-base/DemoAppDelegate.h.svn-base @@ -0,0 +1,23 @@ +// +// DemoAppDelegate.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/12/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class DemoTokensViewController; +@class DemoTreesViewController; + +@interface DemoAppDelegate : NSObject { + IBOutlet NSTabView *tabView; + + DemoTokensViewController *tokensViewController; + DemoTreesViewController *treesViewController; +} + +@property (nonatomic, retain) DemoTokensViewController *tokensViewController; +@property (nonatomic, retain) DemoTreesViewController *treesViewController; +@end diff --git a/demoapp/.svn/text-base/DemoAppDelegate.m.svn-base b/demoapp/.svn/text-base/DemoAppDelegate.m.svn-base new file mode 100644 index 0000000..6de9f3f --- /dev/null +++ b/demoapp/.svn/text-base/DemoAppDelegate.m.svn-base @@ -0,0 +1,35 @@ +// +// DemoAppDelegate.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/12/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "DemoAppDelegate.h" +#import "DemoTokensViewController.h" +#import "DemoTreesViewController.h" + +@implementation DemoAppDelegate + +- (void)dealloc { + self.tokensViewController = nil; + self.treesViewController = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { + self.tokensViewController = [[[DemoTokensViewController alloc] init] autorelease]; + self.treesViewController = [[[DemoTreesViewController alloc] init] autorelease]; + + NSTabViewItem *item = [tabView tabViewItemAtIndex:0]; + [item setView:[tokensViewController view]]; + + item = [tabView tabViewItemAtIndex:1]; + [item setView:[treesViewController view]]; +} + +@synthesize tokensViewController; +@synthesize treesViewController; +@end diff --git a/demoapp/.svn/text-base/DemoAppMainMenu.xib.svn-base b/demoapp/.svn/text-base/DemoAppMainMenu.xib.svn-base new file mode 100644 index 0000000..fc37aa6 --- /dev/null +++ b/demoapp/.svn/text-base/DemoAppMainMenu.xib.svn-base @@ -0,0 +1,2268 @@ + + + + 1050 + 9J61 + 677 + 949.46 + 353.00 + + YES + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + DemoApp + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + DemoApp + + YES + + + About DemoApp + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide DemoApp + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit DemoApp + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + T3BlbuKApg + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + U2F2ZSBBc+KApg + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + UHJpbnTigKY + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + RmluZOKApg + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + U2hvdyBTcGVsbGluZ+KApg + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 1048576 + 2147483647 + + + submenuAction: + + Format + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Show Colors + C + 1179648 + 2147483647 + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Q3VzdG9taXplIFRvb2xiYXLigKY + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + Help + + YES + + + NewApplication Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + 15 + 2 + {{43, 10}, {1146, 856}} + 611844096 + ParseKit Demo + NSWindow + + {3.40282e+38, 3.40282e+38} + {514, 622} + + + 256 + + YES + + + 18 + {{-12, -13}, {1170, 863}} + + + YES + + 1 + + + 256 + {{10, 33}, {508, 580}} + + Tokens + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + + + 2 + + + 256 + {{10, 33}, {1150, 817}} + + + Trees + + + + + + + LucidaGrande + 1.300000e+01 + 1044 + + 0 + YES + YES + + YES + + + + + {1146, 856} + + + {{0, 0}, {1440, 878}} + {514, 644} + {3.40282e+38, 3.40282e+38} + + + DemoAppDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + orderFrontColorPanel: + + + + 361 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 369 + + + + hideOtherApplications: + + + + 370 + + + + terminate: + + + + 371 + + + + unhideAllApplications: + + + + 372 + + + + delegate + + + + 374 + + + + tabView + + + + 438 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + 3 + + + 80 + + + 8 + + + 78 + + + 6 + + + 72 + + + + + 82 + + + 9 + + + 124 + + + YES + + + + + + 77 + + + 5 + + + 73 + + + 1 + + + 79 + + + 7 + + + 112 + + + 10 + + + 74 + + + 2 + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 299 + + + YES + + + + + + 300 + + + YES + + + + + + + 344 + + + + + 345 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 367 + + + YES + + + + + + 368 + + + YES + + + + + + 373 + + + + + 413 + + + YES + + + + + + + 414 + + + YES + + + + + + 415 + + + YES + + + + + 416 + + + YES + + + + + + 417 + + + YES + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 299.IBPluginDependency + 300.IBPluginDependency + 300.editorWindowContentRectSynchronizationRect + 344.IBPluginDependency + 345.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 367.IBEditorWindowLastContentRect + 367.IBWindowTemplateEditedContentRect + 367.NSWindowTemplate.visibleAtLaunch + 367.editorWindowContentRectSynchronizationRect + 367.windowTemplate.hasMinSize + 367.windowTemplate.minSize + 368.IBPluginDependency + 373.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{596, 852}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{365, 632}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{0, 776}, {435, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 727}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{409, 832}, {176, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{8, 0}, {1146, 856}} + {{8, 0}, {1146, 856}} + + {{11, 316}, {480, 370}} + + {514, 622} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{12, 593}, {206, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{101, 533}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{323, 672}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 438 + + + + YES + + DemoAppDelegate + NSObject + + tabView + NSTabView + + + IBProjectSource + demoapp/DemoAppDelegate.h + + + + DemoAppDelegate + NSObject + + IBUserSource + + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + + 0 + ../ParseKit.xcodeproj + 3 + + diff --git a/demoapp/.svn/text-base/DemoTokensViewController.h.svn-base b/demoapp/.svn/text-base/DemoTokensViewController.h.svn-base new file mode 100644 index 0000000..f8b405b --- /dev/null +++ b/demoapp/.svn/text-base/DemoTokensViewController.h.svn-base @@ -0,0 +1,32 @@ +// +// DemoTokensViewController.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKTokenizer; + +@interface DemoTokensViewController : NSViewController { + IBOutlet NSTokenField *tokenField; + + PKTokenizer *tokenizer; + NSString *inString; + NSString *outString; + NSString *tokString; + NSMutableArray *toks; + BOOL busy; +} + +- (IBAction)parse:(id)sender; + +@property (retain) PKTokenizer *tokenizer; +@property (retain) NSString *inString; +@property (retain) NSString *outString; +@property (retain) NSString *tokString; +@property (retain) NSMutableArray *toks; +@property BOOL busy; +@end diff --git a/demoapp/.svn/text-base/DemoTokensViewController.m.svn-base b/demoapp/.svn/text-base/DemoTokensViewController.m.svn-base new file mode 100644 index 0000000..20516de --- /dev/null +++ b/demoapp/.svn/text-base/DemoTokensViewController.m.svn-base @@ -0,0 +1,119 @@ +// +// DemoTokensViewController.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "DemoTokensViewController.h" +#import +#import "PKParseTreeView.h" + +@interface DemoTokensViewController () +- (void)doParse; +- (void)done; +@end + +@implementation DemoTokensViewController + +- (id)init { + return [self initWithNibName:@"TokensView" bundle:nil]; +} + + +- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)b { + if (self = [super initWithNibName:name bundle:b]) { + self.tokenizer = [[[PKTokenizer alloc] init] autorelease]; + + [tokenizer.symbolState add:@"::"]; + [tokenizer.symbolState add:@"<="]; + [tokenizer.symbolState add:@">="]; + [tokenizer.symbolState add:@"=="]; + [tokenizer.symbolState add:@"!="]; + [tokenizer.symbolState add:@"+="]; + [tokenizer.symbolState add:@"-="]; + [tokenizer.symbolState add:@"*="]; + [tokenizer.symbolState add:@"/="]; + [tokenizer.symbolState add:@":="]; + [tokenizer.symbolState add:@"++"]; + [tokenizer.symbolState add:@"--"]; + [tokenizer.symbolState add:@"<>"]; + [tokenizer.symbolState add:@"=:="]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.inString = nil; + self.outString = nil; + self.tokString = nil; + self.toks = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { + NSString *s = [NSString stringWithFormat:@"%C", 0xab]; + NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:s]; + [tokenField setTokenizingCharacterSet:set]; +} + + +- (IBAction)parse:(id)sender { + if (![inString length]) { + NSBeep(); + return; + } + + self.busy = YES; + + //[self doParse]; + [NSThread detachNewThreadSelector:@selector(doParse) toTarget:self withObject:nil]; +} + + +- (void)doParse { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + //self.tokenizer = [PKTokenizer tokenizer]; + self.tokenizer.string = self.inString; + + + self.toks = [NSMutableArray array]; + PKToken *tok = nil; + PKToken *eof = [PKToken EOFToken]; + while (eof != (tok = [tokenizer nextToken])) { + [toks addObject:tok]; + } + + [self performSelectorOnMainThread:@selector(done) withObject:nil waitUntilDone:NO]; + + [pool drain]; +} + + +- (void)done { + NSMutableString *s = [NSMutableString string]; + for (PKToken *tok in toks) { + [s appendFormat:@"%@ %C", tok.stringValue, 0xab]; + } + self.tokString = [[s copy] autorelease]; + + s = [NSMutableString string]; + for (PKToken *tok in toks) { + [s appendFormat:@"%@\n", [tok debugDescription]]; + } + self.outString = [[s copy] autorelease]; + self.busy = NO; +} + +@synthesize tokenizer; +@synthesize inString; +@synthesize outString; +@synthesize tokString; +@synthesize toks; +@synthesize busy; +@end diff --git a/demoapp/.svn/text-base/DemoTreesViewController.h.svn-base b/demoapp/.svn/text-base/DemoTreesViewController.h.svn-base new file mode 100644 index 0000000..ab3d958 --- /dev/null +++ b/demoapp/.svn/text-base/DemoTreesViewController.h.svn-base @@ -0,0 +1,29 @@ +// +// DemoTreesViewController.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKParseTreeView; +@class TDSourceCodeTextView; + +@interface DemoTreesViewController : NSViewController { + IBOutlet TDSourceCodeTextView *grammarTextView; + IBOutlet TDSourceCodeTextView *inputTextView; + IBOutlet PKParseTreeView *parseTreeView; + + NSString *grammarString; + NSString *inString; + BOOL busy; +} + +- (IBAction)parse:(id)sender; + +@property (retain) NSString *grammarString; +@property (retain) NSString *inString; +@property BOOL busy; +@end diff --git a/demoapp/.svn/text-base/DemoTreesViewController.m.svn-base b/demoapp/.svn/text-base/DemoTreesViewController.m.svn-base new file mode 100644 index 0000000..5e83392 --- /dev/null +++ b/demoapp/.svn/text-base/DemoTreesViewController.m.svn-base @@ -0,0 +1,157 @@ +// +// DemoTreesViewController.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "DemoTreesViewController.h" +#import "PKParseTreeView.h" +#import "TDSourceCodeTextView.h" +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" +#import "PKParseTreeAssembler.h" +#import + +@interface DemoTreesViewController () +- (void)renderGutters; +@end + +@implementation DemoTreesViewController + +- (id)init { + return [self initWithNibName:@"TreesView" bundle:nil]; +} + + +- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)b { + if (self = [super initWithNibName:name bundle:b]) { + + } + return self; +} + + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + self.grammarString = nil; + self.inString = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { +// self.grammarString = @"@allowsScientificNotation=YES;\n@start = expr;\nexpr = addExpr;\naddExpr = multExpr (('+'|'-') multExpr)*;\nmultExpr = atom (('*'|'/') atom)*;\natom = Number;"; +// self.grammarString = @"@start = array;array = '[' Number (commaNumber)* ']';commaNumber = ',' Number;"; +// self.grammarString = @"@start = array;array = foo | Word; foo = 'foo';"; + self.grammarString = @"@allowsScientificNotation = YES; @start = Empty | array | object; object = '{' (Empty | property (',' property)*) '}'; property = name ':' value; name = QuotedString; array = '[' (Empty | value (',' value)*) ']'; value = 'null' | boolean | array | object | number | string; string = QuotedString; number = Number; boolean = 'true' | 'false';"; + + +// self.inString = @"4.0*.4 + 2e-12/-47 +3"; +// self.inString = @"[1,2]"; +// self.inString = @"foo"; + self.inString = @"[42e-12, null,{'foo':false}]"; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeMain:) name:NSWindowDidBecomeMainNotification object:[[self view] window]]; +} + + +- (void)windowDidBecomeMain:(NSNotification *)n { + [self renderGutters]; +} + + +- (void)renderGutters { + [grammarTextView renderGutter]; + [inputTextView renderGutter]; +} + + +- (IBAction)parse:(id)sender { + if (![inString length] || ![grammarString length]) { + NSBeep(); + return; + } + + self.busy = YES; + + [NSThread detachNewThreadSelector:@selector(doParse) toTarget:self withObject:nil]; +} + + +- (void)doParse { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + PKParseTreeAssembler *as = [[[PKParseTreeAssembler alloc] init] autorelease]; + PKParser *p = [[PKParserFactory factory] parserFromGrammar:grammarString assembler:as preassembler:as]; + PKParseTree *tr = [p parse:inString]; + [parseTreeView drawParseTree:tr]; + + // release + PKReleaseSubparserTree(p); + + [self performSelectorOnMainThread:@selector(done) withObject:nil waitUntilDone:NO]; + + [pool drain]; +} + + +- (void)done { + self.busy = NO; +} + + +#pragma mark - +#pragma mark NSSplitViewDelegate + +- (BOOL)splitView:(NSSplitView *)sv canCollapseSubview:(NSView *)v { + return v == [[sv subviews] objectAtIndex:1]; +} + + +- (BOOL)splitView:(NSSplitView *)sv shouldCollapseSubview:(NSView *)v forDoubleClickOnDividerAtIndex:(NSInteger)i { + return [self splitView:sv canCollapseSubview:v]; +} + + + +// maintain constant splitview width when resizing window +- (void)splitView:(NSSplitView *)sv resizeSubviewsWithOldSize:(NSSize)oldSize { + NSRect newFrame = [sv frame]; // get the new size of the whole splitView + NSView *top = [[sv subviews] objectAtIndex:0]; + NSRect topFrame = [top frame]; + NSView *bottom = [[sv subviews] objectAtIndex:1]; + NSRect bottomFrame = [bottom frame]; + + CGFloat dividerThickness = [sv dividerThickness]; + topFrame.size.width = newFrame.size.width; + + bottomFrame.size.height = newFrame.size.height - topFrame.size.height - dividerThickness; + bottomFrame.size.width = newFrame.size.width; + topFrame.origin.y = 0; + + [top setFrame:topFrame]; + [bottom setFrame:bottomFrame]; +} + + +- (CGFloat)splitView:(NSSplitView *)sv constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)i { + if (0 == i) { + return 200; + } else { + return proposedMin; + } +} + + +- (CGFloat)splitView:(NSSplitView *)sv constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)i { + return proposedMax; +} + +@synthesize grammarString; +@synthesize inString; +@synthesize busy; +@end + diff --git a/demoapp/.svn/text-base/PKParseTreeView.h.svn-base b/demoapp/.svn/text-base/PKParseTreeView.h.svn-base new file mode 100644 index 0000000..0a9babb --- /dev/null +++ b/demoapp/.svn/text-base/PKParseTreeView.h.svn-base @@ -0,0 +1,21 @@ +// +// PKParseTreeView.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKParseTree; + +@interface PKParseTreeView : NSView { + PKParseTree *parseTree; + NSDictionary *labelAttrs; +} +- (void)drawParseTree:(PKParseTree *)t; + +@property (nonatomic, retain) PKParseTree *parseTree; +@property (nonatomic, retain) NSDictionary *labelAttrs; +@end diff --git a/demoapp/.svn/text-base/PKParseTreeView.m.svn-base b/demoapp/.svn/text-base/PKParseTreeView.m.svn-base new file mode 100644 index 0000000..1cc0030 --- /dev/null +++ b/demoapp/.svn/text-base/PKParseTreeView.m.svn-base @@ -0,0 +1,184 @@ +// +// PKParseTreeView.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKParseTreeView.h" +#import +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" +#import "PKParseTreeAssembler.h" + +#define ROW_HEIGHT 50.0 +#define CELL_WIDTH 55.0 + +@interface PKParseTreeView () +- (void)drawTree:(PKParseTree *)n atPoint:(NSPoint)p; +- (void)drawParentNode:(PKParseTree *)n atPoint:(NSPoint)p; +- (void)drawLeafNode:(PKTokenNode *)n atPoint:(NSPoint)p; + +- (CGFloat)widthForNode:(PKParseTree *)n; +- (CGFloat)depthForNode:(PKParseTree *)n; +- (NSString *)labelFromNode:(PKParseTree *)n; +- (void)drawLabel:(NSString *)label atPoint:(NSPoint)p; +@end + +@implementation PKParseTreeView + +- (id)initWithFrame:(NSRect)frame { + if (self = [super initWithFrame:frame]) { + self.labelAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:10], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, + nil]; + } + return self; +} + + +- (void)dealloc { + self.parseTree = nil; + self.labelAttrs = nil; + [super dealloc]; +} + + +- (BOOL)isFlipped { + return YES; +} + + +- (void)drawParseTree:(PKParseTree *)t { + self.parseTree = t; + + CGFloat w = [self widthForNode:parseTree] * CELL_WIDTH; + CGFloat h = [self depthForNode:parseTree] * ROW_HEIGHT + 120; + + NSSize minSize = [[self superview] bounds].size; + w = w < minSize.width ? minSize.width : w; + h = h < minSize.height ? minSize.height : h; + [self setFrame:NSMakeRect(0, 0, w, h)]; + + [self setNeedsDisplay:YES]; +} + + +- (void)drawRect:(NSRect)r { + [[NSColor whiteColor] set]; + NSRectFill(r); + + [self drawTree:parseTree atPoint:NSMakePoint(r.size.width / 2, 20)]; +} + + +- (void)drawTree:(PKParseTree *)n atPoint:(NSPoint)p { + if ([n isKindOfClass:[PKTokenNode class]]) { + [self drawLeafNode:(id)n atPoint:p]; + } else { + [self drawParentNode:n atPoint:p]; + } +} + + +- (void)drawParentNode:(PKParseTree *)n atPoint:(NSPoint)p { + // draw own label + [self drawLabel:[self labelFromNode:n] atPoint:NSMakePoint(p.x, p.y)]; + + NSUInteger i = 0; + NSUInteger c = [[n children] count]; + + // get total width + CGFloat widths[c]; + CGFloat totalWidth = 0; + for (PKParseTree *child in [n children]) { + widths[i] = [self widthForNode:child] * CELL_WIDTH; + totalWidth += widths[i++]; + } + + + // draw children + NSPoint points[c]; + if (1 == c) { + points[0] = NSMakePoint(p.x, p.y + ROW_HEIGHT); + [self drawTree:[[n children] objectAtIndex:0] atPoint:points[0]]; + } else { + CGFloat x = 0; + CGFloat buff = 0; + for (i = 0; i < c; i++) { + x = p.x - (totalWidth/2) + buff + widths[i]/2; + buff += widths[i]; + + points[i] = NSMakePoint(x, p.y + ROW_HEIGHT); + [self drawTree:[[n children] objectAtIndex:i] atPoint:points[i]]; + } + } + + // draw lines + CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort]; + + for (i = 0; i < c; i++) { + CGContextBeginPath(ctx); + CGContextMoveToPoint(ctx, p.x, p.y + 15); + CGContextAddLineToPoint(ctx, points[i].x, points[i].y - 4); + CGContextClosePath(ctx); + CGContextStrokePath(ctx); + } +} + + +- (void)drawLeafNode:(PKTokenNode *)n atPoint:(NSPoint)p { + [self drawLabel:[self labelFromNode:n] atPoint:NSMakePoint(p.x, p.y)]; +} + + +- (CGFloat)widthForNode:(PKParseTree *)n { + CGFloat res = 0; + for (PKParseTree *child in [n children]) { + res += [self widthForNode:child]; + } + return res ? res : 1; +} + + +- (CGFloat)depthForNode:(PKParseTree *)n { + CGFloat res = 0; + for (PKParseTree *child in [n children]) { + CGFloat n = [self depthForNode:child]; + res = n > res ? n : res; + } + return res + 1; +} + + +- (NSString *)labelFromNode:(PKParseTree *)n { + if ([n isKindOfClass:[PKTokenNode class]]) { + return [[(PKTokenNode *)n token] stringValue]; + } else if ([n isKindOfClass:[PKRuleNode class]]) { + return [(PKRuleNode *)n name]; + } else { + return @"root"; + } +} + + +- (void)drawLabel:(NSString *)label atPoint:(NSPoint)p { + NSSize labelSize = [label sizeWithAttributes:labelAttrs]; + NSRect maxRect = NSMakeRect(p.x - CELL_WIDTH / 2, p.y, CELL_WIDTH, labelSize.height); + + if (!NSContainsRect(maxRect, NSMakeRect(maxRect.origin.x, maxRect.origin.y, labelSize.width, labelSize.height))) { + labelSize = maxRect.size; + } + + p.x -= labelSize.width / 2; + NSRect r = NSMakeRect(p.x, p.y, labelSize.width, labelSize.height); + NSUInteger opts = NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin; + [label drawWithRect:r options:opts attributes:labelAttrs]; +} + +@synthesize parseTree; +@synthesize labelAttrs; +@end diff --git a/demoapp/.svn/text-base/TDGutterView.h.svn-base b/demoapp/.svn/text-base/TDGutterView.h.svn-base new file mode 100644 index 0000000..d3a7b16 --- /dev/null +++ b/demoapp/.svn/text-base/TDGutterView.h.svn-base @@ -0,0 +1,25 @@ +// +// TDGutterView.h +// TextTest +// +// Created by Todd Ditchendorf on 9/9/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import + +@interface TDGutterView : NSView { + IBOutlet NSScrollView *sourceScrollView; + IBOutlet NSTextView *sourceTextView; + + NSArray *lineNumberRects; + NSUInteger startLineNumber; + + NSDictionary *attrs; +} +@property (retain) NSArray *lineNumberRects; +@property NSUInteger startLineNumber; + +@property (retain) NSScrollView *sourceScrollView; +@property (retain) NSTextView *sourceTextView; +@end diff --git a/demoapp/.svn/text-base/TDGutterView.m.svn-base b/demoapp/.svn/text-base/TDGutterView.m.svn-base new file mode 100644 index 0000000..88695f8 --- /dev/null +++ b/demoapp/.svn/text-base/TDGutterView.m.svn-base @@ -0,0 +1,92 @@ +// +// TDGutterView.m +// TextTest +// +// Created by Todd Ditchendorf on 9/9/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "TDGutterView.h" + +@interface TDGutterView () +@property (retain) NSDictionary *attrs; +@end + +@implementation TDGutterView + +- (void)awakeFromNib { + self.attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont userFixedPitchFontOfSize:11.], NSFontAttributeName, + [NSColor grayColor], NSForegroundColorAttributeName, + nil]; +} + + +- (void)dealloc { + self.sourceScrollView = nil; + self.sourceTextView = nil; + self.lineNumberRects = nil; + self.attrs = nil; + [super dealloc]; +} + + +- (BOOL)isFlipped { + return YES; +} + + +- (NSUInteger)autoresizingMask { + return NSViewHeightSizable; +} + + +- (void)drawRect:(NSRect)rect { + NSDrawWindowBackground(rect); + + CGFloat rectWidth = rect.size.width; + NSPoint p1 = NSMakePoint(rectWidth + 2., 0.); + NSPoint p2 = NSMakePoint(rectWidth + 2., rect.size.height); + [NSBezierPath strokeLineFromPoint:p1 toPoint:p2]; + + if (![lineNumberRects count]) { + return; + } + + NSUInteger i = startLineNumber; + NSUInteger count = i + [lineNumberRects count]; + + for ( ; i < count; i++) { + NSRect r = [[lineNumberRects objectAtIndex:i - startLineNumber] rectValue]; + + // set the x origin of the number according to the number of digits it contains + CGFloat x = 0.; + if (i < 9) { + x = rectWidth - 14.; + } else if (i < 99) { + x = rectWidth - 21.; + } else if (i < 999) { + x = rectWidth - 28.; + } else if (i < 9999) { + x = rectWidth - 35.; + } + r.origin.x = x; + + // center the number vertically for tall lines + if (r.origin.y) { + r.origin.y += r.size.height/2. - 7.; + } + + NSString *s = [[NSNumber numberWithInteger:i + 1] stringValue]; + NSAttributedString *as = [[NSAttributedString alloc] initWithString:s attributes:attrs]; + [as drawAtPoint:r.origin]; + [as release]; + } +} + +@synthesize sourceScrollView; +@synthesize sourceTextView; +@synthesize lineNumberRects; +@synthesize startLineNumber; +@synthesize attrs; +@end diff --git a/demoapp/.svn/text-base/TDSourceCodeTextView.h.svn-base b/demoapp/.svn/text-base/TDSourceCodeTextView.h.svn-base new file mode 100644 index 0000000..a746ce1 --- /dev/null +++ b/demoapp/.svn/text-base/TDSourceCodeTextView.h.svn-base @@ -0,0 +1,21 @@ +// +// TDSourceCodeTextView.h +// TextTest +// +// Created by Todd Ditchendorf on 9/9/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import + +@class TDGutterView; + +@interface TDSourceCodeTextView : NSTextView { + IBOutlet TDGutterView *gutterView; + IBOutlet NSScrollView *scrollView; + CGFloat sourceTextViewOffset; +} +- (void)renderGutter; + +@property (assign) TDGutterView *gutterView; +@end diff --git a/demoapp/.svn/text-base/TDSourceCodeTextView.m.svn-base b/demoapp/.svn/text-base/TDSourceCodeTextView.m.svn-base new file mode 100644 index 0000000..0b511b1 --- /dev/null +++ b/demoapp/.svn/text-base/TDSourceCodeTextView.m.svn-base @@ -0,0 +1,116 @@ +// +// TDSourceCodeTextView.m +// TextTest +// +// Created by Todd Ditchendorf on 9/9/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "TDSourceCodeTextView.h" +#import "TDGutterView.h" + +@interface TDSourceCodeTextView () +- (void)registerForNotifications; +- (void)getRectsOfVisibleLines:(NSArray **)outRects startingLineNumber:(NSUInteger *)outRect; +- (NSUInteger)lineNumberForIndex:(NSUInteger)inIndex; +@end + +@implementation TDSourceCodeTextView + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + self.gutterView = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { + [self registerForNotifications]; + [self renderGutter]; +} + + +- (void)textDidChange:(NSNotification *)n { + [self renderGutter]; +} + + +- (void)viewBoundsChanged:(NSNotification *)n { + [self renderGutter]; +} + + +- (void)renderGutter { + if (![[self window] isVisible]) return; + NSArray *rects = nil; + NSUInteger start = 0; + [self getRectsOfVisibleLines:&rects startingLineNumber:&start]; + gutterView.lineNumberRects = rects; + gutterView.startLineNumber = start; + [gutterView setNeedsDisplay:YES]; +} + + +- (void)registerForNotifications { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(textDidChange:) + name:NSTextDidChangeNotification + object:self]; + + [scrollView.contentView setPostsBoundsChangedNotifications:YES]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(viewBoundsChanged:) + name:NSViewBoundsDidChangeNotification + object:scrollView.contentView]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(viewBoundsChanged:) + name:NSWindowDidResizeNotification + object:self.window]; +} + + +//- (void)showFindIndicatorForRange:(NSRange)charRange; + +- (void)getRectsOfVisibleLines:(NSArray **)outRects startingLineNumber:(NSUInteger *)outStart { + NSMutableArray *result = [NSMutableArray array]; + NSString *s = self.string; + + NSLayoutManager *layoutMgr = self.textContainer.layoutManager; + NSRect boundingRect = [scrollView.contentView documentVisibleRect]; + CGFloat scrollY = boundingRect.origin.y; + NSRange visibleGlyphRange = [layoutMgr glyphRangeForBoundingRect:boundingRect inTextContainer:self.textContainer]; + + NSUInteger index = visibleGlyphRange.location; + NSUInteger length = index + [visibleGlyphRange length]; + + (*outStart) = [self lineNumberForIndex:index + 1]; + + while (index < length) { + NSRange r = [s lineRangeForRange:NSMakeRange(index, 0)]; + index = NSMaxRange(r); + NSRect rect = [layoutMgr lineFragmentRectForGlyphAtIndex:r.location effectiveRange:NULL withoutAdditionalLayout:YES]; + rect.origin.y -= scrollY; + [result addObject:[NSValue valueWithRect:rect]]; + } + + (*outRects) = result; +} + + +- (NSUInteger)lineNumberForIndex:(NSUInteger)inIndex { + NSString *s = self.string; + NSUInteger numberOfLines, index, stringLength = [s length]; + + for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++) { + NSRange r = [s lineRangeForRange:NSMakeRange(index, 0)]; + index = NSMaxRange(r); + if (inIndex <= index) { + break; + } + } + + return numberOfLines; +} + +@synthesize gutterView; +@end diff --git a/demoapp/.svn/text-base/TokensView.xib.svn-base b/demoapp/.svn/text-base/TokensView.xib.svn-base new file mode 100644 index 0000000..7d15c41 --- /dev/null +++ b/demoapp/.svn/text-base/TokensView.xib.svn-base @@ -0,0 +1,939 @@ + + + + 1050 + 9J61 + 677 + 949.46 + 353.00 + + YES + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + DemoTokensViewController + + + FirstResponder + + + NSApplication + + + + 268 + + YES + + + 274 + + YES + + + 2304 + + YES + + + 2322 + {457, 84} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + YES + + YES + + YES + NSFont + NSParagraphStyle + + + YES + + LucidaGrande + 1.000000e+01 + 2843 + + + 3 + + YES + + 0.000000e+00 + + + 5.600000e+01 + + + 1.120000e+02 + + + 1.680000e+02 + + + 2.240000e+02 + + + 2.800000e+02 + + + 3.360000e+02 + + + 3.920000e+02 + + + 4.480000e+02 + + + 5.040000e+02 + + + 5.600000e+02 + + + 6.160000e+02 + + + 6.720000e+02 + + + 7.280000e+02 + + + 7.840000e+02 + + + 8.400000e+02 + + + 8.960000e+02 + + + 9.520000e+02 + + + 1.008000e+03 + + + 1.064000e+03 + + + 1.120000e+03 + + + 1.176000e+03 + + + 1.232000e+03 + + + 1.288000e+03 + + + 1.344000e+03 + + + 1.400000e+03 + + + 1.456000e+03 + + + 1.512000e+03 + + + 1.568000e+03 + + + 1.624000e+03 + + + 1.680000e+03 + + + 1.736000e+03 + + + + + + + YES + + YES + NSFont + NSParagraphStyle + + + YES + + LucidaGrande-Bold + 1.000000e+01 + 16 + + + 3 + + YES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GQAEAQgADAEiAAcBhAQAA + + + + + YES + + + 6 + + + + 4.570000e+02 + 1 + + + 11009 + + 3 + MQA + + + 3 + MAA + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + 6 + System + selectedTextBackgroundColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + selectedTextColor + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + 1 + MCAwIDEAA + + + + + + + 6 + {931, 1e+07} + {83, 0} + + + + {{1, 1}, {457, 236}} + + + + + + {4, -5} + 1 + + 4 + + + + 256 + {{458, 1}, {15, 236}} + + + _doScroller: + 2.835196e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{21, 170}, {474, 238}} + + + 18 + + + + + + + 266 + {{18, 529}, {480, 51}} + + YES + + 67239424 + 272629760 + VGhpcyBhcHBsaWNhdGlvbiBnaXZlcyBhIGJhc2ljIHZpc3VhbCBkZW1vbnN0cmF0aW9uIG9mIHRoZSBU +T0RUb2tlbml6ZXIgY2xhc3MgaW5jbHVkZWQgaW4gdGhlIFRPRFBhcnNlS2l0IEZyYW1ld29yay4gUGxh +Y2UgYW55IHRleHQgaW4gdGhlIHRleHQgZmllbGQgZGlyZWN0bHkgYmVsb3cuIENsaWNrIHRoZSAiUGFy +c2UiIGJ1dHRvbiB0byBzZWUgdGhlIHRleHQgdG9rZW5pemVkLg + + LucidaGrande + 1.300000e+01 + 16 + + + + 6 + System + controlColor + + + + 6 + System + controlTextColor + + + + + + + 265 + {{405, 408}, {96, 32}} + + YES + + 67239424 + 134217728 + Parse + + LucidaGrande + 1.300000e+01 + 1044 + + + -2038284033 + 268435585 + + DQ + 200 + 25 + + + + + 290 + + YES + + YES + NSStringPboardType + + + {{21, 20}, {474, 142}} + + YES + + 341966336 + 0 + + LucidaGrande-Bold + 1.200000e+01 + 16 + + + YES + + 6 + System + textBackgroundColor + + + + + 0.000000e+00 + 0 + + 2 + + + + 266 + + YES + + + 2304 + + YES + + + 2322 + {457, 84} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + YES + + + + + GQAEAQgADAEiAAcBhAQAA + + + + + YES + + + 6 + + + + 4.570000e+02 + 1 + + + 11009 + + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + + + + + + 6 + {931, 1e+07} + {83, 0} + + + + {{1, 1}, {457, 75}} + + + + + + 4 + + + + 256 + {{458, 1}, {15, 75}} + + YES + + _doScroller: + 8.928571e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{21, 444}, {474, 77}} + + + 82 + + + + + + + 1289 + + {{387, 416}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + {515, 593} + + NSView + + + + + YES + + + animate: busy + + + + + + animate: busy + animate + busy + 2 + + + 17 + + + + tokenField + + + + 18 + + + + view + + + + 19 + + + + parse: + + + + 20 + + + + value: inString + + + + + + value: inString + value + inString + + NSContinuouslyUpdatesValue + + + 2 + + + 22 + + + + value: outString + + + + + + value: outString + value + outString + + NSContinuouslyUpdatesValue + + + 2 + + + 24 + + + + value: tokString + + + + + + value: tokString + value + tokString + + NSContinuouslyUpdatesValue + + + 2 + + + 28 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + YES + + + + + + + + + + + 2 + + + YES + + + + + + + + 3 + + + YES + + + + + + 4 + + + YES + + + + + + 5 + + + YES + + + + + + 6 + + + YES + + + + + + + + 7 + + + + + 8 + + + + + 9 + + + + + 10 + + + + + 11 + + + + + 12 + + + + + 13 + + + + + 14 + + + + + 15 + + + + + 16 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 1.IBEditorWindowLastContentRect + 1.IBPluginDependency + 1.WindowOrigin + 1.editorWindowContentRectSynchronizationRect + 10.IBPluginDependency + 11.IBPluginDependency + 12.IBPluginDependency + 13.IBPluginDependency + 14.IBPluginDependency + 15.IBPluginDependency + 16.IBPluginDependency + 2.IBPluginDependency + 3.IBPluginDependency + 4.IBPluginDependency + 5.IBPluginDependency + 6.IBPluginDependency + 7.IBPluginDependency + 8.IBPluginDependency + 9.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + {{227, 263}, {515, 593}} + com.apple.InterfaceBuilder.CocoaPlugin + {628, 654} + {{217, 442}, {480, 272}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 28 + + + + YES + + DemoTokensViewController + NSViewController + + parse: + id + + + tokenField + NSTokenField + + + IBProjectSource + demoapp/DemoTokensViewController.h + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + + 0 + ../ParseKit.xcodeproj + 3 + + diff --git a/demoapp/.svn/text-base/TreesView.xib.svn-base b/demoapp/.svn/text-base/TreesView.xib.svn-base new file mode 100644 index 0000000..1088d32 --- /dev/null +++ b/demoapp/.svn/text-base/TreesView.xib.svn-base @@ -0,0 +1,1391 @@ + + + + 1050 + 9J61 + 677 + 949.46 + 353.00 + + YES + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + DemoTreesViewController + + + FirstResponder + + + NSApplication + + + + 268 + + YES + + + 274 + + YES + + + 274 + + YES + + + 1313 + + {{386, 5}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + + 289 + {{404, -5}, {96, 32}} + + YES + + 67239424 + 134217728 + Parse + + LucidaGrande + 1.300000e+01 + 1044 + + + -2038284033 + 268435585 + + DQ + 200 + 25 + + + + + 274 + + YES + + + 278 + + YES + + + 268 + {{37, 223}, {67, 17}} + + YES + + 68288064 + 272630784 + Grammar: + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 276 + {{20, 2}, {40, 214}} + + TDGutterView + + + + 274 + + YES + + + 2304 + + YES + + + 2322 + + YES + + YES + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple PNG pasteboard type + Apple URL pasteboard type + CorePasteboardFlavorType 0x6D6F6F76 + CorePasteboardFlavorType 0x75726C20 + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT Encapsulated PostScript v1.2 pasteboard type + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + NeXT font pasteboard type + NeXT ruler pasteboard type + WebURLsWithTitlesPboardType + + + {189, 432} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + YES + + YES + NSColor + NSFont + NSParagraphStyle + + + YES + + 3 + MQA + + + Monaco + 1.200000e+01 + 16 + + + 3 + + YES + + 0.000000e+00 + + + 5.600000e+01 + + + 1.120000e+02 + + + 1.680000e+02 + + + 2.240000e+02 + + + 2.800000e+02 + + + 3.360000e+02 + + + 3.920000e+02 + + + 4.480000e+02 + + + 5.040000e+02 + + + 5.600000e+02 + + + 6.160000e+02 + + + 6.720000e+02 + + + 7.280000e+02 + + + 7.840000e+02 + + + 8.400000e+02 + + + 8.960000e+02 + + + 9.520000e+02 + + + 1.008000e+03 + + + 1.064000e+03 + + + 1.120000e+03 + + + 1.176000e+03 + + + 1.232000e+03 + + + 1.288000e+03 + + + 1.344000e+03 + + + 1.400000e+03 + + + 1.456000e+03 + + + 1.512000e+03 + + + 1.568000e+03 + + + 1.624000e+03 + + + 1.680000e+03 + + + 1.736000e+03 + + + + + + + + + YES + + + 6 + + + + 1.890000e+02 + 1 + + + 12131 + + 2 + MC4xMTc2NDcwNyAwLjEyNTQ5MDIgMC4xNTY4NjI3NQA + + + 3 + MQA + + 2 + + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + 6 + System + selectedTextBackgroundColor + + + + 6 + System + selectedTextColor + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + 1 + MCAwIDEAA + + + + + + + 6 + {931, 1e+07} + {100, 0} + + + + {190, 214} + + + + + + {4, -5} + 1 + + 4 + + + + 256 + {{190, 0}, {15, 214}} + + YES + + _doScroller: + 4.953704e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{60, 2}, {205, 214}} + + + 80 + + + + + + + 14 + {{20, 214}, {245, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + 6 + System + textBackgroundColor + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + + 38 + {{20, -1}, {245, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + {268, 260} + + NSView + + + + 275 + + YES + + + 268 + {{17, 224}, {67, 17}} + + YES + + 68288064 + 272630784 + Input: + + + + + + + + + 276 + {{0, 2}, {40, 214}} + + TDGutterView + + + + 274 + + YES + + + 2304 + + YES + + + 2322 + + YES + + YES + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple PNG pasteboard type + Apple URL pasteboard type + CorePasteboardFlavorType 0x6D6F6F76 + CorePasteboardFlavorType 0x75726C20 + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT Encapsulated PostScript v1.2 pasteboard type + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + NeXT font pasteboard type + NeXT ruler pasteboard type + WebURLsWithTitlesPboardType + + + {201, 400} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + + + + YES + + + 6 + + + + 2.010000e+02 + 1 + + + 12131 + + 2 + MC4xMTc2NDcwNyAwLjEyNTQ5MDIgMC4xNTY4NjI3NQA + + + 3 + MQA + + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + + + + + + 6 + {931, 1e+07} + {105, 0} + + + + {202, 214} + + + + + + 4 + + + + 256 + {{202, 0}, {15, 214}} + + YES + + _doScroller: + 5.350000e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{40, 2}, {217, 214}} + + + 80 + + + + + + + 11 + {{0, 214}, {257, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + + 35 + {{0, -1}, {265, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + {{277, 0}, {257, 260}} + + NSView + + + {{-20, 34}, {534, 260}} + + YES + + + {514, 274} + + NSView + + + + 256 + + YES + + + 274 + + YES + + + 2304 + + YES + + + 274 + {496, 291} + + PKParseTreeView + + + {{1, 1}, {496, 291}} + + + + + 4 + + + + 256 + {{497, 1}, {15, 288}} + + + _doScroller: + 1.000000e+00 + 9.956332e-01 + + + + 256 + {{1, 292}, {496, 15}} + + 1 + + _doScroller: + 9.978166e-01 + + + {{0, -1}, {513, 308}} + + + 50 + + + + + + {{0, 283}, {514, 307}} + + NSView + + + {514, 590} + + + + {514, 590} + + NSView + + + + + YES + + + nextKeyView + + + + 114 + + + + nextKeyView + + + + 116 + + + + nextKeyView + + + + 119 + + + + delegate + + + + 122 + + + + scrollView + + + + 123 + + + + gutterView + + + + 124 + + + + scrollView + + + + 126 + + + + gutterView + + + + 127 + + + + view + + + + 129 + + + + parseTreeView + + + + 130 + + + + parse: + + + + 131 + + + + grammarTextView + + + + 132 + + + + inputTextView + + + + 133 + + + + value: inString + + + + + + value: inString + value + inString + + NSContinuouslyUpdatesValue + + + 2 + + + 136 + + + + value: grammarString + + + + + + value: grammarString + value + grammarString + + NSContinuouslyUpdatesValue + + + 2 + + + 137 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + YES + + + + + + 60 + + + YES + + + + + + + 62 + + + YES + + + + + + 8 + + + YES + + + + + + bottomContainerView + + + 9 + + + YES + + + + + 10 + + + + + 11 + + + + + 92 + + + YES + + + + + + topContainerView + + + 102 + + + + + 104 + + + YES + + + + + + 105 + + + + + 141 + + + YES + + + + + + + 138 + + + YES + + + + + + + + leftContainerView + + + 100 + + + YES + + + + + + grammarScrollView + + + 98 + + + + + 99 + + + YES + + + + + + 96 + + + + + 113 + + + + + 110 + + + + + 111 + + + + + 112 + + + grammarTextView + + + 139 + + + YES + + + + + + + + rightContainerView + + + 95 + + + + + 94 + + + + + 103 + + + YES + + + + + + 93 + + + + + 101 + + + YES + + + + + + inputScrollView + + + 107 + + + inputTextView + + + 108 + + + + + 109 + + + + + 106 + + + + + 97 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 1.IBEditorWindowLastContentRect + 1.IBPluginDependency + 1.WindowOrigin + 1.editorWindowContentRectSynchronizationRect + 10.IBPluginDependency + 100.IBPluginDependency + 101.IBPluginDependency + 102.IBPluginDependency + 103.IBPluginDependency + 104.IBPluginDependency + 105.IBPluginDependency + 106.IBPluginDependency + 107.CustomClassName + 107.IBPluginDependency + 108.IBPluginDependency + 109.IBPluginDependency + 11.IBPluginDependency + 110.IBPluginDependency + 111.IBPluginDependency + 112.CustomClassName + 112.IBPluginDependency + 113.IBPluginDependency + 60.IBPluginDependency + 62.IBPluginDependency + 8.IBPluginDependency + 9.IBPluginDependency + 93.IBPluginDependency + 94.IBPluginDependency + 95.IBPluginDependency + 96.IBPluginDependency + 97.IBPluginDependency + 98.IBPluginDependency + 99.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + {{32, 260}, {514, 590}} + com.apple.InterfaceBuilder.CocoaPlugin + {628, 654} + {{217, 442}, {480, 272}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + TDSourceCodeTextView + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + TDSourceCodeTextView + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 142 + + + + YES + + DemoTreesViewController + NSViewController + + parse: + id + + + YES + + YES + grammarTextView + inputTextView + parseTreeView + + + YES + TDSourceCodeTextView + TDSourceCodeTextView + PKParseTreeView + + + + IBProjectSource + demoapp/DemoTreesViewController.h + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + PKParseTreeView + NSView + + IBProjectSource + demoapp/PKParseTreeView.h + + + + TDGutterView + NSView + + YES + + YES + sourceScrollView + sourceTextView + + + YES + NSScrollView + NSTextView + + + + IBProjectSource + demoapp/TDGutterView.h + + + + TDSourceCodeTextView + NSTextView + + YES + + YES + gutterView + scrollView + + + YES + TDGutterView + NSScrollView + + + + IBProjectSource + demoapp/TDSourceCodeTextView.h + + + + + 0 + ../ParseKit.xcodeproj + 3 + + diff --git a/demoapp/.svn/text-base/main.m.svn-base b/demoapp/.svn/text-base/main.m.svn-base new file mode 100644 index 0000000..5fdddb1 --- /dev/null +++ b/demoapp/.svn/text-base/main.m.svn-base @@ -0,0 +1,13 @@ +// +// main.m +// DemoApp +// +// Created by Todd Ditchendorf on 7/12/08. +// Copyright Todd Ditchendorf 2008. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) { + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/demoapp/DemoApp-Info.plist b/demoapp/DemoApp-Info.plist new file mode 100644 index 0000000..0e08ed6 --- /dev/null +++ b/demoapp/DemoApp-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.DemoApp + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + DemoAppMainMenu + NSPrincipalClass + NSApplication + + diff --git a/demoapp/DemoAppDelegate.h b/demoapp/DemoAppDelegate.h new file mode 100644 index 0000000..129a75f --- /dev/null +++ b/demoapp/DemoAppDelegate.h @@ -0,0 +1,29 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class DemoTokensViewController; +@class DemoTreesViewController; + +@interface DemoAppDelegate : NSObject { + IBOutlet NSTabView *tabView; + + DemoTokensViewController *tokensViewController; + DemoTreesViewController *treesViewController; +} + +@property (nonatomic, retain) DemoTokensViewController *tokensViewController; +@property (nonatomic, retain) DemoTreesViewController *treesViewController; +@end diff --git a/demoapp/DemoAppDelegate.m b/demoapp/DemoAppDelegate.m new file mode 100644 index 0000000..8db8499 --- /dev/null +++ b/demoapp/DemoAppDelegate.m @@ -0,0 +1,41 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "DemoAppDelegate.h" +#import "DemoTokensViewController.h" +#import "DemoTreesViewController.h" + +@implementation DemoAppDelegate + +- (void)dealloc { + self.tokensViewController = nil; + self.treesViewController = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { + self.tokensViewController = [[[DemoTokensViewController alloc] init] autorelease]; + self.treesViewController = [[[DemoTreesViewController alloc] init] autorelease]; + + NSTabViewItem *item = [tabView tabViewItemAtIndex:0]; + [item setView:[tokensViewController view]]; + + item = [tabView tabViewItemAtIndex:1]; + [item setView:[treesViewController view]]; +} + +@synthesize tokensViewController; +@synthesize treesViewController; +@end diff --git a/demoapp/DemoAppMainMenu.xib b/demoapp/DemoAppMainMenu.xib new file mode 100644 index 0000000..fc37aa6 --- /dev/null +++ b/demoapp/DemoAppMainMenu.xib @@ -0,0 +1,2268 @@ + + + + 1050 + 9J61 + 677 + 949.46 + 353.00 + + YES + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + DemoApp + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + DemoApp + + YES + + + About DemoApp + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide DemoApp + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit DemoApp + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + T3BlbuKApg + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + U2F2ZSBBc+KApg + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + UHJpbnTigKY + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + RmluZOKApg + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + U2hvdyBTcGVsbGluZ+KApg + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 1048576 + 2147483647 + + + submenuAction: + + Format + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Show Colors + C + 1179648 + 2147483647 + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Q3VzdG9taXplIFRvb2xiYXLigKY + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + Help + + YES + + + NewApplication Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + 15 + 2 + {{43, 10}, {1146, 856}} + 611844096 + ParseKit Demo + NSWindow + + {3.40282e+38, 3.40282e+38} + {514, 622} + + + 256 + + YES + + + 18 + {{-12, -13}, {1170, 863}} + + + YES + + 1 + + + 256 + {{10, 33}, {508, 580}} + + Tokens + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + + + 2 + + + 256 + {{10, 33}, {1150, 817}} + + + Trees + + + + + + + LucidaGrande + 1.300000e+01 + 1044 + + 0 + YES + YES + + YES + + + + + {1146, 856} + + + {{0, 0}, {1440, 878}} + {514, 644} + {3.40282e+38, 3.40282e+38} + + + DemoAppDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + orderFrontColorPanel: + + + + 361 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 369 + + + + hideOtherApplications: + + + + 370 + + + + terminate: + + + + 371 + + + + unhideAllApplications: + + + + 372 + + + + delegate + + + + 374 + + + + tabView + + + + 438 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + 3 + + + 80 + + + 8 + + + 78 + + + 6 + + + 72 + + + + + 82 + + + 9 + + + 124 + + + YES + + + + + + 77 + + + 5 + + + 73 + + + 1 + + + 79 + + + 7 + + + 112 + + + 10 + + + 74 + + + 2 + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 299 + + + YES + + + + + + 300 + + + YES + + + + + + + 344 + + + + + 345 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 367 + + + YES + + + + + + 368 + + + YES + + + + + + 373 + + + + + 413 + + + YES + + + + + + + 414 + + + YES + + + + + + 415 + + + YES + + + + + 416 + + + YES + + + + + + 417 + + + YES + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 299.IBPluginDependency + 300.IBPluginDependency + 300.editorWindowContentRectSynchronizationRect + 344.IBPluginDependency + 345.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 367.IBEditorWindowLastContentRect + 367.IBWindowTemplateEditedContentRect + 367.NSWindowTemplate.visibleAtLaunch + 367.editorWindowContentRectSynchronizationRect + 367.windowTemplate.hasMinSize + 367.windowTemplate.minSize + 368.IBPluginDependency + 373.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{596, 852}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{365, 632}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{0, 776}, {435, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 727}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{409, 832}, {176, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{8, 0}, {1146, 856}} + {{8, 0}, {1146, 856}} + + {{11, 316}, {480, 370}} + + {514, 622} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{12, 593}, {206, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{101, 533}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{323, 672}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 438 + + + + YES + + DemoAppDelegate + NSObject + + tabView + NSTabView + + + IBProjectSource + demoapp/DemoAppDelegate.h + + + + DemoAppDelegate + NSObject + + IBUserSource + + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + + 0 + ../ParseKit.xcodeproj + 3 + + diff --git a/demoapp/DemoTokensViewController.h b/demoapp/DemoTokensViewController.h new file mode 100644 index 0000000..d5cf329 --- /dev/null +++ b/demoapp/DemoTokensViewController.h @@ -0,0 +1,38 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKTokenizer; + +@interface DemoTokensViewController : NSViewController { + IBOutlet NSTokenField *tokenField; + + PKTokenizer *tokenizer; + NSString *inString; + NSString *outString; + NSString *tokString; + NSMutableArray *toks; + BOOL busy; +} + +- (IBAction)parse:(id)sender; + +@property (retain) PKTokenizer *tokenizer; +@property (retain) NSString *inString; +@property (retain) NSString *outString; +@property (retain) NSString *tokString; +@property (retain) NSMutableArray *toks; +@property BOOL busy; +@end diff --git a/demoapp/DemoTokensViewController.m b/demoapp/DemoTokensViewController.m new file mode 100644 index 0000000..7fa4fd2 --- /dev/null +++ b/demoapp/DemoTokensViewController.m @@ -0,0 +1,125 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "DemoTokensViewController.h" +#import +#import "PKParseTreeView.h" + +@interface DemoTokensViewController () +- (void)doParse; +- (void)done; +@end + +@implementation DemoTokensViewController + +- (id)init { + return [self initWithNibName:@"TokensView" bundle:nil]; +} + + +- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)b { + if (self = [super initWithNibName:name bundle:b]) { + self.tokenizer = [[[PKTokenizer alloc] init] autorelease]; + + [tokenizer.symbolState add:@"::"]; + [tokenizer.symbolState add:@"<="]; + [tokenizer.symbolState add:@">="]; + [tokenizer.symbolState add:@"=="]; + [tokenizer.symbolState add:@"!="]; + [tokenizer.symbolState add:@"+="]; + [tokenizer.symbolState add:@"-="]; + [tokenizer.symbolState add:@"*="]; + [tokenizer.symbolState add:@"/="]; + [tokenizer.symbolState add:@":="]; + [tokenizer.symbolState add:@"++"]; + [tokenizer.symbolState add:@"--"]; + [tokenizer.symbolState add:@"<>"]; + [tokenizer.symbolState add:@"=:="]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.inString = nil; + self.outString = nil; + self.tokString = nil; + self.toks = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { + NSString *s = [NSString stringWithFormat:@"%C", 0xab]; + NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:s]; + [tokenField setTokenizingCharacterSet:set]; +} + + +- (IBAction)parse:(id)sender { + if (![inString length]) { + NSBeep(); + return; + } + + self.busy = YES; + + //[self doParse]; + [NSThread detachNewThreadSelector:@selector(doParse) toTarget:self withObject:nil]; +} + + +- (void)doParse { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + //self.tokenizer = [PKTokenizer tokenizer]; + self.tokenizer.string = self.inString; + + + self.toks = [NSMutableArray array]; + PKToken *tok = nil; + PKToken *eof = [PKToken EOFToken]; + while (eof != (tok = [tokenizer nextToken])) { + [toks addObject:tok]; + } + + [self performSelectorOnMainThread:@selector(done) withObject:nil waitUntilDone:NO]; + + [pool drain]; +} + + +- (void)done { + NSMutableString *s = [NSMutableString string]; + for (PKToken *tok in toks) { + [s appendFormat:@"%@ %C", tok.stringValue, 0xab]; + } + self.tokString = [[s copy] autorelease]; + + s = [NSMutableString string]; + for (PKToken *tok in toks) { + [s appendFormat:@"%@\n", [tok debugDescription]]; + } + self.outString = [[s copy] autorelease]; + self.busy = NO; +} + +@synthesize tokenizer; +@synthesize inString; +@synthesize outString; +@synthesize tokString; +@synthesize toks; +@synthesize busy; +@end diff --git a/demoapp/DemoTreesViewController.h b/demoapp/DemoTreesViewController.h new file mode 100644 index 0000000..be7dbee --- /dev/null +++ b/demoapp/DemoTreesViewController.h @@ -0,0 +1,35 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKParseTreeView; +@class TDSourceCodeTextView; + +@interface DemoTreesViewController : NSViewController { + IBOutlet TDSourceCodeTextView *grammarTextView; + IBOutlet TDSourceCodeTextView *inputTextView; + IBOutlet PKParseTreeView *parseTreeView; + + NSString *grammarString; + NSString *inString; + BOOL busy; +} + +- (IBAction)parse:(id)sender; + +@property (retain) NSString *grammarString; +@property (retain) NSString *inString; +@property BOOL busy; +@end diff --git a/demoapp/DemoTreesViewController.m b/demoapp/DemoTreesViewController.m new file mode 100644 index 0000000..4aaadc2 --- /dev/null +++ b/demoapp/DemoTreesViewController.m @@ -0,0 +1,163 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "DemoTreesViewController.h" +#import "PKParseTreeView.h" +#import "TDSourceCodeTextView.h" +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" +#import "PKParseTreeAssembler.h" +#import + +@interface DemoTreesViewController () +- (void)renderGutters; +@end + +@implementation DemoTreesViewController + +- (id)init { + return [self initWithNibName:@"TreesView" bundle:nil]; +} + + +- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)b { + if (self = [super initWithNibName:name bundle:b]) { + + } + return self; +} + + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + self.grammarString = nil; + self.inString = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { +// self.grammarString = @"@allowsScientificNotation=YES;\n@start = expr;\nexpr = addExpr;\naddExpr = multExpr (('+'|'-') multExpr)*;\nmultExpr = atom (('*'|'/') atom)*;\natom = Number;"; +// self.grammarString = @"@start = array;array = '[' Number (commaNumber)* ']';commaNumber = ',' Number;"; +// self.grammarString = @"@start = array;array = foo | Word; foo = 'foo';"; + self.grammarString = @"@allowsScientificNotation = YES; @start = Empty | array | object; object = '{' (Empty | property (',' property)*) '}'; property = name ':' value; name = QuotedString; array = '[' (Empty | value (',' value)*) ']'; value = 'null' | boolean | array | object | number | string; string = QuotedString; number = Number; boolean = 'true' | 'false';"; + + +// self.inString = @"4.0*.4 + 2e-12/-47 +3"; +// self.inString = @"[1,2]"; +// self.inString = @"foo"; + self.inString = @"[42e-12, null,{'foo':false}]"; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeMain:) name:NSWindowDidBecomeMainNotification object:[[self view] window]]; +} + + +- (void)windowDidBecomeMain:(NSNotification *)n { + [self renderGutters]; +} + + +- (void)renderGutters { + [grammarTextView renderGutter]; + [inputTextView renderGutter]; +} + + +- (IBAction)parse:(id)sender { + if (![inString length] || ![grammarString length]) { + NSBeep(); + return; + } + + self.busy = YES; + + [NSThread detachNewThreadSelector:@selector(doParse) toTarget:self withObject:nil]; +} + + +- (void)doParse { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + PKParseTreeAssembler *as = [[[PKParseTreeAssembler alloc] init] autorelease]; + PKParser *p = [[PKParserFactory factory] parserFromGrammar:grammarString assembler:as preassembler:as]; + PKParseTree *tr = [p parse:inString]; + [parseTreeView drawParseTree:tr]; + + // release + PKReleaseSubparserTree(p); + + [self performSelectorOnMainThread:@selector(done) withObject:nil waitUntilDone:NO]; + + [pool drain]; +} + + +- (void)done { + self.busy = NO; +} + + +#pragma mark - +#pragma mark NSSplitViewDelegate + +- (BOOL)splitView:(NSSplitView *)sv canCollapseSubview:(NSView *)v { + return v == [[sv subviews] objectAtIndex:1]; +} + + +- (BOOL)splitView:(NSSplitView *)sv shouldCollapseSubview:(NSView *)v forDoubleClickOnDividerAtIndex:(NSInteger)i { + return [self splitView:sv canCollapseSubview:v]; +} + + + +// maintain constant splitview width when resizing window +- (void)splitView:(NSSplitView *)sv resizeSubviewsWithOldSize:(NSSize)oldSize { + NSRect newFrame = [sv frame]; // get the new size of the whole splitView + NSView *top = [[sv subviews] objectAtIndex:0]; + NSRect topFrame = [top frame]; + NSView *bottom = [[sv subviews] objectAtIndex:1]; + NSRect bottomFrame = [bottom frame]; + + CGFloat dividerThickness = [sv dividerThickness]; + topFrame.size.width = newFrame.size.width; + + bottomFrame.size.height = newFrame.size.height - topFrame.size.height - dividerThickness; + bottomFrame.size.width = newFrame.size.width; + topFrame.origin.y = 0; + + [top setFrame:topFrame]; + [bottom setFrame:bottomFrame]; +} + + +- (CGFloat)splitView:(NSSplitView *)sv constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)i { + if (0 == i) { + return 200; + } else { + return proposedMin; + } +} + + +- (CGFloat)splitView:(NSSplitView *)sv constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)i { + return proposedMax; +} + +@synthesize grammarString; +@synthesize inString; +@synthesize busy; +@end + diff --git a/demoapp/PKParseTreeView.h b/demoapp/PKParseTreeView.h new file mode 100644 index 0000000..e9d569b --- /dev/null +++ b/demoapp/PKParseTreeView.h @@ -0,0 +1,27 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKParseTree; + +@interface PKParseTreeView : NSView { + PKParseTree *parseTree; + NSDictionary *labelAttrs; +} +- (void)drawParseTree:(PKParseTree *)t; + +@property (nonatomic, retain) PKParseTree *parseTree; +@property (nonatomic, retain) NSDictionary *labelAttrs; +@end diff --git a/demoapp/PKParseTreeView.m b/demoapp/PKParseTreeView.m new file mode 100644 index 0000000..d7008f1 --- /dev/null +++ b/demoapp/PKParseTreeView.m @@ -0,0 +1,190 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKParseTreeView.h" +#import +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" +#import "PKParseTreeAssembler.h" + +#define ROW_HEIGHT 50.0 +#define CELL_WIDTH 55.0 + +@interface PKParseTreeView () +- (void)drawTree:(PKParseTree *)n atPoint:(NSPoint)p; +- (void)drawParentNode:(PKParseTree *)n atPoint:(NSPoint)p; +- (void)drawLeafNode:(PKTokenNode *)n atPoint:(NSPoint)p; + +- (CGFloat)widthForNode:(PKParseTree *)n; +- (CGFloat)depthForNode:(PKParseTree *)n; +- (NSString *)labelFromNode:(PKParseTree *)n; +- (void)drawLabel:(NSString *)label atPoint:(NSPoint)p; +@end + +@implementation PKParseTreeView + +- (id)initWithFrame:(NSRect)frame { + if (self = [super initWithFrame:frame]) { + self.labelAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:10], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, + nil]; + } + return self; +} + + +- (void)dealloc { + self.parseTree = nil; + self.labelAttrs = nil; + [super dealloc]; +} + + +- (BOOL)isFlipped { + return YES; +} + + +- (void)drawParseTree:(PKParseTree *)t { + self.parseTree = t; + + CGFloat w = [self widthForNode:parseTree] * CELL_WIDTH; + CGFloat h = [self depthForNode:parseTree] * ROW_HEIGHT + 120; + + NSSize minSize = [[self superview] bounds].size; + w = w < minSize.width ? minSize.width : w; + h = h < minSize.height ? minSize.height : h; + [self setFrame:NSMakeRect(0, 0, w, h)]; + + [self setNeedsDisplay:YES]; +} + + +- (void)drawRect:(NSRect)r { + [[NSColor whiteColor] set]; + NSRectFill(r); + + [self drawTree:parseTree atPoint:NSMakePoint(r.size.width / 2, 20)]; +} + + +- (void)drawTree:(PKParseTree *)n atPoint:(NSPoint)p { + if ([n isKindOfClass:[PKTokenNode class]]) { + [self drawLeafNode:(id)n atPoint:p]; + } else { + [self drawParentNode:n atPoint:p]; + } +} + + +- (void)drawParentNode:(PKParseTree *)n atPoint:(NSPoint)p { + // draw own label + [self drawLabel:[self labelFromNode:n] atPoint:NSMakePoint(p.x, p.y)]; + + NSUInteger i = 0; + NSUInteger c = [[n children] count]; + + // get total width + CGFloat widths[c]; + CGFloat totalWidth = 0; + for (PKParseTree *child in [n children]) { + widths[i] = [self widthForNode:child] * CELL_WIDTH; + totalWidth += widths[i++]; + } + + + // draw children + NSPoint points[c]; + if (1 == c) { + points[0] = NSMakePoint(p.x, p.y + ROW_HEIGHT); + [self drawTree:[[n children] objectAtIndex:0] atPoint:points[0]]; + } else { + CGFloat x = 0; + CGFloat buff = 0; + for (i = 0; i < c; i++) { + x = p.x - (totalWidth/2) + buff + widths[i]/2; + buff += widths[i]; + + points[i] = NSMakePoint(x, p.y + ROW_HEIGHT); + [self drawTree:[[n children] objectAtIndex:i] atPoint:points[i]]; + } + } + + // draw lines + CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort]; + + for (i = 0; i < c; i++) { + CGContextBeginPath(ctx); + CGContextMoveToPoint(ctx, p.x, p.y + 15); + CGContextAddLineToPoint(ctx, points[i].x, points[i].y - 4); + CGContextClosePath(ctx); + CGContextStrokePath(ctx); + } +} + + +- (void)drawLeafNode:(PKTokenNode *)n atPoint:(NSPoint)p { + [self drawLabel:[self labelFromNode:n] atPoint:NSMakePoint(p.x, p.y)]; +} + + +- (CGFloat)widthForNode:(PKParseTree *)n { + CGFloat res = 0; + for (PKParseTree *child in [n children]) { + res += [self widthForNode:child]; + } + return res ? res : 1; +} + + +- (CGFloat)depthForNode:(PKParseTree *)n { + CGFloat res = 0; + for (PKParseTree *child in [n children]) { + CGFloat n = [self depthForNode:child]; + res = n > res ? n : res; + } + return res + 1; +} + + +- (NSString *)labelFromNode:(PKParseTree *)n { + if ([n isKindOfClass:[PKTokenNode class]]) { + return [[(PKTokenNode *)n token] stringValue]; + } else if ([n isKindOfClass:[PKRuleNode class]]) { + return [(PKRuleNode *)n name]; + } else { + return @"root"; + } +} + + +- (void)drawLabel:(NSString *)label atPoint:(NSPoint)p { + NSSize labelSize = [label sizeWithAttributes:labelAttrs]; + NSRect maxRect = NSMakeRect(p.x - CELL_WIDTH / 2, p.y, CELL_WIDTH, labelSize.height); + + if (!NSContainsRect(maxRect, NSMakeRect(maxRect.origin.x, maxRect.origin.y, labelSize.width, labelSize.height))) { + labelSize = maxRect.size; + } + + p.x -= labelSize.width / 2; + NSRect r = NSMakeRect(p.x, p.y, labelSize.width, labelSize.height); + NSUInteger opts = NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin; + [label drawWithRect:r options:opts attributes:labelAttrs]; +} + +@synthesize parseTree; +@synthesize labelAttrs; +@end diff --git a/demoapp/TDGutterView.h b/demoapp/TDGutterView.h new file mode 100644 index 0000000..d3a7b16 --- /dev/null +++ b/demoapp/TDGutterView.h @@ -0,0 +1,25 @@ +// +// TDGutterView.h +// TextTest +// +// Created by Todd Ditchendorf on 9/9/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import + +@interface TDGutterView : NSView { + IBOutlet NSScrollView *sourceScrollView; + IBOutlet NSTextView *sourceTextView; + + NSArray *lineNumberRects; + NSUInteger startLineNumber; + + NSDictionary *attrs; +} +@property (retain) NSArray *lineNumberRects; +@property NSUInteger startLineNumber; + +@property (retain) NSScrollView *sourceScrollView; +@property (retain) NSTextView *sourceTextView; +@end diff --git a/demoapp/TDGutterView.m b/demoapp/TDGutterView.m new file mode 100644 index 0000000..88695f8 --- /dev/null +++ b/demoapp/TDGutterView.m @@ -0,0 +1,92 @@ +// +// TDGutterView.m +// TextTest +// +// Created by Todd Ditchendorf on 9/9/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "TDGutterView.h" + +@interface TDGutterView () +@property (retain) NSDictionary *attrs; +@end + +@implementation TDGutterView + +- (void)awakeFromNib { + self.attrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont userFixedPitchFontOfSize:11.], NSFontAttributeName, + [NSColor grayColor], NSForegroundColorAttributeName, + nil]; +} + + +- (void)dealloc { + self.sourceScrollView = nil; + self.sourceTextView = nil; + self.lineNumberRects = nil; + self.attrs = nil; + [super dealloc]; +} + + +- (BOOL)isFlipped { + return YES; +} + + +- (NSUInteger)autoresizingMask { + return NSViewHeightSizable; +} + + +- (void)drawRect:(NSRect)rect { + NSDrawWindowBackground(rect); + + CGFloat rectWidth = rect.size.width; + NSPoint p1 = NSMakePoint(rectWidth + 2., 0.); + NSPoint p2 = NSMakePoint(rectWidth + 2., rect.size.height); + [NSBezierPath strokeLineFromPoint:p1 toPoint:p2]; + + if (![lineNumberRects count]) { + return; + } + + NSUInteger i = startLineNumber; + NSUInteger count = i + [lineNumberRects count]; + + for ( ; i < count; i++) { + NSRect r = [[lineNumberRects objectAtIndex:i - startLineNumber] rectValue]; + + // set the x origin of the number according to the number of digits it contains + CGFloat x = 0.; + if (i < 9) { + x = rectWidth - 14.; + } else if (i < 99) { + x = rectWidth - 21.; + } else if (i < 999) { + x = rectWidth - 28.; + } else if (i < 9999) { + x = rectWidth - 35.; + } + r.origin.x = x; + + // center the number vertically for tall lines + if (r.origin.y) { + r.origin.y += r.size.height/2. - 7.; + } + + NSString *s = [[NSNumber numberWithInteger:i + 1] stringValue]; + NSAttributedString *as = [[NSAttributedString alloc] initWithString:s attributes:attrs]; + [as drawAtPoint:r.origin]; + [as release]; + } +} + +@synthesize sourceScrollView; +@synthesize sourceTextView; +@synthesize lineNumberRects; +@synthesize startLineNumber; +@synthesize attrs; +@end diff --git a/demoapp/TDSourceCodeTextView.h b/demoapp/TDSourceCodeTextView.h new file mode 100644 index 0000000..a746ce1 --- /dev/null +++ b/demoapp/TDSourceCodeTextView.h @@ -0,0 +1,21 @@ +// +// TDSourceCodeTextView.h +// TextTest +// +// Created by Todd Ditchendorf on 9/9/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import + +@class TDGutterView; + +@interface TDSourceCodeTextView : NSTextView { + IBOutlet TDGutterView *gutterView; + IBOutlet NSScrollView *scrollView; + CGFloat sourceTextViewOffset; +} +- (void)renderGutter; + +@property (assign) TDGutterView *gutterView; +@end diff --git a/demoapp/TDSourceCodeTextView.m b/demoapp/TDSourceCodeTextView.m new file mode 100644 index 0000000..0b511b1 --- /dev/null +++ b/demoapp/TDSourceCodeTextView.m @@ -0,0 +1,116 @@ +// +// TDSourceCodeTextView.m +// TextTest +// +// Created by Todd Ditchendorf on 9/9/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "TDSourceCodeTextView.h" +#import "TDGutterView.h" + +@interface TDSourceCodeTextView () +- (void)registerForNotifications; +- (void)getRectsOfVisibleLines:(NSArray **)outRects startingLineNumber:(NSUInteger *)outRect; +- (NSUInteger)lineNumberForIndex:(NSUInteger)inIndex; +@end + +@implementation TDSourceCodeTextView + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + self.gutterView = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { + [self registerForNotifications]; + [self renderGutter]; +} + + +- (void)textDidChange:(NSNotification *)n { + [self renderGutter]; +} + + +- (void)viewBoundsChanged:(NSNotification *)n { + [self renderGutter]; +} + + +- (void)renderGutter { + if (![[self window] isVisible]) return; + NSArray *rects = nil; + NSUInteger start = 0; + [self getRectsOfVisibleLines:&rects startingLineNumber:&start]; + gutterView.lineNumberRects = rects; + gutterView.startLineNumber = start; + [gutterView setNeedsDisplay:YES]; +} + + +- (void)registerForNotifications { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(textDidChange:) + name:NSTextDidChangeNotification + object:self]; + + [scrollView.contentView setPostsBoundsChangedNotifications:YES]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(viewBoundsChanged:) + name:NSViewBoundsDidChangeNotification + object:scrollView.contentView]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(viewBoundsChanged:) + name:NSWindowDidResizeNotification + object:self.window]; +} + + +//- (void)showFindIndicatorForRange:(NSRange)charRange; + +- (void)getRectsOfVisibleLines:(NSArray **)outRects startingLineNumber:(NSUInteger *)outStart { + NSMutableArray *result = [NSMutableArray array]; + NSString *s = self.string; + + NSLayoutManager *layoutMgr = self.textContainer.layoutManager; + NSRect boundingRect = [scrollView.contentView documentVisibleRect]; + CGFloat scrollY = boundingRect.origin.y; + NSRange visibleGlyphRange = [layoutMgr glyphRangeForBoundingRect:boundingRect inTextContainer:self.textContainer]; + + NSUInteger index = visibleGlyphRange.location; + NSUInteger length = index + [visibleGlyphRange length]; + + (*outStart) = [self lineNumberForIndex:index + 1]; + + while (index < length) { + NSRange r = [s lineRangeForRange:NSMakeRange(index, 0)]; + index = NSMaxRange(r); + NSRect rect = [layoutMgr lineFragmentRectForGlyphAtIndex:r.location effectiveRange:NULL withoutAdditionalLayout:YES]; + rect.origin.y -= scrollY; + [result addObject:[NSValue valueWithRect:rect]]; + } + + (*outRects) = result; +} + + +- (NSUInteger)lineNumberForIndex:(NSUInteger)inIndex { + NSString *s = self.string; + NSUInteger numberOfLines, index, stringLength = [s length]; + + for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++) { + NSRange r = [s lineRangeForRange:NSMakeRange(index, 0)]; + index = NSMaxRange(r); + if (inIndex <= index) { + break; + } + } + + return numberOfLines; +} + +@synthesize gutterView; +@end diff --git a/demoapp/TokensView.xib b/demoapp/TokensView.xib new file mode 100644 index 0000000..7d15c41 --- /dev/null +++ b/demoapp/TokensView.xib @@ -0,0 +1,939 @@ + + + + 1050 + 9J61 + 677 + 949.46 + 353.00 + + YES + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + DemoTokensViewController + + + FirstResponder + + + NSApplication + + + + 268 + + YES + + + 274 + + YES + + + 2304 + + YES + + + 2322 + {457, 84} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + YES + + YES + + YES + NSFont + NSParagraphStyle + + + YES + + LucidaGrande + 1.000000e+01 + 2843 + + + 3 + + YES + + 0.000000e+00 + + + 5.600000e+01 + + + 1.120000e+02 + + + 1.680000e+02 + + + 2.240000e+02 + + + 2.800000e+02 + + + 3.360000e+02 + + + 3.920000e+02 + + + 4.480000e+02 + + + 5.040000e+02 + + + 5.600000e+02 + + + 6.160000e+02 + + + 6.720000e+02 + + + 7.280000e+02 + + + 7.840000e+02 + + + 8.400000e+02 + + + 8.960000e+02 + + + 9.520000e+02 + + + 1.008000e+03 + + + 1.064000e+03 + + + 1.120000e+03 + + + 1.176000e+03 + + + 1.232000e+03 + + + 1.288000e+03 + + + 1.344000e+03 + + + 1.400000e+03 + + + 1.456000e+03 + + + 1.512000e+03 + + + 1.568000e+03 + + + 1.624000e+03 + + + 1.680000e+03 + + + 1.736000e+03 + + + + + + + YES + + YES + NSFont + NSParagraphStyle + + + YES + + LucidaGrande-Bold + 1.000000e+01 + 16 + + + 3 + + YES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GQAEAQgADAEiAAcBhAQAA + + + + + YES + + + 6 + + + + 4.570000e+02 + 1 + + + 11009 + + 3 + MQA + + + 3 + MAA + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + 6 + System + selectedTextBackgroundColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + selectedTextColor + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + 1 + MCAwIDEAA + + + + + + + 6 + {931, 1e+07} + {83, 0} + + + + {{1, 1}, {457, 236}} + + + + + + {4, -5} + 1 + + 4 + + + + 256 + {{458, 1}, {15, 236}} + + + _doScroller: + 2.835196e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{21, 170}, {474, 238}} + + + 18 + + + + + + + 266 + {{18, 529}, {480, 51}} + + YES + + 67239424 + 272629760 + VGhpcyBhcHBsaWNhdGlvbiBnaXZlcyBhIGJhc2ljIHZpc3VhbCBkZW1vbnN0cmF0aW9uIG9mIHRoZSBU +T0RUb2tlbml6ZXIgY2xhc3MgaW5jbHVkZWQgaW4gdGhlIFRPRFBhcnNlS2l0IEZyYW1ld29yay4gUGxh +Y2UgYW55IHRleHQgaW4gdGhlIHRleHQgZmllbGQgZGlyZWN0bHkgYmVsb3cuIENsaWNrIHRoZSAiUGFy +c2UiIGJ1dHRvbiB0byBzZWUgdGhlIHRleHQgdG9rZW5pemVkLg + + LucidaGrande + 1.300000e+01 + 16 + + + + 6 + System + controlColor + + + + 6 + System + controlTextColor + + + + + + + 265 + {{405, 408}, {96, 32}} + + YES + + 67239424 + 134217728 + Parse + + LucidaGrande + 1.300000e+01 + 1044 + + + -2038284033 + 268435585 + + DQ + 200 + 25 + + + + + 290 + + YES + + YES + NSStringPboardType + + + {{21, 20}, {474, 142}} + + YES + + 341966336 + 0 + + LucidaGrande-Bold + 1.200000e+01 + 16 + + + YES + + 6 + System + textBackgroundColor + + + + + 0.000000e+00 + 0 + + 2 + + + + 266 + + YES + + + 2304 + + YES + + + 2322 + {457, 84} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + YES + + + + + GQAEAQgADAEiAAcBhAQAA + + + + + YES + + + 6 + + + + 4.570000e+02 + 1 + + + 11009 + + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + + + + + + 6 + {931, 1e+07} + {83, 0} + + + + {{1, 1}, {457, 75}} + + + + + + 4 + + + + 256 + {{458, 1}, {15, 75}} + + YES + + _doScroller: + 8.928571e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{21, 444}, {474, 77}} + + + 82 + + + + + + + 1289 + + {{387, 416}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + {515, 593} + + NSView + + + + + YES + + + animate: busy + + + + + + animate: busy + animate + busy + 2 + + + 17 + + + + tokenField + + + + 18 + + + + view + + + + 19 + + + + parse: + + + + 20 + + + + value: inString + + + + + + value: inString + value + inString + + NSContinuouslyUpdatesValue + + + 2 + + + 22 + + + + value: outString + + + + + + value: outString + value + outString + + NSContinuouslyUpdatesValue + + + 2 + + + 24 + + + + value: tokString + + + + + + value: tokString + value + tokString + + NSContinuouslyUpdatesValue + + + 2 + + + 28 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + YES + + + + + + + + + + + 2 + + + YES + + + + + + + + 3 + + + YES + + + + + + 4 + + + YES + + + + + + 5 + + + YES + + + + + + 6 + + + YES + + + + + + + + 7 + + + + + 8 + + + + + 9 + + + + + 10 + + + + + 11 + + + + + 12 + + + + + 13 + + + + + 14 + + + + + 15 + + + + + 16 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 1.IBEditorWindowLastContentRect + 1.IBPluginDependency + 1.WindowOrigin + 1.editorWindowContentRectSynchronizationRect + 10.IBPluginDependency + 11.IBPluginDependency + 12.IBPluginDependency + 13.IBPluginDependency + 14.IBPluginDependency + 15.IBPluginDependency + 16.IBPluginDependency + 2.IBPluginDependency + 3.IBPluginDependency + 4.IBPluginDependency + 5.IBPluginDependency + 6.IBPluginDependency + 7.IBPluginDependency + 8.IBPluginDependency + 9.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + {{227, 263}, {515, 593}} + com.apple.InterfaceBuilder.CocoaPlugin + {628, 654} + {{217, 442}, {480, 272}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 28 + + + + YES + + DemoTokensViewController + NSViewController + + parse: + id + + + tokenField + NSTokenField + + + IBProjectSource + demoapp/DemoTokensViewController.h + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + + 0 + ../ParseKit.xcodeproj + 3 + + diff --git a/demoapp/TreesView.xib b/demoapp/TreesView.xib new file mode 100644 index 0000000..1088d32 --- /dev/null +++ b/demoapp/TreesView.xib @@ -0,0 +1,1391 @@ + + + + 1050 + 9J61 + 677 + 949.46 + 353.00 + + YES + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + DemoTreesViewController + + + FirstResponder + + + NSApplication + + + + 268 + + YES + + + 274 + + YES + + + 274 + + YES + + + 1313 + + {{386, 5}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + + 289 + {{404, -5}, {96, 32}} + + YES + + 67239424 + 134217728 + Parse + + LucidaGrande + 1.300000e+01 + 1044 + + + -2038284033 + 268435585 + + DQ + 200 + 25 + + + + + 274 + + YES + + + 278 + + YES + + + 268 + {{37, 223}, {67, 17}} + + YES + + 68288064 + 272630784 + Grammar: + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 276 + {{20, 2}, {40, 214}} + + TDGutterView + + + + 274 + + YES + + + 2304 + + YES + + + 2322 + + YES + + YES + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple PNG pasteboard type + Apple URL pasteboard type + CorePasteboardFlavorType 0x6D6F6F76 + CorePasteboardFlavorType 0x75726C20 + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT Encapsulated PostScript v1.2 pasteboard type + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + NeXT font pasteboard type + NeXT ruler pasteboard type + WebURLsWithTitlesPboardType + + + {189, 432} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + YES + + YES + NSColor + NSFont + NSParagraphStyle + + + YES + + 3 + MQA + + + Monaco + 1.200000e+01 + 16 + + + 3 + + YES + + 0.000000e+00 + + + 5.600000e+01 + + + 1.120000e+02 + + + 1.680000e+02 + + + 2.240000e+02 + + + 2.800000e+02 + + + 3.360000e+02 + + + 3.920000e+02 + + + 4.480000e+02 + + + 5.040000e+02 + + + 5.600000e+02 + + + 6.160000e+02 + + + 6.720000e+02 + + + 7.280000e+02 + + + 7.840000e+02 + + + 8.400000e+02 + + + 8.960000e+02 + + + 9.520000e+02 + + + 1.008000e+03 + + + 1.064000e+03 + + + 1.120000e+03 + + + 1.176000e+03 + + + 1.232000e+03 + + + 1.288000e+03 + + + 1.344000e+03 + + + 1.400000e+03 + + + 1.456000e+03 + + + 1.512000e+03 + + + 1.568000e+03 + + + 1.624000e+03 + + + 1.680000e+03 + + + 1.736000e+03 + + + + + + + + + YES + + + 6 + + + + 1.890000e+02 + 1 + + + 12131 + + 2 + MC4xMTc2NDcwNyAwLjEyNTQ5MDIgMC4xNTY4NjI3NQA + + + 3 + MQA + + 2 + + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + 6 + System + selectedTextBackgroundColor + + + + 6 + System + selectedTextColor + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + 1 + MCAwIDEAA + + + + + + + 6 + {931, 1e+07} + {100, 0} + + + + {190, 214} + + + + + + {4, -5} + 1 + + 4 + + + + 256 + {{190, 0}, {15, 214}} + + YES + + _doScroller: + 4.953704e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{60, 2}, {205, 214}} + + + 80 + + + + + + + 14 + {{20, 214}, {245, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + 6 + System + textBackgroundColor + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + + 38 + {{20, -1}, {245, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + {268, 260} + + NSView + + + + 275 + + YES + + + 268 + {{17, 224}, {67, 17}} + + YES + + 68288064 + 272630784 + Input: + + + + + + + + + 276 + {{0, 2}, {40, 214}} + + TDGutterView + + + + 274 + + YES + + + 2304 + + YES + + + 2322 + + YES + + YES + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple PNG pasteboard type + Apple URL pasteboard type + CorePasteboardFlavorType 0x6D6F6F76 + CorePasteboardFlavorType 0x75726C20 + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT Encapsulated PostScript v1.2 pasteboard type + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + NeXT font pasteboard type + NeXT ruler pasteboard type + WebURLsWithTitlesPboardType + + + {201, 400} + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda + + + + + + YES + + + 6 + + + + 2.010000e+02 + 1 + + + 12131 + + 2 + MC4xMTc2NDcwNyAwLjEyNTQ5MDIgMC4xNTY4NjI3NQA + + + 3 + MQA + + + + YES + + YES + NSBackgroundColor + NSColor + + + YES + + + + + + + YES + + YES + NSColor + NSUnderline + + + YES + + + + + + + 6 + {931, 1e+07} + {105, 0} + + + + {202, 214} + + + + + + 4 + + + + 256 + {{202, 0}, {15, 214}} + + YES + + _doScroller: + 5.350000e-01 + + + + 256 + {{-100, -100}, {87, 18}} + + 1 + + _doScroller: + 1.000000e+00 + 9.456522e-01 + + + {{40, 2}, {217, 214}} + + + 80 + + + + + + + 11 + {{0, 214}, {257, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + + 35 + {{0, -1}, {265, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + {{277, 0}, {257, 260}} + + NSView + + + {{-20, 34}, {534, 260}} + + YES + + + {514, 274} + + NSView + + + + 256 + + YES + + + 274 + + YES + + + 2304 + + YES + + + 274 + {496, 291} + + PKParseTreeView + + + {{1, 1}, {496, 291}} + + + + + 4 + + + + 256 + {{497, 1}, {15, 288}} + + + _doScroller: + 1.000000e+00 + 9.956332e-01 + + + + 256 + {{1, 292}, {496, 15}} + + 1 + + _doScroller: + 9.978166e-01 + + + {{0, -1}, {513, 308}} + + + 50 + + + + + + {{0, 283}, {514, 307}} + + NSView + + + {514, 590} + + + + {514, 590} + + NSView + + + + + YES + + + nextKeyView + + + + 114 + + + + nextKeyView + + + + 116 + + + + nextKeyView + + + + 119 + + + + delegate + + + + 122 + + + + scrollView + + + + 123 + + + + gutterView + + + + 124 + + + + scrollView + + + + 126 + + + + gutterView + + + + 127 + + + + view + + + + 129 + + + + parseTreeView + + + + 130 + + + + parse: + + + + 131 + + + + grammarTextView + + + + 132 + + + + inputTextView + + + + 133 + + + + value: inString + + + + + + value: inString + value + inString + + NSContinuouslyUpdatesValue + + + 2 + + + 136 + + + + value: grammarString + + + + + + value: grammarString + value + grammarString + + NSContinuouslyUpdatesValue + + + 2 + + + 137 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + YES + + + + + + 60 + + + YES + + + + + + + 62 + + + YES + + + + + + 8 + + + YES + + + + + + bottomContainerView + + + 9 + + + YES + + + + + 10 + + + + + 11 + + + + + 92 + + + YES + + + + + + topContainerView + + + 102 + + + + + 104 + + + YES + + + + + + 105 + + + + + 141 + + + YES + + + + + + + 138 + + + YES + + + + + + + + leftContainerView + + + 100 + + + YES + + + + + + grammarScrollView + + + 98 + + + + + 99 + + + YES + + + + + + 96 + + + + + 113 + + + + + 110 + + + + + 111 + + + + + 112 + + + grammarTextView + + + 139 + + + YES + + + + + + + + rightContainerView + + + 95 + + + + + 94 + + + + + 103 + + + YES + + + + + + 93 + + + + + 101 + + + YES + + + + + + inputScrollView + + + 107 + + + inputTextView + + + 108 + + + + + 109 + + + + + 106 + + + + + 97 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 1.IBEditorWindowLastContentRect + 1.IBPluginDependency + 1.WindowOrigin + 1.editorWindowContentRectSynchronizationRect + 10.IBPluginDependency + 100.IBPluginDependency + 101.IBPluginDependency + 102.IBPluginDependency + 103.IBPluginDependency + 104.IBPluginDependency + 105.IBPluginDependency + 106.IBPluginDependency + 107.CustomClassName + 107.IBPluginDependency + 108.IBPluginDependency + 109.IBPluginDependency + 11.IBPluginDependency + 110.IBPluginDependency + 111.IBPluginDependency + 112.CustomClassName + 112.IBPluginDependency + 113.IBPluginDependency + 60.IBPluginDependency + 62.IBPluginDependency + 8.IBPluginDependency + 9.IBPluginDependency + 93.IBPluginDependency + 94.IBPluginDependency + 95.IBPluginDependency + 96.IBPluginDependency + 97.IBPluginDependency + 98.IBPluginDependency + 99.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + {{32, 260}, {514, 590}} + com.apple.InterfaceBuilder.CocoaPlugin + {628, 654} + {{217, 442}, {480, 272}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + TDSourceCodeTextView + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + TDSourceCodeTextView + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 142 + + + + YES + + DemoTreesViewController + NSViewController + + parse: + id + + + YES + + YES + grammarTextView + inputTextView + parseTreeView + + + YES + TDSourceCodeTextView + TDSourceCodeTextView + PKParseTreeView + + + + IBProjectSource + demoapp/DemoTreesViewController.h + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + PKParseTreeView + NSView + + IBProjectSource + demoapp/PKParseTreeView.h + + + + TDGutterView + NSView + + YES + + YES + sourceScrollView + sourceTextView + + + YES + NSScrollView + NSTextView + + + + IBProjectSource + demoapp/TDGutterView.h + + + + TDSourceCodeTextView + NSTextView + + YES + + YES + gutterView + scrollView + + + YES + TDGutterView + NSScrollView + + + + IBProjectSource + demoapp/TDSourceCodeTextView.h + + + + + 0 + ../ParseKit.xcodeproj + 3 + + diff --git a/demoapp/main.m b/demoapp/main.m new file mode 100644 index 0000000..5fdddb1 --- /dev/null +++ b/demoapp/main.m @@ -0,0 +1,13 @@ +// +// main.m +// DemoApp +// +// Created by Todd Ditchendorf on 7/12/08. +// Copyright Todd Ditchendorf 2008. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) { + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/docs/.svn/all-wcprops b/docs/.svn/all-wcprops new file mode 100644 index 0000000..3c0e1db --- /dev/null +++ b/docs/.svn/all-wcprops @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 29 +/svn/!svn/ver/1396/trunk/docs +END +Doxyfile +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/1242/trunk/docs/Doxyfile +END +ParseKit.key +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1389/trunk/docs/ParseKit.key +END diff --git a/docs/.svn/dir-prop-base b/docs/.svn/dir-prop-base new file mode 100644 index 0000000..8387a00 --- /dev/null +++ b/docs/.svn/dir-prop-base @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 8 +doxygen + +END diff --git a/docs/.svn/entries b/docs/.svn/entries new file mode 100644 index 0000000..c2c40ac --- /dev/null +++ b/docs/.svn/entries @@ -0,0 +1,106 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/docs +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-09-18T01:37:04.877278Z +1396 +todd.ditchendorf +has-props + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + + + + + + +0 + +Doxyfile +file + + + + +2009-07-19T19:57:58.000000Z +f653467bf611906c2458a7d4096d1442 +2009-07-19T19:43:23.316366Z +1242 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +10715 + +ParseKit.key +file + + + + +2009-09-18T00:47:09.000000Z +9507a262a0d49d6a9e52e51a2445aec3 +2009-09-18T00:47:16.771792Z +1389 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +557092 + +web +dir + diff --git a/docs/.svn/prop-base/ParseKit.key.svn-base b/docs/.svn/prop-base/ParseKit.key.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/.svn/prop-base/ParseKit.key.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/.svn/text-base/Doxyfile.svn-base b/docs/.svn/text-base/Doxyfile.svn-base new file mode 100644 index 0000000..1f3b885 --- /dev/null +++ b/docs/.svn/text-base/Doxyfile.svn-base @@ -0,0 +1,291 @@ +# Doxyfile 1.5.7 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = ParseKit +PROJECT_NUMBER = 1.4 +OUTPUT_DIRECTORY = /Users/itod/work/tpk/trunk/docs/doxygen +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = /Applications/ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = NO +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = /Users/itod/work/tpk/trunk/src +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.vhd \ + *.vhdl +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHG_LOCATION = +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = ALL +TREEVIEW_WIDTH = 250 +FORMULA_FONTSIZE = 10 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = YES +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +MSCGEN_PATH = /Applications/Doxygen.app/Contents/Resources/ +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +DOT_FONTNAME = FreeSans +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = /Applications/Doxygen.app/Contents/Resources/ +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/docs/.svn/text-base/ParseKit.key.svn-base b/docs/.svn/text-base/ParseKit.key.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..1211fb260cea8086f1a6682cdac459a02dd33dc4 GIT binary patch literal 557092 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

+ +
diff --git a/docs/web/.svn/text-base/grammars.html.svn-base b/docs/web/.svn/text-base/grammars.html.svn-base new file mode 100644 index 0000000..27fc36b --- /dev/null +++ b/docs/web/.svn/text-base/grammars.html.svn-base @@ -0,0 +1,167 @@ + + ParseKit Objective-C Parser Generation via Grammars + + +

ParseKit Documentation

+
+ +

Objective-C Parser Generation via Grammars

+ + + + +

Basic Grammar Syntax

+ +

ParseKit allows users to build parsers for custom languages from a declarative, BNF-style grammar without writing any code (well, ok.. a single line of code). Under the hood, grammar support is implemented using the ParseKit Objective-C API, so the grammar syntax closely mirrors the features of the Objective-C API.

+ +

The grammar below describes a simple toy language called Cold Beer and will serve as a quick introduction to the ParseKit grammar syntax. The rules of the Cold Beer language are as follows. The language consists of a sequence of one or more sentences beginning with the word «cold» followed by a repetition of either «cold» or «freezing» followed by «beer» and terminated by the symbol «.».

+ +

For example, each of the following lines are valid instances of the Cold Beer language (as is the example as a whole):

+ +
+
+    cold cold cold freezing cold freezing cold beer.
+    cold cold freezing cold beer.
+    cold freezing beer.
+    cold beer.
+
+ +

The following lines are not valid Cold Beer statements:

+ +
+
+    freezing cold beer.
+    cold freezing beer
+    beer.
+
+ +

Here is a complete ParseKit grammar for the Cold Beer language.

+ +
+
+    @start = sentence+;
+    sentence = adjectives 'beer' '.';
+    adjectives = cold adjective*;
+    adjective = cold | freezing;
+    cold = 'cold';
+    freezing = 'freezing';
+
+ +

As shown above, the ParseKit grammar syntax consists of individual language production declarations separated by «;». Whitespace is ignored, so the productions can be formatted liberally with whitespace as the programmer prefers. Comments are also allowed and resemble the comment style of Objective-C. So a commented Cold Beer grammar may appear as:

+ +
+
+    /*
+        A Grammar for the Cold Beer Language
+        by Todd Ditchendorf
+    */
+    @start = sentence+;     // outermost production
+    sentence = adjectives 'beer' '.';
+    adjectives = cold adjective*;
+    adjective = cold | 'freezing';
+    cold = 'cold';
+    freezing = 'freezing';
+
+ + +

Individual Grammar Production Syntax

+ +

Every ParseKit grammar must contain one and only one production named @start. This will be the highest-level or outermost production rule in the language. For Cold Beer, the outermost production is:

+ +
+
+    @start = sentence+;
+
+ +

Which states that the outermost production of this language consists of a sequence of one or more («+») instances of the sentence production.

+ +
+
+    sentence = adjectives 'beer' '.';
+
+ +

The sentence production states that sentences are a sequence of the adjective production followed by the literal strings beer and .

+ +
+
+    adjectives = cold adjective*;
+
+ +

In turn, adjectives is a sequence of a single instance of the cold production followed by a repetition («*» read as 'zero or more') of the adjective production.

+ +
+
+    adjective = cold | freezing;
+    cold = 'cold';
+    freezing = 'freezing';
+
+ +

The adjective production is an alternation of either an instance of the cold or the freezing production. The cold production is the literal string cold and freezing the literal string freezing.

+ + +

Grouping

+ +

A language may be expressed in many different, yet equivalent grammars. Productions may be referenced in any order (even before they are defined) and grouped using parentheses («(» and «)»).

+ +

For example, the Cold Beer language could also be represented by the following grammar:

+ +
+
+    @start = ('cold' ('cold' | 'freezing')* 'beer' '.')+;
+
+ + +

Instantiating Grammar Parsers in Objective-C

+ +

Create an Objective-C PKParser object by providing the grammar as an NSString and an assembler object (in this example, self).

+ +
+
+  NSString *g = ... // fetch your grammar from a file on disk
+  
+  PKParser *parser = nil;
+  parser = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
+  
+  NSString *s = @"cold freezing cold beer.";
+  [parser parse:s];
+
+ +

The provided assembler object will receive callbacks whenever one of the language grammar productions is matched -- if the callback method is implemented in the assembler object.

+ +

For example, an assembler for the Cold Beer language grammar above will receive the following callbacks if implemented:

+ +
+
+    - (void)didMatchSentence:(PKAssembly *)a;
+    - (void)didMatchAdjectives:(PKAssembly *)a;
+    - (void)didMatchAdjective:(PKAssembly *)a;
+    - (void)didMatchCold:(PKAssembly *)a;
+    - (void)didMatchFreezing:(PKAssembly *)a;
+
+ +

The PKAssembly argument will have the most-recently matched tokens on the top of its stack.

+ +

To prevent leaks when releasing a PKParser created via PKParserFactory, one final step is required:

+ +
+
+          PKParser *parser = nil;
+          parser = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
+
+          ... // do parsing
+          
+          // when you are done with the parser, this function must be called before releasing
+          PKReleaseSubparserTree(parser);
+          [p release]
+
+ +

Most non-trivial language grammars define circular relationships in their production rules. The call to PKReleaseSubparserTree() is required to prevent Objective-C retain cycle leaks where the PKParser objects representing different rules in your grammar have strong references to one another.

+ +
+ + diff --git a/docs/web/.svn/text-base/htaccess.svn-base b/docs/web/.svn/text-base/htaccess.svn-base new file mode 100644 index 0000000..5eafa7f --- /dev/null +++ b/docs/web/.svn/text-base/htaccess.svn-base @@ -0,0 +1,5 @@ +# let's enable php (non-cgi, aka. 'module') for EVERYTHING..' +# AddType application/x-httpd-php5 .htm .html .php + +# better yet.. +AddHandler php5-script .php .html .htm .inc \ No newline at end of file diff --git a/docs/web/.svn/text-base/index.html.svn-base b/docs/web/.svn/text-base/index.html.svn-base new file mode 100644 index 0000000..0fb4e46 --- /dev/null +++ b/docs/web/.svn/text-base/index.html.svn-base @@ -0,0 +1,257 @@ + + ParseKit - Cocoa Objective-C Framework for parsing, tokenizing and language processing + + +

ParseKit Documentation

+
+

ParseKit

+ +

ParseKit is a Mac OS X Framework written by Todd Ditchendorf in Objective-C 2.0 and released under the MIT Open Source License. ParseKit is suitable for use on Mac OS X Leopard, Snow Leopard or iPhone OS. ParseKit is an Objective-C implementation of the tools described in "Building Parsers with Java" by Steven John Metsker. ParseKit includes additional features beyond the designs from the book and also some changes to match common Cocoa/Objective-C conventions. These changes are relatively superficial, however, and Metsker's book is the best documentation available for ParseKit.

+ +

The ParseKit Framework offers 3 basic services of general interest to Cocoa developers:

+ +
    +
  1. String Tokenization via the Objective-C PKTokenizer and PKToken classes.
  2. +
  3. High-Level Language Parsing via Objective-C - An Objective-C parser-building API (the PKParser class and sublcasses).
  4. +
  5. Objective-C Parser Generation via Grammars - Generate an Objective-C parser for your custom language using a BNF-style grammar syntax (similar to yacc or ANTLR). While parsing, the parser will provide callbacks to your Objective-C code.
  6. +
+ +

The ParseKit source code is available from the Subversion repository at the Google Code project page. The latest tagged (stable) version is recommended.

svn co http://todparsekit.googlecode.com/svn/tags/release-1.5-tag

+ +

More documentation:

+ + +

Projects using ParseKit:

+
    +
  • Spike: A Rails log file viewer/analyzer by Matt Mower
  • +
  • JSTalk: Interprocess Cocoa scripting with JavaScript by Gus Mueller
  • +
  • Objective-J Port of ParseKit by Ross Boucher
  • +
  • HTTP Client: HTTP debugging/testing tool
  • +
  • Fluid: Site-Specific Browser for Mac OS X
  • +
  • Cruz: Social Browser for Mac OS X
  • +
  • OkudaKit: Syntax Highlighting Framework for Mac OS X
  • +
  • Exedore: XPath 1.0 implemented in Cocoa (ported from Saxon)
  • +
+ +

Xcode Project

+

The ParseKit Xcode project consists of 6 targets:

+ +
    +
  1. ParseKit : the ParseKit Objective-C framework. The central feature/codebase of this project.
  2. +
  3. Tests : a UnitTest Bundle containing hundreds of unit tests (actually, more correctly, interaction tests) for the framework as well as some example classes that serve as real-world uses of the framework.
  4. +
  5. DemoApp : A simple Cocoa demo app that gives a visual presentation of the results of tokenizing text using the PKTokenizer class.
  6. +
  7. DebugApp : A simple Cocoa app that exists only to run arbitrary test code thru GDB with breakpoints for debugging (I was not able to do that with the UnitTest bundle).
  8. +
  9. JSParseKit : A JavaScriptCore-based scripting interface to ParseKit which can be used to expose the entire framework to JavaScript environments.
  10. +
  11. JSDemoApp: A simple Cocoa application used for exercising the JavaScript interface provided by JSParseKit. Note that this is the only target which links to the WebKit framework. Neither ParseKit nor JSParseKit requires WebKit.
  12. +
+ + + +

ParseKit Framework

+ +
+

Tokenization

+ +

The API for tokenization is provided by the PKTokenizer class. Cocoa developers will be familiar with the NSScanner class provided by the Foundation Framework which provides a similar service. However, the PKTokenizer class is simpler and more powerful for many use cases.

+ +

Example usage:

+ +
+
+NSString *s = @"\"It's 123 blast-off!\", she said, // watch out!\n"
+              @"and <= 3.5 'ticks' later /* wince */, it's blast-off!";
+PKTokenizer *t = [PKTokenizer tokenizerWithString:s];
+
+PKToken *eof = [PKToken EOFToken];
+PKToken *tok = nil;
+
+while ((tok = [t nextToken]) != eof) {
+    NSLog(@" (%@)", tok);
+}
+
+
+ +

outputs:

+
+
 ("It's 123 blast-off!")
+ (,)
+ (she)
+ (said)
+ (,)
+ (and)
+ (<=)
+ (3.5)
+ ('ticks')
+ (later)
+ (,)
+ (it's)
+ (blast-off)
+ (!)
+
+
+ +

Each token produced is an object of class PKToken. PKTokens have a tokenType (Word, Symbol, Num, QuotedString, etc.) and both a stringValue and a floatValue.

+ +

More information about a token can be easily discovered using the -debugDescription method instead of the default -description. Replace the line containing NSLog above with this line:

+ +
+
+NSLog(@" (%@)", [tok debugDescription]);
+
+
+ +

and each token's type will be printed as well:

+ +
+
 <Quoted String «"It's 123 blast-off!"»>
+ <Symbol «,»>
+ <Word «she»>
+ <Word «said»>
+ <Symbol «,»>
+ <Word «and»>
+ <Symbol «<=»>
+ <Number «3.5»>
+ <Quoted String «'ticks'»>
+ <Word «later»>
+ <Symbol «,»>
+ <Word «it's»>
+ <Word «blast-off»>
+ <Symbol «!»>
+
+
+ + +

As you can see from the output, PKTokenzier is configured by default to properly group characters into tokens including:

+ +
    +
  • single- and double-quoted string tokens
  • +
  • common multiple character symbols (<=)
  • +
  • apostrophes, dashes and other symbol chars that should not signal the start of a new Symbol token, but rather be included in the current Word or Num token (it's, blast-off, 3.5)
  • +
  • silently ignoring C- and C++-style comments
  • +
  • silently ignoring whitespace
  • +
+ + +

The PKTokenizer class is very flexible, and all of those features are configurable. PKTokenizer may be configured to:

+ +
    +
  • recognize more (or fewer) multi-char symbols. ex:
    [t.symbolState add:@"!="];
    +

    allows != to be recognized as a single Symbol token rather than two adjacent Symbol tokens

    +
  • + +
  • add new internal symbol chars to be included in the current Word token OR recognize internal symbols like apostrophe and dash to actually signal a new Symbol token rather than being part of the current Word token. ex: +
    [t.wordState setWordChars:YES from:'_' to:'_'];
    +

    allows Word tokens to contain internal underscores

    +
    [t.wordState setWordChars:NO from:'-' to:'-'];
    +

    disallows Word tokens from containing internal dashes.

    +
  • + + +
  • change which chars singnal the start of a token of any given type. ex: +
    [t setTokenizerState:t.wordState from:'_' to:'_'];
    +

    allows Word tokens to start with underscore

    +
    [t setTokenizerState:t.quoteState from:'*' to:'*'];
    +

    allows Quoted String tokens to start with an asterisk, effectively making * a new quote symbol (like " or ')

    +
  • + +
  • turn off recognition of single-line "slash-slash" (//) comments. ex: +
    [t setTokenizerState:t.symbolState from:'/' to:'/'];
    +

    slash chars now produce individual Symbol tokens rather than causing the tokenizer to strip text until the next newline char or begin striping for a multiline comment if appropriate (/*)

    +
  • + +
  • turn on recognition of "hash" (#) single-line comments. ex: +
    +
    [t setTokenizerState:t.commentState from:'#' to:'#'];
    +[t.commentState addSingleLineStartSymbol:@"#"];
    +
    +
  • + +
  • turn on recognition of "XML/HTML" (<!-- -->) multi-line comments. ex: +
    +
    [t setTokenizerState:t.commentState from:'<' to:'<'];
    +[t.commentState addMultiLineStartSymbol:@"<!--" endSymbol:@"-->"];
    +
    +
  • + +
  • report (rather than silently consume) Comment tokens. ex: +
    +
    t.commentState.reportsCommentTokens = YES; // default is NO
    +
    +
  • + +
  • report (rather than silently consume) Whitespace tokens. ex: +
    +
    t.whitespaceState.reportsWhitespaceTokens = YES; // default is NO
    +
    +
  • + +
  • turn on recognition of any characters (say, digits) as whitespace to be silently ignored. ex: +
    +
    [t setTokenizerState:t.whitespaceState from:'0' to:'9'];
    +
    +
  • + +
+ +
+

Parsing

+ +

ParseKit also includes a collection of token parser subclasses (of the abstract PKParser class) including collection parsers such as PKAlternation, PKSequence, and PKRepetition as well as terminal parsers including PKWord, PKNum, PKSymbol, PKQuotedString, etc. Also included are parser subclasses which work in individual chars such as PKChar, PKDigit, and PKSpecificChar. These char parsers are useful for things like RegEx parsing. Generally speaking though, the token parsers will be more useful and interesting.

+ +

The parser classes represent a Composite pattern. Programs can build a composite parser, in Objective-C (rather than a separate language like with lex&yacc), from a collection of terminal parsers composed into alternations, sequences, and repetitions to represent an infinite number of languages.

+ +

Parsers built from ParseKit are non-deterministic, recursive descent parsers, which basically means they trade some performance for ease of user programming and simplicity of implementation.

+ +

Here is an example of how one might build a parser for a simple voice-search command language (note: ParseKit does not include any kind of speech recognition technology). The language consists of:

+ +
+
search google for? <search-term>
+
+ +
+
+...
+
+	[self parseString:@"search google 'iphone'"];
+...
+	
+- (void)parseString:(NSString *)s {
+	PKSequence *parser = [PKSequence sequence];
+
+	[parser add:[[PKLiteral literalWithString:@"search"] discard]];
+	[parser add:[[PKLiteral literalWithString:@"google"] discard]];
+
+	PKAlternation *optionalFor = [PKAlternation alternation];
+	[optionalFor add:[PKEmpty empty]];
+	[optionalFor add:[PKLiteral literalWithString:@"for"]];
+
+	[parser add:[optionalFor discard]];
+
+	PKParser *searchTerm = [PKQuotedString quotedString];
+	[searchTerm setAssembler:self selector:@selector(workOnSearchTermAssembly:)];
+	[parser add:searchTerm];
+
+	PKAssembly *result = [parser bestMatchFor:[PKTokenAssembly assmeblyWithString:s]];
+	
+	NSLog(@" %@", result);
+
+	// output:
+	//  ['iphone']search/google/'iphone'^
+}
+
+...
+
+- (void)workOnSearchTermAssembly:(PKAssembly *)a {
+	PKToken *t = [a pop]; // a QuotedString token with a stringValue of 'iphone'
+	[self doGoogleSearchForTerm:t.stringValue];
+}
+
+
+
+ +
+ + diff --git a/docs/web/.svn/text-base/iphone.html.svn-base b/docs/web/.svn/text-base/iphone.html.svn-base new file mode 100644 index 0000000..3432a97 --- /dev/null +++ b/docs/web/.svn/text-base/iphone.html.svn-base @@ -0,0 +1,59 @@ + + ParseKit - Cocoa parsing, tokenizing and language processing on iPhone + + +

ParseKit Documentation

+
+ +

ParseKit for iPhone OS Applications

+ +

Including ParseKit in your iPhone OS applications is easy. Follow the steps below.

+ +
    +
  1. +
    Check out the ParseKit sourcecode from Google Code. The latest tagged (stable) version is recommended.
    +

    svn co http://todparsekit.googlecode.com/svn/tags/release-1.5-tag

    +
  2. +
  3. +
    Open your iPhone app Xcode project. Drag the ParseKit.xcodeproj file from the finder and drop it at the top of the Groups & Files tree in your app's Xcode project window. In the confirmation dialog that appears, click Add.
    +

    +

    +
  4. + +
  5. +
    Click and expand the disclosure triangle next to the blue ParseKit.xcodeproj icon to reveal all of the potential products of the ParseKit project.
    +

    +
  6. +
  7. +
    Click and expand the disclosure triangle next to your app's Target. Drag the parsekit.a product under ParseKit.xcodeproj to your Target's Link Binary With Libraries build phase.
    +

    +
  8. +
  9. +
    Double-click your Target (MyApp shown here) to edit it. In the General tab of the Target Info window, click the square + button below the Direct Dependencies list. In the sheet that appears, select ParseKitMobile and click Add Target.
    +

    +
    You will now see the ParseKitMobile target appearing as a dependency under your app's Target.
    +

    +
  10. +
  11. +

    Next click the + button below the Linked Libraries list in the same window. Select libicucore.dylib and click Add. (This is for regular expression features in the PKPattern class.)

    +

    +
  12. +
  13. +
    Under the Build tab of your app's Target Info window, edit the Header Search Paths Setting to include the path to the include folder inside of the ParseKit folder you checked out. Make sure you edit this for All Configurations, not just the active one.
    +

    +
  14. + +
  15. +
    Finally, in the same window, edit the Other Linker Flags Setting to include the following flags: -ObjC -all_load. (This is needed for code in Objective-C categories in the ParseKit static library to execute successfully.)
    +

    +
  16. + +
  17. Ship it!
  18. + +
+ +
+ + + + diff --git a/docs/web/.svn/text-base/tokenization.html.svn-base b/docs/web/.svn/text-base/tokenization.html.svn-base new file mode 100644 index 0000000..f7f3dcd --- /dev/null +++ b/docs/web/.svn/text-base/tokenization.html.svn-base @@ -0,0 +1,366 @@ + + ParseKit - String Tokenization in Objective-C, Cocoa + + + +

ParseKit Documentation

+
+ +

Tokenization

+ + + + +

Basic Usage of PKTokenizer

+ +

ParseKit provides general-purpose string tokenization services through the PKTokenizer and PKToken classes. Cocoa developers will be familiar with the NSScanner class provided by the Foundation Framework which provides a similar service. However, the PKTokenizer class is much easier to use for many common tokenization tasks, and offers powerful configuration options if the default tokenization behavior doesn't match your needs.

+ + + + + + + + +
PKTokenizer
+

+ + (id)tokenizerWithString:(NSString *)s;
+

+

+ - (PKToken *)nextToken;
+ ...
+

+
+ +

To use PKTokenizer, create an instance with an NSString object and retrieve a series of PKToken objects as you repeatedly call the -nextToken method. The EOFToken singleton signals the end.

+ +
+
+NSString *s = @"2 != -47. /* comment */ Blast-off!! 'Woo-hoo!' // comment";
+PKTokenizer *t = [PKTokenizer tokenizerWithString:s];
+
+PKToken *eof = [PKToken EOFToken];
+PKToken *tok = nil;
+
+while ((tok = [t nextToken]) != eof) {
+    NSLog(@"(%@) (%.1f) : %@", 
+        tok.stringValue, tok.floatValue, [tok debugDescription]);
+}
+
+
+ +

Outputs:

+ +
+
+(2) (2.0) : <Number «2»>
+(!=) (0.0) : <Symbol «!=»>
+(-47) (-47.0) : <Number «-47»>
+(.) (0.0) : <Symbol «.»>
+(Blast-off) (0.0) : <Word «Blast-off»>
+(!) (0.0) : <Symbol «!»>
+(!) (0.0) : <Symbol «!»>
+('Woo-hoo!') (0.0) : <Quoted String «'Woo-hoo!'»>
+
+
+ +

Each PKToken object returned has a stringValue, a floatValue and a tokenType. The tokenType is and enum value type called PKTokenType with possible values of:

+ +
    +
  • PKTokenTypeWord
  • +
  • PKTokenTypeNumber
  • +
  • PKTokenTypeQuotedString
  • +
  • PKTokenTypeSymbol
  • +
  • PKTokenTypeWhitespace
  • +
  • PKTokenTypeComment
  • +
  • PKTokenTypeDelimitedString
  • +
+ +

PKTokens also have corresponding BOOL properties for convenience (isWord, isNumber, etc.)

+ + + + + + + + +
PKToken
+

+ + (PKToken *)EOFToken;
+

+

+ @property (readonly) PKTokenType tokenType;
+

+

+ @property (readonly) CGFloat floatValue;
+ @property (readonly, copy) NSString *stringValue;
+

+

+ @property (readonly) BOOL isNumber;
+ @property (readonly) BOOL isSymbol;
+ @property (readonly) BOOL isWord;
+ @property (readonly) BOOL isQuotedString;
+ @property (readonly) BOOL isWhitespace;
+ @property (readonly) BOOL isComment;
+ @property (readonly) BOOL isDelimitedString;
+

+

+ ...
+

+
+ + +

Default Behavior of PKTokenizer

+ +

The default behavior of PKTokenizer is correct for most common situations and will fit many tokenization needs without additional configuration.

+ +

Number

+ +

Sequences of digits («2» «42» «1054») are recognized as Number tokens. Floating point numbers containing a dot («3.14») are recognized as single Number tokens as you'd expect (rather than two Number tokens separated by a «.» Symbol token). By default, PKTokenizer will recognize a «-» symbol followed immediately by digits («-47») as a number token with a negative value. However, «+» characters are always seen as the beginning of a Symbol token by default, even when followed immediately by digits, so "explicitly-positive" Number tokens are not recognized by default (this behavior can be configured, see below).

+ +

Symbol

+ +

Most symbol characters («.» «!») are recognized as single-character Symbol tokens (even when sequential such as «!»«!»). However, notice that PKTokenizer recognizes common multi-character symbols («!=») as a single Symbol token by default. In fact, PKTokenizer can be configured to recognize any given string as a multi-character symbol. Alternatively, it can be configured to always recognize each symbol character as an individual Symbol token (no mulit-character symbols). The default multi-character symbols recognized by PKTokenizer are: «<=», «>=», «!=», «==».

+ +

Word

+

«Blast-off» is recognized as a single Word token despite containing a symbol character («-») that would normally signal the start of a new Symbol token. By default, PKTokenzier allows Word tokens to contain (but not start with) several symbol and number characters: «-», «_», «'», «0»-«9». The consequence of this behavior is that PKTokenizer will recognize the follwing strings as individual Word tokens by default: «it's», «first_name», «sat-yr-9» «Rodham-Clinton». Again, you can configure PKTokenizer to alter this default behavior.

+ +

Quoted String

+

PKTokenizer produces Quoted String tokens for substrings enclosed in quote delimiter characters. The default delimiters are single- or double-quotes («'» or «"»). The quote delimiter characters may be changed (see below), but must be a single character. Note that the stringValue of Quoted String tokens include the quote delimiter characters («'Woo-hoo!'»).

+ +

Whitespace

+

By default, whitespace characters are silently consumed by PKTokenizer, and Whitespace tokens are never emitted. However, you can configure which characters are considered Whitespace characters or even ask PKTokenizer to return Whitespace tokens containing the literal whitespace stringValues by setting: t.whitespaceState.reportsWhitespaceTokens = YES.

+ +

Comment

+

By default, PKTokenizer recognizes C-style («//») and C++-style («/*» «*/») comments and silently removes the associated comments from the output rather than producing Comment tokens. See below for steps to either change comment delimiting markers, report Comment tokens, or to turn off comments recognition altogether.

+ +

Delimited String

+

The Delimited String token type is a powerful feature of ParseKit which can be used much like a regular expression. Use the Delimited String token type to ask PKTokenizer to recognize tokens with arbitrary start and end symbol strings much like a Quoted String but with more power:

+ +
    +
  • The start and end symbols may be multi-char (e.g. «<#» «#>»)
  • +
  • The start and end symbols need not match (e.g. «<?=» «?>»)
  • +
  • The characters allowed within the delimited string may be specified using an NSCharacterSet
  • +
+ + + +

Customizing PKTokenizer behavior

+ +

There are two basic types of decisions PKTokenizer must make when tokenizing strings:

+ +
    +
  1. Which token type should be created for a given start character?
  2. +
  3. Which characters are allowed within the current token being created?
  4. +
+ + +

PKTokenizer's behavior with respect to these two types of decisions is totally configurable. Let's tackle them, starting with the second question first.

+ +

Changing which characters are allowed within a token of a particular type

+ +

Once PKTokenizer has decided which token type to create for a given start character (see below), it temporarily passes control to one of its "state" helper objects to finish consumption of characters for the current token. Therefore, the logic for deciding which characters are allowed within a token of a given type is controlled by the "state" objects which are instances of subclasses of the abstract PKTokenizerState class: PKWordState, PKNumberState, PKQuoteState, PKSymbolState, PKWhitespaceState, PKCommentState, and PKDelimitState. The state objects are accessible via properties of the PKTokenizer object.

+ + + + + + + + +
PKTokenizer
+

+ ...
+ @property (readonly, retain) PKWordState *wordState;
+ @property (readonly, retain) PKNumberState *numberState;
+ @property (readonly, retain) PKQuoteState *quoteState;
+ @property (readonly, retain) PKSymbolState *symbolState;
+ @property (readonly, retain) PKWhitespaceState *whitespaceState;
+ @property (readonly, retain) PKCommentState *commentState;
+ @property (readonly, retain) PKDelimitState *delimitState;
+

+
+ +

Some of the PKTokenizerState subclasses have methods that alter which characters are allowed within tokens of their associated token type.

+ +

For example, if you want to add a new multiple-character symbol like «===»:

+ +
+
+...
+PKTokenizer *t = [PKTokenizer tokenizerWithString:s];
+[t.symbolState add:@"==="];
+...
+
+ +

Now «===» strings will be recognized as a single Symbol token with a stringValue of «===». There is a corresponding -[PKSymbolState remove:] method for removing recognition of given multi-char symbols.

+ +

If you don't want to allow digits within Word tokens (digits are allowed within Words by default):

+ +
+
+...
+[t.wordState setWordChars:NO from:'0' to:'9'];
+...
+
+ +

Say you want to allow floating-point Number tokens to end with a «.», sans trailing «0». In other words, you want «49.» to be recognized as a single Number token with a floatValue of «49.0» rather than a Number token followed by a Symbol token with a stringValue of «.»:

+ +
+
+...
+t.numberState.allowsTrailingDot = YES;
+...
+
+ +

Recognition of scientific notation (exponential numbers) can be enabled to recognize numbers like «10e+100», «6.626068E-34» and «6.0221415e23». The resulting PKToken objects will have floatValues which represent the full value of the exponential number, yet retain the original exponential representation as their stringValues.

+ +
+
+...
+t.numberState.allowsScentificNotation = YES;
+...
+
+ +

Similarly, recognition of common octal and hexadecimal number notation can be enabled to recognize numbers like «020» (octal 16) and «0x20» (hex 32).

+ +
+
+...
+t.numberState.allowsOctalNotation = YES;
+t.numberState.allowsHexadecimalNotation = YES;
+...
+
+ +

The resulting PKToken objects will have a tokenType of PKTokenTypeNumber and a stringValue matching the original source notation («020» or «0x20»). Their floatValues will represent the normal decimal value of the number (in this case 16 and 32).

+ +

You can also configure which characters are recognized as whitespace within a whitespace token. To treat digits as whitespace characters within whitespace tokens:

+ +
+
+...
+[t.whitespaceState setWhitespaceChars:YES from:'0' to:'9'];
+...
+
+ +

By default, whitespace chars are silently consumed by a tokenizer's PKWhitespaceState. To force reporting of PKTokens of type PKTokenTypeWhitespace containing the encountered whitespace chars as their stringValues (e.g. this would be necessary for a typical XML parser in which significant whitespace must be reported):

+ +
+
+...
+t.whitespaceState.reportsWhitespaceTokens = YES;
+...
+
+ +

Similarly, comments are also silently consumed by default. To report Comment tokens instead:

+ +
+
+...
+t.commentState.reportsCommentTokens = YES;
+...
+
+ + +

Changing which token type is created for a given start character

+ +

PKTokenizer controls the logic for deciding which token type should be created for a given start character before passing the responsibility for completing tokens to its "state" helper objects. To change which token type is created for a given start character, you must call a method of the PKTokenizer object itself: -[PKTokenizer setTokenizerState:from:to:].

+ + + + + + + + +
PKTokenizer
+

+ ... +

- (void)setTokenizerState:(PKTokenizerState *)state 
+                     from:(PKUniChar)start 
+                       to:(PKUniChar)end;
+ ...
+

+
+ +

For example, suppose you want to turn off support for Number tokens altogether. To recognize digits as signaling the start of Word tokens:

+ +
+
+...
+PKTokenizer *t = [PKTokenizerWithString:s];
+[t setTokenizerState:t.wordState from:'0' to:'9'];
+...
+
+ +

This will cause PKTokenizer to begin creating a Word token (rather than a Number token) whenever a digit («0», «1», «2», «3»,«4», «5», «6», «7», «8», «9», «0» ) is encountered.

+ +

As another example, say you want to add support for new Quoted String token delimiters, such as «#». This would cause a string like #oh hai# to be recognized as a Quoted String token rather than a Symbol, two Words, and a Symbol. Here's how:

+ +
+
+...
+[t setTokenizerState:t.quoteState from:'#' to:'#'];
+...
+
+ +

Note that if the from: and to: arguments are the same char, only behavior for that single char is affected.

+ +

Alternatively, say you want to recognize «+» characters followed immediately by digits as explicitly positive Number tokens rather than as a Symbol token followed by a Number token:

+ +
+
+...
+[t setTokenizerState:t.numberState from:'+' to:'+'];
+...
+
+ +

Finally, customization of comments recognition may be necessary. By default, PKTokenizer passes control to its commentState object which silently consumes the comment text found after «//» or between «/*» «*/». This default behavior is achieved with the sequence:

+ +
+
+...
+[t setTokenizerState:t.commentState from:'/' to:'/'];
+[t.commentState addSingleLineStartSymbol:@"//"];
+[t.commentState addMultiLineStartSymbol:@"/*" endSymbol:@"*/"];
+...
+
+ +

To recognize single-line comments starting with #:

+ +
+
+...
+[t setTokenizerState:t.commentState from:'#' to:'#'];
+[t.commentState addSingleLineStartSymbol:@"#"];
+...
+
+ +

To recognize multi-line "XML"- or "HTML"-style comments:

+ +
+
+...
+[t setTokenizerState:t.commentState from:'<' to:'<'];
+[t.commentState addMultiLineStartSymbol:@"<!--" endSymbol:@"-->"];
+...
+
+ +

To disable comments recognition altogether, tell PKTokenizer to pass control to its symbolState instead of its commentState.

+ +
+
+...
+[t setTokenizerState:t.symbolState from:'/' to:'/'];
+...
+
+ +

Now PKTokenizer will return individual Symbol tokens for all «/» and «*» characters, as well as any other characters set as part of a comment start or end symbol.

+ +
+ diff --git a/docs/web/common-footer.inc b/docs/web/common-footer.inc new file mode 100644 index 0000000..594ae23 --- /dev/null +++ b/docs/web/common-footer.inc @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/docs/web/common-header.inc b/docs/web/common-header.inc new file mode 100644 index 0000000..16d80ec --- /dev/null +++ b/docs/web/common-header.inc @@ -0,0 +1,6 @@ + + + + + diff --git a/docs/web/common-nav.inc b/docs/web/common-nav.inc new file mode 100644 index 0000000..d44c86b --- /dev/null +++ b/docs/web/common-nav.inc @@ -0,0 +1,16 @@ + + + + +
diff --git a/docs/web/css/.svn/all-wcprops b/docs/web/css/.svn/all-wcprops new file mode 100644 index 0000000..b6f6f98 --- /dev/null +++ b/docs/web/css/.svn/all-wcprops @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/1388/trunk/docs/web/css +END diff --git a/docs/web/css/.svn/entries b/docs/web/css/.svn/entries new file mode 100644 index 0000000..c67750f --- /dev/null +++ b/docs/web/css/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/docs/web/css +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +master.css +file + + + + +2009-09-18T00:46:28.000000Z +525b6a2cb506e733672d77378381ea0f +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1306 + diff --git a/docs/web/css/.svn/text-base/master.css.svn-base b/docs/web/css/.svn/text-base/master.css.svn-base new file mode 100644 index 0000000..9b7bbea --- /dev/null +++ b/docs/web/css/.svn/text-base/master.css.svn-base @@ -0,0 +1,88 @@ +#content { + width:675px; + margin:60px auto 30px; + text-align:justify; +} + +body, html { + margin:0; + padding:0; + font:14px/1.5 "Lucida Grande", Lucida Grande, LucidaGrande, Helvetica, sans-serif; +} + +body { + min-width:980px; +} + +tt, pre { + font:12px Monaco; +} + +table { + border:1px solid silver; + background:#eeeeff; + margin:25px 5px; +} + +th, td { + border:1px solid silver; + padding:5px 10px; +} + +.code { + border:2px solid silver; + background:#eee; + padding:5px 10px; + margin:25px 5px; +} + +h1 { + position:fixed; + left:0; top:0; right:0; + margin:0; + border-bottom:1px solid silver; + padding:3px 10px; + background:#eeeeec; + font:bold 16px "Lucida Grande", Lucida Grande, LucidaGrande, Helvetica, sans-serif; +} + +#home-title { + font-size:32px; +} + +h3 { + border-bottom:1px solid silver; + padding:3px; + background:#eeeeff; +} + +a[name] { + display:block; + margin-bottom:60px; +} + +a:hover { + text-decoration:none; +} + +#nav { + position:fixed; + left:10px; top:60px; + border:2px solid silver; + background:#eee; + padding:5px 10px; +} + +#nav ul { + margin:10px 0; padding:0; +} + +#nav li { + list-style-type:none; + margin:0 8px; padding:0; + font-size:smaller; +} + +img { + border:4px solid silver; +} diff --git a/docs/web/css/master.css b/docs/web/css/master.css new file mode 100644 index 0000000..9b7bbea --- /dev/null +++ b/docs/web/css/master.css @@ -0,0 +1,88 @@ +#content { + width:675px; + margin:60px auto 30px; + text-align:justify; +} + +body, html { + margin:0; + padding:0; + font:14px/1.5 "Lucida Grande", Lucida Grande, LucidaGrande, Helvetica, sans-serif; +} + +body { + min-width:980px; +} + +tt, pre { + font:12px Monaco; +} + +table { + border:1px solid silver; + background:#eeeeff; + margin:25px 5px; +} + +th, td { + border:1px solid silver; + padding:5px 10px; +} + +.code { + border:2px solid silver; + background:#eee; + padding:5px 10px; + margin:25px 5px; +} + +h1 { + position:fixed; + left:0; top:0; right:0; + margin:0; + border-bottom:1px solid silver; + padding:3px 10px; + background:#eeeeec; + font:bold 16px "Lucida Grande", Lucida Grande, LucidaGrande, Helvetica, sans-serif; +} + +#home-title { + font-size:32px; +} + +h3 { + border-bottom:1px solid silver; + padding:3px; + background:#eeeeff; +} + +a[name] { + display:block; + margin-bottom:60px; +} + +a:hover { + text-decoration:none; +} + +#nav { + position:fixed; + left:10px; top:60px; + border:2px solid silver; + background:#eee; + padding:5px 10px; +} + +#nav ul { + margin:10px 0; padding:0; +} + +#nav li { + list-style-type:none; + margin:0 8px; padding:0; + font-size:smaller; +} + +img { + border:4px solid silver; +} diff --git a/docs/web/grammars.html b/docs/web/grammars.html new file mode 100644 index 0000000..27fc36b --- /dev/null +++ b/docs/web/grammars.html @@ -0,0 +1,167 @@ + + ParseKit Objective-C Parser Generation via Grammars + + +

ParseKit Documentation

+
+ +

Objective-C Parser Generation via Grammars

+ + + + +

Basic Grammar Syntax

+ +

ParseKit allows users to build parsers for custom languages from a declarative, BNF-style grammar without writing any code (well, ok.. a single line of code). Under the hood, grammar support is implemented using the ParseKit Objective-C API, so the grammar syntax closely mirrors the features of the Objective-C API.

+ +

The grammar below describes a simple toy language called Cold Beer and will serve as a quick introduction to the ParseKit grammar syntax. The rules of the Cold Beer language are as follows. The language consists of a sequence of one or more sentences beginning with the word «cold» followed by a repetition of either «cold» or «freezing» followed by «beer» and terminated by the symbol «.».

+ +

For example, each of the following lines are valid instances of the Cold Beer language (as is the example as a whole):

+ +
+
+    cold cold cold freezing cold freezing cold beer.
+    cold cold freezing cold beer.
+    cold freezing beer.
+    cold beer.
+
+ +

The following lines are not valid Cold Beer statements:

+ +
+
+    freezing cold beer.
+    cold freezing beer
+    beer.
+
+ +

Here is a complete ParseKit grammar for the Cold Beer language.

+ +
+
+    @start = sentence+;
+    sentence = adjectives 'beer' '.';
+    adjectives = cold adjective*;
+    adjective = cold | freezing;
+    cold = 'cold';
+    freezing = 'freezing';
+
+ +

As shown above, the ParseKit grammar syntax consists of individual language production declarations separated by «;». Whitespace is ignored, so the productions can be formatted liberally with whitespace as the programmer prefers. Comments are also allowed and resemble the comment style of Objective-C. So a commented Cold Beer grammar may appear as:

+ +
+
+    /*
+        A Grammar for the Cold Beer Language
+        by Todd Ditchendorf
+    */
+    @start = sentence+;     // outermost production
+    sentence = adjectives 'beer' '.';
+    adjectives = cold adjective*;
+    adjective = cold | 'freezing';
+    cold = 'cold';
+    freezing = 'freezing';
+
+ + +

Individual Grammar Production Syntax

+ +

Every ParseKit grammar must contain one and only one production named @start. This will be the highest-level or outermost production rule in the language. For Cold Beer, the outermost production is:

+ +
+
+    @start = sentence+;
+
+ +

Which states that the outermost production of this language consists of a sequence of one or more («+») instances of the sentence production.

+ +
+
+    sentence = adjectives 'beer' '.';
+
+ +

The sentence production states that sentences are a sequence of the adjective production followed by the literal strings beer and .

+ +
+
+    adjectives = cold adjective*;
+
+ +

In turn, adjectives is a sequence of a single instance of the cold production followed by a repetition («*» read as 'zero or more') of the adjective production.

+ +
+
+    adjective = cold | freezing;
+    cold = 'cold';
+    freezing = 'freezing';
+
+ +

The adjective production is an alternation of either an instance of the cold or the freezing production. The cold production is the literal string cold and freezing the literal string freezing.

+ + +

Grouping

+ +

A language may be expressed in many different, yet equivalent grammars. Productions may be referenced in any order (even before they are defined) and grouped using parentheses («(» and «)»).

+ +

For example, the Cold Beer language could also be represented by the following grammar:

+ +
+
+    @start = ('cold' ('cold' | 'freezing')* 'beer' '.')+;
+
+ + +

Instantiating Grammar Parsers in Objective-C

+ +

Create an Objective-C PKParser object by providing the grammar as an NSString and an assembler object (in this example, self).

+ +
+
+  NSString *g = ... // fetch your grammar from a file on disk
+  
+  PKParser *parser = nil;
+  parser = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
+  
+  NSString *s = @"cold freezing cold beer.";
+  [parser parse:s];
+
+ +

The provided assembler object will receive callbacks whenever one of the language grammar productions is matched -- if the callback method is implemented in the assembler object.

+ +

For example, an assembler for the Cold Beer language grammar above will receive the following callbacks if implemented:

+ +
+
+    - (void)didMatchSentence:(PKAssembly *)a;
+    - (void)didMatchAdjectives:(PKAssembly *)a;
+    - (void)didMatchAdjective:(PKAssembly *)a;
+    - (void)didMatchCold:(PKAssembly *)a;
+    - (void)didMatchFreezing:(PKAssembly *)a;
+
+ +

The PKAssembly argument will have the most-recently matched tokens on the top of its stack.

+ +

To prevent leaks when releasing a PKParser created via PKParserFactory, one final step is required:

+ +
+
+          PKParser *parser = nil;
+          parser = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
+
+          ... // do parsing
+          
+          // when you are done with the parser, this function must be called before releasing
+          PKReleaseSubparserTree(parser);
+          [p release]
+
+ +

Most non-trivial language grammars define circular relationships in their production rules. The call to PKReleaseSubparserTree() is required to prevent Objective-C retain cycle leaks where the PKParser objects representing different rules in your grammar have strong references to one another.

+ +
+ + diff --git a/docs/web/htaccess b/docs/web/htaccess new file mode 100644 index 0000000..5eafa7f --- /dev/null +++ b/docs/web/htaccess @@ -0,0 +1,5 @@ +# let's enable php (non-cgi, aka. 'module') for EVERYTHING..' +# AddType application/x-httpd-php5 .htm .html .php + +# better yet.. +AddHandler php5-script .php .html .htm .inc \ No newline at end of file diff --git a/docs/web/img/.svn/all-wcprops b/docs/web/img/.svn/all-wcprops new file mode 100644 index 0000000..1903897 --- /dev/null +++ b/docs/web/img/.svn/all-wcprops @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/1388/trunk/docs/web/img +END diff --git a/docs/web/img/.svn/entries b/docs/web/img/.svn/entries new file mode 100644 index 0000000..2475b4a --- /dev/null +++ b/docs/web/img/.svn/entries @@ -0,0 +1,538 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/docs/web/img +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +step1a.png +file + + + + +2009-09-18T00:46:31.000000Z +2a844235c536b4f437dfcc4bcb53c507 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +57243 + +step1b.png +file + + + + +2009-09-18T00:46:31.000000Z +6db1abc20711e5e61af4acbbf18361a9 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +59744 + +step2a.png +file + + + + +2009-09-18T00:46:31.000000Z +79fe4753bd148bb371f7e122a1dfdf0c +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +79730 + +step1a.psd +file + + + + +2009-09-18T00:46:31.000000Z +71cf7fe891d325faa24c583be658f897 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +146999 + +step3a.png +file + + + + +2009-09-18T00:46:31.000000Z +38299814d2e693a738e4210e54ce0c59 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +66069 + +step1b.psd +file + + + + +2009-09-18T00:46:31.000000Z +8293419c0eeafbc094881fab11d8990a +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +144527 + +step2a.psd +file + + + + +2009-09-18T00:46:31.000000Z +e99eb879ede85b57e66b1e731381a57b +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +166898 + +step4a.png +file + + + + +2009-09-18T00:46:31.000000Z +097a5b52c0f45c3c181d8bb9b122b100 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +65076 + +step3a.psd +file + + + + +2009-09-18T00:46:31.000000Z +1cc85a6e0713ffeb7982de2b2a65def4 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +164750 + +step4b.png +file + + + + +2009-09-18T00:46:31.000000Z +fe6e11e4bb71a92b57a1a0becb41ac6d +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +25070 + +step5a.png +file + + + + +2009-09-18T00:46:31.000000Z +da7d878d4ab7a1f0722232057b68c713 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +45296 + +step6a.png +file + + + + +2009-09-18T00:46:31.000000Z +7404d6fd3ae33499a218c6d1146e72e1 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +49927 + +step4a.psd +file + + + + +2009-09-18T00:46:31.000000Z +c6ee94d039827440008bcb598f7f8bf7 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +203007 + +step7a.png +file + + + + +2009-09-18T00:46:31.000000Z +d672ec90617930798159626a8ea8e613 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +41304 + +step4b.psd +file + + + + +2009-09-18T00:46:31.000000Z +11da870de6119c77b93e8e5aca8e72bd +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +85694 + diff --git a/docs/web/img/.svn/prop-base/step1a.png.svn-base b/docs/web/img/.svn/prop-base/step1a.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step1a.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step1a.psd.svn-base b/docs/web/img/.svn/prop-base/step1a.psd.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step1a.psd.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step1b.png.svn-base b/docs/web/img/.svn/prop-base/step1b.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step1b.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step1b.psd.svn-base b/docs/web/img/.svn/prop-base/step1b.psd.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step1b.psd.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step2a.png.svn-base b/docs/web/img/.svn/prop-base/step2a.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step2a.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step2a.psd.svn-base b/docs/web/img/.svn/prop-base/step2a.psd.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step2a.psd.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step3a.png.svn-base b/docs/web/img/.svn/prop-base/step3a.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step3a.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step3a.psd.svn-base b/docs/web/img/.svn/prop-base/step3a.psd.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step3a.psd.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step4a.png.svn-base b/docs/web/img/.svn/prop-base/step4a.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step4a.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step4a.psd.svn-base b/docs/web/img/.svn/prop-base/step4a.psd.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step4a.psd.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step4b.png.svn-base b/docs/web/img/.svn/prop-base/step4b.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step4b.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step4b.psd.svn-base b/docs/web/img/.svn/prop-base/step4b.psd.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step4b.psd.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step5a.png.svn-base b/docs/web/img/.svn/prop-base/step5a.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step5a.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step6a.png.svn-base b/docs/web/img/.svn/prop-base/step6a.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step6a.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/prop-base/step7a.png.svn-base b/docs/web/img/.svn/prop-base/step7a.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/docs/web/img/.svn/prop-base/step7a.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/docs/web/img/.svn/text-base/step1a.png.svn-base b/docs/web/img/.svn/text-base/step1a.png.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..88aedf6223346aee02ba497cdaafc7b50d5acb02 GIT binary patch literal 57243 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

VeMzVh7Rj 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 bKE^w{N;NZKn6Q{ign&y+4GybOL4^Ge3yda& literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step1a.psd.svn-base b/docs/web/img/.svn/text-base/step1a.psd.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..078555a8ca723f88ca11cb2134165815e9b310ed GIT binary patch literal 146999 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 TXk@cFYsN5y{d{b2{~`WAi&DWl literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step1b.png.svn-base b/docs/web/img/.svn/text-base/step1b.png.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..75eb7c9372714a655903a36c5a59bd3cb5ff271b GIT binary patch literal 59744 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τm03>+xQD8&POu(|%K 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�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 literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step2a.psd.svn-base b/docs/web/img/.svn/text-base/step2a.psd.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..3373f4980af90eb0a4d526cb04ccdc05c655d351 GIT binary patch literal 166898 zcmeFa2V4}%);C-;3>jn%YrsHQ-C!arVnRhxR4`z~h%h1&g+UaA5e(#@pqO)33?QH) zj*1Ca1tThw1PMci8HNen{hjIoMAzMW{l4e@e)m4F({xXDb=9d8{^wNa?qSrV*>;G5 z_WekQ{`y`2q=%+1XW42=zpjfX*rVLlr@I1U?zdHDPyC(=%5GTX<| z+r^9H0!?GO4y!zUIpg&8aYG%SHsKt+IvVou8BPm2+|kqBV1t8~fzfb7gAU42aV%tx zw)AE@aM+V!9}n`F4>L4_zj;PRqm2wln;1cQw4vcxT)lJ2&n?q5Y&@M@R&V?^4O8RJ zG&+_1ng*D{$${hWZ&B%7_A5HHJf7b3JU!jU%gs4^jVH&`XN{+quBDxcu8o7Eiw8dM zBvf1RHcDd+u#!6|owg{}*H`)f${0?L9k%fD^>(98?&N5|c4ND))(D&Bce~>AlgQ z!(RVWh6ME6*nC?Z?SAF%{-r7DDgYvHm-TEXD{oJC8Z2H8-ahPk8@<@$^yjjDJbk?# z+4>#qwt1wD&1h>6AC7~EBinlNcwb)^r_qxq8<|WtHJWT@KGJgX6eA;ZBTM7SQ_M_9 z8JZgz8jqMrL;1^kofOo@il?J5hFv?&5yoc5R)!PJ%*_6o=H$=y{-=?~aasL2EPeqp zeC4nB!nvbodAooVv}cSr8f);EyiS7C*A`(#yZK^I8V>>7(A?0#$PhklRXbn)y6WP8 zuG;zX*Hu5)obTbn8E@Ry+E>|M*Rln%*0U$OIJ14A&WMpijYpWlJ_>g8p~fSPhZ>ui z!VY<(OoxszF@)U+(vUyOWT>(E$e|{NMng@EM!{}Abc8YNCdQBlbj%E4hq7k)d<0yF z-Ne+yc#Nr))x?ogrdU~7nVDHmwltq&I>~a>By&>}ODiK|lZoKIv=+bMtc~seu{g=z z;PN*(z*qi?1Drd0w#x>#+oH)XfN39WThkF>(r;erq~*`o7k{p4g2C|3D__^7!q0!c}|(Zs91;F{9I?@X;Ljgd<(Xd<3M;jB&mhzzvQ7N>d|qpox#TuK6fj z*L)N%V?GL(F*m2nm>bb)OwF98W^RsKG^c5rV@`|>jYbXy;0^__4;?wwZ0M+==0ia> zMn*%8jE5ST3^g(x3P6TJMrK0+^)Ng$244VI052H<4g+`x*8s$i8DTnQgqe|%nWdqX zG1%M8c;aNMiC_z}5tEJ0CyugeGv*f-`$w3|!4D%m7-1T83^Ch#o{mx3|B=LJoc$jm zFDLq=k?&IO4|V-e*LP{)y9)n6*AI1lmj=G8@DFtTP}g^9;JXU{K-Uj-eU}EltMCtW z{ZQ9;Y2dpG|3KFdb$yoxzN_#Lbp24*cWL0e3jaXY4|RQ)2EMEC4|M%d*LP{)y9)n6 z*AI1lmj=G8@DFtTP}g^9;JXU{K-Uj-eU}EltMCtW{ZQ9;Y2dpG|3KFdb$yoxzN_#L zbp24*cWL0e3jaXY4|RQ)2EMEC4|M%d*LP{)y9)n6*AI1lmj=G8@DFtTP}g^9;JXU{ zBf8W+zqHBrfHyV$;FV1LPNxDNzth?KC%EkHrn{c)jo;xIrw?x^>g%#S9N~RJ59e|E z^XFL&8%4jwsW*9+<-EnSr|80KaXuW~+4CpOw6@gMA7)@M5#E$z8yHNUH(7V~Ol!M& zy7(R4Cy#_{kj<#0JMFK>8{aQJKoXSNmn&ff6ZHq$)4UHm=a?IbsN(PyjyE)Uh( zs(-sa#|6L9I@}Szh3VYj3PW2CzN&rsANhAX^ndI> z|JtLgj&1K7vC7+fOq|A2{eu*^NZT-CCY!@y!^q?FsG`08*JGWwKJr`L_~%~etA1Ry zqtk{KJ9_d?xow=zbMbU`pf&#AtL?v$p_8sX9EQ352dMjN!+tT^o9MLG*N4M)!kKf~ zj-3BSg#|3$W$iRrgWk1!kgMRq4&`2XMC{!R5j`1@ZD zfUhO|8w3n98uf+o+JNyl*=AlCKv z+v)x%Ojy3|X4z~^AE3fS{!mnBVCn}veZLj}VM%&lOzvi@^QTUZNyskf9jlMTfi|-Af zpU^a>E&OsMqy3xyEy!Q#YhCCgeX!V!5Pe0HK4rmi0Da!)%X5Wh`dpPh!hs>LrAD8_ z?^EJBzsY}pQmy0nDj7IeK}eUGh74A(hAVDxRBEdw&pEnxUq_BHP1+ug?PW&LIm15Z z&@@}&93d}+sBeB0D)HrSUZVcLT%$Fkf@y<(u@Vq-f_!h&;z-Cv=nU*_*YT-`ubUfu z(e)O1`*^r{dN{*5{i~jA4~JE&;KvqmIaLo|_epH{2}5?L5-N~6aWyP4bjm|^UXGoq zsJXj%%!1$5a^Y-jD}}A6=I*fJ%UrBoG|A1wrmd7REsqJ#Wn#^N+%S*zAMLbbM^Cv6jx2{~92wl}^d)7DZC$W(V?dw2q;pR<{Za9Nt%T)4O4A&m!9`id1C z|B44}T=W$ldibnivuW<(Mg@Bo{X?rh?QPH$2hbET!sJmy8>g5paKJwC*H-Xv+p4T` z@S&Fu=S^8O56%_QeB^`J$Q#lS9pE=yJ)C^LwC7w$juBj=+nEQySK3JhXeN7gXO*By z98Y)ob^MFE2+eg~({>$xT^H#4!0(5$+ofQ9(T*a04GMLGU70?yp4_P|WoK_sU#~B+ zl;F-L{N^qj+yd%oOtHh%;eHh4!MUb`FUNB#+XH(H+X*rd{*BAF!fNuuI0s*`c6Zi= zum98XE5Hw~wkf`ocYm2<Y zwZTrx?JB1~X==v>sDf-gJ+Q7-Ii6nNmOkvxz)^DpApIp*W0fZd0QHxAbujUouZq(i z@jGq@X~52~XrR+_&(OkYg;#jTx5=@)xqEQD=T4oZyJ)e!uJSwR7yBSJ*atZ{`gl#8 zJ$t6S_P35LZ{(r*5BBlf@U0r1^166KgTNm4jvmhP^aPw< zB~N3Y?BU1p0z)v?;I!i!2f!|46QqZF&zoxr=`)b-;w(>J!|7G>^dp>J@92!{zJ;`* z2RyI<5kUpgqnzO9n%nwRCnq0Aa2VzZ$p7f>?g{i2!XW*-qn9_-Rk#f4fmko_4WD(k z2#toZjl#LldCQ+8l#+~4PovLyzXC7a79eze=I6ZTx3sPpJym>Go6!9vVyLG>*x5}{ z%?kl`e;`EUQIs^DqKH$_#(RWrw>bKGua~!t7>uU~{i}1i%ybR#g6ALud}s&zc3Q3% zx|AV8$8SSq*o@Fj_}&luZ@m!e8i3I336MVlF-=U`cexG`{-|~Q7BGGKKX-6<^TnM% z{`>^HhQ}(~S@4a6Vy@46yD9DI)h<@n?P({6$urv1{%b73Uh?v*y{+c9r`I}6pWU8j zd(5|MPkV7Db(CTIOzFt?Uo#KvBd6o-J9mD2+SPMLM|mgq7to%G)AUqB!ZEr9CJ_t={F$sD{bq$x7nLp%)$`>^)SQdupfcl6_UjWJ%V(PzNj~1P;aSX^wV@J zYb(TncrXn%MAae<`q#NvSlU2|I@E(5#m z8d^X1?%w_9?%jKL)u2CZU-FZ$j|@$9bT^R~p8B_su&T7;>h6Qk`$e=&KF#afja4bb7WffI5b(pk#d69vb3hftv zLJSr|fyrVjDl4fdDrlI%#jXl0y>3Q|6X!T|*IyTGtkh%2(JPaF8Tj+uJF84gy+fW` zDi7Le*HF^v=rf|{vE(hkPL7}FH0ADb&d6Rb=6_^2rEJZ5>08=t^;^P;ZC7{QdsQYl znR@^AC*gwC>$mSdmG33H&4&KoNb8u(w^9GZFt4h2>c3Rr~?C4|KI7kUIp#1BIyDxx=YGGGYiyvq@h5!*%eu!Pxg^3OhkGk23$Gz#@`|3@c!t^o94#_o)V+?=FTk^W~4ef zXhH0tH=Lm}-JT_d+p=f!`n(wvxL_hHEyH~^zrrW~`r%iy`_COYZoPz>iGuNmKK!=W z$Mop_w-2~euRoL3+mEBrUdh@_opK6UA3nUj`%#Il!HCToDa9AN>Tp6F2MlP8t>^kS z_nzMC+;buKM7?8u)iU$f@ADGpK3Sjo+WfR&=Ey!p*AE|0c|{?0$#mZ2qoKJs><$#A z3N9Wfzjf5%=h6|U&YN)!YxC379eEal{HhefptAbm*g^Ayj!noVL!Z1pd}6bIi*WoB z)k(r4ai-9fLW8|{wcEMgE1CoNdE~qjZoUTj>9=mfntq?&>mr4o)}LP?w%bM_Hxubj z3hggiz-v0KPQG;(4Z3%JQ$*JWpW$~NUm6_RbNp##k8Z0h#;lQW|8#D(&$Q>>y|m!V z3KTNCmBjsI+l#oIQ#T`g!NvWr{>aI?H2f&zW54W!u{ySyMF%OQM4^VO5dLC3M z-MLSu{2_SAEaNdfANknTsil=~V5OVf){Wh?eppEHkqTD-Ck?7L+#BP|63m0&@~GTT z`(j@8Z0ef-`1P1^f4s|;+^DQ>o%$?CCR|%|`mC=kqbWZ|HrVBUK$ha`_Z2-;b1nqz z_36tGiWT*;5c;2YuYNoKMZudGdtgP_;>SZ~O=~3n7{Y(Ee8v3pzgJ}LT5S3D{gN5$Q}5Ii zNoFl73-YTQQh0Gp1OLxs`2&V-y!7(2iOs3U1$F1e^Um!Ood2Vz_Ss`ca#yTlr(Q*O z>H;%Xkg6AD^+!&(jNM#va>>z43U8dBr}(&B4&Y_EaZeptYZ7Gj=2|PuwJ6le(dg-$ zeFfLkmTKoX-f>*(vN|VV*ar#)j1R5k-g%c9;%UPld3E=^hgU0Cy?^x4u_~xKen9x4 z%7Tb2Wv~6c9iFFiUrGY(*!P$3Wbj_}TOm4Ef3hXj!c6nx^=;QrJx-5!JNUx>gG&zO z%o;H6R!iQp3jq|Gn)2(Vh6}tGBgYk({Ys%p7xrg|{?xog!6DSGQTmiZFZK@zmHu{) zdsL^Tn%m?uApW(Msg~52CpP_LMm~(BkoN@&jW{gsajVnG&z3C~b`+XmQTv8MWiN{ECNv|eF=r)XZlZ_i{d8)pCyJsn}4M5upRVs zKcH9F2E(JFVF0^`dvCOC9v zDGLQ+xq$0<1dF@R6fot7!wp-c!-~%6TfXq+Vyt>Yh8mKhj@vM5=UHo zU-Vq+_V!O5*{59}_P5NMPoaqv3Q4EX^g+@g=O}c9LU%w5C%f5E&p%a{{gTSOHGg~3 zT*0p4*Z20dYRXlT zE_#z%FI1t9AeX8rXRU#sQ4)!+ZIvCGDSTF*)g zt2Y7Tst$9K*RJd9NBnxYaE*Gng>z-*u2DT4Q=guUTDk5+ao=oBcc1e-@3ax!b9J&I zq!H(%g#M3S=J79$xh@^^Fm0KUMC)|=i+l<#ox{%DM2w9&)#an^94Ge=Bl{PvmMlN~ zlF%XJXVguVl?7!Fskanq<@ZVzC^vDz3)U{*OwJPXYL~9z+Uo|Tyk?-p?lFxP)4*7g z6;IP&g2gPJ$K(fHQA>a6H#Z=CqHEO#qk0k7r0m|UGVZgfr1z~R3kc=Q^V@hk>#rcT zfbJ&Mi@QehuJn~fE$FXm;H~Gvl!s@y`Ln?Btc$!XDpsb~JBkL14#}IJlN?-iV?EJb zd~3zecZuWG&aty8ly;axCw6*Fee?8b{HtGlRzUPlQRIXk;ahT76ypfj{Ixa6Nq>w5ZJtHepR=IfNRbpQ1 zyQ*>i7B9@|XXG6xehCsr#tJ#F2IQpQC>>NM9R8s^Si^_AzvasQIel|Q8Lr-24miIb z7Ju4ePppzb^YNM`_Y-B$xzr2rlOeJ9Z(Q*A9)QmO;&);q>tHB*=WV|fSKf=k^AFCs zBU^CP-^8QnRnto$@6>M1qyjglGx@S8W7+ul#ES-clHJ^z^iveFFOoI-3qM&}no;;rdA9Z?s~fTvad3)<$TgrNy*6zn;V*lq#(P~wLMn`>R2a|TZo@sPcA(@Bb_h3 zakO{qMRtt2-dNo|Re zw8^7t1U3Qo^l4G|F4$3Rp0Q;0 zJJ)>=(r!P!A}h~X;@k?uu*%o>mvUqy}|c;TD`BOK4x$(v#;eK$=l zn^|q#_f_8ox68+@Oa1f|8Ec&?e=RF*;jumaS3FET5tQ?5&lR!NnV0SvaIPt*W}K)M zdHl8-ynb)p?7+7Z?^I}Jd0g5(0mb^py80RAj|4}xXgK#LS-8A(d2V*gOig4lqe?oU z{-n4{*|#?g_vK zae>R!)i1hKxNn}8yZ4vvF48||W~z=J!<`#TByx(Xp|3e)u>AH-Kfd+hB*H|J$F0q* ze!Ht5g)E*ws^A^eDbP8PkaAw?=)J{s#M`BA17dOq_AXdmdx=8NBd4sE_#Md8u5}!& zd39XAZF5F*<|5a=Edk>W9fII^beO{}!8z~IZyt=SnJx;sE!A$&p6EU+^XaJ-RkZ<4 ze>euZ^7cAQru@eCUG=8+uIp0%oprv^dTBkc?JGGgh!T!8;S%e{nSNMQus45S^N3na zFC)Reyqj;OeTl2(QK#N&nRdUaqFKe+wN{Txb(|Gt)gSG zG5L#UyXOdp$|@NBs#UfWPkJ|jv1*ci%_v^Tyq(rRM|?)&be9!Gx5Htw$X~km(#&K( z>p$_$BF{|W8>I)=?-!lO3f#|Iy#AN;pjZ<35lI0QI%e1Jku0*8@^2>xq&u!_SXH_s zE^k@gM)#+FRkcC&&*#8!U^;JB75Ql`&m?QZrO=9(v9Vmflq+&A@g3GuWt+NZ{;j;X zH3u&h=qg*~O%#;RD)--?7GQQN$V7d8hIz4DVqAl1sLg)f9jS*Sul8!M)g@-;Ptv>H z@jExgAphE;MMH!`FD{deuJ+{}t|8Z{_zq7{61|&G;8L*)fTKtg%?HNukTikAxp;?JHf6>HbuZF)Mw2ZFbJAYuV-tLi@bx zjk;%e6iL)B^RMk`dEY!G`h)ArYntSVtD`eBme(J>E~L<#nzz6%=v=ymG~nhE#u|+P0Z)Dj|dgd z=U0kON&;S8$obRJHSo2zyRVH;C3^qnTHS{n`?U0+N3z$w#u(%U@>a5+`s`z9x-PXZ zf0Hx+%_0hY2$b>##H{BM?xFMH;e951_OCJ2{9RO&vh0P~j6LOvJFY()m=ScrgNO~> zPoYFXkL9Ds*o$Ulj}Gqg!BoR*HIb1{2Gv(|ec(LjL$3ci6ns+>^&+s3D@Wue^tSMk zn90miET0b7s-sZEQ&BV*1`8T6zFvB_Fm7#Nz#~Vq_cO0Cy4|h+z)h+ArR3eq_sz>q zPQK|@*FXQ`&uMu}f+8&g*8F12tmRvbR*T1`0nSllJUmkJ8X5>M3+JmWX@`LXI7<$2qmTXTZK?>|2)h;H9JJ+z$y?+V$DJ0I`w)lp>&Y9Ig*Eu=W%V3Bk zR)6PhFLHeUzNl*46EF9}H>S1lq(dHzhoSbzoRiS)*AwZFmfwGMyk-4@%2=!H0;9gm z1Ze>v*ZjE{D9?PvMMqqget5jzNHnr~znx{hPiD6Y&HTex4m}o;b)S9--|t)RySV)F z$oizMW4CAoFob5Q`$v+li>s6C-;A4Y*UPh}X4dpTi<69)VAPI>`_u#%zNq2KcpY{;YR-lQf^3=!S3O2@9~2o z_pe?Vc>jq{zdl!vyT_y!K7J;;B6K_XTEZ&^@3Ov@xyVYETb!$*_Fg?ox(_(a`2f*c z_i|B-r)|+u6Tg>It4G9dI(u6V@@7DX>1jW%`*Z1PtEc;U)?>!4knY&QdnL>~{47vQ zQvZ%Z3+yg%ysDm_vsymk(eA6v-hJv6r3JOJysLRNvZsfi4f$i>&V-%T15f_y_uPV2 zbx<(t&LC57i=(d_b#^TA4V^P!@TsYS(YJnS8e$tA6wB=~+2;UZNyUVW+NyHd#V}k}mLIo)^y3zlC51M4=;%?`hzV5<{VlN2ShkFa~^< zgYj!;Ihc$N8pD|#wB^L$2rIL+9_Vj;pGWHmzNYxt-4ov@X=@8-!3_o2VG$3DF8{PY ztpH~XoNmwW{N0|-fr;E1D)FIYIu0s zIKbOi^v!#m3B^!fj<qlMTH8JU z-ruP04v(62JOV&R^`p238s-j<2Eg}cy|UUKfx=o=ZhMlkGSFq%lF@y{L+R)`Y&Rf38S-)m= zEpUfU4erIM;|)DVd(ajbR@ejGDbUx+YvQy#H5bi+tDZnN9wnl^u4TP`mB<0P!1-ph4Ym^?&tY^Dz7IovPZ;8Hpv-a@)UAQqu^{OKX!926DibIk zgR9O^Y8hIARs$7p;Cl0lfo&s8f(S z3EZ85di&s*1SN-}-(eIu7%f6eVOs**N=Pq+fbY?OM0?nl19eZ3ax>^Q1irTeO?S|@52UsO--#gKeURuidIq*F0MwL#r$j=2 zDA?f|=n1sj}&tI6mfVE!bOxdl}2!j=twaR#WQ!j=LSx(;X2U_B1hJ^;2n4|N|ygm?&C zr_$VC1s_z>e!dE)IQV1s!W9q4BUyKx3ixwNN$?YDeIfY=IJ#%$UW$Km=Z zX#WUs{g^KC5)fNO`+pMnDfaMdw7nvM|1%If&Vi;c13oW9dw0MJJSck)t{edU?*t1x z1Ui3$4$Gll7PQKPQg(wu{|JMG@e*OEY_wU#9H-}lu{a-cI)XM6q2BMK!-_%GpDKs}WHj#~tCIKOo z3N)HqL?U5}5dK;O0z#zNDryx8g+vP>LM`G}W=m@;(L#yDt)v9C5@IA3h>=JlY85ji zQi-^xl__cwldZBAs+ABiTSP7GEK^)ESZi}g$d)bJJ9FHljpH3VcgF9X$Lcn2q;}r{ zI_U#~2dECv(e5?T#SqOGkhRSEhI+C=(nvK?&FYO!O$|*=0-;bKY>^0%NG7CO6ojId z7Kw-w%34SfLo6a&mBp>VD+oij0E4YE2~*rECZ%EsxKfc&L;~9av9uLQT7Xlsm1-g2 zo6#a*`ER6k%namiCWEOEEl@F5a9B9jab#2^5%W`QT-=VG@$tKM4@Cnf4e8xiha7scgfm5ETR zq(w<27K=a(U<#NfMMSGuLP}f33KFrXRVr$PLZEQauMD_uZKXsM7(%5L6KMr2ks`{U z8L%mk3?f0-R0y@D*LIroa2g$vQBg5bQ8ec}$#~Vopsva$~Xw_i^K zmzgZR!p4S%`i2H+qayGN&>)*gfee_YK#c_8fD%H(peh8a24e#*#I2}BCX%)iz^w$- zD-#oNCT?w&5RhVEs7SN6EiRNm~mOF zM5NdPFcJy@BmS&SLI1>WOl)j4@Jq&1yOb0EK!YX%HZa2)Is*pi_V1~)!bwXjMTB92 z8iDKjCU8QcnGg`oB-XHy1)vZJNw7Xc2(ZRj1~tP@v`9si7;BIc6JU9v7`2jsf=00d z292~u5iHT#3V3G1xl|+p*>Fvah`>M@7tv6rwoss71be@TsK`hhDq>>e<9EUqzia=d zpOj5$K=jYh3D%M6sP^k_;yD8u*EG}<4T_Bo^^J|dF4;^9m_k7l*{s;qj6;M}NXl^l z;R8}aaDNe~92ADZEfq;294LaK!Rpw{Hsbf8Vf**S+pNWS`cUg zni5d{Dw_g9?Ocd@WUwNHkgcI@a;SnF5J6(&qT|S&6sVort#)uR>OO8%Uu_*-y_>qh zx-wlg9qrz>p1&bZYkdO_e5g*=fSN$(0ShEbtiuy@J@h>HW9%i=Y5@7kT1I2?d8v`;@>YzC>0%7ESj*Eo0Sdbe3tN7XX` z?)4;~oN88SXlexi6f`x8K@9 z08)TZGT>aXSpX&xiUj}w2sjXS1fYHJ1{`uA#kc1PHuBEP&80WV8TC zlv*JMK{pB>0$QbLhpvP(Mho~SLjdr=;(*^bvxI_Xp+M0ed=*DS<;}skqujck3}r&^ zPK0TOM?^#d%<1TYStoXB>`vS>80k+K+NZyst{x8I1Wu~=2!D;s`&icT4^0wt59DDLICQiIz~gIq(K32 zQ!i;?fDsxQ^$o3!jAj9_(~KIW%?t=hFg#!ggslS9EEYBjg&+ z>gwDErp3CHjz*upD>w90j%(sqSMjUJ8d)t_1H4w(5OTI5+%Ov(>LfVmfX*pko@_$R zQW$JC1N5PjrJAAdYL+#L1T_M%0h~2A<6({pND7@=V*~ULjD{u|)Rl9*ndVrT<`~8# zvM|iBMkJs*E*8{_876QPOx%^Y?{~n*;NJaj(WvgOr>m={JD}GP-<2vlulbdgRiI~C zHL4={%o>~`Ys9rw9kafs2F6=}9tn;723Z|}dn>>_s+R(eWc8qbjGV@%$|eH*89N49 z4?qB|%0O0-xB-k-tBBFe4J5cIm<(Y8!(=EGrY#>z0Vwb|H9BqwW;s3{!bid`B2o3g zX6S^*>h{smBXt=%y7%dhNK;n_JW{V;&*_1q(Y!jck_pO|@fE77tE^O{iCUPC1dxGJS{4T0lGwAM3fYY2QGYb3Q)4XUlH2bkYvRX!UEm1?`kgP@l z1Q>y_8LU8Vr68h&1K$+zjUvf7Dpm=GvJeh;kqKJ3^MSv;`-jqjrJqFaAr-&T20lof=Gx@KpqKaQa+;!q{J{(sOIx)Fe1?=%rT5vV1bIN?t_Z$I6;dck@E zJyqS_dS2^)RzF+)i6|pV70b%Y;g9?zDMuA#Iq`{EUQtPwqfcZxRiRK`Q4Z3`Dpac~ z_~60d#e8uUl&fS^Rf_qnYCd>1St+R!Rw?rF)hcPFaz!P-lFzTGl!DY`l`<45uc)fR zb@-qcqLQ^K5C$j&mj$sq7!EFj>O%=k>0prefsI^ z>9^`V1HCuv_UzwtWY8is{6pEtkHsaWC8cGhr5{T^ek4oDGU+G9@=s--%F2jOsI27^ zQO>9+mwjTCSIWwT72-;&ipj6yOUoq{;1Pf>A;>5#SE{TiudJx70KAn`pO`p>$&^=C zf_}(yU>t(@XQTk*xVNOji3qLe*r=Et^6&zT-}EG{W2E-We{im8&WAjZei^2%}$1B3xlie(>(QVQ>7qEcBI zSt>0Pe*)$z80B!<`l%J90|`rIpJZjSQWhxSQ>o+=1qvWa$&aE^Mp-G^LC0vti%yC6IsT!gxroA%YN(R)j?tfJFvpbw{u zR$3|Xfl*jQ6et%K6ad%7#bl9E$*1!2(vo7b1m2q|loc~eii${(Mitwl7{n_rB}xPz zTT7`=z>WmC5|jehr3xjbA4|m_i4yctTuPOYkfMr3C5(?H#5Wo4i5ZRsC4)NxGGHRH zBOX|WNTRkYAu;}Uq&IeOpZ=mYaH#9)_U|=jiwzp{;lq3K1Eb(QnJ@dGR8UlibxxKk z7Z(Blg#{moLd6fXA;1Df2;^ZDmxzj)Ma3o3Vp$3Ckt&rG3rnO}IN*^gZYhBRl43^5 zM=^X+MUrC0!s2331y(dng*W4=Fho9j42Tu20F(GAGFEd3p2b7wgXcd9@kD|q#&*IU zuBOuPQM!Ew5PI2iR71z9-DmmMUlFJ1-MhSZd2jRHzI*%bJ^7A&&&dBEE1>d8SP7No zlON!LyaMI?4+S5<7KKCs1$Lo65CzggqKH*o1UwN1Ot6!%5EV)a2so1!DnQ8sqEL(r z6`(>ADv$*zUsgbTVA9~m{G%;IC;q7@2IgOhhBtKgJC))Su;$}s2`ce>?2wk>ke_>s z`sQc{!_#z{y}RqMm#b;*O-o5mzH&vD%!F?;Me%BCYRc8CWU3f;@~SjdF)cMMEj3+| zDotagrb*Jp*T{5cT6&r|U3QI;o<^p%UZbv4*JO}^t`X@}Dl_fcHEB9Zm8IcydYUNp zul&L+2lP$CnjslW#VKHI%V3(O7`HP4_?5=9Vh0Z1d^hVuFl;3{ywoqNHs@$RW_0vhxpTW~NaA8nU}kr67e{1X)elb$$Y zM^9X5r<@i52zvjxnAn*0cW$>4V8B8QbYVm=6GrmTiEWe8PEJNC#_j+Dw3llE2}r`! z4>+JRqZyq0;w<&MndkhLEnK+F?_B2HR{At>_44Jb1KUqeE;i8D8@Bjl=3O!?7&cxO z1+6J<4yI>3z%GOox#pR1J7P&-mkBN5-d+QDojX8=*yxxjAMstyJ2xWdEc4#J&3oyb z$QySgIAe#C$JT^|tsYK0aE8{M8-BfYO{Y&a?BCn(#+|!&gJI*{{oLRdte-C$B;u$Y z(C`i-t_v(M?0`KQbQ2X7=?x9ujI#4O^t8F@$ssShsGHE>&4jfPnI8m#g3QRZ36P<6 zb3>0oa}$eRh0ge;`-YpJ8>DD`VsF6uq-S-2F8#>pn3x^7o5hg`2ElQ$FjJzf6dM&C z1Kn`MI`JLN^Y$ArJt=BzDE#x%M*H)UJDN$HJvjyC&CL~sIeR!sk~>`~_54r8@3zNCZfmX3S?b~$v^Qa+hs#o( z6}N8(!^XRfpiArAB=!MWgdWhQn*##=CQ)Bls2^zQdVnI>6HixPxH)Eeq#%)p@~}>`A^SC zcv^-_xLd=b;^HDhw{RC5@_50p@pwN4;z>G<*^ti7G9n|$7!)hTgHvc0z!ObIsYgde zghP|zq1(2(if^%^uGNcW1i_Mt>#s*kZm~}0G>RmIj3p5@=AM+?(i-6y8MpiJ=~IVx z#YC(!y>%-XHr_1+)}-3j!c_2r242?Y6{O9qi) z+qSM1XDY-e38W;UL=uEla4|uW$vT!Ll*nX+f<%~gT#~6}YahS=BrMkJeEYU-+qZ5B<_57_ud8P~ z%(-y(O7hvHoQE0o>C=-Zu3R~J>S^0)b_B=Q*C!(TVFr0U7&hMZ&#h4~gQllL5cjmB zU;#H8!w1%dXj6iS5#W;%;oHfriXof1L4i)9YpU08{rTqo`!|2yy591)C&aa2*m&34 zTTz<%qE}*x5XG%q zwr;~RYJ$=tU~v#@6k;q9s|Gz5bRD42@NgnjbqmNC6cFIQaRu*cFl@Z5?IaX{1UME< z`T%w?pN^tp7;!sbuoKe@cRq51Y~LQX9WxQM$$#U96}*&S*mx;_LxPB60t;;vAOPVg z8@7F0*miI!(8R_Ke#>~t!Lad?aeqjHD)1B;Rw7{9seo5FF%t*^wF-t{G{h9pM3>O* z+e5cvWnv2Jm+`Iy!^XS9qQ^KgdU-|`rU@giaI6Po!T4Dh5X9 zwg4Yrx3$TCgP*UDz4!ua#qhzyjcQF;#zw<_|D{|4kKnARxWHKPv_-;f4C7yrBuN-g zSBP;=iG(L%;Q1eJNeMuRfl7w|M7IV=#(^1YK9Y#)-ljM#7#FPP2f<;n_`H(s5R=j4 zCrqfH$g&tW%5Y$-P~pt^o3EOM@L-8;(|NR6be>_`Bos1SFI^BO2^mecVw_PT%o8&6 zZSre`ZOtn{#|u3Y6|NFSt2HtL#@R~p#-Z1R)}hD6Y7Gevq^-vBUL-!JG}CzOWa}9- z>Swa1Pn}>ksI@`q^wq3~7gG|14QOV?IW$w)pit<2`cYED)dsXd0-0jSENRZ>@ZllPAuexcGkc#VQdWSUQVlw(u3R_|NQ9 z3PpT|;z(Ha{1b7-d}e7^=Rf(WeCEOF2c=L_3?(IeMa2Qy1FRl5^BEdB1guH30*t5q zk}l=5_WwS0VllyIK0ps-d?kN%yyQFW8B0cM&{EKG z4YWxHtAI0u5BPu-XH;j5nL2ykf`tng-y}+yfImZ@BOUR-*y zIL<0hREB0WodM&XK{G^UN+s8_W=C915tS(`sXr_$RasLVv_Mv-SlU0odQB8j#)QWmWMxYJb8BmF z5AYP1waWy{o!jUe$>C&}a(Gx|WHj75lz~XSJ4EX6JAc3R>%F}eichmWw3UVkcyfnSAaP;Bc35A8%NBZ}+x?ULOIOpe;Ir)WYg{%{O`u8~@0}^5&At~&m zm?R$n`2LJTt%W_eX`tfA6oP_omQWf5PSZLdM)+S)pQ@Wl`b9IYc4z zCb}sr)bg7J6}c+;beY0JjSfq0+fIb3<8BTHo)7{fV~ALo$hL`%<1#IF$mXC;8~yxz z*R5M9KE;|oe#X4T#1d6!_OfM{l9nxFuaz!gEuL>PVVE#a@p0*^LrWfu^3e2(Q)s$0 zPb>c1`7;I5s4Z7k<(xT_lAIvR(^oz+Fz?h%`;D3EPxIzR0}-?r`wx;Pu})hI74h`F&Pl5Xj zV0Nqm+_%I~-_QZ>9-(Vn?~6@;QgQkOn+5hu$z`f8&WqRIIJa(zvzv4oYso^}i3Y-4 z#e2L%XYI2@xoCRRNkH;RP(-d)SaYS2D!$Rwa(ThL+1%^lvRr-T=iSaM+_%v8g;_{e zkEgk-9PeFWrstj;ke8dT{$#^~SIy`iGGZVh$z>>BA#;07S#qSi{o-ExUl{MY z+dDT`#0i%5 zMB9Z+iREhRosV8mzn*$*jo%8{a@NvCvn-8-*^0Mrz6r6*6lEjpiWA6MnynR32CMg{ zYid)My2tF>;JjLvt*?~5bfMm#^S!gfO*r?LQ+w z`vQ;<0|`lXAH@sV+4t0fBl;abel|0Evz3oScD6>!{%#MmscgkXR*-v-$VL~)^XQ5+ zTj9^#{k>$_iWkObXYZX&WHT?I3$kp6$8<7V&9&EKdGYKHCG?Uj0lHb-Q?w}o^Z;7u zC7-omkB}q)Z~En7jZRQ2@OaL9=rztP7_x{|eg@tnyf!Ysw~qSpr( zrHisa3CBSRSz2Ce9#FoHE^DW_?F-rAGSFIe(y~xAsez(pKuQdxBw2kFPiOH~=siqV+yCg%{j6J>I!Res z>K7mO-ke3Njj){ zxSZMI%goG3UGq`5h)m`&bPSqxQR}DuN8E!%YbEr z7=T4oH0XjJK*0P5dOWNP&jsS6tZ9~WmaHUKsV`gUu!g;QHQUi~`7+rm*2<-JQ_O_v zDp$5AtQ-_@@HDJMqG=UJ(KKngLdqrKN+Ml(hIM~-f2*)bvUIH%>FHTF(jVPRPq*Hb zp8n@;BE8G=TZw%i-O0I`?q>V=?vrcz>1pY#8%aJ%H)KFa41^@5re1>54CIz-gv(&h_;BPj5cE)|{^O=vvy-Ot_j21s|mR35%Xgctlc`u6XZ7 zPR`TYWV#YvGX1_>74UEkXrhN471%pqmp^RqSrrkqDqzaQg~YeUnqjWQDael2hI#rzSIR?7bmNW?Z%w<9dzB=xQ_UGT0lE zsnphFMoOwQnRy}l0=`5hqm<5)FhLR$?k!W1R0I>|e{D9UCpi&aL6EKV%nAg7QH&S3 z`Vpn2lWZ3)Te-5{fwkOz?iBO#BzR_VY10t^^AX08dP=aV0q~>1q*I_$kxoEL>b?&ssF!X5yI2 zv&_?Rb5TOYVTFXbai@i66}K#$U}3+t=`7>i1>so;fM==md1o)3Re)j%VtJ|3v%Iqu zbOmIHGR;D$oCOl@B>Za*4k?`8w{+UGsmy6h;o0U2`RS3Vm!>K}#%ZzqymTsWDxM7} z;o&$b0;70INrWs*m(OWSeg$GA@EF(pvO6Cbf+e# zLB{mOyx>PBKhp^MOk-~_Y`ndHp@A2l6x&Itbs|A-*Tm4oYXEI*w2{!{25kmDV1~67 zX2+ltCIFj&UIlKv(la1f7{Po1+QUPkgWUqtz&0XY3wV2iVdL#l1R|hUatrIpva`=UujADzZw?B=$lXfN za(zvajHaS`!X!aX5CS}2tNBNQWRN0Fk7f}MvsLANMmvu%(ExhirYIqp&958Y6O2#r z92P||jy%~$JR;DQCPL}TXO_tzCdS0yH2_M$>oVVNK_*fxv>s$Vpw9=9!onGY-$_ME ziaLV^?GkA!ycf+luub$xgp!&>N=coYQ~iHP`wqA$uI}xbWq0Wyy%;r`M3b2I#=ObK z6yG#cG$wY%-V0Jx6hTE1yJCyI_YNW`(gZcOsEH;qF*a-f;7YcHF&F|JvPM-`&0Y>f*+4ZN6LB>8(b&mb-QhB47K{ za#u7Q!^V$S-Ok?qYSG;j|7{w1>+YG)Ui)I+-Q#zK&Bb?(o1Y1Z&#(ZJLDe2)2rERh z1skMEmE%Jx(9QR~DHqhs&`-Ki&~Z$DO5K|`g^L9n-YqC_8FXo#Xa0_+wC$t7xcqsy zvjxdllmeq+P;@N**6mb5%LN7BugL#ocfs%h1^M#|ju!~)iwlhFpMr(LqWVR%lq12S zX6xL)!K!4bt1rg;U_-(0(O368clGK8*JD?&HcYr8oV~jGovT+}j$Xa$o%FMB>!b2j z`>k)C{ZI5o$8*Y6qaiYW0shwQ=+)2XoOkZt`^~Vco1MbW&AWR1s<5i~s&Q3iV0IKR z%4AA53`<-rz5>>~%CIO&RE#Di|0OV${QRGU{IvS{`4=62&(D8(Tb^(}f8Brc^IcBl z=X)Q@|0CEVQ^_|556C~{HsdwyGcg>*t_&CV6ZtLY|1PXaN;;gMf3WrQSLWv*&llDf z=Ns2nhGmOmq+@mdJ58R+;{`CF`kKY4Dxf-p<7?SxEKwj-mTaZa@piNC^9z3#3imf) zh5oI7C_Lp;Q0RUn_ucmj3thGp<}@tKy}gb#?J?-BsLUn0!e8!` zm55icmlV6lO6*+E-@T8$vk&vjOT-74ic8ET;`Ji@K)N%xv2>ERN0I?}#l`|n$S`9)Y(!4;SmqB4Ik z#^I7X*KQR(wkYPJN}_m-9XSu%1}7_1`E-u+V+>0}M5D2YjKUuusJTyV<*0)fc8QD} ztqxv^qcPIMKB#m1Z(Cj6RdDtHTiP6}G_=q)mO);yPE4ShOH%({J$rWV(!N#El^q2X zH&*4kbZ-BByAGYY)8$G&G!tFrr7c7Zw= zKWy@%@KTe{A8|pk{Qn}5=kVEn&jMiPqB6-mQkcoOeNxzf0sXso?X0vCN1U^8U7_&k zAs1J7u8d&)@*kG2T>G>QD3;)01QUwsR5jDg;vioP1_+?FrV9PB+EpD#MoPk`}+EjT~ltnBFL{ISa& zuJC15%u+QpPMlD=DUYGHlpf{1CLGj~`a2HsP9z&Cjw>c4(VaTBxit5u-#Z3%8c=~` z%G;qKj-~vIW=HtnkgQv}VDa(_qf{UfCNW^KBPOLw(fEsx|C?2wMpMd#bT(2r zA_L2~pAKE(`_uX5oMS_Q#i&{(xE(v}P|oG00W1GcSTJ9wMHz-tUd2HbP@-*vvy|&C z(?-ry2+H`lSiV0ZVh4|%FcMJgRVXQbMTq0_QobaJ?`WaLtv4m6zm44!C(dlo*{=CV zh%>_=Y^FDXz^WEacWHH$f_A1>P&EHUMUBx4%44oOA92G15HVeTD;pXXIwb#(Zjk^% zBL*Qm(fyM*?p>+>$$O{x!`E6|uN1O>%a8C*A!anUvFWA;ELgC9HWpmX_JsJI4sIyCi>pHK$l8cWJ@Wvk?QUJVe)Ha=(nq%_J=?_Z%-LCkc&t@d zCmzWewN--XxS_*_qumrWW@!KMN!K-Lf3G`#oIOp_Fc&IWDYjWqipB+rw4>gUW`3ti z=BG&sS)XXRZFEFO!}=q_J3^$GI1M{r$MLat(NU8UtrB-_&q_($wQv8SjPu`{+!9piFYaA_Bg!6$kSo6l)?CY;HYh zjq0SW^jkwQX56Ic$OtP6;YdleaKtM8?D^dM+eHsc&Da8DDJ!u_$MlGe6Lmw_I79TP zapR03rQ?jf1@EYFA)ZIaY0`C&E>9J!mrXT;)>kLf^8UDJ5E`-oaSzm_XUN3-hlPu} zo-EwCN8RvnW54j;0p6xiCA?mzK%e)*`_&2W_q>mP*YI%fR=#eX-ga&ru6^KgxCTf7 z!=fBs9VD9HYmm?vnJ^w}>^4ZISkp1nvmjya!}{0Jz4nf&|M#x_`y0CSZ}eHe=UOZM z>wO#0)~;O_xBfjl_kXtu{^rGAZ`*&?$EmIMfy@1^HkzzuE!y<*HwS6tS~F4{c4DCI zIZ`#!Ws_6WHtoLu_UkV`4<7z@QT6!#{Nv2YliLe11!5iQh_C(ky$+u_cj%!1rmeow ziyp5i9qN7J)8S>$uU$HH`0k_ne)KmT{u|JtgU5&32QGKe@QHC#EYGqR84NB&2Ncb_ ziP57Yu>R69`?5)Rse;r@c>8{h@Guo(y+vJH*4z18m)^Y%9lHphef@PirFXq={CoFs zf7Pw`XKpRtsY`#;`@`pY_xAom`@rSiU|zK4OKo5x&Ts?*C-6*t8=y0l$aZ_P*K-|g*tR`3k@~) z3H5Dm4h`)1Txe(qu}bZ@Y*iIJ#*L_$C#2YF)l z^eI@-i-ILpkh;c|=u_B#Ws}~VUwomLY$`H2ACETu?_9WPUb4ybex6Bu)aI5+3_W|k z1`RNcVq-|krHZP4G8`xF* zz~!;e(1Uh`tBN>PC^Bn0n}wqg^A^mV5jSBh7GJ^<6SqymFmRzE%w*sA2@?x{ll1BE zL2`yopZ!0WOdqu{wJ)^k^T8)I>4OQ{{b}O3IC)yxG=1EpX%i!IHrJ%89_>hSA@4- z7R+hiP(1oRdR0B9bqBG%=7%*0em%Bv_M~xRuw0I?x@8jjf(&+7pk5_1*h5vXS492~ zrXW+F>rn5}o=;7ywwT^GnbOC+e{`Vfc-n=JnMsd`>nK@F&3Z}g(x#eBH)p-y+!S}{ zf35S{o6;7TLdo?a1hMU4@tX91hc=Y-Q_L8CesIf7M78A-}TFSVlwr6_yIFDIXb~)+O_!o``?;OkJ?y2O~Y=+ zQPZJGCey;*Ce!%iwNNf0C&8v1t=;LKr5uKpGONy{Z58v zmFVgaXeOFF0Q&d0XAFa8NCnK~+bQe%hb>vez=0hQmSd%MCdw2YC1^J9ev-*F=-&I# z?3XB$Y1^un%4ejR_0y_m>83*yO{SGQOs2@w&(iF|U*xviDN?X9j17~5&Fb&6;M(da z&vKu?WKGiMg)=9O!;F~RS76e=KXl~4_f!=t(clUdV^5g+SX`R}t;zJM$#l1a>D(g4 z^g43kl4~tV!>>zQm_CjE#MJxZ*H_`TTVqY{zdt+K)FQW=>CXwK2umCFA9&6C=@V1- z1XanP+>cGk@ii+6E}MUw=kQvohOWH2juua6MrKV$7SzVwO_T1+;h$OHz44XEb%kmz zuU$?%*Lt(6+Sc5k6HKPgcrU{ec+X@?IrA~OW#5JHAl~uQOWjP}?sYar7GJvYb<3Y~ z@8YAwujH+SO|*Y8@AsVCpFf3i$hSKSul(GyX64GbQNI6I`s!8bW~-WpaWS--LHnus zWCON>Vu286X>m*$`Cgc<%+X;o!LTLYi^>*lSDHR0Hip_g;h`O~^G#UuhL)9yd*c$5 z?o-nT!v8EL@#7W<*p?qYG>Km{FENSlf2H96K9)`Nm-a0`R0H+1GLzWib7m4_(yC2| zmoNT#=Ja-%J1hAoQ#Y(wlXC9DdS>|t_#jv`4btE%vpL{{9ZZ`_EOh+X=+PrbgdzK1 z2K36rzj3i?ze${z{Lo}KY~NoIHNz=dw)@PjhY#=ExVQdRHE`Hu%-yZVtR4;44zZR) zJM~bCR5W7aN^=4Y%%?4jO=9Oy|EjLmS6HTGnb~|h|Jt?O2YZkFYbeve?9i^l&Q@$S zgJHr|C_>YcK%r@I^_0#g*rjO2?P8pdzLj5eX$!+VO&vLWyd8xUZ9k=BEm*Ia#%I{0 zWYI>R+1TYZJCIgu;15vBX|(%O6Fp)$h14_V1r;JUWM7l+-z&O%C$C`Hy&6TL9W=|X z8j(}c#v{9vw!_0}A#&@!TLlk`AKojzaeV3NCn9+a|C^G+Ol20vi>f2el+ZQ}=s109 z9GmE@u1JxmA@C<|C_R)gJ9ILueiD>>>Ca!!Amm-{t+;gO@uPe93pd8^+FcoxgE0 z_I_cFV9Hk&u+xPX*X5l}T%TqGV~5klDmzjSVS+y}0Kwfpv^gE|roakQF(H^d5lhnG z+T?Ih`0QV}Ys!kGBT{J?=dAqEeH;_Nsc^lqVVyUBF67QFxARADr}8;{aU8|M?S6Xu zm)`);?RpIW&D=RHOTKv~>Da@+mgg?35g*4MdK`38@d?z(n&fJQM+-d&55SwTVDX}D zO4-AryH`)1`i=ia=q{T3c2Uu>4l_9~d(1BdTDUkp_{=|JJF~TH_rX7Q&X^fJeQmYa z#3?Wy&8n1H&)cl0&iRm}w1p@#A8}@6hhI28Ip1;Rog3Hw8Wq{@?JP0*SA{n)UgYur z;l18_Z7t_-tbQr|+ShNj;{0OsH)Acl<@VTaj2l;t=AY}EZD!n*9pKx{JYe2?F*m+` z+jNru(PHrn?_Fv2Ts-G{n>OFVCoSfA4bSl{h^R)5`jqfh!#jV$-L6|Y?3SvFk}H?b zVZgu%x8svC*Uw5kTfA@VA2lobBJEMBsw!=jS5q==vxF-`Izd%^%=G#5rz^kd|MU8P z|CcEqhbtNwf8O12CjXtCc!_hjUJv;AaP(4n*PY5&hk47OH%l4UBY4jHS@^rLp`5pQ z^BR9}mCqc&e=){eK6~YlKRgxIF#ln_@;#sNCBE}{>yx<+@=DsS%^<2w%bqy(KpM#EpE(b^y7SUOFpMJ z<92RC+u$CGYI;DLH*G|$2F2(sUp-{ICyLEnx@plgb)PK8(uf#}Ri_#A<0pk}-JSjO zvP7opB^oa>?r`iA;$T`~Fa;fsjWZGM+I4Sw=pfU4Je&Xb#Ln+?4h zL9ckyYiC1t*t3v-vGu=YejCtq3g$fFBm67UYxGNnwbo0V0Pdyj{8ByE#Og6R6g3OG zmsF3TsW)r;k%SpIVMFIZMo^v92BA3Wbop=M!2=3cmGWHo89$+yp%mv2IQPH6n@v;r zYe;BQ8s8aX*7<1*$6Lid9{@Fov&)8ce@_b zthk23S11XWZc8~5xyx-L`Y&|Q+P0@|8XBW&Aku(SX8CJcO`Q?Hde55a*xwDUMhp)P zq0Fq0nK^%cocx>J>68Vt#jUwk&AQxe+%)Lz5vpckueKP%`MEb=Zax|A;=IoXrIf3? zznS{GaK1vdoWR$jythB`7~k#pezSCbPB_75`(wBc4Sb~q*@STe%r)rq@_W_BV(wqa zEM=0h@XGO>iQ%OtLgek*fC!PK= zdCBZ8C+^_VBfAIO{0Qm1v_$6O-Eu5h-NThadaMFG#9doDTzyi)#m7ZgpN&zLobQ~? z+P-Yz@}xg6EW2y50_Ed*j5q-|gb9;moG6@Xo~A8S%yz{lbM3qlQ52AVH)@;F7IUjF ze&+VYzitd$yz>|EtZJLJS5)IbaPGXs(;63EdCn$Shx;?=xGC}N|K+!0V~Aam~Z2|$@@s0ED4OsVtLUc>7gW+TTV+=g%b&tkql|e zFt)wTucOL`ufS5U7>|R1EXI+BmKKEnAl@Z+fsOTET#0L$NWPI3Nz!BGUWxQbvb(3S z`)4G1yilP%pCTX|2U6EBeh#j&SiEq-JUZ-!DarI1*g7+L5}V)@gR^h7M6fKgf&?$P ztRWC_b(`d>lt{%E^Fv80ePmW1IX;vv_av!ImP?rAS@O87RFaC!B}#db^_whtJTlAp zDLyWjSie1%IIaOjz{Fz9pE`mS5ctM3WJxNw6g^-K9!q8LX1Rnrp(I=>`aqGS`|P3gxZL_p zmOSwn$~~#ve6L8kZ~cb5fGT0f&08?LC(J%)!Qz!$_9Sm!wPgNW>~@^Nrg=WWUSals z;^npgbh*6XqK%g)ZmOh&YkBDdrLba^Pi3deLVrg_PZL52h2LH_OH7zWXOU~j7en0yb z?oC1*t5Iaf9u>>%ff2TSqJ_B_T0E9;pQS}MYw#88H@E^P<7KNFk2EzNJyC8j5p^GMQ|9d9hF$Q9X^C_q5>yUcBBz5PKr||J%@eUv}_2T zIA_V)grkRctX@j4p~?A_DJ;%y;si{x#zot5Q#G@bnw2@YktQG8r^H1}UQEgqOTxW! z35E3DV@bR(Bk1lU1tHob3OM|+{Nck2h>q%hZrWRp3e{xhjM?!Em#tj0X614%38@(4 zu(1aiv6A-$2O;pjHmTCD6co6 z-p1Vdi|C@c`Pv>8EJA6=g{`nK@3gX;zs)9UL}e&Ewsh*+bGUx(?8@IYR1(aFl6Q}c zsC|Eehz=1@&xJ7Q;ZM5ArvdG(Mr>M_?`UuAL=97f4bxN1zXnV;mdD5GVTOrnl~7N3 zLnK`mNGCWN%)(_8s1MYDpi_+0-%*!YajbTD=&<(HaPt3?M46PFHXXeVK1+v23!CPP zay|vDlXgg>zk_4iHh~llHm+QgFl&>;IDx!85!YpE%2}p4gDa?49TRCFNmH;Mqe&WD zMbh8-YYoz#?#3Ds#5TD&?n|si#ElEno(DyPHHj@$s0a<|qr;>?oiE>4tK-E*o}|Tj?bkpo2{YtrzLf;hE)+y=Z4`8=z8f0ND(gsB8tI`V z?iZpx5tZbromXt$)JDqiXYb0e5+CkTeJeEDfLqNmV3Y|QDaeI(>EpNwoQL31raedQ zgQn=MsF`{k;x>}@!3-ZaC+Hu0p%tR5?}bJSu&xE24>rjShfCsAx#(~}rg<8l>O&13 zwLEA-Fl?@N=^lxbm zcd54P$)fGZ-f|4C`IzL6L4$yrG8Gk)Yz!cFnC{?U1}=7sb*G~^bczng0mCSQt80DM zkfNT^*EB|trI!V$5d5)gQiU+t3IVJeXjBN^Fg>zAVL+zBW~RZdAFh+^O)!i8CNN2(XdJ%vU*H}Fj_C%zrFPR+I z;((AvV71pO^6#Cv8q}?5{*7U(pRuL{sgOt)x3W0eqT6uFG&RsL=B*}%PkP(7aL=#1wM8NWySigH@PQg)nSnkMkmiLBi-J80y)FSp8YGbyb6YWs)I( z-^OVn6U(beMleA(Syne;B5W&6mf=D^B@kR=G8M;4a%rNZDOvlq#j7%?iEMNukcs&rhNGKo$v;*N$X%4A*KWV8bKBrm!phTMt?GwM_5u;8KX zkkV?`B~m2!M}Pf%_{r+eoy#P?R1(m&xg_cCmzESr_M^u{q5MT^K(Mj{Q`m5@$wnMw zB#OXdJ!yVL8C^Xc0U$%#*31PUz3Ph3?VBWBmR!ppNslaM%mHyB87?W8iX?{;YKT0> z48hRhk2_RT@Zy}=>ZEb6_G@_h^9=Ie86&5Vd1uML?bv2i^Um*$-u>@c%UX} zxF!+-pP=D_!PFE`8-vl%aelJKll*HXU=J0^5x{U`H?@zrT*(n3Q28Luq9Zdx^{EiYFba2wpam3$^7Vnxg4gI6o-4#BXn(W5jK+?(G4gmkxI%H zbOH?2s8L|?dJim;_8CmCZCxt0Nu_>Vj2I(F=^~@m$mKCcv;gQRGKS6M=cgb;AwuZ> zdi)q6gveDhBdIZTaNFz?-0{)nBS}d|E@OXw4a8lMT&k?n*n-6c8lj_yPMH~NhL|p* zsbqH_eGVqMQMW+COJ2(1pE4P*yQ$E~plVd6NM85R9@Kh0XktFrKFuTSM@3>NMn**| zI!i8^^aL91<@) zs39LJQsv?xTRkO~KcW#(0!Jy59rc)0trW=@uVaubC3x2ZBCSY4YpSZ7(BLUj9zCd{ zmHP3&X{E$yI_W1(gidl?pw&rLGzzQGNY!Tbh97>|uo_y4$G6p}QRUjBjU6ZW31Np; zlo^iDtBoeR2k?_D>Cu#WT&_s3VU#~WN09U(&lML*nwuo)A=++LG{W0ZBp%@~YRnkb zO$a@Xwhk37j>c_ejfj5Od^D0)HsPc1iHA*Fx-ow650^?ybC(6r+$heOhDF*+$98Vv z=uR;g*pX*1JHSEXw6bTwip{L`)->T{d2kpBPyp2IyNUa&a@p`&Hk>=5Cya(}n)MC^YqSu25eTUc*59M2m4L_d!{kJneiw8HzJfNE6M_5yS zi{t)LUf;R`zV^-Q+`_vqu`Q=-OX~qO`Nh_gavzDyEdiKP)>zbO#K)_I7-<-2L4)ad z7a>L=L9ehn#Ce4H_cK4AIwc+eVt*BJ)niJW7Y25|E^`O#QudcK748AN)@5;ZiJaF8 zFOOiOjH3ZJnyLm3T^QJg7C-?PXo+i&tE1k4MWhRpxFI(C-mnzw4*mKwJ0<1-Y<1_D zuo``Dj2AX%I9L~`KV6`qwJvsZTKKLdT7-j&HYyTRUqb6?Lpy;QGpKDqi%Zd~f~^RK z>o|6Q=(KW5%m&s<2c2HB9dzP&F%a*(oF6@ITX$ah-hISE@C2@|V%uvA+D&t67^1dm zgJI-|2n2&NnnxNy-0-pxY>pUDtd^z_xaE_$y&o6_;sDo7-~b40OB3Xwnr-c}E@8!~ z*l-AuaPowhvD!BN-uv6JsBO=G_Q^xuzN>9H`QbNiZ$i_ z1aZwuEFIg9Qt9ttQ&UknttDfjxd>ZTL<<(Gu;h&Yl$Kz%{b6a1Se+{NkC|m=n-`8? zhzjmwG(Q17uyLMNbJGD5m^*lonkrn)H_m2nNj!QfIbre4 zWvSwC_iHGu*xgWN7ulT~6)=X|Ea!?85EV_VnC@#wss%O26&tZnU{G5I35&KnQZWP! zkg$@o$?-Gy{Cclu62_mNN?7fn4<9*Vr0O~mc{AF}3V>XO!i3%`ek1Lxb^t)|B>GsOV;#}>paly=IveX5O%(|UF?98=Otu9#tZxEl8viIBGb~;e>&& z4;lE+5}%^%l?BqU;D|CB7Nn&Il&laMGZu3o2*rTM1#zR;a7T5L0HNPfzt6hw`5#>S z6u-8LH-rzziL8;}A1VMlcyEj{-cx-W0Iq{kD~c+AEQ{8o1!0vR5&;0{VJT?#85pa`zL#RkkJ9G@s%wRrcZ7_D+*rq>>TjZl+3x ztntFQ((!fC{U9QZp6VE?8IT-8Rl}xom418;l2HO}duwnsSvznL5;k1HyQ#^?luGSJ zqi`u0S@aelk{cC8oQ1Mh#Bl1QB5w^E*uS3|T~+$>HORFUNawK7Fzoz8wu(T)g0$Bm zjWh#oLcYL%@QXx_fq^lEk*`7RLXoKk4eZxf6Yp3ol{>{Hyi@@8bgJn7kl)~2FEXjmu|95HgF0*fl6?INSbL^F+P zjeAZNN8LhbM-2tiE(B-ypB;A82BrC zESg3L7&a~tGh~<)m)NRJ7(~vnkRgNMK?pp_ohoe~7M9f@@2SqAU2sTfxH1BiXC&Mt zj}k{mvN7n5lcr;_8xN5yj*WtkN4bqa+=LAqI%Ei>_EDu)>Z}WEYmoYk#-ToVSXdae zwgcZn-l5SVL@JPu@iI<8^af0rGG~Vnq_}R9bjKpuWxSE|BM=TX1P>cFJUpCYgsXWR z{0^p~_Wjtp(PJkpJGeUz#}Xq(j-cMGO#;Xeby?-s;xYisx>d ziIQ|PPdep~{$WhNOF*Lo8Wtv~AuC3ps#HSbg!$9dg>zye!4}v^R}~FHwN_}J(Khrn zoRs2Tm%222d7&h|x}edHUq5@z*`^{TD zrZgM%+h=dQlO-K#KI{2rr@sh{lccRp{<}gNGfVot{xNAq92?4m?LxxCU{xgSQ5IDT z2Mjx;GPoXnfN{RKLkHW65TR=D4^{Q({f}0CiioII^)zH}tUpmYd^fX^B)N9EB1H_A zT<{9gc5Ci@nks$LzG*)CI&l0?J{GBQa=?HL4h{(k4P_%7Mlqj~6QXfk-$UFlY4j6GC3BT2iQN4wmRZo2dt`1WY&lOZ0NPgF9f zDlKGEy{n0xKb3OoOH#KPa?`z z`TQ)=xFq)ksJbkcq)jibngm@MK$keuWlepS>UduI-^%~o^jR`ka#D2}h9Cp~8=*tR zR7R=eSJMdUKq0j%qo9U|(~c8pguK$b*Vm*`t;v^Eg?y>uCXzm`i$0bz?FylfBwdjt zz3&O>&GG0IBF&6_;UcN?mqVU(W%V`5rcqFoH1Weq8vW^DqYV;TusgFX1jFQLLtIANIg}Xo*q#<&TrcA9VUG-f-O`nS|G-?0F5LKT+ zO`3nwN0N>;ed)i^@Q)+~y_-*Yvt!e3hlQUi6x!|oa=7Q}CoYmU`n>bz4(XVXDNXXd z1C8vV(J+jla5kK>t2|1;_|a1{D2k1t%;u-f_An6%3s+mzG(+$89$?l4D z>pIeE{tYb4Tr9u_t28 z6XD1)Y_yNcx`Rh(bePPj$%Dnp#=~>ITEMLtIH>2s8u_ut}sQiZVuwq-?5b7)}B;&OSgB z_^-&NP2!-zgB3^|hDTw28@vM&J-_;Q?9w&| z8#GuRQWriP76R%|Jcs&QM5;!O!dp8cMn$lZ{`5yp;xG_(Bq4BhRpP&(m*w2vwiIQy z%C;Lcc*tNjM6XI`p-xumYKi?fVsx+uG7hg}YZ> zHM;P?HW%cBI4rIoIt)H$p*;Mx;V6})_$b&K)<87j(iBvB)dCd4VDs7_hs}YZ)?|~r zS6$~hzU>JHaR~h2LLg|I5aR^h)Il(d5J!%}ARaxEykIrM(7~Af_v@p%{UonF$>i=; z7iMT(M#!&vrJ8MRrjYYNX7Y||7#6MrCYnQ9Mv9}5R@f*X%x^Te3{mm)LuG+$ruhkfT-FMPngDp*&o!V#y! z%pGv`u&nB7w8Q+yMdKJbnU^|F8eG-9wdICbt-;!dy|(sopbGFR%O6Gnuhseo!PX5N z1S|6)JXi_g;XF(jNpypaG{D5s<0oQo(u63SOGaD4I#Q9WdVKk>SRim$UIoz%{$wS@ z-gcv#(7CotA%&c&z!ep^FpP!RQ_aMng3TLZdPx~~?4%hBS1g=9F&eiZXgxkPxA*L> zqOUdM1NutKA{zKgOCv_>(n$RlwO$)3S@hqkxe^c&HBO*@#9X)gm=|Ow6>U zKV3h)V#-)xr{Koh5m4xRb`NU#?|OFDH4=MmjU;1rm62I_nWQPMkE``M$sMlm-?#sO zL6*UUKbVCG!<0}VOddg|M^TNOFntH6)qAImi_qYsVbiBq4;%biQ#sBvT`RAWtXWC; zEAE_AxPjMVrQ{Ab5?a`s!o>*&4;hBa5E>eWSw6aX^&&<`#!TOmFBK$CiH@L|0lMz} z`t<1yz}-}P*Ou3zGFDwA`RzUdrkhGsgCR#S)JJ8Q7>e@P7!xb1O|%R)dTiW+q~ob` zW23P5k%%37Kghk^y9Iqg4zDe_12M2IkJyNTeLu8M5NreGLAt?1g4wX9YEeYEf%A;>v!=yHkH#{`P#WckHOLOqWY?PKSv56~zySlzgPaEs88S>Q!Z5ZnoR1Jk zV(lkzbkw*BI7NrIM5)u3!RW2^>eWM)_OD2uRh-zTAL}nboI`~;FpuFJ&4&6gE?Qn{ z^AH(K?Ils~5aXzOP}eX19mlhBN@MRnef#$5Kfp}Z9Eyu};7Bn%R1Swo%%Xj+AXN_=l`a6Xj>^4`YC;Mh+7$)iVqPmFX1SIdURaTf({Ra`!JCOO$Lv{ zGEsj`SWwr_pZyyy_e2=$!}~h)p+Fe~+RTQa^@M@VLSG1>E;PC_;WR7LbQ=OwYwE#o zR*AJ`Zj~k4_k}SBKpq?PCLRf5f_^y$ChBJhT9y!uU!>wtkTjyIc#T-kp521FbRi{c z&D3lnb-nxahD{Ni%3uR@7(5s^C7DBb7!NmwhLO+^Hq?W9Xam4}h?RE_>H>S#NWyFn zckbP{58mN|(11e9U~r6c7uRgD!_Y-{d!yaxZ(MfD+iN9sQnn?NHm(}P@rMM zyj8|d8i1ho=+U!Vm(CDynG0u>OyNvnO)E$?OX+*{2Csx8`t|M4kP`V|XH}Bw`;aiq zzeAN_JeUvlgbi(yx?5F&q)eqi$gHI#*sHgU$kz9x0>ChkFad=w!&GnJe=12Dpy|{d zHY1~fy0bDa9@wq?!FTgyz8mkyIe_b5OU_}B!{LP5Xe#!^Yp*PQ9Qq;wTZa{mW3{Ur z%!fH*h#@90@gK|vy7fnmgh?U3YnM)+X5Z#I%hYq_+&u|fZ?NsPysW(R@uNp_qQV_- ze%qvV13$Vdpr$1qYsND4=-InhZ@}Pv*+8S}*TF;NU?GG7f{3X=Ffa}A#MB-+1Q2@k z=oSPEs1Wp)kt5d@SpWjN_X?%Ew{P7kynUb^J@u$cQ^Lx*{e6a!TK2c zk~0Pll9AMuV5~)A8VoD2VZQ2gkjj-x7rJ*NPpCKq3md76%E8-*b&17yXpu`YFLY^FjV)Rz(|JT{n z#B~9jPxn>ULRfp4u1Um#a+2BFCV z=TrPPaIReqLf1d9{AUYV;q{`z)dvtc5|!&f^Ecx8|*uDu$E#GZM}O_ym#r` z(F)OOL-&M-H}eaCE-ybX|Hh5t9l&@@IHuXqQ@iDZ)1E2LGn)0}bj^pMP`wtq7B=MF zc@Lo{14#I}j~$3OrPG0Ew~~K{DX=5u32)>cWP}Qkoh$5U3q>*Uj(me(XZS4^(y)BL zeHoX3q!HnzUD=`Sm3qL>)#bRe0~fKVbA_5PT1gG>uJl0iP>?0<`VJTXfDTAsl#z!9 z%WyFtT+-I0K6Mt27LPbHw3S)cI}47 z_unaHeDT6x=Pz8! zy_T0>YnfvA9!#|*ibg*@=up1_T5^GB2l@;Six`SYf>j6TUCguv7;bG zxb+)=zRiGv#KtJ38J-@yG(>$mk!LMCK%3e>y}Pjo@;GcE_jXt91^9jYVff%n8R$D; zaOiNF;*hPhV%veNRXYk})1s>o#Jbrs31t(8R~hP%E?7Si^b%@_1Ntii9M!dfUL=Qg z)^}*%R+Uo=0#ii}>u%^tDp|$YQ&xgQ29OwG0PC;xbGK>JnbH8HJcGRG9$dm0<6JzP zaF>gh9@mu9tq_E+mLT5Et~&t8&{7ABD*YM(0AdjA3}aj^*94#^m;>=ag79(0P_Kr- z7;b(2#y9nsVpxMhh;#bh zO7ua(QQh3TH|xb!yAm;jo7<^&t%>`H>z>24c-y`4z6Q?S=eTTt-0+z75;okUCi5nL zzWg3Y$?7(b@*7>^A1Cui0``vLx;Ax>xyFuErc?_ZSZAH8g05Q+RR?<{C{+ig59@F2 zhd9NkS2gJF3^yQ6KGEQr zz{f3YU*a_DDjtJ=Rh-gHX%6H(OfV=I1K!S%&X>&EgqeapD-_)qx9J2(#+Ux6Of@6!d?Xl$ib zM6qgNe7laFI(24US&)6VAS#SKp@Py!=&ST`>fHy>k+F#V_jJPuP)lKlcJ11J|B*_a zpUJ3fqjCqDs}3M8z^-mH#|X9X2DzM1AIN{`%O1b_D{s3*38&BjdUZ>>dPy2C>^fJs zCh%73FLY#`bX~eq_;*EO*CE?kdg;+F=!>`IIG~iEfItEG0?}_zu|p+KX)6+bTUvRV zaozgr&9Cb(MPK-}IxVhS;cGXd5&kBDFMjsvB`&pi)gL#d?e%|Yi50)LKV7>Cjo4W& z6~L>lyUHs1o>ugIfZm{?XZT+N?_dSrt}XjsMX${=tK(z$sa6PgN@?HuV=msr`#r>a zrJ!Y{X8eqHrPGaP2$UkZrtr3!n0MrzcxR!D(p877Og1KzBC2#B9Uu}uZ_E!7-QBFw z-LCC-ZQ6YFe`07AGFd0qnRn554GQW8nPLwFrLkwPKJY9uwE&p{5`qVjrXUJR@FocT z_Cs)|+K{vgF-j+;Ge_(*R3<9a3Z=>32DK<+6c|w)X)>mCb)sQQGFpG|@A;Wk97C`o z)v4i1Bt-6IN9=(0=Dq5I_n>!+HiAY3yLKj)+wOZ+Ud;^3_V5nmD5bMq*Pw0~4yd5? zZ1nE&A5=D!Ro@;o;h;7g+5~C}{TGkt9hmxf#6ge~*aG~bK3?w0decudtu1{8lS$lLtf$FNp2XR5NY@61tnpaAd)i5wzomxK>$+enK%uV|Nh*}Ahchr^ z{e$p!?aVqkk;#C$m1?qQlPdzfHuk0C>dV4jvAr#m z?-Z*_o!a19;%VP7?o{cdUM=vlwuHD{hmIYTjsmimr7Ktzvav%DEKAWCBzNU7txE^W zz7&qFtyrJcaZ)4VsK*r^-0tw+x!{Xot5yt#m%GrXZ+*>d^N4wr$%X4my}oWf-uDT_`)? zcL3D^&^E1NAq-&FZ*5qg!GS8B$g4zrO7DXLSx@3^uff?BsPrl-1``r0DilgraJ8TY zs+;j28!&)shp8&UQv;?=;{Q**slNp7b@LW1v@B8<%ggu*yX7lZtWws9YuC#g_(uJv&0Dr^W!r?E z%64&Q0!uXR+PynDB{^A1;d{zc**;5Jd4?skBvVNjGUarZQI=McD(*?KBlM)k^ z1l`W`8b+vE*k+qP}pwsZUTojVf}6L+b& zEGfbsbE*tnJVOR1bJl|_IaA1B=}LwrjqNK-751P4s{&u-+n*9+i#x=tB$|di+x%f{3c8XD%?3YbG96BR52}F z%-}@A#Fz6GY_)OCy7j=cfo%k$t@1V<45cIpyUcijvb@KVs_c`~$VM!kXDV5i{pI`1 zbAxm9mGYI3}m;PDt3bD=}dwP}ys!oQNAuUceF&8j=-})1;oz5r zk7iGyx8~vv_VIRjf&BuuP*EYt%XG_EtYWK$HOg9XJrMCtd^2I<+ue62koS_4QxH}u zDSO~Pw$BVZiJALLavtRH11yK{H)q-H&&teHGIW_4X#k#T*<;)bV(1+PDtJ74)hS;!U%OO&MyvBg&L)%rE- z)~s2_5c0xiGXkFPWC=o&yjwt|TlVr)4qMsnOG`_)WC&T0vV|Na=U%pe&|+CUlV@1c z1z=)(%_)4hn1ryuD0tXAIy*Vzx09o%qy2y0g9Fn6Ne=Y#^J+TeE8%(EWj|xa>{+<* zc+MOkVnD=!$gq6bvgONHDXT@`S+7Gp$y*o@i96stUE=QDGTdj`Ye}^SoPGG6p=25} z5L4MXIhF&K91e>;&MD1iSxP2Hd>J#+0XuykOV#g7P2CHKLNeRUcL@oX1kv7+IoUbe zJ2^2IM^C}C`RiW3fq?;8z-b9|_VxZEP1bZVwZ>IM;C#8h!MlmtSCDR^8aTa$V==0=??> z?&IbuH*@B&1-c&=0-SO2!o^D# zFQK?wVOho38rQ8|zivH7#3r^`*rEU-Qtd8bcX^6=kNw`%RMo+9mbgDl-mlBa&bH(T z*>cXU93@-8m|z(~x+T@PZ!f^@LH>YWli04y7!H0aJSSHd7dICdS8u@+iPtx7uS5cN!cuHL+anLlkH+j1dHuqd&NC_ z$y;_ASpyvgRCGE-uB<7@t$y{9(H)rQMUT(tk zAHU%3S2yr+-JjHObMX%h@Ogf4Uza+O7!xdBKX3m01@kQn*dn&rW!dr-%a^ZMxpMWI zb!*qk>jdO~wprY^9hC`1iR}`S$|=k4QTDQZVp_VK>4apFm6e&be}7h%vY%)1{g#~a zoV)vlEK4R0TQPl~vR6#qOZiPs=1DrB%vIeA!)Yj;ThgQves_HCMr?_hOW2`16NGkRkmA9 zPO(Yn2DjOAa@8^W~AK*IS=>qOc}sBRP;PJt0sHWN4Xhnq&@b>K(@tmRS0yYb;tDh&&XAAivkqRgZ!YaO+ zA^ResY?L?gt$drXUD?SK%}EHFWI4rd@4obOB~47vC`HjM&AyxcI7`gTFlX9jsL6xx z6;e<*cFRdTF;{RfI>Jf>M**5TUO?j}H2k2Ummi^#19^ZD$O2qFUkvTx;5#XPX8fG_ zbLYzQ1PoBSg^Ly~R+c&}TfTA?%I2!o${HO;0NY?#53;dkD`qGOpc?Wn1@Xpcm?GF@ zj6peF2PiD#LDsD-bB0}dS~@Dck|w8$d*MRe?xZAT7f;9)1Voyj8fh+000&EXc=0qcgY9IA3XpNoAD5IpG(OcKnx0mcA!h9_&Qh|J3`84#>oO?vN-;*kJ<@dP8Av3C zy?gfVN!e{l5_Tzx!cJgC{&mr?y12QLSDB~LOYk(k=Htui3V}ajv_7uu80hWaYqY<8 z@A()P@*Huln&~)(tFTN#!0A@4S*@&P>+Cjc+_aeiC{F;?1SJtsy-P{9+l{iy_A(@5 zF?C-Vpd!>V1h6(C4H+a&My)T;P*CsbBP>~1r+I;U}qGJ8cTd5pbsj06Y zt9uysdl+c%{oJ52K90fjsGhMo@;pA@fkq3(<4R&Fe3i%QRmg!DFPk=P-n4o1Cd8$T zxRiG~fuJQNB_}6=L$PGLlszfnc%`6HEKSHz(s@Q1c!H2o3J$EK3NWSuj2y!TpGyWC zNMtamvi+(cJ5i<~Yr4ACkv+MWvyZng26yvDJ^_I$&_{tTby449ItkCCzEQ6B!%IBp z%$>hLCB{IzVl~p=+SRK7T3Ex@T0r;MR%M&G9kEIL03%2bx}K73fmzGy z-vCK9SC^KW_87KI*-PvTe4QZ`XciTAGNgU7s?pw2apKN8U}bJX9mSJ*aUTaSUq{E+ z-wE*bFAThZab6tonveH)ajywq#ZR9;6BlmdopbT?=FP`o$6Fp2EndEM=!tEjxJ zSiPF44BH@Vv~1>x0mJqk#7$+CK1wfacX_e_1Qi~Zfw(-qEL}*$#0TCtB4_VG5k`ol zVuUB-lge%dwHS6y;5!W4w{G3CWwQp_MRBr68n=e4T^$cEFN?QP@OZDOk6)mY`~Dw z2^jNsRK4He{f0jNtnM*jD-Lw3>*v)huC?&W47}q&dkvxQ9GLV6^8dmW>knT&y=kRd zuaVmgtJkhuw*idbyvbgjvF+HoL)lrT=67*-vN;80qBPZywRO#MqS;9CY&BU>*ud8F%?1LvWs9;6j^BY_ z7Nk%Sqj;B$T)4X=MM!x}Q-QsxmNZkrd~J6!!U9e%hm*lXc3{%C4SrCz;^o*I@&pF3 zGD4K2Ofo=4fO;!F4t_p@`x`HKdif~6CwyXk9{4!=`glCoucxC+pAjsa>^Am=|G2vzVq^WsAyx zK;HcU>1`hVeoh&^C2|(W9qfF%Ff|V*1n-ws8!B#sI{_mb!qZ+pzW%PSPB`@ArC5CB zT)H9X47QIlH}0-@h@J>m?ql%x{b0i{$9_B#i?5s`Hw4juG;BwSgC41P=sYQS9K5`} zef<2rqmCau9E-1Xe3UsGT#;bh+!ap;Z!h|om$wh|6TOlTSU;Ix87FfSUEQo7 z_42`|>7z%=e{?>ye`Cj&>(+g_u3pAFiw{}B5z7GF6( z=Bo%SPJ%N7l@jVOPwwsP1q}39Uw?nE@bmo#$(Qk zD|gd-c%ll+UiLmf?dR|3ResQQv#)QXW&`)8^n1IZukU6ve(;iM!1(ol{qJ-tADy%4O-oBMHJ!K?g$ zYd7zPjT$!}*#G^;jT(A)Gaqp6`{wY8@oUmE*2Yg9{$^kE0r%kMD--r)pE{A5lCZLQ z@PPxd_{uo|)b@gwr`_Rj{POVd^uXg`5PH0wuOFZvaDBJ_3okZ)@uP8cVgBLcCx1SD z`sb6!56|n6lM{=toSXtdZv>O9cr-^udw41+F!p}_n5p>rd6s9pzS`8(;;Z)Edvt8| zY4g{cnzLQo$0cSTKYjM>nV+%~71P%i?5vQ0)ZQK z=nrVXbuO+bUT$9A7&G3!fzQ>i|6Cx#aKG#4Z++Fi?}!N#M-AxQs##0(e%HRSStowK zc=hVVvnR7+`$!iOJu`ji{{6A|%GnR_21h)e!KD~C%$15G_i};N zef{da{P`y@)eZ12&vG60pDu%=W-VJ5KQ6div(e@(*Vth{{(kY=&4TNf&K@2%$(-dr zXYkK|<>nO>+_?PLse$oXS+V%a$pU->;DZv9-R)gK6g)i&K zUDLnl6g6w*maVJjjO+SUx;fJ|W8jLvuHG!Tb@ST!m4h(3aNi%Y?EKZ6w{PcN`D=0T z{>;o+eC1>!YJgvTzU=Dl4n_yAE@~!9m>FEcSc8XlIF(GmDlCfQv9l+BM ztQnqwrx)D3x@+Vb{J{OdwlUkzU(e6K{@0dK+YZ>CuA0Z_4D)bjdb}q_5EZn z(d$j0uN&Z5p5dBxY{kH-%QkLWF@4C2W0-N^2kWBO9RB0aBkRYnqaV0u9orGNBJJ3* zeam8Z9778u7GF6Tw~+RA6^|#=yK7JP@e8P1uWmqqzh_yxbLO#QQzIwFj+u7sSf={N z<8vm@oi}C9aqAyXt(yD8f;lTs9YcFA7GF8(w*-58gQKG}W?qy6eB3aSFz*6zp!e}d zNMbB`l%_eRXP^A@!i7IiW`j0A>kmp=EWUEmZewCDJ95<$K6N~4wq$#vpDz-NkFRIR zK0|s&W@biu@l*d}*%ynioPG2Z?r7)i=m==Ct9zZw(7e6;6d%#oGbc3`Upc9_1xI^> z!O@u%LHM}2xKd7_SsJ;(tIS96%-I`@ubjPwf|CI{W1dN!Q0D6H;_9wFTKlY*;v=B; z;~(sa#aGUrLIAalqbafY%1NP*a!2kWY9FO2RzGUCeJ(i` zUpdKl1ZUJhgOiI3aJaZISAQ2*psm1*y5U1P7?#S}9gDA=-S-4HgJ8hFa(wcyL>E_# zK@VdEaD(;VB*o$@C+VJGwEi2ECP>ja(?75W2ZL3-RYhS%KhLsVx;Z_+`=yQUyPk6% z>=GtER{y-V%`WvPrRtwZ5_Cn*k zP3#)K*s$R(rn8*sE5sKh+Qs)hV_A!yj~#vxU#|W62Ft-Us(^{-I=INz2P3`(4_V`2 z-ee13kMf=RUT?hm#($({`nUh{`pYleGz&iqy$W`Uy?%ad)=3}d?ldQu#h-hX(@(CM zbIf^wx`IC3ai3 z??3ynL?{;86z>owmhKSS6ql5Ub-&tKl29TRw<)I|Tq`+OqPzI*#k(a>iBrvEvo*}4 zR~2Etf=BswW9zp+{QT=yt%_Rfzxnci@4ZxZ-?)9>!NZArmXzEVS{G~=T9@3nJMpsp z>V*4y?h9kg_+dGIc=dkaeev3_W%tE`vzGh16T%7Uz7Tbn0$L3VP$ipR95laxe~@FC zk1BVYV{6lAt-f!EEe6xemx|Ln$nEuQzis(Jld?jG4V$)Y-gP}>*X`0mAlN3feq3lc z82!1w_aCK&qTyXus5>c4C@<9A@ECNmaBrb*)iIc?udE#NA=yF=Y zQ3d_jx4(K}pQTX0;^i+txvCWEjtWQRLSwXZL%*hzZqmX{ad98;cWx5(c!_f%eLp8iyG&*rCO{EKpY+MH)J9G7l|y8rel zPq-@Q-O1D6x_c+4lbmO`QSaiN!LyY--9h1?oM((~CrJnDhn43Mcqe-YM@JX5;h_Mb z$FQmhEaqeH?dyw}_3o%3;HnMLYk(>K+n{hFHa&vcmlbhRojsL>j-1K*& z{adEzPVd*&r}ycLxv9DOjRExnHp+NJIUZro4KVD_&AsY2DtFaOZ_m%25T2X6wPWtf z$8$HlT+i6>&)omV*>!+dQ8n$o{ifa&(jX90=pY~{%BLdO0I{Gbf}mofNfEr103v)A zL_m7zy-06Dq@?$r&?1mP1VSK$1hRybySwLqXZPL|NMgSK0dj$C_PjG^&di*dIdi52 zynMLis_MOY!d2agSFT+>I9R-@K7;t>Rnzo$@Pl)WSLA1|UUj@@UGIqJ*CLd;tD!zb z2$dRiN?7x*mAkY9UwU)MFzI855zF^&+M1HIZR6gMk;2E?VIREpa+k7fU2?>VcV9>@ z&*lae?BWJmvQ57(S@ug(*2u}LU$Sfa)4KHwgzNyrmZ0oigNDxxb4bg6Z(;UH?@N#^ZeU zpcUDU5!o$%ysrNz`$Xs5L%knlYli!c%N4S9vxjD9pY|5B)hDx0b9 zW6i}(^$|o{GgVXGlrru2aZ$?SnKrVWoE+`#V6#N%N+;TAxNFEzSUjpoYwgeu===82 z5z;3PpKUvuoPF-Xg_L94KNCLDj`--ESGt!a>B4{C*Q;Atc@j6EU&N%zs~_}^GDiMI3H z5lfOLC3C%(kfhuHQc}{|cf}<2er~^zq?$NTO0pmCm8?9TWTh6neT7=d2?o0kxloo~ zvclZ%KA_(_AJO@!QEN^djM=#H%%Rh3MhTy3KN&Xo)gEOry3m;Q@Ae5Tj{(WsL2``U z7oY6DJowYkKOgrua{8~05n@dGm~HBjG4D@~iE;GW6Z6ya(nZtnK2cj-_s4uYBxXvl zlhOTtxe{|ChFdH-a*GALsSgC9%DS1CroP661`>fJ`q0Gem3I$*LszO8jrmHj;}}X#@#2XLb?70Te<$0P|dOVXNHKO zhSkUW-RSq{!=Hsv)7j9_m{XyNv7w;@W`~BRM2ex#S>Yiq5~DKCgnsjOa&+onR}kjc zo;on~z$pPQs>F+`LS4>fW@IFu3=NIUJe?LE8k(FYh3d|p!au_d87D*I($1v+#fO>_ z|2mNthVLff!T4h-NM5TqavOzEUF=zGIwPe}z5HZo+&!3CxCTy6@O7P?74Nm0bW-6) zxZ|MR!_%d5i~WFpgNLI)`HRm!9%(`4ANQH?1yTL_a}SRi_ASI+k!yDxu^iQ*39HofyxHpd;yL9yUQT3^{r-Y-b z!viYm=N=s8{^aooN#{TBA7#fYkd!)ZIjY{jct3p$r(%y4bB?m}2H|pOm zvV&k0*hg+U;_b9AARsv-~Zg+qu#yrJ#J;eX3fg?mhLXwqgyx~ zeS4RbB5b|C3>7daR@j%l=g=Mv9$Q(dJauDF#GYbgA?ywIl9NsuSKf9sJnkmV?sX&j zr@x`@KVluXyFmHpmNyQ)p}~Lbu2lYgxjL{FT@VbN#|e(?l@bVG>G-!ZO|(8HqpZZ z#zbtGhhGsJl&2wv^*`-teR};o{EAplOfWdWb4Rd~Vs&^o?dK3xv?2xb<+rbYu%7#2 zx%Fod3#4F{@*{$i)|q}rKzxyT>1p!``%QBdv2GrIMXW2KkRYNa@=s_HJ*3!%2D@MD z&uBfs5-)*%V(mQqidZZEgl&vEKOr^4Rt#f!d5Dkw1PDRs#7XODj}au3p2Akx7gN}? zQh9XEJp77SQ$jS$k5azmu}7H~=P4+Uhs?vTh>)7c9hJu^0*d*ps(EpvPrArYN?x3| z74hnM_!Y6b{`b~?TJ%(TxJ0}>55FQ_F5&Eenj&$u!*tflVL8c7)67%ee*m-{xB|z? ztC@>@?kv210c{4f^2sUJ41KfX zB}=(p=hvpqs&XgIJpd$% z#PzZF!*`e8PgAd_sln^TBK0XQLMUn(*L${Se(Fnp?e-PjZS_ylp?8XkI<9WpZC6p@ zhus3MT8cD&(>q_Z6sdFxViDKT`Fv6TRYl3@>3X{;^Oer8EiFnc;&zo5>37wJK`DZ2 z7|i78qR^?}5WO5hWeuTXfqI$eEuo<0Dee3l1s}}FKi1;bE$&Le_Gb$U97pGDb<5w^ zso)kK(64Lle7@l5HL*ai8y!3k-*rwcczt=nyX*7&9x3?ttAhNc1&IaRw$cLqw%Taw zFa=0}M%L;wS41obp@u7YL5n@E<>j3V&im6hFYmHbLSCN#fot6PyiGmx@*Lyy@|qn^ z^Bfc}$BGbCbK2zxA2?e8=Sc{ASVl7sk7u7W4Jv zzsiqx{569-`M-6IyZCQR|KDVVbU%#aW%>yhWW-rhl z0P$~wgOxQ>Gp%PcPY*~7=WT%sRk?+Wg?4v(yqjN`#ubM7Nrm2nRuras6cn1`u0GqV zu+VXLVT6C-)jNgnEEWs(i@mQF&Qos}5KM>{3pq!9M&TPP3!j=L7HV?~3q2E;6($yP zJ4y@nJDx;>{k7n%e*%XZD??O}2qngIue2P{&95ZNPb%?_Y}LbcRY}QouXb~uD=BgM z>}AuYl1(jNdf|pxVkjEpKd?{FR|>@vl`dH<;hdb$l?(_eN$T9@*;yrH+WqJAr6q|a z+#jVS`ak|ZNUF-zh3R)I%2d~Qv5dPdlxdtU72TK0RD6DAnd(7KX<1d7>Us(OrCl}ZR z*=3=~1ejKfb=R5dy6_K_za!8PSD{poY16_pit|G8cA$Rbvi)Oj>yc(0d=Q0Ia&6j>M-ER@x95Ls5`#u?sRFYYIZ3hIJAD< zPj?Sr%U`i#;mT?Rby`8zL9lhr^406AIZ%zjg{HvC2_7ky1-#hDc<=-U+=X!xeca>F zNZ^RWKe>0=cCu`63QXR`grb^$@H&Wr}-7|gytiWoMlXOSf*XYP&IYn=o+xkP(L05G|t!VNhW zL>rKCr12$htq(qwW&DV#FMW5zf+;u}l5hEA&mTMQ-&(aF!>b_#5X0J?713C+mKZ*! zoiGWw3gg(F3lSHpQ5a!M6cnOK?W%yVGC}gT0|@9+PcOIdGR9q~0))^%80xJL?BBt5 z96nOr9FdOhT2IrR$b3*WVxRMDqN%ag2$Cd`Zhe7{B zRn(EgI1#XC=g}kAm1Xw0UcYcYgT{fEUKXMH>{vOH>h%l;BCVXRMI=~`I2rRgV=bE{9s=b57WA8T# z3(mTNC7R!*J;nu|d-m9^+T%a0YESe3cG|ONp4w;6%OCFf z7=OiokMFT(Phc>?(>;20Z3ilRUkm$NluJ)Bav* zzLcInQ!;BIPQR8~%srO!zohRoo9`V&pYuKEga2Ffi#h$6d7b4)>*Gi7t^EG-Ve|R? zpUgiO|2O#DUULJocPaZ^dYWRmFGgG}!}hH)g1o$aeEr&X|Mc9s%q6`#`nQxz$HF1m zbZ?Iez3D+#El+NROjbek8nb!&vg1`m)=y^hnu=4w<{9PjG2ry2sE5mJWL23B2TL%6 zD;}YVe7o#jW^=-cX%Bxio6CQ+K23}1K(_h(A7=BP`0LI~O`z&V#EnN3S7?kZEOE?J z*LMz{OPJ8BeQRHZtOBzz757#QK2qZtt_MLX%K{+&spP;~5QKFtnLQU~-JLO4+O%@z z0tnvr(qGK9?0+o z?qIG;c9^G4JCtOed3&+>`Y!Wk;Yaxg+>c(KWj?!0CUMd2ndYR!jgx4*O|22K+^lP> zxv#HZ&{I90=_#wU=JMLQWmco7zJ+G3mN#2X)ZD^?^c#bsWTK*P=fs=M3-j+>3&pIN z&B@nh(sZQdZ&<{Bon5flyqN#Zyya0r(Y)_-ZkOWGjdzMpfg8$C9L+m>J7+e?g7%EN ze>-Px<78DZy?i0$hLg5t){jtFhiP*_ngJU|&RKM!;zsB~kVjse7i6+k>o)B=bZi#@ z%|Wx~9-eRJrdENt+J5rjGP8QN8J8wo%&M8ekk7d@c(dyJX=S*X?FSKmn~B?L@J+*9 z+#m=F=TzXiIg(kmGreB@mV4!5X2xEDIVd+sZaQ}U;x@@*Jp%r3sL7Q3DyH0*K+AR} z7l>;+*@H{XVP@6QB;Kr9n|54793AqP6<6%zvgf#uOY8T+Y#!VLeQEt@ z2)Ab~-15XX_i0Y0t&+^{B-=gAlCtM~e4BDL=VDeS7NR4ytuKFc?@{@ppxH-j6Y#~X zl&*8;^o(bt_A@p%aFvyS%F1Y1YB@%f~OR z5@pdflJHcv-Ff_ZDOq16103VB!%9TV%Q6w!9i%~~pahwSt>cwvc3>7xy>xVqLdE4C zGBKBXG-Vd#c!Nv@!XWZ2q%)^`;Rm;^`u#t$dhNzPyzY5!OI&ob4#`-S!O z#i*tV*LJd$V|%_jwDHv+{!*y2167vaUaGv)HWkfDMlBG_o^iRwzT76x^%bf*9J%=U z3vA9ZiM5?Mk*)jaq4d=OCO>nFrKYnfOWEoV*tw@}vW*Zi`GcsEbSQ&!Kq^AzWRhG| zCah#5xtQ`wMk3lv^0A{$uM*P$MN7Y5x-~jwRL;%2w{HG(NtJyLNc8?LUDFDg!|Qw5 z!>3PB?_4HYm?r7z^s^w;`FbOSRxyXaPP1z})?k{Zf6A^Es7u>p@mz#EU??Hy{ z#pu6O_4!9KsnU>zj8!~hIn6ChwP1YazZ07IN7dp#at}{D z9pcKXplO$kuV5OiE8G^P8MR;JtC$NSbPs7cmEu|Xqf(hT9IeO1LHR24=243rkO752 zD#1tcWZo+G@N|X?V5ZqExSX1Ja@1F^cUh-ec0go)Xfw08JNvX(XS5W0YEzq&{|xB% zCYEpSuJbJH^}X{xmY9CyH1?{t2QE!|F5JhnM-_E=QhJDA=(9So*R?l&7h7A1&tJ`M z`e(DIBd-X~BwcKndAqc>o#fL(7{&w(u>4_N^h%a|o1=GI& z^~jI@MrZkTQ_)aw)PA0+&h^IM&h>s&mw2sT7n@fm`TS?b`F>%_o z$>Kq6`!3JCv{tnfGwG*KJL12Pos*K=K(x?GlbSv;YXhj)hj&HeJ}m_Kl9z=&J8vRm z)FVpiOP;P@YR+FJ?uE}~G4|7Unj9vvs^kSm zK+VGqPL6ZSn6;bK>)*O3*ATChiQj_7CO17#_h;<$MQ}wbmA0K_&JPE!d#ki9`}GUP zcD>G)dfG$?W^_j2(CpKSdNxYg5=XigdMS$q0&Eoe?r|kxVTp zBSj=3=o2t%*OU&;TOgh&yOPbUt5Y>{U*$p7mdz-$By!xgzQU5VO1DnA6P4VQsx!3g zPi>2cnmcxn*aK?AP4WqXlz!?p1j*e!U6usQW^V+v#q_DF z)mYXtMIRNl?KJ%9DRTeONgey3p{LU56C|-w|0yTKF{0~fcZ`6}-zecK_Dpv%XsuUceqQG*GR22rE!tM(ef`>$X^U zDEG1FEoE~5Pc+GTRFc;)G=X<`a5?JWhSlqjoV&Q8)KZO4LVy#_wx0Sf3C_MSS+*Ka z6cH&QPIRK74N-F+@Sj5DZnz7{P?EG}_?-2zw&cd+4&XJJAsF?>ii7FO9%y53-BBfj zh6WX#?ObpUks?lB$O5?7M)mN)R)czJRFB$#k6%61ot3t2&e78}l)&r!d-d!!;^IS| z=T#rSmH}xaa^->TF|dcp4MA_jg|OL!cZC{0(s2mIYh_olsRKLSSY_MVT-{nK$Rq3h z&+^6dI$kg1AM%f5&yvL7xxaO*;jZ6KIsC}?ubl0kYW*m$1)I~O zj#q?M@$mL-)BWWULtp9|NYOuVo6aVvt*DtNvO#XRAzD`+ePGeV9~;=&*rd(z`l>6o zoz1MhwF&riTJ%#hW;`9nkKE2*Zp-*qbLaEJcJlm`MSN)gg8XN8@k!6|d{)~M>j(IL zc3YQNe&i0G|LS+^M{NSYb{he$I=;B@_CGV8ZSP0vnYsj6*JhKpHVPFM-Z3_$dTX<= zSd>NANWyck?WP00q$vGAgomhT2`b**&-2rN;z#uvFrfE)G8LKKtsf%q{$NmW^m7Us zUv8Ai_;OV#lX>e$!M@v`K8P1QK|KLu~E7lK%Hl}6pnq=A}XLmGmD}`*$MWX2krY zE|cDRHXU@!A8Ed4`OltzdvyQ%BS(GQZ5GeVACLGdXi?xXXlX)GDut7(UM<@`^UnNP zZ*)h74$&%4d1YZeQR#@m6P_Y1Ef}^ZH$2XxHkNfMW>pq89IZ)u3U`?!sNVFc$ON9T zURPl7()(fW^KUfA@1(uY!G%B03SLe$^Srt=ue6G<;#D_`%6SJYwt`Zgq_qJ5YrMtt z`C!9?+Y+y#k1{J&%z)67LKbSEy;}Hp?AGJy?(JZoy_Lh7vYL2|tok-S+EE)TIvf&N zhv7TfS>Ffi-|jmXVVNJs4r6Nv^@(I<<6r*n4qFi%`)Vme1c@zf-ETfNK&3AR4M>xp znmp(g_$=ma!+LHz@WNZSlplzi#Mpa#*!3|i>XqIf=HUldcCSDHW#xiLjS9ro1qVZS z{Jbmq)`6+X#GE^PF|SH`PM|NPylUhQ{EgI)GPB?T2OglH+L^h!;-t5KK%1a|)-A|D zd!PzQg4V2=TW>m=Odi>jTcGw3=+F)m;93sfoIHFa%dM>Je2cB?6we;Dy@$=vjyY__ zGPYtw&#UmRD4g>&rn^_dtBCvH8I~<&AOtk(wHpZmzg3RepgjJdL&cS@U$QkJtXGn> zY63ggdV>X_m4kz^Q*LBU==Z=j92AzS^ zDJ*b@Ckiu-1LG8?ryvYiAbMzFs1-3lIf_-fpWFv|f&(n?!~bAO_ndI-5o0-fo=Ruy zzD04$umNarJZ#jQFNd%dWB#+b76)`P2k=bWs*F{E;J`kX-xmFPf3ZIPUi9kC-Gq1Y z(*MKQ?e-Pto}-=ocQ4&5YnTBxce{!+YB`-AN1_czi8^mMYg};j09$w;4N)d}igMAv z8gngD!5|hhO>RB=p-~$FSsb#2)-5xNZ_iEb4a%lU%uCq*^e)zKX>xKF1U#q9Njaz> z&uv$kGQ{+5^xPUllau~$U!vB7^-pAGG(-OYqmx9qc-yQutzu~Q{{d$sIvGOC4h$* z$+mCU{7?WEOPo8_F{Lgj#gTKj3n%*ATX{_fjTwyTSG$ z@(Q}NqxMI1`@0dDwQXXRDZ`O;D`5yQnb2B8L;V3HoGSIedbEe@MFF(hggv=KvL6(6 zq3xh|$B?QO+0ZZlGkE-)0-?VC><5Fg82@Fr55B;RF}AmB9<9bLy;rl&JF00bezD&- z{pZ!9P5A+-`)Zcudl|HM8T5RnOq&k#dhnT>P&5VoSs&zA=!-ilR z-A>V$wMvfb_gIi7s3$pOs&NdqBmNf@EfIj1daS#|Dp0R#9UkSlCaee-H&GtlwPtiH z?buNN3+;~e=kwyVPK2-potqiG;rAzk;qOGX&*j zGq;3#=d-Yw9mvA2>m2i_?H46mzF`0Ky7lPGU5riKR@x>F`j?VN7pwC_?zirN#z2KNqz$%^;@KWJuSD^)?jN;k>K>}z><|%QwU|W2 zhJG-59mq(oo5EP{EEfJYTlF1dhlaEJo$^b^n`I-y#;zj0gb&2_@0@sRm8^`BII`xC zD&#Zydc6drr*T5K46QpsfeUuv2ykM>2sjg01#8#&P2ceUWdl`jZb(&Q8i|DA6JQKk za=R=UP4BZr!lGG>op_IJ>N#jo|8`|E_AxuGA0l)A>EnoT3Ju5`5e@h#$0wc?1oQZOQsoy*Y$+pa=BSJlbR5lxBl-s5lz|JB zn5$&MQWlzN(CZH88bwbWK7{&mC2F47FoBx(`N)_M3^W{V*!inB15{%RyS?B&-9@B-)8q@+XiFz=>8)m!9zZjoaZq< z6p`u&ft31DJ}5t@=B#+pl>>N<5H1S*ySa(YRJ6Jssbw0)cHsRI?)r8+9bP@qci(SsId)4q7diVvUr1bF$#i-&z`~(rvZT%y zMDkTG=&6R8WQ_S1)TI%-QS16#oNeTU4nWv4OC z(?6;NI5y$6@NC~)ra11W8y3L|UU&D@?q4U&tE`5}X+=G1nGxwHpAr5?m9vrZd-5Tv zYLFgKy7I(6=2j!u-ah{kbUt03`_Mv}h(~Z^kz9thDG?BvB3HW+epT`g#TSP4|7^^Q z>yM=t-jk|vF)bz)xU|5fw5%j=4wI^(oPgZ8k|tGlGtdkQ6I;iZ29oyqzc$PXkvHX^ z-oLe`LLw)g#;)Mi_b!x_@j1LYcKV_MOk)iWG*?1#J{`g#PX}H-JRKYoK)w(~`sD01 z1BW6RM$Q)+AGxl@%05RU3%t|F)qF_b4?14rhj#7q>~?`K;f;&TJU@9pf>U?|2?R}X z*XZa1{t+7QYe}`q`hht&a{(-5qv3av-G}c*J6d!NpeUmkj=0Of8o4r8{+HG-&zAUB1uq1?5hFkK&A`6ftSJvU<01dRBOE%> zqk|nOHtOagGZJ-+oJnxCqvR7gvU2wVFJv!hej8<@&4lRXbpK8(8{IIohuV)tXmRM8 zsG-Ao%1e0U@GClo@ps!^=O6GJr}K+`;};F<0a4IV^uIe8+cLZ#FF(VlmB#-EK~_q8 z$XO5h@hUU~<~Rwl8B2r8iSA__9se=?8`-Aaw zH<9Uka5?(Gp2QpFJ=UEfdMFbj(<49r7(GUr9-S*q4G0oy z2*Sh=L1fJpf@ESgZC|ls`z8>jO5D>ZLA4`P${MjBx%&2Xp8sgKLXMoAa1IAK$lDb0 z>qqmmKQ5N|u2{ig9pdB!&C6j3{a@te3Bps`hw$-!_iGV^AE3}D<@qEn?$j_E(e#L# zEIQXB2+jYL9*ZDILciM@f__=EWAT_3IpyV7*N$JfL$%}=RQ0^jE{JQ>?$w95T^Khg ziKWOG#5Ja0eCSX%`dxAQXSWR zYt8RZT^5={scMNgg#6yEn165)xe7Hj2!{q69J09#>Q{BUi03s0eDR%!_&0}nsvkbg zLp6NhmvtH@OmwGRlvVViZ{7LlQo)uG7@`hNo2E4L2iK44WNtCa+v3Q9W{1 zB$2hU)=SBE7_(s^w&E+L5X+~rIkLseE9E8OXs87hShYBoiXOx+62g8;TR$sKw0f}O zyh%9EWu~R3sv?2YTgF-UOfX}G&4*qWn9*9<^u|JwxdLUaJNFp-A5fw|MT?ju#RcWd zAsk^L&`{h3_4#N^hmOhE&bf9XL3p&h^4w{%y&w%>eMFNs_OOF5#&9s zU+K%U_lMc)ij+Hs6a0tOx?_*ARRIedSyvUd3I&|QM=2wnCV<}7tL+G}5k-RcN1 zg@&04nF2Q?44g@o$*YO{9YW1cJEY{@xm$ccGC4jj;(%)NhFVwcY40McQi1~lk4muL zrfY^(mJ)oiUb%;QE55uDkd@4#rog(a68UQxYB{Mcy~e1w2Ue4VlOxbN5O?84n&5Ub zxi>!=D5A6hB0%R!2&q%mjq~BV560&lJ+OM=+7qg?_ZzdA%v85>AO~S78XngrFL{uH zUAF@ikKPUo1xE}V1qTCq+*0t~I=uoG7kPQY^_Foy5!F$}wr$o}Smzq! z<){rV1~O>u$Y-OL)y{$o!!Fv00_*kq*Rf@Q5 zlok*7O#^#xK+0(&9` zr24*Z>wgUb<*`yY?1F*edI2~l4535t6=urCjxGbkQidOemX*|#R>oW>(S}YT))QE_ znda700p}XI-W7VLPF1RMj_k3p5LeFC6BoKBgJcE-?+i*mH5sSqVo!=6k!I5K#94Ap z+_AvH+d4Tp3-hgeR;#8g=F!yNy+e?T_VQgu^1H<#6jzgkn&iry-i z5`>oS!@QP4c0=*~6_pZphK&KGQ$?K!>P&ZvVkNVy_r zs)V{C#~M-rF5`kTvNLY(GT=JLw5))isyU)nU4Sy;0Atfuu!uKH?>~D$E`X>xhy{Mj z)h$XQ&YF+=7r^Acpot+h#=!LgGIu#s6?luVlHv`*3R+>NGKbm+vA8O@&b3Zqp<=zJ zoaFsK8JqJP`>OAtK`-D?5{enBk6IzUW-V4Bpw(HorUOO)a=B9?Vn@h%yHlSj@KKQg z@RK+SsI?PmxY>=>Ia>8X4bn|hrAK`)-tB@^a)IBqI>)DKBGGj-YK=j~MvKbo(ZbfA z**Q~60kJN`>1cE14hP#shbXo>N$9&kSqT_xlyGy%ht?yd~NO_$04{1iXD zXNNUB-)VK=;ft?zaeRa4GkbLoF5&xa3;s~z^{XcHFKfCX?AY$OSF>)#pZ(f%#^0}X zeI|-eeqo7!&+~6I|C#6ax9_!?pS6U)#o47hR*;D49@RY6GZ$IwOQocBHo&gkG;Q2ot zW;)*CiyXfk(_<#zZ@gP%4Fx)x0tBmD-a0nyRX)}a(cGW-Lhjz_W@EQkXAwOF^&hoUbXbya23fA%bo;F*50tKx>!Ouj&c0cKq-BrHtmZyt6 z){g@P$gIjODCtU5^m0Q-Oi~kwt{9MBracwrfQWF%)<7nrj;no->gq!p(@%B$ZFweC zM2FMbK76F+KIov*YF_J^!FT&Xd>@oYWLz~C^7-2ecpD`nX7m4ju@)sc4rfH( z@Js7y{41?b@(<*sKK0ThLKwEJsG=Y;aFG*|`zAM-1taMZ*j|~8`rUE4#lbzf!NI}C zsH!*otPqwL)c%96-^hfGZT~{wFL^$-bK72XFhM*&;<>w|_=a{qki?}|Q+C3;!&LWe zHFL!O;qh#@!+a_i$^Yc}0HiVKCv3)PnJ@|{Qo}vagG=yC8Uz;+0wvPiQUB;f{$vAQ zyWBScw4rN4qqIF4Z!Y6C`F!zhsLQ)l_?&kSQReISAM)CJcliP&M%ATPOUt1~5eK7U zVJ(XN?cn!V?H_gffGZ)J8o3mVw&~EQGS|F=_U0-uXXPZ}hs7da$B z9s=#>u&={cSHvX@R0Ksb{cp~^hqcb_|J^2`F|^p!(H@D=G6OD$6tM{9{52hA#!g9t zWH3@zN-YPWebS!~e9WI$njQSVdmS`_wvriaX=hujAOfy2AmT6DF$V8=o2@F4+MgY}Gb}AGkIvL38 z!YXqGREUFIQ^wHfh&Wuw!Ov@?mp~&sAb_cx2Tt5$15=F4$q=rk8}}S>GoRchQ$vfM zpuqG|;S&`Y$zbaG_j#cQn1K%CIi*VkRW31kQpYe zDq>emMOnbsxMR;ubu+19XaK?G+u9a$o48up)Iux((kyyW-Xr326Y_#xadiYrVBo{M z2;c@rML9te#;uzJjsK%&ToiKGPJE_{$riv|neLUQWd9;HC zOP!kRk|Ps~45vZKa7NZaStrS<2g)X8Ic2HBrJAD70~j6X=1LFmmO<@1b_nwGX@;z@ zpy)U-Rrc0B z>FMqQCk~NK2q>~E&NA9M9(K8WmSag{YDyJdE9I#`u9f!GThpGcnx6Nh1>~#M>vbr; zp+3_TI&f`AP7Uee@7)aRR*Qu!mnu8f6Wo6MG{`OaEXbdY5n)Y=8kD5ysZDj3 zS?#=NC-i1+a$@u@!!3viElB!S99$#nf8p7>%Qq$W?k?ya=!0k+%s6QW+Hb04N*;5b zpEy@iAfGB}loWQ_sdlDx^9G^?rH@s2(O9JjMXsy~*-}|Wpz6U$i7v^J{5g+ST|T*S z@6PmYfj-TE7wy+k4n_7{LH?L4UFT3rEBR2$|8OS7t)4R}R~nl?Q{ANN+51E^IU~>} z$TwqWX7r$p4&>j%w|(!KyMOH4!OzPbC6iRvMcrskCWm^W;dPIxJS87f`Cm?{xYct? zr4d5ll-LruHBO0KRB80IhmpnYW-e|%0Ue)ywnwLc7PNd}N9?fauOZ+u_qy&8m8aw* zD*wv~71t+Es5FA#R+mu3xuPt=4oPe54(LiY7f+woQlOnbu8_v&3*v-(N5FHeVu$)X z?7F8?o{~?c&=E~4EN;r76t{W~r8EIHBGIV2#PK0)4{)`w$pq7b&K^E;V7E4E7a8^A zVRQFU)dw=G51%x6_M~kS&z>{}8vza4I~F1OAn9GO^_6eK#l2IM9Y;;vmzMjJ+4V^7%+r+aaO~8Dgth~%_HGEkltf3#B5emj-$JpWGt{x}RWFYlO z>k?jU9e4ZxcY@?n!wST9 zL9QMZ10+6fxL6D0$`v^jcEB%W4>YLy016tjQ4hHm17WvOm`T;kMrH>FQq_z^cf3K- z%G(1($J8drCcjUsrx+m)o=~Bakv2Sdod8e>Kmi{Lom-%%v7KmdLk}i(CsDkxAG9LDiu~2S)?&Qt(cGso;bIr+B%O zGrd-KI6M1d_TeVIw?JMQw2j7PcX%Z(eFIX*DklzVv7rH}CVB6VFwu9|b z?L2|IEXuNxL5e-l6!7^FHV)cOjq+JUn{a?eF37;eY$WF3ij#f#9j3PYoQ>kGol?2O zeZIWpUUB~I{DRW$BD1^oR=YudUetQ4ky0ZYr|!^Uel5nsL<&Z4Bs!@41EPU}u&gi` zrG9BZt!3)eEhQFa+F5Yp#*z*l_u`i#WBE-S@+Kz6(SVsj!d4y& zx4Ua;LYyQ=eKmcYMVhLf86jYcyZv^~)tsCwxmW+b^!KH6*RfMjCvh1lj{}J=>1IVW)+1AxeS39l|AsxHwk^W0|V|4#y3*7hIAq+g-YNG5f;#i|4Oy1(q!~ zEX|qR3Xe8UXpZ0o!>9DZW3Tmy+wkvvxeFKsMc$?By>Lf7O%-H;RwY6((7ujVFjmfJ zx8`M^&z8;`&YnMaJ}WB^-6+%vT!O+GH>HgoqdHKW|LpMzqds=JLME*7+0X>e6oNAh znIY7l!TZJ1(_?jD0ZLdQY5#m4(|~FK&UPKL36N6JkhG z-IYdkO3~*7mfeD(6P{#u0Gz2GNKz8Nk8)TYw`t;))a-7Da8?ZMqznm>8d$5+5%ms*|%fA!Nc|#w9#P zhJ7J#LDeS0WhGdAYUz#ypS@^(BO+sE$Q_iB!BWD)h^QEWr9=}AR7T=#F0CV-qDK@3 zsot0tE=90t79mEeQa7SGU{hYN*6EEB?lRPhBm#Q0w8BD#szP-Nh-3~hiuU1G8MlF7 z#WnSvi0&Ko1~iz}6LJGAE#1w5t5qD)*aXbeLg?-AQq!H=`PZ-IUb+1DrOP>2|G9ay zNtj{Rj41mfbq)arLmV8N2e>(5Mj#}B4n=GKF9z4j+}jX-9C)FsV!R7seWRUok73>p z6*5lTEn?TS_Y|P#1GexW77h(wV(;YR=Pm=197P9)`h+H0S}U#s1(%-cQ6;?-oE1<7 zB_V4I*j)M3-q=(-Tk}@f2c7k;YO13~=vPG!3r!0xEeAE;+K{TVBsYGA81SS2umswJNnGi_AYH+*(B zVa;CW;Ew48TzpRo7Q$ffK#30r9i$HAHEwkKPG;<;_c68!@iArCSC26Es0qW~lAV0Y z1VH3fc5+;uVa|{$LM8(at~_>)BCXE?r*PR&mS4V<-^$gk$K@rTPVgBnSr2wlOI>J= zH^vGQ^Dp~6AmBH~hMr+%{-WHyS3U>Aj(6(48>drYu_OO|?f*mV(MTdF+k&`_>}=BP z*ozL3*v9R%YO62mCHFRCYr!bf634xd{1dD#bkPM@VC^op?*(JJ>FtO40XgiYqwFDv zcBW{yE1&sLEVyjVn+6nh7lah4Sp}*ZM=4PE<5&Z=LF=vB+5$*-d&o$gmyBfW)&16! z97{f{V&43C$G_MBnDVcGuEvSJxNj_!n4Q(S!_r6mJ3sTtoa(g-N=(0kkvYO_JjT!Z zta>VU5mW!gOIDblGxpkk>rsv+pI0!?Iepnn`*6~DPBlolApMr3@ZW0m$pL5rGxInn z(#~Ke88vK!;G+Q^xXG~km1(y*iS^lf+XA7p9Y$DKz?4sNV6j-3-&MvIe9cyTEJgaHrdO38x4vXD=`LhP{LPq)@rLIQ~#niRRC@(6d!lTrTI-@PBl)L-7>gG&ClE)f}TK zg%Ohs44xbkK?b$a0m7%JV@K7B{eN;3tgpU?$*4e<6HW-IBcBy1d$ohHiH?EwEl@br zp2z@uprVbDgB|UO;7*aD{hz&o>X(Y}UT_Kkk$=73A~!xlLmVJ9{EP9nz91KB&>O~3 zj{rO=8Aux)d6!>dZ0aj;909r%@dXJU6uAHnSWp@VN3zlX!xmc>dQLDn8*vm@K7=Qq zg~7YjaG3tLZFLUjOfWdYwSkKS`mkw-ETHGVp#cluxbtP@))lmuRKd5?GXsO5;an5F zl9pqGduLn{;Qsby>s^cWH=43-oUd>Q0l*$Hyq-fio{Ef^9XTb9T5a^^ulQhelSa5K zD`^G-)VN8PstojWFwf2)+dG@$d%`wjQ-OZ@=8qXe8nQzQlXt?bt{JBG_-twGcJJ3Z zirGlrzK!O;K{L#n!DK`TSuV5%AXHs9YJdsPmU(Rw*`*#8@f}`e@@DukYfF9Wuh}Kx z0K~BUV*gmV&3zN_ql|sR2t%kly!Oj(zdd6DPE=E2lj% zd(5!Djk^YZ87MLPT1P3H04W=h6zCnSQ3)KP*}^W&il(8BvOHt)uGiT3_hMsP#9Fh7 zbxkOBPM`lCa?7>POzv;Q(pwk7Mf5$P-Kl_mh|+DfuK3hvHz7XX{YN}?Dw>lIb6C=cOaZ)X3EGBa)Rmm(>4U`h_+R^b@0-OfGT$-4!PD{@e)2jekmywl`o|!IW2taGe zdXOcY05*`OsnXMgbX8ian5G*2wKS$`ta{w|Z=?yvZzfKdG?`c|P1a1A z`Ymo`G)GdXxxN3P48-CMRk0o+ocW2=DSqrL6tB@^mcDNYU4QoNB+6YxY!f(6`F zC8mgAu_i4wP3AF|Dy8608cXHUs=#LraHfly7O*)h%W{^>5)sJa&IY_tSsJC7SX4#2@~1-JyQhynfl##GHeJ(@a*xf_AkBBuBC$8 zCBXOT@q>*4e*rIXJ3h{Wqq%y*oDgpn4OL2_lnh3vNXZ1)E;S9TreIcz1cp_D-9oyQ zsm{uT6qKJ;og>2Y1X}$aRY2_CRezQQkpupC?11EOlhNp>fRq+~<6DdKXfVM!MIbfDj z@ClGoih(!|&^WKo(#lCVAQ}=Ns@c zj*X8K=^Qk^iV0Ooz>7aD)hQ(zlAN3jX(o}D(zw*}G)smC^PO3l1wLj%M7XSnnG(J} z$mG%?5Lk^C{I8H!?LRi3HF_ehW#zL%Mvl}QU$ z$YdE%8X005!-}YlTtmpE2|5`$^tHUBOHuP3$&9n5RSKnSy7`1nk+JxK4w5__hveb4G@3*Cw!KyK$pk-M1!6F=DJL z4r+vf;rc{cmRO9yZ?PgLMXgH37cGeht;2LKRR9H0eVKd)2fjmTWUA#gS7qgPB?vHN zWD@>NFj~rxfSjcZV7E@ePLiVjX5vI~f_ma)Sy{7h+0^D!pgj~p0lQ}g2hW;2!PWi+ zl9e|1f-+@caR>?wXxV$(AnkL}vC+hKDb6W2E`f9kekUZx#Z@J;ByD1HQgX7G#F7~Z zf$mEdQ&@Tx>AnngdTMHAx+){RJfjlAAZ1jfS3uv1_=MI;7c&g$Ff34b=_Dgk8blBJ zLye^(=FM;=piA5DPT6_8UH} zt@fMbXeq`*9Jj=AKrSVy;}W2-)k%q1kz!I+vMMRrf-yN@txVS=mY=$PoJ=(xCO zuv;A$6C=XjXu;{k1c?Nlz9z9mE=h#QV@)MhLP{*qB~qG+>;@?b`VHjWRF+r6G zV_yy}Zb{XUq+0+*0wn~kDy<^*LFyw#{iKpXC1VPWB;siit6QCrm@JL92WAfzAB_jova;siT*P9);wJx$S& z10qc~l7Q2%U}2Ws58uEOd96*WfHqQ)Dln)lFe_kQKt%uxH2C`t{QgC5P^=iv!lZB( zWfvV46%iE?9uXBKVyObXEG)X%n79NorDQ}Ua$}REL?ae0luS}0pn?uKiHVg-YES~i z;5H~o!D_C6?x_O1HA&D&0zD`s(wf0q0XragT$~Q%Ky*YaLDB^6M52gRtO$Ch6FsUK z(C5-jw^_5H6=%<$|EAXawHN*TgW9wSvb0IUj64c*3~Uwn^>knR|Hg!cho6zc)Zvj) zVx%@IGAuGuiV{GM8Y{UX2C{@T%*6|E2dWY@vuS!TPPY~ki2?;9)j&m%W`zOF_Cc*z!$+7xgEHU1G=>e z5ZlB8cv+CWf6E>-Ke6*a8gV*YJk6aE!dZkm{4_FnQlvU6GLi>)AyykrD&7*W!}u^# zQe0WQknkwJB0&H*D-t-kHWlEki0^=qcvTz-RK-B})Nxq-P`3=*1QoHFjaN^YI7ynI z22v5mhlB=dQJAis26+dUrC@QEaqf5*``)j$@e7Co$cI4&|CVq6_c`wENXuz8_$!1# z;KguFL}Vn%eS{@a6$37F_ya8&1uY3_F~rK4;h@t$;P?VLq=6;qeB{NBo7>(?8J#uH62*E(sUh`04R}W zxWXFE44ySBc=o&jocF7}{aUwq7?c4!`Y6yVC@`>9+lkYCoR&qLI(72osWWH7&fqVn zgfIsFbK&vbth84U<$T;C8jblIcJ6T&|w>I4}Lk;yV20PB0J?r~#Om@$|(!NztP%NO9 z1_rcl`QhBI+RwuOI)41bUw@rE`4@d9)}K0k>h$UGxb*mN{lqOW@))9wZy?t(G*LgG_NQkDu^NqGK4!m=ltK#`Ft)z5$X4TUG)N9 zKIeHq=Q+=L)_D$yKfu$q*e@)!*6}-XhIEkOf8-37E1k;h zz?4>!H%spg^ zk6y^mKDNIqmF>5rR;RI4Q<^!oD$PjLLzSk1B9^8}O_NixKvHefQ`6E@Q!!gos=Qyu zPi!D>dud~eW^ml}iVq~uZW&KfGDmTZVU)|z<$M93FVX6Rc@BF3f8K~`=`i$VY*4p) zoyFEvfvw5DXSc2a$q(zI_Lz6t{IYY`F4M34H#^8n`u;t;fyJ_$?~!(!z<#|Dp}q1R zwwLd-BWZ$2?Pv5QBmL$6SOr`B&Tul|C4$(KuC%FA^tm#`6+@!>$#2}29I^X4?q3`78yg9g&%luS~mpZRS`=M`~I+Ofd`xf)? z1DDjf4sD0L^Y5`)gIpcvrq&;i#qu~E2?VxV?VJS61N0Ck;?6vKcz~GAc}d`%oCFz} z6KFi>ys1;iK7*ro?+SmqcgIefOb4AewrMwD*zEmjbA}IW*Jh*Xpvy+rwvWD&n6fqO z`A6EiZajD}8Ly0k9KuIaRySG;j7Abnai8jWEdfh-oO2=3Ab=&>%t=U?Zam;Ty+g0w z{a=WTc&=aXULB^J4mkU?er(9g-ft!QyfXB$);^{KF21dvdj92U^W)uzKmSxK-vbAd z@ya+L)y`Y%nX^Us6c5B;7?3zBfs1Y6ms3yy(@3MzeBQp_8aizlLPwo z?c+8S!#>jMg^?4cO%I$lapViV9>uVa^%*gG?1ZUP#*ZESYM;mI4@*F;;$p9knuzEp zwj+$}3Z@FI^MErcaSoyz32e6HXUuSZxX&YxJvHR{=Z8N1_@jLvHf1<>e`>6UUtmaZ zpr6Osr@EUmTzU*~pFDM%m*=#plii1O&&Wu|DMb59v0;9%^z>xBGSZ2~3f2~gJd%BnrJP9Gzzuu_O8OVEYWfEecEH7$#N+r` zGkuI{&ZC|fJ1un1TW`;e@E-s47*m?_(B}iA;_#5!aZ!QK4>hH^yf`!Kr{NY-R#2sDzo}k42kOT@oG+ikvm?%{S-9MFjSb zPfbn6D2UdG6SpNO?pEj*}&2RMq zjCtUHPkNDMH!sQissG^zE(caTe01PAFTd<VWBW#+e#VSwkD9%X`;Q*`a6$4r3qL$|bieraNaCb%<0dB^QNKOMNRf~Rp3P_3#l-?xRMeEJ6g`ZX z{rmQo-}8kzB^j@b6zk*JERNmDu|5ulH81u)J!Oo*%>)ULcbF9y8yg)J9T_<}V|OxM z8M`&nunZ*d-Vv!LO4-m;AYj-}6D@cMpKAxbL5mpA(8oiY&YFpFqqUI{lQVux#w+7D zu1=qxe7ATk4hj-Ui7bisF50r@(wDX*xme)xEc@7)=;)}($cRZ9zb50A@vHR-Hh2Og zfF5rl{^_l#Z1cxCLW{cTeA^xF~u5MS^9ZA>`kF)AuD zB0O|r#?EBCGInxRkx8+N_^|}d9MDcWyMVPU}&GJZ+ME8~~Oeiy$-Ov8SG-)(~j z5^PLPocQhVu;B4EKWmo;PCDtXofNqA_RrGWcf|MW-G3H8sTSW|anEqCdpa?tgM@%>k6&4a4G}gG))_vep&%HE!c#DYMq$d@XhwJU(2KgCj8KdALf@8muW8jT~nqhI&Ch~9+!^aERz=6AYURx zj`XD}uv(ZgY+hHg6NPm_bkKrR4+AFQ2{wV&f zSi5fAIx{|L#3xO~dVRNtx{W$sQLJ(LOD?`qtb6UrF}+gE#k#fqN57me7i)h67E8{g^DVTE)1uWu0Yc#>^#Tg48!`wL6r>nQ{-N)qBE!Q&LxKXw7=Lsa z|NQ95)4aUB{SL6}{2D9L9P+bx>pZ87ed*zv0{cCG=U&gW@Eb%8X#{71~|kJ9++ z0^3U&wvMlv@Eb;a+EiexKX&ul zESG;O3#5EY!HojlwUQfedRYqeSGu0R5&fxLpgkxZv=rDbntJo*fo`*n1(LH64_U~j z(4=w#pW`HOkTM`pVo_Vyw1O!tG$b%!jPVEE_!q}b^=7_~{u$S<7GAkhbhYSUfW=qm z?J<7Xz^Xib_Op|^w#=^1lg1bQ05o}as|!Z2$Q!HMRFl`!&Lb%=ufO~2Z-(UM{X8x& z@40U}ewmlIckrT)qxR-~6gH(@@L%WicIWB7@6@%^_ZB?Dh)0<6I_cB$^732G&0E*! z$z^$O#pmVy=$Y65Sl)O2yV|;)$(z%2_%Ee-nyJZ_JpJxhFXsI;Mb6WvBBGh+GJg_& z@h$uF;xl=9PAYOT%0%$ag*;SR4h?{lwt*Kr6LI<|EdP+;>C?v;H|fT`G=7>d^LGsV z6AiFUMwFsw2U`4fzMd0@KU!tbA738#^fSk+4br%xP0~2C!R6gWuSJIq?;rB^6Z*b$ z-uocgV(4kNzPDl11iyu8jwcLLKQ`>`m=ph^!SJ*F;tMlI7+&kV{om&ooj2?@NatCR zbl!qT8SyBSL8DJ$20q30OqV~;cKSQD-D$&wFAPo@hR*L@w!LK7{m6x%pSx|a@#`LQ z!D7(A?rkva?A&B3@qG3+JjRGen6fqc9W1-;NdNV1{CqpC{pZQ$hdO3wJMG)x{7*K| z*3TU1>t~mRjJXfacEE`Rh8kwC4 zu>|S@d?vm6L{*kPE$+jC{nM(mq_IWcOJmJhE|I=Z2X?V}WLB`-5WgA29vyGV>S>!5 z;O+K@=bWs?PbK*sKhpNm0R!7cW^L@6m9@2fR?^h0tVQF`XKlkHjCh18tCN0PR@UJb z$sc$5?z_!tS#OU@49UuJ+O^j8Xco`X`;5X*56fB7HnvsTVa~GoBYSNJOO}4yOIcZ~ zCnF`kP1=Se$gFWJt3_;wa{dwU%lNF2y8P}uNY zo3XD<@|hkK92}ZuF&h~(TXGNn2bZ1@gr$aL}Xe{oQs zpy`1F9}k-p@My<@mP{Ah%njPOOC? z|JX4E$d6)xLz$U#hh=82T$TBI=if3tlMzziByGZf#Er?!{I2sync~CvWod>C^HOC6 zDMYdibubMSPEde>&uN`N(g3wkj}IFh$G$q*FDN)9Bd0rR z()2rC4t%(EN_CnvwtNFt#RkxyX7l-oR-dypyI#FVj~m>^t*<4`#WwBGykF9$&P+@9 zeB@Bt(8Vmx<)F*ruUd~A*l|nR>_=bh{?z{SX}i;O`(mDnLACKro)@7Sg5q|CI8 zFIx}jvp6k%)ME$J(j2#>edg4|uG7{dF^-S-{G}qzWx^v*4g5AOZP=@6X`l3Xb|^x= z+6~eM3_GJmmxmty?DsU~lWAZBSuG9NV4<)h!~r`u1fm`J$O$lTXQ39N9vi;Zjd^v7 ze=rNx25mTC-mA^{KFAWP3l8uYIixDZeuw+Bo!c#1_rq>eiZrI^TWO3r#b(!(!DHnV zJGX9ao@nFd*~OCL@=r=i=Dw6;hf`9d8G7 zDK5wM>^_l(|INY&f8X`T9yvw3PFiP4(I5WjufI+lU@5lZlPO0iU_dq^$_<2S;Bz#I z0PY~l@5pSa;{qHFhE`$cS^rtRjk*H{l&7=X5-UCHpx5fCUkOZ>o%tEOBFk{>s$U-z0>B)&O3Lp zoi;J!ckasB`P)wIzSa9IJ2k(IHPY|h-YNZBfxi~~E!)X|tJ$g9^_zL8cH5F|^j~bJ zw5uTw%JB#s6lW1(I>Nz)P|pGm^5+DOpa8;Q8}N#|&-CEn(h%HnJ9Xr9unKEn>N0t$@Iw9K}Mg{F8S2x|-8Dl{QnGgC-dB=l|&@%9`2 z7bC|^@%Fvtr}Ocg`114DHfw+QY^wBS(Kj|qq}Q z+6F)P!Ki$HWpu`928)rSdcrcB^avMT8bYH02UCM3y3R>})ipC#_*p8rnsu5VQvW=x zN&VsWI(SO--8YASqVKEe>&pmBb413$H!94id$10+8U>Ik*wM(dgNbn&UnS#}@s$It z@tBx;50Ieh8+`yQAC)-e0c(@-%2l= zY(WW$kgQNbPa5xNf5^@S8DjaP`(F=S;fT2l&uN5##9F#f6rCsIR zcGu}sC$qA){Cz9q7K?eFxI+OUifz?p^ zlKeIPOp~mw__yqwtieTIGM6>$|9l@sT++^R*>-1r!fA|JW;8wqWds_f+fuF18{21W zw@$g$Hs0e0;nL5v!mZYkG48(3Cee(plKF30(H_~+(wjs8!$T)JX&yL{a0 z_sfr!OIymzZMQTzAT49w#CVD#pz-7q?LH*oOS&F;?)CPCf42<)Zz?JFdc0?zxx}XX{7251OEmhUa)~sc<>`_!%S(8Tnbsu@Y%h zd5P_&`gAF?3z4B{sEjzB1yuE_l|d!aW@Uro9Sb1@Sw-4q?XOyjy6)4xbEU|0LE)~> zSFcLvi@qCNROA$u`>ku?)`3M=@d4X4JzAbF+Idkfveic|O2+@T{Ih7(=S7p(7QVcr zC?TS#@Ux<0Mbd`yBHIo3kVf%EB8}##A!+kOw5%R!^*EN_dr7;C`T3_7<^S3xKmVNb z(foY3?H8rf`CmVspYQa0etz3uPPCu!yCvW5$Hz}UvFN;mLC&|;&tLL6{&o+O*WE)LEw!eJOQ6L|;!}^f!alHA3JbHO!adyz3(wo1 zDlF{3xj@P({Pvl`LZ{<}g>4TN{u|qRzg%b=8&PE&yg&O@qxlnR)IbJww*(vFp zUw%1USa@(kkBiF+j}=Pm%L{GS*C$RBD~d8fo2ViM<48r?DryBfu02#hBI3%5ss?Fc z!t6+wiyf{%HMy|(gjAf?ofUVS@I~>T?TU(Bj^qs*W_Z|h2rA&$CeczE0(@5FSh;u|3;a*=2XforS_*@ z?K<}H?xhF2v(kkV4*lL3T3YHHJly5$(yzO|^uiUn)UG7jZQQV@UoDnP zHTvUnspQ=9RO#52rCE>k8T?vlbie0AKPx>}D*aeqYWw3olqm&UD7tNeWmFaoRjd+b zs?rvpyirr7xmY1rN!Kh@HqJREWvoh5QE05v+|DhpGF53Vm*NLEZ~U+7Se3M`yvlal zJp+rHHtS>|fhAO{c&k5KvC%@1)S)k1G|m?42GGkoS z<&p@P=XIml4{a?lUMN%x*~BC3&|K!4%a%)MW^wQCqCAp{!RV0+i%buEAoX@?>{&K( zvlLUpiuo?;D8x?GHQ@CDFdMP({qR<)OU&ciFYUW>HN9WfpBHh0weQ-{dWho&5Xc?`b=?e4AQyQE3aZ|5SO6vF665 zYo&M0vZ=J*Fl0U>KsOWB8^lv&Ns_b((NU&@&+SSXaWPkvXQ{`HP_i=9Z*s?<&z(Pi z=0xV6z4<>E1_rvg1y&%!=SahyHYuc?nw-wBE5L;E##KbiuriM#v zEs4@58N}Qwxlw$rm=|0;opl7nxZc~0w*g}sO2zTx!a}9|0>{=w$x)r41kMnmvCwu6 z`2w++bvG%R8}m{4@_IQDQ&xJb#C+Rmx^~%+T}w=Zp1Tc*`F7RkE7sKVMJ0y8#e)&3 z@P&#kDZ}kRCOFlgG?*rka~EfDH`ZQcG>_oQvYq87T*73m;pXZ)=RizdTU~o=TiyR7 zF+9=k{>1P|J7o_Vm0pe3W*;VghW-X1=FS~%D!*OLZ{NNOV(K-_wNnnlZXKq`Z`(!| z@A2c=TQas-X9+q98zD>TPkBS=A@GED5Bg(WJt7CM*bf2zqtfqiZBEh^Gsvi@u<)wN zigMX}>lVn+LRuiY_50nT-EBS5y-Ph}ig56B*Y)Cz;=8GFs-p(m7@OPiUTTB`Ju1D5 zOaGcc3od`GxpN29fG0a^`_)o22=x^E?(EyuHPzR0FJHY?SzURJ^s|+Ks~K1CCcvSN z0CQubhmm?71@-K_(`YgojWyNPH2BWT%0j(+&-wTCUo;q;qN)N-;+g7#i~?mu+7}R4 zQRblDplohu3Li8!2g%FqAZ?e}~ua%c{u24HDh6X~ergAVNs1Dq@ggg~hJ17VaI zQE`gXPw=HC%TN}4M+7BanJX?2j#u25u1 zHXJpyyALDa{;=Fu`p~4;a(8si&2>7IJK@W7FKw1{yKWh}%YOHv9=U%V%$@Iz|C#j9 zY?tL{I_y$Da3R-9kupi7#qQyfh-lDWi)o_lJ7@|LGJ3(#V)KdY6Gu{aY+k?ZP-){7 zp7}TXk3Y5)!v|tHt@MeDm*)K3B`3%6z$r)H>5s6i+rKMY-Z4VTw~g=7Pa#MV)=L{?Kj1?*>hA zPI_ZAuJRMk5hJ&b721;<2*2;qg{H!Xc05;D_=`=?LhreSui;Dlc-hFp!pAq^f6o;* zO(j)j5tX(ol@?Tk%|h9ra2H0UUpLg8Vg~0G^$e>Ge_9MWX0%l2Sq!BH`^o~t+3L%N zYo(VA8q4`>2F;~AIZYsd6U8Xlz)Bp`yO)$W{ay0=z&_6`l1nrxFR+r1VZBOz>DYg^ z>pJ?M<)ceVp4h5<;6llLa8MGCYIIZ_#BJoP5nY*FXeVbc(A98IV94P4|W7aAhL~hc8H{Snz@oR~(BpjrRt{YHBpD3jf^Xr*(8&_Bi z4j}hhwV~`zO(8e5slIBwbiSgx!eGd)sxCGdD&dwegYDH4LnW&&V1}p9R$ejWROJ{h zRU2#0o-H*RfiL%tu~a^<{>IgtW#*eXhSFXh}kyw!^6`*jthNA6kP8(pG``QOTWu-2eJ2MK{kUUAhW{~~|3vs0kZ1pU}!vb60 z6%csAaM8#OdP`Z3;l@qb;BdRZP?2w_EUP}t47zKjhFr7RV1Ln^TXxl8FcvXGzpLeE z&l__MW!DXt*m;BU@oUEXoXTs4@@fDzoj+TC)o>rt%rTrgc|x%r?#1O)hf4^V0EV;f zNb@DmTl87hsqFRhW<`YutH?CRP{pZPc!IFiGdTYOHXBxR^Aa;?FJ6~1Z#$Ew#bATy=ajQ{VEC#hSKW>`n=`5`eCrZP*hwVFG$v|rU;F6SzYcy*Q>FmJGWZ^*>vjuZ)iYgl087JiLHBu6(IvpbieZNK z7j7F3IqXV)elEnZz?^GR!dcD6>~M8vnfP0ismNp_01+a$3T1oR?NHRR@Xf`mKYIf!4wfHDWsyO5 zIyv#fe+lC4dIoVV#KKC$MaB(|G!vj2u&S@ihKHasij6sh@SJ?skW+BhaIyMa4Q9rK z)#p-FYB*byXSh>nxB|hXUubi!@~q)@p+I?|<}B7-(jd zq52eLR}I?ziHFQIb@eRlT3k8CnzHH%H-&`Vtf>OyFI3l56=UikcvWXHdlfkng$8Ml2_Wm6?klPc zTFjMn)@6~oPYOxmzX%27Y5P|g$DBvKVA`G#@G5{cDCmVon$`ey%%azmOybFH+( zU~{Rg`byK(l&=2yL}6*^)!ggfUL$I5am|L4?7k!=f{&DWsv}8*(+kLrIl(qjtUTH- zFBmk->v;sri6Rc}X)ffPZIU@vt84BQUA}PPeCe(u%1zgLTeq%m6EEO8L26r6#!-H_ zqP~ZO3wd)Zq;ilsmRMc^LIAZt`l8Ia;Ne}b>;ejZ|tm(WOA(9OO)DtdG}hZB01cL^AkWa z^rzd)@g;StTsfAD&n(7Vh;HL2@&5*Av-*arKPsee9ul~~qKJ^DLP2tzJLG@mKKzkx z1KdV0(d3uCOEJ^N;h4G8$u%`RHU1m_RbR$0Gs!~0?MbqXPHU;_sBN(z)vMKN6;A5I z0?sKHHrU1Cpn$W&SNY6pOpMa6oPeBph%0Y2G1Ol~#Ul&{b!kvBgSs@-iGgIr;m{F9 zCMl1Pi8;xgf1Lb8_lLUm>Ds-|Q?pht(`=0Y3pHTdBDUdXisZ85CgB;sy2`WSpYFeK z&Z`S|EASiu&-_L|qv%ztb6+G^c5QVVY z-;Z&n_xZ_om-w=9uDqGJEbLg?aBRqxBv(^Z_$5JS>y;V_7T;QNf`JVFgtFZLS^IV! zyY%ck$p7u{zuB~Tjb`~L=woZ^*6Ohn#oTe!7GC+}Zoy#$R&27KJoyg*x4hg0U=w%T zvyY#AW&WXGKMMLZNx|!C>(;k_c!}B;ox4vT-!XynmTFJbqmw7BA6(tO5P(lOlr0@P zb-?g)?(QKzGyv0E1HcravHI31Y9z=HsbwML_d_=6ga_;hMNI&* zbDOqpJ-=N4?dDCNct19f4~EBqh#a0K`uA(RtQU0(1OD)ge0f8nX&#n zB5EOE*@<$SyI>)jfij=yXyr5k?R6))ix6Fg|h zBj|}Z=<7avFO7YCJUReA_gJ!-kJ^&#&$#Wnd3=QKDO|rdG`&;%r%cpf(yE80+(enA76}-UBz<*fEKkeBwq>59sX!PARPup>`u?2APf&uCZ@_-9n_W$(BPp8X& zoAWR6=Q^+9x|gPn8*v)RLSd%-}wn{(=W5cDQ}aPqE|BebgNKjd(6|wO!>XzsJx3SBHto>0suAlV@>G z9W7PmZo9<%>cjv3>nbZ7#ILXNmF<`D34i2uFQ}UG6-N(hJn?d5Vo6i@YwwlO7H%xC z;@6t~y^3bM_IGgPNzA&RmIiT zn4=Qf9Iu0~7x33(9V%Ob8|R^)@;j1I*;T4qR*qXUvAi!|9LD*kQG97IWVvOGyW9kP ztKoltRCbz5}`sVgi@O_B`YE z`CV3|60XaPw?FII+o<-~9JOV0hYMn-qiO9VaBbkcZfgi#LbzyqaV_Q}e|)Br#5_?Lk zr9EHgqkCrZQv<45=rRFG*Yfh4Pn9>ZREwEZa2+S8Xs%ku;&>jFRMnF}I|v?SW#`Jk zgk}-(trL>o|LTK;m}qf+0{+WLT7i9B+q7wI8E7-0SC>ATfZtSHJ|%qz`aL-ZGsXGr z0mIM{Tj`VyU_9jcYO+ZJ9@~9N%BcmW>it?^%AFeAARXtQcEkdXdFbI`#1Y2zcxcoJ zx3Y`GXN=TZUFmpyN zKw%3kd;wQ659rscYoCC%IlPji*|@0^n?-dMmT-v?iy4tLt`q9Lic@oKG$OrInty-t zEV$~U;P`JF)~ws{_rKrDW|c-cMiYyxzl1pup~H$Q!I!Cpw}3LOGAo)?0shn z9@FuKpr8Q1QMh-{u5jnfu8)L$pWkH1VvKxi)lYvazSsI9>&To=V&boZ;18;Ol)Z@J zM(EIh4p7iTw8zR=u2i8Z&XCj&ejiujqL>PdSh>pTUhOjHx&|GK>{$boya;tt<7;UkdRWBHr0|y4<6nyh{z6IOyU5+wQN|c>a&An^;lc zcAi1^V9cFB>mZgUr~ zF&h|*c%P*_U3RPMckF~4V`rR9>KkUk@O9gxY~r_!d3~h5-Gd`e;OLKN^1RoQ7w;^% zxcQ^E7A~0A_%vV*;N{!>1tvy(#?R6sSk`rfL0p`Um zjK#gqrat`4GrfijF#mQ^-(=RtGIaJ4HwBI7DuKpx)xBthP!XEBi{4rGui13`(`1^J zyM>C3lj%Uym=|TlWw^QKY_2^v^88WnqKc)bJg*P z%ycTkXMphY5V`8%>}zc*87r_kf1+(Z`z(y9Z)Kay^Brn#bUDB#F0@p1xvaj`L3E(@ zcZiW#AtudTn7s5r#jW2ydV4{`b)%e}BZ!Kl*oZsj?7obD{^*F-m-wg-?Ye(k%tFh>U;F*7j}cOU)m3Sa*uU_ zTL6B^OAmL5W*R?G6*??`i2h zO(n?!JZU`4?}E2K`0}T1%iennDzEzx?mxMYFyn=oL&WUz1JD#56bWR5M4c!!ntX z1ef8b_N9#70yiwT8MC3csyc8Eb>LV+Kg19hyq^5t2Oqrq)*@^v4Z+cgpIUH@xmP;( zWi>7+5_)*lT7E(*``@zzaIueYi|7tJUg`UASP}mqChbvJa{mtFZ|Mgn!p*wf*Wsz7 z;!}!W7O`?<=at{}9$KLM!oEPxU;Kt&^y2#->G{e9{NjflYhdYpxadxk(sAw6pZ0J6 zc>Af_zb2d}7F`DmG$-6F^iMg{fDQCd1+$_4A=HG4YNI+s%F!m4rWx}*f6*Inz4->> z?%3S1jA0kebU`d6N}La+oStwr8}YIFL&Se}2`J-y)R%`xjpI2+qiccikCZzDR?p-g zyvIKn+vOarHHyh}!psjjI0z;>`A~{)=KfgzLAy7MUY~LC@iLbhL;ETG(@%K!O!iR# zKdJxB42yT;3vkYxSS5P%nGOHjTEv*P;QK4Jd@#bu&=?EAhwByi>Uzape6WYOD}0b~ z?wdMSEm(jJhAQE)Ln4YGnl*?cU{*FX;%l`B8~BA+dSRt^3D{D_`PpyU9TR?1OL0%Z zNcUM&hw%@*dVN`s4SK-__)>ipAI<$+e%Xohc?-Gn@fY`h{ACBra~HCDaelRB&B-1V zK?v)2qw4-#uv+pCGosKxhf4Br+|3qCni>^|o)k&w$YGh^g-ifdUyCylh?7Kw2IE+p zzaQE1jd)$|%Rst3Jek%rx0j!d|Gg&=!U*p`_W|;O?;bwa9VTFFOl_%E#YN99I1D&rkC7ft;7Ls35gy;~v}Y$o~}~s`=?8r|4&*fssn>glDI}*W z78J>gZE`S4SwE>)UnLHr}TQk_ZbWMUdjax(5{EzRMUDC!7?%O7ySm&l+)VU`4u_ade=LI!aIv5Tg?M()%|2Fz*zXhz`@LEZRK z*ugu|p1&?Js&h#8)4lg|uEa|Dp(j@j#2qjq|HZ9our~XKJvz4Bnj2G7WN1ud{pGailxc}tCHJS?3)a|&0XOutoSbn(QpMt`kCkT%kxBQ~Z z;K5HiSE`vX^-bn&=8fLtqX0shi~!+Himz)y z?EFYMH*Gxz8uQB@9`xOSr+?+vG#30P zCGVx&Tq;slTupnSmj}6Rdz+lmyE9n0G7%egDK8+$6()tqUx`c>{Ub%lkv7y{7N_H5 zYyqbZ5liSsGN{TPHcJ%{x~&8T`1$&d0H8+Pt9~u#RP1akt63@XgG3HXEnA=rRBf(9 zCtR<6O~Gj-Aq61Cl>j1AQ6ect|Ipl!l5oMMPL&xm=@uy3PG$7S!YZOema{s*JHo^@ zK;o|;alSVj7KW6c-ITu;d*N*6g5b4m@VR9fH*2^XlD zbfQmqWKk*7=5hnAP`VE<8aHzK8@+@lVacFTf5 z9k~%r@X^Q|FRq<9Y+$zmJw|4&?NDW8@HB4J`-c*GuSMAZb_luYg z6h)Fr1GbU#LOzwCMi^hcX#`cE~7cn007zsm4+?0pKBATtB ztj!ivOQgxOam@rM#-Tb&Q$_IzC*&@IgTXN$Z%?AJiCgJq=G0){V*?fHT2B0|qRkCv zG_jFubOc&K&EiIC`qY=_YDWe1tds8=H4oEKRWB=su;!}Zx2Y#dGltfBN`~nZ>5oq56B)BsITvniH0Y%0o z1}(s2DxZN+3ORuBK>4-i;jr#vwxSTDzY4<@67W+?f2@p=Uu2FP%P9NP?h0GdDxFn1 z7BdT5702Fxm%Trxa}HyAO0IMS*Sj8gl!?!Ti1%b%HbmNpBhUHWmS6I*|w>NFj`MFt6;mmJN6(GxHA! znxV}vBHUhYg7BG(otN(?NR((2ki^ID1IditMS(>5$NNAMaK8TTi!Z+W8n86SHa7{W zUN}!#)Ga1{cDtCd(Hj*!BJ0!gfWT98hpq5sbH<^o-D6nh=`P2F78;O_Y)UQ@lLSQT zUtw7`=6Z<4FVrDo(NI9qRJjWK)dED8IJ$RIj&W6*`;uExD{wHmKV0?wlISmTtE=-? z$A0|1X6c8hzdke5tUq$ajhtd#w5CE=iZ7*>%{4LD`{9!?ag2S_E|*r;mu`!h>#ACyH~I|leIlVA zP~{iGNEUTbq>AM_m{1V_%40NfvAD(pMa_!OOIa{%5?ES5y7zd-wpIVzlAgY0+48M> zHEEkH;xsHAgRi}>b4}1neAV61Bv7XX&#R>tz5UmmrBVUL?3R7h!N@GR$ogn$hrNZ0 zjvLU-<+o8gP<{t-{W4~(sASr5=^$J(ovz)6t2K7Q@1VR7T@rau z39K5&V0HyN;<^kB{qAD5fT*3n@+F`(T>QGkU@@6 zKwJ!w+J#6Z8{N8P;AkyH2(G*)nRVR`mp*)O%vAC=Uwo#NNni{Ynz(Rrw zLXmWgMna=Lp}s!K{M)4Fmfn`j^@lM3e;n8B``WtPhTL^@eshmkU#{RN3s&pDD#o>Z zd?7#T=3DO;X_2>RV!_o|3+>T!LL7Xt(k(@r1<_~*EeP&JLI8;sBtr^>7+6;r-|zTG z{`DKT$_^a={Yb`k%{O1wyKh>DJd#|B<05xT;Z~QTvOr@l#Xsu3()KR ztCYa%sye-M$;ZF`eXD7!i@V(8MhHHDgt}1NX^^4~2@}Lfkrr%H{iA3vrVY845SV_H z*~Cc^D%4Oc*lEKb;3n{U+=K?Bix}ByuEmODVcPHrq5CLW(h|B_h&-eo`7Fr127!r4 z9?>c+RCHPPr?`W+r^m1d5pb_B016PGZX~+Zp31uKAKuF2HlQ<%g>sO|BXM^Ti&E|( zH^xvs0Ep}W0}R`EM0kiwq>qo6*EEj@a_JsJU!k#)h*evZUEe=sb&q*lOg6roVnbvM1(^6KcF=AqDA zKW&MfOg+1Im21X7vE}||7=rt1=`z{XeFA>7^82nBmS*;V9#p^FWDpB=_Q5g`SSY+5 zK^n3{6dVG`2=t`bQiOa^9FhgKK)D6jJfWFhWE$PAL&0@2jYz6_gp5S0C5o!TNWDkFzivyhckF{WZ9wY}wzA6c z2B}dq@6zyKU|oSzRcOzipCG^U&K#duDv7Fh{LjK$EA>1_2A1tgHYlSm<64B|2 zmY2(r4tER$kYE@>p`m1t@<^?SbO|VtfWo8fuo(z{g@v?4d{y<%rg=;mM#A18LyAxr z9T9xgul9&wZH>~`?v;f-bGh8(Oj@gI^#Gvy1{JLoKs88|{&RmU6v_sG%N7D)3+{%{ zt`Z^w8w7xOj|;v<2r<$O2uS=yz|;c$l=daB1;V4y-ykKb(m$x~U|?-=(b(@ekNkk| zdFFO$x9>$YOWpB5%!R02LJ^#G^XF4;F?5Q4dR^A@%h$ zoVb>OH#p|^LS5C&7oqIVfWNP|MS)nMF1Nu^K04Z=)*Y!iPUWpB>ftleu?-gJ0OCPd z2&gwlXhA4R4UcSvuP_Z_DilwV1v?98m%LpMV*MYyMZHsdQj!HH#~L2lt1a2OIcz}3 z8GP{!nfIBvsKKc`PNz4N7`~dg6mLze;d|owTFd|owj&)A0tqs~4&YH(z)|%6P;?|z zCw3{g>coE7aU?qcFpL1y%ScMgE5x}AL>O+N`p2>UAv+Vdrzk$8LM~SmliBxQnfHn4 zvq1YG+=+ly8UpW3M)dJ6N@Hdw#K%O2p{0hPRFM-arS;N@(!XbFPrjAcW)n}|pP>5$ z_^-38%tqcCzBP~WKqqLBAi+b0i7Zkd6%7#(^575|`^Gn)&yETW36+DKXaPcxLwN`( zs7(!O3O7mxAWc1%2GZ30VAG`CW3Y?3zfRx7Wze4$tcE#`+{`MT_)Wy$EM{hN?1>Y9 z=dpIvQTH*OI2DYIU$FpT1CsPoE|o`gf%L|{yX~vluuh4e6lS7mxG!@}!Rgw-@7;jM+SphzU?6k%*0 zMfckEf=#aabL`W{nG&ggbY1T~`C}e)8pqhVX9vBFsNUwc{TQ?TYA$=#=E;qW^-Js6 z?nz_#{|3KtdCU_-jw9&5yyxJ&ah-7nM4TT$=B!B+WW3d{ocMdFLug_*q z7RG$GT1IEGk-mfOAhwLq{OX4 zk$UHgjHNoh>4c_4PSG=;d6SKdcg?Cpq8CWMVXW)z{nJOY6FnFU`Gi$THOg6%O6Q8P zt0&y_?{XE=0j6{rJun;Mj1v(QDZ<>gy1mwRs4vmNQAzsX0 zjnF$^VoYP0*0xv84QWSa<~fMhkL`1jWl<)jlYsIqV>|l(_z9pOTpaQ#L7|f*4%gX; zAD*smzX7Sm={!)6Nx`~ReT)bmPWqY>G7;u*2VkPeBzAf>-KiGO8zkKX-?s{QiS}qk|n*km;QUE@-p4 zZsODvB4?y5_DKf|P}&8OUch>iA&5LwPa2Na6G9mfMjH}FIn0i>IPA33nSTrHwc^It zNy^+c?xcv0B*2P(Bu!$yH?m))1n!}L?^Gh3f1?KB{F~-VrbC{l9I0zM?}6}mfDDn- zLOshtx?pT_p_VW`tr`#=VGL_0iq}a6z~lDzgnKe|vO@1&9?CNfJruQd$^Wr)$-noX zRZGLzzBpbRV43bj`yDhg76$FZVYZ`FmPL~d02 zan-QCPARgoOS@5DgnW0icCImXa{= zCb_>r0Gjkt+Noa0l$CP4WcfezB54W$yj=1U?R`N%2!mF^D&}fzie$%z3T0Th4gg?R zD*(WM)zq6z0PgivdfnxzD9uIw&%H&O0AS>H)_MVJvo9N93BWFho8lTmv7=xbWGPg} z&PX#sg5*OsD|T}g$XyiHVc*(D&If@int(yUTm5zc9V${pMM|? z4b$Mi|5!%@4l~rxgxgU^_U5I+Z*ZNjkFT#E^T#y%%hP3rU|TW6p>(^Ps>s@s<){Q2 zp}=S>ZwARC@olFhz7Kw<(A)an+_#-~vy_ReO z^diC=P5laq%P^J{lHI}O<~kwB+9M5ar=-CTG$6h~CfpXpH!BrRq%(+ygr&}>VVziK;bpZ4C~jBsUR06}%?G|BKTB;_K(d70%b?#_g;<;U(|p zCdZ381NGd`24(q>6CQ{dHHeo(dtr4E?ctF#W+lD#;oFI^;gn>da2C-%Ws>^@L3@M5 zMYT9FwX`X9sX0_HU9JGAmom3iQ|8@afdF5u&h6I7kPs9{x6H$>hXl!Wa_Z;ae z5(m1PgvR$f*U!O!^A%yM?R1Z_ZGPjyd3Zu11BvX%{q+F|>XLH-4?INZ(QYB35fL$o z%W`gBT$KaGsc@%V@5$!v4dVFxN)Tgq?3{dR-dk_5Z1@7En;x zK=7ctECHH8_!F?UXa$9I#U?)^{`Id?zI}aWq*~KSps>TMvvZf5(eRYmAaP3UzZ?>C zZRC(x6R==vS&Ia$rk3Pw!6d^^vEtwm=--(5xeMmanh_@8ki8<5 z*aT%6-Q{*PJS8?roD%ylhs0Xndq}JaG}faET*#S=AGsC4fH$&mumScY2tuPpMWbLQ zDgx(3sa%2tjWjWVXe2$-@NC#1aW;(3UsFwebB>0&HgYtqnJ}2I6O^)_pA`i}D+tm1 z5JVGDWI(PUc5gaRbuWs$9gsGSoC3S=A+Wy9JOtJh3%C!E;E5n0H(R+G% zdi#idi~HI6`$B@T4#~9O(`}R}C76cE$5ss=+lPDcX%3_nL5g5mL+|3x+O!BVP3p0! zW>BG>=7nhkOE7J)%g6{0FvA(<(>ud}r?4EYEHc!|6qxMpu8iKKzhGsy?KDqMFZ?QP z%^YIQ1N4fjF;8~{qbU$Il;DxsFBy8i1k*>)j(wm@uA3f}_cB+W*7AWcIF% zty>fP0j@WyGT^}1;qA@Ashf&jg!F_bX$oiw61xD>6%Mrjz&wDs$-dm1dpWDSCJjAi zNcwfIHGg10m1HDKQ!GZTNVZ~UIZPB(Rm$Fyk{PwplA zIQfDaOs3GGh}Iwgf$3|FjnYGy$7HpP8#9`uNHUuf^+{+D6262jZSm#fv1q#Oz*zn1g&JD@y8t-wR;oUb0tIgQ6uHpPCL2XreW2=p;u34i>XY5o3Fp|I(to%6b2%XN=FqIs@HU|$KyiTpB6Mbl!L8I1VDn@3|;KWMqZ3Y(^ ztq&4OICIctT7@`lJ+!%v9!;7=QD?Tken{WJC<@dgju7hai>O+~Iou*=&qdQtRBj^z zTZ*+#%{$>zmaJ_;{#33p5B=0BQ>J=&$XFlHFWx3!N1@b+By2C(kZEzy(x3n^DL0}? z(e5t(p72_PEsa!ZkdGhwyEbFUsro6Cr$C-$OqHXz7c3|2%E%e}Fh7kimLnV{Fv5k( zBqoy?F&^u2)Zp|yE(KLgz~AN!;xL6=-6@j=GT9Sr3hZ_QCfdhHE_^UdTi62>HxlDa zB)vU)B#q-zc&+gA#S7=poy|Fyn|G<;QnQAXCRrxiSXs$oJreJjuTBgm`?T{53il&U zDx;BxCR9xuFIL%}WIuVzR4`42BYW8c2kptQVSLSa_RMz!#Iwo0pE#b@-l%8(%d^2O z@oa2%U=$*UpdMP>NA_;#8yEsVf~+AjZiN8g+0C2ED zttO^~SjD~CkuXsDvu>zSn2-y+Sw>6kSei+b*%Ut69*Ye|9A4^RWc*oWTK1AXxrcMZ zff}`0w6}Ay#yHm;-d@5rxp$gU>M9A6JDbF&NYL!IU@BrExasuLSCU|x>ryrAPQ{xxE{3Na&gaDJy5#Bg^$ ziBGmn;ZwDk8`6X%abSqItqmZacI)0WI1k^x&q_)EBA)%B@!OM_;1 z@?+{*HfmW2l{k6^$_Ly;B`>N&Q+bt}ELzKpqi^aN1hRY%JXnFr?wU#N@+AFaY&RYr z79m~|ZH>ZIrfpo&mu#|=@CL`yYE(ho-{8@F+Xc1UTiWu~V5!Ser!9Bfj;ih6(QVMe z`<>}O1h$A;z^kO1MPqnz`b|BdK;}{N5!es{1_XM~X`b+3nHM}w(#OoRy@~<)L^0Uv zVYshVr1`cpApFoyKxnyiI_D#{si)kQ2Ag=tidd&TT&>`>0zk?6Xx!fGpju6^pfVmj z1CA5j-6!Jjq)AXImZ_45S=mrM;jV*tJ1g;Ql8!`r3>(cyYG`%UTAYoUOK1iMAqsm* zB_GkKk=xXRZ%adKc>6bA=4t`2m3WwZuY8X4QK~gXmQ^#jFHL0bc0@f^9P|X6$}t6E z8F=cE6odw3)3}GLh}8n8*#96vBc2ujnzE*>t8y!1{r0d|06?6E!wNO??s=Sl6v>q` zUiI1z(b!y^oD)4b&=cJ7|4O@--8hOU+VgN6+bF?`NTgVbS%9oa2!!n&67lrRnCW*< z&rCLa01E^w*svp;Y!P3;2V}=DSP>{+kcSj03xotpBC)XJ>8i^)x4S1Zirow#dtr^N zx~Fd4$GJ6Cx3=nLQ0_rFk%^m8oY>S!3_RH)m!tL_+uQl%t=o+7N&~S2VWV~89~>U` z`ov$wl(Tr&?}LxL8|bL?*9ULkdRC$@+N~4*&h_`Y?h`2v@=EzdIs38{cj=0I4di6Y z?MaZAYH^5HzY)i0yh&G( zGVrrH`!4k>Q6r8{W0Q(nhZ(owpc9~z@%n`MgwZ;QZM34sacFyu{r|?vW&%$%EF(kc zVz!XAV1gzfPYEEN?A5)B05Y}9@p2Ph?h}&j0z7c3o9KpvY|~cGdKsVMd4hoyZ;Y#sTw>q zQ667RQidLoOq;D?Sk~wG&B5+h>D8Qz4c7e6im~^W8(YF0V_T9vFeM}xmI~P_c?^~u ze+p>LrVbvEF>oc^&fbz-Y;FRlu>;?gp<(pTR)8H9axuJ3E->PNo!Y~8-|g%!OTVh& z0|}kz6_nqk1EuXDbz{K!GfFX;1Jz4%S>u{A?p~Kt&fs44thW2O`=RdXYQv!5#VG-JQ`~%Yd3oUX`w_Zv%;(cp3=|UDE4> zSS-;DG1iGI1Rt&5Klt59B;u`<0CX z?wP@n_99yXut331cna%6s)Kq_E>o|$TJaSE1yUxszT&*~u_ozrC=zjwwtvJ%(eBq@ zZLJ-P_E%nHL^0kxy6an6pX(2>3{EfiE#e2rX{uJpSSu-`5eu)x#1g_&;BkY#?X7g( zgA(d_`$uX7_cx!)m)X(L)=_y5Vvzvxs?wbdXKLpA1Kg|OZ&i@+41Gr7GE5kR3FV?d z%oukSYApgpfau((ZfAJw_z$f1n@{qeuf0IMwq2ZiSfo1y{CMLDj9~9BsH%1!tHWE> zl-|^D1R-5qlBp`TMWxyTY0R_*#iCRJP`9I+tz$aCdAxH+aEjsDhtG>9#*4g$?;~FN z?&7XH*B_wH2uhsRYYsfm`T~Om^999Ztd-Om=BY`X*hHJ$oyY&EN;{o{Pie2`(3-i% z0CQaC_$63P*$|-SUTXE_vE$i+020(!U_$AXwjx-iO{WT}5eCNFPzQ252SoILc9;GJ D^7&X` literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step3a.png.svn-base b/docs/web/img/.svn/text-base/step3a.png.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..b243a986a407375ad300df3ea25c565ac93cbd65 GIT binary patch literal 66069 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 HEbM;(pam1p literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step3a.psd.svn-base b/docs/web/img/.svn/text-base/step3a.psd.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..01958f3b140d86ec8ba172d721d0df433340e07a GIT binary patch literal 164750 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 z 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 z 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 No*n$#AjQL{{||gy!i)d_ literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step4a.png.svn-base b/docs/web/img/.svn/text-base/step4a.png.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..2e66426a2ff81a785cd82f567ae6abc781a252e2 GIT binary patch literal 65076 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≶&3GcL%h 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

4sW$gjGu|;rMTG<1R^9;npu%+ zIf>2p(1<#A7^S~?-DCR?#`?_faP3hlu^D|V$Fv9QjJ998=g_qi8eZ{nLp^w~dt!rU&*m)818fjqqm@ZzF2!1m#z>Ss3F)bsHW!l(FEo?LXvwI1O80 z{ke*vJKyxwl)nFVjXFwMPi6N50d0hpDom6q7b^a!uJty2%>rF4F4=lE2n~6WgI9)m z!4p^$Z$p8gPvwBal(8CkeS<7~jj*E_9?75Igxo z&t6VZ5qp13+7*4LEVDw~J3XoqX3C0eZ$jCh(WZgE2@3n(|=QKvc#E2PjeJME8#zL-+x~ZBJV~#C@i*vJky3 zxxA1y%>stJ*=ERmM*gXi|HQa`Ti4E8xo=n!gF?C(ayga=+e+{(9-mw;Z`+S;JLG0s1J(-qDd zUZ9(3dOjw<7{0rIv}`dFK2PRxrx&0BjLxVLyMj(aJ#yL@jL|VL=wHEiS#sr35r+82 z^qmo6-*q)V%g**8^ zc5q^<84?;&0?Fdcf^1QX+~YpR`jVKARge|Kvs!q&&#ejo$9!>ROfoIUbB- z2!GkNu4wHdDv)XAIl{kUMiQyCvo`WrcIeCK$G2*W-nhCcR?#*+EN{hbIWzhUq*mTy zs~zjuH1@1N$|*OFYjO9Bq>z1_gf)KoJ|pE6rJ{s*vTrY}3duZVQRbQ#s(&^7)Ht1N zncD!txRUoK-QInXkGE|sB`5b*C)_Mo7aUnNEW*-`SkTNjjA$Q9bB3^OqIo{f`L;VC z#TSBWr1$P6CZ6nd*0dmz_tl?Tal(O4g#ln)yiLV)VOFm<+`wM3(0 z{YJSWq=1-yFsC{Vbedp^lk=dibyyb`p-x{&!ICgyRoq+r{*u)Aa-pJAiz%MY@GTq1 z#@Eige386vQ_})0=FXn7DsB9Uf=`AJw1!XA)|EZV`XThHk970p#B7+5XU_e|U&o|{ zxKqXW7L>zWieDp-y4uEV#2#|oCg5`hAcJv~&7tn?(BB>%x);EJ06l8NZLE>EK1jtE zl|S;oA3F;_Kj`=G-}c3aExqVz#HdJF2G6&lJGPii+qLQP6a+7fhCj)r{ODeY=) zF8zVd9i5F-6Y-<&gOk`R2xpN5?46R~rRFb#I=@}{Djv#vna{l#$Lk@gfF`s|yan>N z4ueKWoCs)+Jg7(21v@C63rsfdNo4H@*~WMm)AAwjmbV?u*Y->APdz%xmA<$P#wATV zU&CIoe>LNM#iW!V#8*2xV=}s!dN#H#sMuhD4QwVs-vP68JWx

|RVwi&k{-en`5x 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

VeMzVh7Rj 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 bKE^w{N;NZKn6Q{ign&y+4GybOL4^Ge3yda& literal 0 HcmV?d00001 diff --git a/docs/web/img/step1a.psd b/docs/web/img/step1a.psd new file mode 100644 index 0000000000000000000000000000000000000000..078555a8ca723f88ca11cb2134165815e9b310ed GIT binary patch literal 146999 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 TXk@cFYsN5y{d{b2{~`WAi&DWl literal 0 HcmV?d00001 diff --git a/docs/web/img/step1b.png b/docs/web/img/step1b.png new file mode 100644 index 0000000000000000000000000000000000000000..75eb7c9372714a655903a36c5a59bd3cb5ff271b GIT binary patch literal 59744 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τm03>+xQD8&POu(|%K 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�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 literal 0 HcmV?d00001 diff --git a/docs/web/img/step2a.psd b/docs/web/img/step2a.psd new file mode 100644 index 0000000000000000000000000000000000000000..3373f4980af90eb0a4d526cb04ccdc05c655d351 GIT binary patch literal 166898 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 D^7&X` literal 0 HcmV?d00001 diff --git a/docs/web/img/step3a.png b/docs/web/img/step3a.png new file mode 100644 index 0000000000000000000000000000000000000000..b243a986a407375ad300df3ea25c565ac93cbd65 GIT binary patch literal 66069 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 HEbM;(pam1p literal 0 HcmV?d00001 diff --git a/docs/web/img/step3a.psd b/docs/web/img/step3a.psd new file mode 100644 index 0000000000000000000000000000000000000000..01958f3b140d86ec8ba172d721d0df433340e07a GIT binary patch literal 164750 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 z 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 z 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 No*n$#AjQL{{||gy!i)d_ literal 0 HcmV?d00001 diff --git a/docs/web/img/step4a.png b/docs/web/img/step4a.png new file mode 100644 index 0000000000000000000000000000000000000000..2e66426a2ff81a785cd82f567ae6abc781a252e2 GIT binary patch literal 65076 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≶&3GcL%h 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

4sW$gjGu|;rMTG<1R^9;npu%+ zIf>2p(1<#A7^S~?-DCR?#`?_faP3hlu^D|V$Fv9QjJ998=g_qi8eZ{nLp^w~dt!rU&*m)818fjqqm@ZzF2!1m#z>Ss3F)bsHW!l(FEo?LXvwI1O80 z{ke*vJKyxwl)nFVjXFwMPi6N50d0hpDom6q7b^a!uJty2%>rF4F4=lE2n~6WgI9)m z!4p^$Z$p8gPvwBal(8CkeS<7~jj*E_9?75Igxo z&t6VZ5qp13+7*4LEVDw~J3XoqX3C0eZ$jCh(WZgE2@3n(|=QKvc#E2PjeJME8#zL-+x~ZBJV~#C@i*vJky3 zxxA1y%>stJ*=ERmM*gXi|HQa`Ti4E8xo=n!gF?C(ayga=+e+{(9-mw;Z`+S;JLG0s1J(-qDd zUZ9(3dOjw<7{0rIv}`dFK2PRxrx&0BjLxVLyMj(aJ#yL@jL|VL=wHEiS#sr35r+82 z^qmo6-*q)V%g**8^ zc5q^<84?;&0?Fdcf^1QX+~YpR`jVKARge|Kvs!q&&#ejo$9!>ROfoIUbB- z2!GkNu4wHdDv)XAIl{kUMiQyCvo`WrcIeCK$G2*W-nhCcR?#*+EN{hbIWzhUq*mTy zs~zjuH1@1N$|*OFYjO9Bq>z1_gf)KoJ|pE6rJ{s*vTrY}3duZVQRbQ#s(&^7)Ht1N zncD!txRUoK-QInXkGE|sB`5b*C)_Mo7aUnNEW*-`SkTNjjA$Q9bB3^OqIo{f`L;VC z#TSBWr1$P6CZ6nd*0dmz_tl?Tal(O4g#ln)yiLV)VOFm<+`wM3(0 z{YJSWq=1-yFsC{Vbedp^lk=dibyyb`p-x{&!ICgyRoq+r{*u)Aa-pJAiz%MY@GTq1 z#@Eige386vQ_})0=FXn7DsB9Uf=`AJw1!XA)|EZV`XThHk970p#B7+5XU_e|U&o|{ zxKqXW7L>zWieDp-y4uEV#2#|oCg5`hAcJv~&7tn?(BB>%x);EJ06l8NZLE>EK1jtE zl|S;oA3F;_Kj`=G-}c3aExqVz#HdJF2G6&lJGPii+qLQP6a+7fhCj)r{ODeY=) zF8zVd9i5F-6Y-<&gOk`R2xpN5?46R~rRFb#I=@}{Djv#vna{l#$Lk@gfF`s|yan>N z4ueKWoCs)+Jg7(21v@C63rsfdNo4H@*~WMm)AAwjmbV?u*Y->APdz%xmA<$P#wATV zU&CIoe>LNM#iW!V#8*2xV=}s!dN#H#sMuhD4QwVs-vP68JWx

|RVwi&k{-en`5x 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 + ParseKit - Cocoa Objective-C Framework for parsing, tokenizing and language processing + + +

ParseKit Documentation

+
+

ParseKit

+ +

ParseKit is a Mac OS X Framework written by Todd Ditchendorf in Objective-C 2.0 and released under the MIT Open Source License. ParseKit is suitable for use on Mac OS X Leopard, Snow Leopard or iPhone OS. ParseKit is an Objective-C implementation of the tools described in "Building Parsers with Java" by Steven John Metsker. ParseKit includes additional features beyond the designs from the book and also some changes to match common Cocoa/Objective-C conventions. These changes are relatively superficial, however, and Metsker's book is the best documentation available for ParseKit.

+ +

The ParseKit Framework offers 3 basic services of general interest to Cocoa developers:

+ +
    +
  1. String Tokenization via the Objective-C PKTokenizer and PKToken classes.
  2. +
  3. High-Level Language Parsing via Objective-C - An Objective-C parser-building API (the PKParser class and sublcasses).
  4. +
  5. Objective-C Parser Generation via Grammars - Generate an Objective-C parser for your custom language using a BNF-style grammar syntax (similar to yacc or ANTLR). While parsing, the parser will provide callbacks to your Objective-C code.
  6. +
+ +

The ParseKit source code is available from the Subversion repository at the Google Code project page. The latest tagged (stable) version is recommended.

svn co http://todparsekit.googlecode.com/svn/tags/release-1.5-tag

+ +

More documentation:

+ + +

Projects using ParseKit:

+
    +
  • Spike: A Rails log file viewer/analyzer by Matt Mower
  • +
  • JSTalk: Interprocess Cocoa scripting with JavaScript by Gus Mueller
  • +
  • Objective-J Port of ParseKit by Ross Boucher
  • +
  • HTTP Client: HTTP debugging/testing tool
  • +
  • Fluid: Site-Specific Browser for Mac OS X
  • +
  • Cruz: Social Browser for Mac OS X
  • +
  • OkudaKit: Syntax Highlighting Framework for Mac OS X
  • +
  • Exedore: XPath 1.0 implemented in Cocoa (ported from Saxon)
  • +
+ +

Xcode Project

+

The ParseKit Xcode project consists of 6 targets:

+ +
    +
  1. ParseKit : the ParseKit Objective-C framework. The central feature/codebase of this project.
  2. +
  3. Tests : a UnitTest Bundle containing hundreds of unit tests (actually, more correctly, interaction tests) for the framework as well as some example classes that serve as real-world uses of the framework.
  4. +
  5. DemoApp : A simple Cocoa demo app that gives a visual presentation of the results of tokenizing text using the PKTokenizer class.
  6. +
  7. DebugApp : A simple Cocoa app that exists only to run arbitrary test code thru GDB with breakpoints for debugging (I was not able to do that with the UnitTest bundle).
  8. +
  9. JSParseKit : A JavaScriptCore-based scripting interface to ParseKit which can be used to expose the entire framework to JavaScript environments.
  10. +
  11. JSDemoApp: A simple Cocoa application used for exercising the JavaScript interface provided by JSParseKit. Note that this is the only target which links to the WebKit framework. Neither ParseKit nor JSParseKit requires WebKit.
  12. +
+ + + +

ParseKit Framework

+ +
+

Tokenization

+ +

The API for tokenization is provided by the PKTokenizer class. Cocoa developers will be familiar with the NSScanner class provided by the Foundation Framework which provides a similar service. However, the PKTokenizer class is simpler and more powerful for many use cases.

+ +

Example usage:

+ +
+
+NSString *s = @"\"It's 123 blast-off!\", she said, // watch out!\n"
+              @"and <= 3.5 'ticks' later /* wince */, it's blast-off!";
+PKTokenizer *t = [PKTokenizer tokenizerWithString:s];
+
+PKToken *eof = [PKToken EOFToken];
+PKToken *tok = nil;
+
+while ((tok = [t nextToken]) != eof) {
+    NSLog(@" (%@)", tok);
+}
+
+
+ +

outputs:

+
+
 ("It's 123 blast-off!")
+ (,)
+ (she)
+ (said)
+ (,)
+ (and)
+ (<=)
+ (3.5)
+ ('ticks')
+ (later)
+ (,)
+ (it's)
+ (blast-off)
+ (!)
+
+
+ +

Each token produced is an object of class PKToken. PKTokens have a tokenType (Word, Symbol, Num, QuotedString, etc.) and both a stringValue and a floatValue.

+ +

More information about a token can be easily discovered using the -debugDescription method instead of the default -description. Replace the line containing NSLog above with this line:

+ +
+
+NSLog(@" (%@)", [tok debugDescription]);
+
+
+ +

and each token's type will be printed as well:

+ +
+
 <Quoted String «"It's 123 blast-off!"»>
+ <Symbol «,»>
+ <Word «she»>
+ <Word «said»>
+ <Symbol «,»>
+ <Word «and»>
+ <Symbol «<=»>
+ <Number «3.5»>
+ <Quoted String «'ticks'»>
+ <Word «later»>
+ <Symbol «,»>
+ <Word «it's»>
+ <Word «blast-off»>
+ <Symbol «!»>
+
+
+ + +

As you can see from the output, PKTokenzier is configured by default to properly group characters into tokens including:

+ +
    +
  • single- and double-quoted string tokens
  • +
  • common multiple character symbols (<=)
  • +
  • apostrophes, dashes and other symbol chars that should not signal the start of a new Symbol token, but rather be included in the current Word or Num token (it's, blast-off, 3.5)
  • +
  • silently ignoring C- and C++-style comments
  • +
  • silently ignoring whitespace
  • +
+ + +

The PKTokenizer class is very flexible, and all of those features are configurable. PKTokenizer may be configured to:

+ +
    +
  • recognize more (or fewer) multi-char symbols. ex:
    [t.symbolState add:@"!="];
    +

    allows != to be recognized as a single Symbol token rather than two adjacent Symbol tokens

    +
  • + +
  • add new internal symbol chars to be included in the current Word token OR recognize internal symbols like apostrophe and dash to actually signal a new Symbol token rather than being part of the current Word token. ex: +
    [t.wordState setWordChars:YES from:'_' to:'_'];
    +

    allows Word tokens to contain internal underscores

    +
    [t.wordState setWordChars:NO from:'-' to:'-'];
    +

    disallows Word tokens from containing internal dashes.

    +
  • + + +
  • change which chars singnal the start of a token of any given type. ex: +
    [t setTokenizerState:t.wordState from:'_' to:'_'];
    +

    allows Word tokens to start with underscore

    +
    [t setTokenizerState:t.quoteState from:'*' to:'*'];
    +

    allows Quoted String tokens to start with an asterisk, effectively making * a new quote symbol (like " or ')

    +
  • + +
  • turn off recognition of single-line "slash-slash" (//) comments. ex: +
    [t setTokenizerState:t.symbolState from:'/' to:'/'];
    +

    slash chars now produce individual Symbol tokens rather than causing the tokenizer to strip text until the next newline char or begin striping for a multiline comment if appropriate (/*)

    +
  • + +
  • turn on recognition of "hash" (#) single-line comments. ex: +
    +
    [t setTokenizerState:t.commentState from:'#' to:'#'];
    +[t.commentState addSingleLineStartSymbol:@"#"];
    +
    +
  • + +
  • turn on recognition of "XML/HTML" (<!-- -->) multi-line comments. ex: +
    +
    [t setTokenizerState:t.commentState from:'<' to:'<'];
    +[t.commentState addMultiLineStartSymbol:@"<!--" endSymbol:@"-->"];
    +
    +
  • + +
  • report (rather than silently consume) Comment tokens. ex: +
    +
    t.commentState.reportsCommentTokens = YES; // default is NO
    +
    +
  • + +
  • report (rather than silently consume) Whitespace tokens. ex: +
    +
    t.whitespaceState.reportsWhitespaceTokens = YES; // default is NO
    +
    +
  • + +
  • turn on recognition of any characters (say, digits) as whitespace to be silently ignored. ex: +
    +
    [t setTokenizerState:t.whitespaceState from:'0' to:'9'];
    +
    +
  • + +
+ +
+

Parsing

+ +

ParseKit also includes a collection of token parser subclasses (of the abstract PKParser class) including collection parsers such as PKAlternation, PKSequence, and PKRepetition as well as terminal parsers including PKWord, PKNum, PKSymbol, PKQuotedString, etc. Also included are parser subclasses which work in individual chars such as PKChar, PKDigit, and PKSpecificChar. These char parsers are useful for things like RegEx parsing. Generally speaking though, the token parsers will be more useful and interesting.

+ +

The parser classes represent a Composite pattern. Programs can build a composite parser, in Objective-C (rather than a separate language like with lex&yacc), from a collection of terminal parsers composed into alternations, sequences, and repetitions to represent an infinite number of languages.

+ +

Parsers built from ParseKit are non-deterministic, recursive descent parsers, which basically means they trade some performance for ease of user programming and simplicity of implementation.

+ +

Here is an example of how one might build a parser for a simple voice-search command language (note: ParseKit does not include any kind of speech recognition technology). The language consists of:

+ +
+
search google for? <search-term>
+
+ +
+
+...
+
+	[self parseString:@"search google 'iphone'"];
+...
+	
+- (void)parseString:(NSString *)s {
+	PKSequence *parser = [PKSequence sequence];
+
+	[parser add:[[PKLiteral literalWithString:@"search"] discard]];
+	[parser add:[[PKLiteral literalWithString:@"google"] discard]];
+
+	PKAlternation *optionalFor = [PKAlternation alternation];
+	[optionalFor add:[PKEmpty empty]];
+	[optionalFor add:[PKLiteral literalWithString:@"for"]];
+
+	[parser add:[optionalFor discard]];
+
+	PKParser *searchTerm = [PKQuotedString quotedString];
+	[searchTerm setAssembler:self selector:@selector(workOnSearchTermAssembly:)];
+	[parser add:searchTerm];
+
+	PKAssembly *result = [parser bestMatchFor:[PKTokenAssembly assmeblyWithString:s]];
+	
+	NSLog(@" %@", result);
+
+	// output:
+	//  ['iphone']search/google/'iphone'^
+}
+
+...
+
+- (void)workOnSearchTermAssembly:(PKAssembly *)a {
+	PKToken *t = [a pop]; // a QuotedString token with a stringValue of 'iphone'
+	[self doGoogleSearchForTerm:t.stringValue];
+}
+
+
+
+ +
+ + diff --git a/docs/web/iphone.html b/docs/web/iphone.html new file mode 100644 index 0000000..3432a97 --- /dev/null +++ b/docs/web/iphone.html @@ -0,0 +1,59 @@ + + ParseKit - Cocoa parsing, tokenizing and language processing on iPhone + + +

ParseKit Documentation

+
+ +

ParseKit for iPhone OS Applications

+ +

Including ParseKit in your iPhone OS applications is easy. Follow the steps below.

+ +
    +
  1. +
    Check out the ParseKit sourcecode from Google Code. The latest tagged (stable) version is recommended.
    +

    svn co http://todparsekit.googlecode.com/svn/tags/release-1.5-tag

    +
  2. +
  3. +
    Open your iPhone app Xcode project. Drag the ParseKit.xcodeproj file from the finder and drop it at the top of the Groups & Files tree in your app's Xcode project window. In the confirmation dialog that appears, click Add.
    +

    +

    +
  4. + +
  5. +
    Click and expand the disclosure triangle next to the blue ParseKit.xcodeproj icon to reveal all of the potential products of the ParseKit project.
    +

    +
  6. +
  7. +
    Click and expand the disclosure triangle next to your app's Target. Drag the parsekit.a product under ParseKit.xcodeproj to your Target's Link Binary With Libraries build phase.
    +

    +
  8. +
  9. +
    Double-click your Target (MyApp shown here) to edit it. In the General tab of the Target Info window, click the square + button below the Direct Dependencies list. In the sheet that appears, select ParseKitMobile and click Add Target.
    +

    +
    You will now see the ParseKitMobile target appearing as a dependency under your app's Target.
    +

    +
  10. +
  11. +

    Next click the + button below the Linked Libraries list in the same window. Select libicucore.dylib and click Add. (This is for regular expression features in the PKPattern class.)

    +

    +
  12. +
  13. +
    Under the Build tab of your app's Target Info window, edit the Header Search Paths Setting to include the path to the include folder inside of the ParseKit folder you checked out. Make sure you edit this for All Configurations, not just the active one.
    +

    +
  14. + +
  15. +
    Finally, in the same window, edit the Other Linker Flags Setting to include the following flags: -ObjC -all_load. (This is needed for code in Objective-C categories in the ParseKit static library to execute successfully.)
    +

    +
  16. + +
  17. Ship it!
  18. + +
+ +
+ + + + diff --git a/docs/web/tokenization.html b/docs/web/tokenization.html new file mode 100644 index 0000000..f7f3dcd --- /dev/null +++ b/docs/web/tokenization.html @@ -0,0 +1,366 @@ + + ParseKit - String Tokenization in Objective-C, Cocoa + + + +

ParseKit Documentation

+
+ +

Tokenization

+ + + + +

Basic Usage of PKTokenizer

+ +

ParseKit provides general-purpose string tokenization services through the PKTokenizer and PKToken classes. Cocoa developers will be familiar with the NSScanner class provided by the Foundation Framework which provides a similar service. However, the PKTokenizer class is much easier to use for many common tokenization tasks, and offers powerful configuration options if the default tokenization behavior doesn't match your needs.

+ + + + + + + + +
PKTokenizer
+

+ + (id)tokenizerWithString:(NSString *)s;
+

+

+ - (PKToken *)nextToken;
+ ...
+

+
+ +

To use PKTokenizer, create an instance with an NSString object and retrieve a series of PKToken objects as you repeatedly call the -nextToken method. The EOFToken singleton signals the end.

+ +
+
+NSString *s = @"2 != -47. /* comment */ Blast-off!! 'Woo-hoo!' // comment";
+PKTokenizer *t = [PKTokenizer tokenizerWithString:s];
+
+PKToken *eof = [PKToken EOFToken];
+PKToken *tok = nil;
+
+while ((tok = [t nextToken]) != eof) {
+    NSLog(@"(%@) (%.1f) : %@", 
+        tok.stringValue, tok.floatValue, [tok debugDescription]);
+}
+
+
+ +

Outputs:

+ +
+
+(2) (2.0) : <Number «2»>
+(!=) (0.0) : <Symbol «!=»>
+(-47) (-47.0) : <Number «-47»>
+(.) (0.0) : <Symbol «.»>
+(Blast-off) (0.0) : <Word «Blast-off»>
+(!) (0.0) : <Symbol «!»>
+(!) (0.0) : <Symbol «!»>
+('Woo-hoo!') (0.0) : <Quoted String «'Woo-hoo!'»>
+
+
+ +

Each PKToken object returned has a stringValue, a floatValue and a tokenType. The tokenType is and enum value type called PKTokenType with possible values of:

+ +
    +
  • PKTokenTypeWord
  • +
  • PKTokenTypeNumber
  • +
  • PKTokenTypeQuotedString
  • +
  • PKTokenTypeSymbol
  • +
  • PKTokenTypeWhitespace
  • +
  • PKTokenTypeComment
  • +
  • PKTokenTypeDelimitedString
  • +
+ +

PKTokens also have corresponding BOOL properties for convenience (isWord, isNumber, etc.)

+ + + + + + + + +
PKToken
+

+ + (PKToken *)EOFToken;
+

+

+ @property (readonly) PKTokenType tokenType;
+

+

+ @property (readonly) CGFloat floatValue;
+ @property (readonly, copy) NSString *stringValue;
+

+

+ @property (readonly) BOOL isNumber;
+ @property (readonly) BOOL isSymbol;
+ @property (readonly) BOOL isWord;
+ @property (readonly) BOOL isQuotedString;
+ @property (readonly) BOOL isWhitespace;
+ @property (readonly) BOOL isComment;
+ @property (readonly) BOOL isDelimitedString;
+

+

+ ...
+

+
+ + +

Default Behavior of PKTokenizer

+ +

The default behavior of PKTokenizer is correct for most common situations and will fit many tokenization needs without additional configuration.

+ +

Number

+ +

Sequences of digits («2» «42» «1054») are recognized as Number tokens. Floating point numbers containing a dot («3.14») are recognized as single Number tokens as you'd expect (rather than two Number tokens separated by a «.» Symbol token). By default, PKTokenizer will recognize a «-» symbol followed immediately by digits («-47») as a number token with a negative value. However, «+» characters are always seen as the beginning of a Symbol token by default, even when followed immediately by digits, so "explicitly-positive" Number tokens are not recognized by default (this behavior can be configured, see below).

+ +

Symbol

+ +

Most symbol characters («.» «!») are recognized as single-character Symbol tokens (even when sequential such as «!»«!»). However, notice that PKTokenizer recognizes common multi-character symbols («!=») as a single Symbol token by default. In fact, PKTokenizer can be configured to recognize any given string as a multi-character symbol. Alternatively, it can be configured to always recognize each symbol character as an individual Symbol token (no mulit-character symbols). The default multi-character symbols recognized by PKTokenizer are: «<=», «>=», «!=», «==».

+ +

Word

+

«Blast-off» is recognized as a single Word token despite containing a symbol character («-») that would normally signal the start of a new Symbol token. By default, PKTokenzier allows Word tokens to contain (but not start with) several symbol and number characters: «-», «_», «'», «0»-«9». The consequence of this behavior is that PKTokenizer will recognize the follwing strings as individual Word tokens by default: «it's», «first_name», «sat-yr-9» «Rodham-Clinton». Again, you can configure PKTokenizer to alter this default behavior.

+ +

Quoted String

+

PKTokenizer produces Quoted String tokens for substrings enclosed in quote delimiter characters. The default delimiters are single- or double-quotes («'» or «"»). The quote delimiter characters may be changed (see below), but must be a single character. Note that the stringValue of Quoted String tokens include the quote delimiter characters («'Woo-hoo!'»).

+ +

Whitespace

+

By default, whitespace characters are silently consumed by PKTokenizer, and Whitespace tokens are never emitted. However, you can configure which characters are considered Whitespace characters or even ask PKTokenizer to return Whitespace tokens containing the literal whitespace stringValues by setting: t.whitespaceState.reportsWhitespaceTokens = YES.

+ +

Comment

+

By default, PKTokenizer recognizes C-style («//») and C++-style («/*» «*/») comments and silently removes the associated comments from the output rather than producing Comment tokens. See below for steps to either change comment delimiting markers, report Comment tokens, or to turn off comments recognition altogether.

+ +

Delimited String

+

The Delimited String token type is a powerful feature of ParseKit which can be used much like a regular expression. Use the Delimited String token type to ask PKTokenizer to recognize tokens with arbitrary start and end symbol strings much like a Quoted String but with more power:

+ +
    +
  • The start and end symbols may be multi-char (e.g. «<#» «#>»)
  • +
  • The start and end symbols need not match (e.g. «<?=» «?>»)
  • +
  • The characters allowed within the delimited string may be specified using an NSCharacterSet
  • +
+ + + +

Customizing PKTokenizer behavior

+ +

There are two basic types of decisions PKTokenizer must make when tokenizing strings:

+ +
    +
  1. Which token type should be created for a given start character?
  2. +
  3. Which characters are allowed within the current token being created?
  4. +
+ + +

PKTokenizer's behavior with respect to these two types of decisions is totally configurable. Let's tackle them, starting with the second question first.

+ +

Changing which characters are allowed within a token of a particular type

+ +

Once PKTokenizer has decided which token type to create for a given start character (see below), it temporarily passes control to one of its "state" helper objects to finish consumption of characters for the current token. Therefore, the logic for deciding which characters are allowed within a token of a given type is controlled by the "state" objects which are instances of subclasses of the abstract PKTokenizerState class: PKWordState, PKNumberState, PKQuoteState, PKSymbolState, PKWhitespaceState, PKCommentState, and PKDelimitState. The state objects are accessible via properties of the PKTokenizer object.

+ + + + + + + + +
PKTokenizer
+

+ ...
+ @property (readonly, retain) PKWordState *wordState;
+ @property (readonly, retain) PKNumberState *numberState;
+ @property (readonly, retain) PKQuoteState *quoteState;
+ @property (readonly, retain) PKSymbolState *symbolState;
+ @property (readonly, retain) PKWhitespaceState *whitespaceState;
+ @property (readonly, retain) PKCommentState *commentState;
+ @property (readonly, retain) PKDelimitState *delimitState;
+

+
+ +

Some of the PKTokenizerState subclasses have methods that alter which characters are allowed within tokens of their associated token type.

+ +

For example, if you want to add a new multiple-character symbol like «===»:

+ +
+
+...
+PKTokenizer *t = [PKTokenizer tokenizerWithString:s];
+[t.symbolState add:@"==="];
+...
+
+ +

Now «===» strings will be recognized as a single Symbol token with a stringValue of «===». There is a corresponding -[PKSymbolState remove:] method for removing recognition of given multi-char symbols.

+ +

If you don't want to allow digits within Word tokens (digits are allowed within Words by default):

+ +
+
+...
+[t.wordState setWordChars:NO from:'0' to:'9'];
+...
+
+ +

Say you want to allow floating-point Number tokens to end with a «.», sans trailing «0». In other words, you want «49.» to be recognized as a single Number token with a floatValue of «49.0» rather than a Number token followed by a Symbol token with a stringValue of «.»:

+ +
+
+...
+t.numberState.allowsTrailingDot = YES;
+...
+
+ +

Recognition of scientific notation (exponential numbers) can be enabled to recognize numbers like «10e+100», «6.626068E-34» and «6.0221415e23». The resulting PKToken objects will have floatValues which represent the full value of the exponential number, yet retain the original exponential representation as their stringValues.

+ +
+
+...
+t.numberState.allowsScentificNotation = YES;
+...
+
+ +

Similarly, recognition of common octal and hexadecimal number notation can be enabled to recognize numbers like «020» (octal 16) and «0x20» (hex 32).

+ +
+
+...
+t.numberState.allowsOctalNotation = YES;
+t.numberState.allowsHexadecimalNotation = YES;
+...
+
+ +

The resulting PKToken objects will have a tokenType of PKTokenTypeNumber and a stringValue matching the original source notation («020» or «0x20»). Their floatValues will represent the normal decimal value of the number (in this case 16 and 32).

+ +

You can also configure which characters are recognized as whitespace within a whitespace token. To treat digits as whitespace characters within whitespace tokens:

+ +
+
+...
+[t.whitespaceState setWhitespaceChars:YES from:'0' to:'9'];
+...
+
+ +

By default, whitespace chars are silently consumed by a tokenizer's PKWhitespaceState. To force reporting of PKTokens of type PKTokenTypeWhitespace containing the encountered whitespace chars as their stringValues (e.g. this would be necessary for a typical XML parser in which significant whitespace must be reported):

+ +
+
+...
+t.whitespaceState.reportsWhitespaceTokens = YES;
+...
+
+ +

Similarly, comments are also silently consumed by default. To report Comment tokens instead:

+ +
+
+...
+t.commentState.reportsCommentTokens = YES;
+...
+
+ + +

Changing which token type is created for a given start character

+ +

PKTokenizer controls the logic for deciding which token type should be created for a given start character before passing the responsibility for completing tokens to its "state" helper objects. To change which token type is created for a given start character, you must call a method of the PKTokenizer object itself: -[PKTokenizer setTokenizerState:from:to:].

+ + + + + + + + +
PKTokenizer
+

+ ... +

- (void)setTokenizerState:(PKTokenizerState *)state 
+                     from:(PKUniChar)start 
+                       to:(PKUniChar)end;
+ ...
+

+
+ +

For example, suppose you want to turn off support for Number tokens altogether. To recognize digits as signaling the start of Word tokens:

+ +
+
+...
+PKTokenizer *t = [PKTokenizerWithString:s];
+[t setTokenizerState:t.wordState from:'0' to:'9'];
+...
+
+ +

This will cause PKTokenizer to begin creating a Word token (rather than a Number token) whenever a digit («0», «1», «2», «3»,«4», «5», «6», «7», «8», «9», «0» ) is encountered.

+ +

As another example, say you want to add support for new Quoted String token delimiters, such as «#». This would cause a string like #oh hai# to be recognized as a Quoted String token rather than a Symbol, two Words, and a Symbol. Here's how:

+ +
+
+...
+[t setTokenizerState:t.quoteState from:'#' to:'#'];
+...
+
+ +

Note that if the from: and to: arguments are the same char, only behavior for that single char is affected.

+ +

Alternatively, say you want to recognize «+» characters followed immediately by digits as explicitly positive Number tokens rather than as a Symbol token followed by a Number token:

+ +
+
+...
+[t setTokenizerState:t.numberState from:'+' to:'+'];
+...
+
+ +

Finally, customization of comments recognition may be necessary. By default, PKTokenizer passes control to its commentState object which silently consumes the comment text found after «//» or between «/*» «*/». This default behavior is achieved with the sequence:

+ +
+
+...
+[t setTokenizerState:t.commentState from:'/' to:'/'];
+[t.commentState addSingleLineStartSymbol:@"//"];
+[t.commentState addMultiLineStartSymbol:@"/*" endSymbol:@"*/"];
+...
+
+ +

To recognize single-line comments starting with #:

+ +
+
+...
+[t setTokenizerState:t.commentState from:'#' to:'#'];
+[t.commentState addSingleLineStartSymbol:@"#"];
+...
+
+ +

To recognize multi-line "XML"- or "HTML"-style comments:

+ +
+
+...
+[t setTokenizerState:t.commentState from:'<' to:'<'];
+[t.commentState addMultiLineStartSymbol:@"<!--" endSymbol:@"-->"];
+...
+
+ +

To disable comments recognition altogether, tell PKTokenizer to pass control to its symbolState instead of its commentState.

+ +
+
+...
+[t setTokenizerState:t.symbolState from:'/' to:'/'];
+...
+
+ +

Now PKTokenizer will return individual Symbol tokens for all «/» and «*» characters, as well as any other characters set as part of a comment start or end symbol.

+ +
+ diff --git a/frameworks/.svn/all-wcprops b/frameworks/.svn/all-wcprops new file mode 100644 index 0000000..0b6342e --- /dev/null +++ b/frameworks/.svn/all-wcprops @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 34 +/svn/!svn/ver/351/trunk/frameworks +END diff --git a/frameworks/.svn/entries b/frameworks/.svn/entries new file mode 100644 index 0000000..e5a3e67 --- /dev/null +++ b/frameworks/.svn/entries @@ -0,0 +1,31 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/frameworks +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +OCMock.framework +dir + diff --git a/frameworks/OCMock.framework/.svn/all-wcprops b/frameworks/OCMock.framework/.svn/all-wcprops new file mode 100644 index 0000000..5078038 --- /dev/null +++ b/frameworks/OCMock.framework/.svn/all-wcprops @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework +END +Resources +K 25 +svn:wc:ra_dav:version-url +V 61 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Resources +END +Headers +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Headers +END +OCMock +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/OCMock +END diff --git a/frameworks/OCMock.framework/.svn/entries b/frameworks/OCMock.framework/.svn/entries new file mode 100644 index 0000000..6e61228 --- /dev/null +++ b/frameworks/OCMock.framework/.svn/entries @@ -0,0 +1,133 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/frameworks/OCMock.framework +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +Versions +dir + +Resources +file + + + + +2009-01-13T13:52:45.000000Z +8a6539acc25a583ce7a88f6573bf4687 +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf +has-props + + +svn:special + + + + + + + + + + + + + + + + + +26 + +Headers +file + + + + +2009-01-13T13:52:45.000000Z +574393f6f6e7d44c9dfa3c805bbefb99 +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf +has-props + + +svn:special + + + + + + + + + + + + + + + + + +24 + +OCMock +file + + + + +2009-01-13T13:52:45.000000Z +9b928bf344b4fa0c6323309d37a04c09 +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf +has-props + + +svn:special + + + + + + + + + + + + + + + + + +23 + diff --git a/frameworks/OCMock.framework/.svn/prop-base/Headers.svn-base b/frameworks/OCMock.framework/.svn/prop-base/Headers.svn-base new file mode 100644 index 0000000..d222469 --- /dev/null +++ b/frameworks/OCMock.framework/.svn/prop-base/Headers.svn-base @@ -0,0 +1,5 @@ +K 11 +svn:special +V 1 +* +END diff --git a/frameworks/OCMock.framework/.svn/prop-base/OCMock.svn-base b/frameworks/OCMock.framework/.svn/prop-base/OCMock.svn-base new file mode 100644 index 0000000..d222469 --- /dev/null +++ b/frameworks/OCMock.framework/.svn/prop-base/OCMock.svn-base @@ -0,0 +1,5 @@ +K 11 +svn:special +V 1 +* +END diff --git a/frameworks/OCMock.framework/.svn/prop-base/Resources.svn-base b/frameworks/OCMock.framework/.svn/prop-base/Resources.svn-base new file mode 100644 index 0000000..d222469 --- /dev/null +++ b/frameworks/OCMock.framework/.svn/prop-base/Resources.svn-base @@ -0,0 +1,5 @@ +K 11 +svn:special +V 1 +* +END diff --git a/frameworks/OCMock.framework/.svn/text-base/Headers.svn-base b/frameworks/OCMock.framework/.svn/text-base/Headers.svn-base new file mode 100644 index 0000000..45bda20 --- /dev/null +++ b/frameworks/OCMock.framework/.svn/text-base/Headers.svn-base @@ -0,0 +1 @@ +link Versions/Current/Headers \ No newline at end of file diff --git a/frameworks/OCMock.framework/.svn/text-base/OCMock.svn-base b/frameworks/OCMock.framework/.svn/text-base/OCMock.svn-base new file mode 100644 index 0000000..bf7a568 --- /dev/null +++ b/frameworks/OCMock.framework/.svn/text-base/OCMock.svn-base @@ -0,0 +1 @@ +link Versions/Current/OCMock \ No newline at end of file diff --git a/frameworks/OCMock.framework/.svn/text-base/Resources.svn-base b/frameworks/OCMock.framework/.svn/text-base/Resources.svn-base new file mode 100644 index 0000000..0af1f07 --- /dev/null +++ b/frameworks/OCMock.framework/.svn/text-base/Resources.svn-base @@ -0,0 +1 @@ +link Versions/Current/Resources \ No newline at end of file diff --git a/frameworks/OCMock.framework/Headers b/frameworks/OCMock.framework/Headers new file mode 120000 index 0000000..a177d2a --- /dev/null +++ b/frameworks/OCMock.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/frameworks/OCMock.framework/OCMock b/frameworks/OCMock.framework/OCMock new file mode 120000 index 0000000..c388ea8 --- /dev/null +++ b/frameworks/OCMock.framework/OCMock @@ -0,0 +1 @@ +Versions/Current/OCMock \ No newline at end of file diff --git a/frameworks/OCMock.framework/Resources b/frameworks/OCMock.framework/Resources new file mode 120000 index 0000000..953ee36 --- /dev/null +++ b/frameworks/OCMock.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/frameworks/OCMock.framework/Versions/.svn/all-wcprops b/frameworks/OCMock.framework/Versions/.svn/all-wcprops new file mode 100644 index 0000000..efd9d52 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions +END +Current +K 25 +svn:wc:ra_dav:version-url +V 68 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/Current +END diff --git a/frameworks/OCMock.framework/Versions/.svn/entries b/frameworks/OCMock.framework/Versions/.svn/entries new file mode 100644 index 0000000..ebeca48 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/.svn/entries @@ -0,0 +1,65 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/frameworks/OCMock.framework/Versions +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +A +dir + +Current +file + + + + +2009-01-13T13:52:45.000000Z +654580f41818cd6f51408c7cbd313728 +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf +has-props + + +svn:special + + + + + + + + + + + + + + + + + +1 + diff --git a/frameworks/OCMock.framework/Versions/.svn/prop-base/Current.svn-base b/frameworks/OCMock.framework/Versions/.svn/prop-base/Current.svn-base new file mode 100644 index 0000000..d222469 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/.svn/prop-base/Current.svn-base @@ -0,0 +1,5 @@ +K 11 +svn:special +V 1 +* +END diff --git a/frameworks/OCMock.framework/Versions/.svn/text-base/Current.svn-base b/frameworks/OCMock.framework/Versions/.svn/text-base/Current.svn-base new file mode 100644 index 0000000..613feee --- /dev/null +++ b/frameworks/OCMock.framework/Versions/.svn/text-base/Current.svn-base @@ -0,0 +1 @@ +link A \ No newline at end of file diff --git a/frameworks/OCMock.framework/Versions/A/.svn/all-wcprops b/frameworks/OCMock.framework/Versions/A/.svn/all-wcprops new file mode 100644 index 0000000..ff6a7e6 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 62 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A +END +OCMock +K 25 +svn:wc:ra_dav:version-url +V 69 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/OCMock +END diff --git a/frameworks/OCMock.framework/Versions/A/.svn/entries b/frameworks/OCMock.framework/Versions/A/.svn/entries new file mode 100644 index 0000000..f6543c5 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/.svn/entries @@ -0,0 +1,68 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/frameworks/OCMock.framework/Versions/A +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +Resources +dir + +Headers +dir + +OCMock +file + + + + +2008-12-15T21:27:02.000000Z +153105d53d245f56054269b4b05b1dba +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +182272 + diff --git a/frameworks/OCMock.framework/Versions/A/.svn/prop-base/OCMock.svn-base b/frameworks/OCMock.framework/Versions/A/.svn/prop-base/OCMock.svn-base new file mode 100644 index 0000000..dbc918b --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/.svn/prop-base/OCMock.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/frameworks/OCMock.framework/Versions/A/.svn/text-base/OCMock.svn-base b/frameworks/OCMock.framework/Versions/A/.svn/text-base/OCMock.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..10ba9284bbc51a9f2d1668c57d52723ed6b4197c GIT binary patch literal 182272 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 AjQ{`u literal 0 HcmV?d00001 diff --git a/frameworks/OCMock.framework/Versions/A/Headers/.svn/all-wcprops b/frameworks/OCMock.framework/Versions/A/Headers/.svn/all-wcprops new file mode 100644 index 0000000..c2e3419 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/.svn/all-wcprops @@ -0,0 +1,29 @@ +K 25 +svn:wc:ra_dav:version-url +V 70 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Headers +END +OCMock.h +K 25 +svn:wc:ra_dav:version-url +V 79 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Headers/OCMock.h +END +OCMockRecorder.h +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Headers/OCMockRecorder.h +END +OCMockObject.h +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Headers/OCMockObject.h +END +OCMConstraint.h +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Headers/OCMConstraint.h +END diff --git a/frameworks/OCMock.framework/Versions/A/Headers/.svn/entries b/frameworks/OCMock.framework/Versions/A/Headers/.svn/entries new file mode 100644 index 0000000..efb07b0 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/.svn/entries @@ -0,0 +1,164 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/frameworks/OCMock.framework/Versions/A/Headers +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +OCMock.h +file + + + + +2008-12-15T21:27:02.000000Z +558e04dfa5041cfbdb2977ccba06cb5c +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +408 + +OCMockRecorder.h +file + + + + +2008-12-15T21:27:02.000000Z +760697636267668accf0effdbb5f4bb9 +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1061 + +OCMockObject.h +file + + + + +2008-12-15T21:27:02.000000Z +bff6241b999132630cff6c4e4cd1456e +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +721 + +OCMConstraint.h +file + + + + +2008-12-15T21:27:02.000000Z +5bbf007d5921fb89d4fd7fcf5405de54 +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +842 + diff --git a/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMConstraint.h.svn-base b/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMConstraint.h.svn-base new file mode 100644 index 0000000..e5ec2b1 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMConstraint.h.svn-base @@ -0,0 +1,28 @@ +//--------------------------------------------------------------------------------------- +// $Id: $ +// Copyright (c) 2007-2008 by Mulle Kybernetik. See License file for details. +//--------------------------------------------------------------------------------------- + +#import + + +@interface OCMConstraint : NSObject +{ +} + ++ (id)constraint; + ++ (id)constraintWithSelector:(SEL)aSelector onObject:(id)anObject; ++ (id)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue; + ++ (id)any; ++ (id)isNil; ++ (id)isNotNil; ++ (id)isNotEqual:(id)value; + +- (BOOL)evaluate:(id)value; + +@end + +#define CONSTRAINT(aSelector) [OCMConstraint constraintWithSelector:aSelector onObject:self] +#define CONSTRAINTV(aSelector, aValue) [OCMConstraint constraintWithSelector:aSelector onObject:self withValue:(aValue)] diff --git a/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMock.h.svn-base b/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMock.h.svn-base new file mode 100644 index 0000000..6e9ec41 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMock.h.svn-base @@ -0,0 +1,8 @@ +//--------------------------------------------------------------------------------------- +// $Id: OCMock.h 21 2008-01-24 18:59:39Z erik $ +// Copyright (c) 2004-2008 by Mulle Kybernetik. See License file for details. +//--------------------------------------------------------------------------------------- + +#import +#import +#import diff --git a/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMockObject.h.svn-base b/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMockObject.h.svn-base new file mode 100644 index 0000000..1d97dc2 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMockObject.h.svn-base @@ -0,0 +1,29 @@ +//--------------------------------------------------------------------------------------- +// $Id: OCMockObject.h 21 2008-01-24 18:59:39Z erik $ +// Copyright (c) 2004-2008 by Mulle Kybernetik. See License file for details. +//--------------------------------------------------------------------------------------- + +#import + +@interface OCMockObject : NSProxy +{ + BOOL isNice; + NSMutableArray *recorders; + NSMutableSet *expectations; + NSMutableArray *exceptions; +} + ++ (id)mockForClass:(Class)aClass; ++ (id)mockForProtocol:(Protocol *)aProtocol; + ++ (id)niceMockForClass:(Class)aClass; ++ (id)niceMockForProtocol:(Protocol *)aProtocol; + +- (id)init; + +- (id)stub; +- (id)expect; + +- (void)verify; + +@end diff --git a/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMockRecorder.h.svn-base b/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMockRecorder.h.svn-base new file mode 100644 index 0000000..5142729 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/.svn/text-base/OCMockRecorder.h.svn-base @@ -0,0 +1,33 @@ +//--------------------------------------------------------------------------------------- +// $Id: OCMockRecorder.h 28 2008-06-19 22:37:17Z erik $ +// Copyright (c) 2004-2008 by Mulle Kybernetik. See License file for details. +//--------------------------------------------------------------------------------------- + +#import + +@class OCMConstraint; // reference for backwards compatibility OCMOCK_ANY macro + + +@interface OCMockRecorder : NSProxy +{ + id signatureResolver; + id returnValue; + BOOL returnValueIsBoxed; + BOOL returnValueShouldBeThrown; + NSInvocation *recordedInvocation; +} + +- (id)initWithSignatureResolver:(id)anObject; + +- (id)andReturn:(id)anObject; +- (id)andReturnValue:(NSValue *)aValue; +- (id)andThrow:(NSException *)anException; + +- (BOOL)matchesInvocation:(NSInvocation *)anInvocation; +- (void)setUpReturnValue:(NSInvocation *)anInvocation; +- (void)releaseInvocation; + +@end + +#define OCMOCK_ANY [OCMConstraint any] +#define OCMOCK_VALUE(variable) [NSValue value:&variable withObjCType:@encode(typeof(variable))] diff --git a/frameworks/OCMock.framework/Versions/A/Headers/OCMConstraint.h b/frameworks/OCMock.framework/Versions/A/Headers/OCMConstraint.h new file mode 100644 index 0000000..e5ec2b1 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/OCMConstraint.h @@ -0,0 +1,28 @@ +//--------------------------------------------------------------------------------------- +// $Id: $ +// Copyright (c) 2007-2008 by Mulle Kybernetik. See License file for details. +//--------------------------------------------------------------------------------------- + +#import + + +@interface OCMConstraint : NSObject +{ +} + ++ (id)constraint; + ++ (id)constraintWithSelector:(SEL)aSelector onObject:(id)anObject; ++ (id)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue; + ++ (id)any; ++ (id)isNil; ++ (id)isNotNil; ++ (id)isNotEqual:(id)value; + +- (BOOL)evaluate:(id)value; + +@end + +#define CONSTRAINT(aSelector) [OCMConstraint constraintWithSelector:aSelector onObject:self] +#define CONSTRAINTV(aSelector, aValue) [OCMConstraint constraintWithSelector:aSelector onObject:self withValue:(aValue)] diff --git a/frameworks/OCMock.framework/Versions/A/Headers/OCMock.h b/frameworks/OCMock.framework/Versions/A/Headers/OCMock.h new file mode 100644 index 0000000..6e9ec41 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/OCMock.h @@ -0,0 +1,8 @@ +//--------------------------------------------------------------------------------------- +// $Id: OCMock.h 21 2008-01-24 18:59:39Z erik $ +// Copyright (c) 2004-2008 by Mulle Kybernetik. See License file for details. +//--------------------------------------------------------------------------------------- + +#import +#import +#import diff --git a/frameworks/OCMock.framework/Versions/A/Headers/OCMockObject.h b/frameworks/OCMock.framework/Versions/A/Headers/OCMockObject.h new file mode 100644 index 0000000..1d97dc2 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/OCMockObject.h @@ -0,0 +1,29 @@ +//--------------------------------------------------------------------------------------- +// $Id: OCMockObject.h 21 2008-01-24 18:59:39Z erik $ +// Copyright (c) 2004-2008 by Mulle Kybernetik. See License file for details. +//--------------------------------------------------------------------------------------- + +#import + +@interface OCMockObject : NSProxy +{ + BOOL isNice; + NSMutableArray *recorders; + NSMutableSet *expectations; + NSMutableArray *exceptions; +} + ++ (id)mockForClass:(Class)aClass; ++ (id)mockForProtocol:(Protocol *)aProtocol; + ++ (id)niceMockForClass:(Class)aClass; ++ (id)niceMockForProtocol:(Protocol *)aProtocol; + +- (id)init; + +- (id)stub; +- (id)expect; + +- (void)verify; + +@end diff --git a/frameworks/OCMock.framework/Versions/A/Headers/OCMockRecorder.h b/frameworks/OCMock.framework/Versions/A/Headers/OCMockRecorder.h new file mode 100644 index 0000000..5142729 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Headers/OCMockRecorder.h @@ -0,0 +1,33 @@ +//--------------------------------------------------------------------------------------- +// $Id: OCMockRecorder.h 28 2008-06-19 22:37:17Z erik $ +// Copyright (c) 2004-2008 by Mulle Kybernetik. See License file for details. +//--------------------------------------------------------------------------------------- + +#import + +@class OCMConstraint; // reference for backwards compatibility OCMOCK_ANY macro + + +@interface OCMockRecorder : NSProxy +{ + id signatureResolver; + id returnValue; + BOOL returnValueIsBoxed; + BOOL returnValueShouldBeThrown; + NSInvocation *recordedInvocation; +} + +- (id)initWithSignatureResolver:(id)anObject; + +- (id)andReturn:(id)anObject; +- (id)andReturnValue:(NSValue *)aValue; +- (id)andThrow:(NSException *)anException; + +- (BOOL)matchesInvocation:(NSInvocation *)anInvocation; +- (void)setUpReturnValue:(NSInvocation *)anInvocation; +- (void)releaseInvocation; + +@end + +#define OCMOCK_ANY [OCMConstraint any] +#define OCMOCK_VALUE(variable) [NSValue value:&variable withObjCType:@encode(typeof(variable))] diff --git a/frameworks/OCMock.framework/Versions/A/OCMock b/frameworks/OCMock.framework/Versions/A/OCMock new file mode 100755 index 0000000000000000000000000000000000000000..10ba9284bbc51a9f2d1668c57d52723ed6b4197c GIT binary patch literal 182272 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 AjQ{`u literal 0 HcmV?d00001 diff --git a/frameworks/OCMock.framework/Versions/A/Resources/.svn/all-wcprops b/frameworks/OCMock.framework/Versions/A/Resources/.svn/all-wcprops new file mode 100644 index 0000000..3944d51 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Resources/.svn/all-wcprops @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 72 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Resources +END +License.txt +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Resources/License.txt +END +Info.plist +K 25 +svn:wc:ra_dav:version-url +V 83 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Resources/Info.plist +END diff --git a/frameworks/OCMock.framework/Versions/A/Resources/.svn/entries b/frameworks/OCMock.framework/Versions/A/Resources/.svn/entries new file mode 100644 index 0000000..a762e55 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Resources/.svn/entries @@ -0,0 +1,99 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/frameworks/OCMock.framework/Versions/A/Resources +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +License.txt +file + + + + +2008-12-15T21:27:02.000000Z +97f46e0407438a578d0a4e0cc8cdab8c +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +929 + +Info.plist +file + + + + +2008-12-15T21:27:02.000000Z +f2dc4947c2c6c52bdef8ee53d51a670d +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +607 + +English.lproj +dir + diff --git a/frameworks/OCMock.framework/Versions/A/Resources/.svn/text-base/Info.plist.svn-base b/frameworks/OCMock.framework/Versions/A/Resources/.svn/text-base/Info.plist.svn-base new file mode 100644 index 0000000..7a68a46 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Resources/.svn/text-base/Info.plist.svn-base @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + OCMock + CFBundleIdentifier + com.mulle-kybernetik.OCMock + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/frameworks/OCMock.framework/Versions/A/Resources/.svn/text-base/License.txt.svn-base b/frameworks/OCMock.framework/Versions/A/Resources/.svn/text-base/License.txt.svn-base new file mode 100644 index 0000000..96f7069 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Resources/.svn/text-base/License.txt.svn-base @@ -0,0 +1,15 @@ + + Copyright (c) 2004-2008 by Mulle Kybernetik. All rights reserved. + + Permission to use, copy, modify and distribute this software and its documentation + is hereby granted, provided that both the copyright notice and this permission + notice appear in all copies of the software, derivative works or modified versions, + and any portions thereof, and that both notices appear in supporting documentation, + and that credit is given to Mulle Kybernetik in all documents and publicity + pertaining to direct or indirect use of this code or its derivatives. + + THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE + SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS + "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY + DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE + OR OF ANY DERIVATIVE WORK. \ No newline at end of file diff --git a/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/all-wcprops b/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/all-wcprops new file mode 100644 index 0000000..18d1995 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Resources/English.lproj +END +InfoPlist.strings +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/!svn/ver/351/trunk/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/InfoPlist.strings +END diff --git a/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/entries b/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/entries new file mode 100644 index 0000000..529186b --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/frameworks/OCMock.framework/Versions/A/Resources/English.lproj +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +InfoPlist.strings +file + + + + +2008-12-15T21:27:01.000000Z +29f16bb8859c933409fdf8046edfcc74 +2008-12-15T01:37:32.818725Z +351 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +534 + diff --git a/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/prop-base/InfoPlist.strings.svn-base b/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/prop-base/InfoPlist.strings.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/prop-base/InfoPlist.strings.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/text-base/InfoPlist.strings.svn-base b/frameworks/OCMock.framework/Versions/A/Resources/English.lproj/.svn/text-base/InfoPlist.strings.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..a98e11d3228e0fcb2d1d7dca313da374d7536008 GIT binary patch literal 534 zcmbV|OKZYV5QWdWzvAMmidHQy1aV`)T3RhM;66SQLmo=Bh4#l+zuZ(&i5m$wbMMTV zGw00TUQN|x^scq$@)Rr7ua;Vn`zB`El36Py8luntm6y-`NgIpbYDYE#{bNxzI3M^N z4K>gg=mof?Ch#Xjqdupi4-jKJH{#VR>2S58p20u8(BhKG(3L7Uv9;0Dy20~8_wJ;- ztovNcwR59_yUr{JJsW)H(*xAy&L7!amH5p3mO5(u-@4?+_>Zl7qc{3y)<gg=mof?Ch#Xjqdupi4-jKJH{#VR>2S58p20u8(BhKG(3L7Uv9;0Dy20~8_wJ;- ztovNcwR59_yUr{JJsW)H(*xAy&L7!amH5p3mO5(u-@4?+_>Zl7qc{3y)< + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + OCMock + CFBundleIdentifier + com.mulle-kybernetik.OCMock + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/frameworks/OCMock.framework/Versions/A/Resources/License.txt b/frameworks/OCMock.framework/Versions/A/Resources/License.txt new file mode 100644 index 0000000..96f7069 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/A/Resources/License.txt @@ -0,0 +1,15 @@ + + Copyright (c) 2004-2008 by Mulle Kybernetik. All rights reserved. + + Permission to use, copy, modify and distribute this software and its documentation + is hereby granted, provided that both the copyright notice and this permission + notice appear in all copies of the software, derivative works or modified versions, + and any portions thereof, and that both notices appear in supporting documentation, + and that credit is given to Mulle Kybernetik in all documents and publicity + pertaining to direct or indirect use of this code or its derivatives. + + THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE + SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS + "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY + DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE + OR OF ANY DERIVATIVE WORK. \ No newline at end of file diff --git a/frameworks/OCMock.framework/Versions/Current b/frameworks/OCMock.framework/Versions/Current new file mode 120000 index 0000000..8c7e5a6 --- /dev/null +++ b/frameworks/OCMock.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/include/.svn/all-wcprops b/include/.svn/all-wcprops new file mode 100644 index 0000000..92aa727 --- /dev/null +++ b/include/.svn/all-wcprops @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 32 +/svn/!svn/ver/1403/trunk/include +END diff --git a/include/.svn/entries b/include/.svn/entries new file mode 100644 index 0000000..311d8ba --- /dev/null +++ b/include/.svn/entries @@ -0,0 +1,38 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/include +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-09-26T19:12:29.746961Z +1403 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + + + + + + +0 + +ParseKit +dir + diff --git a/include/ParseKit/.svn/all-wcprops b/include/ParseKit/.svn/all-wcprops new file mode 100644 index 0000000..cf3e62f --- /dev/null +++ b/include/ParseKit/.svn/all-wcprops @@ -0,0 +1,311 @@ +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1403/trunk/include/ParseKit +END +PKEmpty.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1171/trunk/include/ParseKit/PKEmpty.h +END +PKLetter.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1171/trunk/include/ParseKit/PKLetter.h +END +PKDigit.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKDigit.h +END +PKTokenArraySource.h +K 25 +svn:wc:ra_dav:version-url +V 62 +/svn/!svn/ver/1171/trunk/include/ParseKit/PKTokenArraySource.h +END +PKReader.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1171/trunk/include/ParseKit/PKReader.h +END +PKSymbol.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKSymbol.h +END +PKIntersection.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1238/trunk/include/ParseKit/PKIntersection.h +END +PKCaseInsensitiveLiteral.h +K 25 +svn:wc:ra_dav:version-url +V 68 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKCaseInsensitiveLiteral.h +END +PKTokenizer.h +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1401/trunk/include/ParseKit/PKTokenizer.h +END +PKSymbolNode.h +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKSymbolNode.h +END +PKTokenizerState.h +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/1401/trunk/include/ParseKit/PKTokenizerState.h +END +PKWordState.h +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKWordState.h +END +PKPattern.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1179/trunk/include/ParseKit/PKPattern.h +END +PKSymbolRootNode.h +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKSymbolRootNode.h +END +PKAssembly.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1403/trunk/include/ParseKit/PKAssembly.h +END +PKToken.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1177/trunk/include/ParseKit/PKToken.h +END +PKAlternation.h +K 25 +svn:wc:ra_dav:version-url +V 57 +/svn/!svn/ver/1238/trunk/include/ParseKit/PKAlternation.h +END +PKUppercaseWord.h +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKUppercaseWord.h +END +PKTrackException.h +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/1171/trunk/include/ParseKit/PKTrackException.h +END +PKSpecificChar.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1171/trunk/include/ParseKit/PKSpecificChar.h +END +PKNumber.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1177/trunk/include/ParseKit/PKNumber.h +END +PKDelimitState.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1167/trunk/include/ParseKit/PKDelimitState.h +END +PKQuotedString.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKQuotedString.h +END +PKNumberState.h +K 25 +svn:wc:ra_dav:version-url +V 57 +/svn/!svn/ver/1259/trunk/include/ParseKit/PKNumberState.h +END +PKQuoteState.h +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKQuoteState.h +END +PKComment.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKComment.h +END +PKCommentState.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKCommentState.h +END +PKNegation.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1238/trunk/include/ParseKit/PKNegation.h +END +PKTypes.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1167/trunk/include/ParseKit/PKTypes.h +END +PKTrack.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1225/trunk/include/ParseKit/PKTrack.h +END +PKSymbolState.h +K 25 +svn:wc:ra_dav:version-url +V 57 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKSymbolState.h +END +PKSequence.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1225/trunk/include/ParseKit/PKSequence.h +END +PKCollectionParser.h +K 25 +svn:wc:ra_dav:version-url +V 62 +/svn/!svn/ver/1225/trunk/include/ParseKit/PKCollectionParser.h +END +PKTerminal.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1171/trunk/include/ParseKit/PKTerminal.h +END +PKWord.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKWord.h +END +PKChar.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKChar.h +END +PKSingleLineCommentState.h +K 25 +svn:wc:ra_dav:version-url +V 68 +/svn/!svn/ver/1171/trunk/include/ParseKit/PKSingleLineCommentState.h +END +PKLowercaseWord.h +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKLowercaseWord.h +END +PKTokenAssembly.h +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1171/trunk/include/ParseKit/PKTokenAssembly.h +END +PKRepetition.h +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1268/trunk/include/ParseKit/PKRepetition.h +END +PKParserFactory.h +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1268/trunk/include/ParseKit/PKParserFactory.h +END +PKMultiLineCommentState.h +K 25 +svn:wc:ra_dav:version-url +V 67 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKMultiLineCommentState.h +END +PKAny.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKAny.h +END +PKDelimitedString.h +K 25 +svn:wc:ra_dav:version-url +V 61 +/svn/!svn/ver/1167/trunk/include/ParseKit/PKDelimitedString.h +END +ParseKit.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1331/trunk/include/ParseKit/ParseKit.h +END +PKDifference.h +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1238/trunk/include/ParseKit/PKDifference.h +END +PKParser.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1400/trunk/include/ParseKit/PKParser.h +END +PKLiteral.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKLiteral.h +END +PKCharacterAssembly.h +K 25 +svn:wc:ra_dav:version-url +V 63 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKCharacterAssembly.h +END +PKWhitespace.h +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1167/trunk/include/ParseKit/PKWhitespace.h +END +PKWhitespaceState.h +K 25 +svn:wc:ra_dav:version-url +V 61 +/svn/!svn/ver/1170/trunk/include/ParseKit/PKWhitespaceState.h +END diff --git a/include/ParseKit/.svn/entries b/include/ParseKit/.svn/entries new file mode 100644 index 0000000..6f439ce --- /dev/null +++ b/include/ParseKit/.svn/entries @@ -0,0 +1,1769 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/include/ParseKit +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-09-26T19:12:29.746961Z +1403 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + + + + + + +0 + +PKEmpty.h +file + + + + +2009-07-03T19:31:17.000000Z +dfa07f81beb7dd730872063386c5cb40 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +863 + +PKLetter.h +file + + + + +2009-07-03T19:31:17.000000Z +3d56e3668a7ebb4e9bf40eddf1d80142 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +629 + +PKDigit.h +file + + + + +2009-07-03T19:31:15.000000Z +f900c4391df6393c4c90340f3a137771 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +613 + +PKTokenArraySource.h +file + + + + +2009-07-03T19:31:17.000000Z +f77ad1a196ccaa1989f26cfc5d18f868 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1795 + +PKReader.h +file + + + + +2009-07-03T19:48:43.000000Z +69b6fac4dde3a1415de3bf78de9e71ce +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1436 + +PKSymbol.h +file + + + + +2009-07-03T19:31:14.000000Z +733c68b7b025828c6f565f13a807dfd2 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1064 + +PKIntersection.h +file + + + + +2009-07-19T19:15:26.000000Z +c67dc76f9cc5d837d2ac5cf16a671b1e +2009-07-19T19:15:40.768901Z +1238 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1254 + +PKCaseInsensitiveLiteral.h +file + + + + +2009-07-03T19:31:15.000000Z +9ff99901dd7cade0d5b2bcd2eee6404a +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +450 + +PKTokenizer.h +file + + + + +2009-09-26T04:03:30.000000Z +7f0ae17e58b442ae5ad6c1c037cbd958 +2009-09-26T04:04:19.519010Z +1401 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +5451 + +PKSymbolNode.h +file + + + + +2009-07-03T19:42:56.000000Z +31e49911253772af1d2c515492407e70 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2773 + +PKTokenizerState.h +file + + + + +2009-09-26T04:04:07.000000Z +073db2ce68b9bca6dcf3e8a7fafaac90 +2009-09-26T04:04:19.519010Z +1401 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2217 + +PKWordState.h +file + + + + +2009-07-03T19:31:13.000000Z +83a32c3f77b2dcb5e76ed801fcd4214e +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1966 + +PKPattern.h +file + + + + +2009-07-03T22:30:14.000000Z +c0741cc0d7550615d8d9c1f4a143be38 +2009-07-03T22:34:56.929029Z +1179 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +857 + +PKSymbolRootNode.h +file + + + + +2009-07-03T19:31:14.000000Z +c4d2b3b347f7c8a3f1c22cd0e05ae529 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1397 + +PKAssembly.h +file + + + + +2009-09-26T05:49:28.000000Z +2648905aaf62272f91e1746c9bcd0b02 +2009-09-26T19:12:29.746961Z +1403 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +3283 + +PKAlternation.h +file + + + + +2009-07-19T19:15:06.000000Z +ae421cb08ab1b61d83e2e6eadc2fefdc +2009-07-19T19:15:40.768901Z +1238 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +770 + +PKToken.h +file + + + + +2009-07-03T22:16:26.000000Z +f9ebb39c9f4089c0b2ff9036f078923b +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +5775 + +PKSpecificChar.h +file + + + + +2009-07-03T19:31:16.000000Z +e9ad98a58dd1c42b86a19a043fcb18d5 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1096 + +PKTrackException.h +file + + + + +2009-07-03T19:31:18.000000Z +16166635b1bfab48ec5a979735072f01 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +874 + +PKUppercaseWord.h +file + + + + +2009-07-03T19:31:12.000000Z +06339383c80eced073430fd8afdd1006 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +257 + +PKNumber.h +file + + + + +2009-07-03T22:05:22.000000Z +56f9eced2537dbeaf3de246bd1f6877d +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +551 + +PKQuotedString.h +file + + + + +2009-07-03T19:31:14.000000Z +ae2c032dd20afb5d3839b914eadfe7f2 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +618 + +PKDelimitState.h +file + + + + +2009-07-03T19:42:56.000000Z +60790892814c160ebc75bb5f2d51db4a +2009-07-03T19:25:24.801046Z +1167 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2238 + +PKNumberState.h +file + + + + +2009-07-20T00:28:10.000000Z +358308ef6c9ac424088be5ed53ceca93 +2009-07-20T00:28:22.181007Z +1259 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2141 + +PKQuoteState.h +file + + + + +2009-07-03T19:42:56.000000Z +f32e3441610857d0d8bced2d9a03b007 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1000 + +PKComment.h +file + + + + +2009-07-03T19:31:15.000000Z +686c12831bd2299679bc4395b7a04527 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +560 + +PKCommentState.h +file + + + + +2009-07-03T19:42:56.000000Z +6eb57f2fb9243dcadf0e23803dd69588 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3510 + +PKTrack.h +file + + + + +2009-07-14T02:47:26.000000Z +d110bc0de561d3dd7eede6ab0e880b77 +2009-07-14T03:32:39.769371Z +1225 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +771 + +PKNegation.h +file + + + + +2009-07-19T19:10:18.000000Z +7ca3f7013bf46b4aaa22df7576557c04 +2009-07-19T19:15:40.768901Z +1238 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1450 + +PKTypes.h +file + + + + +2009-07-03T18:54:13.000000Z +4c577c71d8e7407c30cdf58e3b9a0a95 +2009-07-03T19:25:24.801046Z +1167 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +274 + +PKSymbolState.h +file + + + + +2009-07-03T19:31:13.000000Z +c92157ca740d4029dd48f105bf6f1b86 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2100 + +PKCollectionParser.h +file + + + + +2009-07-14T03:21:55.000000Z +1a504479cac452da1f9415e94b26f654 +2009-07-14T03:32:39.769371Z +1225 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1064 + +PKSequence.h +file + + + + +2009-07-14T02:43:44.000000Z +6e194945f5c59253362a582493df7cae +2009-07-14T03:32:39.769371Z +1225 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +720 + +PKTerminal.h +file + + + + +2009-07-03T19:42:56.000000Z +e4a26c8dc04dc0b68deabe51b7b63e5f +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1281 + +PKWord.h +file + + + + +2009-07-03T19:31:12.000000Z +c3ec07e1221bfd2aea835f8803d2b34a +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +536 + +PKChar.h +file + + + + +2009-07-03T19:31:15.000000Z +e933cba48a9dff152ea2fb91b82a6b27 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +662 + +PKSingleLineCommentState.h +file + + + + +2009-07-03T19:31:16.000000Z +4245b800e78749e9a0e258fc336620e4 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +363 + +PKTokenAssembly.h +file + + + + +2009-07-03T19:42:56.000000Z +77cea4bf4e3e2391ad912e3c935e4399 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1957 + +PKLowercaseWord.h +file + + + + +2009-07-03T19:31:12.000000Z +30a4f1e95046d48b3a3d4cb3f805355f +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +257 + +PKRepetition.h +file + + + + +2009-08-06T04:02:00.000000Z +61cf193c874b978ddf4ef805a8a487f2 +2009-08-02T20:08:09.420177Z +1268 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1371 + +PKParserFactory.h +file + + + + +2009-08-06T04:02:00.000000Z +3b344223fa9f4caef35f2940aab81cba +2009-08-02T20:08:09.420177Z +1268 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1360 + +PKMultiLineCommentState.h +file + + + + +2009-07-03T19:31:14.000000Z +310e2b37531739322c09a5577b9016a3 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +393 + +ParseKit.h +file + + + + +2009-08-17T00:38:12.000000Z +053924396601a25a082c0535a9251875 +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +3194 + +PKDelimitedString.h +file + + + + +2009-07-03T18:53:37.000000Z +e00259d9e64efb9409d1573a90f89c1b +2009-07-03T19:25:24.801046Z +1167 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +815 + +PKAny.h +file + + + + +2009-07-03T19:31:15.000000Z +f25bdd980e9ed437bdb92b8165ff27b6 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +533 + +PKDifference.h +file + + + + +2009-07-19T19:07:31.000000Z +b6e03a03c25ffacd02d7a6b386f81b29 +2009-07-19T19:15:40.768901Z +1238 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2032 + +PKLiteral.h +file + + + + +2009-07-03T19:31:14.000000Z +2a825195d2b3163362abc1074984314d +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +722 + +PKCharacterAssembly.h +file + + + + +2009-07-03T19:31:15.000000Z +dbce70762bb36d2c3ef9c8319aea19b3 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +386 + +PKParser.h +file + + + + +2009-09-26T03:40:29.000000Z +235507561b01acef816875a11c17c15f +2009-09-26T03:50:36.795525Z +1400 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +8753 + +PKWhitespace.h +file + + + + +2009-07-03T18:54:15.000000Z +069cd2ac8c34945ba9f37b5351ee4ad2 +2009-07-03T19:25:24.801046Z +1167 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +579 + +PKWhitespaceState.h +file + + + + +2009-07-03T19:42:56.000000Z +176a2e92ea53ec53558e3e3d041cdafe +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1552 + diff --git a/include/ParseKit/.svn/prop-base/PKAlternation.h.svn-base b/include/ParseKit/.svn/prop-base/PKAlternation.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKAlternation.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKAssembly.h.svn-base b/include/ParseKit/.svn/prop-base/PKAssembly.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKAssembly.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKCaseInsensitiveLiteral.h.svn-base b/include/ParseKit/.svn/prop-base/PKCaseInsensitiveLiteral.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKCaseInsensitiveLiteral.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKChar.h.svn-base b/include/ParseKit/.svn/prop-base/PKChar.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKChar.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKCharacterAssembly.h.svn-base b/include/ParseKit/.svn/prop-base/PKCharacterAssembly.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKCharacterAssembly.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKCollectionParser.h.svn-base b/include/ParseKit/.svn/prop-base/PKCollectionParser.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKCollectionParser.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKDigit.h.svn-base b/include/ParseKit/.svn/prop-base/PKDigit.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKDigit.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKEmpty.h.svn-base b/include/ParseKit/.svn/prop-base/PKEmpty.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKEmpty.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKLetter.h.svn-base b/include/ParseKit/.svn/prop-base/PKLetter.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKLetter.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKLiteral.h.svn-base b/include/ParseKit/.svn/prop-base/PKLiteral.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKLiteral.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKLowercaseWord.h.svn-base b/include/ParseKit/.svn/prop-base/PKLowercaseWord.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKLowercaseWord.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKNumberState.h.svn-base b/include/ParseKit/.svn/prop-base/PKNumberState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKNumberState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKParser.h.svn-base b/include/ParseKit/.svn/prop-base/PKParser.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKParser.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKParserFactory.h.svn-base b/include/ParseKit/.svn/prop-base/PKParserFactory.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKParserFactory.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKQuoteState.h.svn-base b/include/ParseKit/.svn/prop-base/PKQuoteState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKQuoteState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKQuotedString.h.svn-base b/include/ParseKit/.svn/prop-base/PKQuotedString.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKQuotedString.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKReader.h.svn-base b/include/ParseKit/.svn/prop-base/PKReader.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKReader.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKRepetition.h.svn-base b/include/ParseKit/.svn/prop-base/PKRepetition.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKRepetition.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKSequence.h.svn-base b/include/ParseKit/.svn/prop-base/PKSequence.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKSequence.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKSpecificChar.h.svn-base b/include/ParseKit/.svn/prop-base/PKSpecificChar.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKSpecificChar.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKSymbol.h.svn-base b/include/ParseKit/.svn/prop-base/PKSymbol.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKSymbol.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKSymbolNode.h.svn-base b/include/ParseKit/.svn/prop-base/PKSymbolNode.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKSymbolNode.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKSymbolRootNode.h.svn-base b/include/ParseKit/.svn/prop-base/PKSymbolRootNode.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKSymbolRootNode.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKSymbolState.h.svn-base b/include/ParseKit/.svn/prop-base/PKSymbolState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKSymbolState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKTerminal.h.svn-base b/include/ParseKit/.svn/prop-base/PKTerminal.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKTerminal.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKToken.h.svn-base b/include/ParseKit/.svn/prop-base/PKToken.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKToken.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKTokenArraySource.h.svn-base b/include/ParseKit/.svn/prop-base/PKTokenArraySource.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKTokenArraySource.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKTokenAssembly.h.svn-base b/include/ParseKit/.svn/prop-base/PKTokenAssembly.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKTokenAssembly.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKTokenizer.h.svn-base b/include/ParseKit/.svn/prop-base/PKTokenizer.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKTokenizer.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKTokenizerState.h.svn-base b/include/ParseKit/.svn/prop-base/PKTokenizerState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKTokenizerState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKTrack.h.svn-base b/include/ParseKit/.svn/prop-base/PKTrack.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKTrack.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKUppercaseWord.h.svn-base b/include/ParseKit/.svn/prop-base/PKUppercaseWord.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKUppercaseWord.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKWhitespaceState.h.svn-base b/include/ParseKit/.svn/prop-base/PKWhitespaceState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKWhitespaceState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKWord.h.svn-base b/include/ParseKit/.svn/prop-base/PKWord.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKWord.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/PKWordState.h.svn-base b/include/ParseKit/.svn/prop-base/PKWordState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/PKWordState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/prop-base/ParseKit.h.svn-base b/include/ParseKit/.svn/prop-base/ParseKit.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/include/ParseKit/.svn/prop-base/ParseKit.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/include/ParseKit/.svn/text-base/PKAlternation.h.svn-base b/include/ParseKit/.svn/text-base/PKAlternation.h.svn-base new file mode 100644 index 0000000..464fd59 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKAlternation.h.svn-base @@ -0,0 +1,27 @@ +// +// PKAlternation.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKAlternation + @brief A PKAlternation object is a collection of parsers, any one of which can successfully match against an assembly. It is basically a representation of "Logical Or" or "|". +*/ +@interface PKAlternation : PKCollectionParser { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKAlternation parser. + @result an initialized autoreleased PKAlternation parser. +*/ ++ (id)alternation; + ++ (id)alternationWithSubparsers:(PKParser *)p1, ...; +@end diff --git a/include/ParseKit/.svn/text-base/PKAny.h.svn-base b/include/ParseKit/.svn/text-base/PKAny.h.svn-base new file mode 100644 index 0000000..64e6cab --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKAny.h.svn-base @@ -0,0 +1,25 @@ +// +// PKAny.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKAny + @brief A PKAny matches any token from a token assembly. +*/ +@interface PKAny : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKAny object. + @result an initialized autoreleased PKAny object +*/ ++ (id)any; +@end diff --git a/include/ParseKit/.svn/text-base/PKAssembly.h.svn-base b/include/ParseKit/.svn/text-base/PKAssembly.h.svn-base new file mode 100644 index 0000000..8722577 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKAssembly.h.svn-base @@ -0,0 +1,80 @@ +// +// PKAssembly.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +/*! + @class PKAssembly + @brief An Abstract class. A PKAssembly maintains a stream of language elements along with stack and target objects. + @details

Parsers use assemblers to record progress at recognizing language elements from assembly's string.

+

Note that PKAssembly is an abstract class and may not be instantiated directly. Subclasses include PKTokenAssembly and PKCharAssembly.

+*/ +@interface PKAssembly : NSObject { + NSMutableArray *stack; + id target; + NSUInteger index; + NSString *string; + NSString *defaultDelimiter; +} + +/*! + @brief Convenience factory method for initializing an autoreleased assembly. + @param s string to be worked on + @result an initialized autoreleased assembly +*/ ++ (id)assemblyWithString:(NSString *)s; + +/*! + @brief Designated Initializer. Initializes an assembly with a given string. + @details Designated Initializer. + @param s string to be worked on + @result an initialized assembly +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief Removes the object at the top of this assembly's stack and returns it. + @details Note this returns an object from this assembly's stack, not from its stream of elements (tokens or chars depending on the type of concrete PKAssembly subclass of this object). + @result the object at the top of this assembly's stack +*/ +- (id)pop; + +/*! + @brief Pushes an object onto the top of this assembly's stack. + @param object object to push +*/ +- (void)push:(id)object; + +/*! + @brief Returns true if this assembly's stack is empty. + @result true, if this assembly's stack is empty +*/ +- (BOOL)isStackEmpty; + +/*! + @brief Returns a vector of the elements on this assembly's stack that appear before a specified fence. + @details

Returns a vector of the elements on this assembly's stack that appear before a specified fence.

+

Sometimes a parser will recognize a list from within a pair of parentheses or brackets. The parser can mark the beginning of the list with a fence, and then retrieve all the items that come after the fence with this method.

+ @param fence object that indicates the limit of elements returned from this assembly's stack + @result Array of the elements above the specified fence +*/ +- (NSArray *)objectsAbove:(id)fence; + +/*! + @property stack + @brief This assembly's stack. +*/ +@property (nonatomic, readonly, retain) NSMutableArray *stack; + +/*! + @property target + @brief This assembly's target. + @details The object identified as this assembly's "target". Clients can set and retrieve a target, which can be a convenient supplement as a place to work, in addition to the assembly's stack. For example, a parser for an HTML file might use a web page object as its "target". As the parser recognizes markup commands like <head>, it could apply its findings to the target. +*/ +@property (nonatomic, retain) id target; +@end diff --git a/include/ParseKit/.svn/text-base/PKCaseInsensitiveLiteral.h.svn-base b/include/ParseKit/.svn/text-base/PKCaseInsensitiveLiteral.h.svn-base new file mode 100644 index 0000000..1700c2d --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKCaseInsensitiveLiteral.h.svn-base @@ -0,0 +1,20 @@ +// +// PKCaseInsensitiveLiteral.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKCaseInsensitiveLiteral + @brief A PKCaselessLiteral matches a specified NSString from an assembly, disregarding case. +*/ +@interface PKCaseInsensitiveLiteral : PKLiteral { + +} + +@end diff --git a/include/ParseKit/.svn/text-base/PKChar.h.svn-base b/include/ParseKit/.svn/text-base/PKChar.h.svn-base new file mode 100644 index 0000000..e6e3035 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKChar.h.svn-base @@ -0,0 +1,25 @@ +// +// PKChar.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +/*! + @class PKChar + @brief A PKChar matches a character from a character assembly. + @details -[PKChar qualifies:] returns true every time, since this class assumes it is working against a PKCharacterAssembly. +*/ +@interface PKChar : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKChar parser. + @result an initialized autoreleased PKChar parser. +*/ ++ (id)char; +@end diff --git a/include/ParseKit/.svn/text-base/PKCharacterAssembly.h.svn-base b/include/ParseKit/.svn/text-base/PKCharacterAssembly.h.svn-base new file mode 100644 index 0000000..6462e14 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKCharacterAssembly.h.svn-base @@ -0,0 +1,19 @@ +// +// PKCharacterAssembly.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +/*! + @class PKCharacterAssembly + @brief A PKCharacterAssembly is a PKAssembly whose elements are characters. +*/ +@interface PKCharacterAssembly : PKAssembly { + +} + +@end diff --git a/include/ParseKit/.svn/text-base/PKCollectionParser.h.svn-base b/include/ParseKit/.svn/text-base/PKCollectionParser.h.svn-base new file mode 100644 index 0000000..6388f42 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKCollectionParser.h.svn-base @@ -0,0 +1,38 @@ +// +// PKCollectionParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKCollectionParser + @brief An Abstract class. This class abstracts the behavior common to parsers that consist of a series of other parsers. +*/ +@interface PKCollectionParser : PKParser { + NSMutableArray *subparsers; +} + +/*! + @brief Designated Initializer. Initialize an instance of a PKCollectionParser subclass. + @param p1, ... A comma-separated list of parser objects ending with nil + @result an initialized instance of a PKCollectionParser subclass. +*/ +- (id)initWithSubparsers:(PKParser *)p1, ...; + +/*! + @brief Adds a parser to the collection. + @param p parser to add +*/ +- (void)add:(PKParser *)p; + +/*! + @property subparsers + @brief This parser's subparsers. +*/ +@property (nonatomic, readonly, retain) NSMutableArray *subparsers; +@end diff --git a/include/ParseKit/.svn/text-base/PKComment.h.svn-base b/include/ParseKit/.svn/text-base/PKComment.h.svn-base new file mode 100644 index 0000000..3d81709 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKComment.h.svn-base @@ -0,0 +1,25 @@ +// +// PKComment.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/31/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKComment + @brief A PKComment matches a comment from a token assembly. +*/ +@interface PKComment : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKComment object. + @result an initialized autoreleased PKComment object +*/ ++ (id)comment; +@end diff --git a/include/ParseKit/.svn/text-base/PKCommentState.h.svn-base b/include/ParseKit/.svn/text-base/PKCommentState.h.svn-base new file mode 100644 index 0000000..703c31f --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKCommentState.h.svn-base @@ -0,0 +1,71 @@ +// +// PKCommentState.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class PKSymbolRootNode; +@class PKSingleLineCommentState; +@class PKMultiLineCommentState; + +/*! + @class PKCommentState + @brief This state will either delegate to a comment-handling state, or return a PKSymbol token with just the first char in it. + @details By default, C and C++ style comments. (// to end of line and /&0x002A; &0x002A;/) +*/ +@interface PKCommentState : PKTokenizerState { + PKSymbolRootNode *rootNode; + PKSingleLineCommentState *singleLineState; + PKMultiLineCommentState *multiLineState; + BOOL reportsCommentTokens; + BOOL balancesEOFTerminatedComments; +} + +/*! + @brief Adds the given string as a single-line comment start marker. may be multi-char. + @details single line comments begin with start and continue until the next new line character. e.g. C-style comments (// comment text) + @param start a single- or multi-character marker that should be recognized as the start of a single-line comment +*/ +- (void)addSingleLineStartMarker:(NSString *)start; + +/*! + @brief Removes the given string as a single-line comment start marker. may be multi-char. + @details If start was never added as a single-line comment start marker, this has no effect. + @param start a single- or multi-character marker that should no longer be recognized as the start of a single-line comment +*/ +- (void)removeSingleLineStartMarker:(NSString *)start; + +/*! + @brief Adds the given strings as a multi-line comment start and end markers. both may be multi-char + @details start and end may be different strings. e.g. /&0x002A; and &0x002A;/. Also, the actual comment may or may not be multi-line. + @param start a single- or multi-character marker that should be recognized as the start of a multi-line comment + @param end a single- or multi-character marker that should be recognized as the end of a multi-line comment that began with start +*/ +- (void)addMultiLineStartMarker:(NSString *)start endMarker:(NSString *)end; + +/*! + @brief Removes start and its orignal end counterpart as a multi-line comment start and end markers. + @details If start was never added as a multi-line comment start marker, this has no effect. + @param start a single- or multi-character marker that should no longer be recognized as the start of a multi-line comment +*/ +- (void)removeMultiLineStartMarker:(NSString *)start; + +/*! + @property reportsCommentTokens + @brief if true, the tokenizer associated with this state will report comment tokens, otherwise it silently consumes comments + @details if true, this state will return PKTokens of type PKTokenTypeComment. + Otherwise, it will silently consume comment text and return the next token from another of the tokenizer's states +*/ +@property (nonatomic) BOOL reportsCommentTokens; + +/*! + @property balancesEOFTerminatedComments + @brief if true, this state will append a matching comment string (&0x002A;/ [C++] or :) [XQuery]) to quotes terminated by EOF. Default is NO. +*/ +@property (nonatomic) BOOL balancesEOFTerminatedComments; +@end diff --git a/include/ParseKit/.svn/text-base/PKDelimitState.h.svn-base b/include/ParseKit/.svn/text-base/PKDelimitState.h.svn-base new file mode 100644 index 0000000..ce99b78 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKDelimitState.h.svn-base @@ -0,0 +1,51 @@ +// +// PKDelimitState.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/21/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKSymbolRootNode; + +/*! + @class PKDelimitState + @brief A delimit state returns a delimited string token from a reader + @details This state will collect characters until it sees a match to the end marker that corresponds to the start marker the tokenizer used to switch to this state. +*/ +@interface PKDelimitState : PKTokenizerState { + PKSymbolRootNode *rootNode; + BOOL balancesEOFTerminatedStrings; + BOOL allowsUnbalancedStrings; + + NSMutableArray *startMarkers; + NSMutableArray *endMarkers; + NSMutableArray *characterSets; +} + +/*! + @brief Adds the given strings as a delimited string start and end markers. both may be multi-char + @details start and end may be different strings. e.g. <# and #>. + @param start a single- or multi-character marker that should be recognized as the start of a multi-line comment + @param end a single- or multi-character marker that should be recognized as the end of a multi-line comment that began with start + @param set of characters allowed to appear within the delimited string or nil to allow any non-newline characters +*/ +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end allowedCharacterSet:(NSCharacterSet *)set; + +/*! + @brief Removes start and its orignal end counterpart as a delimited string start and end markers. + @details If start was never added as a delimited string start marker, this has no effect. + @param start a single- or multi-character marker that should no longer be recognized as the start of a delimited string +*/ +- (void)removeStartMarker:(NSString *)start; + +/*! + @property balancesEOFTerminatedStrings + @brief if true, this state will append a matching end delimiter marker (e.g. --> or %>) to strings terminated by EOF. Default is NO. +*/ +@property (nonatomic) BOOL balancesEOFTerminatedStrings; + +@property (nonatomic) BOOL allowsUnbalancedStrings; +@end diff --git a/include/ParseKit/.svn/text-base/PKDelimitedString.h.svn-base b/include/ParseKit/.svn/text-base/PKDelimitedString.h.svn-base new file mode 100644 index 0000000..a062ab5 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKDelimitedString.h.svn-base @@ -0,0 +1,30 @@ +// +// PKDelimitedString.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/21/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKDelimitedString + @brief A PKDelimitedString matches a delimited string from a token assembly. +*/ +@interface PKDelimitedString : PKTerminal { + NSString *startMarker; + NSString *endMarker; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKDelimitedString object. + @result an initialized autoreleased PKDelimitedString object +*/ ++ (id)delimitedString; + ++ (id)delimitedStringWithStartMarker:(NSString *)start; + ++ (id)delimitedStringWithStartMarker:(NSString *)start endMarker:(NSString *)end; +@end diff --git a/include/ParseKit/.svn/text-base/PKDifference.h.svn-base b/include/ParseKit/.svn/text-base/PKDifference.h.svn-base new file mode 100644 index 0000000..9778eda --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKDifference.h.svn-base @@ -0,0 +1,57 @@ +// +// PKDifference.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/26/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKDifference + @brief A PKDifference matches anything its subparser would match except for anything its minus parser would match. + @details The example below would match any Word token except for true or false. + +@code + PKParser *trueParser = [PKLiteral literalWithString:@"true"]; + PKParser *falseParser = [PKLiteral literalWithString:@"false"]; + PKAlternation *reservedWords = [PKAlternation alternationWithSubparsers:trueParser, falseParser, nil]; + + PKDifference *diff = [PKDifference differenceWithSubparser:[PKWord word] minus:reservedWords]; +@endcode +*/ +@interface PKDifference : PKParser { + PKParser *subparser; + PKParser *minus; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKDifference parser. + @param subparser the parser this parser uses for matching + @param minus the parser whose matches will be exluded + @result an initialized autoreleased PKDifference parser. +*/ ++ (id)differenceWithSubparser:(PKParser *)s minus:(PKParser *)m; + +/*! + @brief Designated initializer + @param subparser the parser this parser uses for matching + @param minus the parser whose matches will be exluded + @result an initialized PKDifference parser. +*/ +- (id)initWithSubparser:(PKParser *)s minus:(PKParser *)m; + +/*! + @property subparser + @brief this parser's subparser which it will initially match against +*/ +@property (nonatomic, retain, readonly) PKParser *subparser; + +/*! + @property minus + @brief after a successful match against subparser, matches against minus will not be matched by this parser +*/ +@property (nonatomic, retain, readonly) PKParser *minus; +@end diff --git a/include/ParseKit/.svn/text-base/PKDigit.h.svn-base b/include/ParseKit/.svn/text-base/PKDigit.h.svn-base new file mode 100644 index 0000000..60642c6 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKDigit.h.svn-base @@ -0,0 +1,25 @@ +// +// PKDigit.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +/*! + @class PKDigit + @brief A PKDigit matches a digit from a character assembly. + @details -[PKDitgit qualifies:] returns true if an assembly's next element is a digit. +*/ +@interface PKDigit : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKDigit parser. + @result an initialized autoreleased PKDigit parser. +*/ ++ (id)digit; +@end diff --git a/include/ParseKit/.svn/text-base/PKEmpty.h.svn-base b/include/ParseKit/.svn/text-base/PKEmpty.h.svn-base new file mode 100644 index 0000000..5b882cf --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKEmpty.h.svn-base @@ -0,0 +1,26 @@ +// +// PKEmpty.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKEmpty + @brief A PKEmpty parser matches any assembly once, and applies its assembler that one time. + @details

Language elements often contain empty parts. For example, a language may at some point allow a list of parameters in parentheses, and may allow an empty list. An empty parser makes it easy to match, within the parenthesis, either a list of parameters or "empty".

+*/ +@interface PKEmpty : PKParser { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKEmpty parser. + @result an initialized autoreleased PKEmpty parser. +*/ ++ (id)empty; +@end diff --git a/include/ParseKit/.svn/text-base/PKIntersection.h.svn-base b/include/ParseKit/.svn/text-base/PKIntersection.h.svn-base new file mode 100644 index 0000000..034b764 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKIntersection.h.svn-base @@ -0,0 +1,35 @@ +// +// PKIntersection.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/27/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKIntersection + @brief A PKIntersection matches input that matches all of its subparsers. It is basically a representation of "Logical And" or "&". + @details The example below would match any token which is both a word and matches the given regular expression pattern. + Using a PKIntersection in this case would improve performance over using just a PKPattern parser as the regular expression would be evaluated fewer times. + +@code + PKParser *pattern = [PKPattern patternWithString:@"_.+"]; + + PKIntersection *wordStartingWithUnderscore = [PKIntersection intersectionWithSubparsers:[PKWord word], pattern, nil]; +@endcode +*/ +@interface PKIntersection : PKCollectionParser { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKIntersection parser. + @result an initialized autoreleased PKIntersection parser. +*/ ++ (id)intersection; + ++ (id)intersectionWithSubparsers:(PKParser *)p1, ...; +@end diff --git a/include/ParseKit/.svn/text-base/PKLetter.h.svn-base b/include/ParseKit/.svn/text-base/PKLetter.h.svn-base new file mode 100644 index 0000000..3c06290 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKLetter.h.svn-base @@ -0,0 +1,25 @@ +// +// PKLetter.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +/*! + @class PKLetter + @brief A PKLetter matches any letter from a character assembly. + @details -[PKLetter qualifies:] returns true if an assembly's next element is a letter. +*/ +@interface PKLetter : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKLetter parser. + @result an initialized autoreleased PKLetter parser. +*/ ++ (id)letter; +@end diff --git a/include/ParseKit/.svn/text-base/PKLiteral.h.svn-base b/include/ParseKit/.svn/text-base/PKLiteral.h.svn-base new file mode 100644 index 0000000..2f71582 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKLiteral.h.svn-base @@ -0,0 +1,28 @@ +// +// PKLiteral.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class PKToken; + +/*! + @class PKLiteral + @brief A PKLiteral matches a specific word from an assembly. +*/ +@interface PKLiteral : PKTerminal { + PKToken *literal; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKLiteral object with a given string. + @param s the word represented by this literal + @result an initialized autoreleased PKLiteral object representing s +*/ ++ (id)literalWithString:(NSString *)s; +@end diff --git a/include/ParseKit/.svn/text-base/PKLowercaseWord.h.svn-base b/include/ParseKit/.svn/text-base/PKLowercaseWord.h.svn-base new file mode 100644 index 0000000..11bd30d --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKLowercaseWord.h.svn-base @@ -0,0 +1,16 @@ +// +// PKLowercaseWord.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKLowercaseWord : PKWord { + +} + +@end diff --git a/include/ParseKit/.svn/text-base/PKMultiLineCommentState.h.svn-base b/include/ParseKit/.svn/text-base/PKMultiLineCommentState.h.svn-base new file mode 100644 index 0000000..b1c58af --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKMultiLineCommentState.h.svn-base @@ -0,0 +1,18 @@ +// +// PKMultiLineCommentState.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKMultiLineCommentState : PKTokenizerState { + NSMutableArray *startMarkers; + NSMutableArray *endMarkers; + NSString *currentStartMarker; +} + +@end diff --git a/include/ParseKit/.svn/text-base/PKNegation.h.svn-base b/include/ParseKit/.svn/text-base/PKNegation.h.svn-base new file mode 100644 index 0000000..a12ee8f --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKNegation.h.svn-base @@ -0,0 +1,46 @@ +// +// PKNegation.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +/*! + @class PKNegation + @brief A PKNegation negates the matching logic of its subparser. It matches anything its subparser would not. + @details The example below would match any token except for a ?> symbol token. This could be useful for matching all tokens until an end marker (in this case a PHP end marker) is found. + +@code + PKParser *question = [PKSymbol symbolWithString:@"?>"]; + + PKNegation *n = [PKNegation negationWithSubparser:question]; +@endcode +*/ +@interface PKNegation : PKParser { + PKParser *subparser; + PKParser *difference; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKNegation parser. + @param subparser the parser whose matching logic is negated + @result an initialized autoreleased PKNegation parser. +*/ ++ (id)negationWithSubparser:(PKParser *)s; + +/*! + @brief Designated initializer + @param subparser the parser whose matching logic is negated + @result an initialized PKNegation parser. +*/ +- (id)initWithSubparser:(PKParser *)s; + +/*! + @property subparser + @brief this parser's subparser whose matching logic is negated +*/ +@property (nonatomic, retain, readonly) PKParser *subparser; +@end diff --git a/include/ParseKit/.svn/text-base/PKNumber.h.svn-base b/include/ParseKit/.svn/text-base/PKNumber.h.svn-base new file mode 100644 index 0000000..7ffdee1 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKNumber.h.svn-base @@ -0,0 +1,25 @@ +// +// PKNumber.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKNumber + @brief A PKNumber matches a number from a token assembly. +*/ +@interface PKNumber : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKNumber object. + @result an initialized autoreleased PKNumber object +*/ ++ (id)number; +@end diff --git a/include/ParseKit/.svn/text-base/PKNumberState.h.svn-base b/include/ParseKit/.svn/text-base/PKNumberState.h.svn-base new file mode 100644 index 0000000..1b1871f --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKNumberState.h.svn-base @@ -0,0 +1,65 @@ +// +// PKNumberState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKNumberState + @brief A number state returns a number from a reader. + @details This state's idea of a number allows an optional, initial minus sign, followed by one or more digits. A decimal point and another string of digits may follow these digits. + If allowsScientificNotation is YES (default is NO) this state allows 'e' or 'E' followed by an (optionally explicityly positive or negative) integer to represent 10 to the indicated power. For example, this state will recognize 1e2 as equaling 100.

+*/ +@interface PKNumberState : PKTokenizerState { + BOOL allowsTrailingDot; + BOOL allowsScientificNotation; + BOOL allowsOctalNotation; + BOOL allowsHexadecimalNotation; + BOOL isDecimal; + BOOL isFraction; + BOOL isNegative; + BOOL isHex; + BOOL gotADigit; + NSUInteger len; + CGFloat base; + PKUniChar originalCin; + PKUniChar firstNum; + PKUniChar c; + CGFloat floatValue; + CGFloat exp; + BOOL isNegativeExp; +} + +/*! + @property allowsTrailingDot + @brief If YES, numbers are allowed to end with a trialing dot, e.g. 42. + @details default is NO +*/ +@property (nonatomic) BOOL allowsTrailingDot; + +/*! + @property allowsScientificNotation + @brief If YES, supports exponential numbers like 42.0e2, 2E+6, or 5.1e-6 + @details default is NO +*/ +@property (nonatomic) BOOL allowsScientificNotation; + +/*! + @property allowsOctalNotation + @brief If YES, supports octal numbers like 020 (16), or 0102 (66) + @details default is NO +*/ +@property (nonatomic) BOOL allowsOctalNotation; + +/*! + @property allowsHexidecimalNotation + @brief If YES, supports hex numbers like 0x20 (32), or 0xB7 (183) + @details default is NO +*/ +@property (nonatomic) BOOL allowsHexadecimalNotation; +@end diff --git a/include/ParseKit/.svn/text-base/PKParser.h.svn-base b/include/ParseKit/.svn/text-base/PKParser.h.svn-base new file mode 100644 index 0000000..b5e3ce0 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKParser.h.svn-base @@ -0,0 +1,167 @@ +// +// PKParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKAssembly; +@class PKTokenizer; + +/*! + @class PKParser + @brief An Abstract class. A PKParser is an object that recognizes the elements of a language. + @details

Each PKParser object is either a PKTerminal or a composition of other parsers. The PKTerminal class is a subclass of Parser, and is itself a hierarchy of parsers that recognize specific patterns of text. For example, a PKWord recognizes any word, and a PKLiteral matches a specific string.

+

In addition to PKTerminal, other subclasses of PKParser provide composite parsers, describing sequences, alternations, and repetitions of other parsers. For example, the following PKParser objects culminate in a good parser that recognizes a description of good coffee.

+@code + PKAlternation *adjective = [PKAlternation alternation]; + [adjective add:[PKLiteral literalWithString:@"steaming"]]; + [adjective add:[PKLiteral literalWithString:@"hot"]]; + PKSequence *good = [PKSequence sequence]; + [good add:[PKRepetition repetitionWithSubparser:adjective]]; + [good add:[PKLiteral literalWithString:@"coffee"]]; + NSString *s = @"hot hot steaming hot coffee"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + NSLog([good bestMatchFor:a]); +@endcode +

This prints out:

+@code + [hot, hot, steaming, hot, coffee] + hot/hot/steaming/hot/coffee^ +@endcode +

The parser does not match directly against a string, it matches against a PKAssembly. The resulting assembly shows its stack, with four words on it, along with its sequence of tokens, and the index at the end of these. In practice, parsers will do some work on an assembly, based on the text they recognize.

+*/ +@interface PKParser : NSObject { +#ifdef TARGET_OS_SNOW_LEOPARD + void (^assemblerBlock)(PKAssembly *); + void (^preassemblerBlock)(PKAssembly *); +#endif + id assembler; + SEL assemblerSelector; + id preassembler; + SEL preassemblerSelector; + NSString *name; + PKTokenizer *tokenizer; // PKParserFactoryAdditions ivar +} + +/*! + @brief Convenience factory method for initializing an autoreleased parser. + @result an initialized autoreleased parser. +*/ ++ (id)parser; + +/*! + @brief Sets the object and method that will work on an assembly whenever this parser successfully matches against the assembly. + @details The method represented by sel must accept a single PKAssembly argument. The signature of sel should be similar to: - (void)didMatchAssembly:(PKAssembly *)a. + @param a the assembler this parser will use to work on an assembly + @param sel a selector that assembler a responds to which will work on an assembly +*/ +- (void)setAssembler:(id)a selector:(SEL)sel; + +/*! + @brief Sets the object that will work on every assembly before matching against it. + @details Setting a preassembler is entirely optional, but sometimes useful for repetition parsers to do work on an assembly before matching against it. + @param a the assembler this parser will use to work on an assembly before matching against it. + @param sel a selector that assembler a responds to which will work on an assembly +*/ +- (void)setPreassembler:(id)a selector:(SEL)sel; + +/*! + @brief Returns the most-matched assembly in a collection. + @param inAssembly the assembly for which to find the best match + @result an assembly with the greatest possible number of elements consumed by this parser +*/ +- (PKAssembly *)bestMatchFor:(PKAssembly *)inAssembly; + +/*! + @brief Returns either nil, or a completely matched version of the supplied assembly. + @param inAssembly the assembly for which to find the complete match + @result either nil, or a completely matched version of the supplied assembly +*/ +- (PKAssembly *)completeMatchFor:(PKAssembly *)inAssembly; + +/*! + @brief Given a set of assemblies, this method matches this parser against all of them, and returns a new set of the assemblies that result from the matches. + @details

Given a set of assemblies, this method matches this parser against all of them, and returns a new set of the assemblies that result from the matches.

+

For example, consider matching the regular expression a* against the string aaab. The initial set of states is {^aaab}, where the ^ indicates how far along the assembly is. When a* matches against this initial state, it creates a new set {^aaab, a^aab, aa^ab, aaa^b}.

+ @param inAssemblies set of assemblies to match against + @result a set of assemblies that result from matching against a beginning set of assemblies +*/ +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; + +/*! + @brief Find a parser with the given name + @details Performs a depth-first recursive search (starting with this parser) for a parser or subparser with the given name. If this parser's name is name, it will be returned. + @param name of the parser to be found + @result the parser with the given name or nil if not found + */ +- (PKParser *)parserNamed:(NSString *)name; + +#ifdef TARGET_OS_SNOW_LEOPARD +/*! + @property assemblerBlock + @brief Set a block which should be executed after this parser is matched + @details

This is an alternative to calling -setAssembler:selector:.

+

Passing a block to this method will cause this parser to execute the given block after it is matched (rather than sending assembler the assemblerSelector message.

+

Using a block as the assembler will sometimes be more convient than setting an assembler object.

+ @param block of code to be executed after a parser is matched. +*/ +@property (nonatomic, retain) void (^assemblerBlock)(PKAssembly *); + +/*! + @property preassemblerBlock + @brief Set a block which should be executed before this parser is matched + @details

This is an alternative to calling -setPreassembler:selector:.

+

Passing a block to this method will cause this parser to execute the given block before it is matched (rather than sending preassembler the preassemblerSelector message.

+

Using a block as the preassembler will sometimes be more convient than setting an preassembler object.

+ @param block of code to be executed before a parser is matched. + */ +@property (nonatomic, retain) void (^preassemblerBlock)(PKAssembly *); +#endif + +/*! + @property assembler + @brief The assembler this parser will use to work on a matched assembly. + @details assembler should respond to the selector held by this parser's selector property. +*/ +@property (nonatomic, assign) id assembler; + +/*! + @property assemblerSelector + @brief The method of assembler this parser will call to work on a matched assembly. + @details The method represented by assemblerSelector must accept a single PKAssembly argument. The signature of assemblerSelector should be similar to: - (void)didMatchFoo:(PKAssembly *)a. +*/ +@property (nonatomic, assign) SEL assemblerSelector; + +/*! + @property preassembler + @brief The assembler this parser will use to work on an assembly before matching against it. + @discussion preassembler should respond to the selector held by this parser's preassemblerSelector property. +*/ +@property (nonatomic, assign) id preassembler; + +/*! + @property preAssemlerSelector + @brief The method of preassembler this parser will call to work on an assembly. + @details The method represented by preassemblerSelector must accept a single PKAssembly argument. The signature of preassemblerSelector should be similar to: - (void)didMatchAssembly:(PKAssembly *)a. +*/ +@property (nonatomic, assign) SEL preassemblerSelector; + +/*! + @property name + @brief The name of this parser. + @discussion Use this property to help in identifying a parser or for debugging purposes. +*/ +@property (nonatomic, copy) NSString *name; +@end + +@interface PKParser (PKParserFactoryAdditions) + +- (id)parse:(NSString *)s; + +- (PKTokenizer *)tokenizer; +@end + diff --git a/include/ParseKit/.svn/text-base/PKParserFactory.h.svn-base b/include/ParseKit/.svn/text-base/PKParserFactory.h.svn-base new file mode 100644 index 0000000..8024df6 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKParserFactory.h.svn-base @@ -0,0 +1,47 @@ +// +// PKParserFactory.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf All rights reserved. +// + +#import + +@class PKGrammarParser; +@class PKToken; +@class PKTokenizer; +@class PKParser; +@class PKCollectionParser; + +void PKReleaseSubparserTree(PKParser *p); + +typedef enum { + PKParserFactoryAssemblerSettingBehaviorOnAll = 1 << 1, // Default + PKParserFactoryAssemblerSettingBehaviorOnTerminals = 1 << 2, + PKParserFactoryAssemblerSettingBehaviorOnExplicit = 1 << 3, + PKParserFactoryAssemblerSettingBehaviorOnNone = 1 << 4 +} PKParserFactoryAssemblerSettingBehavior; + +@interface PKParserFactory : NSObject { + PKParserFactoryAssemblerSettingBehavior assemblerSettingBehavior; + PKGrammarParser *grammarParser; + id assembler; + id preassembler; + NSMutableDictionary *parserTokensTable; + NSMutableDictionary *parserClassTable; + NSMutableDictionary *selectorTable; + PKToken *equals; + PKToken *curly; + PKToken *paren; + BOOL isGatheringClasses; +} ++ (id)factory; + +- (PKParser *)parserFromGrammar:(NSString *)s assembler:(id)a; +- (PKParser *)parserFromGrammar:(NSString *)s assembler:(id)a preassembler:(id)pa; + +- (PKCollectionParser *)exprParser; + +@property (nonatomic) PKParserFactoryAssemblerSettingBehavior assemblerSettingBehavior; +@end diff --git a/include/ParseKit/.svn/text-base/PKPattern.h.svn-base b/include/ParseKit/.svn/text-base/PKPattern.h.svn-base new file mode 100644 index 0000000..75ca2d5 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKPattern.h.svn-base @@ -0,0 +1,32 @@ +// +// PKPattern.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/31/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import + +typedef enum { + PKPatternOptionsNone = 0, + PKPatternOptionsIgnoreCase = 2, + PKPatternOptionsComments = 4, + PKPatternOptionsMultiline = 8, + PKPatternOptionsDotAll = 32, + PKPatternOptionsUnicodeWordBoundaries = 256 +} PKPatternOptions; + +@interface PKPattern : PKTerminal { + PKPatternOptions options; +} ++ (id)patternWithString:(NSString *)s; + ++ (id)patternWithString:(NSString *)s options:(PKPatternOptions)opts; + +- (id)initWithString:(NSString *)s; + +- (id)initWithString:(NSString *)s options:(PKPatternOptions)opts; +@end diff --git a/include/ParseKit/.svn/text-base/PKQuoteState.h.svn-base b/include/ParseKit/.svn/text-base/PKQuoteState.h.svn-base new file mode 100644 index 0000000..33c6d3f --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKQuoteState.h.svn-base @@ -0,0 +1,26 @@ +// +// PKQuoteState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKQuoteState + @brief A quote state returns a quoted string token from a reader + @details This state will collect characters until it sees a match to the character that the tokenizer used to switch to this state. For example, if a tokenizer uses a double- quote character to enter this state, then -nextToken will search for another double-quote until it finds one or finds the end of the reader. +*/ +@interface PKQuoteState : PKTokenizerState { + BOOL balancesEOFTerminatedQuotes; +} + +/*! + @property balancesEOFTerminatedQuotes + @brief if true, this state will append a matching quote char (' or ") to strings terminated by EOF. Default is NO. +*/ +@property (nonatomic) BOOL balancesEOFTerminatedQuotes; +@end diff --git a/include/ParseKit/.svn/text-base/PKQuotedString.h.svn-base b/include/ParseKit/.svn/text-base/PKQuotedString.h.svn-base new file mode 100644 index 0000000..6785932 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKQuotedString.h.svn-base @@ -0,0 +1,25 @@ +// +// PKQuotedString.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKQuotedString + @brief A PKQuotedString matches a quoted string, like "this one" from a token assembly. +*/ +@interface PKQuotedString : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKQuotedString object. + @result an initialized autoreleased PKQuotedString object +*/ ++ (id)quotedString; +@end diff --git a/include/ParseKit/.svn/text-base/PKReader.h.svn-base b/include/ParseKit/.svn/text-base/PKReader.h.svn-base new file mode 100644 index 0000000..35409df --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKReader.h.svn-base @@ -0,0 +1,60 @@ +// +// PKReader.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/21/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKReader + @brief A character-stream reader that allows characters to be pushed back into the stream. +*/ +@interface PKReader : NSObject { + NSString *string; + NSUInteger offset; + NSUInteger length; +} + +/*! + @brief Designated Initializer. Initializes a reader with a given string. + @details Designated Initializer. + @param s string from which to read + @result an initialized reader +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief Read a single UTF-16 unicode character + @result The character read, or PKEOF (-1) if the end of the stream has been reached +*/ +- (PKUniChar)read; + +/*! + @brief Push back a single character + @details moves the offset back one position +*/ +- (void)unread; + +/*! + @brief Push back count characters + @param count of characters to push back + @details moves the offset back count positions +*/ +- (void)unread:(NSUInteger)count; + +/*! + @property string + @brief This reader's string. +*/ +@property (nonatomic, copy) NSString *string; + +/*! + @property offset + @brief This reader's current offset in string +*/ +@property (nonatomic, readonly) NSUInteger offset; +@end diff --git a/include/ParseKit/.svn/text-base/PKRepetition.h.svn-base b/include/ParseKit/.svn/text-base/PKRepetition.h.svn-base new file mode 100644 index 0000000..f0edcea --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKRepetition.h.svn-base @@ -0,0 +1,40 @@ +// +// PKRepetition.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKRepetition + @brief A PKRepetition matches its underlying parser repeatedly against a assembly. +*/ +@interface PKRepetition : PKParser { + PKParser *subparser; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKRepetition parser to repeatedly match against subparser p. + @param p the subparser against wich to repeatedly match + @result an initialized autoreleased PKRepetition parser. +*/ ++ (id)repetitionWithSubparser:(PKParser *)p; + +/*! + @brief Designated Initializer. Initialize a PKRepetition parser to repeatedly match against subparser p. + @details Designated Initializer. Initialize a PKRepetition parser to repeatedly match against subparser p. + @param p the subparser against wich to repeatedly match + @result an initialized PKRepetition parser. +*/ +- (id)initWithSubparser:(PKParser *)p; + +/*! + @property subparser + @brief this parser's subparser against which it repeatedly matches +*/ +@property (nonatomic, readonly, retain) PKParser *subparser; +@end diff --git a/include/ParseKit/.svn/text-base/PKSequence.h.svn-base b/include/ParseKit/.svn/text-base/PKSequence.h.svn-base new file mode 100644 index 0000000..931dc13 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKSequence.h.svn-base @@ -0,0 +1,27 @@ +// +// PKSequence.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKSequence + @brief A PKSequence object is a collection of parsers, all of which must in turn match against an assembly for this parser to successfully match. +*/ +@interface PKSequence : PKCollectionParser { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKSequence parser. + @result an initialized autoreleased PKSequence parser. +*/ ++ (id)sequence; + ++ (id)sequenceWithSubparsers:(PKParser *)p1, ...; +@end diff --git a/include/ParseKit/.svn/text-base/PKSingleLineCommentState.h.svn-base b/include/ParseKit/.svn/text-base/PKSingleLineCommentState.h.svn-base new file mode 100644 index 0000000..2781129 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKSingleLineCommentState.h.svn-base @@ -0,0 +1,17 @@ +// +// PKSingleLineCommentState.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKSingleLineCommentState : PKTokenizerState { + NSMutableArray *startMarkers; + NSString *currentStartMarker; +} + +@end diff --git a/include/ParseKit/.svn/text-base/PKSpecificChar.h.svn-base b/include/ParseKit/.svn/text-base/PKSpecificChar.h.svn-base new file mode 100644 index 0000000..08e5ced --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKSpecificChar.h.svn-base @@ -0,0 +1,34 @@ +// +// PKSpecificChar.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKSpecificChar + @brief A PKSpecificChar matches a specified character from a character assembly. + @details -[PKSpecificChar qualifies:] returns true if an assembly's next element is equal to the character this object was constructed with. +*/ +@interface PKSpecificChar : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKSpecificChar parser. + @param c the character this object should match + @result an initialized autoreleased PKSpecificChar parser. +*/ ++ (id)specificCharWithChar:(PKUniChar)c; + +/*! + @brief Designated Initializer. Initializes a PKSpecificChar parser. + @param c the character this object should match + @result an initialized PKSpecificChar parser. +*/ +- (id)initWithSpecificChar:(PKUniChar)c; +@end diff --git a/include/ParseKit/.svn/text-base/PKSymbol.h.svn-base b/include/ParseKit/.svn/text-base/PKSymbol.h.svn-base new file mode 100644 index 0000000..41611e8 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKSymbol.h.svn-base @@ -0,0 +1,34 @@ +// +// PKSymbol.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class PKToken; + +/*! + @class PKSymbol + @brief A PKSymbol matches a specific sequence, such as <, or <= that a tokenizer returns as a symbol. +*/ +@interface PKSymbol : PKTerminal { + PKToken *symbol; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKSymbol object with a nil string value. + @result an initialized autoreleased PKSymbol object with a nil string value +*/ ++ (id)symbol; + +/*! + @brief Convenience factory method for initializing an autoreleased PKSymbol object with s as a string value. + @param s the string represented by this symbol + @result an initialized autoreleased PKSymbol object with s as a string value +*/ ++ (id)symbolWithString:(NSString *)s; +@end diff --git a/include/ParseKit/.svn/text-base/PKSymbolNode.h.svn-base b/include/ParseKit/.svn/text-base/PKSymbolNode.h.svn-base new file mode 100644 index 0000000..bc17a47 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKSymbolNode.h.svn-base @@ -0,0 +1,38 @@ +// +// PKSymbolNode.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKSymbolNode + @brief A PKSymbolNode object is a member of a tree that contains all possible prefixes of allowable symbols. + @details A PKSymbolNode object is a member of a tree that contains all possible prefixes of allowable symbols. Multi-character symbols appear in a PKSymbolNode tree with one node for each character. For example, the symbol =:~ will appear in a tree as three nodes. The first node contains an equals sign, and has a child; that child contains a colon and has a child; this third child contains a tilde, and has no children of its own. If the colon node had another child for a dollar sign character, then the tree would contain the symbol =:$. A tree of PKSymbolNode objects collaborate to read a (potentially multi-character) symbol from an input stream. A root node with no character of its own finds an initial node that represents the first character in the input. This node looks to see if the next character in the stream matches one of its children. If so, the node delegates its reading task to its child. This approach walks down the tree, pulling symbols from the input that match the path down the tree. When a node does not have a child that matches the next character, we will have read the longest possible symbol prefix. This prefix may or may not be a valid symbol. Consider a tree that has had =:~ added and has not had =: added. In this tree, of the three nodes that contain =:~, only the first and third contain complete symbols. If, say, the input contains =:a, the colon node will not have a child that matches the 'a' and so it will stop reading. The colon node has to "unread": it must push back its character, and ask its parent to unread. Unreading continues until it reaches an ancestor that represents a valid symbol. +*/ +@interface PKSymbolNode : NSObject { + NSString *ancestry; + PKSymbolNode *parent; + NSMutableDictionary *children; + PKUniChar character; + NSString *string; +} + +/*! + @brief Initializes a PKSymbolNode with the given parent, representing the given character. + @param p the parent of this node + @param c the character for this node + @result An initialized PKSymbolNode +*/ +- (id)initWithParent:(PKSymbolNode *)p character:(PKUniChar)c; + +/*! + @property ancestry + @brief The string of the mulit-character symbol this node represents. +*/ +@property (nonatomic, readonly, retain) NSString *ancestry; +@end diff --git a/include/ParseKit/.svn/text-base/PKSymbolRootNode.h.svn-base b/include/ParseKit/.svn/text-base/PKSymbolRootNode.h.svn-base new file mode 100644 index 0000000..346ce87 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKSymbolRootNode.h.svn-base @@ -0,0 +1,42 @@ +// +// PKSymbolRootNode.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class PKReader; + +/*! + @class PKSymbolRootNode + @brief This class is a special case of a PKSymbolNode. + @details This class is a special case of a PKSymbolNode. A PKSymbolRootNode object has no symbol of its own, but has children that represent all possible symbols. +*/ +@interface PKSymbolRootNode : PKSymbolNode { +} + +/*! + @brief Adds the given string as a multi-character symbol. + @param s a multi-character symbol that should be recognized as a single symbol token by this state +*/ +- (void)add:(NSString *)s; + +/*! + @brief Removes the given string as a multi-character symbol. + @param s a multi-character symbol that should no longer be recognized as a single symbol token by this state + @details if s was never added as a multi-character symbol, this has no effect +*/ +- (void)remove:(NSString *)s; + +/*! + @brief Return a symbol string from a reader. + @param r the reader from which to read + @param cin the character from witch to start + @result a symbol string from a reader +*/ +- (NSString *)nextSymbol:(PKReader *)r startingWith:(PKUniChar)cin; +@end diff --git a/include/ParseKit/.svn/text-base/PKSymbolState.h.svn-base b/include/ParseKit/.svn/text-base/PKSymbolState.h.svn-base new file mode 100644 index 0000000..d53e32a --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKSymbolState.h.svn-base @@ -0,0 +1,38 @@ +// +// PKSymbolState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class PKSymbolRootNode; + +/*! + @class PKSymbolState + @brief The idea of a symbol is a character that stands on its own, such as an ampersand or a parenthesis. + @details

The idea of a symbol is a character that stands on its own, such as an ampersand or a parenthesis. For example, when tokenizing the expression (isReady)& (isWilling) , a typical tokenizer would return 7 tokens, including one for each parenthesis and one for the ampersand. Thus a series of symbols such as )&( becomes three tokens, while a series of letters such as isReady becomes a single word token.

+

Multi-character symbols are an exception to the rule that a symbol is a standalone character. For example, a tokenizer may want less-than-or-equals to tokenize as a single token. This class provides a method for establishing which multi-character symbols an object of this class should treat as single symbols. This allows, for example, "cat <= dog" to tokenize as three tokens, rather than splitting the less-than and equals symbols into separate tokens.

+

By default, this state recognizes the following multi- character symbols: !=, :-, <=, >=

+*/ +@interface PKSymbolState : PKTokenizerState { + PKSymbolRootNode *rootNode; + NSMutableArray *addedSymbols; +} + +/*! + @brief Adds the given string as a multi-character symbol. + @param s a multi-character symbol that should be recognized as a single symbol token by this state +*/ +- (void)add:(NSString *)s; + +/*! + @brief Removes the given string as a multi-character symbol. + @details If s was never added as a multi-character symbol, this has no effect. + @param s a multi-character symbol that should no longer be recognized as a single symbol token by this state +*/ +- (void)remove:(NSString *)s; +@end diff --git a/include/ParseKit/.svn/text-base/PKTerminal.h.svn-base b/include/ParseKit/.svn/text-base/PKTerminal.h.svn-base new file mode 100644 index 0000000..1697a1b --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKTerminal.h.svn-base @@ -0,0 +1,43 @@ +// +// PKTerminal.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class PKToken; + +/*! + @class PKTerminal + @brief An Abstract Class. A PKTerminal is a parser that is not a composition of other parsers. +*/ +@interface PKTerminal : PKParser { + NSString *string; + BOOL discardFlag; +} + +/*! + @brief Designated Initializer for all concrete PKTerminal subclasses. + @details Note this is an abtract class and this method must be called on a concrete subclass. + @param s the string matched by this parser + @result an initialized PKTerminal subclass object +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief By default, terminals push themselves upon a assembly's stack, after a successful match. This method will turn off that behavior. + @details This method returns this parser as a convenience for chainging-style usage. + @result this parser, returned for chaining/convenience +*/ +- (PKTerminal *)discard; + +/*! + @property string + @brief the string matched by this parser. +*/ +@property (nonatomic, readonly, copy) NSString *string; +@end diff --git a/include/ParseKit/.svn/text-base/PKToken.h.svn-base b/include/ParseKit/.svn/text-base/PKToken.h.svn-base new file mode 100644 index 0000000..747618c --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKToken.h.svn-base @@ -0,0 +1,166 @@ +// +// PKToken.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +/*! + @typedef enum PKTokenType + @brief Indicates the type of a PKToken + @var PKTokenTypeEOF A constant indicating that the endo fo the stream has been read. + @var PKTokenTypeNumber A constant indicating that a token is a number, like 3.14. + @var PKTokenTypeQuotedString A constant indicating that a token is a quoted string, like "Launch Mi". + @var PKTokenTypeSymbol A constant indicating that a token is a symbol, like "<=". + @var PKTokenTypeWord A constant indicating that a token is a word, like cat. + @var PKTokenTypeWhitespace A constant indicating that a token is whitespace, like \t. + @var PKTokenTypeComment A constant indicating that a token is a comment, like // this is a hack. + @var PKTokenTypeDelimtedString A constant indicating that a token is a delimitedString, like <#foo>. +*/ +typedef enum { + PKTokenTypeEOF, + PKTokenTypeNumber, + PKTokenTypeQuotedString, + PKTokenTypeSymbol, + PKTokenTypeWord, + PKTokenTypeWhitespace, + PKTokenTypeComment, + PKTokenTypeDelimitedString, + PKTokenTypeAny +} PKTokenType; + +/*! + @class PKToken + @brief A token represents a logical chunk of a string. + @details For example, a typical tokenizer would break the string "1.23 <= 12.3" into three tokens: the number 1.23, a less-than-or-equal symbol, and the number 12.3. A token is a receptacle, and relies on a tokenizer to decide precisely how to divide a string into tokens. +*/ +@interface PKToken : NSObject { + CGFloat floatValue; + NSString *stringValue; + PKTokenType tokenType; + + BOOL number; + BOOL quotedString; + BOOL symbol; + BOOL word; + BOOL whitespace; + BOOL comment; + BOOL delimitedString; + + id value; + NSUInteger offset; +} + +/*! + @brief Factory method for creating a singleton PKToken used to indicate that there are no more tokens. + @result A singleton used to indicate that there are no more tokens. +*/ ++ (PKToken *)EOFToken; + +/*! + @brief Factory convenience method for creating an autoreleased token. + @param t the type of this token. + @param s the string value of this token. + @param n the number falue of this token. + @result an autoreleased initialized token. +*/ ++ (id)tokenWithTokenType:(PKTokenType)t stringValue:(NSString *)s floatValue:(CGFloat)n; + +/*! + @brief Designated initializer. Constructs a token of the indicated type and associated string or numeric values. + @param t the type of this token. + @param s the string value of this token. + @param n the number falue of this token. + @result an autoreleased initialized token. +*/ +- (id)initWithTokenType:(PKTokenType)t stringValue:(NSString *)s floatValue:(CGFloat)n; + +/*! + @brief Returns true if the supplied object is an equivalent PKToken, ignoring differences in case. + @param obj the object to compare this token to. + @result true if obj is an equivalent PKToken, ignoring differences in case. +*/ +- (BOOL)isEqualIgnoringCase:(id)obj; + +/*! + @brief Returns more descriptive textual representation than -description which may be useful for debugging puposes only. + @details Usually of format similar to: <QuotedString "Launch Mi">, <Word cat>, or <Number 3.14> + @result A textual representation including more descriptive information than -description. +*/ +- (NSString *)debugDescription; + +/*! + @property number + @brief True if this token is a number. getter=isNumber +*/ +@property (nonatomic, readonly, getter=isNumber) BOOL number; + +/*! + @property quotedString + @brief True if this token is a quoted string. getter=isQuotedString +*/ +@property (nonatomic, readonly, getter=isQuotedString) BOOL quotedString; + +/*! + @property symbol + @brief True if this token is a symbol. getter=isSymbol +*/ +@property (nonatomic, readonly, getter=isSymbol) BOOL symbol; + +/*! + @property word + @brief True if this token is a word. getter=isWord +*/ +@property (nonatomic, readonly, getter=isWord) BOOL word; + +/*! + @property whitespace + @brief True if this token is whitespace. getter=isWhitespace +*/ +@property (nonatomic, readonly, getter=isWhitespace) BOOL whitespace; + +/*! + @property comment + @brief True if this token is a comment. getter=isComment +*/ +@property (nonatomic, readonly, getter=isComment) BOOL comment; + +/*! + @property delimitedString + @brief True if this token is a delimited string. getter=isDelimitedString +*/ +@property (nonatomic, readonly, getter=isDelimitedString) BOOL delimitedString; + +/*! + @property tokenType + @brief The type of this token. +*/ +@property (nonatomic, readonly) PKTokenType tokenType; + +/*! + @property floatValue + @brief The numeric value of this token. +*/ +@property (nonatomic, readonly) CGFloat floatValue; + +/*! + @property stringValue + @brief The string value of this token. +*/ +@property (nonatomic, readonly, copy) NSString *stringValue; + +/*! + @property value + @brief Returns an object that represents the value of this token. +*/ +@property (nonatomic, readonly, copy) id value; + +/*! + @property offset + @brief The character offset of this token in the original source string. +*/ +@property (nonatomic, readonly) NSUInteger offset; +@end diff --git a/include/ParseKit/.svn/text-base/PKTokenArraySource.h.svn-base b/include/ParseKit/.svn/text-base/PKTokenArraySource.h.svn-base new file mode 100644 index 0000000..e4b63cf --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKTokenArraySource.h.svn-base @@ -0,0 +1,62 @@ +// +// PKTokenArraySource.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/11/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKTokenizer; +@class PKToken; + +/*! + @class PKTokenArraySource + @brief A TokenArraySource is a handy utility that enumerates over a specified reader, returning NSArrays of PKTokens delimited by a specified delimiter. + @details For example, + +@code + NSString *s = @"I came; I saw; I left in peace;"; + + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKTokenArraySource *src = [[[PKTokenArraySource alloc] initWithTokenizer:t delimiter:@";"] autorelease]; + + while ([src hasMore]) { + NSLog(@"%@", [src nextTokenArray]); + } +@endcode + + prints out: + +@code + I came + I saw + I left in peace +@endcode +*/ +@interface PKTokenArraySource : NSObject { + PKTokenizer *tokenizer; + NSString *delimiter; + PKToken *nextToken; +} + +/*! + @brief Constructs a PKTokenArraySource that will read an NSArrays of PKTokens using the specified tokenizer, delimited by the specified delimiter. + @param tokenizer a tokenizer to read tokens from + @param delimiter the character(s) that fences off where one array of tokens ends and the next begins +*/ +- (id)initWithTokenizer:(PKTokenizer *)t delimiter:(NSString *)s; + +/*! + @brief true if the source has more arrays of tokens. + @result true, if the source has more arrays of tokens that have not yet been popped with -nextTokenArray +*/ +- (BOOL)hasMore; + +/*! + @brief Returns the next array of tokens from the source. + @result the next array of tokens from the source +*/ +- (NSArray *)nextTokenArray; +@end diff --git a/include/ParseKit/.svn/text-base/PKTokenAssembly.h.svn-base b/include/ParseKit/.svn/text-base/PKTokenAssembly.h.svn-base new file mode 100644 index 0000000..04dc038 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKTokenAssembly.h.svn-base @@ -0,0 +1,57 @@ +// +// PKTokenAssembly.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKTokenizer; + +/*! + @class PKTokenAssembly + @brief A PKTokenAssembly is a PKAssembly whose elements are PKTokens. + @details PKTokens are, roughly, the chunks of text that a PKTokenizer returns. +*/ +@interface PKTokenAssembly : PKAssembly { + PKTokenizer *tokenizer; + NSArray *tokens; + BOOL preservesWhitespaceTokens; +} + +/*! + @brief Convenience factory method for initializing an autoreleased assembly with the tokenizer t and its string + @param t tokenizer whose string will be worked on + @result an initialized autoreleased assembly +*/ ++ (id)assemblyWithTokenizer:(PKTokenizer *)t; + +/*! + @brief Convenience factory method for initializing an autoreleased assembly with the token array a and its string + @param a token array whose string will be worked on + @result an initialized autoreleased assembly +*/ ++ (id)assemblyWithTokenArray:(NSArray *)a; + +/*! + @brief Initializes an assembly with the tokenizer t and its string + @param t tokenizer whose string will be worked on + @result an initialized assembly +*/ +- (id)initWithTokenzier:(PKTokenizer *)t; + +/*! + @brief Initializes an assembly with the token array a and its string + @param a token array whose string will be worked on + @result an initialized assembly +*/ +- (id)initWithTokenArray:(NSArray *)a; + +/*! + @property preservesWhitespaceTokens + @brief If true, whitespace tokens retreived from this assembly's tokenizier will be silently placed on this assembly's stack without being reported by -next or -peek. Default is false. +*/ +@property (nonatomic) BOOL preservesWhitespaceTokens; +@end diff --git a/include/ParseKit/.svn/text-base/PKTokenizer.h.svn-base b/include/ParseKit/.svn/text-base/PKTokenizer.h.svn-base new file mode 100644 index 0000000..647d9bd --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKTokenizer.h.svn-base @@ -0,0 +1,150 @@ +// +// ParseKit.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class PKToken; +@class PKTokenizerState; +@class PKNumberState; +@class PKQuoteState; +@class PKCommentState; +@class PKSymbolState; +@class PKWhitespaceState; +@class PKWordState; +@class PKDelimitState; +@class PKReader; + +/*! + @class PKTokenizer + @brief A tokenizer divides a string into tokens. + @details

This class is highly customizable with regard to exactly how this division occurs, but it also has defaults that are suitable for many languages. This class assumes that the character values read from the string lie in the range 0-MAXINT. For example, the Unicode value of a capital A is 65, so NSLog(@"%C", (unichar)65); prints out a capital A.

+

The behavior of a tokenizer depends on its character state table. This table is an array of 256 PKTokenizerState states. The state table decides which state to enter upon reading a character from the input string.

+

For example, by default, upon reading an 'A', a tokenizer will enter a "word" state. This means the tokenizer will ask a PKWordState object to consume the 'A', along with the characters after the 'A' that form a word. The state's responsibility is to consume characters and return a complete token.

+

The default table sets a PKSymbolState for every character from 0 to 255, and then overrides this with:

+@code + From To State + 0 ' ' whitespaceState + 'a' 'z' wordState + 'A' 'Z' wordState + 160 255 wordState + '0' '9' numberState + '-' '-' numberState + '.' '.' numberState + '"' '"' quoteState + '\'' '\'' quoteState + '/' '/' commentState +@endcode +

In addition to allowing modification of the state table, this class makes each of the states above available. Some of these states are customizable. For example, wordState allows customization of what characters can be part of a word, after the first character.

+*/ +@interface PKTokenizer : NSObject { + NSString *string; + PKReader *reader; + + NSMutableArray *tokenizerStates; + + PKNumberState *numberState; + PKQuoteState *quoteState; + PKCommentState *commentState; + PKSymbolState *symbolState; + PKWhitespaceState *whitespaceState; + PKWordState *wordState; + PKDelimitState *delimitState; +} + +/*! + @brief Convenience factory method. Sets string from which to to read to nil. + @result An initialized tokenizer. +*/ ++ (id)tokenizer; + +/*! + @brief Convenience factory method. + @param s string to read from. + @result An autoreleased initialized tokenizer. +*/ ++ (id)tokenizerWithString:(NSString *)s; + +/*! + @brief Designated Initializer. Constructs a tokenizer to read from the supplied string. + @param s string to read from. + @result An initialized tokenizer. +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief Returns the next token. + @result the next token. +*/ +- (PKToken *)nextToken; + +#ifdef TARGET_OS_SNOW_LEOPARD +/*! + @brief Enumerate tokens in this tokenizer using block + @details repeatedly executes block by passing the token returned from calling -nextToken on this tokenizer + @param block the code to execute with every token returned by calling -nextToken on this tokenizer +*/ +- (void)enumerateTokensUsingBlock:(void (^)(PKToken *tok, BOOL *stop))block; +#endif + +/*! + @brief Change the state the tokenizer will enter upon reading any character between "start" and "end". + @param state the state for this character range + @param start the "start" character. e.g. 'a' or 65. + @param end the "end" character. 'z' or 90. +*/ +- (void)setTokenizerState:(PKTokenizerState *)state from:(PKUniChar)start to:(PKUniChar)end; + +/*! + @property string + @brief The string to read from. +*/ +@property (nonatomic, retain) NSString *string; + +/*! + @property numberState + @brief The state this tokenizer uses to build numbers. +*/ +@property (nonatomic, retain) PKNumberState *numberState; + +/*! + @property quoteState + @brief The state this tokenizer uses to build quoted strings. +*/ +@property (nonatomic, retain) PKQuoteState *quoteState; + +/*! + @property commentState + @brief The state this tokenizer uses to recognize (and possibly ignore) comments. +*/ +@property (nonatomic, retain) PKCommentState *commentState; + +/*! + @property symbolState + @brief The state this tokenizer uses to recognize symbols. +*/ +@property (nonatomic, retain) PKSymbolState *symbolState; + +/*! + @property whitespaceState + @brief The state this tokenizer uses to recognize (and possibly ignore) whitespace. +*/ +@property (nonatomic, retain) PKWhitespaceState *whitespaceState; + +/*! + @property wordState + @brief The state this tokenizer uses to build words. +*/ +@property (nonatomic, retain) PKWordState *wordState; + +/*! + @property delimitState + @brief The state this tokenizer uses to build delimited strings. +*/ +@property (nonatomic, retain) PKDelimitState *delimitState; +@end diff --git a/include/ParseKit/.svn/text-base/PKTokenizerState.h.svn-base b/include/ParseKit/.svn/text-base/PKTokenizerState.h.svn-base new file mode 100644 index 0000000..820240d --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKTokenizerState.h.svn-base @@ -0,0 +1,50 @@ +// +// ParseKitState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class PKToken; +@class PKTokenizer; +@class PKReader; + +/*! + @class PKTokenizerState + @brief A PKTokenizerState returns a token, given a reader, an initial character read from the reader, and a tokenizer that is conducting an overall tokenization of the reader. + @details The tokenizer will typically have a character state table that decides which state to use, depending on an initial character. If a single character is insufficient, a state such as PKCommentState will read a second character, and may delegate to another state, such as PKSingleLineState. This prospect of delegation is the reason that the -nextToken method has a tokenizer argument. +*/ +@interface PKTokenizerState : NSObject { + NSMutableString *stringbuf; + NSUInteger offset; + PKTokenizerState *fallbackState; + NSMutableArray *fallbackStates; +} + +/*! + @brief Return a token that represents a logical piece of a reader. + @param r the reader from which to read additional characters + @param cin the character that a tokenizer used to determine to use this state + @param t the tokenizer currently powering the tokenization + @result a token that represents a logical piece of the reader +*/ +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t; + +/*! + @brief Change the state this state will defer to upon reading any character between "start" and "end". + @param state the fallback state for this character range + @param start the "start" character. e.g. 'a' or 65. + @param end the "end" character. 'z' or 90. +*/ +- (void)setFallbackState:(PKTokenizerState *)state from:(PKUniChar)start to:(PKUniChar)end; + +/*! + @property fallbackState + @brief The state this tokenizer defers to if it starts, but ultimately aborts recognizing a token +*/ +@property (nonatomic, retain) PKTokenizerState *fallbackState; +@end diff --git a/include/ParseKit/.svn/text-base/PKTrack.h.svn-base b/include/ParseKit/.svn/text-base/PKTrack.h.svn-base new file mode 100644 index 0000000..fc0005a --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKTrack.h.svn-base @@ -0,0 +1,28 @@ +// +// PKTrack.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKTrack + @brief A PKTrack is a sequence that throws a PKTrackException if the sequence begins but does not complete. + @details If -[PKTrack allMatchesFor:] begins but does not complete, it throws a PKTrackException. +*/ +@interface PKTrack : PKSequence { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKTrack parser. + @result an initialized autoreleased PKTrack parser. +*/ ++ (id)track; + ++ (id)trackWithSubparsers:(PKParser *)p1, ...; +@end diff --git a/include/ParseKit/.svn/text-base/PKTrackException.h.svn-base b/include/ParseKit/.svn/text-base/PKTrackException.h.svn-base new file mode 100644 index 0000000..8ab3d4d --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKTrackException.h.svn-base @@ -0,0 +1,25 @@ +// +// PKTrackException.h +// ParseKit +// +// Created by Todd Ditchendorf on 10/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +extern NSString * const PKTrackExceptionName; + +/*! + @class PKTrackException + @brief Signals that a parser could not match text after a specific point. + @details The userInfo for this exception contains the following keys:
+            after (NSString *) - some indication of what text was interpretable before this exception occurred
+            expected (NSString *) - some indication of what kind of thing was expected, such as a ')' token
+            found (NSString *) - the text element the thrower actually found when it expected something else
+*/ +@interface PKTrackException : NSException { + +} + +@end diff --git a/include/ParseKit/.svn/text-base/PKTypes.h.svn-base b/include/ParseKit/.svn/text-base/PKTypes.h.svn-base new file mode 100644 index 0000000..9cac91b --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKTypes.h.svn-base @@ -0,0 +1,13 @@ +/* + * PKTypes.h + * ParseKit + * + * Created by Todd Ditchendorf on 3/15/09. + * Copyright 2009 Todd Ditchendorf. All rights reserved. + * + */ + +// a UTF-16 character. signed so that it may represent -1 as well +typedef SInt32 PKUniChar; + +#define PKEOF (PKUniChar)-1 \ No newline at end of file diff --git a/include/ParseKit/.svn/text-base/PKUppercaseWord.h.svn-base b/include/ParseKit/.svn/text-base/PKUppercaseWord.h.svn-base new file mode 100644 index 0000000..24533cb --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKUppercaseWord.h.svn-base @@ -0,0 +1,16 @@ +// +// PKUppercaseWord.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKUppercaseWord : PKWord { + +} + +@end diff --git a/include/ParseKit/.svn/text-base/PKWhitespace.h.svn-base b/include/ParseKit/.svn/text-base/PKWhitespace.h.svn-base new file mode 100644 index 0000000..0bea0c1 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKWhitespace.h.svn-base @@ -0,0 +1,25 @@ +// +// PKWhitespace.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/19/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKWhitespace + @brief A PKWhitespace matches a number from a token assembly. +*/ +@interface PKWhitespace : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKWhitespace object. + @result an initialized autoreleased PKWhitespace object +*/ ++ (id)whitespace; +@end diff --git a/include/ParseKit/.svn/text-base/PKWhitespaceState.h.svn-base b/include/ParseKit/.svn/text-base/PKWhitespaceState.h.svn-base new file mode 100644 index 0000000..e780e13 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKWhitespaceState.h.svn-base @@ -0,0 +1,42 @@ +// +// PKWhitespaceState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKWhitespaceState + @brief A whitespace state ignores whitespace (such as blanks and tabs), and returns the tokenizer's next token. + @details By default, all characters from 0 to 32 are whitespace. +*/ +@interface PKWhitespaceState : PKTokenizerState { + NSMutableArray *whitespaceChars; + BOOL reportsWhitespaceTokens; +} + +/*! + @brief Informs whether the given character is recognized as whitespace (and therefore ignored) by this state. + @param cin the character to check + @result true if the given chracter is recognized as whitespace +*/ +- (BOOL)isWhitespaceChar:(PKUniChar)cin; + +/*! + @brief Establish the given character range as whitespace to ignore. + @param yn true if the given character range is whitespace + @param start the "start" character. e.g. 'a' or 65. + @param end the "end" character. 'z' or 90. +*/ +- (void)setWhitespaceChars:(BOOL)yn from:(PKUniChar)start to:(PKUniChar)end; + +/*! + @property reportsWhitespaceTokens + @brief determines whether a PKTokenizer associated with this state reports or silently consumes whitespace tokens. default is NO which causes silent consumption of whitespace chars +*/ +@property (nonatomic) BOOL reportsWhitespaceTokens; +@end diff --git a/include/ParseKit/.svn/text-base/PKWord.h.svn-base b/include/ParseKit/.svn/text-base/PKWord.h.svn-base new file mode 100644 index 0000000..2e94aa7 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKWord.h.svn-base @@ -0,0 +1,25 @@ +// +// PKWord.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKWord + @brief A PKWord matches a word from a token assembly. +*/ +@interface PKWord : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKWord object. + @result an initialized autoreleased PKWord object +*/ ++ (id)word; +@end diff --git a/include/ParseKit/.svn/text-base/PKWordState.h.svn-base b/include/ParseKit/.svn/text-base/PKWordState.h.svn-base new file mode 100644 index 0000000..7b9b0a8 --- /dev/null +++ b/include/ParseKit/.svn/text-base/PKWordState.h.svn-base @@ -0,0 +1,43 @@ +// +// PKWordState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKWordState + @brief A word state returns a word from a reader. + @details

Like other states, a tokenizer transfers the job of reading to this state, depending on an initial character. Thus, the tokenizer decides which characters may begin a word, and this state determines which characters may appear as a second or later character in a word. These are typically different sets of characters; in particular, it is typical for digits to appear as parts of a word, but not as the initial character of a word.

+

By default, the following characters may appear in a word. The method setWordChars() allows customizing this.

+@code + From To + 'a' 'z' + 'A' 'Z' + '0' '9' +@endcode +

as well as: minus sign -, underscore _, and apostrophe '.

+*/ +@interface PKWordState : PKTokenizerState { + NSMutableArray *wordChars; +} + +/*! + @brief Establish characters in the given range as valid characters for part of a word after the first character. Note that the tokenizer must determine which characters are valid as the beginning character of a word. + @param yn true if characters in the given range are word characters + @param start the "start" character. e.g. 'a' or 65. + @param end the "end" character. 'z' or 90. +*/ +- (void)setWordChars:(BOOL)yn from:(PKUniChar)start to:(PKUniChar)end; + +/*! + @brief Informs whether the given character is recognized as a word character by this state. + @param cin the character to check + @result true if the given chracter is recognized as a word character +*/ +- (BOOL)isWordChar:(PKUniChar)c; +@end diff --git a/include/ParseKit/.svn/text-base/ParseKit.h.svn-base b/include/ParseKit/.svn/text-base/ParseKit.h.svn-base new file mode 100644 index 0000000..926783f --- /dev/null +++ b/include/ParseKit/.svn/text-base/ParseKit.h.svn-base @@ -0,0 +1,82 @@ +// +// ParseKit.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/21/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +/*! + @mainpage ParseKit + ParseKit is a Mac OS X Framework written by Todd Ditchendorf in Objective-C 2.0 and released under the MIT Open Source License. + The framework is an Objective-C implementation of the tools described in "Building Parsers with Java" by Steven John Metsker. + ParseKit includes some significant additions beyond the designs from the book (many of them hinted at in the book itself) in order to enhance the framework's feature set, usefulness and ease-of-use. Other changes have been made to the designs in the book to match common Cocoa/Objective-C design patterns and conventions. + However, these changes are relatively superficial, and Metsker's book is the best documentation available for this framework. + + Classes in the ParseKit Framework offer 2 basic services of general use to Cocoa developers: + @li Tokenization via a tokenizer class + @li Parsing via a high-level parser-building toolkit + Learn more on the project site +*/ + +#import + +// io +#import +#import + +// parse +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +//chars +#import +#import +#import +#import +#import + +// tokens +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +// grammar +#import diff --git a/include/ParseKit/PKAlternation.h b/include/ParseKit/PKAlternation.h new file mode 100644 index 0000000..4545774 --- /dev/null +++ b/include/ParseKit/PKAlternation.h @@ -0,0 +1,33 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKAlternation + @brief A PKAlternation object is a collection of parsers, any one of which can successfully match against an assembly. It is basically a representation of "Logical Or" or "|". +*/ +@interface PKAlternation : PKCollectionParser { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKAlternation parser. + @result an initialized autoreleased PKAlternation parser. +*/ ++ (id)alternation; + ++ (id)alternationWithSubparsers:(PKParser *)p1, ...; +@end diff --git a/include/ParseKit/PKAny.h b/include/ParseKit/PKAny.h new file mode 100644 index 0000000..656e0cd --- /dev/null +++ b/include/ParseKit/PKAny.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKAny + @brief A PKAny matches any token from a token assembly. +*/ +@interface PKAny : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKAny object. + @result an initialized autoreleased PKAny object +*/ ++ (id)any; +@end diff --git a/include/ParseKit/PKAssembly.h b/include/ParseKit/PKAssembly.h new file mode 100644 index 0000000..274e062 --- /dev/null +++ b/include/ParseKit/PKAssembly.h @@ -0,0 +1,86 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/*! + @class PKAssembly + @brief An Abstract class. A PKAssembly maintains a stream of language elements along with stack and target objects. + @details

Parsers use assemblers to record progress at recognizing language elements from assembly's string.

+

Note that PKAssembly is an abstract class and may not be instantiated directly. Subclasses include PKTokenAssembly and PKCharAssembly.

+*/ +@interface PKAssembly : NSObject { + NSMutableArray *stack; + id target; + NSUInteger index; + NSString *string; + NSString *defaultDelimiter; +} + +/*! + @brief Convenience factory method for initializing an autoreleased assembly. + @param s string to be worked on + @result an initialized autoreleased assembly +*/ ++ (id)assemblyWithString:(NSString *)s; + +/*! + @brief Designated Initializer. Initializes an assembly with a given string. + @details Designated Initializer. + @param s string to be worked on + @result an initialized assembly +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief Removes the object at the top of this assembly's stack and returns it. + @details Note this returns an object from this assembly's stack, not from its stream of elements (tokens or chars depending on the type of concrete PKAssembly subclass of this object). + @result the object at the top of this assembly's stack +*/ +- (id)pop; + +/*! + @brief Pushes an object onto the top of this assembly's stack. + @param object object to push +*/ +- (void)push:(id)object; + +/*! + @brief Returns true if this assembly's stack is empty. + @result true, if this assembly's stack is empty +*/ +- (BOOL)isStackEmpty; + +/*! + @brief Returns a vector of the elements on this assembly's stack that appear before a specified fence. + @details

Returns a vector of the elements on this assembly's stack that appear before a specified fence.

+

Sometimes a parser will recognize a list from within a pair of parentheses or brackets. The parser can mark the beginning of the list with a fence, and then retrieve all the items that come after the fence with this method.

+ @param fence object that indicates the limit of elements returned from this assembly's stack + @result Array of the elements above the specified fence +*/ +- (NSArray *)objectsAbove:(id)fence; + +/*! + @property stack + @brief This assembly's stack. +*/ +@property (nonatomic, readonly, retain) NSMutableArray *stack; + +/*! + @property target + @brief This assembly's target. + @details The object identified as this assembly's "target". Clients can set and retrieve a target, which can be a convenient supplement as a place to work, in addition to the assembly's stack. For example, a parser for an HTML file might use a web page object as its "target". As the parser recognizes markup commands like <head>, it could apply its findings to the target. +*/ +@property (nonatomic, retain) id target; +@end diff --git a/include/ParseKit/PKCaseInsensitiveLiteral.h b/include/ParseKit/PKCaseInsensitiveLiteral.h new file mode 100644 index 0000000..f621b3a --- /dev/null +++ b/include/ParseKit/PKCaseInsensitiveLiteral.h @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKCaseInsensitiveLiteral + @brief A PKCaselessLiteral matches a specified NSString from an assembly, disregarding case. +*/ +@interface PKCaseInsensitiveLiteral : PKLiteral { + +} + +@end diff --git a/include/ParseKit/PKChar.h b/include/ParseKit/PKChar.h new file mode 100644 index 0000000..fd48647 --- /dev/null +++ b/include/ParseKit/PKChar.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/*! + @class PKChar + @brief A PKChar matches a character from a character assembly. + @details -[PKChar qualifies:] returns true every time, since this class assumes it is working against a PKCharacterAssembly. +*/ +@interface PKChar : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKChar parser. + @result an initialized autoreleased PKChar parser. +*/ ++ (id)char; +@end diff --git a/include/ParseKit/PKCharacterAssembly.h b/include/ParseKit/PKCharacterAssembly.h new file mode 100644 index 0000000..e34c9cb --- /dev/null +++ b/include/ParseKit/PKCharacterAssembly.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/*! + @class PKCharacterAssembly + @brief A PKCharacterAssembly is a PKAssembly whose elements are characters. +*/ +@interface PKCharacterAssembly : PKAssembly { + +} + +@end diff --git a/include/ParseKit/PKCollectionParser.h b/include/ParseKit/PKCollectionParser.h new file mode 100644 index 0000000..488fd93 --- /dev/null +++ b/include/ParseKit/PKCollectionParser.h @@ -0,0 +1,44 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKCollectionParser + @brief An Abstract class. This class abstracts the behavior common to parsers that consist of a series of other parsers. +*/ +@interface PKCollectionParser : PKParser { + NSMutableArray *subparsers; +} + +/*! + @brief Designated Initializer. Initialize an instance of a PKCollectionParser subclass. + @param p1, ... A comma-separated list of parser objects ending with nil + @result an initialized instance of a PKCollectionParser subclass. +*/ +- (id)initWithSubparsers:(PKParser *)p1, ...; + +/*! + @brief Adds a parser to the collection. + @param p parser to add +*/ +- (void)add:(PKParser *)p; + +/*! + @property subparsers + @brief This parser's subparsers. +*/ +@property (nonatomic, readonly, retain) NSMutableArray *subparsers; +@end diff --git a/include/ParseKit/PKComment.h b/include/ParseKit/PKComment.h new file mode 100644 index 0000000..4763e04 --- /dev/null +++ b/include/ParseKit/PKComment.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKComment + @brief A PKComment matches a comment from a token assembly. +*/ +@interface PKComment : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKComment object. + @result an initialized autoreleased PKComment object +*/ ++ (id)comment; +@end diff --git a/include/ParseKit/PKCommentState.h b/include/ParseKit/PKCommentState.h new file mode 100644 index 0000000..b7c49ca --- /dev/null +++ b/include/ParseKit/PKCommentState.h @@ -0,0 +1,77 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class PKSymbolRootNode; +@class PKSingleLineCommentState; +@class PKMultiLineCommentState; + +/*! + @class PKCommentState + @brief This state will either delegate to a comment-handling state, or return a PKSymbol token with just the first char in it. + @details By default, C and C++ style comments. (// to end of line and /&0x002A; &0x002A;/) +*/ +@interface PKCommentState : PKTokenizerState { + PKSymbolRootNode *rootNode; + PKSingleLineCommentState *singleLineState; + PKMultiLineCommentState *multiLineState; + BOOL reportsCommentTokens; + BOOL balancesEOFTerminatedComments; +} + +/*! + @brief Adds the given string as a single-line comment start marker. may be multi-char. + @details single line comments begin with start and continue until the next new line character. e.g. C-style comments (// comment text) + @param start a single- or multi-character marker that should be recognized as the start of a single-line comment +*/ +- (void)addSingleLineStartMarker:(NSString *)start; + +/*! + @brief Removes the given string as a single-line comment start marker. may be multi-char. + @details If start was never added as a single-line comment start marker, this has no effect. + @param start a single- or multi-character marker that should no longer be recognized as the start of a single-line comment +*/ +- (void)removeSingleLineStartMarker:(NSString *)start; + +/*! + @brief Adds the given strings as a multi-line comment start and end markers. both may be multi-char + @details start and end may be different strings. e.g. /&0x002A; and &0x002A;/. Also, the actual comment may or may not be multi-line. + @param start a single- or multi-character marker that should be recognized as the start of a multi-line comment + @param end a single- or multi-character marker that should be recognized as the end of a multi-line comment that began with start +*/ +- (void)addMultiLineStartMarker:(NSString *)start endMarker:(NSString *)end; + +/*! + @brief Removes start and its orignal end counterpart as a multi-line comment start and end markers. + @details If start was never added as a multi-line comment start marker, this has no effect. + @param start a single- or multi-character marker that should no longer be recognized as the start of a multi-line comment +*/ +- (void)removeMultiLineStartMarker:(NSString *)start; + +/*! + @property reportsCommentTokens + @brief if true, the tokenizer associated with this state will report comment tokens, otherwise it silently consumes comments + @details if true, this state will return PKTokens of type PKTokenTypeComment. + Otherwise, it will silently consume comment text and return the next token from another of the tokenizer's states +*/ +@property (nonatomic) BOOL reportsCommentTokens; + +/*! + @property balancesEOFTerminatedComments + @brief if true, this state will append a matching comment string (&0x002A;/ [C++] or :) [XQuery]) to quotes terminated by EOF. Default is NO. +*/ +@property (nonatomic) BOOL balancesEOFTerminatedComments; +@end diff --git a/include/ParseKit/PKDelimitState.h b/include/ParseKit/PKDelimitState.h new file mode 100644 index 0000000..212053f --- /dev/null +++ b/include/ParseKit/PKDelimitState.h @@ -0,0 +1,57 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKSymbolRootNode; + +/*! + @class PKDelimitState + @brief A delimit state returns a delimited string token from a reader + @details This state will collect characters until it sees a match to the end marker that corresponds to the start marker the tokenizer used to switch to this state. +*/ +@interface PKDelimitState : PKTokenizerState { + PKSymbolRootNode *rootNode; + BOOL balancesEOFTerminatedStrings; + BOOL allowsUnbalancedStrings; + + NSMutableArray *startMarkers; + NSMutableArray *endMarkers; + NSMutableArray *characterSets; +} + +/*! + @brief Adds the given strings as a delimited string start and end markers. both may be multi-char + @details start and end may be different strings. e.g. <# and #>. + @param start a single- or multi-character marker that should be recognized as the start of a multi-line comment + @param end a single- or multi-character marker that should be recognized as the end of a multi-line comment that began with start + @param set of characters allowed to appear within the delimited string or nil to allow any non-newline characters +*/ +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end allowedCharacterSet:(NSCharacterSet *)set; + +/*! + @brief Removes start and its orignal end counterpart as a delimited string start and end markers. + @details If start was never added as a delimited string start marker, this has no effect. + @param start a single- or multi-character marker that should no longer be recognized as the start of a delimited string +*/ +- (void)removeStartMarker:(NSString *)start; + +/*! + @property balancesEOFTerminatedStrings + @brief if true, this state will append a matching end delimiter marker (e.g. --> or %>) to strings terminated by EOF. Default is NO. +*/ +@property (nonatomic) BOOL balancesEOFTerminatedStrings; + +@property (nonatomic) BOOL allowsUnbalancedStrings; +@end diff --git a/include/ParseKit/PKDelimitedString.h b/include/ParseKit/PKDelimitedString.h new file mode 100644 index 0000000..6830c22 --- /dev/null +++ b/include/ParseKit/PKDelimitedString.h @@ -0,0 +1,36 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKDelimitedString + @brief A PKDelimitedString matches a delimited string from a token assembly. +*/ +@interface PKDelimitedString : PKTerminal { + NSString *startMarker; + NSString *endMarker; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKDelimitedString object. + @result an initialized autoreleased PKDelimitedString object +*/ ++ (id)delimitedString; + ++ (id)delimitedStringWithStartMarker:(NSString *)start; + ++ (id)delimitedStringWithStartMarker:(NSString *)start endMarker:(NSString *)end; +@end diff --git a/include/ParseKit/PKDifference.h b/include/ParseKit/PKDifference.h new file mode 100644 index 0000000..2be9547 --- /dev/null +++ b/include/ParseKit/PKDifference.h @@ -0,0 +1,63 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKDifference + @brief A PKDifference matches anything its subparser would match except for anything its minus parser would match. + @details The example below would match any Word token except for true or false. + +@code + PKParser *trueParser = [PKLiteral literalWithString:@"true"]; + PKParser *falseParser = [PKLiteral literalWithString:@"false"]; + PKAlternation *reservedWords = [PKAlternation alternationWithSubparsers:trueParser, falseParser, nil]; + + PKDifference *diff = [PKDifference differenceWithSubparser:[PKWord word] minus:reservedWords]; +@endcode +*/ +@interface PKDifference : PKParser { + PKParser *subparser; + PKParser *minus; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKDifference parser. + @param subparser the parser this parser uses for matching + @param minus the parser whose matches will be exluded + @result an initialized autoreleased PKDifference parser. +*/ ++ (id)differenceWithSubparser:(PKParser *)s minus:(PKParser *)m; + +/*! + @brief Designated initializer + @param subparser the parser this parser uses for matching + @param minus the parser whose matches will be exluded + @result an initialized PKDifference parser. +*/ +- (id)initWithSubparser:(PKParser *)s minus:(PKParser *)m; + +/*! + @property subparser + @brief this parser's subparser which it will initially match against +*/ +@property (nonatomic, retain, readonly) PKParser *subparser; + +/*! + @property minus + @brief after a successful match against subparser, matches against minus will not be matched by this parser +*/ +@property (nonatomic, retain, readonly) PKParser *minus; +@end diff --git a/include/ParseKit/PKDigit.h b/include/ParseKit/PKDigit.h new file mode 100644 index 0000000..e981fa9 --- /dev/null +++ b/include/ParseKit/PKDigit.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/*! + @class PKDigit + @brief A PKDigit matches a digit from a character assembly. + @details -[PKDitgit qualifies:] returns true if an assembly's next element is a digit. +*/ +@interface PKDigit : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKDigit parser. + @result an initialized autoreleased PKDigit parser. +*/ ++ (id)digit; +@end diff --git a/include/ParseKit/PKEmpty.h b/include/ParseKit/PKEmpty.h new file mode 100644 index 0000000..d615c05 --- /dev/null +++ b/include/ParseKit/PKEmpty.h @@ -0,0 +1,32 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKEmpty + @brief A PKEmpty parser matches any assembly once, and applies its assembler that one time. + @details

Language elements often contain empty parts. For example, a language may at some point allow a list of parameters in parentheses, and may allow an empty list. An empty parser makes it easy to match, within the parenthesis, either a list of parameters or "empty".

+*/ +@interface PKEmpty : PKParser { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKEmpty parser. + @result an initialized autoreleased PKEmpty parser. +*/ ++ (id)empty; +@end diff --git a/include/ParseKit/PKIntersection.h b/include/ParseKit/PKIntersection.h new file mode 100644 index 0000000..6eac3a5 --- /dev/null +++ b/include/ParseKit/PKIntersection.h @@ -0,0 +1,41 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKIntersection + @brief A PKIntersection matches input that matches all of its subparsers. It is basically a representation of "Logical And" or "&". + @details The example below would match any token which is both a word and matches the given regular expression pattern. + Using a PKIntersection in this case would improve performance over using just a PKPattern parser as the regular expression would be evaluated fewer times. + +@code + PKParser *pattern = [PKPattern patternWithString:@"_.+"]; + + PKIntersection *wordStartingWithUnderscore = [PKIntersection intersectionWithSubparsers:[PKWord word], pattern, nil]; +@endcode +*/ +@interface PKIntersection : PKCollectionParser { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKIntersection parser. + @result an initialized autoreleased PKIntersection parser. +*/ ++ (id)intersection; + ++ (id)intersectionWithSubparsers:(PKParser *)p1, ...; +@end diff --git a/include/ParseKit/PKLetter.h b/include/ParseKit/PKLetter.h new file mode 100644 index 0000000..596e1e1 --- /dev/null +++ b/include/ParseKit/PKLetter.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/*! + @class PKLetter + @brief A PKLetter matches any letter from a character assembly. + @details -[PKLetter qualifies:] returns true if an assembly's next element is a letter. +*/ +@interface PKLetter : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKLetter parser. + @result an initialized autoreleased PKLetter parser. +*/ ++ (id)letter; +@end diff --git a/include/ParseKit/PKLiteral.h b/include/ParseKit/PKLiteral.h new file mode 100644 index 0000000..ae297b4 --- /dev/null +++ b/include/ParseKit/PKLiteral.h @@ -0,0 +1,34 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class PKToken; + +/*! + @class PKLiteral + @brief A PKLiteral matches a specific word from an assembly. +*/ +@interface PKLiteral : PKTerminal { + PKToken *literal; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKLiteral object with a given string. + @param s the word represented by this literal + @result an initialized autoreleased PKLiteral object representing s +*/ ++ (id)literalWithString:(NSString *)s; +@end diff --git a/include/ParseKit/PKLowercaseWord.h b/include/ParseKit/PKLowercaseWord.h new file mode 100644 index 0000000..59c91cc --- /dev/null +++ b/include/ParseKit/PKLowercaseWord.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKLowercaseWord : PKWord { + +} + +@end diff --git a/include/ParseKit/PKMultiLineCommentState.h b/include/ParseKit/PKMultiLineCommentState.h new file mode 100644 index 0000000..053f93b --- /dev/null +++ b/include/ParseKit/PKMultiLineCommentState.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKMultiLineCommentState : PKTokenizerState { + NSMutableArray *startMarkers; + NSMutableArray *endMarkers; + NSString *currentStartMarker; +} + +@end diff --git a/include/ParseKit/PKNegation.h b/include/ParseKit/PKNegation.h new file mode 100644 index 0000000..b81f70c --- /dev/null +++ b/include/ParseKit/PKNegation.h @@ -0,0 +1,52 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/*! + @class PKNegation + @brief A PKNegation negates the matching logic of its subparser. It matches anything its subparser would not. + @details The example below would match any token except for a ?> symbol token. This could be useful for matching all tokens until an end marker (in this case a PHP end marker) is found. + +@code + PKParser *question = [PKSymbol symbolWithString:@"?>"]; + + PKNegation *n = [PKNegation negationWithSubparser:question]; +@endcode +*/ +@interface PKNegation : PKParser { + PKParser *subparser; + PKParser *difference; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKNegation parser. + @param subparser the parser whose matching logic is negated + @result an initialized autoreleased PKNegation parser. +*/ ++ (id)negationWithSubparser:(PKParser *)s; + +/*! + @brief Designated initializer + @param subparser the parser whose matching logic is negated + @result an initialized PKNegation parser. +*/ +- (id)initWithSubparser:(PKParser *)s; + +/*! + @property subparser + @brief this parser's subparser whose matching logic is negated +*/ +@property (nonatomic, retain, readonly) PKParser *subparser; +@end diff --git a/include/ParseKit/PKNumber.h b/include/ParseKit/PKNumber.h new file mode 100644 index 0000000..6aefc73 --- /dev/null +++ b/include/ParseKit/PKNumber.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKNumber + @brief A PKNumber matches a number from a token assembly. +*/ +@interface PKNumber : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKNumber object. + @result an initialized autoreleased PKNumber object +*/ ++ (id)number; +@end diff --git a/include/ParseKit/PKNumberState.h b/include/ParseKit/PKNumberState.h new file mode 100644 index 0000000..eba4a3b --- /dev/null +++ b/include/ParseKit/PKNumberState.h @@ -0,0 +1,71 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKNumberState + @brief A number state returns a number from a reader. + @details This state's idea of a number allows an optional, initial minus sign, followed by one or more digits. A decimal point and another string of digits may follow these digits. + If allowsScientificNotation is YES (default is NO) this state allows 'e' or 'E' followed by an (optionally explicityly positive or negative) integer to represent 10 to the indicated power. For example, this state will recognize 1e2 as equaling 100.

+*/ +@interface PKNumberState : PKTokenizerState { + BOOL allowsTrailingDot; + BOOL allowsScientificNotation; + BOOL allowsOctalNotation; + BOOL allowsHexadecimalNotation; + BOOL isDecimal; + BOOL isFraction; + BOOL isNegative; + BOOL isHex; + BOOL gotADigit; + NSUInteger len; + CGFloat base; + PKUniChar originalCin; + PKUniChar firstNum; + PKUniChar c; + CGFloat floatValue; + CGFloat exp; + BOOL isNegativeExp; +} + +/*! + @property allowsTrailingDot + @brief If YES, numbers are allowed to end with a trialing dot, e.g. 42. + @details default is NO +*/ +@property (nonatomic) BOOL allowsTrailingDot; + +/*! + @property allowsScientificNotation + @brief If YES, supports exponential numbers like 42.0e2, 2E+6, or 5.1e-6 + @details default is NO +*/ +@property (nonatomic) BOOL allowsScientificNotation; + +/*! + @property allowsOctalNotation + @brief If YES, supports octal numbers like 020 (16), or 0102 (66) + @details default is NO +*/ +@property (nonatomic) BOOL allowsOctalNotation; + +/*! + @property allowsHexidecimalNotation + @brief If YES, supports hex numbers like 0x20 (32), or 0xB7 (183) + @details default is NO +*/ +@property (nonatomic) BOOL allowsHexadecimalNotation; +@end diff --git a/include/ParseKit/PKParser.h b/include/ParseKit/PKParser.h new file mode 100644 index 0000000..5d70478 --- /dev/null +++ b/include/ParseKit/PKParser.h @@ -0,0 +1,173 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKAssembly; +@class PKTokenizer; + +/*! + @class PKParser + @brief An Abstract class. A PKParser is an object that recognizes the elements of a language. + @details

Each PKParser object is either a PKTerminal or a composition of other parsers. The PKTerminal class is a subclass of Parser, and is itself a hierarchy of parsers that recognize specific patterns of text. For example, a PKWord recognizes any word, and a PKLiteral matches a specific string.

+

In addition to PKTerminal, other subclasses of PKParser provide composite parsers, describing sequences, alternations, and repetitions of other parsers. For example, the following PKParser objects culminate in a good parser that recognizes a description of good coffee.

+@code + PKAlternation *adjective = [PKAlternation alternation]; + [adjective add:[PKLiteral literalWithString:@"steaming"]]; + [adjective add:[PKLiteral literalWithString:@"hot"]]; + PKSequence *good = [PKSequence sequence]; + [good add:[PKRepetition repetitionWithSubparser:adjective]]; + [good add:[PKLiteral literalWithString:@"coffee"]]; + NSString *s = @"hot hot steaming hot coffee"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + NSLog([good bestMatchFor:a]); +@endcode +

This prints out:

+@code + [hot, hot, steaming, hot, coffee] + hot/hot/steaming/hot/coffee^ +@endcode +

The parser does not match directly against a string, it matches against a PKAssembly. The resulting assembly shows its stack, with four words on it, along with its sequence of tokens, and the index at the end of these. In practice, parsers will do some work on an assembly, based on the text they recognize.

+*/ +@interface PKParser : NSObject { +#ifdef TARGET_OS_SNOW_LEOPARD + void (^assemblerBlock)(PKAssembly *); + void (^preassemblerBlock)(PKAssembly *); +#endif + id assembler; + SEL assemblerSelector; + id preassembler; + SEL preassemblerSelector; + NSString *name; + PKTokenizer *tokenizer; // PKParserFactoryAdditions ivar +} + +/*! + @brief Convenience factory method for initializing an autoreleased parser. + @result an initialized autoreleased parser. +*/ ++ (id)parser; + +/*! + @brief Sets the object and method that will work on an assembly whenever this parser successfully matches against the assembly. + @details The method represented by sel must accept a single PKAssembly argument. The signature of sel should be similar to: - (void)didMatchAssembly:(PKAssembly *)a. + @param a the assembler this parser will use to work on an assembly + @param sel a selector that assembler a responds to which will work on an assembly +*/ +- (void)setAssembler:(id)a selector:(SEL)sel; + +/*! + @brief Sets the object that will work on every assembly before matching against it. + @details Setting a preassembler is entirely optional, but sometimes useful for repetition parsers to do work on an assembly before matching against it. + @param a the assembler this parser will use to work on an assembly before matching against it. + @param sel a selector that assembler a responds to which will work on an assembly +*/ +- (void)setPreassembler:(id)a selector:(SEL)sel; + +/*! + @brief Returns the most-matched assembly in a collection. + @param inAssembly the assembly for which to find the best match + @result an assembly with the greatest possible number of elements consumed by this parser +*/ +- (PKAssembly *)bestMatchFor:(PKAssembly *)inAssembly; + +/*! + @brief Returns either nil, or a completely matched version of the supplied assembly. + @param inAssembly the assembly for which to find the complete match + @result either nil, or a completely matched version of the supplied assembly +*/ +- (PKAssembly *)completeMatchFor:(PKAssembly *)inAssembly; + +/*! + @brief Given a set of assemblies, this method matches this parser against all of them, and returns a new set of the assemblies that result from the matches. + @details

Given a set of assemblies, this method matches this parser against all of them, and returns a new set of the assemblies that result from the matches.

+

For example, consider matching the regular expression a* against the string aaab. The initial set of states is {^aaab}, where the ^ indicates how far along the assembly is. When a* matches against this initial state, it creates a new set {^aaab, a^aab, aa^ab, aaa^b}.

+ @param inAssemblies set of assemblies to match against + @result a set of assemblies that result from matching against a beginning set of assemblies +*/ +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; + +/*! + @brief Find a parser with the given name + @details Performs a depth-first recursive search (starting with this parser) for a parser or subparser with the given name. If this parser's name is name, it will be returned. + @param name of the parser to be found + @result the parser with the given name or nil if not found + */ +- (PKParser *)parserNamed:(NSString *)name; + +#ifdef TARGET_OS_SNOW_LEOPARD +/*! + @property assemblerBlock + @brief Set a block which should be executed after this parser is matched + @details

This is an alternative to calling -setAssembler:selector:.

+

Passing a block to this method will cause this parser to execute the given block after it is matched (rather than sending assembler the assemblerSelector message.

+

Using a block as the assembler will sometimes be more convient than setting an assembler object.

+ @param block of code to be executed after a parser is matched. +*/ +@property (nonatomic, retain) void (^assemblerBlock)(PKAssembly *); + +/*! + @property preassemblerBlock + @brief Set a block which should be executed before this parser is matched + @details

This is an alternative to calling -setPreassembler:selector:.

+

Passing a block to this method will cause this parser to execute the given block before it is matched (rather than sending preassembler the preassemblerSelector message.

+

Using a block as the preassembler will sometimes be more convient than setting an preassembler object.

+ @param block of code to be executed before a parser is matched. + */ +@property (nonatomic, retain) void (^preassemblerBlock)(PKAssembly *); +#endif + +/*! + @property assembler + @brief The assembler this parser will use to work on a matched assembly. + @details assembler should respond to the selector held by this parser's selector property. +*/ +@property (nonatomic, assign) id assembler; + +/*! + @property assemblerSelector + @brief The method of assembler this parser will call to work on a matched assembly. + @details The method represented by assemblerSelector must accept a single PKAssembly argument. The signature of assemblerSelector should be similar to: - (void)didMatchFoo:(PKAssembly *)a. +*/ +@property (nonatomic, assign) SEL assemblerSelector; + +/*! + @property preassembler + @brief The assembler this parser will use to work on an assembly before matching against it. + @discussion preassembler should respond to the selector held by this parser's preassemblerSelector property. +*/ +@property (nonatomic, assign) id preassembler; + +/*! + @property preAssemlerSelector + @brief The method of preassembler this parser will call to work on an assembly. + @details The method represented by preassemblerSelector must accept a single PKAssembly argument. The signature of preassemblerSelector should be similar to: - (void)didMatchAssembly:(PKAssembly *)a. +*/ +@property (nonatomic, assign) SEL preassemblerSelector; + +/*! + @property name + @brief The name of this parser. + @discussion Use this property to help in identifying a parser or for debugging purposes. +*/ +@property (nonatomic, copy) NSString *name; +@end + +@interface PKParser (PKParserFactoryAdditions) + +- (id)parse:(NSString *)s; + +- (PKTokenizer *)tokenizer; +@end + diff --git a/include/ParseKit/PKParserFactory.h b/include/ParseKit/PKParserFactory.h new file mode 100644 index 0000000..8024df6 --- /dev/null +++ b/include/ParseKit/PKParserFactory.h @@ -0,0 +1,47 @@ +// +// PKParserFactory.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf All rights reserved. +// + +#import + +@class PKGrammarParser; +@class PKToken; +@class PKTokenizer; +@class PKParser; +@class PKCollectionParser; + +void PKReleaseSubparserTree(PKParser *p); + +typedef enum { + PKParserFactoryAssemblerSettingBehaviorOnAll = 1 << 1, // Default + PKParserFactoryAssemblerSettingBehaviorOnTerminals = 1 << 2, + PKParserFactoryAssemblerSettingBehaviorOnExplicit = 1 << 3, + PKParserFactoryAssemblerSettingBehaviorOnNone = 1 << 4 +} PKParserFactoryAssemblerSettingBehavior; + +@interface PKParserFactory : NSObject { + PKParserFactoryAssemblerSettingBehavior assemblerSettingBehavior; + PKGrammarParser *grammarParser; + id assembler; + id preassembler; + NSMutableDictionary *parserTokensTable; + NSMutableDictionary *parserClassTable; + NSMutableDictionary *selectorTable; + PKToken *equals; + PKToken *curly; + PKToken *paren; + BOOL isGatheringClasses; +} ++ (id)factory; + +- (PKParser *)parserFromGrammar:(NSString *)s assembler:(id)a; +- (PKParser *)parserFromGrammar:(NSString *)s assembler:(id)a preassembler:(id)pa; + +- (PKCollectionParser *)exprParser; + +@property (nonatomic) PKParserFactoryAssemblerSettingBehavior assemblerSettingBehavior; +@end diff --git a/include/ParseKit/PKPattern.h b/include/ParseKit/PKPattern.h new file mode 100644 index 0000000..8511ff7 --- /dev/null +++ b/include/ParseKit/PKPattern.h @@ -0,0 +1,38 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import + +typedef enum { + PKPatternOptionsNone = 0, + PKPatternOptionsIgnoreCase = 2, + PKPatternOptionsComments = 4, + PKPatternOptionsMultiline = 8, + PKPatternOptionsDotAll = 32, + PKPatternOptionsUnicodeWordBoundaries = 256 +} PKPatternOptions; + +@interface PKPattern : PKTerminal { + PKPatternOptions options; +} ++ (id)patternWithString:(NSString *)s; + ++ (id)patternWithString:(NSString *)s options:(PKPatternOptions)opts; + +- (id)initWithString:(NSString *)s; + +- (id)initWithString:(NSString *)s options:(PKPatternOptions)opts; +@end diff --git a/include/ParseKit/PKQuoteState.h b/include/ParseKit/PKQuoteState.h new file mode 100644 index 0000000..580f835 --- /dev/null +++ b/include/ParseKit/PKQuoteState.h @@ -0,0 +1,32 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKQuoteState + @brief A quote state returns a quoted string token from a reader + @details This state will collect characters until it sees a match to the character that the tokenizer used to switch to this state. For example, if a tokenizer uses a double- quote character to enter this state, then -nextToken will search for another double-quote until it finds one or finds the end of the reader. +*/ +@interface PKQuoteState : PKTokenizerState { + BOOL balancesEOFTerminatedQuotes; +} + +/*! + @property balancesEOFTerminatedQuotes + @brief if true, this state will append a matching quote char (' or ") to strings terminated by EOF. Default is NO. +*/ +@property (nonatomic) BOOL balancesEOFTerminatedQuotes; +@end diff --git a/include/ParseKit/PKQuotedString.h b/include/ParseKit/PKQuotedString.h new file mode 100644 index 0000000..e1d1f4d --- /dev/null +++ b/include/ParseKit/PKQuotedString.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKQuotedString + @brief A PKQuotedString matches a quoted string, like "this one" from a token assembly. +*/ +@interface PKQuotedString : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKQuotedString object. + @result an initialized autoreleased PKQuotedString object +*/ ++ (id)quotedString; +@end diff --git a/include/ParseKit/PKReader.h b/include/ParseKit/PKReader.h new file mode 100644 index 0000000..cf9b9d1 --- /dev/null +++ b/include/ParseKit/PKReader.h @@ -0,0 +1,66 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKReader + @brief A character-stream reader that allows characters to be pushed back into the stream. +*/ +@interface PKReader : NSObject { + NSString *string; + NSUInteger offset; + NSUInteger length; +} + +/*! + @brief Designated Initializer. Initializes a reader with a given string. + @details Designated Initializer. + @param s string from which to read + @result an initialized reader +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief Read a single UTF-16 unicode character + @result The character read, or PKEOF (-1) if the end of the stream has been reached +*/ +- (PKUniChar)read; + +/*! + @brief Push back a single character + @details moves the offset back one position +*/ +- (void)unread; + +/*! + @brief Push back count characters + @param count of characters to push back + @details moves the offset back count positions +*/ +- (void)unread:(NSUInteger)count; + +/*! + @property string + @brief This reader's string. +*/ +@property (nonatomic, copy) NSString *string; + +/*! + @property offset + @brief This reader's current offset in string +*/ +@property (nonatomic, readonly) NSUInteger offset; +@end diff --git a/include/ParseKit/PKRepetition.h b/include/ParseKit/PKRepetition.h new file mode 100644 index 0000000..275f8ef --- /dev/null +++ b/include/ParseKit/PKRepetition.h @@ -0,0 +1,46 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKRepetition + @brief A PKRepetition matches its underlying parser repeatedly against a assembly. +*/ +@interface PKRepetition : PKParser { + PKParser *subparser; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKRepetition parser to repeatedly match against subparser p. + @param p the subparser against wich to repeatedly match + @result an initialized autoreleased PKRepetition parser. +*/ ++ (id)repetitionWithSubparser:(PKParser *)p; + +/*! + @brief Designated Initializer. Initialize a PKRepetition parser to repeatedly match against subparser p. + @details Designated Initializer. Initialize a PKRepetition parser to repeatedly match against subparser p. + @param p the subparser against wich to repeatedly match + @result an initialized PKRepetition parser. +*/ +- (id)initWithSubparser:(PKParser *)p; + +/*! + @property subparser + @brief this parser's subparser against which it repeatedly matches +*/ +@property (nonatomic, readonly, retain) PKParser *subparser; +@end diff --git a/include/ParseKit/PKSequence.h b/include/ParseKit/PKSequence.h new file mode 100644 index 0000000..1eb199e --- /dev/null +++ b/include/ParseKit/PKSequence.h @@ -0,0 +1,33 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKSequence + @brief A PKSequence object is a collection of parsers, all of which must in turn match against an assembly for this parser to successfully match. +*/ +@interface PKSequence : PKCollectionParser { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKSequence parser. + @result an initialized autoreleased PKSequence parser. +*/ ++ (id)sequence; + ++ (id)sequenceWithSubparsers:(PKParser *)p1, ...; +@end diff --git a/include/ParseKit/PKSingleLineCommentState.h b/include/ParseKit/PKSingleLineCommentState.h new file mode 100644 index 0000000..bd71c73 --- /dev/null +++ b/include/ParseKit/PKSingleLineCommentState.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKSingleLineCommentState : PKTokenizerState { + NSMutableArray *startMarkers; + NSString *currentStartMarker; +} + +@end diff --git a/include/ParseKit/PKSpecificChar.h b/include/ParseKit/PKSpecificChar.h new file mode 100644 index 0000000..22219ce --- /dev/null +++ b/include/ParseKit/PKSpecificChar.h @@ -0,0 +1,40 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKSpecificChar + @brief A PKSpecificChar matches a specified character from a character assembly. + @details -[PKSpecificChar qualifies:] returns true if an assembly's next element is equal to the character this object was constructed with. +*/ +@interface PKSpecificChar : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKSpecificChar parser. + @param c the character this object should match + @result an initialized autoreleased PKSpecificChar parser. +*/ ++ (id)specificCharWithChar:(PKUniChar)c; + +/*! + @brief Designated Initializer. Initializes a PKSpecificChar parser. + @param c the character this object should match + @result an initialized PKSpecificChar parser. +*/ +- (id)initWithSpecificChar:(PKUniChar)c; +@end diff --git a/include/ParseKit/PKSymbol.h b/include/ParseKit/PKSymbol.h new file mode 100644 index 0000000..32c0819 --- /dev/null +++ b/include/ParseKit/PKSymbol.h @@ -0,0 +1,40 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class PKToken; + +/*! + @class PKSymbol + @brief A PKSymbol matches a specific sequence, such as <, or <= that a tokenizer returns as a symbol. +*/ +@interface PKSymbol : PKTerminal { + PKToken *symbol; +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKSymbol object with a nil string value. + @result an initialized autoreleased PKSymbol object with a nil string value +*/ ++ (id)symbol; + +/*! + @brief Convenience factory method for initializing an autoreleased PKSymbol object with s as a string value. + @param s the string represented by this symbol + @result an initialized autoreleased PKSymbol object with s as a string value +*/ ++ (id)symbolWithString:(NSString *)s; +@end diff --git a/include/ParseKit/PKSymbolNode.h b/include/ParseKit/PKSymbolNode.h new file mode 100644 index 0000000..a0f0b2d --- /dev/null +++ b/include/ParseKit/PKSymbolNode.h @@ -0,0 +1,44 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKSymbolNode + @brief A PKSymbolNode object is a member of a tree that contains all possible prefixes of allowable symbols. + @details A PKSymbolNode object is a member of a tree that contains all possible prefixes of allowable symbols. Multi-character symbols appear in a PKSymbolNode tree with one node for each character. For example, the symbol =:~ will appear in a tree as three nodes. The first node contains an equals sign, and has a child; that child contains a colon and has a child; this third child contains a tilde, and has no children of its own. If the colon node had another child for a dollar sign character, then the tree would contain the symbol =:$. A tree of PKSymbolNode objects collaborate to read a (potentially multi-character) symbol from an input stream. A root node with no character of its own finds an initial node that represents the first character in the input. This node looks to see if the next character in the stream matches one of its children. If so, the node delegates its reading task to its child. This approach walks down the tree, pulling symbols from the input that match the path down the tree. When a node does not have a child that matches the next character, we will have read the longest possible symbol prefix. This prefix may or may not be a valid symbol. Consider a tree that has had =:~ added and has not had =: added. In this tree, of the three nodes that contain =:~, only the first and third contain complete symbols. If, say, the input contains =:a, the colon node will not have a child that matches the 'a' and so it will stop reading. The colon node has to "unread": it must push back its character, and ask its parent to unread. Unreading continues until it reaches an ancestor that represents a valid symbol. +*/ +@interface PKSymbolNode : NSObject { + NSString *ancestry; + PKSymbolNode *parent; + NSMutableDictionary *children; + PKUniChar character; + NSString *string; +} + +/*! + @brief Initializes a PKSymbolNode with the given parent, representing the given character. + @param p the parent of this node + @param c the character for this node + @result An initialized PKSymbolNode +*/ +- (id)initWithParent:(PKSymbolNode *)p character:(PKUniChar)c; + +/*! + @property ancestry + @brief The string of the mulit-character symbol this node represents. +*/ +@property (nonatomic, readonly, retain) NSString *ancestry; +@end diff --git a/include/ParseKit/PKSymbolRootNode.h b/include/ParseKit/PKSymbolRootNode.h new file mode 100644 index 0000000..d225e80 --- /dev/null +++ b/include/ParseKit/PKSymbolRootNode.h @@ -0,0 +1,48 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class PKReader; + +/*! + @class PKSymbolRootNode + @brief This class is a special case of a PKSymbolNode. + @details This class is a special case of a PKSymbolNode. A PKSymbolRootNode object has no symbol of its own, but has children that represent all possible symbols. +*/ +@interface PKSymbolRootNode : PKSymbolNode { +} + +/*! + @brief Adds the given string as a multi-character symbol. + @param s a multi-character symbol that should be recognized as a single symbol token by this state +*/ +- (void)add:(NSString *)s; + +/*! + @brief Removes the given string as a multi-character symbol. + @param s a multi-character symbol that should no longer be recognized as a single symbol token by this state + @details if s was never added as a multi-character symbol, this has no effect +*/ +- (void)remove:(NSString *)s; + +/*! + @brief Return a symbol string from a reader. + @param r the reader from which to read + @param cin the character from witch to start + @result a symbol string from a reader +*/ +- (NSString *)nextSymbol:(PKReader *)r startingWith:(PKUniChar)cin; +@end diff --git a/include/ParseKit/PKSymbolState.h b/include/ParseKit/PKSymbolState.h new file mode 100644 index 0000000..747be8c --- /dev/null +++ b/include/ParseKit/PKSymbolState.h @@ -0,0 +1,44 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class PKSymbolRootNode; + +/*! + @class PKSymbolState + @brief The idea of a symbol is a character that stands on its own, such as an ampersand or a parenthesis. + @details

The idea of a symbol is a character that stands on its own, such as an ampersand or a parenthesis. For example, when tokenizing the expression (isReady)& (isWilling) , a typical tokenizer would return 7 tokens, including one for each parenthesis and one for the ampersand. Thus a series of symbols such as )&( becomes three tokens, while a series of letters such as isReady becomes a single word token.

+

Multi-character symbols are an exception to the rule that a symbol is a standalone character. For example, a tokenizer may want less-than-or-equals to tokenize as a single token. This class provides a method for establishing which multi-character symbols an object of this class should treat as single symbols. This allows, for example, "cat <= dog" to tokenize as three tokens, rather than splitting the less-than and equals symbols into separate tokens.

+

By default, this state recognizes the following multi- character symbols: !=, :-, <=, >=

+*/ +@interface PKSymbolState : PKTokenizerState { + PKSymbolRootNode *rootNode; + NSMutableArray *addedSymbols; +} + +/*! + @brief Adds the given string as a multi-character symbol. + @param s a multi-character symbol that should be recognized as a single symbol token by this state +*/ +- (void)add:(NSString *)s; + +/*! + @brief Removes the given string as a multi-character symbol. + @details If s was never added as a multi-character symbol, this has no effect. + @param s a multi-character symbol that should no longer be recognized as a single symbol token by this state +*/ +- (void)remove:(NSString *)s; +@end diff --git a/include/ParseKit/PKTerminal.h b/include/ParseKit/PKTerminal.h new file mode 100644 index 0000000..cc4a6f5 --- /dev/null +++ b/include/ParseKit/PKTerminal.h @@ -0,0 +1,49 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class PKToken; + +/*! + @class PKTerminal + @brief An Abstract Class. A PKTerminal is a parser that is not a composition of other parsers. +*/ +@interface PKTerminal : PKParser { + NSString *string; + BOOL discardFlag; +} + +/*! + @brief Designated Initializer for all concrete PKTerminal subclasses. + @details Note this is an abtract class and this method must be called on a concrete subclass. + @param s the string matched by this parser + @result an initialized PKTerminal subclass object +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief By default, terminals push themselves upon a assembly's stack, after a successful match. This method will turn off that behavior. + @details This method returns this parser as a convenience for chainging-style usage. + @result this parser, returned for chaining/convenience +*/ +- (PKTerminal *)discard; + +/*! + @property string + @brief the string matched by this parser. +*/ +@property (nonatomic, readonly, copy) NSString *string; +@end diff --git a/include/ParseKit/PKToken.h b/include/ParseKit/PKToken.h new file mode 100644 index 0000000..a7851e4 --- /dev/null +++ b/include/ParseKit/PKToken.h @@ -0,0 +1,172 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/*! + @typedef enum PKTokenType + @brief Indicates the type of a PKToken + @var PKTokenTypeEOF A constant indicating that the endo fo the stream has been read. + @var PKTokenTypeNumber A constant indicating that a token is a number, like 3.14. + @var PKTokenTypeQuotedString A constant indicating that a token is a quoted string, like "Launch Mi". + @var PKTokenTypeSymbol A constant indicating that a token is a symbol, like "<=". + @var PKTokenTypeWord A constant indicating that a token is a word, like cat. + @var PKTokenTypeWhitespace A constant indicating that a token is whitespace, like \t. + @var PKTokenTypeComment A constant indicating that a token is a comment, like // this is a hack. + @var PKTokenTypeDelimtedString A constant indicating that a token is a delimitedString, like <#foo>. +*/ +typedef enum { + PKTokenTypeEOF, + PKTokenTypeNumber, + PKTokenTypeQuotedString, + PKTokenTypeSymbol, + PKTokenTypeWord, + PKTokenTypeWhitespace, + PKTokenTypeComment, + PKTokenTypeDelimitedString, + PKTokenTypeAny +} PKTokenType; + +/*! + @class PKToken + @brief A token represents a logical chunk of a string. + @details For example, a typical tokenizer would break the string "1.23 <= 12.3" into three tokens: the number 1.23, a less-than-or-equal symbol, and the number 12.3. A token is a receptacle, and relies on a tokenizer to decide precisely how to divide a string into tokens. +*/ +@interface PKToken : NSObject { + CGFloat floatValue; + NSString *stringValue; + PKTokenType tokenType; + + BOOL number; + BOOL quotedString; + BOOL symbol; + BOOL word; + BOOL whitespace; + BOOL comment; + BOOL delimitedString; + + id value; + NSUInteger offset; +} + +/*! + @brief Factory method for creating a singleton PKToken used to indicate that there are no more tokens. + @result A singleton used to indicate that there are no more tokens. +*/ ++ (PKToken *)EOFToken; + +/*! + @brief Factory convenience method for creating an autoreleased token. + @param t the type of this token. + @param s the string value of this token. + @param n the number falue of this token. + @result an autoreleased initialized token. +*/ ++ (id)tokenWithTokenType:(PKTokenType)t stringValue:(NSString *)s floatValue:(CGFloat)n; + +/*! + @brief Designated initializer. Constructs a token of the indicated type and associated string or numeric values. + @param t the type of this token. + @param s the string value of this token. + @param n the number falue of this token. + @result an autoreleased initialized token. +*/ +- (id)initWithTokenType:(PKTokenType)t stringValue:(NSString *)s floatValue:(CGFloat)n; + +/*! + @brief Returns true if the supplied object is an equivalent PKToken, ignoring differences in case. + @param obj the object to compare this token to. + @result true if obj is an equivalent PKToken, ignoring differences in case. +*/ +- (BOOL)isEqualIgnoringCase:(id)obj; + +/*! + @brief Returns more descriptive textual representation than -description which may be useful for debugging puposes only. + @details Usually of format similar to: <QuotedString "Launch Mi">, <Word cat>, or <Number 3.14> + @result A textual representation including more descriptive information than -description. +*/ +- (NSString *)debugDescription; + +/*! + @property number + @brief True if this token is a number. getter=isNumber +*/ +@property (nonatomic, readonly, getter=isNumber) BOOL number; + +/*! + @property quotedString + @brief True if this token is a quoted string. getter=isQuotedString +*/ +@property (nonatomic, readonly, getter=isQuotedString) BOOL quotedString; + +/*! + @property symbol + @brief True if this token is a symbol. getter=isSymbol +*/ +@property (nonatomic, readonly, getter=isSymbol) BOOL symbol; + +/*! + @property word + @brief True if this token is a word. getter=isWord +*/ +@property (nonatomic, readonly, getter=isWord) BOOL word; + +/*! + @property whitespace + @brief True if this token is whitespace. getter=isWhitespace +*/ +@property (nonatomic, readonly, getter=isWhitespace) BOOL whitespace; + +/*! + @property comment + @brief True if this token is a comment. getter=isComment +*/ +@property (nonatomic, readonly, getter=isComment) BOOL comment; + +/*! + @property delimitedString + @brief True if this token is a delimited string. getter=isDelimitedString +*/ +@property (nonatomic, readonly, getter=isDelimitedString) BOOL delimitedString; + +/*! + @property tokenType + @brief The type of this token. +*/ +@property (nonatomic, readonly) PKTokenType tokenType; + +/*! + @property floatValue + @brief The numeric value of this token. +*/ +@property (nonatomic, readonly) CGFloat floatValue; + +/*! + @property stringValue + @brief The string value of this token. +*/ +@property (nonatomic, readonly, copy) NSString *stringValue; + +/*! + @property value + @brief Returns an object that represents the value of this token. +*/ +@property (nonatomic, readonly, copy) id value; + +/*! + @property offset + @brief The character offset of this token in the original source string. +*/ +@property (nonatomic, readonly) NSUInteger offset; +@end diff --git a/include/ParseKit/PKTokenArraySource.h b/include/ParseKit/PKTokenArraySource.h new file mode 100644 index 0000000..59f4d53 --- /dev/null +++ b/include/ParseKit/PKTokenArraySource.h @@ -0,0 +1,68 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKTokenizer; +@class PKToken; + +/*! + @class PKTokenArraySource + @brief A TokenArraySource is a handy utility that enumerates over a specified reader, returning NSArrays of PKTokens delimited by a specified delimiter. + @details For example, + +@code + NSString *s = @"I came; I saw; I left in peace;"; + + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKTokenArraySource *src = [[[PKTokenArraySource alloc] initWithTokenizer:t delimiter:@";"] autorelease]; + + while ([src hasMore]) { + NSLog(@"%@", [src nextTokenArray]); + } +@endcode + + prints out: + +@code + I came + I saw + I left in peace +@endcode +*/ +@interface PKTokenArraySource : NSObject { + PKTokenizer *tokenizer; + NSString *delimiter; + PKToken *nextToken; +} + +/*! + @brief Constructs a PKTokenArraySource that will read an NSArrays of PKTokens using the specified tokenizer, delimited by the specified delimiter. + @param tokenizer a tokenizer to read tokens from + @param delimiter the character(s) that fences off where one array of tokens ends and the next begins +*/ +- (id)initWithTokenizer:(PKTokenizer *)t delimiter:(NSString *)s; + +/*! + @brief true if the source has more arrays of tokens. + @result true, if the source has more arrays of tokens that have not yet been popped with -nextTokenArray +*/ +- (BOOL)hasMore; + +/*! + @brief Returns the next array of tokens from the source. + @result the next array of tokens from the source +*/ +- (NSArray *)nextTokenArray; +@end diff --git a/include/ParseKit/PKTokenAssembly.h b/include/ParseKit/PKTokenAssembly.h new file mode 100644 index 0000000..3d18d8f --- /dev/null +++ b/include/ParseKit/PKTokenAssembly.h @@ -0,0 +1,63 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKTokenizer; + +/*! + @class PKTokenAssembly + @brief A PKTokenAssembly is a PKAssembly whose elements are PKTokens. + @details PKTokens are, roughly, the chunks of text that a PKTokenizer returns. +*/ +@interface PKTokenAssembly : PKAssembly { + PKTokenizer *tokenizer; + NSArray *tokens; + BOOL preservesWhitespaceTokens; +} + +/*! + @brief Convenience factory method for initializing an autoreleased assembly with the tokenizer t and its string + @param t tokenizer whose string will be worked on + @result an initialized autoreleased assembly +*/ ++ (id)assemblyWithTokenizer:(PKTokenizer *)t; + +/*! + @brief Convenience factory method for initializing an autoreleased assembly with the token array a and its string + @param a token array whose string will be worked on + @result an initialized autoreleased assembly +*/ ++ (id)assemblyWithTokenArray:(NSArray *)a; + +/*! + @brief Initializes an assembly with the tokenizer t and its string + @param t tokenizer whose string will be worked on + @result an initialized assembly +*/ +- (id)initWithTokenzier:(PKTokenizer *)t; + +/*! + @brief Initializes an assembly with the token array a and its string + @param a token array whose string will be worked on + @result an initialized assembly +*/ +- (id)initWithTokenArray:(NSArray *)a; + +/*! + @property preservesWhitespaceTokens + @brief If true, whitespace tokens retreived from this assembly's tokenizier will be silently placed on this assembly's stack without being reported by -next or -peek. Default is false. +*/ +@property (nonatomic) BOOL preservesWhitespaceTokens; +@end diff --git a/include/ParseKit/PKTokenizer.h b/include/ParseKit/PKTokenizer.h new file mode 100644 index 0000000..9ed2841 --- /dev/null +++ b/include/ParseKit/PKTokenizer.h @@ -0,0 +1,156 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class PKToken; +@class PKTokenizerState; +@class PKNumberState; +@class PKQuoteState; +@class PKCommentState; +@class PKSymbolState; +@class PKWhitespaceState; +@class PKWordState; +@class PKDelimitState; +@class PKReader; + +/*! + @class PKTokenizer + @brief A tokenizer divides a string into tokens. + @details

This class is highly customizable with regard to exactly how this division occurs, but it also has defaults that are suitable for many languages. This class assumes that the character values read from the string lie in the range 0-MAXINT. For example, the Unicode value of a capital A is 65, so NSLog(@"%C", (unichar)65); prints out a capital A.

+

The behavior of a tokenizer depends on its character state table. This table is an array of 256 PKTokenizerState states. The state table decides which state to enter upon reading a character from the input string.

+

For example, by default, upon reading an 'A', a tokenizer will enter a "word" state. This means the tokenizer will ask a PKWordState object to consume the 'A', along with the characters after the 'A' that form a word. The state's responsibility is to consume characters and return a complete token.

+

The default table sets a PKSymbolState for every character from 0 to 255, and then overrides this with:

+@code + From To State + 0 ' ' whitespaceState + 'a' 'z' wordState + 'A' 'Z' wordState + 160 255 wordState + '0' '9' numberState + '-' '-' numberState + '.' '.' numberState + '"' '"' quoteState + '\'' '\'' quoteState + '/' '/' commentState +@endcode +

In addition to allowing modification of the state table, this class makes each of the states above available. Some of these states are customizable. For example, wordState allows customization of what characters can be part of a word, after the first character.

+*/ +@interface PKTokenizer : NSObject { + NSString *string; + PKReader *reader; + + NSMutableArray *tokenizerStates; + + PKNumberState *numberState; + PKQuoteState *quoteState; + PKCommentState *commentState; + PKSymbolState *symbolState; + PKWhitespaceState *whitespaceState; + PKWordState *wordState; + PKDelimitState *delimitState; +} + +/*! + @brief Convenience factory method. Sets string from which to to read to nil. + @result An initialized tokenizer. +*/ ++ (id)tokenizer; + +/*! + @brief Convenience factory method. + @param s string to read from. + @result An autoreleased initialized tokenizer. +*/ ++ (id)tokenizerWithString:(NSString *)s; + +/*! + @brief Designated Initializer. Constructs a tokenizer to read from the supplied string. + @param s string to read from. + @result An initialized tokenizer. +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief Returns the next token. + @result the next token. +*/ +- (PKToken *)nextToken; + +#ifdef TARGET_OS_SNOW_LEOPARD +/*! + @brief Enumerate tokens in this tokenizer using block + @details repeatedly executes block by passing the token returned from calling -nextToken on this tokenizer + @param block the code to execute with every token returned by calling -nextToken on this tokenizer +*/ +- (void)enumerateTokensUsingBlock:(void (^)(PKToken *tok, BOOL *stop))block; +#endif + +/*! + @brief Change the state the tokenizer will enter upon reading any character between "start" and "end". + @param state the state for this character range + @param start the "start" character. e.g. 'a' or 65. + @param end the "end" character. 'z' or 90. +*/ +- (void)setTokenizerState:(PKTokenizerState *)state from:(PKUniChar)start to:(PKUniChar)end; + +/*! + @property string + @brief The string to read from. +*/ +@property (nonatomic, retain) NSString *string; + +/*! + @property numberState + @brief The state this tokenizer uses to build numbers. +*/ +@property (nonatomic, retain) PKNumberState *numberState; + +/*! + @property quoteState + @brief The state this tokenizer uses to build quoted strings. +*/ +@property (nonatomic, retain) PKQuoteState *quoteState; + +/*! + @property commentState + @brief The state this tokenizer uses to recognize (and possibly ignore) comments. +*/ +@property (nonatomic, retain) PKCommentState *commentState; + +/*! + @property symbolState + @brief The state this tokenizer uses to recognize symbols. +*/ +@property (nonatomic, retain) PKSymbolState *symbolState; + +/*! + @property whitespaceState + @brief The state this tokenizer uses to recognize (and possibly ignore) whitespace. +*/ +@property (nonatomic, retain) PKWhitespaceState *whitespaceState; + +/*! + @property wordState + @brief The state this tokenizer uses to build words. +*/ +@property (nonatomic, retain) PKWordState *wordState; + +/*! + @property delimitState + @brief The state this tokenizer uses to build delimited strings. +*/ +@property (nonatomic, retain) PKDelimitState *delimitState; +@end diff --git a/include/ParseKit/PKTokenizerState.h b/include/ParseKit/PKTokenizerState.h new file mode 100644 index 0000000..bd30ceb --- /dev/null +++ b/include/ParseKit/PKTokenizerState.h @@ -0,0 +1,56 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class PKToken; +@class PKTokenizer; +@class PKReader; + +/*! + @class PKTokenizerState + @brief A PKTokenizerState returns a token, given a reader, an initial character read from the reader, and a tokenizer that is conducting an overall tokenization of the reader. + @details The tokenizer will typically have a character state table that decides which state to use, depending on an initial character. If a single character is insufficient, a state such as PKCommentState will read a second character, and may delegate to another state, such as PKSingleLineState. This prospect of delegation is the reason that the -nextToken method has a tokenizer argument. +*/ +@interface PKTokenizerState : NSObject { + NSMutableString *stringbuf; + NSUInteger offset; + PKTokenizerState *fallbackState; + NSMutableArray *fallbackStates; +} + +/*! + @brief Return a token that represents a logical piece of a reader. + @param r the reader from which to read additional characters + @param cin the character that a tokenizer used to determine to use this state + @param t the tokenizer currently powering the tokenization + @result a token that represents a logical piece of the reader +*/ +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t; + +/*! + @brief Change the state this state will defer to upon reading any character between "start" and "end". + @param state the fallback state for this character range + @param start the "start" character. e.g. 'a' or 65. + @param end the "end" character. 'z' or 90. +*/ +- (void)setFallbackState:(PKTokenizerState *)state from:(PKUniChar)start to:(PKUniChar)end; + +/*! + @property fallbackState + @brief The state this tokenizer defers to if it starts, but ultimately aborts recognizing a token +*/ +@property (nonatomic, retain) PKTokenizerState *fallbackState; +@end diff --git a/include/ParseKit/PKTrack.h b/include/ParseKit/PKTrack.h new file mode 100644 index 0000000..087566f --- /dev/null +++ b/include/ParseKit/PKTrack.h @@ -0,0 +1,34 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKTrack + @brief A PKTrack is a sequence that throws a PKTrackException if the sequence begins but does not complete. + @details If -[PKTrack allMatchesFor:] begins but does not complete, it throws a PKTrackException. +*/ +@interface PKTrack : PKSequence { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKTrack parser. + @result an initialized autoreleased PKTrack parser. +*/ ++ (id)track; + ++ (id)trackWithSubparsers:(PKParser *)p1, ...; +@end diff --git a/include/ParseKit/PKTrackException.h b/include/ParseKit/PKTrackException.h new file mode 100644 index 0000000..65f0fc3 --- /dev/null +++ b/include/ParseKit/PKTrackException.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +extern NSString * const PKTrackExceptionName; + +/*! + @class PKTrackException + @brief Signals that a parser could not match text after a specific point. + @details The userInfo for this exception contains the following keys:
+            after (NSString *) - some indication of what text was interpretable before this exception occurred
+            expected (NSString *) - some indication of what kind of thing was expected, such as a ')' token
+            found (NSString *) - the text element the thrower actually found when it expected something else
+*/ +@interface PKTrackException : NSException { + +} + +@end diff --git a/include/ParseKit/PKTypes.h b/include/ParseKit/PKTypes.h new file mode 100644 index 0000000..02d2d6a --- /dev/null +++ b/include/ParseKit/PKTypes.h @@ -0,0 +1,18 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// a UTF-16 character. signed so that it may represent -1 as well +typedef SInt32 PKUniChar; + +#define PKEOF (PKUniChar)-1 \ No newline at end of file diff --git a/include/ParseKit/PKUppercaseWord.h b/include/ParseKit/PKUppercaseWord.h new file mode 100644 index 0000000..1bc5e64 --- /dev/null +++ b/include/ParseKit/PKUppercaseWord.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKUppercaseWord : PKWord { + +} + +@end diff --git a/include/ParseKit/PKWhitespace.h b/include/ParseKit/PKWhitespace.h new file mode 100644 index 0000000..be0ea89 --- /dev/null +++ b/include/ParseKit/PKWhitespace.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKWhitespace + @brief A PKWhitespace matches a number from a token assembly. +*/ +@interface PKWhitespace : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKWhitespace object. + @result an initialized autoreleased PKWhitespace object +*/ ++ (id)whitespace; +@end diff --git a/include/ParseKit/PKWhitespaceState.h b/include/ParseKit/PKWhitespaceState.h new file mode 100644 index 0000000..eb698e8 --- /dev/null +++ b/include/ParseKit/PKWhitespaceState.h @@ -0,0 +1,48 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKWhitespaceState + @brief A whitespace state ignores whitespace (such as blanks and tabs), and returns the tokenizer's next token. + @details By default, all characters from 0 to 32 are whitespace. +*/ +@interface PKWhitespaceState : PKTokenizerState { + NSMutableArray *whitespaceChars; + BOOL reportsWhitespaceTokens; +} + +/*! + @brief Informs whether the given character is recognized as whitespace (and therefore ignored) by this state. + @param cin the character to check + @result true if the given chracter is recognized as whitespace +*/ +- (BOOL)isWhitespaceChar:(PKUniChar)cin; + +/*! + @brief Establish the given character range as whitespace to ignore. + @param yn true if the given character range is whitespace + @param start the "start" character. e.g. 'a' or 65. + @param end the "end" character. 'z' or 90. +*/ +- (void)setWhitespaceChars:(BOOL)yn from:(PKUniChar)start to:(PKUniChar)end; + +/*! + @property reportsWhitespaceTokens + @brief determines whether a PKTokenizer associated with this state reports or silently consumes whitespace tokens. default is NO which causes silent consumption of whitespace chars +*/ +@property (nonatomic) BOOL reportsWhitespaceTokens; +@end diff --git a/include/ParseKit/PKWord.h b/include/ParseKit/PKWord.h new file mode 100644 index 0000000..90372fe --- /dev/null +++ b/include/ParseKit/PKWord.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKWord + @brief A PKWord matches a word from a token assembly. +*/ +@interface PKWord : PKTerminal { + +} + +/*! + @brief Convenience factory method for initializing an autoreleased PKWord object. + @result an initialized autoreleased PKWord object +*/ ++ (id)word; +@end diff --git a/include/ParseKit/PKWordState.h b/include/ParseKit/PKWordState.h new file mode 100644 index 0000000..030f5d7 --- /dev/null +++ b/include/ParseKit/PKWordState.h @@ -0,0 +1,49 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKWordState + @brief A word state returns a word from a reader. + @details

Like other states, a tokenizer transfers the job of reading to this state, depending on an initial character. Thus, the tokenizer decides which characters may begin a word, and this state determines which characters may appear as a second or later character in a word. These are typically different sets of characters; in particular, it is typical for digits to appear as parts of a word, but not as the initial character of a word.

+

By default, the following characters may appear in a word. The method setWordChars() allows customizing this.

+@code + From To + 'a' 'z' + 'A' 'Z' + '0' '9' +@endcode +

as well as: minus sign -, underscore _, and apostrophe '.

+*/ +@interface PKWordState : PKTokenizerState { + NSMutableArray *wordChars; +} + +/*! + @brief Establish characters in the given range as valid characters for part of a word after the first character. Note that the tokenizer must determine which characters are valid as the beginning character of a word. + @param yn true if characters in the given range are word characters + @param start the "start" character. e.g. 'a' or 65. + @param end the "end" character. 'z' or 90. +*/ +- (void)setWordChars:(BOOL)yn from:(PKUniChar)start to:(PKUniChar)end; + +/*! + @brief Informs whether the given character is recognized as a word character by this state. + @param cin the character to check + @result true if the given chracter is recognized as a word character +*/ +- (BOOL)isWordChar:(PKUniChar)c; +@end diff --git a/include/ParseKit/ParseKit.h b/include/ParseKit/ParseKit.h new file mode 100644 index 0000000..c13608d --- /dev/null +++ b/include/ParseKit/ParseKit.h @@ -0,0 +1,88 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + @mainpage ParseKit + ParseKit is a Mac OS X Framework written by Todd Ditchendorf in Objective-C 2.0 and released under the MIT Open Source License. + The framework is an Objective-C implementation of the tools described in "Building Parsers with Java" by Steven John Metsker. + ParseKit includes some significant additions beyond the designs from the book (many of them hinted at in the book itself) in order to enhance the framework's feature set, usefulness and ease-of-use. Other changes have been made to the designs in the book to match common Cocoa/Objective-C design patterns and conventions. + However, these changes are relatively superficial, and Metsker's book is the best documentation available for this framework. + + Classes in the ParseKit Framework offer 2 basic services of general use to Cocoa developers: + @li Tokenization via a tokenizer class + @li Parsing via a high-level parser-building toolkit + Learn more on the project site +*/ + +#import + +// io +#import +#import + +// parse +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +//chars +#import +#import +#import +#import +#import + +// tokens +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +// grammar +#import diff --git a/jsdemoapp/.svn/all-wcprops b/jsdemoapp/.svn/all-wcprops new file mode 100644 index 0000000..a669369 --- /dev/null +++ b/jsdemoapp/.svn/all-wcprops @@ -0,0 +1,53 @@ +K 25 +svn:wc:ra_dav:version-url +V 34 +/svn/!svn/ver/1404/trunk/jsdemoapp +END +main.m +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/583/trunk/jsdemoapp/main.m +END +ParserTest.html +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1115/trunk/jsdemoapp/ParserTest.html +END +Test.html +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1112/trunk/jsdemoapp/Test.html +END +JSDemoAppDelegate.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1115/trunk/jsdemoapp/JSDemoAppDelegate.h +END +JSDemoApp-Info.plist +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1173/trunk/jsdemoapp/JSDemoApp-Info.plist +END +JSDemoAppDelegate.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1404/trunk/jsdemoapp/JSDemoAppDelegate.m +END +JSDemoAppMainMenu.xib +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1176/trunk/jsdemoapp/JSDemoAppMainMenu.xib +END +DefaultValues.plist +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/584/trunk/jsdemoapp/DefaultValues.plist +END diff --git a/jsdemoapp/.svn/entries b/jsdemoapp/.svn/entries new file mode 100644 index 0000000..b20066f --- /dev/null +++ b/jsdemoapp/.svn/entries @@ -0,0 +1,300 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/jsdemoapp +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +main.m +file + + + + +2009-01-11T18:01:14.000000Z +d0119959215a3c0e063c1080b72c21ac +2009-01-11T01:15:32.782160Z +583 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +263 + +ParserTest.html +file + + + + +2009-06-30T06:11:02.000000Z +987976a960610d216d1114cc3adf1b2c +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +734 + +Test.html +file + + + + +2009-06-30T04:56:26.000000Z +6d814de5650e5d3d5d6355fb804d3e9f +2009-06-30T05:02:01.546527Z +1112 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +721 + +JSDemoAppDelegate.h +file + + + + +2009-07-03T19:42:56.000000Z +fae5b94c26b123225dc2e7c37abd375b +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +529 + +JSDemoApp-Info.plist +file + + + + +2009-07-03T20:36:46.000000Z +08cb0d5aa8a87a6178461b262cba9015 +2009-07-03T20:39:51.719779Z +1173 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +757 + +JSDemoAppDelegate.m +file + + + + +2009-11-13T07:14:30.000000Z +11da56b751f8560a53af90ce2e14e257 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3429 + +JSDemoAppMainMenu.xib +file + + + + +2009-07-03T20:47:13.000000Z +e761ba8b1d431479386bc37e71ff4d54 +2009-07-03T20:47:45.514705Z +1176 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +162358 + +DefaultValues.plist +file + + + + +2009-01-11T18:01:14.000000Z +c816c3d5b3620a32d7833be66c12212e +2009-01-11T02:09:50.994986Z +584 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +395 + diff --git a/jsdemoapp/.svn/prop-base/JSDemoAppMainMenu.xib.svn-base b/jsdemoapp/.svn/prop-base/JSDemoAppMainMenu.xib.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jsdemoapp/.svn/prop-base/JSDemoAppMainMenu.xib.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jsdemoapp/.svn/text-base/DefaultValues.plist.svn-base b/jsdemoapp/.svn/text-base/DefaultValues.plist.svn-base new file mode 100644 index 0000000..4ecd006 --- /dev/null +++ b/jsdemoapp/.svn/text-base/DefaultValues.plist.svn-base @@ -0,0 +1,15 @@ + + + + + + WebKitDeveloperExtras + + + diff --git a/jsdemoapp/.svn/text-base/JSDemoApp-Info.plist.svn-base b/jsdemoapp/.svn/text-base/JSDemoApp-Info.plist.svn-base new file mode 100644 index 0000000..ad8f8c1 --- /dev/null +++ b/jsdemoapp/.svn/text-base/JSDemoApp-Info.plist.svn-base @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + JSDemoAppMainMenu + NSPrincipalClass + NSApplication + + diff --git a/jsdemoapp/.svn/text-base/JSDemoAppDelegate.h.svn-base b/jsdemoapp/.svn/text-base/JSDemoAppDelegate.h.svn-base new file mode 100644 index 0000000..fb52575 --- /dev/null +++ b/jsdemoapp/.svn/text-base/JSDemoAppDelegate.h.svn-base @@ -0,0 +1,24 @@ +// +// JSDemoAppDelegate.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/10/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class WebView; + +@interface JSDemoAppDelegate : NSObject { + IBOutlet NSWindow *window; + IBOutlet WebView *webView; + IBOutlet NSTextField *comboBox; +} +- (IBAction)goToLocation:(id)sender; +- (IBAction)openLocation:(id)sender; +- (IBAction)collect:(id)sender; +- (IBAction)showConsole:(id)sender; + +@property (nonatomic, retain) WebView *webView; +@end diff --git a/jsdemoapp/.svn/text-base/JSDemoAppDelegate.m.svn-base b/jsdemoapp/.svn/text-base/JSDemoAppDelegate.m.svn-base new file mode 100644 index 0000000..48c03ab --- /dev/null +++ b/jsdemoapp/.svn/text-base/JSDemoAppDelegate.m.svn-base @@ -0,0 +1,135 @@ +// +// JSDemoAppDelegate.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/10/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "JSDemoAppDelegate.h" +#import +#import + +@interface NSObject (JSDemoAppExtras) +- (id)inspector; +- (void)showConsole:(id)sender; +@end + +@interface JSDemoAppDelegate () ++ (void)setUpDefaults; +@end + +@implementation JSDemoAppDelegate + ++ (void)load { + if ([JSDemoAppDelegate class] == self) { + [self setUpDefaults]; + } +} + + ++ (void)setUpDefaults { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString *path = [[NSBundle mainBundle] pathForResource:@"DefaultValues" ofType:@"plist"]; + id defaultValues = [NSMutableDictionary dictionaryWithContentsOfFile:path]; + [[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:defaultValues]; + [[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues]; + [[NSUserDefaults standardUserDefaults] synchronize]; + [pool release]; +} + + +- (id)init { + if (self = [super init]) { + + } + return self; +} + + +- (void)dealloc { + self.webView = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { + NSString *path = [[NSBundle mainBundle] pathForResource:@"Test" ofType:@"html"]; + [comboBox setStringValue:[[NSURL fileURLWithPath:path] absoluteString]]; + [self goToLocation:self]; +} + + +#pragma mark - +#pragma mark Actions + +- (IBAction)openLocation:(id)sender { + [window makeFirstResponder:comboBox]; +} + + +- (IBAction)goToLocation:(id)sender { + NSString *URLString = [comboBox stringValue]; + + if (![URLString length]) { + NSBeep(); + return; + } + + if (![URLString hasPrefix:@"file://"] && ![URLString hasPrefix:@"http://"] && ![URLString hasPrefix:@"https://"]) { + URLString = [NSString stringWithFormat:@"http://%@", URLString]; + [comboBox setStringValue:URLString]; + } + + [webView setMainFrameURL:URLString]; +} + + +- (IBAction)collect:(id)sender { + JSGlobalContextRef ctx = [[webView mainFrame] globalContext]; + JSGarbageCollect(ctx); +} + + +- (IBAction)showConsole:(id)sender { + [[webView inspector] showConsole:sender]; +} + + +#pragma mark - +#pragma mark WebFrameLoadDelegate + +- (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame { + if (frame != [sender mainFrame]) return; + + [window setTitle:title]; +} + + +- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame { + if (frame != [sender mainFrame]) return; + + NSString *URLString = [[[[frame provisionalDataSource] request] URL] absoluteString]; + [comboBox setStringValue:URLString]; +} + + +- (void)webView:(WebView *)sender didReceiveServerRedirectForProvisionalLoadForFrame:(WebFrame *)frame { + if (frame != [sender mainFrame]) return; + + NSString *URLString = [[[[frame provisionalDataSource] request] URL] absoluteString]; + [comboBox setStringValue:URLString]; +} + + +- (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date forFrame:(WebFrame *)frame { + [comboBox setStringValue:[URL absoluteString]]; +} + + +- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame { + PKJSParseKitSetUpContext([[sender mainFrame] globalContext]); +} + +@synthesize webView; +@end diff --git a/jsdemoapp/.svn/text-base/JSDemoAppMainMenu.xib.svn-base b/jsdemoapp/.svn/text-base/JSDemoAppMainMenu.xib.svn-base new file mode 100644 index 0000000..8ce0b7c --- /dev/null +++ b/jsdemoapp/.svn/text-base/JSDemoAppMainMenu.xib.svn-base @@ -0,0 +1,3802 @@ + + + + 1050 + 9J61 + 677 + 949.46 + 353.00 + + YES + + + + + YES + com.apple.WebKitIBPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + NSFontManager + + + AMainMenu + + YES + + + JSDemoApp + + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + JSDemoApp + + YES + + + About JSDemoApp + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Services + + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 2147483647 + + + + + + Hide JSDemoApp + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Quit JSDemoApp + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + T3BlbuKApg + o + 1048576 + 2147483647 + + + + + + T3BlbiBMb2NhdGlvbuKApg + l + 1048576 + 2147483647 + + + + + + Open Recent + + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 2147483647 + + + + + + Reload + r + 1048576 + 2147483647 + + + + + + Stop Loading + . + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + U2F2ZSBBc+KApg + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + UHJpbnTigKY + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Find + + 2147483647 + + + submenuAction: + + Find + + YES + + + RmluZOKApg + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + U2hvdyBTcGVsbGluZ+KApg + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 2147483647 + + + + + + Check Grammar With Spelling + + 2147483647 + + + + + + + + + Substitutions + + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 2147483647 + + + + + + Stop Speaking + + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Q3VzdG9taXplIFRvb2xiYXLigKY + + 2147483647 + + + + + + + + + Window + + 2147483647 + + + submenuAction: + + Window + + YES + + + Show Console + c + 1572864 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bring All to Front + + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + JSDemoApp Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + 15 + 2 + {{30, 591}, {359, 258}} + 1886912512 + Window + NSWindow + View + {3.40282e+38, 3.40282e+38} + {359, 258} + + + 256 + + YES + + + 274 + + YES + + YES + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple URL pasteboard type + Apple Web Archive pasteboard type + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + WebURLsWithTitlesPboardType + public.png + public.url + public.url-name + + + {{0, 20}, {359, 172}} + + + + + + + + YES + + YES + WebKitDefaultFixedFontSize + WebKitDefaultFontSize + WebKitMinimumFontSize + + + YES + + + + + + + YES + YES + + + + 266 + {{240, 215}, {82, 22}} + + YES + + -1804468671 + 268436480 + + + LucidaGrande + 1.300000e+01 + 1044 + + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + 3 + MAA + + + + + + + 268 + {{20, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + Round Textured + + + -2033958657 + 163 + + NSImage + NSLeftFacingTriangleTemplate + + + + 400 + 75 + + + + + 268 + {{64, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + Round Textured + + + -2033958657 + 163 + + NSImage + NSRightFacingTriangleTemplate + + + + 400 + 75 + + + + + 268 + {{108, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + Round Textured + + + -2033958657 + 163 + + NSImage + NSRefreshTemplate + + + + 400 + 75 + + + + + 268 + {{152, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + Round Textured + + + -2033958657 + 163 + + NSImage + NSStopProgressTemplate + + + + 400 + 75 + + + + + 14 + {{0, 190}, {359, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + + 34 + {{0, 17}, {359, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + + 1289 + + {{330, 218}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + + 268 + {{196, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + GC + + + -2033434369 + 163 + + + 400 + 75 + + + + {359, 258} + + + {{0, 0}, {1440, 878}} + {359, 280} + {3.40282e+38, 3.40282e+38} + + + JSDemoAppDelegate + + + + + YES + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + terminate: + + + + 369 + + + + unhideAllApplications: + + + + 370 + + + + addFontTrait: + + + + 418 + + + + addFontTrait: + + + + 419 + + + + modifyFont: + + + + 420 + + + + orderFrontFontPanel: + + + + 421 + + + + modifyFont: + + + + 422 + + + + raiseBaseline: + + + + 423 + + + + lowerBaseline: + + + + 424 + + + + copyFont: + + + + 425 + + + + subscript: + + + + 426 + + + + superscript: + + + + 427 + + + + tightenKerning: + + + + 428 + + + + underline: + + + + 429 + + + + orderFrontColorPanel: + + + + 430 + + + + useAllLigatures: + + + + 431 + + + + loosenKerning: + + + + 432 + + + + pasteFont: + + + + 433 + + + + unscript: + + + + 434 + + + + useStandardKerning: + + + + 435 + + + + useStandardLigatures: + + + + 436 + + + + turnOffLigatures: + + + + 437 + + + + turnOffKerning: + + + + 438 + + + + alignLeft: + + + + 439 + + + + alignJustified: + + + + 440 + + + + copyRuler: + + + + 441 + + + + alignCenter: + + + + 442 + + + + toggleRuler: + + + + 443 + + + + alignRight: + + + + 444 + + + + pasteRuler: + + + + 445 + + + + nextKeyView + + + + 463 + + + + nextKeyView + + + + 464 + + + + nextKeyView + + + + 465 + + + + nextKeyView + + + + 466 + + + + nextKeyView + + + + 467 + + + + initialFirstResponder + + + + 471 + + + + window + + + + 473 + + + + webView + + + + 474 + + + + comboBox + + + + 475 + + + + goBack: + + + + 476 + + + + goForward: + + + + 477 + + + + reload: + + + + 478 + + + + stopLoading: + + + + 479 + + + + goToLocation: + + + + 480 + + + + openLocation: + + + + 483 + + + + reload: + + + + 486 + + + + stopLoading: + + + + 488 + + + + animate: webView.isLoading + + + + + + animate: webView.isLoading + animate + webView.isLoading + 2 + + + 489 + + + + frameLoadDelegate + + + + 490 + + + + UIDelegate + + + + 491 + + + + policyDelegate + + + + 492 + + + + collect: + + + + 495 + + + + showConsole: + + + + 498 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + + + + + 75 + + + 3 + + + 80 + + + 8 + + + 78 + + + 6 + + + 72 + + + + + 82 + + + 9 + + + 124 + + + YES + + + + + + 77 + + + 5 + + + 73 + + + 1 + + + 79 + + + 7 + + + 112 + + + 10 + + + 74 + + + 2 + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + + + 373 + + + YES + + + + + + 374 + + + YES + + + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + 377 + + + YES + + + + + + + + + + + + + 378 + + + + + 379 + + + + + 380 + + + + + 381 + + + + + 382 + + + + + 383 + + + + + 384 + + + + + 385 + + + + + 386 + + + YES + + + + + + + + + + + + + + + + + + + + + 387 + + + + + 388 + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + YES + + + + + + 396 + + + YES + + + + + + 397 + + + YES + + + + + + 398 + + + + + 399 + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + YES + + + + + + + + + + 404 + + + + + 405 + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + YES + + + + + + + + 410 + + + + + 411 + + + + + 412 + + + + + 413 + + + YES + + + + + + + + + 414 + + + + + 415 + + + + + 416 + + + + + 417 + + + + + 446 + + + YES + + + + Window + + + 447 + + + YES + + + + + + + + + + + + + + + 448 + + + + + 449 + + + YES + + + + + + 450 + + + + + 451 + + + + + 452 + + + YES + + + + + + 453 + + + YES + + + + + + 454 + + + YES + + + + + + 455 + + + YES + + + + + + 456 + + + + + 457 + + + + + 458 + + + + + 459 + + + + + 460 + + + + + 461 + + + + + 472 + + + + + 482 + + + + + 484 + + + 1 + + + 485 + + + 7 + + + 487 + + + 1 + + + 493 + + + YES + + + + + + 494 + + + + + 496 + + + + + 497 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBEditorWindowLastContentRect + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBEditorWindowLastContentRect + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 371.IBPluginDependency + 373.IBPluginDependency + 374.IBEditorWindowLastContentRect + 374.IBPluginDependency + 375.IBPluginDependency + 376.IBPluginDependency + 377.IBPluginDependency + 378.IBPluginDependency + 379.IBPluginDependency + 380.IBPluginDependency + 381.IBPluginDependency + 382.IBPluginDependency + 383.IBPluginDependency + 384.IBPluginDependency + 385.IBPluginDependency + 386.IBEditorWindowLastContentRect + 386.IBPluginDependency + 387.IBPluginDependency + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 446.IBEditorWindowLastContentRect + 446.IBWindowTemplateEditedContentRect + 446.ImportedFromIB2 + 446.NSWindowTemplate.visibleAtLaunch + 446.editorWindowContentRectSynchronizationRect + 446.windowTemplate.hasMinSize + 446.windowTemplate.minSize + 447.IBPluginDependency + 447.ImportedFromIB2 + 448.IBPluginDependency + 449.IBPluginDependency + 450.IBPluginDependency + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 455.IBPluginDependency + 456.IBPluginDependency + 457.IBPluginDependency + 458.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 461.IBPluginDependency + 472.IBPluginDependency + 482.IBPluginDependency + 482.ImportedFromIB2 + 484.IBPluginDependency + 484.ImportedFromIB2 + 485.IBPluginDependency + 485.ImportedFromIB2 + 487.IBPluginDependency + 487.ImportedFromIB2 + 493.IBPluginDependency + 494.IBPluginDependency + 496.IBPluginDependency + 496.ImportedFromIB2 + 497.IBPluginDependency + 497.ImportedFromIB2 + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + {{524, 524}, {189, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{596, 852}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{817, 764}, {132, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{895, 584}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{652, 604}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{365, 632}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{895, 584}, {153, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{895, 584}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{812, -102}, {211, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{495, 1}, {449, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 977}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{762, 804}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{895, 584}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{696, 804}, {86, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{782, 564}, {178, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{88, 559}, {359, 258}} + {{88, 559}, {359, 258}} + + + {{201, 387}, {507, 413}} + + {359, 258} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{507, 664}, {218, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{610, 574}, {207, 273}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{323, 672}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 498 + + + + YES + + FirstResponder + NSObject + + openLocation: + id + + + IBUserSource + + + + + JSDemoAppDelegate + NSObject + + YES + + YES + collect: + goToLocation: + openLocation: + showConsole: + + + YES + id + id + id + id + + + + YES + + YES + comboBox + webView + window + + + YES + NSTextField + WebView + NSWindow + + + + IBProjectSource + jsdemoapp/JSDemoAppDelegate.h + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + + 0 + ../ParseKit.xcodeproj + 3 + + diff --git a/jsdemoapp/.svn/text-base/ParserTest.html.svn-base b/jsdemoapp/.svn/text-base/ParserTest.html.svn-base new file mode 100644 index 0000000..c0f7785 --- /dev/null +++ b/jsdemoapp/.svn/text-base/ParserTest.html.svn-base @@ -0,0 +1,25 @@ + diff --git a/jsdemoapp/.svn/text-base/Test.html.svn-base b/jsdemoapp/.svn/text-base/Test.html.svn-base new file mode 100644 index 0000000..bdfe4eb --- /dev/null +++ b/jsdemoapp/.svn/text-base/Test.html.svn-base @@ -0,0 +1,35 @@ + diff --git a/jsdemoapp/.svn/text-base/main.m.svn-base b/jsdemoapp/.svn/text-base/main.m.svn-base new file mode 100644 index 0000000..8aa7981 --- /dev/null +++ b/jsdemoapp/.svn/text-base/main.m.svn-base @@ -0,0 +1,14 @@ +/* + * main.m + * TDParseKit + * + * Created by Todd Ditchendorf on 1/10/09. + * Copyright 2009 Todd Ditchendorf. All rights reserved. + * + */ + +#import + +int main(int argc, char *argv[]) { + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/jsdemoapp/DefaultValues.plist b/jsdemoapp/DefaultValues.plist new file mode 100644 index 0000000..4ecd006 --- /dev/null +++ b/jsdemoapp/DefaultValues.plist @@ -0,0 +1,15 @@ + + + + + + WebKitDeveloperExtras + + + diff --git a/jsdemoapp/JSDemoApp-Info.plist b/jsdemoapp/JSDemoApp-Info.plist new file mode 100644 index 0000000..ad8f8c1 --- /dev/null +++ b/jsdemoapp/JSDemoApp-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + JSDemoAppMainMenu + NSPrincipalClass + NSApplication + + diff --git a/jsdemoapp/JSDemoAppDelegate.h b/jsdemoapp/JSDemoAppDelegate.h new file mode 100644 index 0000000..8e19f6a --- /dev/null +++ b/jsdemoapp/JSDemoAppDelegate.h @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class WebView; + +@interface JSDemoAppDelegate : NSObject { + IBOutlet NSWindow *window; + IBOutlet WebView *webView; + IBOutlet NSTextField *comboBox; +} +- (IBAction)goToLocation:(id)sender; +- (IBAction)openLocation:(id)sender; +- (IBAction)collect:(id)sender; +- (IBAction)showConsole:(id)sender; + +@property (nonatomic, retain) WebView *webView; +@end diff --git a/jsdemoapp/JSDemoAppDelegate.m b/jsdemoapp/JSDemoAppDelegate.m new file mode 100644 index 0000000..22e2ef8 --- /dev/null +++ b/jsdemoapp/JSDemoAppDelegate.m @@ -0,0 +1,141 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "JSDemoAppDelegate.h" +#import +#import + +@interface NSObject (JSDemoAppExtras) +- (id)inspector; +- (void)showConsole:(id)sender; +@end + +@interface JSDemoAppDelegate () ++ (void)setUpDefaults; +@end + +@implementation JSDemoAppDelegate + ++ (void)load { + if ([JSDemoAppDelegate class] == self) { + [self setUpDefaults]; + } +} + + ++ (void)setUpDefaults { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString *path = [[NSBundle mainBundle] pathForResource:@"DefaultValues" ofType:@"plist"]; + id defaultValues = [NSMutableDictionary dictionaryWithContentsOfFile:path]; + [[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:defaultValues]; + [[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues]; + [[NSUserDefaults standardUserDefaults] synchronize]; + [pool release]; +} + + +- (id)init { + if (self = [super init]) { + + } + return self; +} + + +- (void)dealloc { + self.webView = nil; + [super dealloc]; +} + + +- (void)awakeFromNib { + NSString *path = [[NSBundle mainBundle] pathForResource:@"Test" ofType:@"html"]; + [comboBox setStringValue:[[NSURL fileURLWithPath:path] absoluteString]]; + [self goToLocation:self]; +} + + +#pragma mark - +#pragma mark Actions + +- (IBAction)openLocation:(id)sender { + [window makeFirstResponder:comboBox]; +} + + +- (IBAction)goToLocation:(id)sender { + NSString *URLString = [comboBox stringValue]; + + if (![URLString length]) { + NSBeep(); + return; + } + + if (![URLString hasPrefix:@"file://"] && ![URLString hasPrefix:@"http://"] && ![URLString hasPrefix:@"https://"]) { + URLString = [NSString stringWithFormat:@"http://%@", URLString]; + [comboBox setStringValue:URLString]; + } + + [webView setMainFrameURL:URLString]; +} + + +- (IBAction)collect:(id)sender { + JSGlobalContextRef ctx = [[webView mainFrame] globalContext]; + JSGarbageCollect(ctx); +} + + +- (IBAction)showConsole:(id)sender { + [[webView inspector] showConsole:sender]; +} + + +#pragma mark - +#pragma mark WebFrameLoadDelegate + +- (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame { + if (frame != [sender mainFrame]) return; + + [window setTitle:title]; +} + + +- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame { + if (frame != [sender mainFrame]) return; + + NSString *URLString = [[[[frame provisionalDataSource] request] URL] absoluteString]; + [comboBox setStringValue:URLString]; +} + + +- (void)webView:(WebView *)sender didReceiveServerRedirectForProvisionalLoadForFrame:(WebFrame *)frame { + if (frame != [sender mainFrame]) return; + + NSString *URLString = [[[[frame provisionalDataSource] request] URL] absoluteString]; + [comboBox setStringValue:URLString]; +} + + +- (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date forFrame:(WebFrame *)frame { + [comboBox setStringValue:[URL absoluteString]]; +} + + +- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame { + PKJSParseKitSetUpContext([[sender mainFrame] globalContext]); +} + +@synthesize webView; +@end diff --git a/jsdemoapp/JSDemoAppMainMenu.xib b/jsdemoapp/JSDemoAppMainMenu.xib new file mode 100644 index 0000000..8ce0b7c --- /dev/null +++ b/jsdemoapp/JSDemoAppMainMenu.xib @@ -0,0 +1,3802 @@ + + + + 1050 + 9J61 + 677 + 949.46 + 353.00 + + YES + + + + + YES + com.apple.WebKitIBPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + NSFontManager + + + AMainMenu + + YES + + + JSDemoApp + + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + JSDemoApp + + YES + + + About JSDemoApp + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Services + + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 2147483647 + + + + + + Hide JSDemoApp + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Quit JSDemoApp + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + T3BlbuKApg + o + 1048576 + 2147483647 + + + + + + T3BlbiBMb2NhdGlvbuKApg + l + 1048576 + 2147483647 + + + + + + Open Recent + + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 2147483647 + + + + + + Reload + r + 1048576 + 2147483647 + + + + + + Stop Loading + . + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + U2F2ZSBBc+KApg + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + UHJpbnTigKY + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Find + + 2147483647 + + + submenuAction: + + Find + + YES + + + RmluZOKApg + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + U2hvdyBTcGVsbGluZ+KApg + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 2147483647 + + + + + + Check Grammar With Spelling + + 2147483647 + + + + + + + + + Substitutions + + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 2147483647 + + + + + + Stop Speaking + + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Q3VzdG9taXplIFRvb2xiYXLigKY + + 2147483647 + + + + + + + + + Window + + 2147483647 + + + submenuAction: + + Window + + YES + + + Show Console + c + 1572864 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bring All to Front + + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + JSDemoApp Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + 15 + 2 + {{30, 591}, {359, 258}} + 1886912512 + Window + NSWindow + View + {3.40282e+38, 3.40282e+38} + {359, 258} + + + 256 + + YES + + + 274 + + YES + + YES + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple URL pasteboard type + Apple Web Archive pasteboard type + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + WebURLsWithTitlesPboardType + public.png + public.url + public.url-name + + + {{0, 20}, {359, 172}} + + + + + + + + YES + + YES + WebKitDefaultFixedFontSize + WebKitDefaultFontSize + WebKitMinimumFontSize + + + YES + + + + + + + YES + YES + + + + 266 + {{240, 215}, {82, 22}} + + YES + + -1804468671 + 268436480 + + + LucidaGrande + 1.300000e+01 + 1044 + + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + 3 + MAA + + + + + + + 268 + {{20, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + Round Textured + + + -2033958657 + 163 + + NSImage + NSLeftFacingTriangleTemplate + + + + 400 + 75 + + + + + 268 + {{64, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + Round Textured + + + -2033958657 + 163 + + NSImage + NSRightFacingTriangleTemplate + + + + 400 + 75 + + + + + 268 + {{108, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + Round Textured + + + -2033958657 + 163 + + NSImage + NSRefreshTemplate + + + + 400 + 75 + + + + + 268 + {{152, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + Round Textured + + + -2033958657 + 163 + + NSImage + NSStopProgressTemplate + + + + 400 + 75 + + + + + 14 + {{0, 190}, {359, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + + 34 + {{0, 17}, {359, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + + 1289 + + {{330, 218}, {16, 16}} + + 28938 + 1.600000e+01 + 1.000000e+02 + + + + 268 + {{196, 214}, {36, 25}} + + YES + + -2080244224 + 134217728 + GC + + + -2033434369 + 163 + + + 400 + 75 + + + + {359, 258} + + + {{0, 0}, {1440, 878}} + {359, 280} + {3.40282e+38, 3.40282e+38} + + + JSDemoAppDelegate + + + + + YES + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + terminate: + + + + 369 + + + + unhideAllApplications: + + + + 370 + + + + addFontTrait: + + + + 418 + + + + addFontTrait: + + + + 419 + + + + modifyFont: + + + + 420 + + + + orderFrontFontPanel: + + + + 421 + + + + modifyFont: + + + + 422 + + + + raiseBaseline: + + + + 423 + + + + lowerBaseline: + + + + 424 + + + + copyFont: + + + + 425 + + + + subscript: + + + + 426 + + + + superscript: + + + + 427 + + + + tightenKerning: + + + + 428 + + + + underline: + + + + 429 + + + + orderFrontColorPanel: + + + + 430 + + + + useAllLigatures: + + + + 431 + + + + loosenKerning: + + + + 432 + + + + pasteFont: + + + + 433 + + + + unscript: + + + + 434 + + + + useStandardKerning: + + + + 435 + + + + useStandardLigatures: + + + + 436 + + + + turnOffLigatures: + + + + 437 + + + + turnOffKerning: + + + + 438 + + + + alignLeft: + + + + 439 + + + + alignJustified: + + + + 440 + + + + copyRuler: + + + + 441 + + + + alignCenter: + + + + 442 + + + + toggleRuler: + + + + 443 + + + + alignRight: + + + + 444 + + + + pasteRuler: + + + + 445 + + + + nextKeyView + + + + 463 + + + + nextKeyView + + + + 464 + + + + nextKeyView + + + + 465 + + + + nextKeyView + + + + 466 + + + + nextKeyView + + + + 467 + + + + initialFirstResponder + + + + 471 + + + + window + + + + 473 + + + + webView + + + + 474 + + + + comboBox + + + + 475 + + + + goBack: + + + + 476 + + + + goForward: + + + + 477 + + + + reload: + + + + 478 + + + + stopLoading: + + + + 479 + + + + goToLocation: + + + + 480 + + + + openLocation: + + + + 483 + + + + reload: + + + + 486 + + + + stopLoading: + + + + 488 + + + + animate: webView.isLoading + + + + + + animate: webView.isLoading + animate + webView.isLoading + 2 + + + 489 + + + + frameLoadDelegate + + + + 490 + + + + UIDelegate + + + + 491 + + + + policyDelegate + + + + 492 + + + + collect: + + + + 495 + + + + showConsole: + + + + 498 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + + + + + 75 + + + 3 + + + 80 + + + 8 + + + 78 + + + 6 + + + 72 + + + + + 82 + + + 9 + + + 124 + + + YES + + + + + + 77 + + + 5 + + + 73 + + + 1 + + + 79 + + + 7 + + + 112 + + + 10 + + + 74 + + + 2 + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + + + 373 + + + YES + + + + + + 374 + + + YES + + + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + 377 + + + YES + + + + + + + + + + + + + 378 + + + + + 379 + + + + + 380 + + + + + 381 + + + + + 382 + + + + + 383 + + + + + 384 + + + + + 385 + + + + + 386 + + + YES + + + + + + + + + + + + + + + + + + + + + 387 + + + + + 388 + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + YES + + + + + + 396 + + + YES + + + + + + 397 + + + YES + + + + + + 398 + + + + + 399 + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + YES + + + + + + + + + + 404 + + + + + 405 + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + YES + + + + + + + + 410 + + + + + 411 + + + + + 412 + + + + + 413 + + + YES + + + + + + + + + 414 + + + + + 415 + + + + + 416 + + + + + 417 + + + + + 446 + + + YES + + + + Window + + + 447 + + + YES + + + + + + + + + + + + + + + 448 + + + + + 449 + + + YES + + + + + + 450 + + + + + 451 + + + + + 452 + + + YES + + + + + + 453 + + + YES + + + + + + 454 + + + YES + + + + + + 455 + + + YES + + + + + + 456 + + + + + 457 + + + + + 458 + + + + + 459 + + + + + 460 + + + + + 461 + + + + + 472 + + + + + 482 + + + + + 484 + + + 1 + + + 485 + + + 7 + + + 487 + + + 1 + + + 493 + + + YES + + + + + + 494 + + + + + 496 + + + + + 497 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBEditorWindowLastContentRect + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBEditorWindowLastContentRect + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 371.IBPluginDependency + 373.IBPluginDependency + 374.IBEditorWindowLastContentRect + 374.IBPluginDependency + 375.IBPluginDependency + 376.IBPluginDependency + 377.IBPluginDependency + 378.IBPluginDependency + 379.IBPluginDependency + 380.IBPluginDependency + 381.IBPluginDependency + 382.IBPluginDependency + 383.IBPluginDependency + 384.IBPluginDependency + 385.IBPluginDependency + 386.IBEditorWindowLastContentRect + 386.IBPluginDependency + 387.IBPluginDependency + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 446.IBEditorWindowLastContentRect + 446.IBWindowTemplateEditedContentRect + 446.ImportedFromIB2 + 446.NSWindowTemplate.visibleAtLaunch + 446.editorWindowContentRectSynchronizationRect + 446.windowTemplate.hasMinSize + 446.windowTemplate.minSize + 447.IBPluginDependency + 447.ImportedFromIB2 + 448.IBPluginDependency + 449.IBPluginDependency + 450.IBPluginDependency + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 455.IBPluginDependency + 456.IBPluginDependency + 457.IBPluginDependency + 458.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 461.IBPluginDependency + 472.IBPluginDependency + 482.IBPluginDependency + 482.ImportedFromIB2 + 484.IBPluginDependency + 484.ImportedFromIB2 + 485.IBPluginDependency + 485.ImportedFromIB2 + 487.IBPluginDependency + 487.ImportedFromIB2 + 493.IBPluginDependency + 494.IBPluginDependency + 496.IBPluginDependency + 496.ImportedFromIB2 + 497.IBPluginDependency + 497.ImportedFromIB2 + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + {{524, 524}, {189, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{596, 852}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{817, 764}, {132, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{895, 584}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{652, 604}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{365, 632}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{895, 584}, {153, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{895, 584}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{812, -102}, {211, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{495, 1}, {449, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 977}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{762, 804}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{895, 584}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{696, 804}, {86, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{782, 564}, {178, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{88, 559}, {359, 258}} + {{88, 559}, {359, 258}} + + + {{201, 387}, {507, 413}} + + {359, 258} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{507, 664}, {218, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{610, 574}, {207, 273}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{323, 672}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 498 + + + + YES + + FirstResponder + NSObject + + openLocation: + id + + + IBUserSource + + + + + JSDemoAppDelegate + NSObject + + YES + + YES + collect: + goToLocation: + openLocation: + showConsole: + + + YES + id + id + id + id + + + + YES + + YES + comboBox + webView + window + + + YES + NSTextField + WebView + NSWindow + + + + IBProjectSource + jsdemoapp/JSDemoAppDelegate.h + + + + NSObject + + IBProjectSource + test/XMLReader.h + + + + + 0 + ../ParseKit.xcodeproj + 3 + + diff --git a/jsdemoapp/ParserTest.html b/jsdemoapp/ParserTest.html new file mode 100644 index 0000000..c0f7785 --- /dev/null +++ b/jsdemoapp/ParserTest.html @@ -0,0 +1,25 @@ + diff --git a/jsdemoapp/Test.html b/jsdemoapp/Test.html new file mode 100644 index 0000000..bdfe4eb --- /dev/null +++ b/jsdemoapp/Test.html @@ -0,0 +1,35 @@ + diff --git a/jsdemoapp/main.m b/jsdemoapp/main.m new file mode 100644 index 0000000..8aa7981 --- /dev/null +++ b/jsdemoapp/main.m @@ -0,0 +1,14 @@ +/* + * main.m + * TDParseKit + * + * Created by Todd Ditchendorf on 1/10/09. + * Copyright 2009 Todd Ditchendorf. All rights reserved. + * + */ + +#import + +int main(int argc, char *argv[]) { + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/jssrc/.svn/all-wcprops b/jssrc/.svn/all-wcprops new file mode 100644 index 0000000..6abcfa5 --- /dev/null +++ b/jssrc/.svn/all-wcprops @@ -0,0 +1,455 @@ +K 25 +svn:wc:ra_dav:version-url +V 30 +/svn/!svn/ver/1404/trunk/jssrc +END +PKJSWhitespaceState.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1123/trunk/jssrc/PKJSWhitespaceState.m +END +PKJSCommentState.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1123/trunk/jssrc/PKJSCommentState.h +END +PKJSQuoteState.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1123/trunk/jssrc/PKJSQuoteState.m +END +PKJSCommentState.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1123/trunk/jssrc/PKJSCommentState.m +END +PKJSCollectionParser.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1123/trunk/jssrc/PKJSCollectionParser.h +END +PKJSTokenizer.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1123/trunk/jssrc/PKJSTokenizer.h +END +PKJSValueHolder.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1121/trunk/jssrc/PKJSValueHolder.h +END +PKJSCollectionParser.m +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1123/trunk/jssrc/PKJSCollectionParser.m +END +PKJSPattern.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1123/trunk/jssrc/PKJSPattern.h +END +PKJSTokenizer.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1123/trunk/jssrc/PKJSTokenizer.m +END +PKJSValueHolder.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1121/trunk/jssrc/PKJSValueHolder.m +END +PKJSRepetition.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1123/trunk/jssrc/PKJSRepetition.h +END +PKJSPattern.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1190/trunk/jssrc/PKJSPattern.m +END +PKJSRepetition.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1123/trunk/jssrc/PKJSRepetition.m +END +JSParseKit.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1167/trunk/jssrc/JSParseKit.h +END +PKJSNumberState.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1123/trunk/jssrc/PKJSNumberState.h +END +JSParseKit.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1123/trunk/jssrc/JSParseKit.m +END +PKJSNumberState.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1123/trunk/jssrc/PKJSNumberState.m +END +PKJSUtils.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1123/trunk/jssrc/PKJSUtils.h +END +PKJSComment.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1123/trunk/jssrc/PKJSComment.h +END +PKJSTrack.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1123/trunk/jssrc/PKJSTrack.h +END +PKJSUtils.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1126/trunk/jssrc/PKJSUtils.m +END +PKJSSymbol.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1123/trunk/jssrc/PKJSSymbol.h +END +PKJSComment.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1123/trunk/jssrc/PKJSComment.m +END +PKJSTrack.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1123/trunk/jssrc/PKJSTrack.m +END +PKJSSymbol.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1123/trunk/jssrc/PKJSSymbol.m +END +PKJSAssemblerAdapter.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1276/trunk/jssrc/PKJSAssemblerAdapter.h +END +PKJSAssembly.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1121/trunk/jssrc/PKJSAssembly.h +END +PKJSAssemblerAdapter.m +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1383/trunk/jssrc/PKJSAssemblerAdapter.m +END +PKJSAssembly.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1123/trunk/jssrc/PKJSAssembly.m +END +PKJSAny.h +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1123/trunk/jssrc/PKJSAny.h +END +PKJSDelimitState.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1123/trunk/jssrc/PKJSDelimitState.h +END +PKJSQuotedString.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1123/trunk/jssrc/PKJSQuotedString.h +END +PKJSCharacterAssembly.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1122/trunk/jssrc/PKJSCharacterAssembly.h +END +PKJSLiteral.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1123/trunk/jssrc/PKJSLiteral.h +END +PKJSAny.m +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1123/trunk/jssrc/PKJSAny.m +END +PKJSDelimitState.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1123/trunk/jssrc/PKJSDelimitState.m +END +PKJSQuotedString.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1123/trunk/jssrc/PKJSQuotedString.m +END +PKJSEmpty.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1123/trunk/jssrc/PKJSEmpty.h +END +PKJSCharacterAssembly.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1404/trunk/jssrc/PKJSCharacterAssembly.m +END +PKJSLiteral.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1123/trunk/jssrc/PKJSLiteral.m +END +PKJSEmpty.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1123/trunk/jssrc/PKJSEmpty.m +END +PKJSUtils_macros.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1126/trunk/jssrc/PKJSUtils_macros.h +END +PKJSSequence.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1123/trunk/jssrc/PKJSSequence.h +END +PKJSTerminal.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1123/trunk/jssrc/PKJSTerminal.h +END +PKJSWord.h +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1123/trunk/jssrc/PKJSWord.h +END +PKJSWordState.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1123/trunk/jssrc/PKJSWordState.h +END +PKJSSequence.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1123/trunk/jssrc/PKJSSequence.m +END +PKJSWord.m +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1123/trunk/jssrc/PKJSWord.m +END +PKJSToken.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1123/trunk/jssrc/PKJSToken.h +END +PKJSTerminal.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1123/trunk/jssrc/PKJSTerminal.m +END +PKJSAlternation.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1123/trunk/jssrc/PKJSAlternation.h +END +PKJSWordState.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1123/trunk/jssrc/PKJSWordState.m +END +PKJSUppercaseWord.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1123/trunk/jssrc/PKJSUppercaseWord.h +END +PKJSAlternation.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1123/trunk/jssrc/PKJSAlternation.m +END +PKJSToken.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1123/trunk/jssrc/PKJSToken.m +END +PKJSUppercaseWord.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1123/trunk/jssrc/PKJSUppercaseWord.m +END +PKJSParser.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1123/trunk/jssrc/PKJSParser.h +END +PKJSNum.h +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1123/trunk/jssrc/PKJSNum.h +END +PKJSParser.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1276/trunk/jssrc/PKJSParser.m +END +PKJSNum.m +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1177/trunk/jssrc/PKJSNum.m +END +PKJSSymbolState.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1123/trunk/jssrc/PKJSSymbolState.h +END +PKJSCaseInsensitiveLiteral.h +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1123/trunk/jssrc/PKJSCaseInsensitiveLiteral.h +END +PKJSSymbolState.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1123/trunk/jssrc/PKJSSymbolState.m +END +PKJSTokenizerState.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1123/trunk/jssrc/PKJSTokenizerState.h +END +PKJSCaseInsensitiveLiteral.m +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1123/trunk/jssrc/PKJSCaseInsensitiveLiteral.m +END +PKJSLowercaseWord.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1123/trunk/jssrc/PKJSLowercaseWord.h +END +PKJSTokenAssembly.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1383/trunk/jssrc/PKJSTokenAssembly.h +END +PKJSTokenizerState.m +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1123/trunk/jssrc/PKJSTokenizerState.m +END +PKJSLowercaseWord.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1123/trunk/jssrc/PKJSLowercaseWord.m +END +PKJSTokenAssembly.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1404/trunk/jssrc/PKJSTokenAssembly.m +END +PKJSDelimitedString.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1123/trunk/jssrc/PKJSDelimitedString.h +END +PKJSDelimitedString.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1123/trunk/jssrc/PKJSDelimitedString.m +END +PKJSWhitespaceState.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1123/trunk/jssrc/PKJSWhitespaceState.h +END +PKJSQuoteState.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1123/trunk/jssrc/PKJSQuoteState.h +END diff --git a/jssrc/.svn/entries b/jssrc/.svn/entries new file mode 100644 index 0000000..1c24420 --- /dev/null +++ b/jssrc/.svn/entries @@ -0,0 +1,2578 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/jssrc +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +PKJSWhitespaceState.m +file + + + + +2009-06-30T07:08:45.000000Z +adc56d219f02635a02d7c8dec8248ae4 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4237 + +PKJSQuoteState.m +file + + + + +2009-06-30T07:08:45.000000Z +5b9e2e890e70292c046833580cf0a534 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2704 + +PKJSCommentState.h +file + + + + +2009-06-30T07:08:45.000000Z +073e85ebab7e87ed6ba2c264efdf29a8 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +438 + +PKJSCommentState.m +file + + + + +2009-06-30T07:08:45.000000Z +c03ab48282d5bf479bad9a0febc36f9f +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +5933 + +PKJSCollectionParser.h +file + + + + +2009-06-30T07:13:32.000000Z +d0f62099f9913227e79c8a1c9f3eeb21 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +324 + +PKJSValueHolder.h +file + + + + +2009-07-03T19:42:56.000000Z +e73b99e38d5f450df028817da89db67f +2009-06-30T06:58:43.669534Z +1121 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +471 + +PKJSTokenizer.h +file + + + + +2009-06-30T07:08:45.000000Z +43e7d6697a3a74cf9fd0b6f02634554f +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +426 + +PKJSPattern.h +file + + + + +2009-06-30T07:15:42.000000Z +d8848011010892483f8e5388c7b84ef1 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +418 + +PKJSCollectionParser.m +file + + + + +2009-06-30T07:13:32.000000Z +97113c6a18b2d8ffd561a302dd0e04da +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2017 + +PKJSValueHolder.m +file + + + + +2009-06-30T06:57:08.000000Z +11dd59ba02b5ef162338cd30194d8bba +2009-06-30T06:58:43.669534Z +1121 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +474 + +PKJSTokenizer.m +file + + + + +2009-06-30T07:08:45.000000Z +9ffc87db099cb31ba425a41586400a66 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +8639 + +PKJSPattern.m +file + + + + +2009-07-10T08:08:29.000000Z +58884de3ea9f1ab66ef04a08e3e4dd41 +2009-07-07T18:57:37.377581Z +1190 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2250 + +PKJSRepetition.h +file + + + + +2009-06-30T07:13:32.000000Z +24d6471ed6dce64d63e6056efdd53aed +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +431 + +JSParseKit.h +file + + + + +2009-07-03T19:23:18.000000Z +517a2a6d4e490d936272659d07125029 +2009-07-03T19:25:24.801046Z +1167 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +267 + +PKJSRepetition.m +file + + + + +2009-06-30T07:13:32.000000Z +48978e2c1f53486262f74ae95d0ad6e1 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1950 + +PKJSNumberState.h +file + + + + +2009-06-30T07:08:45.000000Z +52426bc24bd277801a3cbc45a8b63f66 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +434 + +JSParseKit.m +file + + + + +2009-06-30T07:09:16.000000Z +4441c898e9877ae10df239d54873bc20 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +5418 + +PKJSNumberState.m +file + + + + +2009-06-30T07:08:45.000000Z +2afae062d3ada0e74acde9fef4dd0c15 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2670 + +PKJSUtils.h +file + + + + +2009-06-30T07:17:10.000000Z +fb59dcee5ae773870ad825ef8ef67a6a +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1652 + +PKJSComment.h +file + + + + +2009-06-30T07:15:22.000000Z +c2f93ed49122daa284381da69d3f4309 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +419 + +PKJSTrack.h +file + + + + +2009-06-30T07:13:32.000000Z +64c983c98250bb63e0e5cb4e46285d64 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +411 + +PKJSUtils.m +file + + + + +2009-06-30T07:35:04.000000Z +94957eef18676ecf03d713fe1df6a2e2 +2009-06-30T07:36:06.027198Z +1126 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +8965 + +PKJSSymbol.h +file + + + + +2009-06-30T07:16:04.000000Z +0651c09a0041d95ce9c0f53715ef7cf5 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +415 + +PKJSComment.m +file + + + + +2009-06-30T07:15:26.000000Z +3a8eece7f2dc7e310c3f5c97678e3d34 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1559 + +PKJSTrack.m +file + + + + +2009-06-30T07:13:32.000000Z +ed12be85b7c1aa0d289aab064ddb85d9 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1523 + +PKJSSymbol.m +file + + + + +2009-06-30T07:16:09.000000Z +7ff5404cb2e9a10abc5ca362e31c5b9e +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1664 + +PKJSAssemblerAdapter.h +file + + + + +2009-08-06T04:02:07.000000Z +41444b77ab65e502ad261dfa5975ec62 +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +490 + +PKJSAssembly.h +file + + + + +2009-06-30T06:54:21.000000Z +7d076a8b90d542248e0438a20c488a9b +2009-06-30T06:58:43.669534Z +1121 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +291 + +PKJSAssemblerAdapter.m +file + + + + +2009-09-17T22:53:00.000000Z +0876d5e525e209c523981819686d8b38 +2009-09-17T22:53:43.141543Z +1383 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1804 + +PKJSAssembly.m +file + + + + +2009-06-30T07:17:10.000000Z +c073dd785dfdf060ceed60ebdbef66fe +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4956 + +PKJSAny.h +file + + + + +2009-06-30T07:13:32.000000Z +0a721c037aeaae98902e5d19798af107 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +403 + +PKJSDelimitState.h +file + + + + +2009-06-30T07:08:45.000000Z +3131de90921b550ba309112f0ae949f8 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +438 + +PKJSQuotedString.h +file + + + + +2009-06-30T07:15:52.000000Z +54559ff1843288776aa7e380480b2acb +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +439 + +PKJSLiteral.h +file + + + + +2009-06-30T07:14:30.000000Z +1ae3cdb21fd794f4a5cd29596e2119f9 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +417 + +PKJSAny.m +file + + + + +2009-06-30T07:13:32.000000Z +2f3fe0ad37a33d27649ad452c797324d +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1487 + +PKJSCharacterAssembly.h +file + + + + +2009-06-30T07:01:22.000000Z +de6166fbce0277034a66abcdb0a1af0a +2009-06-30T07:02:05.278274Z +1122 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +459 + +PKJSDelimitState.m +file + + + + +2009-06-30T07:08:45.000000Z +8d166674d8bb673ea4f2ca1025367748 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3460 + +PKJSQuotedString.m +file + + + + +2009-06-30T07:15:56.000000Z +443f24e549e932b8de7af7c44d4b71e2 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1649 + +PKJSEmpty.h +file + + + + +2009-06-30T07:13:32.000000Z +d599eea24b94f1ae78ec4677e7ee6bbe +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +411 + +PKJSLiteral.m +file + + + + +2009-06-30T07:14:35.000000Z +b8c7f96c54ed5313da0c5c933faba8a7 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1686 + +PKJSCharacterAssembly.m +file + + + + +2009-11-13T07:14:30.000000Z +af6c11d42ff67a1e6911a6f2c1cb353a +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +4512 + +PKJSEmpty.m +file + + + + +2009-06-30T07:13:32.000000Z +b548e62705c202ec338bef5c7cf9459b +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1523 + +PKJSUtils_macros.h +file + + + + +2009-06-30T07:35:04.000000Z +81964ff0c06ab7be038a562ebacb208f +2009-06-30T07:36:06.027198Z +1126 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1120 + +PKJSSequence.h +file + + + + +2009-06-30T07:13:32.000000Z +ce075c5b1704d409c15f7c07ff08c84b +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +423 + +PKJSWord.h +file + + + + +2009-06-30T07:16:24.000000Z +6e435c1fae3f746b2fb17e5519a8f3f3 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +407 + +PKJSTerminal.h +file + + + + +2009-06-30T07:13:32.000000Z +e5e99870da01e7cd64a8d44c9d579570 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +292 + +PKJSWordState.h +file + + + + +2009-06-30T07:08:45.000000Z +da748defc13e08b42a187e067a279950 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +426 + +PKJSSequence.m +file + + + + +2009-06-30T07:13:32.000000Z +9e8741ce982fc7943de8ef0936b4d142 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1593 + +PKJSAlternation.h +file + + + + +2009-06-30T07:13:32.000000Z +c7441a796cabb8bffaeadd8dffa6eb39 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +435 + +PKJSTerminal.m +file + + + + +2009-06-30T07:13:32.000000Z +e972f82db848466691a0ceb1cb269ccc +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1720 + +PKJSWord.m +file + + + + +2009-06-30T07:16:28.000000Z +14881f86c81a5d586f2ba01110ecce9b +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1505 + +PKJSToken.h +file + + + + +2009-06-30T07:08:45.000000Z +79d27ac328a7daed14f7a50df419698c +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +649 + +PKJSWordState.m +file + + + + +2009-06-30T07:08:45.000000Z +03825aa5d584a6e0574fd02867163ebe +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +3241 + +PKJSUppercaseWord.h +file + + + + +2009-06-30T07:16:15.000000Z +6f8b82179d901d9ea1ae6b4a5684617f +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +443 + +PKJSAlternation.m +file + + + + +2009-06-30T07:13:32.000000Z +e3ea1ab22f12e1d9f2fdc1ff901a1ec0 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1647 + +PKJSToken.m +file + + + + +2009-06-30T07:08:45.000000Z +8363cce72bd9809467308434898c713b +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +6242 + +PKJSUppercaseWord.m +file + + + + +2009-06-30T07:16:20.000000Z +dbdd2fc3f27ddd4a026de530f0de0d11 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1796 + +PKJSParser.h +file + + + + +2009-06-30T07:13:32.000000Z +72478186f6aa5b452d5b893dcd237769 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +286 + +PKJSNum.h +file + + + + +2009-06-30T07:14:50.000000Z +c4a8707715fa8fd4d2744ca0d9edc69a +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +403 + +PKJSParser.m +file + + + + +2009-08-06T04:02:08.000000Z +562faf8085c2bedfa9d5300330f11131 +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +5401 + +PKJSNum.m +file + + + + +2009-07-03T21:56:32.000000Z +9f057b786d8add8d57b488a5bef52bb4 +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1496 + +PKJSSymbolState.h +file + + + + +2009-06-30T07:08:45.000000Z +2ea7428cd99a7ab24a7050ecc546cc96 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +434 + +PKJSCaseInsensitiveLiteral.h +file + + + + +2009-06-30T07:15:31.000000Z +664f969300da66d28bd2e710eba46cc4 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +494 + +PKJSSymbolState.m +file + + + + +2009-06-30T07:08:45.000000Z +1abcbd7fd78d56408976f9da06ebd45d +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +3042 + +PKJSTokenizerState.h +file + + + + +2009-06-30T07:08:45.000000Z +a6c2c1a2afbc5b6e87f5a74acb49e52c +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +309 + +PKJSCaseInsensitiveLiteral.m +file + + + + +2009-06-30T07:15:36.000000Z +a5b6a57bc7a9375187a3b35a4c931ecd +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1990 + +PKJSLowercaseWord.h +file + + + + +2009-06-30T07:14:39.000000Z +a1bdd9ce5a21a2bb7f75eb16f13a144a +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +443 + +PKJSTokenAssembly.h +file + + + + +2009-09-17T22:51:52.000000Z +581ddb46340252ae15f37296cf8db65b +2009-09-17T22:53:43.141543Z +1383 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +442 + +PKJSTokenizerState.m +file + + + + +2009-06-30T07:08:45.000000Z +817e530605e37a92bef59e9a6e56b5eb +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1476 + +PKJSTokenAssembly.m +file + + + + +2009-11-13T07:14:30.000000Z +d498e42a3cb6c8eb9ed99e3206c2bcad +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4214 + +PKJSLowercaseWord.m +file + + + + +2009-06-30T07:14:46.000000Z +4abf12aa4dc2678b60feab6417d4eaf7 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1796 + +PKJSDelimitedString.h +file + + + + +2009-06-30T07:15:08.000000Z +022b65237cb0fdcda2a12de72b57e2a5 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +450 + +PKJSDelimitedString.m +file + + + + +2009-06-30T07:15:13.000000Z +1f3318390344b46ada8f50bed9415b76 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1841 + +PKJSWhitespaceState.h +file + + + + +2009-06-30T07:08:45.000000Z +2285fa200c75530cf8143a11e20d7d73 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +450 + +PKJSQuoteState.h +file + + + + +2009-06-30T07:08:45.000000Z +45558bd431ac406af8cb67ceee47c9a9 +2009-06-30T07:21:31.602960Z +1123 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +430 + diff --git a/jssrc/.svn/prop-base/JSParseKit.h.svn-base b/jssrc/.svn/prop-base/JSParseKit.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/JSParseKit.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/JSParseKit.m.svn-base b/jssrc/.svn/prop-base/JSParseKit.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/JSParseKit.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSAssembly.h.svn-base b/jssrc/.svn/prop-base/PKJSAssembly.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSAssembly.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSAssembly.m.svn-base b/jssrc/.svn/prop-base/PKJSAssembly.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSAssembly.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSCollectionParser.h.svn-base b/jssrc/.svn/prop-base/PKJSCollectionParser.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSCollectionParser.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSCollectionParser.m.svn-base b/jssrc/.svn/prop-base/PKJSCollectionParser.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSCollectionParser.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSCommentState.h.svn-base b/jssrc/.svn/prop-base/PKJSCommentState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSCommentState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSCommentState.m.svn-base b/jssrc/.svn/prop-base/PKJSCommentState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSCommentState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSNumberState.h.svn-base b/jssrc/.svn/prop-base/PKJSNumberState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSNumberState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSNumberState.m.svn-base b/jssrc/.svn/prop-base/PKJSNumberState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSNumberState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSQuoteState.h.svn-base b/jssrc/.svn/prop-base/PKJSQuoteState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSQuoteState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSQuoteState.m.svn-base b/jssrc/.svn/prop-base/PKJSQuoteState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSQuoteState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSSymbolState.h.svn-base b/jssrc/.svn/prop-base/PKJSSymbolState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSSymbolState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSSymbolState.m.svn-base b/jssrc/.svn/prop-base/PKJSSymbolState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSSymbolState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSToken.h.svn-base b/jssrc/.svn/prop-base/PKJSToken.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSToken.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSToken.m.svn-base b/jssrc/.svn/prop-base/PKJSToken.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSToken.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSTokenAssembly.h.svn-base b/jssrc/.svn/prop-base/PKJSTokenAssembly.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSTokenAssembly.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSTokenAssembly.m.svn-base b/jssrc/.svn/prop-base/PKJSTokenAssembly.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSTokenAssembly.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSTokenizer.h.svn-base b/jssrc/.svn/prop-base/PKJSTokenizer.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSTokenizer.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSTokenizer.m.svn-base b/jssrc/.svn/prop-base/PKJSTokenizer.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSTokenizer.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSTokenizerState.h.svn-base b/jssrc/.svn/prop-base/PKJSTokenizerState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSTokenizerState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSTokenizerState.m.svn-base b/jssrc/.svn/prop-base/PKJSTokenizerState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSTokenizerState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSUtils.h.svn-base b/jssrc/.svn/prop-base/PKJSUtils.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSUtils.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSUtils.m.svn-base b/jssrc/.svn/prop-base/PKJSUtils.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSUtils.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSValueHolder.h.svn-base b/jssrc/.svn/prop-base/PKJSValueHolder.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSValueHolder.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSValueHolder.m.svn-base b/jssrc/.svn/prop-base/PKJSValueHolder.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSValueHolder.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSWhitespaceState.h.svn-base b/jssrc/.svn/prop-base/PKJSWhitespaceState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSWhitespaceState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSWhitespaceState.m.svn-base b/jssrc/.svn/prop-base/PKJSWhitespaceState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSWhitespaceState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSWordState.h.svn-base b/jssrc/.svn/prop-base/PKJSWordState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSWordState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/prop-base/PKJSWordState.m.svn-base b/jssrc/.svn/prop-base/PKJSWordState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/jssrc/.svn/prop-base/PKJSWordState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/jssrc/.svn/text-base/JSParseKit.h.svn-base b/jssrc/.svn/text-base/JSParseKit.h.svn-base new file mode 100644 index 0000000..1c5bc19 --- /dev/null +++ b/jssrc/.svn/text-base/JSParseKit.h.svn-base @@ -0,0 +1,12 @@ +// +// JSParseKit.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/10/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +void PKJSParseKitSetUpContext(JSContextRef ctx); \ No newline at end of file diff --git a/jssrc/.svn/text-base/JSParseKit.m.svn-base b/jssrc/.svn/text-base/JSParseKit.m.svn-base new file mode 100644 index 0000000..546ff89 --- /dev/null +++ b/jssrc/.svn/text-base/JSParseKit.m.svn-base @@ -0,0 +1,116 @@ +// +// PKJSParseKit.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/10/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import "PKJSUtils.h" +#import "PKJSToken.h" +#import "PKJSTokenizer.h" +#import "PKJSTokenizerState.h" +#import "PKJSAssembly.h" +#import "PKJSTokenAssembly.h" +#import "PKJSCharacterAssembly.h" +#import "PKJSWordState.h" +#import "PKJSNumberState.h" +#import "PKJSWhitespaceState.h" +#import "PKJSCommentState.h" +#import "PKJSQuoteState.h" +#import "PKJSSymbolState.h" +#import "PKJSRepetition.h" +#import "PKJSSequence.h" +#import "PKJSTrack.h" +#import "PKJSAlternation.h" +#import "PKJSEmpty.h" +#import "PKJSAny.h" +#import "PKJSWord.h" +#import "PKJSNum.h" +#import "PKJSQuotedString.h" +#import "PKJSSymbol.h" +#import "PKJSComment.h" +#import "PKJSLiteral.h" +#import "PKJSCaseInsensitiveLiteral.h" +#import "PKJSUppercaseWord.h" +#import "PKJSLowercaseWord.h" + +static void printValue(JSContextRef ctx, JSValueRef val) { + NSString *s = PKJSValueGetNSString(ctx, val, NULL); + NSLog(@"%@", s); +} + +static JSValueRef print(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + printValue(ctx, argv[0]); // TODO check args + return JSValueMakeUndefined(ctx); +} + +static JSObjectRef setUpFunction(JSContextRef ctx, char *funcName, JSObjectCallAsFunctionCallback funcCallback, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef funcNameStr = JSStringCreateWithUTF8CString(funcName); + JSObjectRef func = JSObjectMakeFunctionWithCallback(ctx, funcNameStr, funcCallback); + JSObjectSetProperty(ctx, globalObj, funcNameStr, func, kJSPropertyAttributeNone, ex); + JSStringRelease(funcNameStr); + return func; +} + +static JSObjectRef setUpConstructor(JSContextRef ctx, char *className, JSClassRef jsClass, JSObjectCallAsConstructorCallback constrCallback, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef classNameStr = JSStringCreateWithUTF8CString(className); + JSObjectRef constr = JSObjectMakeConstructor(ctx, jsClass, constrCallback); + JSObjectSetProperty(ctx, globalObj, classNameStr, constr, kJSPropertyAttributeNone, ex); + JSStringRelease(classNameStr); + return constr; +} + +static void setUpClassProperty(JSContextRef ctx, char *propName, JSValueRef prop, JSObjectRef constr, JSValueRef *ex) { + JSStringRef propNameStr = JSStringCreateWithUTF8CString(propName); + JSObjectSetProperty(ctx, constr, propNameStr, prop, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly, NULL); + JSStringRelease(propNameStr); +} + +void PKJSParseKitSetUpContext(JSContextRef ctx) { + JSValueRef ex = NULL; + + setUpFunction(ctx, "print", print, &ex); + + // Assemblies + setUpConstructor(ctx, "PKTokenAssembly", PKTokenAssembly_class(ctx), PKTokenAssembly_construct, &ex); + setUpConstructor(ctx, "PKCharacterAssembly", PKCharacterAssembly_class(ctx), PKCharacterAssembly_construct, &ex); + + // Tokenization + JSObjectRef constr = setUpConstructor(ctx, "PKToken", PKToken_class(ctx), PKToken_construct, &ex); + setUpClassProperty(ctx, "EOFToken", PKToken_getEOFToken(ctx), constr, &ex); // Class property on Token constructor + + setUpConstructor(ctx, "PKTokenizer", PKTokenizer_class(ctx), PKTokenizer_construct, &ex); + setUpConstructor(ctx, "PKWordState", PKWordState_class(ctx), PKWordState_construct, &ex); + setUpConstructor(ctx, "PKQuoteState", PKQuoteState_class(ctx), PKQuoteState_construct, &ex); + setUpConstructor(ctx, "PKNumberState", PKNumberState_class(ctx), PKNumberState_construct, &ex); + setUpConstructor(ctx, "PKSymbolState", PKSymbolState_class(ctx), PKSymbolState_construct, &ex); + setUpConstructor(ctx, "PKCommentState", PKCommentState_class(ctx), PKCommentState_construct, &ex); + setUpConstructor(ctx, "PKWhitespaceState", PKWhitespaceState_class(ctx), PKWhitespaceState_construct, &ex); + + // Parsers + setUpConstructor(ctx, "PKRepetition", PKRepetition_class(ctx), PKRepetition_construct, &ex); + + // Collection Parsers + setUpConstructor(ctx, "PKAlternation", PKAlternation_class(ctx), PKAlternation_construct, &ex); + setUpConstructor(ctx, "PKSequence", PKSequence_class(ctx), PKSequence_construct, &ex); + + // Terminal Parsers + setUpConstructor(ctx, "PKEmpty", PKEmpty_class(ctx), PKEmpty_construct, &ex); + setUpConstructor(ctx, "PKAny", PKAny_class(ctx), PKAny_construct, &ex); + + // Token Terminals + setUpConstructor(ctx, "PKWord", PKWord_class(ctx), PKWord_construct, &ex); + setUpConstructor(ctx, "PKNum", PKNum_class(ctx), PKNum_construct, &ex); + setUpConstructor(ctx, "PKQuotedString", PKQuotedString_class(ctx), PKQuotedString_construct, &ex); + setUpConstructor(ctx, "PKSymbol", PKSymbol_class(ctx), PKSymbol_construct, &ex); + setUpConstructor(ctx, "PKComment", PKComment_class(ctx), PKComment_construct, &ex); + setUpConstructor(ctx, "PKLiteral", PKLiteral_class(ctx), PKLiteral_construct, &ex); + setUpConstructor(ctx, "PKCaseInsensitiveLiteral", PKCaseInsensitiveLiteral_class(ctx), PKCaseInsensitiveLiteral_construct, &ex); + setUpConstructor(ctx, "PKUppercaseWord", PKUppercaseWord_class(ctx), PKUppercaseWord_construct, &ex); + setUpConstructor(ctx, "PKLowercaseWord", PKLowercaseWord_class(ctx), PKLowercaseWord_construct, &ex); +} diff --git a/jssrc/.svn/text-base/PKJSAlternation.h.svn-base b/jssrc/.svn/text-base/PKJSAlternation.h.svn-base new file mode 100644 index 0000000..8cbdff4 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSAlternation.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSAlternation.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKAlternation_new(JSContextRef ctx, void *data); +JSClassRef PKAlternation_class(JSContextRef ctx); +JSObjectRef PKAlternation_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSAlternation.m.svn-base b/jssrc/.svn/text-base/PKJSAlternation.m.svn-base new file mode 100644 index 0000000..4440d87 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSAlternation.m.svn-base @@ -0,0 +1,63 @@ +// +// PKJSAlternation.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSAlternation.h" +#import "PKJSUtils.h" +#import "PKJSCollectionParser.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKAlternation_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKAlternation_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKAlternation_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKAlternation_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKAlternation_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKCollectionParser_class(ctx); + def.staticFunctions = PKAlternation_staticFunctions; + def.staticValues = PKAlternation_staticValues; + def.initialize = PKAlternation_initialize; + def.finalize = PKAlternation_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKAlternation_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKAlternation_class(ctx), data); +} + +JSObjectRef PKAlternation_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKAlternation *data = [[PKAlternation alloc] init]; + return PKAlternation_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSAny.h.svn-base b/jssrc/.svn/text-base/PKJSAny.h.svn-base new file mode 100644 index 0000000..5f9f8ea --- /dev/null +++ b/jssrc/.svn/text-base/PKJSAny.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSAny.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKAny_new(JSContextRef ctx, void *data); +JSClassRef PKAny_class(JSContextRef ctx); +JSObjectRef PKAny_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSAny.m.svn-base b/jssrc/.svn/text-base/PKJSAny.m.svn-base new file mode 100644 index 0000000..2c0331c --- /dev/null +++ b/jssrc/.svn/text-base/PKJSAny.m.svn-base @@ -0,0 +1,63 @@ +// +// PKJSAny.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSAny.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKAny_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKAny_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKAny_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKAny_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKAny_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKAny_staticFunctions; + def.staticValues = PKAny_staticValues; + def.initialize = PKAny_initialize; + def.finalize = PKAny_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKAny_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKAny_class(ctx), data); +} + +JSObjectRef PKAny_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKAny *data = [[PKAny alloc] init]; + return PKAny_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSAssemblerAdapter.h.svn-base b/jssrc/.svn/text-base/PKJSAssemblerAdapter.h.svn-base new file mode 100644 index 0000000..a63dd2f --- /dev/null +++ b/jssrc/.svn/text-base/PKJSAssemblerAdapter.h.svn-base @@ -0,0 +1,22 @@ +// +// PKJSAssemblerAdapter.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/10/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class PKAssembly; + +@interface PKJSAssemblerAdapter : NSObject { + JSContextRef ctx; + JSObjectRef assemblerFunction; +} +- (void)didMatch:(PKAssembly *)a; + +- (JSObjectRef)assemblerFunction; +- (void)setAssemblerFunction:(JSObjectRef)f fromContext:(JSContextRef)c; +@end diff --git a/jssrc/.svn/text-base/PKJSAssemblerAdapter.m.svn-base b/jssrc/.svn/text-base/PKJSAssemblerAdapter.m.svn-base new file mode 100644 index 0000000..65b07df --- /dev/null +++ b/jssrc/.svn/text-base/PKJSAssemblerAdapter.m.svn-base @@ -0,0 +1,74 @@ +// +// PKJSAssemblerAdapter.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/10/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSAssemblerAdapter.h" +#import "PKJSTokenAssembly.h" +#import "PKJSCharacterAssembly.h" +#import "PKJSUtils.h" +#import +#import +#import + +@implementation PKJSAssemblerAdapter + +- (id)init { + if (self = [super init]) { + + } + return self; +} + + +- (void)dealloc { + [self setAssemblerFunction:NULL fromContext:NULL]; + [super dealloc]; +} + + +- (void)didMatch:(PKAssembly *)a { + JSValueRef arg = NULL; + if ([a isMemberOfClass:[PKTokenAssembly class]]) { + arg = (JSValueRef)PKTokenAssembly_new(ctx, a); + } else if ([a isMemberOfClass:[PKCharacterAssembly class]]) { + arg = (JSValueRef)PKCharacterAssembly_new(ctx, a); + } else { + NSAssert(0, @"Should not reach here."); + } + + JSValueRef argv[] = { arg }; + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSValueRef ex = NULL; + JSObjectCallAsFunction(ctx, assemblerFunction, globalObj, 1, argv, &ex); + if (ex) { + NSString *s = PKJSValueGetNSString(ctx, ex, NULL); + [NSException raise:@"PKJSException" format:s arguments:NULL]; + } +} + + +- (JSObjectRef)assemblerFunction { + return assemblerFunction; +} + + +- (void)setAssemblerFunction:(JSObjectRef)f fromContext:(JSContextRef)c { + if (assemblerFunction != f) { + if (ctx && assemblerFunction) { + JSValueUnprotect(ctx, assemblerFunction); + JSGarbageCollect(ctx); + } + + ctx = c; + assemblerFunction = f; + if (ctx && assemblerFunction) { + JSValueProtect(ctx, assemblerFunction); + } + } +} + +@end diff --git a/jssrc/.svn/text-base/PKJSAssembly.h.svn-base b/jssrc/.svn/text-base/PKJSAssembly.h.svn-base new file mode 100644 index 0000000..f329032 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSAssembly.h.svn-base @@ -0,0 +1,12 @@ +// +// PKJSAssembly.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/3/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKAssembly_new(JSContextRef ctx, void *data); +JSClassRef PKAssembly_class(JSContextRef ctx); diff --git a/jssrc/.svn/text-base/PKJSAssembly.m.svn-base b/jssrc/.svn/text-base/PKJSAssembly.m.svn-base new file mode 100644 index 0000000..30e0444 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSAssembly.m.svn-base @@ -0,0 +1,136 @@ +// +// PKJSAssembly.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/3/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSAssembly.h" +#import "PKJSToken.h" +#import "PKJSUtils.h" +#import +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKAssembly_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKAssembly_class, "toString"); + PKAssembly *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, [data description], ex); +} + +static JSValueRef PKAssembly_pop(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKAssembly_class, "pop"); + + PKAssembly *data = JSObjectGetPrivate(this); + PKToken *tok = [data pop]; + return PKToken_new(ctx, tok); +} + +static JSValueRef PKAssembly_push(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKAssembly_class, "push"); + PKPreconditionMethodArgc(1, "PKAssembly.push"); + + JSValueRef v = argv[0]; + + PKAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + [data push:obj]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKAssembly_objectsAbove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKAssembly_class, "objectsAbove"); + PKPreconditionMethodArgc(1, "PKAssembly.objectsAbove"); + + JSValueRef v = argv[0]; + + PKAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + id array = [data objectsAbove:obj]; + + return PKNSArrayToJSObject(ctx, array, ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKAssembly_getDefaultDelimiter(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, data.defaultDelimiter, ex); +} + +static JSValueRef PKAssembly_getStack(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + return PKNSArrayToJSObject(ctx, data.stack, ex); +} + +static JSValueRef PKAssembly_getTarget(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + return PKCFTypeToJSValue(ctx, (CFTypeRef)data.target, ex); +} + +static bool PKAssembly_setTarget(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + data.target = PKJSValueGetId(ctx, value, ex); + return true; +} + +static JSValueRef PKAssembly_getIsStackEmpty(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isStackEmpty); +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKAssembly_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKAssembly_finalize(JSObjectRef this) { + PKAssembly *data = (PKAssembly *)JSObjectGetPrivate(this); + [data autorelease]; +} + +static JSStaticFunction PKAssembly_staticFunctions[] = { +{ "toString", PKAssembly_toString, kJSPropertyAttributeDontDelete }, +{ "pop", PKAssembly_pop, kJSPropertyAttributeDontDelete }, +{ "push", PKAssembly_push, kJSPropertyAttributeDontDelete }, +{ "objectsAbove", PKAssembly_objectsAbove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKAssembly_staticValues[] = { +{ "defaulDelimiter", PKAssembly_getDefaultDelimiter, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // String +{ "stack", PKAssembly_getStack, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Array +{ "target", PKAssembly_getTarget, PKAssembly_setTarget, kJSPropertyAttributeDontDelete }, // Object +{ "isStackEmpty", PKAssembly_getIsStackEmpty, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark ClassMethods + +#pragma mark - +#pragma mark Public + +JSClassRef PKAssembly_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKAssembly_staticFunctions; + def.staticValues = PKAssembly_staticValues; + def.initialize = PKAssembly_initialize; + def.finalize = PKAssembly_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKAssembly_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKAssembly_class(ctx), data); +} diff --git a/jssrc/.svn/text-base/PKJSCaseInsensitiveLiteral.h.svn-base b/jssrc/.svn/text-base/PKJSCaseInsensitiveLiteral.h.svn-base new file mode 100644 index 0000000..c6e1794 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSCaseInsensitiveLiteral.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSCaseInsensitiveCaseInsensitiveLiteral.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKCaseInsensitiveLiteral_new(JSContextRef ctx, void *data); +JSClassRef PKCaseInsensitiveLiteral_class(JSContextRef ctx); +JSObjectRef PKCaseInsensitiveLiteral_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSCaseInsensitiveLiteral.m.svn-base b/jssrc/.svn/text-base/PKJSCaseInsensitiveLiteral.m.svn-base new file mode 100644 index 0000000..bfc6f3b --- /dev/null +++ b/jssrc/.svn/text-base/PKJSCaseInsensitiveLiteral.m.svn-base @@ -0,0 +1,67 @@ +// +// PKJSCaseInsensitiveCaseInsensitiveLiteral.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSCaseInsensitiveLiteral.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKCaseInsensitiveLiteral_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKCaseInsensitiveLiteral_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKCaseInsensitiveLiteral_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKCaseInsensitiveLiteral_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKCaseInsensitiveLiteral_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKCaseInsensitiveLiteral_staticFunctions; + def.staticValues = PKCaseInsensitiveLiteral_staticValues; + def.initialize = PKCaseInsensitiveLiteral_initialize; + def.finalize = PKCaseInsensitiveLiteral_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKCaseInsensitiveLiteral_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKCaseInsensitiveLiteral_class(ctx), data); +} + +JSObjectRef PKCaseInsensitiveLiteral_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKCaseInsensitiveLiteral"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKCaseInsensitiveLiteral *data = [[PKCaseInsensitiveLiteral alloc] initWithString:s]; + return PKCaseInsensitiveLiteral_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSCharacterAssembly.h.svn-base b/jssrc/.svn/text-base/PKJSCharacterAssembly.h.svn-base new file mode 100644 index 0000000..0d8cf5a --- /dev/null +++ b/jssrc/.svn/text-base/PKJSCharacterAssembly.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSCharacterAssembly.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKCharacterAssembly_new(JSContextRef ctx, void *data); +JSClassRef PKCharacterAssembly_class(JSContextRef ctx); +JSObjectRef PKCharacterAssembly_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSCharacterAssembly.m.svn-base b/jssrc/.svn/text-base/PKJSCharacterAssembly.m.svn-base new file mode 100644 index 0000000..83a2db9 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSCharacterAssembly.m.svn-base @@ -0,0 +1,123 @@ +// +// PKJSCharacterAssembly.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSCharacterAssembly.h" +#import "PKJSUtils.h" +#import "PKJSAssembly.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKCharacterAssembly_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCharacterAssembly_class, "toString"); + PKCharacterAssembly *data = JSObjectGetPrivate(this); + JSStringRef resStr = JSStringCreateWithCFString((CFStringRef)[data description]); + JSValueRef res = JSValueMakeString(ctx, resStr); + JSStringRelease(resStr); + return res; +} + +static JSValueRef PKCharacterAssembly_pop(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCharacterAssembly_class, "pop"); + PKCharacterAssembly *data = JSObjectGetPrivate(this); + NSNumber *obj = [data pop]; + return JSValueMakeNumber(ctx, [obj doubleValue]); +} + +static JSValueRef PKCharacterAssembly_push(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCharacterAssembly_class, "push"); + PKPreconditionMethodArgc(1, "PKCharacterAssembly.push"); + + JSValueRef v = argv[0]; + + PKCharacterAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + [data push:obj]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKCharacterAssembly_objectsAbove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCharacterAssembly_class, "objectsAbove"); + PKPreconditionMethodArgc(1, "PKCharacterAssembly.objectsAbove"); + + JSValueRef v = argv[0]; + + PKCharacterAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + id array = [data objectsAbove:obj]; + + return PKNSArrayToJSObject(ctx, array, ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKCharacterAssembly_getLength(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKCharacterAssembly *data = JSObjectGetPrivate(this); + return JSValueMakeNumber(ctx, [data length]); +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKCharacterAssembly_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKCharacterAssembly_finalize(JSObjectRef this) { + // released in PKAssembly_finalize +} + +static JSStaticFunction PKCharacterAssembly_staticFunctions[] = { +{ "toString", PKCharacterAssembly_toString, kJSPropertyAttributeDontDelete }, +{ "pop", PKCharacterAssembly_pop, kJSPropertyAttributeDontDelete }, +{ "push", PKCharacterAssembly_push, kJSPropertyAttributeDontDelete }, +{ "objectsAbove", PKCharacterAssembly_objectsAbove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKCharacterAssembly_staticValues[] = { +{ "length", PKCharacterAssembly_getLength, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Number +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark ClassMethods + +#pragma mark - +#pragma mark Public + +JSClassRef PKCharacterAssembly_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKAssembly_class(ctx); + def.staticFunctions = PKCharacterAssembly_staticFunctions; + def.staticValues = PKCharacterAssembly_staticValues; + def.initialize = PKCharacterAssembly_initialize; + def.finalize = PKCharacterAssembly_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKCharacterAssembly_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKCharacterAssembly_class(ctx), data); +} + +JSObjectRef PKCharacterAssembly_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKCharacterAssembly"); + + JSValueRef s = argv[0]; + NSString *string = PKJSValueGetNSString(ctx, s, ex); + + PKCharacterAssembly *data = [[PKCharacterAssembly alloc] initWithString:string]; + return PKCharacterAssembly_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSCollectionParser.h.svn-base b/jssrc/.svn/text-base/PKJSCollectionParser.h.svn-base new file mode 100644 index 0000000..38fbbd0 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSCollectionParser.h.svn-base @@ -0,0 +1,12 @@ +// +// PKCollectionCollectionParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKCollectionParser_new(JSContextRef ctx, void *data); +JSClassRef PKCollectionParser_class(JSContextRef ctx); diff --git a/jssrc/.svn/text-base/PKJSCollectionParser.m.svn-base b/jssrc/.svn/text-base/PKJSCollectionParser.m.svn-base new file mode 100644 index 0000000..721d149 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSCollectionParser.m.svn-base @@ -0,0 +1,71 @@ +// +// PKCollectionCollectionParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKCollectionParser.h" +#import "PKJSUtils.h" +#import "PKJSParser.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKCollectionParser_add(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCollectionParser_class, "add"); + PKPreconditionMethodArgc(1, "add"); + + PKCollectionParser *data = JSObjectGetPrivate(this); + + JSObjectRef arg = (JSObjectRef)argv[0]; + PKParser *p = (PKParser *)JSObjectGetPrivate(arg); + [data add:p]; + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKCollectionParser_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKCollectionParser_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKCollectionParser_staticFunctions[] = { +{ "add", PKCollectionParser_add, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKCollectionParser_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKCollectionParser_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKParser_class(ctx); + def.staticFunctions = PKCollectionParser_staticFunctions; + def.staticValues = PKCollectionParser_staticValues; + def.initialize = PKCollectionParser_initialize; + def.finalize = PKCollectionParser_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKCollectionParser_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKCollectionParser_class(ctx), data); +} diff --git a/jssrc/.svn/text-base/PKJSComment.h.svn-base b/jssrc/.svn/text-base/PKJSComment.h.svn-base new file mode 100644 index 0000000..c8620b2 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSComment.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSComment.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKComment_new(JSContextRef ctx, void *data); +JSClassRef PKComment_class(JSContextRef ctx); +JSObjectRef PKComment_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSComment.m.svn-base b/jssrc/.svn/text-base/PKJSComment.m.svn-base new file mode 100644 index 0000000..0659589 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSComment.m.svn-base @@ -0,0 +1,63 @@ +// +// PKJSComment.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSComment.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKComment_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKComment_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKComment_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKComment_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKComment_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKComment_staticFunctions; + def.staticValues = PKComment_staticValues; + def.initialize = PKComment_initialize; + def.finalize = PKComment_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKComment_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKComment_class(ctx), data); +} + +JSObjectRef PKComment_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKComment *data = [[PKComment alloc] init]; + return PKComment_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSCommentState.h.svn-base b/jssrc/.svn/text-base/PKJSCommentState.h.svn-base new file mode 100644 index 0000000..64b81bd --- /dev/null +++ b/jssrc/.svn/text-base/PKJSCommentState.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSCommentState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKCommentState_new(JSContextRef ctx, void *data); +JSClassRef PKCommentState_class(JSContextRef ctx); +JSObjectRef PKCommentState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSCommentState.m.svn-base b/jssrc/.svn/text-base/PKJSCommentState.m.svn-base new file mode 100644 index 0000000..7c76e54 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSCommentState.m.svn-base @@ -0,0 +1,147 @@ +// +// PKJSCommentState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSCommentState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKCommentState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKCommentState]", ex); +} + +static JSValueRef PKCommentState_addSingleLine(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "addSingleLine"); + PKPreconditionMethodArgc(1, "PKCommentState.addSingleLine"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + + PKCommentState *data = JSObjectGetPrivate(this); + [data addSingleLineStartMarker:start]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKCommentState_removeSingleLine(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "removeSingleLine"); + PKPreconditionMethodArgc(1, "PKCommentState.removeSingleLine"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + + PKCommentState *data = JSObjectGetPrivate(this); + [data removeSingleLineStartMarker:start]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKCommentState_addMultiLine(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "addMultiLine"); + PKPreconditionMethodArgc(2, "PKCommentState.addMultiLine"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + NSString *end = PKJSValueGetNSString(ctx, argv[1], ex); + + PKCommentState *data = JSObjectGetPrivate(this); + [data addMultiLineStartMarker:start endMarker:end]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKCommentState_removeMultiLine(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "removeSingleLine"); + PKPreconditionMethodArgc(1, "PKCommentState.removeMultiLine"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + + PKCommentState *data = JSObjectGetPrivate(this); + [data removeMultiLineStartMarker:start]; + + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKCommentState_getReportsCommentTokens(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKCommentState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.reportsCommentTokens); +} + +static bool PKCommentState_setReportsCommentTokens(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKCommentState *data = JSObjectGetPrivate(this); + data.reportsCommentTokens = JSValueToBoolean(ctx, value); + return true; +} + +static JSValueRef PKCommentState_getBalancesEOFTerminatedComments(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKCommentState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.balancesEOFTerminatedComments); +} + +static bool PKCommentState_setBalancesEOFTerminatedComments(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKCommentState *data = JSObjectGetPrivate(this); + data.balancesEOFTerminatedComments = JSValueToBoolean(ctx, value); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKCommentState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKCommentState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKCommentState_staticFunctions[] = { +{ "toString", PKCommentState_toString, kJSPropertyAttributeDontDelete }, +{ "addSingleLine", PKCommentState_addSingleLine, kJSPropertyAttributeDontDelete }, +{ "removeSingleLine", PKCommentState_removeSingleLine, kJSPropertyAttributeDontDelete }, +{ "addMultiLine", PKCommentState_addMultiLine, kJSPropertyAttributeDontDelete }, +{ "removeMultiLine", PKCommentState_removeMultiLine, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + + +static JSStaticValue PKCommentState_staticValues[] = { +{ "reportsCommentTokens", PKCommentState_getReportsCommentTokens, PKCommentState_setReportsCommentTokens, kJSPropertyAttributeDontDelete }, // Boolean +{ "balancesEOFTerminatedComments", PKCommentState_getBalancesEOFTerminatedComments, PKCommentState_setBalancesEOFTerminatedComments, kJSPropertyAttributeDontDelete }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKCommentState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKCommentState_staticFunctions; + def.staticValues = PKCommentState_staticValues; + def.initialize = PKCommentState_initialize; + def.finalize = PKCommentState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKCommentState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKCommentState_class(ctx), data); +} + +JSObjectRef PKCommentState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKCommentState *data = [[PKCommentState alloc] init]; + return PKCommentState_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSDelimitState.h.svn-base b/jssrc/.svn/text-base/PKJSDelimitState.h.svn-base new file mode 100644 index 0000000..7df505c --- /dev/null +++ b/jssrc/.svn/text-base/PKJSDelimitState.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSDelimitState.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/1/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKDelimitState_new(JSContextRef ctx, void *data); +JSClassRef PKDelimitState_class(JSContextRef ctx); +JSObjectRef PKDelimitState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSDelimitState.m.svn-base b/jssrc/.svn/text-base/PKJSDelimitState.m.svn-base new file mode 100644 index 0000000..d591bda --- /dev/null +++ b/jssrc/.svn/text-base/PKJSDelimitState.m.svn-base @@ -0,0 +1,102 @@ +// +// PKJSDelimitState.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/1/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSDelimitState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKDelimitState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKDelimitState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKDelimitState]", ex); +} + +static JSValueRef PKDelimitState_add(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKDelimitState_class, "add"); + PKPreconditionMethodArgc(4, "PKDelimitState.add"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + NSString *end = PKJSValueGetNSString(ctx, argv[1], ex); + NSString *chars = PKJSValueGetNSString(ctx, argv[2], ex); + BOOL invert = JSValueToBoolean(ctx, argv[3]); + + PKDelimitState *data = JSObjectGetPrivate(this); + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:chars]; + if (invert) { + cs = [cs invertedSet]; + } + [data addStartMarker:start endMarker:end allowedCharacterSet:cs]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKDelimitState_remove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKDelimitState_class, "remove"); + PKPreconditionMethodArgc(1, "PKDelimitState.remove"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + + PKDelimitState *data = JSObjectGetPrivate(this); + [data removeStartMarker:start]; + + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKDelimitState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKDelimitState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKDelimitState_staticFunctions[] = { +{ "toString", PKDelimitState_toString, kJSPropertyAttributeDontDelete }, +{ "add", PKDelimitState_add, kJSPropertyAttributeDontDelete }, +{ "remove", PKDelimitState_remove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKDelimitState_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKDelimitState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKDelimitState_staticFunctions; + def.staticValues = PKDelimitState_staticValues; + def.initialize = PKDelimitState_initialize; + def.finalize = PKDelimitState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKDelimitState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKDelimitState_class(ctx), data); +} + +JSObjectRef PKDelimitState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKDelimitState *data = [[PKDelimitState alloc] init]; + return PKDelimitState_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSDelimitedString.h.svn-base b/jssrc/.svn/text-base/PKJSDelimitedString.h.svn-base new file mode 100644 index 0000000..7a7fb3e --- /dev/null +++ b/jssrc/.svn/text-base/PKJSDelimitedString.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSDelimitedString.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/1/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKDelimitedString_new(JSContextRef ctx, void *data); +JSClassRef PKDelimitedString_class(JSContextRef ctx); +JSObjectRef PKDelimitedString_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSDelimitedString.m.svn-base b/jssrc/.svn/text-base/PKJSDelimitedString.m.svn-base new file mode 100644 index 0000000..aec66a4 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSDelimitedString.m.svn-base @@ -0,0 +1,67 @@ +// +// PKJSDelimitedString.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/1/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSDelimitedString.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKDelimitedString_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKDelimitedString_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKDelimitedString_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKDelimitedString_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKDelimitedString_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKDelimitedString_staticFunctions; + def.staticValues = PKDelimitedString_staticValues; + def.initialize = PKDelimitedString_initialize; + def.finalize = PKDelimitedString_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKDelimitedString_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKDelimitedString_class(ctx), data); +} + +JSObjectRef PKDelimitedString_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKDelimitedString"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKDelimitedString *data = [[PKDelimitedString alloc] initWithString:s]; + return PKDelimitedString_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSEmpty.h.svn-base b/jssrc/.svn/text-base/PKJSEmpty.h.svn-base new file mode 100644 index 0000000..0dd2a98 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSEmpty.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSEmpty.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKEmpty_new(JSContextRef ctx, void *data); +JSClassRef PKEmpty_class(JSContextRef ctx); +JSObjectRef PKEmpty_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSEmpty.m.svn-base b/jssrc/.svn/text-base/PKJSEmpty.m.svn-base new file mode 100644 index 0000000..b7ffdc4 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSEmpty.m.svn-base @@ -0,0 +1,63 @@ +// +// PKJSEmpty.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSEmpty.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKEmpty_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKEmpty_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKEmpty_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKEmpty_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKEmpty_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKEmpty_staticFunctions; + def.staticValues = PKEmpty_staticValues; + def.initialize = PKEmpty_initialize; + def.finalize = PKEmpty_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKEmpty_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKEmpty_class(ctx), data); +} + +JSObjectRef PKEmpty_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKEmpty *data = [[PKEmpty alloc] init]; + return PKEmpty_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSLiteral.h.svn-base b/jssrc/.svn/text-base/PKJSLiteral.h.svn-base new file mode 100644 index 0000000..bb34f68 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSLiteral.h.svn-base @@ -0,0 +1,13 @@ +// +// PKLiteral.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKLiteral_new(JSContextRef ctx, void *data); +JSClassRef PKLiteral_class(JSContextRef ctx); +JSObjectRef PKLiteral_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSLiteral.m.svn-base b/jssrc/.svn/text-base/PKJSLiteral.m.svn-base new file mode 100644 index 0000000..f3d0375 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSLiteral.m.svn-base @@ -0,0 +1,67 @@ +// +// PKLiteral.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKLiteral.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKLiteral_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKLiteral_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKLiteral_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKLiteral_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKLiteral_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKLiteral_staticFunctions; + def.staticValues = PKLiteral_staticValues; + def.initialize = PKLiteral_initialize; + def.finalize = PKLiteral_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKLiteral_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKLiteral_class(ctx), data); +} + +JSObjectRef PKLiteral_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKLiteral"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKLiteral *data = [[PKLiteral alloc] initWithString:s]; + return PKLiteral_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSLowercaseWord.h.svn-base b/jssrc/.svn/text-base/PKJSLowercaseWord.h.svn-base new file mode 100644 index 0000000..845625f --- /dev/null +++ b/jssrc/.svn/text-base/PKJSLowercaseWord.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSLowercaseWord.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/13/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKLowercaseWord_new(JSContextRef ctx, void *data); +JSClassRef PKLowercaseWord_class(JSContextRef ctx); +JSObjectRef PKLowercaseWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSLowercaseWord.m.svn-base b/jssrc/.svn/text-base/PKJSLowercaseWord.m.svn-base new file mode 100644 index 0000000..ce8e265 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSLowercaseWord.m.svn-base @@ -0,0 +1,67 @@ +// +// PKJSLowercaseWord.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/13/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSLowercaseWord.h" +#import "PKJSUtils.h" +#import "PKJSWord.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKLowercaseWord_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKLowercaseWord_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKLowercaseWord_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKLowercaseWord_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKLowercaseWord_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKWord_class(ctx); + def.staticFunctions = PKLowercaseWord_staticFunctions; + def.staticValues = PKLowercaseWord_staticValues; + def.initialize = PKLowercaseWord_initialize; + def.finalize = PKLowercaseWord_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKLowercaseWord_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKLowercaseWord_class(ctx), data); +} + +JSObjectRef PKLowercaseWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKLowercaseWord"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKLowercaseWord *data = [[PKLowercaseWord alloc] initWithString:s]; + return PKLowercaseWord_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSNum.h.svn-base b/jssrc/.svn/text-base/PKJSNum.h.svn-base new file mode 100644 index 0000000..edd4609 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSNum.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSNum.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKNum_new(JSContextRef ctx, void *data); +JSClassRef PKNum_class(JSContextRef ctx); +JSObjectRef PKNum_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSNum.m.svn-base b/jssrc/.svn/text-base/PKJSNum.m.svn-base new file mode 100644 index 0000000..023905a --- /dev/null +++ b/jssrc/.svn/text-base/PKJSNum.m.svn-base @@ -0,0 +1,63 @@ +// +// PKJSNum.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSNum.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKNum_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKNum_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKNum_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKNum_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKNum_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKNum_staticFunctions; + def.staticValues = PKNum_staticValues; + def.initialize = PKNum_initialize; + def.finalize = PKNum_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKNum_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKNum_class(ctx), data); +} + +JSObjectRef PKNum_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKNumber *data = [[PKNumber alloc] init]; + return PKNum_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSNumberState.h.svn-base b/jssrc/.svn/text-base/PKJSNumberState.h.svn-base new file mode 100644 index 0000000..de81da6 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSNumberState.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSNumberState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKNumberState_new(JSContextRef ctx, void *data); +JSClassRef PKNumberState_class(JSContextRef ctx); +JSObjectRef PKNumberState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSNumberState.m.svn-base b/jssrc/.svn/text-base/PKJSNumberState.m.svn-base new file mode 100644 index 0000000..c22c639 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSNumberState.m.svn-base @@ -0,0 +1,81 @@ +// +// PKJSNumberState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSNumberState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKNumberState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKNumberState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKNumberState]", ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKNumberState_getAllowsTrailingDot(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKNumberState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.allowsTrailingDot); +} + +static bool PKNumberState_setAllowsTrailingDot(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKNumberState *data = JSObjectGetPrivate(this); + data.allowsTrailingDot = JSValueToBoolean(ctx, value); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKNumberState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKNumberState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKNumberState_staticFunctions[] = { +{ "toString", PKNumberState_toString, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKNumberState_staticValues[] = { +{ "allowsTrailingDot", PKNumberState_getAllowsTrailingDot, PKNumberState_setAllowsTrailingDot, kJSPropertyAttributeDontDelete }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKNumberState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKNumberState_staticFunctions; + def.staticValues = PKNumberState_staticValues; + def.initialize = PKNumberState_initialize; + def.finalize = PKNumberState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKNumberState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKNumberState_class(ctx), data); +} + +JSObjectRef PKNumberState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKNumberState *data = [[PKNumberState alloc] init]; + return PKNumberState_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSParser.h.svn-base b/jssrc/.svn/text-base/PKJSParser.h.svn-base new file mode 100644 index 0000000..8b84eab --- /dev/null +++ b/jssrc/.svn/text-base/PKJSParser.h.svn-base @@ -0,0 +1,12 @@ +// +// PKJSParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/10/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKParser_new(JSContextRef ctx, void *data); +JSClassRef PKParser_class(JSContextRef ctx); diff --git a/jssrc/.svn/text-base/PKJSParser.m.svn-base b/jssrc/.svn/text-base/PKJSParser.m.svn-base new file mode 100644 index 0000000..e6b1c6c --- /dev/null +++ b/jssrc/.svn/text-base/PKJSParser.m.svn-base @@ -0,0 +1,154 @@ +// +// PKJSParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/10/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSParser.h" +#import "PKJSUtils.h" +#import "PKJSAssemblerAdapter.h" +#import "PKJSAssembly.h" +#import "PKJSTokenAssembly.h" +#import "PKJSCharacterAssembly.h" +#import +#import +#import +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKParser_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKParser_class, "toString"); + PKParser *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, [data description], ex); +} + +static JSValueRef PKParser_bestMatch(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKParser_class, "bestMatch"); + PKPreconditionMethodArgc(1, "bestMatch"); + + PKParser *data = JSObjectGetPrivate(this); + + JSObjectRef arg = (JSObjectRef)argv[0]; + PKAssembly *a = (PKAssembly *)JSObjectGetPrivate(arg); + a = [data bestMatchFor:a]; + + JSObjectRef result = NULL; + if ([a isMemberOfClass:[PKTokenAssembly class]]) { + result = PKTokenAssembly_new(ctx, a); + } else if ([a isMemberOfClass:[PKCharacterAssembly class]]) { + result = PKCharacterAssembly_new(ctx, a); + } + + return result; +} + +static JSValueRef PKParser_completeMatch(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKParser_class, "completeMatch"); + PKPreconditionMethodArgc(1, "completeMatch"); + + PKParser *data = JSObjectGetPrivate(this); + + JSObjectRef arg = (JSObjectRef)argv[0]; + PKAssembly *a = (PKAssembly *)JSObjectGetPrivate(arg); + a = [data completeMatchFor:a]; + + JSObjectRef result = NULL; + if ([a isMemberOfClass:[PKTokenAssembly class]]) { + result = PKTokenAssembly_new(ctx, a); + } else if ([a isMemberOfClass:[PKCharacterAssembly class]]) { + result = PKCharacterAssembly_new(ctx, a); + } + + return result; +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKParser_getAssembler(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKParser *data = JSObjectGetPrivate(this); + id assembler = data.assembler; + if ([assembler isMemberOfClass:[PKJSAssemblerAdapter class]]) { + return [assembler assemblerFunction]; + } else { + return NULL; + } +} + +static bool PKParser_setAssembler(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + if (!JSValueIsObject(ctx, value) || !JSObjectIsFunction(ctx, (JSObjectRef)value)) { + (*ex) = PKNSStringToJSValue(ctx, @"only a function object can be set as a parser's assembler property", ex); + return false; + } + + PKParser *data = JSObjectGetPrivate(this); + PKJSAssemblerAdapter *adapter = [[PKJSAssemblerAdapter alloc] init]; // retained. released in PKParser_finalize + [adapter setAssemblerFunction:(JSObjectRef)value fromContext:ctx]; + [data setAssembler:adapter selector:@selector(didMatch:)]; + return true; +} + +static JSValueRef PKParser_getName(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKParser *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, data.name, ex); +} + +static bool PKParser_setName(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKParser *data = JSObjectGetPrivate(this); + data.name = PKJSValueGetNSString(ctx, value, ex); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKParser_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKParser_finalize(JSObjectRef this) { + PKParser *data = (PKParser *)JSObjectGetPrivate(this); + id assembler = data.assembler; + data.assembler = nil; + if ([assembler isMemberOfClass:[PKJSAssemblerAdapter class]]) { + [assembler autorelease]; + } + [data autorelease]; +} + +static JSStaticFunction PKParser_staticFunctions[] = { +{ "toString", PKParser_toString, kJSPropertyAttributeDontDelete }, +{ "bestMatch", PKParser_bestMatch, kJSPropertyAttributeDontDelete }, +{ "completeMatch", PKParser_completeMatch, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKParser_staticValues[] = { +{ "assembler", PKParser_getAssembler, PKParser_setAssembler, kJSPropertyAttributeDontDelete }, // Function +{ "name", PKParser_getName, PKParser_setName, kJSPropertyAttributeDontDelete }, // String +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKParser_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKParser_staticFunctions; + def.staticValues = PKParser_staticValues; + def.initialize = PKParser_initialize; + def.finalize = PKParser_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKParser_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKParser_class(ctx), data); +} diff --git a/jssrc/.svn/text-base/PKJSPattern.h.svn-base b/jssrc/.svn/text-base/PKJSPattern.h.svn-base new file mode 100644 index 0000000..dac0b0d --- /dev/null +++ b/jssrc/.svn/text-base/PKJSPattern.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSPattern.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/1/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKPattern_new(JSContextRef ctx, void *data); +JSClassRef PKPattern_class(JSContextRef ctx); +JSObjectRef PKPattern_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSPattern.m.svn-base b/jssrc/.svn/text-base/PKJSPattern.m.svn-base new file mode 100644 index 0000000..ae612e7 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSPattern.m.svn-base @@ -0,0 +1,80 @@ +// +// PKJSPattern.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/1/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSPattern.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +//static JSValueRef PKPattern_invertedPattern(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { +// PKPreconditionInstaceOf(PKPattern_class, "invertedPattern"); +// +// PKPattern *data = JSObjectGetPrivate(this); +// return PKPattern_new(ctx, [data invertedPattern]); +//} +// +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKPattern_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKPattern_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKPattern_staticFunctions[] = { +//{ "invertedPattern", PKPattern_invertedPattern, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKPattern_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKPattern_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKPattern_staticFunctions; + def.staticValues = PKPattern_staticValues; + def.initialize = PKPattern_initialize; + def.finalize = PKPattern_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKPattern_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKPattern_class(ctx), data); +} + +JSObjectRef PKPattern_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKPattern"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + NSInteger opts = PKPatternOptionsNone; + + if (argc > 1) { + opts = JSValueToNumber(ctx, argv[1], ex); + } + + PKPattern *data = [[PKPattern alloc] initWithString:s options:opts]; + return PKPattern_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSQuoteState.h.svn-base b/jssrc/.svn/text-base/PKJSQuoteState.h.svn-base new file mode 100644 index 0000000..1a06d72 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSQuoteState.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSQuoteState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKQuoteState_new(JSContextRef ctx, void *data); +JSClassRef PKQuoteState_class(JSContextRef ctx); +JSObjectRef PKQuoteState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSQuoteState.m.svn-base b/jssrc/.svn/text-base/PKJSQuoteState.m.svn-base new file mode 100644 index 0000000..fa72f3d --- /dev/null +++ b/jssrc/.svn/text-base/PKJSQuoteState.m.svn-base @@ -0,0 +1,81 @@ +// +// PKJSQuoteState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSQuoteState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKQuoteState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKQuoteState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKQuoteState]", ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKQuoteState_getBalancesEOFTerminatedQuotes(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKQuoteState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.balancesEOFTerminatedQuotes); +} + +static bool PKQuoteState_setBalancesEOFTerminatedQuotes(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKQuoteState *data = JSObjectGetPrivate(this); + data.balancesEOFTerminatedQuotes = JSValueToBoolean(ctx, value); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKQuoteState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKQuoteState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKQuoteState_staticFunctions[] = { +{ "toString", PKQuoteState_toString, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKQuoteState_staticValues[] = { +{ "balancesEOFTerminatedQuotes", PKQuoteState_getBalancesEOFTerminatedQuotes, PKQuoteState_setBalancesEOFTerminatedQuotes, kJSPropertyAttributeDontDelete }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKQuoteState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKQuoteState_staticFunctions; + def.staticValues = PKQuoteState_staticValues; + def.initialize = PKQuoteState_initialize; + def.finalize = PKQuoteState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKQuoteState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKQuoteState_class(ctx), data); +} + +JSObjectRef PKQuoteState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKQuoteState *data = [[PKQuoteState alloc] init]; + return PKQuoteState_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSQuotedString.h.svn-base b/jssrc/.svn/text-base/PKJSQuotedString.h.svn-base new file mode 100644 index 0000000..1b37674 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSQuotedString.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSQuotedString.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKQuotedString_new(JSContextRef ctx, void *data); +JSClassRef PKQuotedString_class(JSContextRef ctx); +JSObjectRef PKQuotedString_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSQuotedString.m.svn-base b/jssrc/.svn/text-base/PKJSQuotedString.m.svn-base new file mode 100644 index 0000000..07c4f47 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSQuotedString.m.svn-base @@ -0,0 +1,63 @@ +// +// PKJSQuotedString.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSQuotedString.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKQuotedString_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKQuotedString_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKQuotedString_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKQuotedString_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKQuotedString_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKQuotedString_staticFunctions; + def.staticValues = PKQuotedString_staticValues; + def.initialize = PKQuotedString_initialize; + def.finalize = PKQuotedString_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKQuotedString_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKQuotedString_class(ctx), data); +} + +JSObjectRef PKQuotedString_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKQuotedString *data = [[PKQuotedString alloc] init]; + return PKQuotedString_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSRepetition.h.svn-base b/jssrc/.svn/text-base/PKJSRepetition.h.svn-base new file mode 100644 index 0000000..2ea1ec9 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSRepetition.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSRepetition.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKRepetition_new(JSContextRef ctx, void *data); +JSClassRef PKRepetition_class(JSContextRef ctx); +JSObjectRef PKRepetition_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSRepetition.m.svn-base b/jssrc/.svn/text-base/PKJSRepetition.m.svn-base new file mode 100644 index 0000000..72657f4 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSRepetition.m.svn-base @@ -0,0 +1,72 @@ +// +// PKJSRepetition.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSRepetition.h" +#import "PKJSUtils.h" +#import "PKJSParser.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKRepetition_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKRepetition_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKRepetition_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKRepetition_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKRepetition_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKParser_class(ctx); + def.staticFunctions = PKRepetition_staticFunctions; + def.staticValues = PKRepetition_staticValues; + def.initialize = PKRepetition_initialize; + def.finalize = PKRepetition_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKRepetition_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKRepetition_class(ctx), data); +} + +JSObjectRef PKRepetition_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKRepetition"); + + JSValueRef v = argv[0]; + if (!PKJSValueIsInstanceOfClass(ctx, v, "PKParser", ex)) { + *ex = PKNSStringToJSValue(ctx, @"argument to PKRepeition constructor must be and instance of a PKParser subclass", ex); + } + + PKParser *p = JSObjectGetPrivate((JSObjectRef)v); + + PKRepetition *data = [[PKRepetition alloc] initWithSubparser:p]; + return PKRepetition_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSSequence.h.svn-base b/jssrc/.svn/text-base/PKJSSequence.h.svn-base new file mode 100644 index 0000000..0dc69d1 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSSequence.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSSequence.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKSequence_new(JSContextRef ctx, void *data); +JSClassRef PKSequence_class(JSContextRef ctx); +JSObjectRef PKSequence_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSSequence.m.svn-base b/jssrc/.svn/text-base/PKJSSequence.m.svn-base new file mode 100644 index 0000000..820da91 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSSequence.m.svn-base @@ -0,0 +1,63 @@ +// +// PKJSSequence.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSSequence.h" +#import "PKJSUtils.h" +#import "PKJSCollectionParser.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKSequence_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKSequence_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKSequence_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKSequence_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKSequence_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKCollectionParser_class(ctx); + def.staticFunctions = PKSequence_staticFunctions; + def.staticValues = PKSequence_staticValues; + def.initialize = PKSequence_initialize; + def.finalize = PKSequence_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKSequence_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKSequence_class(ctx), data); +} + +JSObjectRef PKSequence_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKSequence *data = [[PKSequence alloc] init]; + return PKSequence_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSSymbol.h.svn-base b/jssrc/.svn/text-base/PKJSSymbol.h.svn-base new file mode 100644 index 0000000..45893eb --- /dev/null +++ b/jssrc/.svn/text-base/PKJSSymbol.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSSymbol.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKSymbol_new(JSContextRef ctx, void *data); +JSClassRef PKSymbol_class(JSContextRef ctx); +JSObjectRef PKSymbol_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSSymbol.m.svn-base b/jssrc/.svn/text-base/PKJSSymbol.m.svn-base new file mode 100644 index 0000000..a5140af --- /dev/null +++ b/jssrc/.svn/text-base/PKJSSymbol.m.svn-base @@ -0,0 +1,69 @@ +// +// PKJSSymbol.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSSymbol.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKSymbol_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKSymbol_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKSymbol_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKSymbol_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKSymbol_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKSymbol_staticFunctions; + def.staticValues = PKSymbol_staticValues; + def.initialize = PKSymbol_initialize; + def.finalize = PKSymbol_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKSymbol_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKSymbol_class(ctx), data); +} + +JSObjectRef PKSymbol_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + NSString *s = nil; + + if (argc > 0) { + s = PKJSValueGetNSString(ctx, argv[0], ex); + } + + PKSymbol *data = [[PKSymbol alloc] initWithString:s]; + return PKSymbol_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSSymbolState.h.svn-base b/jssrc/.svn/text-base/PKJSSymbolState.h.svn-base new file mode 100644 index 0000000..ae3aa9b --- /dev/null +++ b/jssrc/.svn/text-base/PKJSSymbolState.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSSymbolState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKSymbolState_new(JSContextRef ctx, void *data); +JSClassRef PKSymbolState_class(JSContextRef ctx); +JSObjectRef PKSymbolState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSSymbolState.m.svn-base b/jssrc/.svn/text-base/PKJSSymbolState.m.svn-base new file mode 100644 index 0000000..a36a68d --- /dev/null +++ b/jssrc/.svn/text-base/PKJSSymbolState.m.svn-base @@ -0,0 +1,95 @@ +// +// PKJSSymbolState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSSymbolState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKSymbolState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKSymbolState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKSymbolState]", ex); +} + +static JSValueRef PKSymbolState_add(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKSymbolState_class, "add"); + PKPreconditionMethodArgc(1, "PKSymbolState.add"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKSymbolState *data = JSObjectGetPrivate(this); + [data add:s]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKSymbolState_remove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKSymbolState_class, "remove"); + PKPreconditionMethodArgc(1, "PKSymbolState.remove"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKSymbolState *data = JSObjectGetPrivate(this); + [data remove:s]; + + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKSymbolState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKSymbolState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKSymbolState_staticFunctions[] = { +{ "toString", PKSymbolState_toString, kJSPropertyAttributeDontDelete }, +{ "add", PKSymbolState_add, kJSPropertyAttributeDontDelete }, +{ "remove", PKSymbolState_remove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKSymbolState_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKSymbolState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKSymbolState_staticFunctions; + def.staticValues = PKSymbolState_staticValues; + def.initialize = PKSymbolState_initialize; + def.finalize = PKSymbolState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKSymbolState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKSymbolState_class(ctx), data); +} + +JSObjectRef PKSymbolState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKSymbolState *data = [[PKSymbolState alloc] init]; + return PKSymbolState_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSTerminal.h.svn-base b/jssrc/.svn/text-base/PKJSTerminal.h.svn-base new file mode 100644 index 0000000..d4f7ddb --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTerminal.h.svn-base @@ -0,0 +1,12 @@ +// +// PKJSTerminal.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKTerminal_new(JSContextRef ctx, void *data); +JSClassRef PKTerminal_class(JSContextRef ctx); diff --git a/jssrc/.svn/text-base/PKJSTerminal.m.svn-base b/jssrc/.svn/text-base/PKJSTerminal.m.svn-base new file mode 100644 index 0000000..98efca4 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTerminal.m.svn-base @@ -0,0 +1,67 @@ +// +// PKJSTerminal.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSTerminal.h" +#import "PKJSUtils.h" +#import "PKJSParser.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKTerminal_discard(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTerminal_class, "discard"); + + PKTerminal *data = JSObjectGetPrivate(this); + [data discard]; + return this; +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTerminal_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTerminal_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKTerminal_staticFunctions[] = { +{ "discard", PKTerminal_discard, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKTerminal_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKTerminal_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKParser_class(ctx); + def.staticFunctions = PKTerminal_staticFunctions; + def.staticValues = PKTerminal_staticValues; + def.initialize = PKTerminal_initialize; + def.finalize = PKTerminal_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTerminal_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTerminal_class(ctx), data); +} diff --git a/jssrc/.svn/text-base/PKJSToken.h.svn-base b/jssrc/.svn/text-base/PKJSToken.h.svn-base new file mode 100644 index 0000000..b91d9b5 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSToken.h.svn-base @@ -0,0 +1,19 @@ +// +// PKJSToken.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKToken_new(JSContextRef ctx, void *data); +JSClassRef PKToken_class(JSContextRef ctx); +JSObjectRef PKToken_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); + +// a JS Class method +//JSValueRef PKToken_EOFToken(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* ex); + +// a JS Class property +JSValueRef PKToken_getEOFToken(JSContextRef ctx); diff --git a/jssrc/.svn/text-base/PKJSToken.m.svn-base b/jssrc/.svn/text-base/PKJSToken.m.svn-base new file mode 100644 index 0000000..ffd3ad3 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSToken.m.svn-base @@ -0,0 +1,159 @@ +// +// PKJSToken.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSToken.h" +#import "PKJSUtils.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKToken_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKToken_class, "toString"); + PKToken *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, [data debugDescription], ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKToken_getTokenType(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeNumber(ctx, data.tokenType); +} + +static JSValueRef PKToken_getStringValue(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, data.stringValue, ex); +} + +static JSValueRef PKToken_getFloatValue(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeNumber(ctx, data.floatValue); +} + +static JSValueRef PKToken_getIsNumber(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isNumber); +} + +static JSValueRef PKToken_getIsSymbol(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isSymbol); +} + +static JSValueRef PKToken_getIsWord(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isWord); +} + +static JSValueRef PKToken_getIsQuotedString(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isQuotedString); +} + +static JSValueRef PKToken_getIsWhitespace(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isWhitespace); +} + +static JSValueRef PKToken_getIsComment(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isComment); +} + +static JSValueRef PKToken_getIsDelimitedString(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isDelimitedString); +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKToken_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKToken_finalize(JSObjectRef this) { + PKToken *data = (PKToken *)JSObjectGetPrivate(this); + [data autorelease]; +} + +static JSStaticFunction PKToken_staticFunctions[] = { +{ "toString", PKToken_toString, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKToken_staticValues[] = { +{ "tokenType", PKToken_getTokenType, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Number +{ "stringValue", PKToken_getStringValue, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // String +{ "floatValue", PKToken_getFloatValue, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Number +{ "isNumber", PKToken_getIsNumber, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isSymbol", PKToken_getIsSymbol, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isWord", PKToken_getIsWord, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isQuotedString", PKToken_getIsQuotedString, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isWhitespace", PKToken_getIsWhitespace, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isComment", PKToken_getIsComment, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isDelimitedString", PKToken_getIsDelimitedString, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Class Methods + +// JSObjectCallAsFunctionCallback +//JSValueRef PKToken_EOFToken(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { +// static JSValueRef eof = NULL; +// if (!eof) { +// eof = PKToken_new(ctx, [PKToken EOFToken]); +// JSValueProtect(ctx, eof); // is this necessary/appropriate? +// } +// return eof; +//} + +#pragma mark - +#pragma mark Class Properties + +JSValueRef PKToken_getEOFToken(JSContextRef ctx) { + static JSObjectRef eof = NULL; + if (!eof) { + eof = PKToken_new(ctx, [PKToken EOFToken]); + } + return eof; +} + +#pragma mark - +#pragma mark Public + +JSClassRef PKToken_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKToken_staticFunctions; + def.staticValues = PKToken_staticValues; + def.initialize = PKToken_initialize; + def.finalize = PKToken_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKToken_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKToken_class(ctx), data); +} + +JSObjectRef PKToken_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(3, "PKToken"); + + CGFloat tokenType = JSValueToNumber(ctx, argv[0], NULL); + NSString *stringValue = PKJSValueGetNSString(ctx, argv[1], ex); + CGFloat floatValue = JSValueToNumber(ctx, argv[2], NULL); + + PKToken *data = [[PKToken alloc] initWithTokenType:tokenType stringValue:stringValue floatValue:floatValue]; + return PKToken_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSTokenAssembly.h.svn-base b/jssrc/.svn/text-base/PKJSTokenAssembly.h.svn-base new file mode 100644 index 0000000..e00b979 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTokenAssembly.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSTokenAssembly.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/3/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKTokenAssembly_new(JSContextRef ctx, void *data); +JSClassRef PKTokenAssembly_class(JSContextRef ctx); +JSObjectRef PKTokenAssembly_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSTokenAssembly.m.svn-base b/jssrc/.svn/text-base/PKJSTokenAssembly.m.svn-base new file mode 100644 index 0000000..32f9c1f --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTokenAssembly.m.svn-base @@ -0,0 +1,121 @@ +// +// PKJSTokenAssembly.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/3/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSTokenAssembly.h" +#import "PKJSToken.h" +#import "PKJSUtils.h" +#import "PKJSAssembly.h" +#import +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKTokenAssembly_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenAssembly_class, "toString"); + PKTokenAssembly *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, [data description], ex); +} + +static JSValueRef PKTokenAssembly_pop(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenAssembly_class, "pop"); + PKTokenAssembly *data = JSObjectGetPrivate(this); + PKToken *tok = [data pop]; + return PKToken_new(ctx, tok); +} + +static JSValueRef PKTokenAssembly_push(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenAssembly_class, "push"); + PKPreconditionMethodArgc(1, "PKTokenAssembly.push"); + + JSValueRef v = argv[0]; + + PKTokenAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + [data push:obj]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKTokenAssembly_objectsAbove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenAssembly_class, "objectsAbove"); + PKPreconditionMethodArgc(1, "PKTokenAssembly.objectsAbove"); + + JSValueRef v = argv[0]; + + PKTokenAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + id array = [data objectsAbove:obj]; + + return PKNSArrayToJSObject(ctx, array, ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKTokenAssembly_getLength(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenAssembly *data = JSObjectGetPrivate(this); + return JSValueMakeNumber(ctx, [data length]); +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTokenAssembly_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTokenAssembly_finalize(JSObjectRef this) { + // released in PKAssembly_finalize +} + +static JSStaticFunction PKTokenAssembly_staticFunctions[] = { +{ "toString", PKTokenAssembly_toString, kJSPropertyAttributeDontDelete }, +{ "pop", PKTokenAssembly_pop, kJSPropertyAttributeDontDelete }, +{ "push", PKTokenAssembly_push, kJSPropertyAttributeDontDelete }, +{ "objectsAbove", PKTokenAssembly_objectsAbove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKTokenAssembly_staticValues[] = { +{ "length", PKTokenAssembly_getLength, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Number +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark ClassMethods + +#pragma mark - +#pragma mark Public + +JSClassRef PKTokenAssembly_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKAssembly_class(ctx); + def.staticFunctions = PKTokenAssembly_staticFunctions; + def.staticValues = PKTokenAssembly_staticValues; + def.initialize = PKTokenAssembly_initialize; + def.finalize = PKTokenAssembly_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTokenAssembly_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTokenAssembly_class(ctx), data); +} + +JSObjectRef PKTokenAssembly_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKTokenAssembly"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKTokenAssembly *data = [[PKTokenAssembly alloc] initWithString:s]; + return PKTokenAssembly_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSTokenizer.h.svn-base b/jssrc/.svn/text-base/PKJSTokenizer.h.svn-base new file mode 100644 index 0000000..c56fa3b --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTokenizer.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSTokenizer.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/3/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKTokenizer_new(JSContextRef ctx, void *data); +JSClassRef PKTokenizer_class(JSContextRef ctx); +JSObjectRef PKTokenizer_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSTokenizer.m.svn-base b/jssrc/.svn/text-base/PKJSTokenizer.m.svn-base new file mode 100644 index 0000000..76f4e34 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTokenizer.m.svn-base @@ -0,0 +1,215 @@ +// +// PKJSTokenizer.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/3/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSTokenizer.h" +#import "PKJSUtils.h" +#import "PKJSToken.h" +#import "PKJSWordState.h" +#import "PKJSNumberState.h" +#import "PKJSQuoteState.h" +#import "PKJSWhitespaceState.h" +#import "PKJSCommentState.h" +#import "PKJSSymbolState.h" +#import +#import +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKTokenizer_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenizer_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKTokenizer]", ex); +} + +static JSValueRef PKTokenizer_nextToken(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenizer_class, "nextToken"); + PKTokenizer *data = JSObjectGetPrivate(this); + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = [data nextToken]; + + if (eof == tok) { + return PKToken_getEOFToken(ctx); + } + + return PKToken_new(ctx, tok); +} + +static JSValueRef PKTokenizer_setTokenizerState(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenizer_class, "setTokenizerState"); + PKPreconditionMethodArgc(3, "PKTokenizer.setTokenizerState"); + + JSObjectRef stateObj = (JSObjectRef)argv[0]; + PKTokenizerState *state = JSObjectGetPrivate(stateObj); + NSString *from = PKJSValueGetNSString(ctx, argv[1], ex); + NSString *to = PKJSValueGetNSString(ctx, argv[2], ex); + + PKTokenizer *data = JSObjectGetPrivate(this); + [data setTokenizerState:state from:[from characterAtIndex:0] to:[to characterAtIndex:0]]; + + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKTokenizer_getString(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, data.string, ex); +} + +static bool PKTokenizer_setString(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + data.string = PKJSValueGetNSString(ctx, value, ex); + return true; +} + +static JSValueRef PKTokenizer_getWordState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKWordState_new(ctx, data.wordState); + return NULL; +} + +static bool PKTokenizer_setWordState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKWordState *state = JSObjectGetPrivate(stateObj); + data.wordState = state; + return true; +} + +static JSValueRef PKTokenizer_getNumberState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKNumberState_new(ctx, data.numberState); + return NULL; +} + +static bool PKTokenizer_setNumberState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKNumberState *state = JSObjectGetPrivate(stateObj); + data.numberState = state; + return true; +} + +static JSValueRef PKTokenizer_getQuoteState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKQuoteState_new(ctx, data.quoteState); + return NULL; +} + +static bool PKTokenizer_setQuoteState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKQuoteState *state = JSObjectGetPrivate(stateObj); + data.quoteState = state; + return true; +} + +static JSValueRef PKTokenizer_getSymbolState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKSymbolState_new(ctx, data.symbolState); + return NULL; +} + +static bool PKTokenizer_setSymbolState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKSymbolState *state = JSObjectGetPrivate(stateObj); + data.symbolState = state; + return true; +} + +static JSValueRef PKTokenizer_getWhitespaceState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKWhitespaceState_new(ctx, data.whitespaceState); + return NULL; +} + +static bool PKTokenizer_setWhitespaceState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKWhitespaceState *state = JSObjectGetPrivate(stateObj); + data.whitespaceState = state; + return true; +} + +static JSValueRef PKTokenizer_getCommentState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKCommentState_new(ctx, data.commentState); + return NULL; +} + +static bool PKTokenizer_setCommentState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKCommentState *state = JSObjectGetPrivate(stateObj); + data.commentState = state; + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTokenizer_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTokenizer_finalize(JSObjectRef this) { + PKTokenizer *data = (PKTokenizer *)JSObjectGetPrivate(this); + [data autorelease]; +} + +static JSStaticFunction PKTokenizer_staticFunctions[] = { +{ "toString", PKTokenizer_toString, kJSPropertyAttributeDontDelete }, +{ "setTokenizerState", PKTokenizer_setTokenizerState, kJSPropertyAttributeDontDelete }, +{ "nextToken", PKTokenizer_nextToken, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKTokenizer_staticValues[] = { +{ "string", PKTokenizer_getString, PKTokenizer_setString, kJSPropertyAttributeDontDelete }, // String +{ "numberState", PKTokenizer_getNumberState, PKTokenizer_setNumberState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "quoteState", PKTokenizer_getQuoteState, PKTokenizer_setQuoteState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "commentState", PKTokenizer_getCommentState, PKTokenizer_setCommentState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "symbolState", PKTokenizer_getSymbolState, PKTokenizer_setSymbolState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "whitespaceState", PKTokenizer_getWhitespaceState, PKTokenizer_setWhitespaceState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "wordState", PKTokenizer_getWordState, PKTokenizer_setWordState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKTokenizer_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKTokenizer_staticFunctions; + def.staticValues = PKTokenizer_staticValues; + def.initialize = PKTokenizer_initialize; + def.finalize = PKTokenizer_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTokenizer_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTokenizer_class(ctx), data); +} + +JSObjectRef PKTokenizer_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKTokenizer"); + + JSValueRef s = argv[0]; + NSString *string = PKJSValueGetNSString(ctx, s, ex); + + PKTokenizer *data = [[PKTokenizer alloc] initWithString:string]; + return PKTokenizer_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSTokenizerState.h.svn-base b/jssrc/.svn/text-base/PKJSTokenizerState.h.svn-base new file mode 100644 index 0000000..ef4e19f --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTokenizerState.h.svn-base @@ -0,0 +1,12 @@ +// +// PKJSTokenizerState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKTokenizerState_new(JSContextRef ctx, void *data); +JSClassRef PKTokenizerState_class(JSContextRef ctx); diff --git a/jssrc/.svn/text-base/PKJSTokenizerState.m.svn-base b/jssrc/.svn/text-base/PKJSTokenizerState.m.svn-base new file mode 100644 index 0000000..0b246c6 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTokenizerState.m.svn-base @@ -0,0 +1,59 @@ +// +// PKJSTokenizerState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSTokenizerState.h" +#import "PKJSUtils.h" +#import "PKJSToken.h" +#import +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTokenizerState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTokenizerState_finalize(JSObjectRef this) { + PKTokenizerState *data = (PKTokenizerState *)JSObjectGetPrivate(this); + [data autorelease]; +} + +static JSStaticFunction PKTokenizerState_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKTokenizerState_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKTokenizerState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKTokenizerState_staticFunctions; + def.staticValues = PKTokenizerState_staticValues; + def.initialize = PKTokenizerState_initialize; + def.finalize = PKTokenizerState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTokenizerState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTokenizerState_class(ctx), data); +} diff --git a/jssrc/.svn/text-base/PKJSTrack.h.svn-base b/jssrc/.svn/text-base/PKJSTrack.h.svn-base new file mode 100644 index 0000000..a4036b6 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTrack.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSTrack.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKTrack_new(JSContextRef ctx, void *data); +JSClassRef PKTrack_class(JSContextRef ctx); +JSObjectRef PKTrack_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSTrack.m.svn-base b/jssrc/.svn/text-base/PKJSTrack.m.svn-base new file mode 100644 index 0000000..3d272fe --- /dev/null +++ b/jssrc/.svn/text-base/PKJSTrack.m.svn-base @@ -0,0 +1,63 @@ +// +// PKJSTrack.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSTrack.h" +#import "PKJSUtils.h" +#import "PKJSSequence.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTrack_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTrack_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKTrack_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKTrack_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKTrack_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKSequence_class(ctx); + def.staticFunctions = PKTrack_staticFunctions; + def.staticValues = PKTrack_staticValues; + def.initialize = PKTrack_initialize; + def.finalize = PKTrack_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTrack_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTrack_class(ctx), data); +} + +JSObjectRef PKTrack_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKTrack *data = [[PKTrack alloc] init]; + return PKTrack_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSUppercaseWord.h.svn-base b/jssrc/.svn/text-base/PKJSUppercaseWord.h.svn-base new file mode 100644 index 0000000..a43c32d --- /dev/null +++ b/jssrc/.svn/text-base/PKJSUppercaseWord.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSUppercaseWord.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/13/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKUppercaseWord_new(JSContextRef ctx, void *data); +JSClassRef PKUppercaseWord_class(JSContextRef ctx); +JSObjectRef PKUppercaseWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSUppercaseWord.m.svn-base b/jssrc/.svn/text-base/PKJSUppercaseWord.m.svn-base new file mode 100644 index 0000000..bb73a5d --- /dev/null +++ b/jssrc/.svn/text-base/PKJSUppercaseWord.m.svn-base @@ -0,0 +1,67 @@ +// +// PKJSUppercaseWord.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/13/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSUppercaseWord.h" +#import "PKJSUtils.h" +#import "PKJSWord.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKUppercaseWord_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKUppercaseWord_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKUppercaseWord_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKUppercaseWord_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKUppercaseWord_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKWord_class(ctx); + def.staticFunctions = PKUppercaseWord_staticFunctions; + def.staticValues = PKUppercaseWord_staticValues; + def.initialize = PKUppercaseWord_initialize; + def.finalize = PKUppercaseWord_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKUppercaseWord_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKUppercaseWord_class(ctx), data); +} + +JSObjectRef PKUppercaseWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKUppercaseWord"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKUppercaseWord *data = [[PKUppercaseWord alloc] initWithString:s]; + return PKUppercaseWord_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSUtils.h.svn-base b/jssrc/.svn/text-base/PKJSUtils.h.svn-base new file mode 100644 index 0000000..d4073be --- /dev/null +++ b/jssrc/.svn/text-base/PKJSUtils.h.svn-base @@ -0,0 +1,32 @@ +// +// PKJSUtils.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +#define PKPreconditionInstaceOf(cls, meth) +#define PKPreconditionMethodArgc(n, meth) +#define PKPreconditionConstructorArgc(n, meth) + +JSValueRef PKCFTypeToJSValue(JSContextRef ctx, CFTypeRef value, JSValueRef *ex); +JSValueRef PKCFStringToJSValue(JSContextRef ctx, CFStringRef cfStr, JSValueRef *ex); +JSValueRef PKNSStringToJSValue(JSContextRef ctx, NSString *nsStr, JSValueRef *ex); +JSObjectRef PKCFArrayToJSObject(JSContextRef ctx, CFArrayRef cfArray, JSValueRef *ex); +JSObjectRef PKNSArrayToJSObject(JSContextRef ctx, NSArray *nsArray, JSValueRef *ex); +JSObjectRef PKCFDictionaryToJSObject(JSContextRef ctx, CFDictionaryRef cfDict, JSValueRef *ex); +JSObjectRef PKNSDictionaryToJSObject(JSContextRef ctx, NSDictionary *nsDict, JSValueRef *ex); + +CFTypeRef PKJSValueCopyCFType(JSContextRef ctx, JSValueRef value, JSValueRef *ex); +id PKJSValueGetId(JSContextRef ctx, JSValueRef value, JSValueRef *ex); +CFStringRef PKJSValueCopyCFString(JSContextRef ctx, JSValueRef value, JSValueRef *ex); +NSString *PKJSValueGetNSString(JSContextRef ctx, JSValueRef value, JSValueRef *ex); +CFArrayRef PKJSObjectCopyCFArray(JSContextRef ctx, JSObjectRef obj, JSValueRef *ex); +CFDictionaryRef PKJSObjectCopyCFDictionary(JSContextRef ctx, JSObjectRef obj, JSValueRef *ex); + +JSObjectRef PKNSErrorToJSObject(JSContextRef ctx, NSError *nsErr, JSValueRef *ex); +bool PKJSValueIsInstanceOfClass(JSContextRef ctx, JSValueRef value, char *className, JSValueRef* ex); \ No newline at end of file diff --git a/jssrc/.svn/text-base/PKJSUtils.m.svn-base b/jssrc/.svn/text-base/PKJSUtils.m.svn-base new file mode 100644 index 0000000..bf02c8c --- /dev/null +++ b/jssrc/.svn/text-base/PKJSUtils.m.svn-base @@ -0,0 +1,236 @@ +// +// PKJSUtils.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSUtils.h" + +JSValueRef PKCFTypeToJSValue(JSContextRef ctx, CFTypeRef value, JSValueRef *ex) { + JSValueRef result = NULL; + CFTypeID typeID = CFGetTypeID(value); + + if (CFNumberGetTypeID() == typeID) { + double d; + CFNumberGetValue(value, kCFNumberDoubleType, &d); + result = JSValueMakeNumber(ctx, d); + } else if (CFBooleanGetTypeID() == typeID) { + Boolean b = CFBooleanGetValue(value); + result = JSValueMakeBoolean(ctx, b); + } else if (CFStringGetTypeID() == typeID) { + result = PKCFStringToJSValue(ctx, value, ex); + } else if (CFArrayGetTypeID() == typeID) { + result = PKCFArrayToJSObject(ctx, value, ex); + } else if (CFDictionaryGetTypeID() == typeID) { + result = PKCFDictionaryToJSObject(ctx, value, ex); + } else { + result = JSValueMakeNull(ctx); + } + + return result; +} + +JSValueRef PKCFStringToJSValue(JSContextRef ctx, CFStringRef cfStr, JSValueRef *ex) { + JSStringRef str = JSStringCreateWithCFString(cfStr); + JSValueRef result = JSValueMakeString(ctx, str); + JSStringRelease(str); + return result; +} + +JSValueRef PKNSStringToJSValue(JSContextRef ctx, NSString *nsStr, JSValueRef *ex) { + return PKCFStringToJSValue(ctx, (CFStringRef)nsStr, ex); +} + +JSObjectRef PKCFArrayToJSObject(JSContextRef ctx, CFArrayRef cfArray, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef className = JSStringCreateWithUTF8CString("Array"); + JSObjectRef arrayConstr = (JSObjectRef)JSObjectGetProperty(ctx, globalObj, className, NULL); + JSStringRelease(className); + + JSObjectRef obj = (JSObjectRef)JSObjectCallAsConstructor(ctx, arrayConstr, 0, NULL, NULL); + + CFIndex len = 0; + if (NULL != cfArray) { + len = CFArrayGetCount(cfArray); + } + + CFIndex i = 0; + for ( ; i < len; i++) { + CFTypeRef value = CFArrayGetValueAtIndex(cfArray, i); + JSValueRef propVal = PKCFTypeToJSValue(ctx, value, ex); + JSObjectSetPropertyAtIndex(ctx, obj, i, propVal, NULL); + } + + return obj; +} + +JSObjectRef PKNSArrayToJSObject(JSContextRef ctx, NSArray *nsArray, JSValueRef *ex) { + return PKCFArrayToJSObject(ctx, (CFArrayRef)nsArray, ex); +} + +JSObjectRef PKCFDictionaryToJSObject(JSContextRef ctx, CFDictionaryRef cfDict, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef className = JSStringCreateWithUTF8CString("Object"); + JSObjectRef objConstr = (JSObjectRef)JSObjectGetProperty(ctx, globalObj, className, NULL); + JSStringRelease(className); + + JSObjectRef obj = (JSObjectRef)JSObjectCallAsConstructor(ctx, objConstr, 0, NULL, NULL); + + if (NULL != cfDict) { + CFIndex len = CFDictionaryGetCount(cfDict); + CFStringRef keys[len]; + CFTypeRef values[len]; + CFDictionaryGetKeysAndValues(cfDict, (const void**)keys, (const void**)values); + + CFIndex i = 0; + for ( ; i < len; i++) { + CFStringRef key = keys[i]; + CFTypeRef value = values[i]; + + JSStringRef propName = JSStringCreateWithCFString(key); + JSValueRef propVal = PKCFTypeToJSValue(ctx, value, ex); + JSObjectSetProperty(ctx, obj, propName, propVal, kJSPropertyAttributeNone, NULL); + JSStringRelease(propName); + } + } + + return obj; +} + +JSObjectRef PKNSDictionaryToJSObject(JSContextRef ctx, NSDictionary *nsDict, JSValueRef *ex) { + return PKCFDictionaryToJSObject(ctx, (CFDictionaryRef)nsDict, ex); +} + +CFTypeRef PKJSValueCopyCFType(JSContextRef ctx, JSValueRef value, JSValueRef *ex) { + CFTypeRef result = NULL; + + if (JSValueIsBoolean(ctx, value)) { + Boolean b = JSValueToBoolean(ctx, value); + result = (b ? kCFBooleanTrue : kCFBooleanFalse); + } else if (JSValueIsNull(ctx, value)) { + result = NULL; + } else if (JSValueIsNumber(ctx, value)) { + CGFloat d = JSValueToNumber(ctx, value, NULL); + result = CFNumberCreate(NULL, kCFNumberCGFloatType, &d); + } else if (JSValueIsString(ctx, value)) { + result = PKJSValueCopyCFString(ctx, value, ex); + } else if (JSValueIsObject(ctx, value)) { + if (PKJSValueIsInstanceOfClass(ctx, value, "Array", NULL)) { + result = PKJSObjectCopyCFArray(ctx, (JSObjectRef)value, ex); + } else { + result = PKJSObjectCopyCFDictionary(ctx, (JSObjectRef)value, ex); + } + } + + return result; +} + +id PKJSValueGetId(JSContextRef ctx, JSValueRef value, JSValueRef *ex) { + return [(id)PKJSValueCopyCFType(ctx, value, ex) autorelease]; +} + +CFStringRef PKJSValueCopyCFString(JSContextRef ctx, JSValueRef value, JSValueRef *ex) { + JSStringRef str = JSValueToStringCopy(ctx, value, ex); + CFStringRef result = JSStringCopyCFString(NULL, str); + JSStringRelease(str); + return result; +} + +NSString *PKJSValueGetNSString(JSContextRef ctx, JSValueRef value, JSValueRef *ex) { + return [(id)PKJSValueCopyCFString(ctx, value, ex) autorelease]; +} + +CFArrayRef PKJSObjectCopyCFArray(JSContextRef ctx, JSObjectRef obj, JSValueRef *ex) { + JSStringRef propName = JSStringCreateWithUTF8CString("length"); + JSValueRef propVal = JSObjectGetProperty(ctx, obj, propName, NULL); + JSStringRelease(propName); + CFIndex len = (CFIndex)JSValueToNumber(ctx, propVal, NULL); + + CFMutableArrayRef cfArray = CFArrayCreateMutable(NULL, len, NULL); + + CFIndex i = 0; + for ( ; i < len; i++) { + JSValueRef val = JSObjectGetPropertyAtIndex(ctx, obj, i, NULL); + CFTypeRef cfType = PKJSValueCopyCFType(ctx, val, ex); + CFArraySetValueAtIndex(cfArray, i, cfType); + + CFRelease(cfType); + } + + CFArrayRef result = CFArrayCreateCopy(NULL, cfArray); + CFRelease(cfArray); + + return result; +} + +CFDictionaryRef PKJSObjectCopyCFDictionary(JSContextRef ctx, JSObjectRef obj, JSValueRef *ex) { + JSPropertyNameArrayRef propNames = JSObjectCopyPropertyNames(ctx, obj); + CFIndex len = JSPropertyNameArrayGetCount(propNames); + + CFMutableDictionaryRef cfDict = CFDictionaryCreateMutable(NULL, len, NULL, NULL); + + CFIndex i = 0; + for ( ; i < len; i++) { + JSStringRef propName = JSPropertyNameArrayGetNameAtIndex(propNames, i); + JSValueRef val = JSObjectGetProperty(ctx, obj, propName, NULL); + CFTypeRef cfType = PKJSValueCopyCFType(ctx, val, ex); + + CFStringRef key = JSStringCopyCFString(NULL, propName); + CFDictionarySetValue(cfDict, (const void *)key, (const void *)cfType); + + CFRelease(key); + CFRelease(cfType); + } + + JSPropertyNameArrayRelease(propNames); + CFDictionaryRef result = CFDictionaryCreateCopy(NULL, cfDict); + CFRelease(cfDict); + + return result; +} + +JSObjectRef PKNSErrorToJSObject(JSContextRef ctx, NSError *nsErr, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef className = JSStringCreateWithUTF8CString("Error"); + JSObjectRef errConstr = (JSObjectRef)JSObjectGetProperty(ctx, globalObj, className, ex); + JSStringRelease(className); + + JSObjectRef obj = (JSObjectRef)JSObjectCallAsConstructor(ctx, errConstr, 0, NULL, ex); + + if (nsErr) { + JSStringRef nameStr = JSStringCreateWithUTF8CString("ParseKitError"); + JSValueRef name = JSValueMakeString(ctx, nameStr); + JSStringRelease(nameStr); + + JSStringRef msgStr = JSStringCreateWithCFString((CFStringRef)[nsErr localizedDescription]); + JSValueRef msg = JSValueMakeString(ctx, msgStr); + JSStringRelease(msgStr); + + JSValueRef code = JSValueMakeNumber(ctx, [nsErr code]); + + JSStringRef propName = JSStringCreateWithUTF8CString("name"); + JSObjectSetProperty(ctx, obj, propName, name, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete, ex); + JSStringRelease(propName); + + propName = JSStringCreateWithUTF8CString("message"); + JSObjectSetProperty(ctx, obj, propName, msg, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete, ex); + JSStringRelease(propName); + + propName = JSStringCreateWithUTF8CString("code"); + JSObjectSetProperty(ctx, obj, propName, code, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete, ex); + JSStringRelease(propName); + } + + return obj; +} + +bool PKJSValueIsInstanceOfClass(JSContextRef ctx, JSValueRef value, char *className, JSValueRef* ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef classNameStr = JSStringCreateWithUTF8CString(className); + JSObjectRef constr = (JSObjectRef)JSObjectGetProperty(ctx, globalObj, classNameStr, ex); + JSStringRelease(classNameStr); + + return JSValueIsInstanceOfConstructor(ctx, value, constr, NULL); +} diff --git a/jssrc/.svn/text-base/PKJSUtils_macros.h.svn-base b/jssrc/.svn/text-base/PKJSUtils_macros.h.svn-base new file mode 100644 index 0000000..0be22bd --- /dev/null +++ b/jssrc/.svn/text-base/PKJSUtils_macros.h.svn-base @@ -0,0 +1,33 @@ +/* + * PKJSUtils_macros.h + * ParseKit + * + * Created by Todd Ditchendorf on 1/11/09. + * Copyright 2009 Todd Ditchendorf. All rights reserved. + * + */ + +#undef PKPreconditionInstaceOf +#define PKPreconditionInstaceOf(cls, meth) \ + if (!JSValueIsObjectOfClass(ctx, this, (cls)(ctx))) { \ + NSString *s = [NSString stringWithFormat:@"calling method '%s' on an object that is not an instance of '%s'", (meth), #cls]; \ + (*ex) = PKNSStringToJSValue(ctx, s, ex); \ + return JSValueMakeUndefined(ctx); \ + } + +#undef PKPreconditionMethodArgc +#define PKPreconditionMethodArgc(n, meth) \ + if (argc < (n)) { \ + NSString *s = [NSString stringWithFormat:@"%s() requires %d arguments", (meth), (n)]; \ + (*ex) = PKNSStringToJSValue(ctx, s, ex); \ + return JSValueMakeUndefined(ctx); \ + } + +#undef PKPreconditionConstructorArgc +#define PKPreconditionConstructorArgc(n, meth) \ + if (argc < (n)) { \ + NSString *s = [NSString stringWithFormat:@"%s constructor requires %d arguments", (meth), (n)]; \ + (*ex) = PKNSStringToJSValue(ctx, s, ex); \ + return NULL; \ + } + diff --git a/jssrc/.svn/text-base/PKJSValueHolder.h.svn-base b/jssrc/.svn/text-base/PKJSValueHolder.h.svn-base new file mode 100644 index 0000000..0fc309c --- /dev/null +++ b/jssrc/.svn/text-base/PKJSValueHolder.h.svn-base @@ -0,0 +1,20 @@ +// +// PKJSValueHolder.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface JSValueHolder : NSObject { + JSContextRef context; + JSValueRef heldValue; +} +- (id)initWithContext:(JSContextRef)c heldValue:(JSValueRef)v; + +@property (nonatomic) JSContextRef context; +@property (nonatomic) JSValueRef heldValue; +@end \ No newline at end of file diff --git a/jssrc/.svn/text-base/PKJSValueHolder.m.svn-base b/jssrc/.svn/text-base/PKJSValueHolder.m.svn-base new file mode 100644 index 0000000..6b4eb79 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSValueHolder.m.svn-base @@ -0,0 +1,29 @@ +// +// PKJSValueHolder.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSValueHolder.h" + +@implementation JSValueHolder + +- (id)initWithContext:(JSContextRef)c heldValue:(JSValueRef)v { + if (self = [super init]) { + self.context = c; + self.heldValue = v; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +@synthesize context; +@synthesize heldValue; +@end diff --git a/jssrc/.svn/text-base/PKJSWhitespaceState.h.svn-base b/jssrc/.svn/text-base/PKJSWhitespaceState.h.svn-base new file mode 100644 index 0000000..68a04a7 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSWhitespaceState.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSWhitespaceState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKWhitespaceState_new(JSContextRef ctx, void *data); +JSClassRef PKWhitespaceState_class(JSContextRef ctx); +JSObjectRef PKWhitespaceState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSWhitespaceState.m.svn-base b/jssrc/.svn/text-base/PKJSWhitespaceState.m.svn-base new file mode 100644 index 0000000..54a4fc6 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSWhitespaceState.m.svn-base @@ -0,0 +1,109 @@ +// +// PKJSWhitespaceState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSWhitespaceState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKWhitespaceState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWhitespaceState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKWhitespaceState]", ex); +} + +static JSValueRef PKWhitespaceState_setWhitespaceChars(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWhitespaceState_class, "setWhitespaceChars"); + PKPreconditionMethodArgc(3, "PKWhitespaceState.setWhitespaceChars"); + + BOOL yn = JSValueToBoolean(ctx, argv[0]); + NSString *start = PKJSValueGetNSString(ctx, argv[1], ex); + NSString *end = PKJSValueGetNSString(ctx, argv[2], ex); + + PKWhitespaceState *data = JSObjectGetPrivate(this); + [data setWhitespaceChars:yn from:[start characterAtIndex:0] to:[end characterAtIndex:0]]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKWhitespaceState_isWhitespaceChar(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWhitespaceState_class, "isWhitespaceChar"); + PKPreconditionMethodArgc(1, "PKWhitespaceState.add"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKWhitespaceState *data = JSObjectGetPrivate(this); + BOOL yn = [data isWhitespaceChar:[s characterAtIndex:0]]; + + return JSValueMakeBoolean(ctx, yn); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKWhitespaceState_getReportsWhitespaceTokens(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKWhitespaceState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.reportsWhitespaceTokens); +} + +static bool PKWhitespaceState_setReportsWhitespaceTokens(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKWhitespaceState *data = JSObjectGetPrivate(this); + data.reportsWhitespaceTokens = JSValueToBoolean(ctx, value); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKWhitespaceState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKWhitespaceState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKWhitespaceState_staticFunctions[] = { +{ "toString", PKWhitespaceState_toString, kJSPropertyAttributeDontDelete }, +{ "setWhitespaceChars", PKWhitespaceState_setWhitespaceChars, kJSPropertyAttributeDontDelete }, +{ "isWhitespaceChar", PKWhitespaceState_isWhitespaceChar, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKWhitespaceState_staticValues[] = { +{ "reportsWhitespaceTokens", PKWhitespaceState_getReportsWhitespaceTokens, PKWhitespaceState_setReportsWhitespaceTokens, kJSPropertyAttributeDontDelete }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKWhitespaceState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKWhitespaceState_staticFunctions; + def.staticValues = PKWhitespaceState_staticValues; + def.initialize = PKWhitespaceState_initialize; + def.finalize = PKWhitespaceState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKWhitespaceState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKWhitespaceState_class(ctx), data); +} + +JSObjectRef PKWhitespaceState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKWhitespaceState *data = [[PKWhitespaceState alloc] init]; + return PKWhitespaceState_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSWord.h.svn-base b/jssrc/.svn/text-base/PKJSWord.h.svn-base new file mode 100644 index 0000000..bc3880c --- /dev/null +++ b/jssrc/.svn/text-base/PKJSWord.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSWord.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKWord_new(JSContextRef ctx, void *data); +JSClassRef PKWord_class(JSContextRef ctx); +JSObjectRef PKWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSWord.m.svn-base b/jssrc/.svn/text-base/PKJSWord.m.svn-base new file mode 100644 index 0000000..63d4156 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSWord.m.svn-base @@ -0,0 +1,63 @@ +// +// PKJSWord.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSWord.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKWord_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKWord_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKWord_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKWord_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKWord_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKWord_staticFunctions; + def.staticValues = PKWord_staticValues; + def.initialize = PKWord_initialize; + def.finalize = PKWord_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKWord_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKWord_class(ctx), data); +} + +JSObjectRef PKWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKWord *data = [[PKWord alloc] init]; + return PKWord_new(ctx, data); +} diff --git a/jssrc/.svn/text-base/PKJSWordState.h.svn-base b/jssrc/.svn/text-base/PKJSWordState.h.svn-base new file mode 100644 index 0000000..34e2562 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSWordState.h.svn-base @@ -0,0 +1,13 @@ +// +// PKJSWordState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +JSObjectRef PKWordState_new(JSContextRef ctx, void *data); +JSClassRef PKWordState_class(JSContextRef ctx); +JSObjectRef PKWordState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/.svn/text-base/PKJSWordState.m.svn-base b/jssrc/.svn/text-base/PKJSWordState.m.svn-base new file mode 100644 index 0000000..1082294 --- /dev/null +++ b/jssrc/.svn/text-base/PKJSWordState.m.svn-base @@ -0,0 +1,97 @@ +// +// PKJSWordState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/9/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKJSWordState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKWordState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWordState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKWordState]", ex); +} + +static JSValueRef PKWordState_setWordChars(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWordState_class, "setWordChars"); + PKPreconditionMethodArgc(3, "PKWordState.setWordChars"); + + BOOL yn = JSValueToBoolean(ctx, argv[0]); + NSString *start = PKJSValueGetNSString(ctx, argv[1], ex); + NSString *end = PKJSValueGetNSString(ctx, argv[2], ex); + + PKWordState *data = JSObjectGetPrivate(this); + [data setWordChars:yn from:[start characterAtIndex:0] to:[end characterAtIndex:0]]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKWordState_isWordChar(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWordState_class, "isWordChar"); + PKPreconditionMethodArgc(1, "PKWordState.isWordChar"); + + NSInteger c = (NSInteger)JSValueToNumber(ctx, argv[0], ex); + + PKWordState *data = JSObjectGetPrivate(this); + BOOL yn = [data isWordChar:c]; + + return JSValueMakeBoolean(ctx, yn); +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKWordState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKWordState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKWordState_staticFunctions[] = { +{ "toString", PKWordState_toString, kJSPropertyAttributeDontDelete }, +{ "setWordChars", PKWordState_setWordChars, kJSPropertyAttributeDontDelete }, +{ "isWordChar", PKWordState_isWordChar, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKWordState_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKWordState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKWordState_staticFunctions; + def.staticValues = PKWordState_staticValues; + def.initialize = PKWordState_initialize; + def.finalize = PKWordState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKWordState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKWordState_class(ctx), data); +} + +JSObjectRef PKWordState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKWordState *data = [[PKWordState alloc] init]; + return PKWordState_new(ctx, data); +} diff --git a/jssrc/JSParseKit.h b/jssrc/JSParseKit.h new file mode 100644 index 0000000..9550956 --- /dev/null +++ b/jssrc/JSParseKit.h @@ -0,0 +1,18 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +void PKJSParseKitSetUpContext(JSContextRef ctx); \ No newline at end of file diff --git a/jssrc/JSParseKit.m b/jssrc/JSParseKit.m new file mode 100644 index 0000000..dbc999f --- /dev/null +++ b/jssrc/JSParseKit.m @@ -0,0 +1,122 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import "PKJSUtils.h" +#import "PKJSToken.h" +#import "PKJSTokenizer.h" +#import "PKJSTokenizerState.h" +#import "PKJSAssembly.h" +#import "PKJSTokenAssembly.h" +#import "PKJSCharacterAssembly.h" +#import "PKJSWordState.h" +#import "PKJSNumberState.h" +#import "PKJSWhitespaceState.h" +#import "PKJSCommentState.h" +#import "PKJSQuoteState.h" +#import "PKJSSymbolState.h" +#import "PKJSRepetition.h" +#import "PKJSSequence.h" +#import "PKJSTrack.h" +#import "PKJSAlternation.h" +#import "PKJSEmpty.h" +#import "PKJSAny.h" +#import "PKJSWord.h" +#import "PKJSNum.h" +#import "PKJSQuotedString.h" +#import "PKJSSymbol.h" +#import "PKJSComment.h" +#import "PKJSLiteral.h" +#import "PKJSCaseInsensitiveLiteral.h" +#import "PKJSUppercaseWord.h" +#import "PKJSLowercaseWord.h" + +static void printValue(JSContextRef ctx, JSValueRef val) { + NSString *s = PKJSValueGetNSString(ctx, val, NULL); + NSLog(@"%@", s); +} + +static JSValueRef print(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + printValue(ctx, argv[0]); // TODO check args + return JSValueMakeUndefined(ctx); +} + +static JSObjectRef setUpFunction(JSContextRef ctx, char *funcName, JSObjectCallAsFunctionCallback funcCallback, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef funcNameStr = JSStringCreateWithUTF8CString(funcName); + JSObjectRef func = JSObjectMakeFunctionWithCallback(ctx, funcNameStr, funcCallback); + JSObjectSetProperty(ctx, globalObj, funcNameStr, func, kJSPropertyAttributeNone, ex); + JSStringRelease(funcNameStr); + return func; +} + +static JSObjectRef setUpConstructor(JSContextRef ctx, char *className, JSClassRef jsClass, JSObjectCallAsConstructorCallback constrCallback, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef classNameStr = JSStringCreateWithUTF8CString(className); + JSObjectRef constr = JSObjectMakeConstructor(ctx, jsClass, constrCallback); + JSObjectSetProperty(ctx, globalObj, classNameStr, constr, kJSPropertyAttributeNone, ex); + JSStringRelease(classNameStr); + return constr; +} + +static void setUpClassProperty(JSContextRef ctx, char *propName, JSValueRef prop, JSObjectRef constr, JSValueRef *ex) { + JSStringRef propNameStr = JSStringCreateWithUTF8CString(propName); + JSObjectSetProperty(ctx, constr, propNameStr, prop, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly, NULL); + JSStringRelease(propNameStr); +} + +void PKJSParseKitSetUpContext(JSContextRef ctx) { + JSValueRef ex = NULL; + + setUpFunction(ctx, "print", print, &ex); + + // Assemblies + setUpConstructor(ctx, "PKTokenAssembly", PKTokenAssembly_class(ctx), PKTokenAssembly_construct, &ex); + setUpConstructor(ctx, "PKCharacterAssembly", PKCharacterAssembly_class(ctx), PKCharacterAssembly_construct, &ex); + + // Tokenization + JSObjectRef constr = setUpConstructor(ctx, "PKToken", PKToken_class(ctx), PKToken_construct, &ex); + setUpClassProperty(ctx, "EOFToken", PKToken_getEOFToken(ctx), constr, &ex); // Class property on Token constructor + + setUpConstructor(ctx, "PKTokenizer", PKTokenizer_class(ctx), PKTokenizer_construct, &ex); + setUpConstructor(ctx, "PKWordState", PKWordState_class(ctx), PKWordState_construct, &ex); + setUpConstructor(ctx, "PKQuoteState", PKQuoteState_class(ctx), PKQuoteState_construct, &ex); + setUpConstructor(ctx, "PKNumberState", PKNumberState_class(ctx), PKNumberState_construct, &ex); + setUpConstructor(ctx, "PKSymbolState", PKSymbolState_class(ctx), PKSymbolState_construct, &ex); + setUpConstructor(ctx, "PKCommentState", PKCommentState_class(ctx), PKCommentState_construct, &ex); + setUpConstructor(ctx, "PKWhitespaceState", PKWhitespaceState_class(ctx), PKWhitespaceState_construct, &ex); + + // Parsers + setUpConstructor(ctx, "PKRepetition", PKRepetition_class(ctx), PKRepetition_construct, &ex); + + // Collection Parsers + setUpConstructor(ctx, "PKAlternation", PKAlternation_class(ctx), PKAlternation_construct, &ex); + setUpConstructor(ctx, "PKSequence", PKSequence_class(ctx), PKSequence_construct, &ex); + + // Terminal Parsers + setUpConstructor(ctx, "PKEmpty", PKEmpty_class(ctx), PKEmpty_construct, &ex); + setUpConstructor(ctx, "PKAny", PKAny_class(ctx), PKAny_construct, &ex); + + // Token Terminals + setUpConstructor(ctx, "PKWord", PKWord_class(ctx), PKWord_construct, &ex); + setUpConstructor(ctx, "PKNum", PKNum_class(ctx), PKNum_construct, &ex); + setUpConstructor(ctx, "PKQuotedString", PKQuotedString_class(ctx), PKQuotedString_construct, &ex); + setUpConstructor(ctx, "PKSymbol", PKSymbol_class(ctx), PKSymbol_construct, &ex); + setUpConstructor(ctx, "PKComment", PKComment_class(ctx), PKComment_construct, &ex); + setUpConstructor(ctx, "PKLiteral", PKLiteral_class(ctx), PKLiteral_construct, &ex); + setUpConstructor(ctx, "PKCaseInsensitiveLiteral", PKCaseInsensitiveLiteral_class(ctx), PKCaseInsensitiveLiteral_construct, &ex); + setUpConstructor(ctx, "PKUppercaseWord", PKUppercaseWord_class(ctx), PKUppercaseWord_construct, &ex); + setUpConstructor(ctx, "PKLowercaseWord", PKLowercaseWord_class(ctx), PKLowercaseWord_construct, &ex); +} diff --git a/jssrc/PKJSAlternation.h b/jssrc/PKJSAlternation.h new file mode 100644 index 0000000..6f1fdf5 --- /dev/null +++ b/jssrc/PKJSAlternation.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKAlternation_new(JSContextRef ctx, void *data); +JSClassRef PKAlternation_class(JSContextRef ctx); +JSObjectRef PKAlternation_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSAlternation.m b/jssrc/PKJSAlternation.m new file mode 100644 index 0000000..437e75a --- /dev/null +++ b/jssrc/PKJSAlternation.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSAlternation.h" +#import "PKJSUtils.h" +#import "PKJSCollectionParser.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKAlternation_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKAlternation_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKAlternation_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKAlternation_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKAlternation_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKCollectionParser_class(ctx); + def.staticFunctions = PKAlternation_staticFunctions; + def.staticValues = PKAlternation_staticValues; + def.initialize = PKAlternation_initialize; + def.finalize = PKAlternation_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKAlternation_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKAlternation_class(ctx), data); +} + +JSObjectRef PKAlternation_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKAlternation *data = [[PKAlternation alloc] init]; + return PKAlternation_new(ctx, data); +} diff --git a/jssrc/PKJSAny.h b/jssrc/PKJSAny.h new file mode 100644 index 0000000..a54887a --- /dev/null +++ b/jssrc/PKJSAny.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKAny_new(JSContextRef ctx, void *data); +JSClassRef PKAny_class(JSContextRef ctx); +JSObjectRef PKAny_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSAny.m b/jssrc/PKJSAny.m new file mode 100644 index 0000000..2f672de --- /dev/null +++ b/jssrc/PKJSAny.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSAny.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKAny_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKAny_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKAny_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKAny_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKAny_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKAny_staticFunctions; + def.staticValues = PKAny_staticValues; + def.initialize = PKAny_initialize; + def.finalize = PKAny_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKAny_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKAny_class(ctx), data); +} + +JSObjectRef PKAny_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKAny *data = [[PKAny alloc] init]; + return PKAny_new(ctx, data); +} diff --git a/jssrc/PKJSAssemblerAdapter.h b/jssrc/PKJSAssemblerAdapter.h new file mode 100644 index 0000000..417783c --- /dev/null +++ b/jssrc/PKJSAssemblerAdapter.h @@ -0,0 +1,28 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class PKAssembly; + +@interface PKJSAssemblerAdapter : NSObject { + JSContextRef ctx; + JSObjectRef assemblerFunction; +} +- (void)didMatch:(PKAssembly *)a; + +- (JSObjectRef)assemblerFunction; +- (void)setAssemblerFunction:(JSObjectRef)f fromContext:(JSContextRef)c; +@end diff --git a/jssrc/PKJSAssemblerAdapter.m b/jssrc/PKJSAssemblerAdapter.m new file mode 100644 index 0000000..c39ee42 --- /dev/null +++ b/jssrc/PKJSAssemblerAdapter.m @@ -0,0 +1,80 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSAssemblerAdapter.h" +#import "PKJSTokenAssembly.h" +#import "PKJSCharacterAssembly.h" +#import "PKJSUtils.h" +#import +#import +#import + +@implementation PKJSAssemblerAdapter + +- (id)init { + if (self = [super init]) { + + } + return self; +} + + +- (void)dealloc { + [self setAssemblerFunction:NULL fromContext:NULL]; + [super dealloc]; +} + + +- (void)didMatch:(PKAssembly *)a { + JSValueRef arg = NULL; + if ([a isMemberOfClass:[PKTokenAssembly class]]) { + arg = (JSValueRef)PKTokenAssembly_new(ctx, a); + } else if ([a isMemberOfClass:[PKCharacterAssembly class]]) { + arg = (JSValueRef)PKCharacterAssembly_new(ctx, a); + } else { + NSAssert(0, @"Should not reach here."); + } + + JSValueRef argv[] = { arg }; + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSValueRef ex = NULL; + JSObjectCallAsFunction(ctx, assemblerFunction, globalObj, 1, argv, &ex); + if (ex) { + NSString *s = PKJSValueGetNSString(ctx, ex, NULL); + [NSException raise:@"PKJSException" format:s arguments:NULL]; + } +} + + +- (JSObjectRef)assemblerFunction { + return assemblerFunction; +} + + +- (void)setAssemblerFunction:(JSObjectRef)f fromContext:(JSContextRef)c { + if (assemblerFunction != f) { + if (ctx && assemblerFunction) { + JSValueUnprotect(ctx, assemblerFunction); + JSGarbageCollect(ctx); + } + + ctx = c; + assemblerFunction = f; + if (ctx && assemblerFunction) { + JSValueProtect(ctx, assemblerFunction); + } + } +} + +@end diff --git a/jssrc/PKJSAssembly.h b/jssrc/PKJSAssembly.h new file mode 100644 index 0000000..efddd30 --- /dev/null +++ b/jssrc/PKJSAssembly.h @@ -0,0 +1,18 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKAssembly_new(JSContextRef ctx, void *data); +JSClassRef PKAssembly_class(JSContextRef ctx); diff --git a/jssrc/PKJSAssembly.m b/jssrc/PKJSAssembly.m new file mode 100644 index 0000000..1282f66 --- /dev/null +++ b/jssrc/PKJSAssembly.m @@ -0,0 +1,142 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSAssembly.h" +#import "PKJSToken.h" +#import "PKJSUtils.h" +#import +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKAssembly_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKAssembly_class, "toString"); + PKAssembly *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, [data description], ex); +} + +static JSValueRef PKAssembly_pop(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKAssembly_class, "pop"); + + PKAssembly *data = JSObjectGetPrivate(this); + PKToken *tok = [data pop]; + return PKToken_new(ctx, tok); +} + +static JSValueRef PKAssembly_push(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKAssembly_class, "push"); + PKPreconditionMethodArgc(1, "PKAssembly.push"); + + JSValueRef v = argv[0]; + + PKAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + [data push:obj]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKAssembly_objectsAbove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKAssembly_class, "objectsAbove"); + PKPreconditionMethodArgc(1, "PKAssembly.objectsAbove"); + + JSValueRef v = argv[0]; + + PKAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + id array = [data objectsAbove:obj]; + + return PKNSArrayToJSObject(ctx, array, ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKAssembly_getDefaultDelimiter(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, data.defaultDelimiter, ex); +} + +static JSValueRef PKAssembly_getStack(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + return PKNSArrayToJSObject(ctx, data.stack, ex); +} + +static JSValueRef PKAssembly_getTarget(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + return PKCFTypeToJSValue(ctx, (CFTypeRef)data.target, ex); +} + +static bool PKAssembly_setTarget(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + data.target = PKJSValueGetId(ctx, value, ex); + return true; +} + +static JSValueRef PKAssembly_getIsStackEmpty(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKAssembly *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isStackEmpty); +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKAssembly_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKAssembly_finalize(JSObjectRef this) { + PKAssembly *data = (PKAssembly *)JSObjectGetPrivate(this); + [data autorelease]; +} + +static JSStaticFunction PKAssembly_staticFunctions[] = { +{ "toString", PKAssembly_toString, kJSPropertyAttributeDontDelete }, +{ "pop", PKAssembly_pop, kJSPropertyAttributeDontDelete }, +{ "push", PKAssembly_push, kJSPropertyAttributeDontDelete }, +{ "objectsAbove", PKAssembly_objectsAbove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKAssembly_staticValues[] = { +{ "defaulDelimiter", PKAssembly_getDefaultDelimiter, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // String +{ "stack", PKAssembly_getStack, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Array +{ "target", PKAssembly_getTarget, PKAssembly_setTarget, kJSPropertyAttributeDontDelete }, // Object +{ "isStackEmpty", PKAssembly_getIsStackEmpty, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark ClassMethods + +#pragma mark - +#pragma mark Public + +JSClassRef PKAssembly_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKAssembly_staticFunctions; + def.staticValues = PKAssembly_staticValues; + def.initialize = PKAssembly_initialize; + def.finalize = PKAssembly_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKAssembly_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKAssembly_class(ctx), data); +} diff --git a/jssrc/PKJSCaseInsensitiveLiteral.h b/jssrc/PKJSCaseInsensitiveLiteral.h new file mode 100644 index 0000000..c719403 --- /dev/null +++ b/jssrc/PKJSCaseInsensitiveLiteral.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKCaseInsensitiveLiteral_new(JSContextRef ctx, void *data); +JSClassRef PKCaseInsensitiveLiteral_class(JSContextRef ctx); +JSObjectRef PKCaseInsensitiveLiteral_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSCaseInsensitiveLiteral.m b/jssrc/PKJSCaseInsensitiveLiteral.m new file mode 100644 index 0000000..1414623 --- /dev/null +++ b/jssrc/PKJSCaseInsensitiveLiteral.m @@ -0,0 +1,73 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSCaseInsensitiveLiteral.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKCaseInsensitiveLiteral_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKCaseInsensitiveLiteral_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKCaseInsensitiveLiteral_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKCaseInsensitiveLiteral_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKCaseInsensitiveLiteral_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKCaseInsensitiveLiteral_staticFunctions; + def.staticValues = PKCaseInsensitiveLiteral_staticValues; + def.initialize = PKCaseInsensitiveLiteral_initialize; + def.finalize = PKCaseInsensitiveLiteral_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKCaseInsensitiveLiteral_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKCaseInsensitiveLiteral_class(ctx), data); +} + +JSObjectRef PKCaseInsensitiveLiteral_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKCaseInsensitiveLiteral"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKCaseInsensitiveLiteral *data = [[PKCaseInsensitiveLiteral alloc] initWithString:s]; + return PKCaseInsensitiveLiteral_new(ctx, data); +} diff --git a/jssrc/PKJSCharacterAssembly.h b/jssrc/PKJSCharacterAssembly.h new file mode 100644 index 0000000..8da40a5 --- /dev/null +++ b/jssrc/PKJSCharacterAssembly.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKCharacterAssembly_new(JSContextRef ctx, void *data); +JSClassRef PKCharacterAssembly_class(JSContextRef ctx); +JSObjectRef PKCharacterAssembly_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSCharacterAssembly.m b/jssrc/PKJSCharacterAssembly.m new file mode 100644 index 0000000..81dd943 --- /dev/null +++ b/jssrc/PKJSCharacterAssembly.m @@ -0,0 +1,129 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSCharacterAssembly.h" +#import "PKJSUtils.h" +#import "PKJSAssembly.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKCharacterAssembly_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCharacterAssembly_class, "toString"); + PKCharacterAssembly *data = JSObjectGetPrivate(this); + JSStringRef resStr = JSStringCreateWithCFString((CFStringRef)[data description]); + JSValueRef res = JSValueMakeString(ctx, resStr); + JSStringRelease(resStr); + return res; +} + +static JSValueRef PKCharacterAssembly_pop(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCharacterAssembly_class, "pop"); + PKCharacterAssembly *data = JSObjectGetPrivate(this); + NSNumber *obj = [data pop]; + return JSValueMakeNumber(ctx, [obj doubleValue]); +} + +static JSValueRef PKCharacterAssembly_push(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCharacterAssembly_class, "push"); + PKPreconditionMethodArgc(1, "PKCharacterAssembly.push"); + + JSValueRef v = argv[0]; + + PKCharacterAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + [data push:obj]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKCharacterAssembly_objectsAbove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCharacterAssembly_class, "objectsAbove"); + PKPreconditionMethodArgc(1, "PKCharacterAssembly.objectsAbove"); + + JSValueRef v = argv[0]; + + PKCharacterAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + id array = [data objectsAbove:obj]; + + return PKNSArrayToJSObject(ctx, array, ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKCharacterAssembly_getLength(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKCharacterAssembly *data = JSObjectGetPrivate(this); + return JSValueMakeNumber(ctx, [data length]); +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKCharacterAssembly_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKCharacterAssembly_finalize(JSObjectRef this) { + // released in PKAssembly_finalize +} + +static JSStaticFunction PKCharacterAssembly_staticFunctions[] = { +{ "toString", PKCharacterAssembly_toString, kJSPropertyAttributeDontDelete }, +{ "pop", PKCharacterAssembly_pop, kJSPropertyAttributeDontDelete }, +{ "push", PKCharacterAssembly_push, kJSPropertyAttributeDontDelete }, +{ "objectsAbove", PKCharacterAssembly_objectsAbove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKCharacterAssembly_staticValues[] = { +{ "length", PKCharacterAssembly_getLength, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Number +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark ClassMethods + +#pragma mark - +#pragma mark Public + +JSClassRef PKCharacterAssembly_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKAssembly_class(ctx); + def.staticFunctions = PKCharacterAssembly_staticFunctions; + def.staticValues = PKCharacterAssembly_staticValues; + def.initialize = PKCharacterAssembly_initialize; + def.finalize = PKCharacterAssembly_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKCharacterAssembly_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKCharacterAssembly_class(ctx), data); +} + +JSObjectRef PKCharacterAssembly_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKCharacterAssembly"); + + JSValueRef s = argv[0]; + NSString *string = PKJSValueGetNSString(ctx, s, ex); + + PKCharacterAssembly *data = [[PKCharacterAssembly alloc] initWithString:string]; + return PKCharacterAssembly_new(ctx, data); +} diff --git a/jssrc/PKJSCollectionParser.h b/jssrc/PKJSCollectionParser.h new file mode 100644 index 0000000..697880b --- /dev/null +++ b/jssrc/PKJSCollectionParser.h @@ -0,0 +1,18 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKCollectionParser_new(JSContextRef ctx, void *data); +JSClassRef PKCollectionParser_class(JSContextRef ctx); diff --git a/jssrc/PKJSCollectionParser.m b/jssrc/PKJSCollectionParser.m new file mode 100644 index 0000000..4bc2513 --- /dev/null +++ b/jssrc/PKJSCollectionParser.m @@ -0,0 +1,77 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKCollectionParser.h" +#import "PKJSUtils.h" +#import "PKJSParser.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKCollectionParser_add(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCollectionParser_class, "add"); + PKPreconditionMethodArgc(1, "add"); + + PKCollectionParser *data = JSObjectGetPrivate(this); + + JSObjectRef arg = (JSObjectRef)argv[0]; + PKParser *p = (PKParser *)JSObjectGetPrivate(arg); + [data add:p]; + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKCollectionParser_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKCollectionParser_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKCollectionParser_staticFunctions[] = { +{ "add", PKCollectionParser_add, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKCollectionParser_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKCollectionParser_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKParser_class(ctx); + def.staticFunctions = PKCollectionParser_staticFunctions; + def.staticValues = PKCollectionParser_staticValues; + def.initialize = PKCollectionParser_initialize; + def.finalize = PKCollectionParser_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKCollectionParser_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKCollectionParser_class(ctx), data); +} diff --git a/jssrc/PKJSComment.h b/jssrc/PKJSComment.h new file mode 100644 index 0000000..972e35a --- /dev/null +++ b/jssrc/PKJSComment.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKComment_new(JSContextRef ctx, void *data); +JSClassRef PKComment_class(JSContextRef ctx); +JSObjectRef PKComment_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSComment.m b/jssrc/PKJSComment.m new file mode 100644 index 0000000..6435e4b --- /dev/null +++ b/jssrc/PKJSComment.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSComment.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKComment_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKComment_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKComment_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKComment_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKComment_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKComment_staticFunctions; + def.staticValues = PKComment_staticValues; + def.initialize = PKComment_initialize; + def.finalize = PKComment_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKComment_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKComment_class(ctx), data); +} + +JSObjectRef PKComment_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKComment *data = [[PKComment alloc] init]; + return PKComment_new(ctx, data); +} diff --git a/jssrc/PKJSCommentState.h b/jssrc/PKJSCommentState.h new file mode 100644 index 0000000..ac50ae6 --- /dev/null +++ b/jssrc/PKJSCommentState.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKCommentState_new(JSContextRef ctx, void *data); +JSClassRef PKCommentState_class(JSContextRef ctx); +JSObjectRef PKCommentState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSCommentState.m b/jssrc/PKJSCommentState.m new file mode 100644 index 0000000..abb8744 --- /dev/null +++ b/jssrc/PKJSCommentState.m @@ -0,0 +1,153 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSCommentState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKCommentState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKCommentState]", ex); +} + +static JSValueRef PKCommentState_addSingleLine(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "addSingleLine"); + PKPreconditionMethodArgc(1, "PKCommentState.addSingleLine"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + + PKCommentState *data = JSObjectGetPrivate(this); + [data addSingleLineStartMarker:start]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKCommentState_removeSingleLine(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "removeSingleLine"); + PKPreconditionMethodArgc(1, "PKCommentState.removeSingleLine"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + + PKCommentState *data = JSObjectGetPrivate(this); + [data removeSingleLineStartMarker:start]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKCommentState_addMultiLine(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "addMultiLine"); + PKPreconditionMethodArgc(2, "PKCommentState.addMultiLine"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + NSString *end = PKJSValueGetNSString(ctx, argv[1], ex); + + PKCommentState *data = JSObjectGetPrivate(this); + [data addMultiLineStartMarker:start endMarker:end]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKCommentState_removeMultiLine(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKCommentState_class, "removeSingleLine"); + PKPreconditionMethodArgc(1, "PKCommentState.removeMultiLine"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + + PKCommentState *data = JSObjectGetPrivate(this); + [data removeMultiLineStartMarker:start]; + + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKCommentState_getReportsCommentTokens(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKCommentState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.reportsCommentTokens); +} + +static bool PKCommentState_setReportsCommentTokens(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKCommentState *data = JSObjectGetPrivate(this); + data.reportsCommentTokens = JSValueToBoolean(ctx, value); + return true; +} + +static JSValueRef PKCommentState_getBalancesEOFTerminatedComments(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKCommentState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.balancesEOFTerminatedComments); +} + +static bool PKCommentState_setBalancesEOFTerminatedComments(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKCommentState *data = JSObjectGetPrivate(this); + data.balancesEOFTerminatedComments = JSValueToBoolean(ctx, value); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKCommentState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKCommentState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKCommentState_staticFunctions[] = { +{ "toString", PKCommentState_toString, kJSPropertyAttributeDontDelete }, +{ "addSingleLine", PKCommentState_addSingleLine, kJSPropertyAttributeDontDelete }, +{ "removeSingleLine", PKCommentState_removeSingleLine, kJSPropertyAttributeDontDelete }, +{ "addMultiLine", PKCommentState_addMultiLine, kJSPropertyAttributeDontDelete }, +{ "removeMultiLine", PKCommentState_removeMultiLine, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + + +static JSStaticValue PKCommentState_staticValues[] = { +{ "reportsCommentTokens", PKCommentState_getReportsCommentTokens, PKCommentState_setReportsCommentTokens, kJSPropertyAttributeDontDelete }, // Boolean +{ "balancesEOFTerminatedComments", PKCommentState_getBalancesEOFTerminatedComments, PKCommentState_setBalancesEOFTerminatedComments, kJSPropertyAttributeDontDelete }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKCommentState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKCommentState_staticFunctions; + def.staticValues = PKCommentState_staticValues; + def.initialize = PKCommentState_initialize; + def.finalize = PKCommentState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKCommentState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKCommentState_class(ctx), data); +} + +JSObjectRef PKCommentState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKCommentState *data = [[PKCommentState alloc] init]; + return PKCommentState_new(ctx, data); +} diff --git a/jssrc/PKJSDelimitState.h b/jssrc/PKJSDelimitState.h new file mode 100644 index 0000000..6b462e6 --- /dev/null +++ b/jssrc/PKJSDelimitState.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKDelimitState_new(JSContextRef ctx, void *data); +JSClassRef PKDelimitState_class(JSContextRef ctx); +JSObjectRef PKDelimitState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSDelimitState.m b/jssrc/PKJSDelimitState.m new file mode 100644 index 0000000..f06425f --- /dev/null +++ b/jssrc/PKJSDelimitState.m @@ -0,0 +1,108 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSDelimitState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKDelimitState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKDelimitState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKDelimitState]", ex); +} + +static JSValueRef PKDelimitState_add(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKDelimitState_class, "add"); + PKPreconditionMethodArgc(4, "PKDelimitState.add"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + NSString *end = PKJSValueGetNSString(ctx, argv[1], ex); + NSString *chars = PKJSValueGetNSString(ctx, argv[2], ex); + BOOL invert = JSValueToBoolean(ctx, argv[3]); + + PKDelimitState *data = JSObjectGetPrivate(this); + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:chars]; + if (invert) { + cs = [cs invertedSet]; + } + [data addStartMarker:start endMarker:end allowedCharacterSet:cs]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKDelimitState_remove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKDelimitState_class, "remove"); + PKPreconditionMethodArgc(1, "PKDelimitState.remove"); + + NSString *start = PKJSValueGetNSString(ctx, argv[0], ex); + + PKDelimitState *data = JSObjectGetPrivate(this); + [data removeStartMarker:start]; + + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKDelimitState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKDelimitState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKDelimitState_staticFunctions[] = { +{ "toString", PKDelimitState_toString, kJSPropertyAttributeDontDelete }, +{ "add", PKDelimitState_add, kJSPropertyAttributeDontDelete }, +{ "remove", PKDelimitState_remove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKDelimitState_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKDelimitState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKDelimitState_staticFunctions; + def.staticValues = PKDelimitState_staticValues; + def.initialize = PKDelimitState_initialize; + def.finalize = PKDelimitState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKDelimitState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKDelimitState_class(ctx), data); +} + +JSObjectRef PKDelimitState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKDelimitState *data = [[PKDelimitState alloc] init]; + return PKDelimitState_new(ctx, data); +} diff --git a/jssrc/PKJSDelimitedString.h b/jssrc/PKJSDelimitedString.h new file mode 100644 index 0000000..2ffc1de --- /dev/null +++ b/jssrc/PKJSDelimitedString.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKDelimitedString_new(JSContextRef ctx, void *data); +JSClassRef PKDelimitedString_class(JSContextRef ctx); +JSObjectRef PKDelimitedString_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSDelimitedString.m b/jssrc/PKJSDelimitedString.m new file mode 100644 index 0000000..1763308 --- /dev/null +++ b/jssrc/PKJSDelimitedString.m @@ -0,0 +1,73 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSDelimitedString.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKDelimitedString_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKDelimitedString_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKDelimitedString_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKDelimitedString_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKDelimitedString_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKDelimitedString_staticFunctions; + def.staticValues = PKDelimitedString_staticValues; + def.initialize = PKDelimitedString_initialize; + def.finalize = PKDelimitedString_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKDelimitedString_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKDelimitedString_class(ctx), data); +} + +JSObjectRef PKDelimitedString_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKDelimitedString"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKDelimitedString *data = [[PKDelimitedString alloc] initWithString:s]; + return PKDelimitedString_new(ctx, data); +} diff --git a/jssrc/PKJSEmpty.h b/jssrc/PKJSEmpty.h new file mode 100644 index 0000000..068ebe1 --- /dev/null +++ b/jssrc/PKJSEmpty.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKEmpty_new(JSContextRef ctx, void *data); +JSClassRef PKEmpty_class(JSContextRef ctx); +JSObjectRef PKEmpty_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSEmpty.m b/jssrc/PKJSEmpty.m new file mode 100644 index 0000000..20c1cbd --- /dev/null +++ b/jssrc/PKJSEmpty.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSEmpty.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKEmpty_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKEmpty_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKEmpty_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKEmpty_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKEmpty_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKEmpty_staticFunctions; + def.staticValues = PKEmpty_staticValues; + def.initialize = PKEmpty_initialize; + def.finalize = PKEmpty_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKEmpty_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKEmpty_class(ctx), data); +} + +JSObjectRef PKEmpty_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKEmpty *data = [[PKEmpty alloc] init]; + return PKEmpty_new(ctx, data); +} diff --git a/jssrc/PKJSLiteral.h b/jssrc/PKJSLiteral.h new file mode 100644 index 0000000..4358010 --- /dev/null +++ b/jssrc/PKJSLiteral.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKLiteral_new(JSContextRef ctx, void *data); +JSClassRef PKLiteral_class(JSContextRef ctx); +JSObjectRef PKLiteral_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSLiteral.m b/jssrc/PKJSLiteral.m new file mode 100644 index 0000000..65540c6 --- /dev/null +++ b/jssrc/PKJSLiteral.m @@ -0,0 +1,73 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKLiteral.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKLiteral_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKLiteral_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKLiteral_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKLiteral_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKLiteral_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKLiteral_staticFunctions; + def.staticValues = PKLiteral_staticValues; + def.initialize = PKLiteral_initialize; + def.finalize = PKLiteral_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKLiteral_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKLiteral_class(ctx), data); +} + +JSObjectRef PKLiteral_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKLiteral"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKLiteral *data = [[PKLiteral alloc] initWithString:s]; + return PKLiteral_new(ctx, data); +} diff --git a/jssrc/PKJSLowercaseWord.h b/jssrc/PKJSLowercaseWord.h new file mode 100644 index 0000000..3177bd5 --- /dev/null +++ b/jssrc/PKJSLowercaseWord.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKLowercaseWord_new(JSContextRef ctx, void *data); +JSClassRef PKLowercaseWord_class(JSContextRef ctx); +JSObjectRef PKLowercaseWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSLowercaseWord.m b/jssrc/PKJSLowercaseWord.m new file mode 100644 index 0000000..e4c8942 --- /dev/null +++ b/jssrc/PKJSLowercaseWord.m @@ -0,0 +1,73 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSLowercaseWord.h" +#import "PKJSUtils.h" +#import "PKJSWord.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKLowercaseWord_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKLowercaseWord_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKLowercaseWord_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKLowercaseWord_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKLowercaseWord_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKWord_class(ctx); + def.staticFunctions = PKLowercaseWord_staticFunctions; + def.staticValues = PKLowercaseWord_staticValues; + def.initialize = PKLowercaseWord_initialize; + def.finalize = PKLowercaseWord_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKLowercaseWord_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKLowercaseWord_class(ctx), data); +} + +JSObjectRef PKLowercaseWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKLowercaseWord"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKLowercaseWord *data = [[PKLowercaseWord alloc] initWithString:s]; + return PKLowercaseWord_new(ctx, data); +} diff --git a/jssrc/PKJSNum.h b/jssrc/PKJSNum.h new file mode 100644 index 0000000..9304a10 --- /dev/null +++ b/jssrc/PKJSNum.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKNum_new(JSContextRef ctx, void *data); +JSClassRef PKNum_class(JSContextRef ctx); +JSObjectRef PKNum_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSNum.m b/jssrc/PKJSNum.m new file mode 100644 index 0000000..4cc1182 --- /dev/null +++ b/jssrc/PKJSNum.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSNum.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKNum_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKNum_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKNum_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKNum_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKNum_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKNum_staticFunctions; + def.staticValues = PKNum_staticValues; + def.initialize = PKNum_initialize; + def.finalize = PKNum_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKNum_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKNum_class(ctx), data); +} + +JSObjectRef PKNum_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKNumber *data = [[PKNumber alloc] init]; + return PKNum_new(ctx, data); +} diff --git a/jssrc/PKJSNumberState.h b/jssrc/PKJSNumberState.h new file mode 100644 index 0000000..cc0e483 --- /dev/null +++ b/jssrc/PKJSNumberState.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKNumberState_new(JSContextRef ctx, void *data); +JSClassRef PKNumberState_class(JSContextRef ctx); +JSObjectRef PKNumberState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSNumberState.m b/jssrc/PKJSNumberState.m new file mode 100644 index 0000000..60345d9 --- /dev/null +++ b/jssrc/PKJSNumberState.m @@ -0,0 +1,87 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSNumberState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKNumberState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKNumberState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKNumberState]", ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKNumberState_getAllowsTrailingDot(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKNumberState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.allowsTrailingDot); +} + +static bool PKNumberState_setAllowsTrailingDot(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKNumberState *data = JSObjectGetPrivate(this); + data.allowsTrailingDot = JSValueToBoolean(ctx, value); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKNumberState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKNumberState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKNumberState_staticFunctions[] = { +{ "toString", PKNumberState_toString, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKNumberState_staticValues[] = { +{ "allowsTrailingDot", PKNumberState_getAllowsTrailingDot, PKNumberState_setAllowsTrailingDot, kJSPropertyAttributeDontDelete }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKNumberState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKNumberState_staticFunctions; + def.staticValues = PKNumberState_staticValues; + def.initialize = PKNumberState_initialize; + def.finalize = PKNumberState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKNumberState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKNumberState_class(ctx), data); +} + +JSObjectRef PKNumberState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKNumberState *data = [[PKNumberState alloc] init]; + return PKNumberState_new(ctx, data); +} diff --git a/jssrc/PKJSParser.h b/jssrc/PKJSParser.h new file mode 100644 index 0000000..7f62cb4 --- /dev/null +++ b/jssrc/PKJSParser.h @@ -0,0 +1,18 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKParser_new(JSContextRef ctx, void *data); +JSClassRef PKParser_class(JSContextRef ctx); diff --git a/jssrc/PKJSParser.m b/jssrc/PKJSParser.m new file mode 100644 index 0000000..106e879 --- /dev/null +++ b/jssrc/PKJSParser.m @@ -0,0 +1,160 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSParser.h" +#import "PKJSUtils.h" +#import "PKJSAssemblerAdapter.h" +#import "PKJSAssembly.h" +#import "PKJSTokenAssembly.h" +#import "PKJSCharacterAssembly.h" +#import +#import +#import +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKParser_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKParser_class, "toString"); + PKParser *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, [data description], ex); +} + +static JSValueRef PKParser_bestMatch(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKParser_class, "bestMatch"); + PKPreconditionMethodArgc(1, "bestMatch"); + + PKParser *data = JSObjectGetPrivate(this); + + JSObjectRef arg = (JSObjectRef)argv[0]; + PKAssembly *a = (PKAssembly *)JSObjectGetPrivate(arg); + a = [data bestMatchFor:a]; + + JSObjectRef result = NULL; + if ([a isMemberOfClass:[PKTokenAssembly class]]) { + result = PKTokenAssembly_new(ctx, a); + } else if ([a isMemberOfClass:[PKCharacterAssembly class]]) { + result = PKCharacterAssembly_new(ctx, a); + } + + return result; +} + +static JSValueRef PKParser_completeMatch(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKParser_class, "completeMatch"); + PKPreconditionMethodArgc(1, "completeMatch"); + + PKParser *data = JSObjectGetPrivate(this); + + JSObjectRef arg = (JSObjectRef)argv[0]; + PKAssembly *a = (PKAssembly *)JSObjectGetPrivate(arg); + a = [data completeMatchFor:a]; + + JSObjectRef result = NULL; + if ([a isMemberOfClass:[PKTokenAssembly class]]) { + result = PKTokenAssembly_new(ctx, a); + } else if ([a isMemberOfClass:[PKCharacterAssembly class]]) { + result = PKCharacterAssembly_new(ctx, a); + } + + return result; +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKParser_getAssembler(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKParser *data = JSObjectGetPrivate(this); + id assembler = data.assembler; + if ([assembler isMemberOfClass:[PKJSAssemblerAdapter class]]) { + return [assembler assemblerFunction]; + } else { + return NULL; + } +} + +static bool PKParser_setAssembler(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + if (!JSValueIsObject(ctx, value) || !JSObjectIsFunction(ctx, (JSObjectRef)value)) { + (*ex) = PKNSStringToJSValue(ctx, @"only a function object can be set as a parser's assembler property", ex); + return false; + } + + PKParser *data = JSObjectGetPrivate(this); + PKJSAssemblerAdapter *adapter = [[PKJSAssemblerAdapter alloc] init]; // retained. released in PKParser_finalize + [adapter setAssemblerFunction:(JSObjectRef)value fromContext:ctx]; + [data setAssembler:adapter selector:@selector(didMatch:)]; + return true; +} + +static JSValueRef PKParser_getName(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKParser *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, data.name, ex); +} + +static bool PKParser_setName(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKParser *data = JSObjectGetPrivate(this); + data.name = PKJSValueGetNSString(ctx, value, ex); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKParser_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKParser_finalize(JSObjectRef this) { + PKParser *data = (PKParser *)JSObjectGetPrivate(this); + id assembler = data.assembler; + data.assembler = nil; + if ([assembler isMemberOfClass:[PKJSAssemblerAdapter class]]) { + [assembler autorelease]; + } + [data autorelease]; +} + +static JSStaticFunction PKParser_staticFunctions[] = { +{ "toString", PKParser_toString, kJSPropertyAttributeDontDelete }, +{ "bestMatch", PKParser_bestMatch, kJSPropertyAttributeDontDelete }, +{ "completeMatch", PKParser_completeMatch, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKParser_staticValues[] = { +{ "assembler", PKParser_getAssembler, PKParser_setAssembler, kJSPropertyAttributeDontDelete }, // Function +{ "name", PKParser_getName, PKParser_setName, kJSPropertyAttributeDontDelete }, // String +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKParser_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKParser_staticFunctions; + def.staticValues = PKParser_staticValues; + def.initialize = PKParser_initialize; + def.finalize = PKParser_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKParser_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKParser_class(ctx), data); +} diff --git a/jssrc/PKJSPattern.h b/jssrc/PKJSPattern.h new file mode 100644 index 0000000..d0b678a --- /dev/null +++ b/jssrc/PKJSPattern.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKPattern_new(JSContextRef ctx, void *data); +JSClassRef PKPattern_class(JSContextRef ctx); +JSObjectRef PKPattern_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSPattern.m b/jssrc/PKJSPattern.m new file mode 100644 index 0000000..d5938ea --- /dev/null +++ b/jssrc/PKJSPattern.m @@ -0,0 +1,86 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSPattern.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +//static JSValueRef PKPattern_invertedPattern(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { +// PKPreconditionInstaceOf(PKPattern_class, "invertedPattern"); +// +// PKPattern *data = JSObjectGetPrivate(this); +// return PKPattern_new(ctx, [data invertedPattern]); +//} +// +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKPattern_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKPattern_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKPattern_staticFunctions[] = { +//{ "invertedPattern", PKPattern_invertedPattern, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKPattern_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKPattern_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKPattern_staticFunctions; + def.staticValues = PKPattern_staticValues; + def.initialize = PKPattern_initialize; + def.finalize = PKPattern_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKPattern_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKPattern_class(ctx), data); +} + +JSObjectRef PKPattern_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKPattern"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + NSInteger opts = PKPatternOptionsNone; + + if (argc > 1) { + opts = JSValueToNumber(ctx, argv[1], ex); + } + + PKPattern *data = [[PKPattern alloc] initWithString:s options:opts]; + return PKPattern_new(ctx, data); +} diff --git a/jssrc/PKJSQuoteState.h b/jssrc/PKJSQuoteState.h new file mode 100644 index 0000000..4f9ffd4 --- /dev/null +++ b/jssrc/PKJSQuoteState.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKQuoteState_new(JSContextRef ctx, void *data); +JSClassRef PKQuoteState_class(JSContextRef ctx); +JSObjectRef PKQuoteState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSQuoteState.m b/jssrc/PKJSQuoteState.m new file mode 100644 index 0000000..87a7d8b --- /dev/null +++ b/jssrc/PKJSQuoteState.m @@ -0,0 +1,87 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSQuoteState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKQuoteState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKQuoteState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKQuoteState]", ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKQuoteState_getBalancesEOFTerminatedQuotes(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKQuoteState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.balancesEOFTerminatedQuotes); +} + +static bool PKQuoteState_setBalancesEOFTerminatedQuotes(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKQuoteState *data = JSObjectGetPrivate(this); + data.balancesEOFTerminatedQuotes = JSValueToBoolean(ctx, value); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKQuoteState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKQuoteState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKQuoteState_staticFunctions[] = { +{ "toString", PKQuoteState_toString, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKQuoteState_staticValues[] = { +{ "balancesEOFTerminatedQuotes", PKQuoteState_getBalancesEOFTerminatedQuotes, PKQuoteState_setBalancesEOFTerminatedQuotes, kJSPropertyAttributeDontDelete }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKQuoteState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKQuoteState_staticFunctions; + def.staticValues = PKQuoteState_staticValues; + def.initialize = PKQuoteState_initialize; + def.finalize = PKQuoteState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKQuoteState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKQuoteState_class(ctx), data); +} + +JSObjectRef PKQuoteState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKQuoteState *data = [[PKQuoteState alloc] init]; + return PKQuoteState_new(ctx, data); +} diff --git a/jssrc/PKJSQuotedString.h b/jssrc/PKJSQuotedString.h new file mode 100644 index 0000000..e328a14 --- /dev/null +++ b/jssrc/PKJSQuotedString.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKQuotedString_new(JSContextRef ctx, void *data); +JSClassRef PKQuotedString_class(JSContextRef ctx); +JSObjectRef PKQuotedString_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSQuotedString.m b/jssrc/PKJSQuotedString.m new file mode 100644 index 0000000..649b7fc --- /dev/null +++ b/jssrc/PKJSQuotedString.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSQuotedString.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKQuotedString_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKQuotedString_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKQuotedString_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKQuotedString_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKQuotedString_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKQuotedString_staticFunctions; + def.staticValues = PKQuotedString_staticValues; + def.initialize = PKQuotedString_initialize; + def.finalize = PKQuotedString_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKQuotedString_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKQuotedString_class(ctx), data); +} + +JSObjectRef PKQuotedString_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKQuotedString *data = [[PKQuotedString alloc] init]; + return PKQuotedString_new(ctx, data); +} diff --git a/jssrc/PKJSRepetition.h b/jssrc/PKJSRepetition.h new file mode 100644 index 0000000..1e61cef --- /dev/null +++ b/jssrc/PKJSRepetition.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKRepetition_new(JSContextRef ctx, void *data); +JSClassRef PKRepetition_class(JSContextRef ctx); +JSObjectRef PKRepetition_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSRepetition.m b/jssrc/PKJSRepetition.m new file mode 100644 index 0000000..68cdb23 --- /dev/null +++ b/jssrc/PKJSRepetition.m @@ -0,0 +1,78 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSRepetition.h" +#import "PKJSUtils.h" +#import "PKJSParser.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKRepetition_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKRepetition_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKRepetition_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKRepetition_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKRepetition_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKParser_class(ctx); + def.staticFunctions = PKRepetition_staticFunctions; + def.staticValues = PKRepetition_staticValues; + def.initialize = PKRepetition_initialize; + def.finalize = PKRepetition_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKRepetition_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKRepetition_class(ctx), data); +} + +JSObjectRef PKRepetition_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKRepetition"); + + JSValueRef v = argv[0]; + if (!PKJSValueIsInstanceOfClass(ctx, v, "PKParser", ex)) { + *ex = PKNSStringToJSValue(ctx, @"argument to PKRepeition constructor must be and instance of a PKParser subclass", ex); + } + + PKParser *p = JSObjectGetPrivate((JSObjectRef)v); + + PKRepetition *data = [[PKRepetition alloc] initWithSubparser:p]; + return PKRepetition_new(ctx, data); +} diff --git a/jssrc/PKJSSequence.h b/jssrc/PKJSSequence.h new file mode 100644 index 0000000..e0f633a --- /dev/null +++ b/jssrc/PKJSSequence.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKSequence_new(JSContextRef ctx, void *data); +JSClassRef PKSequence_class(JSContextRef ctx); +JSObjectRef PKSequence_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSSequence.m b/jssrc/PKJSSequence.m new file mode 100644 index 0000000..6868060 --- /dev/null +++ b/jssrc/PKJSSequence.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSSequence.h" +#import "PKJSUtils.h" +#import "PKJSCollectionParser.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKSequence_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKSequence_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKSequence_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKSequence_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKSequence_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKCollectionParser_class(ctx); + def.staticFunctions = PKSequence_staticFunctions; + def.staticValues = PKSequence_staticValues; + def.initialize = PKSequence_initialize; + def.finalize = PKSequence_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKSequence_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKSequence_class(ctx), data); +} + +JSObjectRef PKSequence_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKSequence *data = [[PKSequence alloc] init]; + return PKSequence_new(ctx, data); +} diff --git a/jssrc/PKJSSymbol.h b/jssrc/PKJSSymbol.h new file mode 100644 index 0000000..3441639 --- /dev/null +++ b/jssrc/PKJSSymbol.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKSymbol_new(JSContextRef ctx, void *data); +JSClassRef PKSymbol_class(JSContextRef ctx); +JSObjectRef PKSymbol_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSSymbol.m b/jssrc/PKJSSymbol.m new file mode 100644 index 0000000..582bd18 --- /dev/null +++ b/jssrc/PKJSSymbol.m @@ -0,0 +1,75 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSSymbol.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKSymbol_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKSymbol_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKSymbol_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKSymbol_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKSymbol_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKSymbol_staticFunctions; + def.staticValues = PKSymbol_staticValues; + def.initialize = PKSymbol_initialize; + def.finalize = PKSymbol_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKSymbol_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKSymbol_class(ctx), data); +} + +JSObjectRef PKSymbol_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + NSString *s = nil; + + if (argc > 0) { + s = PKJSValueGetNSString(ctx, argv[0], ex); + } + + PKSymbol *data = [[PKSymbol alloc] initWithString:s]; + return PKSymbol_new(ctx, data); +} diff --git a/jssrc/PKJSSymbolState.h b/jssrc/PKJSSymbolState.h new file mode 100644 index 0000000..230b7da --- /dev/null +++ b/jssrc/PKJSSymbolState.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKSymbolState_new(JSContextRef ctx, void *data); +JSClassRef PKSymbolState_class(JSContextRef ctx); +JSObjectRef PKSymbolState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSSymbolState.m b/jssrc/PKJSSymbolState.m new file mode 100644 index 0000000..60f83e8 --- /dev/null +++ b/jssrc/PKJSSymbolState.m @@ -0,0 +1,101 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSSymbolState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKSymbolState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKSymbolState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKSymbolState]", ex); +} + +static JSValueRef PKSymbolState_add(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKSymbolState_class, "add"); + PKPreconditionMethodArgc(1, "PKSymbolState.add"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKSymbolState *data = JSObjectGetPrivate(this); + [data add:s]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKSymbolState_remove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKSymbolState_class, "remove"); + PKPreconditionMethodArgc(1, "PKSymbolState.remove"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKSymbolState *data = JSObjectGetPrivate(this); + [data remove:s]; + + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKSymbolState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKSymbolState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKSymbolState_staticFunctions[] = { +{ "toString", PKSymbolState_toString, kJSPropertyAttributeDontDelete }, +{ "add", PKSymbolState_add, kJSPropertyAttributeDontDelete }, +{ "remove", PKSymbolState_remove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKSymbolState_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKSymbolState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKSymbolState_staticFunctions; + def.staticValues = PKSymbolState_staticValues; + def.initialize = PKSymbolState_initialize; + def.finalize = PKSymbolState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKSymbolState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKSymbolState_class(ctx), data); +} + +JSObjectRef PKSymbolState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKSymbolState *data = [[PKSymbolState alloc] init]; + return PKSymbolState_new(ctx, data); +} diff --git a/jssrc/PKJSTerminal.h b/jssrc/PKJSTerminal.h new file mode 100644 index 0000000..4ed426b --- /dev/null +++ b/jssrc/PKJSTerminal.h @@ -0,0 +1,18 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKTerminal_new(JSContextRef ctx, void *data); +JSClassRef PKTerminal_class(JSContextRef ctx); diff --git a/jssrc/PKJSTerminal.m b/jssrc/PKJSTerminal.m new file mode 100644 index 0000000..d982fb0 --- /dev/null +++ b/jssrc/PKJSTerminal.m @@ -0,0 +1,73 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSTerminal.h" +#import "PKJSUtils.h" +#import "PKJSParser.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKTerminal_discard(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTerminal_class, "discard"); + + PKTerminal *data = JSObjectGetPrivate(this); + [data discard]; + return this; +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTerminal_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTerminal_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKTerminal_staticFunctions[] = { +{ "discard", PKTerminal_discard, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKTerminal_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKTerminal_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKParser_class(ctx); + def.staticFunctions = PKTerminal_staticFunctions; + def.staticValues = PKTerminal_staticValues; + def.initialize = PKTerminal_initialize; + def.finalize = PKTerminal_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTerminal_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTerminal_class(ctx), data); +} diff --git a/jssrc/PKJSToken.h b/jssrc/PKJSToken.h new file mode 100644 index 0000000..7154e48 --- /dev/null +++ b/jssrc/PKJSToken.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKToken_new(JSContextRef ctx, void *data); +JSClassRef PKToken_class(JSContextRef ctx); +JSObjectRef PKToken_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); + +// a JS Class method +//JSValueRef PKToken_EOFToken(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* ex); + +// a JS Class property +JSValueRef PKToken_getEOFToken(JSContextRef ctx); diff --git a/jssrc/PKJSToken.m b/jssrc/PKJSToken.m new file mode 100644 index 0000000..37935b1 --- /dev/null +++ b/jssrc/PKJSToken.m @@ -0,0 +1,165 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSToken.h" +#import "PKJSUtils.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKToken_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKToken_class, "toString"); + PKToken *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, [data debugDescription], ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKToken_getTokenType(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeNumber(ctx, data.tokenType); +} + +static JSValueRef PKToken_getStringValue(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, data.stringValue, ex); +} + +static JSValueRef PKToken_getFloatValue(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeNumber(ctx, data.floatValue); +} + +static JSValueRef PKToken_getIsNumber(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isNumber); +} + +static JSValueRef PKToken_getIsSymbol(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isSymbol); +} + +static JSValueRef PKToken_getIsWord(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isWord); +} + +static JSValueRef PKToken_getIsQuotedString(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isQuotedString); +} + +static JSValueRef PKToken_getIsWhitespace(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isWhitespace); +} + +static JSValueRef PKToken_getIsComment(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isComment); +} + +static JSValueRef PKToken_getIsDelimitedString(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKToken *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.isDelimitedString); +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKToken_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKToken_finalize(JSObjectRef this) { + PKToken *data = (PKToken *)JSObjectGetPrivate(this); + [data autorelease]; +} + +static JSStaticFunction PKToken_staticFunctions[] = { +{ "toString", PKToken_toString, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKToken_staticValues[] = { +{ "tokenType", PKToken_getTokenType, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Number +{ "stringValue", PKToken_getStringValue, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // String +{ "floatValue", PKToken_getFloatValue, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Number +{ "isNumber", PKToken_getIsNumber, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isSymbol", PKToken_getIsSymbol, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isWord", PKToken_getIsWord, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isQuotedString", PKToken_getIsQuotedString, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isWhitespace", PKToken_getIsWhitespace, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isComment", PKToken_getIsComment, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ "isDelimitedString", PKToken_getIsDelimitedString, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Class Methods + +// JSObjectCallAsFunctionCallback +//JSValueRef PKToken_EOFToken(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { +// static JSValueRef eof = NULL; +// if (!eof) { +// eof = PKToken_new(ctx, [PKToken EOFToken]); +// JSValueProtect(ctx, eof); // is this necessary/appropriate? +// } +// return eof; +//} + +#pragma mark - +#pragma mark Class Properties + +JSValueRef PKToken_getEOFToken(JSContextRef ctx) { + static JSObjectRef eof = NULL; + if (!eof) { + eof = PKToken_new(ctx, [PKToken EOFToken]); + } + return eof; +} + +#pragma mark - +#pragma mark Public + +JSClassRef PKToken_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKToken_staticFunctions; + def.staticValues = PKToken_staticValues; + def.initialize = PKToken_initialize; + def.finalize = PKToken_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKToken_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKToken_class(ctx), data); +} + +JSObjectRef PKToken_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(3, "PKToken"); + + CGFloat tokenType = JSValueToNumber(ctx, argv[0], NULL); + NSString *stringValue = PKJSValueGetNSString(ctx, argv[1], ex); + CGFloat floatValue = JSValueToNumber(ctx, argv[2], NULL); + + PKToken *data = [[PKToken alloc] initWithTokenType:tokenType stringValue:stringValue floatValue:floatValue]; + return PKToken_new(ctx, data); +} diff --git a/jssrc/PKJSTokenAssembly.h b/jssrc/PKJSTokenAssembly.h new file mode 100644 index 0000000..fb9c9e3 --- /dev/null +++ b/jssrc/PKJSTokenAssembly.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKTokenAssembly_new(JSContextRef ctx, void *data); +JSClassRef PKTokenAssembly_class(JSContextRef ctx); +JSObjectRef PKTokenAssembly_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSTokenAssembly.m b/jssrc/PKJSTokenAssembly.m new file mode 100644 index 0000000..c8b40d7 --- /dev/null +++ b/jssrc/PKJSTokenAssembly.m @@ -0,0 +1,127 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSTokenAssembly.h" +#import "PKJSToken.h" +#import "PKJSUtils.h" +#import "PKJSAssembly.h" +#import +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKTokenAssembly_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenAssembly_class, "toString"); + PKTokenAssembly *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, [data description], ex); +} + +static JSValueRef PKTokenAssembly_pop(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenAssembly_class, "pop"); + PKTokenAssembly *data = JSObjectGetPrivate(this); + PKToken *tok = [data pop]; + return PKToken_new(ctx, tok); +} + +static JSValueRef PKTokenAssembly_push(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenAssembly_class, "push"); + PKPreconditionMethodArgc(1, "PKTokenAssembly.push"); + + JSValueRef v = argv[0]; + + PKTokenAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + [data push:obj]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKTokenAssembly_objectsAbove(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenAssembly_class, "objectsAbove"); + PKPreconditionMethodArgc(1, "PKTokenAssembly.objectsAbove"); + + JSValueRef v = argv[0]; + + PKTokenAssembly *data = JSObjectGetPrivate(this); + id obj = PKJSValueGetId(ctx, v, ex); + id array = [data objectsAbove:obj]; + + return PKNSArrayToJSObject(ctx, array, ex); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKTokenAssembly_getLength(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenAssembly *data = JSObjectGetPrivate(this); + return JSValueMakeNumber(ctx, [data length]); +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTokenAssembly_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTokenAssembly_finalize(JSObjectRef this) { + // released in PKAssembly_finalize +} + +static JSStaticFunction PKTokenAssembly_staticFunctions[] = { +{ "toString", PKTokenAssembly_toString, kJSPropertyAttributeDontDelete }, +{ "pop", PKTokenAssembly_pop, kJSPropertyAttributeDontDelete }, +{ "push", PKTokenAssembly_push, kJSPropertyAttributeDontDelete }, +{ "objectsAbove", PKTokenAssembly_objectsAbove, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKTokenAssembly_staticValues[] = { +{ "length", PKTokenAssembly_getLength, NULL, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly }, // Number +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark ClassMethods + +#pragma mark - +#pragma mark Public + +JSClassRef PKTokenAssembly_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKAssembly_class(ctx); + def.staticFunctions = PKTokenAssembly_staticFunctions; + def.staticValues = PKTokenAssembly_staticValues; + def.initialize = PKTokenAssembly_initialize; + def.finalize = PKTokenAssembly_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTokenAssembly_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTokenAssembly_class(ctx), data); +} + +JSObjectRef PKTokenAssembly_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKTokenAssembly"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKTokenAssembly *data = [[PKTokenAssembly alloc] initWithString:s]; + return PKTokenAssembly_new(ctx, data); +} diff --git a/jssrc/PKJSTokenizer.h b/jssrc/PKJSTokenizer.h new file mode 100644 index 0000000..1aa5084 --- /dev/null +++ b/jssrc/PKJSTokenizer.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKTokenizer_new(JSContextRef ctx, void *data); +JSClassRef PKTokenizer_class(JSContextRef ctx); +JSObjectRef PKTokenizer_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSTokenizer.m b/jssrc/PKJSTokenizer.m new file mode 100644 index 0000000..2a93eea --- /dev/null +++ b/jssrc/PKJSTokenizer.m @@ -0,0 +1,221 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSTokenizer.h" +#import "PKJSUtils.h" +#import "PKJSToken.h" +#import "PKJSWordState.h" +#import "PKJSNumberState.h" +#import "PKJSQuoteState.h" +#import "PKJSWhitespaceState.h" +#import "PKJSCommentState.h" +#import "PKJSSymbolState.h" +#import +#import +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKTokenizer_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenizer_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKTokenizer]", ex); +} + +static JSValueRef PKTokenizer_nextToken(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenizer_class, "nextToken"); + PKTokenizer *data = JSObjectGetPrivate(this); + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = [data nextToken]; + + if (eof == tok) { + return PKToken_getEOFToken(ctx); + } + + return PKToken_new(ctx, tok); +} + +static JSValueRef PKTokenizer_setTokenizerState(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKTokenizer_class, "setTokenizerState"); + PKPreconditionMethodArgc(3, "PKTokenizer.setTokenizerState"); + + JSObjectRef stateObj = (JSObjectRef)argv[0]; + PKTokenizerState *state = JSObjectGetPrivate(stateObj); + NSString *from = PKJSValueGetNSString(ctx, argv[1], ex); + NSString *to = PKJSValueGetNSString(ctx, argv[2], ex); + + PKTokenizer *data = JSObjectGetPrivate(this); + [data setTokenizerState:state from:[from characterAtIndex:0] to:[to characterAtIndex:0]]; + + return JSValueMakeUndefined(ctx); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKTokenizer_getString(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKNSStringToJSValue(ctx, data.string, ex); +} + +static bool PKTokenizer_setString(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + data.string = PKJSValueGetNSString(ctx, value, ex); + return true; +} + +static JSValueRef PKTokenizer_getWordState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKWordState_new(ctx, data.wordState); + return NULL; +} + +static bool PKTokenizer_setWordState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKWordState *state = JSObjectGetPrivate(stateObj); + data.wordState = state; + return true; +} + +static JSValueRef PKTokenizer_getNumberState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKNumberState_new(ctx, data.numberState); + return NULL; +} + +static bool PKTokenizer_setNumberState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKNumberState *state = JSObjectGetPrivate(stateObj); + data.numberState = state; + return true; +} + +static JSValueRef PKTokenizer_getQuoteState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKQuoteState_new(ctx, data.quoteState); + return NULL; +} + +static bool PKTokenizer_setQuoteState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKQuoteState *state = JSObjectGetPrivate(stateObj); + data.quoteState = state; + return true; +} + +static JSValueRef PKTokenizer_getSymbolState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKSymbolState_new(ctx, data.symbolState); + return NULL; +} + +static bool PKTokenizer_setSymbolState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKSymbolState *state = JSObjectGetPrivate(stateObj); + data.symbolState = state; + return true; +} + +static JSValueRef PKTokenizer_getWhitespaceState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKWhitespaceState_new(ctx, data.whitespaceState); + return NULL; +} + +static bool PKTokenizer_setWhitespaceState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKWhitespaceState *state = JSObjectGetPrivate(stateObj); + data.whitespaceState = state; + return true; +} + +static JSValueRef PKTokenizer_getCommentState(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + return PKCommentState_new(ctx, data.commentState); + return NULL; +} + +static bool PKTokenizer_setCommentState(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKTokenizer *data = JSObjectGetPrivate(this); + JSObjectRef stateObj = JSValueToObject(ctx, value, ex); + PKCommentState *state = JSObjectGetPrivate(stateObj); + data.commentState = state; + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTokenizer_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTokenizer_finalize(JSObjectRef this) { + PKTokenizer *data = (PKTokenizer *)JSObjectGetPrivate(this); + [data autorelease]; +} + +static JSStaticFunction PKTokenizer_staticFunctions[] = { +{ "toString", PKTokenizer_toString, kJSPropertyAttributeDontDelete }, +{ "setTokenizerState", PKTokenizer_setTokenizerState, kJSPropertyAttributeDontDelete }, +{ "nextToken", PKTokenizer_nextToken, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKTokenizer_staticValues[] = { +{ "string", PKTokenizer_getString, PKTokenizer_setString, kJSPropertyAttributeDontDelete }, // String +{ "numberState", PKTokenizer_getNumberState, PKTokenizer_setNumberState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "quoteState", PKTokenizer_getQuoteState, PKTokenizer_setQuoteState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "commentState", PKTokenizer_getCommentState, PKTokenizer_setCommentState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "symbolState", PKTokenizer_getSymbolState, PKTokenizer_setSymbolState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "whitespaceState", PKTokenizer_getWhitespaceState, PKTokenizer_setWhitespaceState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ "wordState", PKTokenizer_getWordState, PKTokenizer_setWordState, kJSPropertyAttributeDontDelete }, // PKTokenizerState +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKTokenizer_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKTokenizer_staticFunctions; + def.staticValues = PKTokenizer_staticValues; + def.initialize = PKTokenizer_initialize; + def.finalize = PKTokenizer_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTokenizer_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTokenizer_class(ctx), data); +} + +JSObjectRef PKTokenizer_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKTokenizer"); + + JSValueRef s = argv[0]; + NSString *string = PKJSValueGetNSString(ctx, s, ex); + + PKTokenizer *data = [[PKTokenizer alloc] initWithString:string]; + return PKTokenizer_new(ctx, data); +} diff --git a/jssrc/PKJSTokenizerState.h b/jssrc/PKJSTokenizerState.h new file mode 100644 index 0000000..48ab5ca --- /dev/null +++ b/jssrc/PKJSTokenizerState.h @@ -0,0 +1,18 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKTokenizerState_new(JSContextRef ctx, void *data); +JSClassRef PKTokenizerState_class(JSContextRef ctx); diff --git a/jssrc/PKJSTokenizerState.m b/jssrc/PKJSTokenizerState.m new file mode 100644 index 0000000..3083808 --- /dev/null +++ b/jssrc/PKJSTokenizerState.m @@ -0,0 +1,65 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSTokenizerState.h" +#import "PKJSUtils.h" +#import "PKJSToken.h" +#import +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTokenizerState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTokenizerState_finalize(JSObjectRef this) { + PKTokenizerState *data = (PKTokenizerState *)JSObjectGetPrivate(this); + [data autorelease]; +} + +static JSStaticFunction PKTokenizerState_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKTokenizerState_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKTokenizerState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.staticFunctions = PKTokenizerState_staticFunctions; + def.staticValues = PKTokenizerState_staticValues; + def.initialize = PKTokenizerState_initialize; + def.finalize = PKTokenizerState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTokenizerState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTokenizerState_class(ctx), data); +} diff --git a/jssrc/PKJSTrack.h b/jssrc/PKJSTrack.h new file mode 100644 index 0000000..ac92390 --- /dev/null +++ b/jssrc/PKJSTrack.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKTrack_new(JSContextRef ctx, void *data); +JSClassRef PKTrack_class(JSContextRef ctx); +JSObjectRef PKTrack_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSTrack.m b/jssrc/PKJSTrack.m new file mode 100644 index 0000000..6a4e70d --- /dev/null +++ b/jssrc/PKJSTrack.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSTrack.h" +#import "PKJSUtils.h" +#import "PKJSSequence.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKTrack_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKTrack_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKTrack_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKTrack_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKTrack_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKSequence_class(ctx); + def.staticFunctions = PKTrack_staticFunctions; + def.staticValues = PKTrack_staticValues; + def.initialize = PKTrack_initialize; + def.finalize = PKTrack_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKTrack_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKTrack_class(ctx), data); +} + +JSObjectRef PKTrack_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKTrack *data = [[PKTrack alloc] init]; + return PKTrack_new(ctx, data); +} diff --git a/jssrc/PKJSUppercaseWord.h b/jssrc/PKJSUppercaseWord.h new file mode 100644 index 0000000..5763965 --- /dev/null +++ b/jssrc/PKJSUppercaseWord.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKUppercaseWord_new(JSContextRef ctx, void *data); +JSClassRef PKUppercaseWord_class(JSContextRef ctx); +JSObjectRef PKUppercaseWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSUppercaseWord.m b/jssrc/PKJSUppercaseWord.m new file mode 100644 index 0000000..5e2f6f2 --- /dev/null +++ b/jssrc/PKJSUppercaseWord.m @@ -0,0 +1,73 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSUppercaseWord.h" +#import "PKJSUtils.h" +#import "PKJSWord.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKUppercaseWord_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKUppercaseWord_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKUppercaseWord_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKUppercaseWord_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKUppercaseWord_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKWord_class(ctx); + def.staticFunctions = PKUppercaseWord_staticFunctions; + def.staticValues = PKUppercaseWord_staticValues; + def.initialize = PKUppercaseWord_initialize; + def.finalize = PKUppercaseWord_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKUppercaseWord_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKUppercaseWord_class(ctx), data); +} + +JSObjectRef PKUppercaseWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionConstructorArgc(1, "PKUppercaseWord"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKUppercaseWord *data = [[PKUppercaseWord alloc] initWithString:s]; + return PKUppercaseWord_new(ctx, data); +} diff --git a/jssrc/PKJSUtils.h b/jssrc/PKJSUtils.h new file mode 100644 index 0000000..f119d47 --- /dev/null +++ b/jssrc/PKJSUtils.h @@ -0,0 +1,38 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +#define PKPreconditionInstaceOf(cls, meth) +#define PKPreconditionMethodArgc(n, meth) +#define PKPreconditionConstructorArgc(n, meth) + +JSValueRef PKCFTypeToJSValue(JSContextRef ctx, CFTypeRef value, JSValueRef *ex); +JSValueRef PKCFStringToJSValue(JSContextRef ctx, CFStringRef cfStr, JSValueRef *ex); +JSValueRef PKNSStringToJSValue(JSContextRef ctx, NSString *nsStr, JSValueRef *ex); +JSObjectRef PKCFArrayToJSObject(JSContextRef ctx, CFArrayRef cfArray, JSValueRef *ex); +JSObjectRef PKNSArrayToJSObject(JSContextRef ctx, NSArray *nsArray, JSValueRef *ex); +JSObjectRef PKCFDictionaryToJSObject(JSContextRef ctx, CFDictionaryRef cfDict, JSValueRef *ex); +JSObjectRef PKNSDictionaryToJSObject(JSContextRef ctx, NSDictionary *nsDict, JSValueRef *ex); + +CFTypeRef PKJSValueCopyCFType(JSContextRef ctx, JSValueRef value, JSValueRef *ex); +id PKJSValueGetId(JSContextRef ctx, JSValueRef value, JSValueRef *ex); +CFStringRef PKJSValueCopyCFString(JSContextRef ctx, JSValueRef value, JSValueRef *ex); +NSString *PKJSValueGetNSString(JSContextRef ctx, JSValueRef value, JSValueRef *ex); +CFArrayRef PKJSObjectCopyCFArray(JSContextRef ctx, JSObjectRef obj, JSValueRef *ex); +CFDictionaryRef PKJSObjectCopyCFDictionary(JSContextRef ctx, JSObjectRef obj, JSValueRef *ex); + +JSObjectRef PKNSErrorToJSObject(JSContextRef ctx, NSError *nsErr, JSValueRef *ex); +bool PKJSValueIsInstanceOfClass(JSContextRef ctx, JSValueRef value, char *className, JSValueRef* ex); \ No newline at end of file diff --git a/jssrc/PKJSUtils.m b/jssrc/PKJSUtils.m new file mode 100644 index 0000000..c9be532 --- /dev/null +++ b/jssrc/PKJSUtils.m @@ -0,0 +1,242 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSUtils.h" + +JSValueRef PKCFTypeToJSValue(JSContextRef ctx, CFTypeRef value, JSValueRef *ex) { + JSValueRef result = NULL; + CFTypeID typeID = CFGetTypeID(value); + + if (CFNumberGetTypeID() == typeID) { + double d; + CFNumberGetValue(value, kCFNumberDoubleType, &d); + result = JSValueMakeNumber(ctx, d); + } else if (CFBooleanGetTypeID() == typeID) { + Boolean b = CFBooleanGetValue(value); + result = JSValueMakeBoolean(ctx, b); + } else if (CFStringGetTypeID() == typeID) { + result = PKCFStringToJSValue(ctx, value, ex); + } else if (CFArrayGetTypeID() == typeID) { + result = PKCFArrayToJSObject(ctx, value, ex); + } else if (CFDictionaryGetTypeID() == typeID) { + result = PKCFDictionaryToJSObject(ctx, value, ex); + } else { + result = JSValueMakeNull(ctx); + } + + return result; +} + +JSValueRef PKCFStringToJSValue(JSContextRef ctx, CFStringRef cfStr, JSValueRef *ex) { + JSStringRef str = JSStringCreateWithCFString(cfStr); + JSValueRef result = JSValueMakeString(ctx, str); + JSStringRelease(str); + return result; +} + +JSValueRef PKNSStringToJSValue(JSContextRef ctx, NSString *nsStr, JSValueRef *ex) { + return PKCFStringToJSValue(ctx, (CFStringRef)nsStr, ex); +} + +JSObjectRef PKCFArrayToJSObject(JSContextRef ctx, CFArrayRef cfArray, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef className = JSStringCreateWithUTF8CString("Array"); + JSObjectRef arrayConstr = (JSObjectRef)JSObjectGetProperty(ctx, globalObj, className, NULL); + JSStringRelease(className); + + JSObjectRef obj = (JSObjectRef)JSObjectCallAsConstructor(ctx, arrayConstr, 0, NULL, NULL); + + CFIndex len = 0; + if (NULL != cfArray) { + len = CFArrayGetCount(cfArray); + } + + CFIndex i = 0; + for ( ; i < len; i++) { + CFTypeRef value = CFArrayGetValueAtIndex(cfArray, i); + JSValueRef propVal = PKCFTypeToJSValue(ctx, value, ex); + JSObjectSetPropertyAtIndex(ctx, obj, i, propVal, NULL); + } + + return obj; +} + +JSObjectRef PKNSArrayToJSObject(JSContextRef ctx, NSArray *nsArray, JSValueRef *ex) { + return PKCFArrayToJSObject(ctx, (CFArrayRef)nsArray, ex); +} + +JSObjectRef PKCFDictionaryToJSObject(JSContextRef ctx, CFDictionaryRef cfDict, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef className = JSStringCreateWithUTF8CString("Object"); + JSObjectRef objConstr = (JSObjectRef)JSObjectGetProperty(ctx, globalObj, className, NULL); + JSStringRelease(className); + + JSObjectRef obj = (JSObjectRef)JSObjectCallAsConstructor(ctx, objConstr, 0, NULL, NULL); + + if (NULL != cfDict) { + CFIndex len = CFDictionaryGetCount(cfDict); + CFStringRef keys[len]; + CFTypeRef values[len]; + CFDictionaryGetKeysAndValues(cfDict, (const void**)keys, (const void**)values); + + CFIndex i = 0; + for ( ; i < len; i++) { + CFStringRef key = keys[i]; + CFTypeRef value = values[i]; + + JSStringRef propName = JSStringCreateWithCFString(key); + JSValueRef propVal = PKCFTypeToJSValue(ctx, value, ex); + JSObjectSetProperty(ctx, obj, propName, propVal, kJSPropertyAttributeNone, NULL); + JSStringRelease(propName); + } + } + + return obj; +} + +JSObjectRef PKNSDictionaryToJSObject(JSContextRef ctx, NSDictionary *nsDict, JSValueRef *ex) { + return PKCFDictionaryToJSObject(ctx, (CFDictionaryRef)nsDict, ex); +} + +CFTypeRef PKJSValueCopyCFType(JSContextRef ctx, JSValueRef value, JSValueRef *ex) { + CFTypeRef result = NULL; + + if (JSValueIsBoolean(ctx, value)) { + Boolean b = JSValueToBoolean(ctx, value); + result = (b ? kCFBooleanTrue : kCFBooleanFalse); + } else if (JSValueIsNull(ctx, value)) { + result = NULL; + } else if (JSValueIsNumber(ctx, value)) { + CGFloat d = JSValueToNumber(ctx, value, NULL); + result = CFNumberCreate(NULL, kCFNumberCGFloatType, &d); + } else if (JSValueIsString(ctx, value)) { + result = PKJSValueCopyCFString(ctx, value, ex); + } else if (JSValueIsObject(ctx, value)) { + if (PKJSValueIsInstanceOfClass(ctx, value, "Array", NULL)) { + result = PKJSObjectCopyCFArray(ctx, (JSObjectRef)value, ex); + } else { + result = PKJSObjectCopyCFDictionary(ctx, (JSObjectRef)value, ex); + } + } + + return result; +} + +id PKJSValueGetId(JSContextRef ctx, JSValueRef value, JSValueRef *ex) { + return [(id)PKJSValueCopyCFType(ctx, value, ex) autorelease]; +} + +CFStringRef PKJSValueCopyCFString(JSContextRef ctx, JSValueRef value, JSValueRef *ex) { + JSStringRef str = JSValueToStringCopy(ctx, value, ex); + CFStringRef result = JSStringCopyCFString(NULL, str); + JSStringRelease(str); + return result; +} + +NSString *PKJSValueGetNSString(JSContextRef ctx, JSValueRef value, JSValueRef *ex) { + return [(id)PKJSValueCopyCFString(ctx, value, ex) autorelease]; +} + +CFArrayRef PKJSObjectCopyCFArray(JSContextRef ctx, JSObjectRef obj, JSValueRef *ex) { + JSStringRef propName = JSStringCreateWithUTF8CString("length"); + JSValueRef propVal = JSObjectGetProperty(ctx, obj, propName, NULL); + JSStringRelease(propName); + CFIndex len = (CFIndex)JSValueToNumber(ctx, propVal, NULL); + + CFMutableArrayRef cfArray = CFArrayCreateMutable(NULL, len, NULL); + + CFIndex i = 0; + for ( ; i < len; i++) { + JSValueRef val = JSObjectGetPropertyAtIndex(ctx, obj, i, NULL); + CFTypeRef cfType = PKJSValueCopyCFType(ctx, val, ex); + CFArraySetValueAtIndex(cfArray, i, cfType); + + CFRelease(cfType); + } + + CFArrayRef result = CFArrayCreateCopy(NULL, cfArray); + CFRelease(cfArray); + + return result; +} + +CFDictionaryRef PKJSObjectCopyCFDictionary(JSContextRef ctx, JSObjectRef obj, JSValueRef *ex) { + JSPropertyNameArrayRef propNames = JSObjectCopyPropertyNames(ctx, obj); + CFIndex len = JSPropertyNameArrayGetCount(propNames); + + CFMutableDictionaryRef cfDict = CFDictionaryCreateMutable(NULL, len, NULL, NULL); + + CFIndex i = 0; + for ( ; i < len; i++) { + JSStringRef propName = JSPropertyNameArrayGetNameAtIndex(propNames, i); + JSValueRef val = JSObjectGetProperty(ctx, obj, propName, NULL); + CFTypeRef cfType = PKJSValueCopyCFType(ctx, val, ex); + + CFStringRef key = JSStringCopyCFString(NULL, propName); + CFDictionarySetValue(cfDict, (const void *)key, (const void *)cfType); + + CFRelease(key); + CFRelease(cfType); + } + + JSPropertyNameArrayRelease(propNames); + CFDictionaryRef result = CFDictionaryCreateCopy(NULL, cfDict); + CFRelease(cfDict); + + return result; +} + +JSObjectRef PKNSErrorToJSObject(JSContextRef ctx, NSError *nsErr, JSValueRef *ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef className = JSStringCreateWithUTF8CString("Error"); + JSObjectRef errConstr = (JSObjectRef)JSObjectGetProperty(ctx, globalObj, className, ex); + JSStringRelease(className); + + JSObjectRef obj = (JSObjectRef)JSObjectCallAsConstructor(ctx, errConstr, 0, NULL, ex); + + if (nsErr) { + JSStringRef nameStr = JSStringCreateWithUTF8CString("ParseKitError"); + JSValueRef name = JSValueMakeString(ctx, nameStr); + JSStringRelease(nameStr); + + JSStringRef msgStr = JSStringCreateWithCFString((CFStringRef)[nsErr localizedDescription]); + JSValueRef msg = JSValueMakeString(ctx, msgStr); + JSStringRelease(msgStr); + + JSValueRef code = JSValueMakeNumber(ctx, [nsErr code]); + + JSStringRef propName = JSStringCreateWithUTF8CString("name"); + JSObjectSetProperty(ctx, obj, propName, name, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete, ex); + JSStringRelease(propName); + + propName = JSStringCreateWithUTF8CString("message"); + JSObjectSetProperty(ctx, obj, propName, msg, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete, ex); + JSStringRelease(propName); + + propName = JSStringCreateWithUTF8CString("code"); + JSObjectSetProperty(ctx, obj, propName, code, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete, ex); + JSStringRelease(propName); + } + + return obj; +} + +bool PKJSValueIsInstanceOfClass(JSContextRef ctx, JSValueRef value, char *className, JSValueRef* ex) { + JSObjectRef globalObj = JSContextGetGlobalObject(ctx); + JSStringRef classNameStr = JSStringCreateWithUTF8CString(className); + JSObjectRef constr = (JSObjectRef)JSObjectGetProperty(ctx, globalObj, classNameStr, ex); + JSStringRelease(classNameStr); + + return JSValueIsInstanceOfConstructor(ctx, value, constr, NULL); +} diff --git a/jssrc/PKJSUtils_macros.h b/jssrc/PKJSUtils_macros.h new file mode 100644 index 0000000..0be22bd --- /dev/null +++ b/jssrc/PKJSUtils_macros.h @@ -0,0 +1,33 @@ +/* + * PKJSUtils_macros.h + * ParseKit + * + * Created by Todd Ditchendorf on 1/11/09. + * Copyright 2009 Todd Ditchendorf. All rights reserved. + * + */ + +#undef PKPreconditionInstaceOf +#define PKPreconditionInstaceOf(cls, meth) \ + if (!JSValueIsObjectOfClass(ctx, this, (cls)(ctx))) { \ + NSString *s = [NSString stringWithFormat:@"calling method '%s' on an object that is not an instance of '%s'", (meth), #cls]; \ + (*ex) = PKNSStringToJSValue(ctx, s, ex); \ + return JSValueMakeUndefined(ctx); \ + } + +#undef PKPreconditionMethodArgc +#define PKPreconditionMethodArgc(n, meth) \ + if (argc < (n)) { \ + NSString *s = [NSString stringWithFormat:@"%s() requires %d arguments", (meth), (n)]; \ + (*ex) = PKNSStringToJSValue(ctx, s, ex); \ + return JSValueMakeUndefined(ctx); \ + } + +#undef PKPreconditionConstructorArgc +#define PKPreconditionConstructorArgc(n, meth) \ + if (argc < (n)) { \ + NSString *s = [NSString stringWithFormat:@"%s constructor requires %d arguments", (meth), (n)]; \ + (*ex) = PKNSStringToJSValue(ctx, s, ex); \ + return NULL; \ + } + diff --git a/jssrc/PKJSValueHolder.h b/jssrc/PKJSValueHolder.h new file mode 100644 index 0000000..5fe242f --- /dev/null +++ b/jssrc/PKJSValueHolder.h @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface JSValueHolder : NSObject { + JSContextRef context; + JSValueRef heldValue; +} +- (id)initWithContext:(JSContextRef)c heldValue:(JSValueRef)v; + +@property (nonatomic) JSContextRef context; +@property (nonatomic) JSValueRef heldValue; +@end \ No newline at end of file diff --git a/jssrc/PKJSValueHolder.m b/jssrc/PKJSValueHolder.m new file mode 100644 index 0000000..dbad598 --- /dev/null +++ b/jssrc/PKJSValueHolder.m @@ -0,0 +1,35 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSValueHolder.h" + +@implementation JSValueHolder + +- (id)initWithContext:(JSContextRef)c heldValue:(JSValueRef)v { + if (self = [super init]) { + self.context = c; + self.heldValue = v; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +@synthesize context; +@synthesize heldValue; +@end diff --git a/jssrc/PKJSWhitespaceState.h b/jssrc/PKJSWhitespaceState.h new file mode 100644 index 0000000..7c9f0bd --- /dev/null +++ b/jssrc/PKJSWhitespaceState.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKWhitespaceState_new(JSContextRef ctx, void *data); +JSClassRef PKWhitespaceState_class(JSContextRef ctx); +JSObjectRef PKWhitespaceState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSWhitespaceState.m b/jssrc/PKJSWhitespaceState.m new file mode 100644 index 0000000..39702be --- /dev/null +++ b/jssrc/PKJSWhitespaceState.m @@ -0,0 +1,115 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSWhitespaceState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKWhitespaceState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWhitespaceState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKWhitespaceState]", ex); +} + +static JSValueRef PKWhitespaceState_setWhitespaceChars(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWhitespaceState_class, "setWhitespaceChars"); + PKPreconditionMethodArgc(3, "PKWhitespaceState.setWhitespaceChars"); + + BOOL yn = JSValueToBoolean(ctx, argv[0]); + NSString *start = PKJSValueGetNSString(ctx, argv[1], ex); + NSString *end = PKJSValueGetNSString(ctx, argv[2], ex); + + PKWhitespaceState *data = JSObjectGetPrivate(this); + [data setWhitespaceChars:yn from:[start characterAtIndex:0] to:[end characterAtIndex:0]]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKWhitespaceState_isWhitespaceChar(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWhitespaceState_class, "isWhitespaceChar"); + PKPreconditionMethodArgc(1, "PKWhitespaceState.add"); + + NSString *s = PKJSValueGetNSString(ctx, argv[0], ex); + + PKWhitespaceState *data = JSObjectGetPrivate(this); + BOOL yn = [data isWhitespaceChar:[s characterAtIndex:0]]; + + return JSValueMakeBoolean(ctx, yn); +} + +#pragma mark - +#pragma mark Properties + +static JSValueRef PKWhitespaceState_getReportsWhitespaceTokens(JSContextRef ctx, JSObjectRef this, JSStringRef propName, JSValueRef *ex) { + PKWhitespaceState *data = JSObjectGetPrivate(this); + return JSValueMakeBoolean(ctx, data.reportsWhitespaceTokens); +} + +static bool PKWhitespaceState_setReportsWhitespaceTokens(JSContextRef ctx, JSObjectRef this, JSStringRef propertyName, JSValueRef value, JSValueRef *ex) { + PKWhitespaceState *data = JSObjectGetPrivate(this); + data.reportsWhitespaceTokens = JSValueToBoolean(ctx, value); + return true; +} + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKWhitespaceState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKWhitespaceState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKWhitespaceState_staticFunctions[] = { +{ "toString", PKWhitespaceState_toString, kJSPropertyAttributeDontDelete }, +{ "setWhitespaceChars", PKWhitespaceState_setWhitespaceChars, kJSPropertyAttributeDontDelete }, +{ "isWhitespaceChar", PKWhitespaceState_isWhitespaceChar, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKWhitespaceState_staticValues[] = { +{ "reportsWhitespaceTokens", PKWhitespaceState_getReportsWhitespaceTokens, PKWhitespaceState_setReportsWhitespaceTokens, kJSPropertyAttributeDontDelete }, // Boolean +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKWhitespaceState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKWhitespaceState_staticFunctions; + def.staticValues = PKWhitespaceState_staticValues; + def.initialize = PKWhitespaceState_initialize; + def.finalize = PKWhitespaceState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKWhitespaceState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKWhitespaceState_class(ctx), data); +} + +JSObjectRef PKWhitespaceState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKWhitespaceState *data = [[PKWhitespaceState alloc] init]; + return PKWhitespaceState_new(ctx, data); +} diff --git a/jssrc/PKJSWord.h b/jssrc/PKJSWord.h new file mode 100644 index 0000000..bdd5a9c --- /dev/null +++ b/jssrc/PKJSWord.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKWord_new(JSContextRef ctx, void *data); +JSClassRef PKWord_class(JSContextRef ctx); +JSObjectRef PKWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSWord.m b/jssrc/PKJSWord.m new file mode 100644 index 0000000..4e8bc09 --- /dev/null +++ b/jssrc/PKJSWord.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSWord.h" +#import "PKJSUtils.h" +#import "PKJSTerminal.h" +#import + +#pragma mark - +#pragma mark Methods + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKWord_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKWord_finalize(JSObjectRef this) { + // released in PKParser_finalize +} + +static JSStaticFunction PKWord_staticFunctions[] = { +{ 0, 0, 0 } +}; + +static JSStaticValue PKWord_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKWord_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTerminal_class(ctx); + def.staticFunctions = PKWord_staticFunctions; + def.staticValues = PKWord_staticValues; + def.initialize = PKWord_initialize; + def.finalize = PKWord_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKWord_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKWord_class(ctx), data); +} + +JSObjectRef PKWord_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKWord *data = [[PKWord alloc] init]; + return PKWord_new(ctx, data); +} diff --git a/jssrc/PKJSWordState.h b/jssrc/PKJSWordState.h new file mode 100644 index 0000000..aaa91a4 --- /dev/null +++ b/jssrc/PKJSWordState.h @@ -0,0 +1,19 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +JSObjectRef PKWordState_new(JSContextRef ctx, void *data); +JSClassRef PKWordState_class(JSContextRef ctx); +JSObjectRef PKWordState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* ex); diff --git a/jssrc/PKJSWordState.m b/jssrc/PKJSWordState.m new file mode 100644 index 0000000..851ec6d --- /dev/null +++ b/jssrc/PKJSWordState.m @@ -0,0 +1,103 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKJSWordState.h" +#import "PKJSUtils.h" +#import "PKJSTokenizerState.h" +#import + +#pragma mark - +#pragma mark Methods + +static JSValueRef PKWordState_toString(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWordState_class, "toString"); + return PKNSStringToJSValue(ctx, @"[object PKWordState]", ex); +} + +static JSValueRef PKWordState_setWordChars(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWordState_class, "setWordChars"); + PKPreconditionMethodArgc(3, "PKWordState.setWordChars"); + + BOOL yn = JSValueToBoolean(ctx, argv[0]); + NSString *start = PKJSValueGetNSString(ctx, argv[1], ex); + NSString *end = PKJSValueGetNSString(ctx, argv[2], ex); + + PKWordState *data = JSObjectGetPrivate(this); + [data setWordChars:yn from:[start characterAtIndex:0] to:[end characterAtIndex:0]]; + + return JSValueMakeUndefined(ctx); +} + +static JSValueRef PKWordState_isWordChar(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKPreconditionInstaceOf(PKWordState_class, "isWordChar"); + PKPreconditionMethodArgc(1, "PKWordState.isWordChar"); + + NSInteger c = (NSInteger)JSValueToNumber(ctx, argv[0], ex); + + PKWordState *data = JSObjectGetPrivate(this); + BOOL yn = [data isWordChar:c]; + + return JSValueMakeBoolean(ctx, yn); +} + +#pragma mark - +#pragma mark Properties + +#pragma mark - +#pragma mark Initializer/Finalizer + +static void PKWordState_initialize(JSContextRef ctx, JSObjectRef this) { + +} + +static void PKWordState_finalize(JSObjectRef this) { + // released in PKTokenizerState_finalize +} + +static JSStaticFunction PKWordState_staticFunctions[] = { +{ "toString", PKWordState_toString, kJSPropertyAttributeDontDelete }, +{ "setWordChars", PKWordState_setWordChars, kJSPropertyAttributeDontDelete }, +{ "isWordChar", PKWordState_isWordChar, kJSPropertyAttributeDontDelete }, +{ 0, 0, 0 } +}; + +static JSStaticValue PKWordState_staticValues[] = { +{ 0, 0, 0, 0 } +}; + +#pragma mark - +#pragma mark Public + +JSClassRef PKWordState_class(JSContextRef ctx) { + static JSClassRef jsClass = NULL; + if (!jsClass) { + JSClassDefinition def = kJSClassDefinitionEmpty; + def.parentClass = PKTokenizerState_class(ctx); + def.staticFunctions = PKWordState_staticFunctions; + def.staticValues = PKWordState_staticValues; + def.initialize = PKWordState_initialize; + def.finalize = PKWordState_finalize; + jsClass = JSClassCreate(&def); + } + return jsClass; +} + +JSObjectRef PKWordState_new(JSContextRef ctx, void *data) { + return JSObjectMake(ctx, PKWordState_class(ctx), data); +} + +JSObjectRef PKWordState_construct(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef *ex) { + PKWordState *data = [[PKWordState alloc] init]; + return PKWordState_new(ctx, data); +} diff --git a/res/.svn/all-wcprops b/res/.svn/all-wcprops new file mode 100644 index 0000000..5056f2d --- /dev/null +++ b/res/.svn/all-wcprops @@ -0,0 +1,251 @@ +K 25 +svn:wc:ra_dav:version-url +V 28 +/svn/!svn/ver/1399/trunk/res +END +css2_1.grammar +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1177/trunk/res/css2_1.grammar +END +css.css +K 25 +svn:wc:ra_dav:version-url +V 35 +/svn/!svn/ver/552/trunk/res/css.css +END +small-xml-file.xml +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/99/trunk/res/small-xml-file.xml +END +xml.grammar +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1276/trunk/res/xml.grammar +END +proto.grammar +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1177/trunk/res/proto.grammar +END +example1.srgs +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/524/trunk/res/example1.srgs +END +mini_css.grammar +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1275/trunk/res/mini_css.grammar +END +erb.grammar +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1274/trunk/res/erb.grammar +END +example.html +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1263/trunk/res/example.html +END +objc.grammar +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1145/trunk/res/objc.grammar +END +nonascii.html +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/119/trunk/res/nonascii.html +END +xpath_grammar.txt +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/2/trunk/res/xpath_grammar.txt +END +rubyhash.grammar +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1177/trunk/res/rubyhash.grammar +END +apple-boss.json +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/527/trunk/res/apple-boss.json +END +nyt.html +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/1171/trunk/res/nyt.html +END +example.css +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1264/trunk/res/example.css +END +svn-commands.txt +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1392/trunk/res/svn-commands.txt +END +xml_grammar.txt +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/68/trunk/res/xml_grammar.txt +END +nspredicate.grammar +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1275/trunk/res/nspredicate.grammar +END +yahoo.json +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/527/trunk/res/yahoo.json +END +yahoo_with_comments.json +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/543/trunk/res/yahoo_with_comments.json +END +html.grammar +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1264/trunk/res/html.grammar +END +html.css +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/1263/trunk/res/html.css +END +javascript.grammar +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1177/trunk/res/javascript.grammar +END +yahoo-small.json +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/2/trunk/res/yahoo-small.json +END +json.grammar +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1316/trunk/res/json.grammar +END +json_with_comments.grammar +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1276/trunk/res/json_with_comments.grammar +END +json_with_comments.css +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/543/trunk/res/json_with_comments.css +END +json.css +K 25 +svn:wc:ra_dav:version-url +V 36 +/svn/!svn/ver/473/trunk/res/json.css +END +nasty.html +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/198/trunk/res/nasty.html +END +date.grammar +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1107/trunk/res/date.grammar +END +SRGSGrammar.txt +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/24/trunk/res/SRGSGrammar.txt +END +apple-boss.xml +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/527/trunk/res/apple-boss.xml +END +json_with_discards.grammar +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1276/trunk/res/json_with_discards.grammar +END +stuff.txt +K 25 +svn:wc:ra_dav:version-url +V 36 +/svn/!svn/ver/38/trunk/res/stuff.txt +END +c.grammar +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/986/trunk/res/c.grammar +END +xpath1_0.grammar +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1224/trunk/res/xpath1_0.grammar +END +json-old.grammar +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/363/trunk/res/json-old.grammar +END +javascript_ll.txt +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/893/trunk/res/javascript_ll.txt +END +css.grammar +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1177/trunk/res/css.grammar +END +arithmetic.grammar +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1399/trunk/res/arithmetic.grammar +END diff --git a/res/.svn/entries b/res/.svn/entries new file mode 100644 index 0000000..8e056e5 --- /dev/null +++ b/res/.svn/entries @@ -0,0 +1,1429 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/res +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-09-25T23:53:58.853281Z +1399 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + + + + + + +0 + +css.css +file + + + + +2009-01-04T21:18:31.000000Z +78c18946f6ffaeeadfd3225a10c13aa9 +2009-01-02T21:43:54.047733Z +552 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1214 + +css2_1.grammar +file + + + + +2009-07-03T22:20:03.000000Z +7f4b8609cb7a9e7de4784d2027854e0e +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +4703 + +small-xml-file.xml +file + + + + +2008-09-09T00:54:01.000000Z +635b643c51c10c25d74855a7dcd65ad7 +2008-09-08T23:19:29.702882Z +99 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +166 + +xml.grammar +file + + + + +2009-08-06T04:02:07.000000Z +94d761cc17bb711ba4009cbdc0455cb4 +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +11924 + +proto.grammar +file + + + + +2009-07-03T22:20:03.000000Z +71ffa9a03c1e9ff3f87e462e3e6f167a +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3405 + +example1.srgs +file + + + + +2008-12-29T06:08:01.000000Z +ac4d9edd3f3a8d0885cd1574fbfee228 +2008-12-29T03:54:03.697310Z +524 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +711 + +mini_css.grammar +file + + + + +2009-08-06T04:02:07.000000Z +68d7c36dd4772abaf6e52f5e4b9ab7d0 +2009-08-02T22:59:20.682429Z +1275 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +813 + +erb.grammar +file + + + + +2009-08-06T04:02:07.000000Z +025b7af4a42f649ca18f18967d98d7a5 +2009-08-02T22:44:31.009697Z +1274 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +325 + +example.html +file + + + + +2009-07-27T05:59:17.000000Z +8acc3431d1ef730e3a44e514510f9574 +2009-07-27T06:00:08.623243Z +1263 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +783 + +objc.grammar +file + + + + +2009-07-02T08:13:09.000000Z +1ef69df65f7382e86f87d489a71ba253 +2009-07-02T08:13:30.903884Z +1145 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +4399 + +nonascii.html +file + + + + +2008-09-18T01:15:25.000000Z +0918e25c989141d4da9df817d8f673cb +2008-09-16T19:18:13.595792Z +119 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +6 + +xpath_grammar.txt +file + + + + +2008-08-16T23:18:00.000000Z +32115e5c48f844d6bd2e83af42fe8446 +2008-08-18T01:13:08.367577Z +2 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3950 + +rubyhash.grammar +file + + + + +2009-07-03T22:20:03.000000Z +61fb027ff53c0b8e5df4ca5887596acf +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1038 + +nyt.html +file + + + + +2009-07-03T19:31:31.000000Z +5abad5697c979748ef9bda66990736df +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +113050 + +apple-boss.json +file + + + + +2008-12-29T06:08:02.000000Z +7e719d89f39e583f06642d862ed813ef +2008-12-29T04:00:43.071407Z +527 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +8216 + +example.css +file + + + + +2009-07-28T03:33:06.000000Z +875b6fe0d66f849e7419cb66227cdd84 +2009-07-28T06:26:12.609772Z +1264 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +840 + +svn-commands.txt +file + + + + +2009-09-18T00:49:42.000000Z +d5e47b33bce5963b78b2bc22de7669c6 +2009-09-18T00:49:49.588045Z +1392 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +854 + +xml_grammar.txt +file + + + + +2008-08-26T03:36:19.000000Z +31ab6ac70b8792fbcb63cd2e36f7dd74 +2008-08-26T05:15:19.863356Z +68 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +5496 + +nspredicate.grammar +file + + + + +2009-08-06T04:02:07.000000Z +d4cf34d579213216979219c558582098 +2009-08-02T22:59:20.682429Z +1275 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3462 + +yahoo.json +file + + + + +2008-12-29T06:08:01.000000Z +10f19042248cc1480cceafe7175eb45c +2008-12-29T04:00:43.071407Z +527 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +11443 + +yahoo_with_comments.json +file + + + + +2008-12-31T23:28:36.000000Z +2617530644acc7917735d879d502b1d6 +2008-12-31T21:33:31.036262Z +543 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +11458 + +html.grammar +file + + + + +2009-07-27T06:05:06.000000Z +42ff37705f7dc757bbb05eed90db135c +2009-07-28T06:26:12.609772Z +1264 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1095 + +javascript.grammar +file + + + + +2009-07-03T22:20:03.000000Z +429f32f5c4ec3a566d867094eee35365 +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +11065 + +html.css +file + + + + +2009-07-27T05:59:49.000000Z +1857dbf2d1fe28ae47ca777a1316e622 +2009-07-27T06:00:08.623243Z +1263 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1243 + +yahoo-small.json +file + + + + +2008-08-08T08:34:59.000000Z +23e4438ccaa83a0346f3ab81436a61a2 +2008-08-18T01:13:08.367577Z +2 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +504 + +json.grammar +file + + + + +2009-08-06T04:02:07.000000Z +52a4cde3481a720099df8bed8918b91f +2009-08-09T07:55:34.749013Z +1316 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2046 + +json_with_comments.grammar +file + + + + +2009-08-06T04:02:07.000000Z +2df8fb3e2f25a33674065bd6ea33ef73 +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2322 + +json_with_comments.css +file + + + + +2008-12-31T23:28:36.000000Z +0574c6077487daae145207849c703125 +2008-12-31T21:33:31.036262Z +543 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1099 + +json.css +file + + + + +2008-12-29T06:08:01.000000Z +b2276bc75b093411857889aeeb276c39 +2008-12-26T09:14:14.897421Z +473 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +969 + +nasty.html +file + + + + +2008-11-27T01:12:57.000000Z +4cd07edd01f6efb55ad479b50f096e32 +2008-11-22T03:34:58.359586Z +198 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +735 + +date.grammar +file + + + + +2009-06-30T04:19:25.000000Z +f9244b34537528d24141a96a3f72bc9d +2009-06-30T04:22:36.109998Z +1107 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1310 + +SRGSGrammar.txt +file + + + + +2008-08-20T02:41:16.000000Z +bfbf550b59adb8b21f035e76baec3708 +2008-08-20T06:37:48.564650Z +24 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +5060 + +apple-boss.xml +file + + + + +2008-12-29T06:08:02.000000Z +db9d148b40fa176c258a35a0c988e880 +2008-12-29T04:00:43.071407Z +527 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +9613 + +json_with_discards.grammar +file + + + + +2009-08-06T04:02:07.000000Z +18a78c158a62ccb02ee08df390048281 +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1463 + +stuff.txt +file + + + + +2008-08-24T02:17:00.000000Z +481f79553a2649211a1c487bd57ac5dc +2008-08-24T02:19:05.295252Z +38 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +174 + +c.grammar +file + + + + +2009-06-19T01:49:29.000000Z +1ea0553001b76ace1feb861a7621228b +2009-06-18T19:17:13.046641Z +986 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +7964 + +xpath1_0.grammar +file + + + + +2009-07-13T06:15:35.000000Z +b7e468adee1046af806193595765d28a +2009-07-13T06:15:46.893213Z +1224 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3566 + +json-old.grammar +file + + + + +2008-12-15T21:27:05.000000Z +ad5d870f4668e457c6d2daf5d08060a0 +2008-12-15T09:09:56.347605Z +363 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +958 + +javascript_ll.txt +file + + + + +2009-06-04T04:25:06.000000Z +f683396eb9bb1c5937e80196d162f141 +2009-06-04T04:57:04.693087Z +893 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3930 + +css.grammar +file + + + + +2009-07-03T22:20:03.000000Z +164208ebbcbf2b14b4476ff61d4ab437 +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1342 + +arithmetic.grammar +file + + + + +2009-09-26T03:08:41.000000Z +64cceacdfc3c183d3908227b31550ba8 +2009-09-25T23:53:58.853281Z +1399 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +352 + diff --git a/res/.svn/prop-base/example1.srgs.svn-base b/res/.svn/prop-base/example1.srgs.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/res/.svn/prop-base/example1.srgs.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/res/.svn/prop-base/mini_css.grammar.svn-base b/res/.svn/prop-base/mini_css.grammar.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/res/.svn/prop-base/mini_css.grammar.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/res/.svn/prop-base/nyt.html.svn-base b/res/.svn/prop-base/nyt.html.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/res/.svn/prop-base/nyt.html.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/res/.svn/prop-base/yahoo-small.json.svn-base b/res/.svn/prop-base/yahoo-small.json.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/res/.svn/prop-base/yahoo-small.json.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/res/.svn/text-base/SRGSGrammar.txt.svn-base b/res/.svn/text-base/SRGSGrammar.txt.svn-base new file mode 100644 index 0000000..d894c82 --- /dev/null +++ b/res/.svn/text-base/SRGSGrammar.txt.svn-base @@ -0,0 +1,218 @@ +selfIdentHeader ::= + '#ABNF' #x20 VersionNumber (#x20 CharEncoding)? ';' + [Additional constraints: + - The semicolon (';') must immediately be followed + by an end-of-line. + ] + +VersionNumber ::= + '1.0' + +CharEncoding ::= + Nmtoken + +BaseURI ::= + ABNF_URI + +LanguageCode ::= + Nmtoken + [Additional constraints: + - The language code must be a valid language identifier. + ] + +RuleName ::= + '$' ConstrainedName + +ConstrainedName ::= + Name - (Char* ('.' | ':' | '-') Char*) + +TagFormat ::= + ABNF_URI + +LexiconURI ::= + ABNF_URI | ABNF_URI_with_Media_Type + +SingleQuotedCharacters ::= + ''' [^']* ''' + +DoubleQuotedCharacters ::= + '"' [^"]* '"' + +QuotedCharacters ::= + SingleQuotedCharacters | DoubleQuotedCharacters + +Weight ::= + '/' Number '/' + + +Repeat ::= + [0-9]+ ('-' [0-9]*)? + [Additional constraints: + - A number to the right of the hyphen must not be + greater than the number to the left of the hyphen. + ] + + +Probability ::= + '/' Number '/' + [Additional constraints: + - The float value must be in the range of "0.0" + to "1.0" (inclusive). + ] + +Number ::= + [0-9]+ | [0-9]+ '.' [0-9]* | [0-9]* '.' [0-9]+ + +ExternalRuleRef ::= + '$' ABNF_URI | '$' ABNF_URI_with_Media_Type + [Additional constraints: + - The referenced grammar must have the same mode + ("voice" or "dtmf") as the referencing grammar. + - If the URI reference contains a fragment + identifier, the referenced rule must be a + public rule of another grammar. + - If the URI reference does not contain a fragment + identifier, i.e. if it is an implicit root rule reference, + then the referenced grammar must declare a root + rule. + ] + +Token ::= + Nmtoken | DoubleQuotedCharacters + +LanguageAttachment ::= + '!' LanguageCode + +Tag ::= + '{' [^}]* '}' + | '{!{' (Char* - (Char* '}!}' Char*)) '}!}' + +------------------------------------------------------------ + +ABNF_URI + and ABNF_URI_with_Media_Type + are defined +in Section 1.6 Terminology. + +Name is defined by the XML Name production [XML §2.3]. + +Nmtoken is defined by the XML Nmtoken production [XML §2.3]. + +NameChar is defined by the XML NameChar production [XML §2.3]. + +Char is defined by the XML Char production [XML §2.2]. + + + + + + + + + + + + + +grammar ::= + selfIdentHeader declaration* ruleDefinition* + +declaration ::= + baseDecl | languageDecl | modeDecl | rootRuleDecl + | tagFormatDecl | lexiconDecl | metaDecl | tagDecl + +baseDecl ::= + 'base' BaseURI ';' + [Additional constraints: + - A base declaration must not appear more than + once in grammar. + ] + +languageDecl ::= + 'language' LanguageCode ';' + [Additional constraints: + - A language declaration must not appear more than + once in grammar. + - A language declaration is required if the + grammar mode is "voice". + ] + +modeDecl ::= + 'mode' 'voice' ';' | 'mode' 'dtmf' ';' + [Additional constraints: + - A mode declaration must not appear more than + once in grammar. + ] + +rootRuleDecl ::= + 'root' RuleName ';' + [Additional constraints: + - A root rule declaration must not appear more + than once in grammar. + - The root rule must be a rule that is defined + within the grammar. + ] + +tagFormatDecl ::= + 'tag-format' TagFormat ';' + [Additional constraints: + - A tag-format declaration must not appear more + than once in grammar. + ] + +lexiconDecl ::= + 'lexicon' LexiconURI ';' + +metaDecl ::= + 'http-equiv' QuotedCharacters 'is' QuotedCharacters ';' + | 'meta' QuotedCharacters 'is' QuotedCharacters ';' + + +tagDecl ::= + Tag ';' + + +ruleDefinition ::= + scope? RuleName '=' ruleExpansion ';' + [Additional constraints: + - The rule name must be unique within a grammar, + i.e. no rule must be defined more than once + within a grammar. + ] + +scope ::= + 'private' | 'public' + +ruleExpansion ::= + ruleAlternative ( '|' ruleAlternative )* + +ruleAlternative ::= + Weight? sequenceElement+ + +sequenceElement ::= + subexpansion | subexpansion repeatOperator + +subexpansion ::= + Token LanguageAttachment? + | ruleRef + | Tag + | '(' ')' + | '(' ruleExpansion ')' LanguageAttachment? + | '[' ruleExpansion ']' LanguageAttachment? + +ruleRef ::= + localRuleRef | ExternalRuleRef | specialRuleRef + +localRuleRef ::= + RuleName + [Additional constraints: + - The referenced rule must be defined within the + same grammar. + ] + +specialRuleRef ::= + '$NULL' | '$VOID' | '$GARBAGE' + + +repeatOperator ::= + '<' Repeat Probability? '>' \ No newline at end of file diff --git a/res/.svn/text-base/apple-boss.json.svn-base b/res/.svn/text-base/apple-boss.json.svn-base new file mode 100644 index 0000000..a082201 --- /dev/null +++ b/res/.svn/text-base/apple-boss.json.svn-base @@ -0,0 +1,80 @@ +{"ysearchresponse": + {"responsecode":"200", + "nextpage":"\/ysearch\/web\/v1\/apple?appid=LcU4qWbV34HAOHTXXZbYfB1_AgYH5_AhlzYZ6Qvm4hdEDw6B1MicVEIYPtQLOTnb&format=json&start=10", + "totalhits":"50793319", + "deephits":"1510000000", + "count":"10", + "start":"0", + "resultset_web": + [{"abstract":"Macintosh hardware, software, and Internet tools. Offering Quicktime info, developer resources, and other items related to Apple<\/b> computers.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnNTdsamw3BGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzAEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=10qut2vvd\/**http%3A\/\/www.apple.com\/","date":"2008\/08\/12", + "dispurl":"www.apple.com<\/b>", + "size":"10765", + "title":"Apple<\/b>, Inc.", + "url":"http:\/\/www.apple.com\/"}, + {"abstract":"The official online store for iPods, Mac laptops and Macintosh computers, with free shipping over $50. Also featuring software such as Final Cut and Office 2008 for Mac.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnaTZsYjRpBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzEEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=1fufchaio\/**http%3A\/\/rdrw1.yahoo.com\/click%3Fu=http%3A\/\/feedpoint.net\/r\/redir.jsp%253Fengine%253DINK%2526pcid%253D597997%2526fid%253D-2%2526url%253Dhttp%3A\/\/store.apple.com\/1-800-MY-APPLE\/WebObjects\/AppleStore%253Faosid%253Dp210%2526cid%253DOAS-US-YPI%2526src%253Dyssp%26y=04C664CB0EAC6A0CE6%26i=1473%26c=59131%26q=02%255ESSHPM%255BL7~oosz6%26e=utf-8%26r=1%26d=wow~LcU4qWbV34HAOHTXXZbYfB1_AgYH5_AhlzYZ6Qvm4hdEDw6B1MicVEIYPtQLOTnb-en-us%26n=LN94K1HIB6HKGRUL%26s=1%26t=%26m=48A3A234%26x=051726E3806650ACD5A44E8C8BD13ADACC", + "date":"2008\/08\/13", + "dispurl":"store.apple.com<\/b>", + "size":"49418", + "title":"Mac Laptops, iPods and Macintosh Computers | Apple<\/b> Online Store", + "url":"http:\/\/store.apple.com\/"}, + {"abstract":"Encyclopedia article about the computer company, including history, product lines, and corporate affairs. ...<\/b> Apple's<\/b> software products include the Mac OS X ...<\/b>", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnNHB0OGduBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzIEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=11c328ll9\/**http%3A\/\/en.wikipedia.org\/wiki\/Apple_Inc.", + "date":"2008\/08\/10", + "dispurl":"en.wikipedia.org<\/b>\/wiki\/Apple<\/b>_Inc.", + "size":"285957", + "title":"Apple<\/b> Inc. - Wikipedia, the free encyclopedia", + "url":"http:\/\/en.wikipedia.org\/wiki\/Apple_Inc."}, + {"abstract":"Detailed overview of the apple's<\/b> origins, flavors, and health benefits.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnMmh1a3BkBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzMEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=117d3a7f6\/**http%3A\/\/en.wikipedia.org\/wiki\/Apple", + "date":"2008\/08\/11", + "dispurl":"en.wikipedia.org<\/b>\/wiki\/Apple<\/b>", + "size":"128319", + "title":"Apple<\/b> - Wikipedia", + "url":"http:\/\/en.wikipedia.org\/wiki\/Apple"}, + {"abstract":"Your complete guide to all things Macintosh. Get the latest reviews, news, videos, downloads, tips, and more for Mac laptops, desktops, and OS X 10.5 (Leopard)", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnNWR1czdzBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzQEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=117n1p7jv\/**http%3A\/\/www.cnet.com\/apple-mac.html", + "date":"2008\/08\/09", + "dispurl":"www.cnet.com<\/b>\/apple<\/b>-mac.html", + "size":"102719", + "title":"Apple<\/b> Mac: Mac OS, Mac laptop, Mac desktop - CNET.com", + "url":"http:\/\/www.cnet.com\/apple-mac.html"}, + {"abstract":"Watch Apple<\/b> CEO Steve Jobs unveil iPhone 3G, the App Store, MobileMe, and more ...<\/b> Copyright \u00a9 2008 Apple<\/b> Inc. All rights reserved. Terms of Use | Privacy Policy ...<\/b>", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnbjkwdjF0BGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzUEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=1272or2mo\/**http%3A\/\/events.apple.com.edgesuite.net\/0806wdt546x\/event\/index.html", + "date":"2008\/07\/16", + "dispurl":"events.apple.com.edgesuite.net<\/b>\/0806wdt546x\/event\/index.html", + "size":"17259", + "title":"Apple<\/b> - QuickTime - WWDC 2008 Keynote", + "url":"http:\/\/events.apple.com.edgesuite.net\/0806wdt546x\/event\/index.html"}, + {"abstract":"Apple's<\/b> GrayShare technology gives you the ability to print over 130 shades of ...<\/b> are part of the CSW 4000 Series Update 1.0 posted on Apple<\/b> Software Updates. ...<\/b>", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRndXBuYjJ1BGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzYEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=11r2bnul4\/**http%3A\/\/docs.info.apple.com\/article.html%3Fartnum=30153", + "date":"2004\/09\/20", + "dispurl":"docs.info.apple.com<\/b>\/article.html?artnum=30153", + "size":"37078", + "title":"StyleWriter Printers: Print Drivers and Cable Matrix", + "url":"http:\/\/docs.info.apple.com\/article.html?artnum=30153"}, + {"abstract":"8 Jumps Apple<\/b> releases firmware 2.0 for iPhone, iPod Touch ...<\/b> Apple<\/b> underestimated the load on their servers, which left many users stuck on ...<\/b>", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnY3I0MWFoBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzcEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=10pb88a2t\/**http%3A\/\/apple.qj.net\/", + "date":"2008\/07\/14", + "dispurl":"apple.qj.net<\/b>", + "size":"82416", + "title":"QJ.NET - QuickJump Home - Apple<\/b> News - QJ.NET", + "url":"http:\/\/apple.qj.net\/"}, + {"abstract":"Daily Apple<\/b> news updates, forums, reviews, and features.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnN2tqM2ZpBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzgEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=111js1asj\/**http%3A\/\/www.appleinsider.com\/", + "date":"2008\/08\/12", + "dispurl":"www.appleinsider.com<\/b>", + "size":"82410", + "title":"AppleInsider", + "url":"http:\/\/www.appleinsider.com\/"}, + {"abstract":"Offers threaded discussions related to news for Apple<\/b> users.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnaTlmZm5iBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzkEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=10vvqn6ao\/**http%3A\/\/apple.slashdot.org\/", + "date":"2008\/08\/13", + "dispurl":"apple.slashdot.org<\/b>", + "size":"43683", + "title":"apple<\/b>.slashdot.org", + "url":"http:\/\/apple.slashdot.org\/"} + ] + } +} \ No newline at end of file diff --git a/res/.svn/text-base/apple-boss.xml.svn-base b/res/.svn/text-base/apple-boss.xml.svn-base new file mode 100644 index 0000000..14a3187 --- /dev/null +++ b/res/.svn/text-base/apple-boss.xml.svn-base @@ -0,0 +1,96 @@ + + + + + + Apple computers.]]> + + 2008/08/17 + apple.com]]> + 10765 + <![CDATA[<b>Apple</b>, Inc.]]> + http://www.apple.com/ + + + The official online store for iPods, Mac laptops and Macintosh computers, with free shipping over $50. Also featuring software such as Final Cut and Office 2008 for Mac. + + 2008/08/18 + store.apple.com]]> + 101744 + <![CDATA[Mac Laptops, iPods and Macintosh Computers | <b>Apple</b> Online Store]]> + http://store.apple.com/ + + + ... Apple's software products include the Mac OS X ...]]> + + 2008/08/10 + en.wikipedia.org/wiki/Apple_Inc.]]> + 285957 + <![CDATA[<b>Apple</b> Inc. - Wikipedia, the free encyclopedia]]> + http://en.wikipedia.org/wiki/Apple_Inc. + + + Apple's software products include the Mac OS X operating system, iTunes media ... Apple was established on April 1, 1976 by Steve Jobs, Steve Wozniak, and Ronald ...]]> + + 2008/08/18 + en.wikipedia.org/wiki/Apple_Computer]]> + 249715 + <![CDATA[<b>Apple</b> Inc. - Wikipedia, the free encyclopedia]]> + http://en.wikipedia.org/wiki/Apple_Computer + + + Your complete guide to all things Macintosh. Get the latest reviews, news, videos, downloads, tips, and more for Mac laptops, desktops, and OS X 10.5 (Leopard) + + 2008/08/18 + cnet.com/apple-mac.html]]> + 100558 + <![CDATA[<b>Apple</b> Mac: Mac OS, Mac laptop, Mac desktop - CNET.com]]> + http://www.cnet.com/apple-mac.html + + + Apple CEO Steve Jobs unveil iPhone 3G, the App Store, MobileMe, and more ... Copyright © 2008 Apple Inc. All rights reserved. Terms of Use | Privacy Policy ...]]> + + 2008/07/16 + events.apple.com.edgesuite.net/0806wdt546x/event/index.html]]> + 17259 + <![CDATA[<b>Apple</b> - QuickTime - WWDC 2008 Keynote]]> + http://events.apple.com.edgesuite.net/0806wdt546x/event/index.html + + + Apple's GrayShare technology gives you the ability to print over 130 shades of ... are part of the CSW 4000 Series Update 1.0 posted on Apple Software Updates. ...]]> + + 2004/09/20 + docs.info.apple.com/article.html?artnum=30153]]> + 37078 + StyleWriter Printers: Print Drivers and Cable Matrix + http://docs.info.apple.com/article.html?artnum=30153 + + + Apple releases firmware 2.0 for iPhone, iPod Touch ... Apple underestimated the load on their servers, which left many users stuck on ...]]> + + 2008/07/14 + apple.qj.net]]> + 82416 + <![CDATA[QJ.NET - QuickJump Home - <b>Apple</b> News - QJ.NET]]> + http://apple.qj.net/ + + + Apple users.]]> + + 2008/08/18 + apple.slashdot.org]]> + 44408 + <![CDATA[<b>apple</b>.slashdot.org]]> + http://apple.slashdot.org/ + + + Apple Authorized Training Centers offer Mac OS X and Pro Apps exams ... Publicize your certifications on Apple's website, and connect with clients and employers ...]]> + + 2008/07/25 + prometric.com/apple/default.htm]]> + 13318 + <![CDATA[Prometric: <b>Apple</b> Certification]]> + http://www.prometric.com/apple/default.htm + + + diff --git a/res/.svn/text-base/arithmetic.grammar.svn-base b/res/.svn/text-base/arithmetic.grammar.svn-base new file mode 100644 index 0000000..9b2e038 --- /dev/null +++ b/res/.svn/text-base/arithmetic.grammar.svn-base @@ -0,0 +1,10 @@ +@start = expr; +expr = term (plusTerm | minusTerm)*; +term = factor (timesFactor | divFactor)*; +plusTerm = '+' term; +minusTerm = '-' term; +factor = phrase exponentFactor | phrase; +timesFactor = '*' factor; +divFactor = '/' factor; +exponentFactor = '^' factor; +phrase = '(' expr ')' | Number; diff --git a/res/.svn/text-base/c.grammar.svn-base b/res/.svn/text-base/c.grammar.svn-base new file mode 100644 index 0000000..03fa75f --- /dev/null +++ b/res/.svn/text-base/c.grammar.svn-base @@ -0,0 +1,314 @@ + translation-unit: + external-declaration + translation-unit external-declaration + + external-declaration: + function-definition + declaration + + function-definition: + declaration-specifiersopt declarator declaration-listopt compound-statement + + declaration: + declaration-specifiers init-declarator-listopt; + + declaration-list: + declaration + declaration-list declaration + + declaration-specifiers: + storage-class-specifier declaration-specifiersopt + type-specifier declaration-specifiersopt + type-qualifier declaration-specifiersopt + + storage-class specifier: one of + auto register static extern typedef + + type specifier: one of + void char short int long float double signed + unsigned struct-or-union-specifier enum-specifier typedef-name + + type-qualifier: one of + const volatile + + struct-or-union-specifier: + struct-or-union identifieropt { struct-declaration-list } + struct-or-union identifier + + struct-or-union: one of + struct union + + struct-declaration-list: + struct declaration + struct-declaration-list struct declaration + + init-declarator-list: + init-declarator + init-declarator-list, init-declarator + + init-declarator: + declarator + declarator = initializer + + struct-declaration: + specifier-qualifier-list struct-declarator-list; + + specifier-qualifier-list: + type-specifier specifier-qualifier-listopt + type-qualifier specifier-qualifier-listopt + + struct-declarator-list: + struct-declarator + struct-declarator-list , struct-declarator + + struct-declarator: + declarator + declaratoropt : constant-expression + + enum-specifier: + enum identifieropt { enumerator-list } + enum identifier + + enumerator-list: + enumerator + enumerator-list , enumerator + + enumerator: + identifier + identifier = constant-expression + + declarator: + pointeropt direct-declarator + + direct-declarator: + identifier + (declarator) + direct-declarator [ constant-expressionopt ] + direct-declarator ( parameter-type-list ) + direct-declarator ( identifier-listopt ) + + pointer: + * type-qualifier-listopt + * type-qualifier-listopt pointer + + type-qualifier-list: + type-qualifier + type-qualifier-list type-qualifier + + parameter-type-list: + parameter-list + parameter-list , ... + + parameter-list: + parameter-declaration + parameter-list , parameter-declaration + + parameter-declaration: + declaration-specifiers declarator + declaration-specifiers abstract-declaratoropt + + identifier-list: + identifier + identifier-list , identifier + + initializer: + assignment-expression + { initializer-list } + { initializer-list , } + + initializer-list: + initializer + initializer-list , initializer + + type-name: + specifier-qualifier-list abstract-declaratoropt + + abstract-declarator: + pointer + pointeropt direct-abstract-declarator + + direct-abstract-declarator: + ( abstract-declarator ) + direct-abstract-declaratoropt [constant-expressionopt] + direct-abstract-declaratoropt (parameter-type-listopt) + + typedef-name: + identifier + + statement: + labeled-statement + expression-statement + compound-statement + selection-statement + iteration-statement + jump-statement + + labeled-statement: + identifier : statement + case constant-expression : statement + default : statement + + expression-statement: + expressionopt; + + compound-statement: + { declaration-listopt statement-listopt } + + statement-list: + statement + statement-list statement + + selection-statement: + if (expression) statement + if (expression) statement else statement + switch (expression) statement + + iteration-statement: + while (expression) statement + do statement while (expression); + for (expressionopt; expressionopt; expressionopt) statement + + jump-statement: + goto identifier; + continue; + break; + return expressionopt; + + expression: + assignment-expression + expression , assignment-expression + + assignment-expression: + conditional-expression + unary-expression assignment-operator assignment-expression + + assignment-operator: one of + = *= /= %= += -= <<= >>= &= ^= |= + + conditional-expression: + logical-OR-expression + logical-OR-expression ? expression : conditional-expression + + constant-expression: + conditional-expression + + logical-OR-expression: + logical-AND-expression + logical-OR-expression || logical-AND-expression + + logical-AND-expression: + inclusive-OR-expression + logical-AND-expression && inclusive-OR-expression + + inclusive-OR-expression: + exclusive-OR-expression + inclusive-OR-expression | exclusive-OR-expression + + exclusive-OR-expression: + AND-expression + exclusive-OR-expression ^ AND-expression + + AND-expression: + equality-expression + AND-expression & equality-expression + + equality-expression: + relational-expression + equality-expression == relational-expression + equality-expression != relational-expression + + relational-expression: + shift-expression + relational-expression < shift-expression + relational-expression > shift-expression + relational-expression <= shift-expression + relational-expression >= shift-expression + + shift-expression: + additive-expression + shift-expression << additive-expression + shift-expression >> additive-expression + + additive-expression: + multiplicative-expression + additive-expression + multiplicative-expression + additive-expression - multiplicative-expression + + multiplicative-expression: + multiplicative-expression * cast-expression + multiplicative-expression / cast-expression + multiplicative-expression % cast-expression + + cast-expression: + unary expression + (type-name) cast-expression + + unary-expression: + postfix expression + ++unary expression + --unary expression + unary-operator cast-expression + sizeof unary-expression + sizeof (type-name) + + unary operator: one of + & * + - ~ ! + + postfix-expression: + primary-expression + postfix-expression[expression] + postfix-expression(argument-expression-listopt) + postfix-expression.identifier + postfix-expression->+identifier + postfix-expression++ + postfix-expression-- + primary-expression: + identifier + constant + string + (expression) + + argument-expression-list: + assignment-expression + assignment-expression-list , assignment-expression + + constant: + integer-constant + character-constant + floating-constant + enumeration-constant + +# The following grammar for the preprocessor summarizes the structure of control lines, but is not suitable for mechanized parsing. It includes the symbol text, which means ordinary program text, non-conditional preprocessor control lines, or complete preprocessor conditional instructions. + + control-line: + # define identifier token-sequence + # define identifier(identifier, ... , identifier) token-sequence + # undef identifier + # include + # include "filename" + # line constant "filename" + # line constant + # error token-sequenceopt + # pragma token-sequenceopt + # + preprocessor-conditional + + preprocessor-conditional: + if-line text elif-parts else-partopt #endif + + if-line: + # if constant-expression + # ifdef identifier + # ifndef identifier + + elif-parts: + elif-line text + elif-partsopt + + elif-line: + # elif constant-expression + + else-part: + else-line text + else-line: + #else \ No newline at end of file diff --git a/res/.svn/text-base/css.css.svn-base b/res/.svn/text-base/css.css.svn-base new file mode 100644 index 0000000..0c139b9 --- /dev/null +++ b/res/.svn/text-base/css.css.svn-base @@ -0,0 +1,71 @@ +openCurly, +closeCurly, +openBracket, +closeBracket, +eq, +comma, +colon, +semi, +openParen, +closeParen, +gt, +tilde, +pipe, +fwdSlash, +hash, +dot { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +selectorWord { + color:rgb(255, 255, 255); + background-color:rgb(20, 20, 26); + font-family:'Georgia'; + font-size:15px; +} + +selectorQuotedString { + color:rgb(196.35, 45.9, 51.0); + background-color:rgb(20, 20, 26); + font-family:'Georgia'; + font-size:15px; +} + +constant, string, semi { + color:rgb(196.35, 45.9, 51.0); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +property { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +num { + color:rgb(22.95, 158.1, 188.7); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +//text { +// color:rgb(61.2, 178.5, 68.85); +// background-color:rgb(30, 30, 36); +// font-family:'Monaco'; +// font-size:11px; +//} + +word { + color:rgb(255, 255, 255); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + diff --git a/res/.svn/text-base/css.grammar.svn-base b/res/.svn/text-base/css.grammar.svn-base new file mode 100644 index 0000000..e414a53 --- /dev/null +++ b/res/.svn/text-base/css.grammar.svn-base @@ -0,0 +1,44 @@ +/** + A Grammar for CSS + + This grammar is intentionally lenient/forgiving. + The purpose is to highlight, not validate (possibly invalid) CSS. + +*/ + +@multiLineComments = '/*' '*/'; +@wordState = '-'; + +@start = ruleset*; +ruleset = selectors openCurly decls closeCurly; +selectors = selector commaSelector*; +selector = (selectorWord | hash | dot |colon | gt | openBracket | closeBracket | eq | selectorQuotedString | tilde | pipe)+; +selectorWord = Word; +selectorQuotedString = QuotedString; +commaSelector = comma selector; +decls = Empty | actualDecls; +actualDecls = decl decl*; +decl = property colon expr semi; +property = Word; +expr = (string | constant | num | openParen | closeParen | comma | fwdSlash)+; +string = QuotedString; +constant = Word; + +openCurly = '{'; +closeCurly = '}'; +openBracket = '['; +closeBracket = ']'; +eq = '='; +comma = ','; +colon = ':'; +semi = ';'; +openParen = '('; +closeParen = ')'; +gt = '>'; +tilde = '~'; +pipe = '|'; +fwdSlash = '/'; +hash = '#'; +dot = '.'; + +num = Number; \ No newline at end of file diff --git a/res/.svn/text-base/css2_1.grammar.svn-base b/res/.svn/text-base/css2_1.grammar.svn-base new file mode 100644 index 0000000..7e412ca --- /dev/null +++ b/res/.svn/text-base/css2_1.grammar.svn-base @@ -0,0 +1,203 @@ +/* + This is an attempt to convert the official CSS 2.1 grammar to TDParseKit +*/ + + +@start = stylesheet; + +// stylesheet +// : [ CHARSET_SYM S* STRING S* ';' ]? +// [S|CDO|CDC]* [ import [S|CDO|CDC]* ]* +// [ [ ruleset | media | page | font_face ] [S|CDO|CDC]* ]* +// ; +charsetSymbol = '@' 'charset'; +charset = (charsetSymbol Word ';'); +stylesheet = charset? import* contents; +contents = (ruleset | media | page | fontFace)*; +stuff = (cdo|cdc)*; + + +// import +// : IMPORT_SYM S* +// [STRING|URI] S* [ medium [ ',' S* medium]* ]? ';' S* +// ; +mediaList = medium commaMedium*; +commaMedium = ',' medium; +importSymbol = '@' 'import'; +import = importSymbol (Word | uri) mediaList? ';'; + + +// media +// : MEDIA_SYM S* medium [ ',' S* medium ]* '{' S* ruleset* '}' S* +// ; + +mediaSymbol = '@' 'media'; +media = mediaSymbol mediaList '{' ruleset* '}'; + + + +// medium +// : IDENT S* +// ; +medium = identifier; + + + +// page +// : PAGE_SYM S* IDENT? pseudo_page? S* +// '{' S* declaration [ ';' S* declaration ]* '}' S* +// ; +pageSymbol = '@' 'page'; +page = pagePrefix pageBody; +pagePrefix = pageSymbol identifier? pseudoPage?; +pageBody = '{' decl decl* '}'; + + +// pseudo_page +// : ':' IDENT +// ; +pseudoPage = ':' identifier; + + +// font_face +// : FONT_FACE_SYM S* +// '{' S* declaration [ ';' S* declaration ]* '}' S* +// ; +fontFaceSymbol = '@' fontFace; +fontFace = fontFaceSymbol '{' decl decl* '}'; + + +// operator +// : '/' S* | ',' S* | /* empty * / +// ; +operator = '/' | ',' | Empty; + + + +// combinator +// : '+' S* | '>' S* | /* empty * / +// ; +combinator = '+' | '>' | Empty; + + + +// unary_operator +// : '-' | '+' +// ; +unaryOperator = '-' | '+'; + + +// property +// : IDENT S* +// ; +property = identifier; + + +// ruleset +// : selector [ ',' S* selector ]* +// '{' S* declaration [ ';' S* declaration ]* '}' S* +// ; +ruleset = selector commaSelector* '{' decl decl* '}'; +commaSelector = ',' selector; + + +// selector +// : simple_selector [ combinator simple_selector ]* +// ; +selector = simpleSelector (combinator simpleSelector)*; + + +// simple_selector +// : element_name? [ HASH | class | attrib | pseudo ]* S* +// ; +simpleSelector = elementName? (hash | class | attrib | pseudo)*; + + +// class +// : '.' IDENT +// ; +class = '.' identifier; + + +// element_name +// : IDENT | '*' +// ; +elementName = identifier | '*'; + + +// attrib +// : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* +// [ IDENT | STRING ] S* ]? ']' +// ; +attrib = '[' identifier (('=' | includes | dashmatch) (identifier | Word))? ']'; + + +// pseudo +// : ':' [ IDENT | FUNCTION S* IDENT S* ')' ] +// ; +pseudo = ':' identifier | function identifier ')'; + + +// declaration +// : property ':' S* expr prio? +// | /* empty * / +// ; +decl = (property ':' expr prio?) | Empty; + + +// prio +// : IMPORTANT_SYM S* +// ; +prio = '!' 'important'; + + +// expr +// : term [ operator term ]* +// ; +expr = term (operator term)*; + + +// term +// : unary_operator? +// [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* | +// TIME S* | FREQ S* | function ] +// | STRING S* | IDENT S* | URI S* | RGB S* | UNICODERANGE S* | hexcolor +// ; +term = unaryOperator? (Number | percentage | length | ems | exs | angle | time | freq | function) + | Word | identifier | uri | hexcolor; + + +// function +// : FUNCTION S* expr ')' S* +// ; +function = XXX expr ')'; + + +// * +// * There is a constraint on the color that it must +// * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) +// * after the "#"; e.g., "#000" is OK, but "#abcd" is not. +// * +// hexcolor +// : HASH S* +// ; +hexcolor = hash; + +cdo = ''; +includes = '~='; +dashmatch = '|='; + +identifier = Word; + +hash = '#' (Word|Number); +ems = Number 'em'; +exs = Number 'ex'; +length = Number ('px'|'cm'|'mm'|'in'|'pt'|'pc'); +angle = Number ('deg'|'rad'|'grad'); +time = Number ('s'|'ms'); +freq = Number ('hz'|'khz'); +dimension = Number identifier; +percentage = Number '%'; +uri = 'url' '(' (Word|Symbol|Number)+ ')'; +function = identifier '('; diff --git a/res/.svn/text-base/date.grammar.svn-base b/res/.svn/text-base/date.grammar.svn-base new file mode 100644 index 0000000..b1084a9 --- /dev/null +++ b/res/.svn/text-base/date.grammar.svn-base @@ -0,0 +1,40 @@ +/* + + TDParseKit Grammar Syntax now supports regular expressions (powered by RegExKit Lite) + + So, as a trivial (and useless) example, the following TDPK grammar + specifies a tiny language which allows dates in the format of: + + 2009-06-21 + +*/ + +@start = date; // the 'date' production is the outermost production in this grammar + +date = /\d{4}/ '-' /\d{2}/ '-' /\d{2}/; // will match any sequence of tokens whose `stringValue` property matches these regexes + // separated by two '-' chars + + + + + + + + +/* +NOTE: +An equivalent grammar could be expressed in many ways. Here's an equivalent grammar with explicit ObjC assembler callbacks added: + + +@start = year dash month dash day; + +dash = '-'; + +year (matchedYear:) = /\d{4}/; // when matched, your specified `assembler` object (think delegate) will receive a + // callback to it's `-matchedYear:` method with a `PKAssembly` argument. + // the token matched by the regex will on the top of the assebly's stack ready for you + +month (matchedMonth:) = /\d{2}/; +day (matchedDay:) = /\d{2}/; + +*/ \ No newline at end of file diff --git a/res/.svn/text-base/erb.grammar.svn-base b/res/.svn/text-base/erb.grammar.svn-base new file mode 100644 index 0000000..a8ff87a --- /dev/null +++ b/res/.svn/text-base/erb.grammar.svn-base @@ -0,0 +1,15 @@ +@symbols = '<@' '<@=' '@>'; + +@start = (ignored | importantStuff)*; +ignored = ~startMarker; + +importantStuff = print | eval; +print = printStartMarker keyPath endMarker; +eval = evalStartMarker keyPath endMarker; + +keyPath = Word dotWord*; +dotWord = ('.' Word); + +printStartMarker = '<@='; +evalStartMarker = '<@'; +endMarker = '@>'; \ No newline at end of file diff --git a/res/.svn/text-base/example.css.svn-base b/res/.svn/text-base/example.css.svn-base new file mode 100644 index 0000000..790775a --- /dev/null +++ b/res/.svn/text-base/example.css.svn-base @@ -0,0 +1,54 @@ +.openCurly > closeCurly, +#comma[foo], +colon[foo=bar] bat, +openParen[foo="bar"], +closeParen, +name:psuedo-name, +foo[bar|=baz] +px, +px, +rgb { + -webkit-border-radius:12px; + color: rgb(178.5, 35.7, 135.15); + background-color: rgb(30, 30, 36); + font-family: 'Monaco'; + font-size: 11 em; + font-weight: bold; +} + +body { + font:14px/1.4 "Lucida Grande", LucidaGrande, Verdana, Helvetica, Arial; +} + +#content { + position:relative; + width:650px; + margin:20px auto; +} + +#icon { + float:left; + margin-right:15px; +} + +h1 { + padding-top:15px; + font-size:48px; +} + +#desc { + position:absolute; + left:170px; top:75px; +} + +#screenshot { + display:block; + width:500px; + margin:80px auto 35px; + border:1px solid silver; +} + +#copyright, #credits, #hostedby { + font-size:small; + text-align:center; +} diff --git a/res/.svn/text-base/example.html.svn-base b/res/.svn/text-base/example.html.svn-base new file mode 100644 index 0000000..beb23a0 --- /dev/null +++ b/res/.svn/text-base/example.html.svn-base @@ -0,0 +1,28 @@ + + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + + CFBundleName + ${PRODUCT_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.parsekit.ParseKit + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.4 + NSPrincipalClass + + + \ No newline at end of file diff --git a/res/.svn/text-base/example1.srgs.svn-base b/res/.svn/text-base/example1.srgs.svn-base new file mode 100644 index 0000000..2549db4 --- /dev/null +++ b/res/.svn/text-base/example1.srgs.svn-base @@ -0,0 +1,24 @@ +#ABNF 1.0 ISO-8859-1; + +// Default grammar language is US English +language en-US; + +// Single language attachment to tokens +// Note that "fr-CA" (Canadian French) is applied to only +// the word "oui" because of precedence rules +$yes = yes | oui!fr-CA; + +// Single language attachment to an expansion +$people1 = (Michel Tremblay | André Roy)!fr-CA; + +// Handling language-specific pronunciations of the same word +// A capable speech recognizer will listen for Mexican Spanish and +// US English pronunciations. +$people2 = Jose!en-US | Jose!es-MX; + +/** + * Multi-lingual input possible + * @example may I speak to André Roy + * @example may I speak to Jose + */ +public $request = may I speak to ($people1 | $people2); \ No newline at end of file diff --git a/res/.svn/text-base/html.css.svn-base b/res/.svn/text-base/html.css.svn-base new file mode 100644 index 0000000..43d3ba0 --- /dev/null +++ b/res/.svn/text-base/html.css.svn-base @@ -0,0 +1,63 @@ +lt, gt, fwdSlash, endTagStart, eq { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +eq { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +tagName { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +attrValue { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +attrName { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +text { +// color:rgb(61.2, 178.5, 68.85); + color:rgb(255, 255, 255); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +comment { + color:rgb(61.2, 178.5, 68.85); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +pi { + color:rgb(22.95, 158.1, 188.7); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +doctype { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} \ No newline at end of file diff --git a/res/.svn/text-base/html.grammar.svn-base b/res/.svn/text-base/html.grammar.svn-base new file mode 100644 index 0000000..4754f8d --- /dev/null +++ b/res/.svn/text-base/html.grammar.svn-base @@ -0,0 +1,41 @@ +/* + An HTML grammar for use with TDParseKit + + this grammar is intentionally very forgiving (non-strict) + the point here is to highlight, not validate, HTML. +*/ + +@multiLineComments = ''; +@commentState = '<'; +@commentState.fallbackState = delimitState; + +@delimitedString = '' nil; +@delimitedString = '' nil; +@delimitState.fallbackState = symbolState; + +@start = any*; +any = element | text | doctype | pi | comment; + +pi = DelimitedString(''); + +doctype = DelimitedString(''); +element = emptyTag | startTag elementContent* endTag; +elementContent = element | text | comment | pi; +text = /[^<]+/; + +emptyTag = lt tagName attr* fwdSlash gt; +startTag = lt junk? tagName attr* gt; +endTag = lt fwdSlash tagName gt; + +tagName = Word; + +attr = attrName (eq attrValue)?; +attrName = Word; +attrValue = QuotedString; + +eq = '='; +lt = '<'; +gt = '>'; +fwdSlash = '/'; + +comment = Comment; diff --git a/res/.svn/text-base/javascript.grammar.svn-base b/res/.svn/text-base/javascript.grammar.svn-base new file mode 100644 index 0000000..af9032f --- /dev/null +++ b/res/.svn/text-base/javascript.grammar.svn-base @@ -0,0 +1,430 @@ +@symbols = '||' '&&' '!=' '!==' '==' '===' '<=' '>=' '++' '--' '+=' '-=' '*=' '/=' '%=' '<<' '>>' '>>>' '<<=' '>>=' '>>>=' '&=' '^=' '|='; + +@reportsCommentTokens = YES; +@commentState = '/'; +@singleLineComments = '//'; +@multiLineComments = '/*' '*/'; + +@start = program; + +if = 'if'; +else = 'else'; +while = 'while'; +for = 'for'; +in = 'in'; +break = 'break'; +continue = 'continue'; +with = 'with'; +return = 'return'; +var = 'var'; +delete = 'delete'; +new = 'new'; +this = 'this'; +false = 'false'; +true = 'true'; +null = 'null'; +undefined = 'undefined'; +void = 'void'; +typeof = 'typeof'; +instanceof = 'instanceof'; +function = 'function'; + +openCurly = '{'; +closeCurly = '}'; +openParen = '('; +closeParen = ')'; +openBracket = '['; +closeBracket = ']'; +comma = ','; +dot = '.'; +semi = ';'; +colon = ':'; +equals = '='; +not = '!'; +lt = '<'; +gt = '>'; +amp = '&'; +pipe = '|'; +caret = '^'; +tilde = '~'; +question = '?'; +plus = '+'; +minus = '-'; +times = '*'; +div = '/'; +mod = '%'; + +or = '||'; +and = '&&'; +ne = '!='; +isnot = '!=='; +eq = '=='; +is = '==='; +le = '<='; +ge = '>='; +plusPlus = '++'; +minusMinus = '--'; +plusEq = '+='; +minusEq = '-='; +timesEq = '*='; +divEq = '/='; +modEq = '%='; +shiftLeft = '<<'; +shiftRight = '>>'; +shiftRightExt = '>>>'; +shiftLeftEq = '<<='; +shiftRightEq = '>>='; +shiftRightExtEq = '>>>='; +andEq = '&='; +xorEq = '^='; +orEq = '|='; + +assignmentOperator = equals | plusEq | minusEq | timesEq | divEq | modEq | shiftLeftEq | shiftRightEq | shiftRightExtEq | andEq | xorEq | orEq; + +relationalOperator = lt | gt | ge | le | instanceof; +equalityOperator = eq | ne | is | isnot; + +shiftOperator = shiftLeft | shiftRight | shiftRightExt; +incrementOperator = plusPlus | minusMinus; +unaryOperator = tilde | delete | typeof | void; + +multiplicativeOperator = times | div | mod; + + + +// Program: +// empty +// Element Program + +program = element+; + + + +// Element: +// function Identifier ( ParameterListOpt ) CompoundStatement +// Statement + +element = func | stmt; +func = function identifier openParen paramListOpt closeParen compoundStmt; + + + +// ParameterListOpt: +// empty +// ParameterList + +paramListOpt = Empty | paramList; + + + +// ParameterList: +// Identifier +// Identifier , ParameterList + +paramList = identifier commaIdentifier*; +commaIdentifier = comma identifier; + + + +// CompoundStatement: +// { Statements } + +compoundStmt = openCurly stmts closeCurly; + + + +// Statements: +// empty +// Statement Statements + +stmts = stmt*; + + + +// Statement: +// ; +// if Condition Statement +// if Condition Statement else Statement +// while Condition Statement +// ForParen ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin in Expression ) Statement +// break ; +// continue ; +// with ( Expression ) Statement +// return ExpressionOpt ; +// CompoundStatement +// VariablesOrExpression ; + +stmt = semi | ifStmt | ifElseStmt | whileStmt | forParenStmt | forBeginStmt | forInStmt | breakStmt | continueStmt | withStmt | returnStmt | compoundStmt | variablesOrExprStmt; +ifStmt = if condition stmt; +ifElseStmt = if condition stmt else stmt; +whileStmt = while condition stmt; +forParenStmt = forParen semi exprOpt semi exprOpt closeParen stmt; +forBeginStmt = forBegin semi exprOpt semi exprOpt closeParen stmt; +forInStmt = forBegin in expr closeParen stmt; +breakStmt = break semi; +continueStmt = continue semi; +withStmt = with openParen expr closeParen stmt; +returnStmt = return exprOpt semi; +variablesOrExprStmt = variablesOrExpr semi; + + + +// Condition: +// ( Expression ) + +condition = openParen expr closeParen; + + + +// ForParen: +// for ( + +forParen = for openParen; + + + +// ForBegin: +// ForParen VariablesOrExpression + +forBegin = forParen variablesOrExpr; + + + +// VariablesOrExpression: +// var Variables +// Expression + +variablesOrExpr = varVariables | expr; +varVariables = var variables; + + + +// Variables: +// Variable +// Variable , Variables + +variables = variable commaVariable*; +commaVariable = comma variable; + + + +// Variable: +// Identifier +// Identifier = AssignmentExpression + +variable = identifier assignment?; +assignment = equals assignmentExpr; + + + +// ExpressionOpt: +// empty +// Expression + +exprOpt = Empty | expr; // TODO -- Empty | expr; + + + +// Expression: +// AssignmentExpression +// AssignmentExpression , Expression + +expr = assignmentExpr commaExpr?; +commaExpr = comma expr; + + + +// AssignmentExpression: +// ConditionalExpression +// ConditionalExpression AssignmentOperator AssignmentExpression + +assignmentExpr = conditionalExpr extraAssignment?; +extraAssignment = assignmentOperator assignmentExpr; + + + +// ConditionalExpression: +// OrExpression +// OrExpression ? AssignmentExpression : AssignmentExpression + +conditionalExpr = orExpr ternaryExpr?; +ternaryExpr = question assignmentExpr colon assignmentExpr; + + + +// OrExpression: +// AndExpression +// AndExpression || OrExpression + +orExpr = andExpr orAndExpr*; +orAndExpr = or andExpr; + + + +// AndExpression: +// BitwiseOrExpression +// BitwiseOrExpression && AndExpression + +andExpr = bitwiseOrExpr andAndExpr?; +andAndExpr = and andExpr; + + + +// BitwiseOrExpression: +// BitwiseXorExpression +// BitwiseXorExpression | BitwiseOrExpression + +bitwiseOrExpr = bitwiseXorExpr pipeBitwiseOrExpr?; +pipeBitwiseOrExpr = pipe bitwiseOrExpr; + + + +// BitwiseXorExpression: +// BitwiseAndExpression +// BitwiseAndExpression ^ BitwiseXorExpression + +bitwiseXorExpr = bitwiseAndExpr caretBitwiseXorExpr?; +caretBitwiseXorExpr = caret bitwiseXorExpr; + + + +// BitwiseAndExpression: +// EqualityExpression +// EqualityExpression & BitwiseAndExpression + +bitwiseAndExpr = equalityExpr ampBitwiseAndExpression?; +ampBitwiseAndExpression = amp bitwiseAndExpr; + + + +// EqualityExpression: +// RelationalExpression +// RelationalExpression EqualityualityOperator EqualityExpression + +equalityExpr = relationalExpr equalityOpEqualityExpr?; +equalityOpEqualityExpr = equalityOperator equalityExpr; + + + +// RelationalExpression: +// ShiftExpression +// RelationalExpression RelationalationalOperator ShiftExpression + +relationalExpr = shiftExpr | relationalExprRHS; +relationalExprRHS = relationalExpr relationalOperator shiftExpr; + + + +// ShiftExpression: +// AdditiveExpression +// AdditiveExpression ShiftOperator ShiftExpression + +shiftExpr = additiveExpr shiftOpShiftExpr?; +shiftOpShiftExpr = shiftOperator shiftExpr; + + + +// AdditiveExpression: +// MultiplicativeExpression +// MultiplicativeExpression + AdditiveExpression +// MultiplicativeExpression - AdditiveExpression + +additiveExpr = multiplicativeExpr plusOrMinusExpr?; +plusOrMinusExpr = plusExpr | minusExpr; +plusExpr = plus additiveExpr; +minusExpr = minus additiveExpr; + + + +// MultiplicativeExpression: +// UnaryExpression +// UnaryExpression MultiplicativeOperator MultiplicativeExpression + +multiplicativeExpr = unaryExpr (multiplicativeOperator multiplicativeExpr)?; + + + +// UnaryExpression: +// MemberExpression +// UnaryOperator UnaryExpression +// - UnaryExpression +// IncrementOperator MemberExpression +// MemberExpression IncrementOperator +// new Constructor +// delete MemberExpression + +unaryExpr = memberExpr | unaryExpr1 | unaryExpr2 | unaryExpr3 | unaryExpr4 | unaryExpr5 | unaryExpr6; +unaryExpr1 = unaryOperator unaryExpr; +unaryExpr2 = minus unaryExpr; +unaryExpr3 = incrementOperator memberExpr; +unaryExpr4 = memberExpr incrementOperator; +unaryExpr5 = new constructor; +unaryExpr6 = delete memberExpr; + + + +// Constructor: +// this . ConstructorCall +// ConstructorCall + +constructor = constructorCall; // TODO ??? + + + +// ConstructorCall: +// Identifier +// Identifier ( ArgumentListOpt ) +// Identifier . ConstructorCall + +constructorCall = identifier parenArgListParen?; // TODO +parenArgListParen = openParen argListOpt closeParen; + + + +// MemberExpression: +// PrimaryExpression +// PrimaryExpression . MemberExpression +// PrimaryExpression [ Expression ] +// PrimaryExpression ( ArgumentListOpt ) + +memberExpr = primaryExpr dotBracketOrParenExpr?; +dotBracketOrParenExpr = dotMemberExpr | bracketMemberExpr | parenMemberExpr; +dotMemberExpr = dot memberExpr; +bracketMemberExpr = openBracket expr closeBracket; +parenMemberExpr = openParen argListOpt closeParen; + + + +// ArgumentListOpt: +// empty +// ArgumentList + +argListOpt = argList?; + + + +// ArgumentList: +// AssignmentExpression +// AssignmentExpression , ArgumentList + +argList = assignmentExpr commaAssignmentExpr*; +commaAssignmentExpr = comma assignmentExpr; + + + +// PrimaryExpression: +// ( Expression ) +// Identifier +// IntegerLiteral +// FloatingPointLiteral +// StringLiteral +// false +// true +// null +// this + +primaryExpr = parenExprParen | identifier | Number | QuotedString | false | true | null | undefined | this; +parenExprParen = openParen expr closeParen; +identifier = Word; diff --git a/res/.svn/text-base/javascript_ll.txt.svn-base b/res/.svn/text-base/javascript_ll.txt.svn-base new file mode 100644 index 0000000..9ddb815 --- /dev/null +++ b/res/.svn/text-base/javascript_ll.txt.svn-base @@ -0,0 +1,133 @@ + +JavaScript LL(1) Grammar + +This appendix contains the NQLL(1) grammar (Not Quite LL(1)) for JavaScript. +NOTE: This appendix is missing the algorithm for recovering from missing semicolon errors. + + +Program: + empty + Element Program + Element: + function Identifier ( ParameterListOpt ) CompoundStatement + Statement + ParameterListOpt: + empty + ParameterList + ParameterList: + Identifier + Identifier , ParameterList + CompoundStatement: + { Statements } + Statements: + empty + Statement Statements + Statement: + ; + if Condition Statement + if Condition Statement else Statement + while Condition Statement + ForParen ; ExpressionOpt ; ExpressionOpt ) Statement + ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement + ForBegin in Expression ) Statement + break ; + continue ; + with ( Expression ) Statement + return ExpressionOpt ; + CompoundStatement + VariablesOrExpression ; + Condition: + ( Expression ) + ForParen: + for ( + ForBegin: + ForParen VariablesOrExpression + VariablesOrExpression: + var Variables + Expression + Variables: + Variable + Variable , Variables + Variable: + Identifier + Identifier = AssignmentExpression + ExpressionOpt: + empty + Expression + Expression: + AssignmentExpression + AssignmentExpression , Expression + AssignmentExpression: + ConditionalExpression + ConditionalExpression AssignmentOperator AssignmentExpression + ConditionalExpression: + OrExpression + OrExpression ? AssignmentExpression : AssignmentExpression + OrExpression: + AndExpression + AndExpression || OrExpression + AndExpression: + BitwiseOrExpression + BitwiseOrExpression && AndExpression + BitwiseOrExpression: + BitwiseXorExpression + BitwiseXorExpression | BitwiseOrExpression + BitwiseXorExpression: + BitwiseAndExpression + BitwiseAndExpression ^ BitwiseXorExpression + BitwiseAndExpression: + EqualityExpression + EqualityExpression & BitwiseAndExpression + EqualityExpression: + RelationalExpression + RelationalExpression EqualityualityOperator EqualityExpression + RelationalExpression: + ShiftExpression + RelationalExpression RelationalationalOperator ShiftExpression + ShiftExpression: + AdditiveExpression + AdditiveExpression ShiftOperator ShiftExpression + AdditiveExpression: + MultiplicativeExpression + MultiplicativeExpression + AdditiveExpression + MultiplicativeExpression - AdditiveExpression + MultiplicativeExpression: + UnaryExpression + UnaryExpression MultiplicativeOperator MultiplicativeExpression + UnaryExpression: + MemberExpression + UnaryOperator UnaryExpression + - UnaryExpression + IncrementOperator MemberExpression + MemberExpression IncrementOperator + new Constructor + delete MemberExpression + Constructor: + this . ConstructorCall + ConstructorCall + ConstructorCall: + Identifier + Identifier ( ArgumentListOpt ) + Identifier . ConstructorCall + MemberExpression: + PrimaryExpression + PrimaryExpression . MemberExpression + PrimaryExpression [ Expression ] + PrimaryExpression ( ArgumentListOpt ) + ArgumentListOpt: + empty + ArgumentList + ArgumentList: + AssignmentExpression + AssignmentExpression , ArgumentList + PrimaryExpression: + ( Expression ) + Identifier + IntegerLiteral + FloatingPointLiteral + StringLiteral + false + true + null + this +[Previous] [First] \ No newline at end of file diff --git a/res/.svn/text-base/json-old.grammar.svn-base b/res/.svn/text-base/json-old.grammar.svn-base new file mode 100644 index 0000000..782543c --- /dev/null +++ b/res/.svn/text-base/json-old.grammar.svn-base @@ -0,0 +1,26 @@ +/** + A Grammar for JSON + + NOTE: This grammar has a fatal flaw. it does not allow for the heirarchical nature of + JSON. Objects and arrays may only be one level deep according to this grammar. + This is a limitation of my grammar parser: it does not allow circular references. + That wll be fixed soon + + */ +null = 'null'; +true = 'true'; +false = 'false'; +value = null | true | false | Num | QuotedString; // here's the flaw. should include: "array | object" + +commaValue = ',' value; +actualArray = value commaValue*; +arrayContent = Empty | actualArray; +array = '[' arrayContent ']'; + +property = QuotedString ':' value; // NOTE: property names are quoted in JSON +commaProperty = ',' property; +actualObject = property commaProperty*; +objectContent = Empty | actualObject; +object = '{' objectContent '}'; + +start = (array | object); \ No newline at end of file diff --git a/res/.svn/text-base/json.css.svn-base b/res/.svn/text-base/json.css.svn-base new file mode 100644 index 0000000..b5083e7 --- /dev/null +++ b/res/.svn/text-base/json.css.svn-base @@ -0,0 +1,43 @@ +/** + +A CSS Stylesheet that matches the JSON grammar + +note that each terminal production from json.grammar is listed in a CSS selector below. +text that matches any of these productions will display with the css properties listed here + +*/ + +openCurly, closeCurly, openBracket, closeBracket, comma, colon { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +null, true, false { + color:rgb(196.35, 45.9, 51.0); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +propertyName { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +string { + color:rgb(61.2, 178.5, 68.85); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +number { + color:rgb(22.95, 158.1, 188.7); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} diff --git a/res/.svn/text-base/json.grammar.svn-base b/res/.svn/text-base/json.grammar.svn-base new file mode 100644 index 0000000..decd888 --- /dev/null +++ b/res/.svn/text-base/json.grammar.svn-base @@ -0,0 +1,60 @@ +/* + A Grammar for JSON. + +*/ + +@start = Empty | array | object; + +object = openCurly (Empty | objectContent) closeCurly; +objectContent = property commaProperty*; +property = propertyName colon value; +commaProperty = comma property; +propertyName = QuotedString; // NOTE: property names are quoted in JSON + +array = openBracket (Empty | arrayContent) closeBracket; +arrayContent = value commaValue*; +commaValue = comma value; + +value = null | boolean | array | object | number | string; + +string = QuotedString; +number = Number; +null = 'null'; +boolean = 'true' | 'false'; + +openCurly = '{'; +closeCurly = '}'; +openBracket = '['; +closeBracket = ']'; +comma = ','; +colon = ':'; + + +/* + + The built-in terminal production types are (note titlecase) : Empty, Number, QuotedString, Word, UppercaseWord, LowercaseWord + You define collections (alternations, repetitions or sequences) and literal terminals (in quotes). These should be lowercase. + The special '@start' production is the outermost production. + + you can discard tokens by following them with a bang ('!') like: + + closeCurly = '}'!; + + Feed this grammar to -[PKParserFactory parserFromGrammar:assembler:] along with a reference + to an assembler (a call back delegate), and it will return a PKParser object which can + parse strings conforming to this language/grammar. + + The when the returned parser is used, the provided assembler will receive method callbacks for each production matched, like: + + -didMatchObjectAssembly: + -didMatchObjectContentAssembly: + -didMatchPropertyAssembly: + -didMatchArrayAssembly: + -didMatchOpenCurlyAssembly: + etc. + + Each callback method must accept a single PKAssembly argument. This assembly argument + will contain information about the progress made on the the string currently being parsed. + Also the assembly's stack will contain the tokens parsed so far in the current statement. + +*/ \ No newline at end of file diff --git a/res/.svn/text-base/json_with_comments.css.svn-base b/res/.svn/text-base/json_with_comments.css.svn-base new file mode 100644 index 0000000..b0c9d02 --- /dev/null +++ b/res/.svn/text-base/json_with_comments.css.svn-base @@ -0,0 +1,50 @@ +/** + +A CSS Stylesheet that matches the JSON grammar + +note that each terminal production from json.grammar is listed in a CSS selector below. +text that matches any of these productions will display with the css properties listed here + +*/ + +openCurly, closeCurly, openBracket, closeBracket, comma, colon { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +null, true, false { + color:rgb(196.35, 45.9, 51.0); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +propertyName { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +string { + color:rgb(61.2, 178.5, 68.85); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +number { + color:rgb(22.95, 158.1, 188.7); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +comment { + color:rgb(72.95, 208.1, 238.7); + background-color:rgb(0, 0, 0); + font-family:'Monaco'; + font-size:11px; +} diff --git a/res/.svn/text-base/json_with_comments.grammar.svn-base b/res/.svn/text-base/json_with_comments.grammar.svn-base new file mode 100644 index 0000000..a397488 --- /dev/null +++ b/res/.svn/text-base/json_with_comments.grammar.svn-base @@ -0,0 +1,67 @@ +/* + A Fake Grammar for JSON with comments (JSON does not have comments). + +*/ + +@singleLineComments = '#'; +@multiLineComments = '/*' '*/'; + +@start = (Empty | array | object) comment?; + +object = openCurly comment? objectContent closeCurly; +objectContent = Empty | actualObject; +actualObject = property commaProperty*; +property = propertyName colon comment? value; +commaProperty = comma comment? property; +propertyName = QuotedString; // NOTE: property names are quoted in JSON + +array = openBracket comment? arrayContent closeBracket; +arrayContent = Empty | actualArray; +actualArray = value commaValue*; +commaValue = comma comment? value; + +value = (null | true | false | number | string | array | object) comment?; + +comment = Comment; +string = QuotedString; +number = Number; +null = 'null'; +true = 'true'; +false = 'false'; + +openCurly = '{'; +closeCurly = '}'; +openBracket = '['; +closeBracket = ']'; +comma = ','; +colon = ':'; + + +/* + + The built-in terminal production types are (note titlecase) : Empty, Number, QuotedString, Word, UppercaseWord, LowercaseWord + You define collections (alternations, repetitions or sequences) and literal terminals (in quotes). These should be lowercase. + The special '@start' production is the outermost production. + + you can discard tokens by following them with a bang ('!') like: + + closeCurly = '}'!; + + Feed this grammar to -[PKParserFactory parserFromGrammar:assembler:] along with a reference + to an assembler (a call back delegate), and it will return a PKParser object which can + parse strings conforming to this language/grammar. + + The when the returned parser is used, the provided assembler will receive method callbacks for each production matched, like: + + -didMatchObjectAssembly: + -didMatchObjectContentAssembly: + -didMatchPropertyAssembly: + -didMatchArrayAssembly: + -didMatchOpenCurlyAssembly: + etc. + + Each callback method must accept a single PKAssembly argument. This assembly argument + will contain information about the progress made on the the string currently being parsed. + Also the assembly's stack will contain the tokens parsed so far in the current statement. + +*/ \ No newline at end of file diff --git a/res/.svn/text-base/json_with_discards.grammar.svn-base b/res/.svn/text-base/json_with_discards.grammar.svn-base new file mode 100644 index 0000000..f2afb83 --- /dev/null +++ b/res/.svn/text-base/json_with_discards.grammar.svn-base @@ -0,0 +1,39 @@ +/* + A Grammar for JSON which specifies which tokens should be discarded + + Feed this to -[PKParserFactory parserFromGrammar:assembler:] along with a reference + to an assembler (a call back delegate), and it will return a PKParser object which can + parse strings conforming to this language/grammar. + + The when the returned parser is used, the provided assembler will receive method callbacks like: + + -didMatchStart: + -didMatchObject: + -didMatchProperty: + -didMatchArray: + etc. + + whenever a grammar production of the corresponding name has been matched. + + Each callback method must accept a single PKAssembly argument. The provided assembly + will contain information about the progress made on the the string currently being parsed. + Also the assembly's stack will contain the tokens parsed so far in the current statement. +*/ + +@start = Empty | array | object; + +object = '{' objectContent '}'!; +objectContent = Empty | actualObject; +actualObject = property commaProperty*; +commaProperty = ','! property; +property = QuotedString ':'! value; // NOTE: property names are quoted in JSON + +array = '[' arrayContent ']'!; +arrayContent = Empty | actualArray; +actualArray = value commaValue*; +commaValue = ','! value; + +value = null | true | false | array | object | Number | QuotedString; +null = 'null'!; +true = 'true'!; +false = 'false'!; diff --git a/res/.svn/text-base/mini_css.grammar.svn-base b/res/.svn/text-base/mini_css.grammar.svn-base new file mode 100644 index 0000000..12f6ecf --- /dev/null +++ b/res/.svn/text-base/mini_css.grammar.svn-base @@ -0,0 +1,18 @@ +/* + A Grammar for a small subset of CSS useful for syntax highlighting in an NSTextView + NSAttributedString +*/ + +@start = ruleset*; +ruleset = selectors '{' decls '}'!; +selectors = selector commaSelector*; +selector = LowercaseWord; // forcing selectors to be lowercase words for use in a future syntax-highlight framework where i want that +commaSelector = ','! selector; +decls = Empty | actualDecls; +actualDecls = decl decl*; +decl = property ':'! expr ';'!?; +property = 'color' | 'background-color' | 'font-family' | 'font-size'; +expr = pixelValue | rgb | string | constants; +pixelValue = Number 'px'!; +rgb = 'rgb'! '(' Number ','! Number ','! Number ')'!; +string = QuotedString; +constants = 'bold' | 'normal' | 'italic'; \ No newline at end of file diff --git a/res/.svn/text-base/nasty.html.svn-base b/res/.svn/text-base/nasty.html.svn-base new file mode 100644 index 0000000..fa9aceb --- /dev/null +++ b/res/.svn/text-base/nasty.html.svn-base @@ -0,0 +1,68 @@ + + + +http://www.apple.com/ + + + +< + + url + xmls:foo="bar" baz + + = + + "foobar">yes maam + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/.svn/text-base/nonascii.html.svn-base b/res/.svn/text-base/nonascii.html.svn-base new file mode 100644 index 0000000..f39658d --- /dev/null +++ b/res/.svn/text-base/nonascii.html.svn-base @@ -0,0 +1 @@ +ア \ No newline at end of file diff --git a/res/.svn/text-base/nspredicate.grammar.svn-base b/res/.svn/text-base/nspredicate.grammar.svn-base new file mode 100644 index 0000000..8022439 --- /dev/null +++ b/res/.svn/text-base/nspredicate.grammar.svn-base @@ -0,0 +1,121 @@ +/* +A Grammar for Apple's NSPredicate String Format Syntax + +See: http://developer.apple.com/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html + +*/ + +@wordState = '#'; +@wordChars = '.' '[' ']'; + +@symbols = '==' '>=' '=>' '<=' '=<' '!=' '<>' '&&' '||'; + +@start = expr; + +// Expressions + expr = orTerm orOrTerm*; + orOrTerm = or orTerm; + orTerm = andTerm andAndTerm*; + andAndTerm = and andTerm; + andTerm = primaryExpr | compoundExpr; + compoundExpr = '('! expr ')'!; + primaryExpr = predicate | negatedPredicate; + negatedPredicate = not predicate; + + predicate = boolPredicate | comparisonPredicate | stringTestPredicate | collectionTestPredicate; + + +// values + value = keyPath | string | num | bool | array; + + string = QuotedString; + num = Number; + bool = true | false; + true = 'true'!; + false = 'false'!; + +// arrays + array = '{' arrayContentsOpt '}'!; + arrayContentsOpt = Empty | arrayContents; + arrayContents = value commaValue*; + commaValue = ','! value; + + +// keyPaths + keyPath = Word; + +// keyPath = key dotKey*; +// key = name memberAccess?; +// name = Word; +// dotKey = '.' key; +// memberAccess = '[' (num | 'FIRST' | 'LAST' | 'SIZE') ']'; + + +// Comparison Tests + comparisonPredicate = numComparisonPredicate | collectionComparisonPredicate; + + numComparisonPredicate = numComparisonValue comparisonOp numComparisonValue; + numComparisonValue = keyPath | num; + + comparisonOp = eq | gt | lt | gtEq | ltEq | notEq | between; + + eq = '=' | '=='; + gt = '>'; + lt = '<'; + gtEq = '>=' | '=>'; + ltEq = '<=' | '=<'; + notEq = '!=' | '<>'; + between = 'BETWEEN'; + +// breaking these out to make the assembler callbacks simpler + collectionComparisonPredicate = collectionLtPredicate | collectionGtPredicate | collectionLtEqPredicate | collectionGtEqPredicate | collectionEqPredicate | collectionNotEqPredicate; + + collectionLtPredicate = aggregateOp collection lt value; + collectionGtPredicate = aggregateOp collection gt value; + collectionLtEqPredicate = aggregateOp collection ltEq value; + collectionGtEqPredicate = aggregateOp collection gtEq value; + collectionEqPredicate = aggregateOp collection eq value; + collectionNotEqPredicate = aggregateOp collection notEq value; + + + +// Boolean Value Predicates + boolPredicate = truePredicate | falsePredicate; + + truePredicate = 'TRUEPREDICATE'!; + falsePredicate = 'FALSEPREDICATE'!; + + + +// Compound Expressions + and = 'AND'! | '&&'!; + or = 'OR'! | '||'!; + not = 'NOT'! | '!'!; + + + +// String Tests + stringTestPredicate = string stringTestOp value; + + stringTestOp = beginswith | contains | endswith | like | matches; + + beginswith = 'BEGINSWITH'; + contains = 'CONTAINS'; + endswith = 'ENDSWITH'; + like = 'LIKE'; + matches = 'MATCHES'; + + +// Collection Tests + collectionTestPredicate = value in collection; + collection = keyPath | array; + in = 'IN'!; + + +// Aggregate Operators + aggregateOp = any | some | all | none; + any = 'ANY'; + some = 'SOME'; + all = 'ALL'; + none = 'NONE'; + diff --git a/res/.svn/text-base/nyt.html.svn-base b/res/.svn/text-base/nyt.html.svn-base new file mode 100644 index 0000000..3cd9c5d --- /dev/null +++ b/res/.svn/text-base/nyt.html.svn-base @@ -0,0 +1,1843 @@ + + + + + + + + + + + + + + + + +The New York Times - Breaking News, World News & Multimedia + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ +
+
+ + +
+
+ + +
+ +
Wednesday, September 17, 2008 Last Update: 2:12 PM ET
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + +
+ + + + + + +
+ +
+ + + + + +
+
+
+ + + + + +

+Stocks Drop Sharply Despite Bailout of Big Insurer +

+
+ +

+The Fed’s rescue of A.I.G. failed to placate investors, and a report showing a further decline in housing starts added to the gloom. +

+ + + + +
+ + + + +
+
Q & A
+
The A.I.G. Rescue
+

+David Leonhardt answers questions about the implications of the A.I.G. bailout and the economy. +

+ +
+ +
+
+ + +
+
+
+ + +
+
+ +
+ + + +
+ +
Yuriko Nakao/Reuters
+
+ +
+

A board in Tokyo displayed rising stock prices. Stock markets rallied across much of Asia in early trading in response to the rescue of A.I.G.

+ + +
+ + +
+
+ +
+ +
+ + + +
+
+In Asia, the Bloom Is Off the A.I.G. Rose +
+ +

If A.I.G.’s reputation suffers heavily, the company will face an uphill battle in Asia and its other global markets.

+ + + +
+ +
+ + + + + + + + + + +
+
+
+
+
+
+ +
+ + + +
+
American Exception
+
+Supreme Court’s Global Influence Is Waning +
+ +

A diminishing number of foreign courts seem to pay attention to the writings of American justices.

+ + + + +
+ + + + +
+
+16 Are Killed in Attack on U.S. Embassy in Yemen +
+ +

Militants opened fire on the embassy in Sana and detonated a car bomb at its gates, but no Americans were killed or injured, a Yemeni official said.

+ + + + +
+ +
+ +
+
+ + +

2008 Campaign

+ + +
+ + + +
+
+Abortion Issue Again Dividing Catholic Votes +
+ +

A struggle on how Catholics should apply their beliefs in politics is reaching swing cities like Scranton, Pa.

+ + + + +
+ + + + +
+
+New York Settles Lawsuit Over Homeless Families +
+ +

The costly litigation, over homeless families’ access to shelter in New York City, has dragged on since 1983.

+ + + +
+ +
+ + +
+
+
MORE NEWS
+ +
+
+ + + + + + +
+
+
+ +
 
+
+
+
+ +
+ + + + +
+ + +
+
+
+
+ +
+
GUEST Q & A
+
Wheels: Questions for Motocross Champion
+

James Stewart, winner of both the World Supercross and AMA Supercross championships, is taking questions from readers.

+ +
+
+ +
National Correspondent
+

+Amy Harmon, who covers the impact of science and technology on American life, is answering questions. +

+
+ +
+ +
+
+
+ + +
+ + + +
+
+
+ + +

Travel »

+
A Cultural Cornerstone

A Cultural CornerstoneCasco Viejo seems poised to become a hotbed of nightclubs, cafes, and hotels.

+ +
+
36 Hours in San Francisco

36 Hours in San Francisco Prosperity hasn’t sapped the Mission District of its eclecticism.

+
+
+ + +
+
+
+ + +
+ + + + + +
+
+ +
+ +

My Portfolios »

+ + + +
+ +
+ + +
+ +
+
+ + + + + +
+ + +
+ + +
+ + +
+
+ +
+ +
+
+ +
A Scottish House, Traditional Yet Modern
+

BerlinThe “Upside-Down House”, designed in 1959 by James Morris and Robert Steedman, holds a prominent place in Edinburgh’s recent architectural history.

+ +
+
+
+
+Find Properties +
+
+ + +Advanced Search » +
+ + +
+ + + + +
+ + +
+
+
+
General Motors at 100
+

Chevrolet VoltThe Chevrolet Volt, which G.M. unveiled on Tuesday, is intended to provide a jump-start for General Motors’ second century.

+ +
+
+ +

+Submit photos and view and comment on other readers’ cars. Also, view and submit events to the +Automotive Events Calendar. +

+ +
+
+ +
+ + +
+
+Search for new cars +
+
+ + + +
+
+
+
+Search for used cars +
+
+ + + + +
+
+
+More in Automobiles +
+ +
+ +
+
+ + +
+ + +
+

+NYtimes.com / Monster +

+
+
+
Fresh Starts
+
Navigators for the College Bound
+

Navigators for the College BoundPrivate educational consultants take up where overburdened high school guidance counselors leave off.

+
+
ADVERTISEMENT
+
+
+
+

+Find the best job in the +New York metro area +and beyond. +

+
+ + + + Advanced Search » +
+
+Tools +
+ +
+Employers +
+ +
+
+ +
+ + + + + +
+ +
+ + + + + + + + +
+ +
+ + +
+
+  +
+

Inside NYTimes.com

+
+ + + + + + + + + + + + + + + + + + + + + +

Media & Advertising »

World »

Opinion »

Music »

Opinion »

Dining & Wine »

+
+
+ +Chrysler Is Loyal to Its Pickup in a Cold Market + +
+
Chrysler Is Loyal to Its Pickup in a Cold Market
+
+
+
+
+ +Friction as India Converts Farmland Into Factories + +
+
Friction as India Converts Farmland Into Factories
+
+
+
+
+ + + +
+
+
+
+
+
+ +When Julian Schnabel Met Plácido Domingo + +
+
When Julian Schnabel Met Plácido Domingo
+
+
+
+
+ +Op-Ed: Another Country + +
+
Op-Ed: Another Country
+
+
+
+
+ +Instead of Eating to Diet, They’re Eating to Enjoy + +
+
Instead of Eating to Diet, They’re Eating to Enjoy
+
+
+ +
+ +
+ + + + + + + + + +
+ + + + + + + + + +
+ +
+ + + + + +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ + + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/.svn/text-base/objc.grammar.svn-base b/res/.svn/text-base/objc.grammar.svn-base new file mode 100644 index 0000000..5dec845 --- /dev/null +++ b/res/.svn/text-base/objc.grammar.svn-base @@ -0,0 +1,236 @@ + +@symbol = '@interface'; +@symbol = '@implementation'; +@symbol = '@end'; +@symbol = '@class'; +@symbol = '@protocol'; + +// external-declaration: +// function-definition +// declaration +// class-interface +// class-implementation +// category-interface +// category-implementation +// protocol-declaration +// class-declaration-list + +externalDecl = functionDef | decl | classInterface | classImpl | categoryInterface | categoryImpl | protocolDecl | classDeclList; + +// class-interface: +// @interface class-name [ : superclass-name ] +// [ protocol-reference-list ] +// [ instance-variables ] +// [ interface-declaration-list ] +// @end + +classInterface = '@interface' className (':' superclassName)? protocolRefList? ivars? interfaceDeclList? '@end'; + +// class-implementation: +// @implementation class-name [ : superclass-name ] +// [ instance-variables ] +// [ implementation-definition-list ] +// @end + +classImpl = '@implementation' className (':' superclassName)? ivars? implementationDefList? '@end'; + +// category-interface: +// @interface class-name ( category-name ) +// [ protocol-reference-list ] +// [ interface-declaration-list ] +// @end + +categoryInterface = '@interface' className '(' categoryName ')' protocolRefList? interfaceDeclList? '@end'; + +category-implementation: +@implementation class-name ( category-name ) +[ implementation-definition-list ] +@end + +protocol-declaration: +@protocol protocol-name +[ protocol-reference-list ] +[ interface-declaration-list ] +@end + +class-declaration-list: +@class class-list ; + +class-list: +class-name +class-list , class-name + +protocol-reference-list: +< protocol-list > + +protocol-list: +protocol-name +protocol-list , protocol-name + +class-name: +identifier + +superclass-name: +identifier + +category-name: +identifier + +protocol-name: +identifier + +instance-variables: +{ [ visibility-specification ] struct-declaration-list [ instance-variables ] } + +visibility-specification: +@private +@protected +@public + +interface-declaration-list: +declaration +method-declaration +interface-declaration-list declaration +interface-declaration-list method-declaration + +method-declaration: +class-method-declaration +instance-method-declaration + +class-method-declaration: ++ [ method-type ] method-selector ; + +instance-method-declaration: +- [ method-type ] method-selector ; + +implementation-definition-list: +function-definition +declaration +method-definition +implementation-definition-list function-definition +implementation-definition-list declaration +implementation-definition-list method-definition + +method-definition: +class-method-definition +instance-method-definition + +class-method-definition: ++ [ method-type ] method-selector [ declaration-list ] compound-statement + +instance-method-definition: +- [ method-type ] method-selector [ declaration-list ] compound-statement + +method-selector: +unary-selector +keyword-selector [ , ... ] +keyword-selector [ , parameter-type-list ] + +unary-selector: +selector + +keyword-selector: +keyword-declarator +keyword-selector keyword-declarator + +keyword-declarator: +: [ method-type ] identifier +selector : [ method-type ] identifier + +selector: +identifier + +method-type: +( type-name ) + + +Type Specifiers +type-specifier: +void +char +short +int +long +float +double +signed +unsigned +id [ protocol-reference-list ] +class-name [ protocol-reference-list ] +struct-or-union-specifier +enum-specifier +typedef-name + +struct-or-union-specifier: +struct-or-union [ identifier ] { struct-declaration-list } +struct-or-union [ identifier ] { @defs ( class-name ) } +struct-or-union identifier + + +Type Qualifiers +type-qualifier: +const +volatile +protocol-qualifier + +protocol-qualifier: +in +out +inout +bycopy +byref +oneway + + +Primary Expressions +primary-expression: +identifier +constant +string +( expression ) +self +message-expression +selector-expression +protocol-expression +encode-expression + +message-expression: +[ receiver message-selector ] + +receiver: +expression +class-name +super + +message-selector: +selector +keyword-argument-list + +keyword-argument-list: +keyword-argument +keyword-argument-list keyword-argument + +keyword-argument: +selector : expression +: expression + +selector-expression: +@selector ( selector-name ) + +selector-name: +selector +keyword-name-list + +keyword-name-list: +keyword-name +keyword-name-list keyword-name + +keyword-name: +selector : +: + +protocol-expression: +@protocol ( protocol-name ) + +encode-expression: +@encode ( type-name ) \ No newline at end of file diff --git a/res/.svn/text-base/proto.grammar.svn-base b/res/.svn/text-base/proto.grammar.svn-base new file mode 100644 index 0000000..e9adbb7 --- /dev/null +++ b/res/.svn/text-base/proto.grammar.svn-base @@ -0,0 +1,93 @@ +// proto ::= ( message | extend | enum | import | package | option | ";" )* +proto = ( message | extend | enum | import | package | option | ";" )*; + +// import ::= "import" strLit ";" +import = "import" strLit ";"; + +// package ::= "package" ident ";" +package = "package" ident ";"; + +// option ::= "option" optionBody ";" +option = "option" optionBody ";"; + +// optionBody ::= ident ( "." ident )* "=" constant +optionBody = ident ( "." ident )* "=" constant; + +// message ::= "message" ident messageBody +message = "message" ident messageBody; + +// extend ::= "extend" userType messageBody +extend = "extend" userType messageBody; + +// enum ::= "enum" ident "{" ( option | enumField | ";" )* "}" +enum = "enum" ident "{" ( option | enumField | ";" )* "}"; + +// enumField ::= ident "=" intLit ";" +enumField = ident "=" intLit ";"; + +// service ::= "service" ident "{" ( option | rpc | ";" )* "}" +service = "service" ident "{" ( option | rpc | ";" )* "}"; + +// rpc ::= "rpc" ident "(" userType ")" "returns" "(" userType ")" ";" +rpc = "rpc" ident "(" userType ")" "returns" "(" userType ")" ";"; + +// messageBody ::= "{" ( field | enum | message | extend | extensions | group | option | ":" )* "}" +messageBody = "{" ( field | enum | message | extend | extensions | group | option | ":" )* "}"; + +// group ::= modifier "group" camelIdent "=" intLit messageBody +group = modifier "group" camelIdent "=" intLit messageBody; + +// // tag number must be 2^28-1 or lower + +// field ::= modifier type ident "=" intLit ( "[" fieldOption ( "," fieldOption )* "]" )? ";" +field = modifier type ident "=" intLit ( "[" fieldOption ( "," fieldOption )* "]" )? ";"; + +// fieldOption ::= optionBody | "default" "=" constant +fieldOption = optionBody | "default" "=" constant; + +// extensions ::= "extensions" intLit "to" ( intLit | "max" ) ";" +extensions = "extensions" intLit "to" ( intLit | "max" ) ";"; + +// modifier ::= "required" | "optional" | "repeated" +modifier ::= "required" | "optional" | "repeated"; + +// type ::= "double" | "float" | "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string" | "bytes" | userType +type = "double" | "float" | "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string" | "bytes" | userType; + +// // leading dot for identifiers means they're fully qualified + +// userType ::= ( "."? ident )+ +userType = ( "."? ident )+; + +// constant ::= ident | intLit | floatLit | strLit | boolLit +constant = ident | numLit | strLit | boolLit; + +// ident ::= /[A-Za-z_][\w_]*/ +ident = /[A-Za-z_][\w_]*/; + +// // according to parser.cc, group names must start with a capital letter as a +// // hack for backwards-compatibility + +// camelIdent ::= /[A-Z][\w_]*/ +camelIdent = /[A-Z][\w_]*/; + +// intLit ::= decInt | hexInt | octInt +// decInt ::= /\d+/ +// hexInt ::= /0[xX]([A-Fa-f0-9])+/ +// octInt ::= /0[0-7]+/ +// floatLit ::= /\d+(\.\d+)?([Ee][\+-]?\d+)?/ // allow_f_after_float_ is +numLit = Number; + +// disabled by default in tokenizer.cc + +// boolLit ::= "true" | "false" +boolLit = "true" | "false"; + +// strLit ::= quote ( hexEscape | octEscape | charEscape | /[^\0\n]/ )* +strLit = QuotedString; + +// quote +// quote ::= /["']/ +// hexEscape ::= /\\[Xx][A-Fa-f0-9]{1,2}/ +// octEscape ::= /\\0?[0-7]{1,3}/ +// charEscape ::= /\\[abfnrtv\\\?'"]/ diff --git a/res/.svn/text-base/rubyhash.grammar.svn-base b/res/.svn/text-base/rubyhash.grammar.svn-base new file mode 100644 index 0000000..e66161c --- /dev/null +++ b/res/.svn/text-base/rubyhash.grammar.svn-base @@ -0,0 +1,35 @@ +/* + {"brand"=>{"name"=>"something", + "logo"=>#, + "summary"=>"wee", "content"=>"woopy doo"}, "commit"=>"Save", + "authenticity_token"=>"43a94d60304a7fb13a4ff61a5960461ce714e92b", + "action"=>"create", "controller"=>"admin/brands"} +*/ + +@reportsCommentTokens = YES; +@commentState = '#'; +@multiLineComments = '#<' '>'; +@symbols = '=>'; + +@start = Empty | object; + +object = openCurly objectContent closeCurly; +objectContent = Empty | actualObject; +actualObject = property commaProperty*; +property = propertyName arrow value; +commaProperty = comma property; +propertyName = QuotedString; // NOTE: property names are quoted + +value = null | true | false | object | number | string | fileRef; + +string = QuotedString; +number = Number; +fileRef = Comment; +null = 'null'; +true = 'true'; +false = 'false'; + +openCurly = '{'; +closeCurly = '}'; +comma = ','; +arrow = '=>'; diff --git a/res/.svn/text-base/small-xml-file.xml.svn-base b/res/.svn/text-base/small-xml-file.xml.svn-base new file mode 100644 index 0000000..da49760 --- /dev/null +++ b/res/.svn/text-base/small-xml-file.xml.svn-base @@ -0,0 +1,6 @@ + +http://www.apple.com/ +yes maam + + + \ No newline at end of file diff --git a/res/.svn/text-base/stuff.txt.svn-base b/res/.svn/text-base/stuff.txt.svn-base new file mode 100644 index 0000000..17690e4 --- /dev/null +++ b/res/.svn/text-base/stuff.txt.svn-base @@ -0,0 +1,8 @@ + + + +sudo /Users/itod/Downloads/checker-60/scan-build -o Desktop xcodebuild \ No newline at end of file diff --git a/res/.svn/text-base/svn-commands.txt.svn-base b/res/.svn/text-base/svn-commands.txt.svn-base new file mode 100644 index 0000000..9abc1e8 --- /dev/null +++ b/res/.svn/text-base/svn-commands.txt.svn-base @@ -0,0 +1,23 @@ +svn copy -r1392 https://todparsekit.googlecode.com/svn/trunk/ \ + https://todparsekit.googlecode.com/svn/tags/release-1.5-tag \ + -m "Creating 1.5 release tag from -r1392" + +svn copy -r1392 https://todparsekit.googlecode.com/svn/tags/release-1.5-tag \ + https://todparsekit.googlecode.com/svn/branches/release-1.5-branch \ + -m "Creating 1.5 release branch from -r1392" + + + + +svn delete https://todparsekit.googlecode.com/svn/tags/release-1.4.2-tag \ + -m "deleting first 1.4.2 release tag" + +svn delete https://todparsekit.googlecode.com/svn/branches/release-1.4.2-branch \ + -m "deleting first 1.4.2 release branch" + + + +svn copy -r1361 https://todparsekit.googlecode.com/svn/trunk/ \ + https://todparsekit.googlecode.com/svn/branches/dev-gcd-branch \ + -m "Creating a dev branch for testing GCD stuff. from -r1361" + \ No newline at end of file diff --git a/res/.svn/text-base/xml.grammar.svn-base b/res/.svn/text-base/xml.grammar.svn-base new file mode 100644 index 0000000..15979d6 --- /dev/null +++ b/res/.svn/text-base/xml.grammar.svn-base @@ -0,0 +1,388 @@ +/** + This is a relatively complete TDParseKit grammar for XML 1.0 derived from the XML specification: + + http://www.w3.org/TR/REC-xml/ + + You can create the parser in ObjC like: + + NSString *g = .. // fetch this grammar from disk or wherever + PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self]; + + NSString *XMLString = .. // fetch some XML + [p parse:XMLString]; + + If implemented, your assembler object will receive callbacks for each production in this grammar, like: + + - (void)didMatchElement:(PKAssembly *)a; + - (void)didMatchAttribute:(PKAssembly *)a; + + + This parser is running successfully on some non-trivial real-world XML documents, + but i'm sure there are bugs (espcially in the DTD stuff). + + It's also a little too lenient about a few quoted string values in the spec, and doesnt yet forbid some chars it should. + + I have some tests, But will need many more if this is to be a serious parser: + + http://code.google.com/p/todparsekit/source/browse/trunk/test/TDXMLParserTest.m + + + (I'd like to write an ObjC SAX interface to this parser) + + (Is this the first XML parser implemented directly in Objective-C?) +*/ + +@start = document; + +@reportsWhitespaceTokens = YES; + +@symbols = '&#' '&#x' '' '' '' nil; +@delimitedString = '' nil; + + +// [1] document ::= prolog element Misc* + + document = prolog element misc*; + + +// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */ +// [3] S ::= (#x20 | #x9 | #xD | #xA)+ +// [4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] +// [4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] +// [5] Name ::= NameStartChar (NameChar)* +// [6] Names ::= Name (#x20 Name)* +// [7] Nmtoken ::= (NameChar)+ +// [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)* + + @wordState = ':' '.' '-' '_'; + @wordChars = ':' '.' '-' '_'; + + nmtoken = Word; + + name = Word & /[^-:\.].*/; + + // names = name (S name)*; + // nmtokens = nmtoken (S nmtoken)*; + + + +// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'" +// [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" +// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") + + entityValue = QuotedString; // TODO + attValue = QuotedString; // TODO + systemLiteral = QuotedString; + + +// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" +// [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] + + pubidLiteral = QuotedString; // TODO + + +// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) + + charData = /[^<\&]+/; + + +// [15] Comment ::= '' + + comment = DelimitedString(''); + + +// [16] PI ::= '' Char*)))? '?>' +// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) + + pi = '/* '?>'; + piTarget = name - /xml/i; + + +// [18] CDSect ::= CDStart CData CDEnd +// [19] CDStart ::= '' Char*)) +// [21] CDEnd ::= ']]>' + + cdSect = DelimitedString(''); + + +// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? + + prolog = xmlDecl? misc* (doctypedecl misc*)?; + + +// [23] XMLDecl ::= '' + + xmlDecl = ''; + + +// [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') +// [26] VersionNum ::= '1.' [0-9]+ + + versionNum = /(['"])1\.[0-9]\1/; + versionInfo = S 'version' eq versionNum; + + +// [25] Eq ::= S? '=' S? + + eq = S? '=' S?; + + +// [27] Misc ::= Comment | PI | S + + misc = comment | pi | S; + + +// [28] doctypedecl ::= '' + + doctypedecl = ''; + + +// [28a] DeclSep ::= PEReference | S + + declSep = peReference | S; + + +// [28b] intSubset ::= (markupdecl | DeclSep)* + + intSubset = (markupdecl | declSep)*; + + +// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment + + markupdecl = elementdecl | attlistDecl | entityDecl | notationDecl | pi | comment; + + +// [30] extSubset ::= TextDecl? extSubsetDecl + + extSubset = textDecl? extSubsetDecl; + +// [31] extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)* + + extSubsetDecl = (markupdecl | conditionalSect | declSep)*; + + +// [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) + + sdDecl = S 'standalone' eq /(["'])(yes|no)\1/; + +// [39] element ::= EmptyElemTag | STag content ETag + + element = emptyElemTag | sTag content eTag; + + +// [40] STag ::= '<' Name (S Attribute)* S? '>' + + sTag = '<' name (S attribute)* S? '>'; + + +// [41] Attribute ::= Name Eq AttValue + + attribute = name eq attValue; + + +// [42] ETag ::= '' + + eTag = ''; + + +// [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* + + content = Empty | (element | reference | cdSect | pi | comment | charData)+; + + +// [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' + + emptyElemTag = '<' name (S attribute)* S? '/>'; + + +// [45] elementdecl ::= '' + + elementdecl = ''; + + +// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children + + contentspec = 'EMPTY' | 'ANY' | mixed | children; + + +// [47] children ::= (choice | seq) ('?' | '*' | '+')? + + children = (choice | seq) ('?' | '*' | '+')?; + + +// [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')? + + cp = (name) ('?' | '*' | '+')?; // TODO !!!!!!!!!!!!!! + + +// [49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')' + + choice = '(' S? cp ( S? '|' S? cp )+ S? ')'; + + +// [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')' + + seq = '(' S? cp ( S? ',' S? cp )* S? ')'; + + +// [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')' + + mixed = '(' S? '#PCDATA' (S? '|' S? name)* S? ')*' | '(' S? '#PCDATA' S? ')'; + + +// [52] AttlistDecl ::= '' + + attlistDecl = ''; + + +// AttDef ::= S Name S AttType S DefaultDecl + + attDef = S name S attType S defaultDecl; + + +// [54] AttType ::= StringType | TokenizedType | EnumeratedType + + attType = stringType | tokenizedType | enumeratedType; + + +// [55] StringType ::= 'CDATA' + + stringType = 'CDATA'; + + +// [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS' + + tokenizedType = 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'; + + +// [57] EnumeratedType ::= NotationType | Enumeration + + enumeratedType = notationType | enumeration; + + +// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')' + + notationType = 'NOTATION' S '(' S? name (S? '|' S? name)* S? ')'; + + +// [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')' + + enumeration = '(' S? nmtoken (S? '|' S? nmtoken)* S? ')'; + + +// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue) + + defaultDecl = '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? attValue); + + +// [61] conditionalSect ::= includeSect | ignoreSect + + conditionalSect = includeSect | ignoreSect; + + +// [62] includeSect ::= '' + + includeSect = ''; + + +// [63] ignoreSect ::= '' + + ignoreSect = ''; + + +// [64] ignoreSectContents ::= Ignore ('' Ignore)* + + ignoreSectContents = ignore ('' ignore)*; + + +// [65] Ignore ::= Char* - (Char* ('') Char*) + + ignore = Word - /[^<]*().*/; + + +// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';' + + charRef = '&#' /[0-9]+/ ';' | '&#x' /[0-9a-fA-F]+/ ';'; + + +// [67] Reference ::= EntityRef | CharRef + + reference = entityRef | charRef; + + +// [68] EntityRef ::= '&' Name ';' + + entityRef = '&' name ';'; + + +// [69] PEReference ::= '%' Name ';' + + peReference = '%' name ';'; + + +// [70] EntityDecl ::= GEDecl | PEDecl + + entityDecl = geDecl | peDecl; + + +// [71] GEDecl ::= '' + + geDecl = ''; + + +// [72] PEDecl ::= '' + + peDecl = ''; + + +// [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?) + + entityDef = entityValue | (externalID nDataDecl?); + + +// [74] PEDef ::= EntityValue | ExternalID + + peDef = entityValue | externalID; + + +// [75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral + + externalID = 'SYSTEM' S systemLiteral | 'PUBLIC' S pubidLiteral S systemLiteral; + + +// [76] NDataDecl ::= S 'NDATA' S Name + + nDataDecl = S 'NDATA' S name; + + +// [77] TextDecl ::= '' + + textDecl = ''; + + +// [78] extParsedEnt ::= TextDecl? content + + extParsedEnt = textDecl? content; + + +// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ) +// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* + + encName = /[A-Za-z][-A-Za-z0-9._]*/+; + encodingDecl = S 'encoding' eq QuotedString; + + +// [82] NotationDecl ::= '' + + notationDecl = ''; + + +// [83] PublicID ::= 'PUBLIC' S PubidLiteral + + publicID = 'PUBLIC' S pubidLiteral; diff --git a/res/.svn/text-base/xml_grammar.txt.svn-base b/res/.svn/text-base/xml_grammar.txt.svn-base new file mode 100644 index 0000000..bd01b6b --- /dev/null +++ b/res/.svn/text-base/xml_grammar.txt.svn-base @@ -0,0 +1,78 @@ +[1] document ::= prolog element Misc* +[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]/* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */ +[3] S ::= (#x20 | #x9 | #xD | #xA)+ +[4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender +[5] Name ::= (Letter | '_' | ':') (NameChar)* +[6] Names ::= Name (#x20 Name)* +[7] Nmtoken ::= (NameChar)+ +[8] Nmtokens ::= Nmtoken (#x20 Nmtoken)* +[9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'" +[10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" +[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") +[12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" +[13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] +[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) +[15] Comment ::= '' +[16] PI ::= '' Char*)))? '?>' +[17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) +[18] CDSect ::= CDStart CData CDEnd +[19] CDStart ::= '' Char*)) +[21] CDEnd ::= ']]>' +[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? +[23] XMLDecl ::= '' +[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') +[25] Eq ::= S? '=' S? +[26] VersionNum ::= '1.0' +[27] Misc ::= Comment | PI | S +[28] doctypedecl ::= ''[VC: Root Element Type] +[28a] DeclSep ::= PEReference | S[WFC: PE Between Declarations] +[28b] intSubset ::= (markupdecl | DeclSep)* +[29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment[VC: Proper Declaration/PE Nesting] +[30] extSubset ::= TextDecl? extSubsetDecl +[31] extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)* +[32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))[VC: Standalone Document Declaration] +[39] element ::= EmptyElemTag | STag content ETag[WFC: Element Type Match] +[40] STag ::= '<' Name (S Attribute)* S? '>'[WFC: Unique Att Spec] +[41] Attribute ::= Name Eq AttValue[VC: Attribute Value Type] +[42] ETag ::= '' +[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* +[44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'[WFC: Unique Att Spec] +[45] elementdecl ::= ''[VC: Unique Element Type Declaration] +[46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children +[47] children ::= (choice | seq) ('?' | '*' | '+')? +[48] cp ::= (Name | choice | seq) ('?' | '*' | '+')? +[49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')'[VC: Proper Group/PE Nesting] +[50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'[VC: Proper Group/PE Nesting] +[51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'[VC: Proper Group/PE Nesting] +[52] AttlistDecl ::= '' +[53] AttDef ::= S Name S AttType S DefaultDecl +[54] AttType ::= StringType | TokenizedType | EnumeratedType +[55] StringType ::= 'CDATA' +[56] TokenizedType ::= 'ID'[VC: ID] +[57] EnumeratedType ::= NotationType | Enumeration +[58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'[VC: Notation Attributes] +[59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'[VC: Enumeration] +[60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)[VC: Required Attribute] +[61] conditionalSect ::= includeSect | ignoreSect +[62] includeSect ::= ''[VC: Proper Conditional Section/PE Nesting] +[63] ignoreSect ::= ''[VC: Proper Conditional Section/PE Nesting] +[64] ignoreSectContents ::= Ignore ('' Ignore)* +[65] Ignore ::= Char* - (Char* ('') Char*) +[66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'[WFC: Legal Character] +[67] Reference ::= EntityRef | CharRef +[68] EntityRef ::= '&' Name ';'[WFC: Entity Declared] +[69] PEReference ::= '%' Name ';'[VC: Entity Declared] +[70] EntityDecl ::= GEDecl | PEDecl +[71] GEDecl ::= '' +[72] PEDecl ::= '' +[73] EntityDef ::= EntityValue | (ExternalID NDataDecl?) +[74] PEDef ::= EntityValue | ExternalID +[75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral +[76] NDataDecl ::= S 'NDATA' S Name[VC: Notation Declared] +[77] TextDecl ::= '' +[78] extParsedEnt ::= TextDecl? content +[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ) +[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*/* Encoding name contains only Latin characters */ +[82] NotationDecl ::= ''[VC: Unique Notation Name] +[83] PublicID ::= 'PUBLIC' S PubidLiteral \ No newline at end of file diff --git a/res/.svn/text-base/xpath1_0.grammar.svn-base b/res/.svn/text-base/xpath1_0.grammar.svn-base new file mode 100644 index 0000000..12e37f8 --- /dev/null +++ b/res/.svn/text-base/xpath1_0.grammar.svn-base @@ -0,0 +1,80 @@ +/* + An XPath 1.0 grammar derived from the XPath 1.0 Specification: + + http://www.w3.org/TR/xpath + + + + NOTE-TO-SELF: to avoid infinite recursion, I had to eliminate this production: + + abbreviatedRelativeLocationPath = relativeLocationPath '//' step; + + and therefore remove `abbreviatedRelativeLocationPath` from `relativeLocationPath` which changed from + + relativeLocationPath = step ('/' step)* | abbreviatedRelativeLocationPath; + + to: + + relativeLocationPath = '//'? step ('/' step)*; + + +*/ + +@start = expr; + +@symbols = '//' '..' '!=' '::' '<=' '>='; + +@wordState = '_'; +@wordChars = '_' '.' '-'; + +@numberState = '.'; // numbers may start with dot +@allowsTrailingDot = YES; // numbers may end with dot +@symbolState = '+' '-'; // numbers may not start with a plus or minus sign. they're actually unary operators +@allowsScientificNotation = NO; // exponents not allowed +@allowsOctalNotation = NO; // octal not allowed +@allowsHexidecimalNotation = NO; // hex not allowed + + +expr = orExpr; + orExpr = andExpr ('or' andExpr)*; + andExpr = equalityExpr ('and' equalityExpr)*; + equalityExpr = relationalExpr (('=' | '!=') relationalExpr)*; + relationalExpr = additiveExpr (('<' | '>' | '<=' | '>=') additiveExpr)*; + additiveExpr = multiplicativeExpr (('+' | '-') multiplicativeExpr)*; + multiplicativeExpr = unaryExpr ((multiplyOperator | 'div' | 'mod') unaryExpr)*; + multiplyOperator = '*'; + unaryExpr = '-'* unionExpr; + unionExpr = pathExpr ('|' pathExpr)*; + + +pathExpr = locationPath | filterExpr (('/'| '//') relativeLocationPath)?; + locationPath = relativeLocationPath | absoluteLocationPath; + relativeLocationPath = '//'? step ('/' step)*; + absoluteLocationPath = '/' relativeLocationPath? | abbreviatedAbsoluteLocationPath; + abbreviatedAbsoluteLocationPath = '//' relativeLocationPath; + + filterExpr = primaryExpr predicate*; + primaryExpr = variableReference | literal | number | functionCall | '(' expr ')'; + variableReference = '$' qName; // note whitespace is not allowed here. also qName is optional + literal = QuotedString; + number = Number; + functionCall = functionName '(' (argument (',' argument)* )? ')'; + functionName = qName - nodeType; + qName = (prefix ':')? localPart; + prefix = ncName; + localPart = ncName; + ncName = Word; + argument = expr; + predicate = '[' predicateExpr ']'; + predicateExpr = expr; + + + step = axisSpecifier nodeTest predicate* | abbreviatedStep; + axisSpecifier = axisName '::' | abbreviatedAxisSpecifier; + axisName = 'ancestor' | 'ancestor-or-self' | 'attribute' | 'child' | 'descendant' | 'descendant-or-self' | 'following' | 'following-sibling' | 'namespace' | 'parent' | 'preceding' | 'preceding-sibling' | 'self'; + abbreviatedAxisSpecifier = '@'?; + nodeTest = nameTest | nodeType '(' ')' | 'processing-instruction' '(' literal ')'; + nameTest = '*' | ncName ':' '*' | qName; // note whitespace should not be allowed in second alt here + nodeType = 'comment' | 'text' | 'processing-instruction' | 'node'; + abbreviatedStep = '.' | '..'; + diff --git a/res/.svn/text-base/xpath_grammar.txt.svn-base b/res/.svn/text-base/xpath_grammar.txt.svn-base new file mode 100644 index 0000000..5aacfcf --- /dev/null +++ b/res/.svn/text-base/xpath_grammar.txt.svn-base @@ -0,0 +1,88 @@ +[1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath +[2] AbsoluteLocationPath ::= '/' RelativeLocationPath? | AbbreviatedAbsoluteLocationPath +[3] RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | AbbreviatedRelativeLocationPath +[4] Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep +[5] AxisSpecifier ::= AxisName '::' | AbbreviatedAxisSpecifier +[6] AxisName ::= 'ancestor' + | 'ancestor-or-self' + | 'attribute' + | 'child' + | 'descendant' + | 'descendant-or-self' + | 'following' + | 'following-sibling' + | 'namespace' + | 'parent' + | 'preceding' + | 'preceding-sibling' + | 'self' +[7] NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' +[8] Predicate ::= '[' PredicateExpr ']' +[9] PredicateExpr ::= Expr +[10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath +[11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step +[12] AbbreviatedStep ::= '.' | '..' +[13] AbbreviatedAxisSpecifier ::= '@'? +[14] Expr ::= OrExpr +[15] PrimaryExpr ::= VariableReference + | '(' Expr ')' + | Literal + | Number + | FunctionCall +[16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' +[17] Argument ::= Expr +[18] UnionExpr ::= PathExpr | UnionExpr '|' PathExpr +[19] PathExpr ::= LocationPath + | FilterExpr + | FilterExpr '/' RelativeLocationPath + | FilterExpr '//' RelativeLocationPath +[20] FilterExpr ::= PrimaryExpr | FilterExpr Predicate +[21] OrExpr ::= AndExpr | OrExpr 'or' AndExpr +[22] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr +[23] EqualityExpr ::= RelationalExpr + | EqualityExpr '=' RelationalExpr + | EqualityExpr '!=' RelationalExpr +[24] RelationalExpr ::= AdditiveExpr + | RelationalExpr '<' AdditiveExpr + | RelationalExpr '>' AdditiveExpr + | RelationalExpr '<=' AdditiveExpr + | RelationalExpr '>=' AdditiveExpr +[25] AdditiveExpr ::= MultiplicativeExpr + | AdditiveExpr '+' MultiplicativeExpr + | AdditiveExpr '-' MultiplicativeExpr +[26] MultiplicativeExpr ::= UnaryExpr + | MultiplicativeExpr MultiplyOperator UnaryExpr + | MultiplicativeExpr 'div' UnaryExpr + | MultiplicativeExpr 'mod' UnaryExpr +[27] UnaryExpr ::= UnionExpr + | '-' UnaryExpr + +[28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' + | NameTest + | NodeType + | Operator + | FunctionName + | AxisName + | Literal + | Number + | VariableReference +[29] Literal ::= '"' [^"]* '"' + | "'" [^']* "'" +[30] Number ::= Digits ('.' Digits?)? + | '.' Digits +[31] Digits ::= [0-9]+ +[32] Operator ::= OperatorName + | MultiplyOperator + | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' +[33] OperatorName ::= 'and' | 'or' | 'mod' | 'div' +[34] MultiplyOperator ::= '*' +[35] FunctionName ::= QName - NodeType +[36] VariableReference ::= '$' QName +[37] NameTest ::= '*' + | NCName ':' '*' + | QName +[38] NodeType ::= 'comment' + | 'text' + | 'processing-instruction' + | 'node' +[39] ExprWhitespace ::= S \ No newline at end of file diff --git a/res/.svn/text-base/yahoo-small.json.svn-base b/res/.svn/text-base/yahoo-small.json.svn-base new file mode 100644 index 0000000..210bf96 --- /dev/null +++ b/res/.svn/text-base/yahoo-small.json.svn-base @@ -0,0 +1,18 @@ +{"name": "Yahoo!", + "permalink": "yahoo", + "homepage_url": "http://www.yahoo.com", + "blog_url": "http://yodel.yahoo.com/", + "blog_feed_url": "http://ycorpblog.com/feed/", + "category_code": "web", + "number_of_employees": 13600, + "founded_year": 1994, + "founded_month": null, + "founded_day": null, + "deadpooled_year": null, + "deadpooled_month": null, + "deadpooled_day": null, + "deadpooled_url": null, + "tag_list": "search, portal, webmail, photos", + "email_address": "", + "phone_number": "(408) 349-3300" +} \ No newline at end of file diff --git a/res/.svn/text-base/yahoo.json.svn-base b/res/.svn/text-base/yahoo.json.svn-base new file mode 100644 index 0000000..aab012a --- /dev/null +++ b/res/.svn/text-base/yahoo.json.svn-base @@ -0,0 +1,370 @@ +{"name": "Yahoo!", + "permalink": "yahoo", + "homepage_url": "http://www.yahoo.com", + "blog_url": "http://yodel.yahoo.com/", + "blog_feed_url": "http://ycorpblog.com/feed/", + "category_code": "web", + "number_of_employees": 13600, + "founded_year": 1994, + "founded_month": null, + "founded_day": null, + "deadpooled_year": null, + "deadpooled_month": null, + "deadpooled_day": null, + "deadpooled_url": null, + "tag_list": "search, portal, webmail, photos", + "email_address": "", + "phone_number": "(408) 349-3300", + "overview": "Yahoo was founded in 1994 by Stanford Ph.D. students David Filo and Jerry Yang. It has since evolved into a major internet brand with search, content verticals, and other web services.", + "image": + {"available_sizes": + [[[150, + 37], + "assets/images/resized/0001/0836/10836v1-max-250x150.png"], + [[200, + 50], + "assets/images/resized/0001/0836/10836v1-max-250x250.png"], + [[200, + 50], + "assets/images/resized/0001/0836/10836v1-max-450x450.png"]], + "attribution": null}, + "products": + [{"name": "Yahoo.com", + "permalink": "yahoo-com"}, + {"name": "Yahoo! Mail", + "permalink": "yahoo-mail"}, + {"name": "Yahoo! Search", + "permalink": "yahoo-search"}, + {"name": "Yahoo! Directory", + "permalink": "yahoo-directory"}, + {"name": "Yahoo! Finance", + "permalink": "yahoo-finance"}, + {"name": "My Yahoo", + "permalink": "my-yahoo"}, + {"name": "Yahoo! News", + "permalink": "yahoo-news"}, + {"name": "Yahoo! Groups", + "permalink": "yahoo-groups"}, + {"name": "Yahoo! Messenger", + "permalink": "yahoo-messenger"}, + {"name": "Yahoo! Games", + "permalink": "yahoo-games"}, + {"name": "Yahoo! People Search", + "permalink": "yahoo-people-search"}, + {"name": "Yahoo! Movies", + "permalink": "yahoo-movies"}, + {"name": "Yahoo! Weather", + "permalink": "yahoo-weather"}, + {"name": "Yahoo! Video", + "permalink": "yahoo-video"}, + {"name": "Yahoo! Music", + "permalink": "yahoo-music"}, + {"name": "Yahoo! Sports", + "permalink": "yahoo-sports"}, + {"name": "Yahoo! Maps", + "permalink": "yahoo-maps"}, + {"name": "Yahoo! Auctions", + "permalink": "yahoo-auctions"}, + {"name": "Yahoo! Widgets", + "permalink": "yahoo-widgets"}, + {"name": "Yahoo! Shopping", + "permalink": "yahoo-shopping"}, + {"name": "Yahoo! Real Estate", + "permalink": "yahoo-real-estate"}, + {"name": "Yahoo! Travel", + "permalink": "yahoo-travel"}, + {"name": "Yahoo! Classifieds", + "permalink": "yahoo-classifieds"}, + {"name": "Yahoo! Answers", + "permalink": "yahoo-answers"}, + {"name": "Yahoo! Mobile", + "permalink": "yahoo-mobile"}, + {"name": "Yahoo! Buzz", + "permalink": "yahoo-buzz"}, + {"name": "Yahoo! Open Search Platform", + "permalink": "yahoo-open-search-platform"}, + {"name": "Fire Eagle", + "permalink": "fireeagle"}, + {"name": "Shine", + "permalink": "shine"}, + {"name": "Yahoo! Shortcuts", + "permalink": "yahoo-shortcuts"}], + "competitions": + [{"competitor": + {"name": "Google", + "permalink": "google"}}, + {"competitor": + {"name": "seesmic", + "permalink": "seesmic"}}, + {"competitor": + {"name": "BricaBox", + "permalink": "bricabox"}}, + {"competitor": + {"name": "Clickpass", + "permalink": "clickpass"}}, + {"competitor": + {"name": "Tencent", + "permalink": "tencent"}}, + {"competitor": + {"name": "Hurdan", + "permalink": "better-searcher"}}, + {"competitor": + {"name": "Powerset", + "permalink": "powerset"}}, + {"competitor": + {"name": "Baidu", + "permalink": "baidu"}}, + {"competitor": + {"name": "Zenbe", + "permalink": "zenbe"}}, + {"competitor": + {"name": "Yandex", + "permalink": "yandex"}}, + {"competitor": + {"name": "Placebase", + "permalink": "placebase"}}, + {"competitor": + {"name": "AOL", + "permalink": "aol"}}], + "providerships": + [{"title": "", + "is_past": false, + "provider": + {"name": "OutCast Communications", + "permalink": "outcast-communications"}}, + {"title": "Investment Banking", + "is_past": null, + "provider": + {"name": "Moelis \u0026 Company", + "permalink": "moelis-company"}}, + {"title": "Public Relations", + "is_past": false, + "provider": + {"name": "Powerscourt", + "permalink": "powerscourt"}}], + "funding_rounds": + [], + "investments": + [{"funding_round": + {"round_code": "c", + "source_url": "http://sanjose.bizjournals.com/sanjose/stories/2004/05/24/daily3.html", + "source_description": "Plaxo connects to more funding", + "raised_amount": 7000000.0, + "raised_currency_code": "USD", + "funded_year": 2004, + "funded_month": 4, + "funded_day": 1, + "company": + {"name": "Plaxo", + "permalink": "plaxo"}}}, + {"funding_round": + {"round_code": "b", + "source_url": "http://www.techcrunch.com/2007/08/21/vlingo-voice-enable-any-mobile-application/", + "source_description": "", + "raised_amount": 20000000.0, + "raised_currency_code": "USD", + "funded_year": 2008, + "funded_month": 4, + "funded_day": 2, + "company": + {"name": "Vlingo", + "permalink": "vlingo"}}}, + {"funding_round": + {"round_code": "b", + "source_url": "http://www.paidcontent.org/entry/419-india-deals-ebay-sells-stake-in-indian-ops-bharatmatrimony-gets-2175-mi/", + "source_description": "India Deals: eBay Sells Stake In Indian Ops; Bharatmatrimony Gets $11.75 Million From Yahoo \u0026 Others", + "raised_amount": 11750000.0, + "raised_currency_code": "USD", + "funded_year": 2008, + "funded_month": 2, + "funded_day": 5, + "company": + {"name": "Bharat Matrimony", + "permalink": "bharat-matrimony"}}}], + "acquisition": null, + "acquisitions": + [{"price_amount": null, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 12, + "acquired_day": 1, + "company": + {"name": "delicious", + "permalink": "delicious"}}, + {"price_amount": 1000000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 8, + "acquired_day": 1, + "company": + {"name": "Alibaba", + "permalink": "alibaba"}}, + {"price_amount": 160000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2004, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "Musicmatch", + "permalink": "musicmatch"}}, + {"price_amount": 350000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2007, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "Zimbra", + "permalink": "zimbra"}}, + {"price_amount": 670000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2004, + "acquired_month": 4, + "acquired_day": 1, + "company": + {"name": "Kelkoo", + "permalink": "kelkoo"}}, + {"price_amount": 35000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://arstechnica.com/news.ars/post/20050324-4732.html", + "source_description": "", + "acquired_year": 2005, + "acquired_month": 3, + "acquired_day": 1, + "company": + {"name": "Flickr", + "permalink": "flickr"}}, + {"price_amount": 1000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 10, + "acquired_day": 1, + "company": + {"name": "Upcoming", + "permalink": "upcoming"}}, + {"price_amount": 300000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2007, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "BlueLithium", + "permalink": "bluelithium"}}, + {"price_amount": 160000000.0, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2008/02/12/yahoo-confirms-maven-networks-acquisition/", + "source_description": "Yahoo Confirms Maven Networks Acquisition", + "acquired_year": 2008, + "acquired_month": 1, + "acquired_day": 31, + "company": + {"name": "Maven Networks", + "permalink": "maven-networks"}}, + {"price_amount": 800000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.techcrunch.com/2007/04/29/panama-not-enough-to-battle-google-yahoo-acquires-rightmedia/", + "source_description": "Panama Not Enough To Battle Google: Yahoo Acquires RightMedia", + "acquired_year": 2007, + "acquired_month": 4, + "acquired_day": null, + "company": + {"name": "Right Media", + "permalink": "right-media"}}, + {"price_amount": 10000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.techcrunch.com/2007/01/08/yahoo-buys-mybloglog-no-they-didnt-wait-yes/", + "source_description": "", + "acquired_year": 2007, + "acquired_month": 1, + "acquired_day": null, + "company": + {"name": "MyBlogLog", + "permalink": "mybloglog"}}, + {"price_amount": 40000000.0, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2008/02/04/yahoo-acquires-israeli-foxytunes/", + "source_description": "TechCrunch", + "acquired_year": 2008, + "acquired_month": 2, + "acquired_day": 4, + "company": + {"name": "FoxyTunes", + "permalink": "foxytunes"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2006/09/27/yahoo-has-acquired-jumpcut/", + "source_description": "Yahoo! has acquired Jumpcut", + "acquired_year": 2006, + "acquired_month": 10, + "acquired_day": 2, + "company": + {"name": "Jumpcut", + "permalink": "jumpcut"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.ysearchblog.com/archives/000581.html", + "source_description": "Inquisitor Joins the Yahoo! Search Team", + "acquired_year": 2008, + "acquired_month": 5, + "acquired_day": 9, + "company": + {"name": "Inquisitor", + "permalink": "inquisitor"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.thealarmclock.com/mt/archives/2008/04/yahoo_buys_ad_a.html", + "source_description": "Yahoo! Buys Ad Analytics Firm Indextools", + "acquired_year": 2008, + "acquired_month": 4, + "acquired_day": 10, + "company": + {"name": "Indextools", + "permalink": "indextools"}}], + "offices": + [{"description": null, + "address1": "701 First Avenue", + "address2": "", + "zip_code": "94089", + "city": "Sunnyvale", + "state_code": "CA", + "country_code": "USA", + "latitude": 37.418531, + "longitude": -122.025485}], + "milestones": + [], + "ipo": + {"valuation_amount": null, + "valuation_currency_code": "USD", + "pub_year": 1996, + "pub_month": 4, + "pub_day": 12, + "stock_symbol": "YHOO"} +} \ No newline at end of file diff --git a/res/.svn/text-base/yahoo_with_comments.json.svn-base b/res/.svn/text-base/yahoo_with_comments.json.svn-base new file mode 100644 index 0000000..9d11005 --- /dev/null +++ b/res/.svn/text-base/yahoo_with_comments.json.svn-base @@ -0,0 +1,370 @@ +{"name": "Yahoo!" /* foo bar */ , + "permalink": "yahoo", + "homepage_url": "http://www.yahoo.com", + "blog_url": "http://yodel.yahoo.com/", + "blog_feed_url": "http://ycorpblog.com/feed/", + "category_code": "web", + "number_of_employees": 13600, + "founded_year": 1994, + "founded_month": null, + "founded_day": null, + "deadpooled_year": null, + "deadpooled_month": null, + "deadpooled_day": null, + "deadpooled_url": null, + "tag_list": "search, portal, webmail, photos", + "email_address": "", + "phone_number": "(408) 349-3300", + "overview": "Yahoo was founded in 1994 by Stanford Ph.D. students David Filo and Jerry Yang. It has since evolved into a major internet brand with search, content verticals, and other web services.", + "image": + {"available_sizes": + [[[150, + 37], + "assets/images/resized/0001/0836/10836v1-max-250x150.png"], + [[200, + 50], + "assets/images/resized/0001/0836/10836v1-max-250x250.png"], + [[200, + 50], + "assets/images/resized/0001/0836/10836v1-max-450x450.png"]], + "attribution": null}, + "products": + [{"name": "Yahoo.com", + "permalink": "yahoo-com"}, + {"name": "Yahoo! Mail", + "permalink": "yahoo-mail"}, + {"name": "Yahoo! Search", + "permalink": "yahoo-search"}, + {"name": "Yahoo! Directory", + "permalink": "yahoo-directory"}, + {"name": "Yahoo! Finance", + "permalink": "yahoo-finance"}, + {"name": "My Yahoo", + "permalink": "my-yahoo"}, + {"name": "Yahoo! News", + "permalink": "yahoo-news"}, + {"name": "Yahoo! Groups", + "permalink": "yahoo-groups"}, + {"name": "Yahoo! Messenger", + "permalink": "yahoo-messenger"}, + {"name": "Yahoo! Games", + "permalink": "yahoo-games"}, + {"name": "Yahoo! People Search", + "permalink": "yahoo-people-search"}, + {"name": "Yahoo! Movies", + "permalink": "yahoo-movies"}, + {"name": "Yahoo! Weather", + "permalink": "yahoo-weather"}, + {"name": "Yahoo! Video", + "permalink": "yahoo-video"}, + {"name": "Yahoo! Music", + "permalink": "yahoo-music"}, + {"name": "Yahoo! Sports", + "permalink": "yahoo-sports"}, + {"name": "Yahoo! Maps", + "permalink": "yahoo-maps"}, + {"name": "Yahoo! Auctions", + "permalink": "yahoo-auctions"}, + {"name": "Yahoo! Widgets", + "permalink": "yahoo-widgets"}, + {"name": "Yahoo! Shopping", + "permalink": "yahoo-shopping"}, + {"name": "Yahoo! Real Estate", + "permalink": "yahoo-real-estate"}, + {"name": "Yahoo! Travel", + "permalink": "yahoo-travel"}, + {"name": "Yahoo! Classifieds", + "permalink": "yahoo-classifieds"}, + {"name": "Yahoo! Answers", + "permalink": "yahoo-answers"}, + {"name": "Yahoo! Mobile", + "permalink": "yahoo-mobile"}, + {"name": "Yahoo! Buzz", + "permalink": "yahoo-buzz"}, + {"name": "Yahoo! Open Search Platform", + "permalink": "yahoo-open-search-platform"}, + {"name": "Fire Eagle", + "permalink": "fireeagle"}, + {"name": "Shine", + "permalink": "shine"}, + {"name": "Yahoo! Shortcuts", + "permalink": "yahoo-shortcuts"}], + "competitions": + [{"competitor": + {"name": "Google", + "permalink": "google"}}, + {"competitor": + {"name": "seesmic", + "permalink": "seesmic"}}, + {"competitor": + {"name": "BricaBox", + "permalink": "bricabox"}}, + {"competitor": + {"name": "Clickpass", + "permalink": "clickpass"}}, + {"competitor": + {"name": "Tencent", + "permalink": "tencent"}}, + {"competitor": + {"name": "Hurdan", + "permalink": "better-searcher"}}, + {"competitor": + {"name": "Powerset", + "permalink": "powerset"}}, + {"competitor": + {"name": "Baidu", + "permalink": "baidu"}}, + {"competitor": + {"name": "Zenbe", + "permalink": "zenbe"}}, + {"competitor": + {"name": "Yandex", + "permalink": "yandex"}}, + {"competitor": + {"name": "Placebase", + "permalink": "placebase"}}, + {"competitor": + {"name": "AOL", + "permalink": "aol"}}], + "providerships": + [{"title": "", + "is_past": false, + "provider": + {"name": "OutCast Communications", + "permalink": "outcast-communications"}}, + {"title": "Investment Banking", + "is_past": null, + "provider": + {"name": "Moelis \u0026 Company", + "permalink": "moelis-company"}}, + {"title": "Public Relations", + "is_past": false, + "provider": + {"name": "Powerscourt", + "permalink": "powerscourt"}}], + "funding_rounds": + [], + "investments": + [{"funding_round": + {"round_code": "c", + "source_url": "http://sanjose.bizjournals.com/sanjose/stories/2004/05/24/daily3.html", + "source_description": "Plaxo connects to more funding", + "raised_amount": 7000000.0, + "raised_currency_code": "USD", + "funded_year": 2004, + "funded_month": 4, + "funded_day": 1, + "company": + {"name": "Plaxo", + "permalink": "plaxo"}}}, + {"funding_round": + {"round_code": "b", + "source_url": "http://www.techcrunch.com/2007/08/21/vlingo-voice-enable-any-mobile-application/", + "source_description": "", + "raised_amount": 20000000.0, + "raised_currency_code": "USD", + "funded_year": 2008, + "funded_month": 4, + "funded_day": 2, + "company": + {"name": "Vlingo", + "permalink": "vlingo"}}}, + {"funding_round": + {"round_code": "b", + "source_url": "http://www.paidcontent.org/entry/419-india-deals-ebay-sells-stake-in-indian-ops-bharatmatrimony-gets-2175-mi/", + "source_description": "India Deals: eBay Sells Stake In Indian Ops; Bharatmatrimony Gets $11.75 Million From Yahoo \u0026 Others", + "raised_amount": 11750000.0, + "raised_currency_code": "USD", + "funded_year": 2008, + "funded_month": 2, + "funded_day": 5, + "company": + {"name": "Bharat Matrimony", + "permalink": "bharat-matrimony"}}}], + "acquisition": null, + "acquisitions": + [{"price_amount": null, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 12, + "acquired_day": 1, + "company": + {"name": "delicious", + "permalink": "delicious"}}, + {"price_amount": 1000000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 8, + "acquired_day": 1, + "company": + {"name": "Alibaba", + "permalink": "alibaba"}}, + {"price_amount": 160000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2004, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "Musicmatch", + "permalink": "musicmatch"}}, + {"price_amount": 350000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2007, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "Zimbra", + "permalink": "zimbra"}}, + {"price_amount": 670000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2004, + "acquired_month": 4, + "acquired_day": 1, + "company": + {"name": "Kelkoo", + "permalink": "kelkoo"}}, + {"price_amount": 35000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://arstechnica.com/news.ars/post/20050324-4732.html", + "source_description": "", + "acquired_year": 2005, + "acquired_month": 3, + "acquired_day": 1, + "company": + {"name": "Flickr", + "permalink": "flickr"}}, + {"price_amount": 1000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 10, + "acquired_day": 1, + "company": + {"name": "Upcoming", + "permalink": "upcoming"}}, + {"price_amount": 300000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2007, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "BlueLithium", + "permalink": "bluelithium"}}, + {"price_amount": 160000000.0, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2008/02/12/yahoo-confirms-maven-networks-acquisition/", + "source_description": "Yahoo Confirms Maven Networks Acquisition", + "acquired_year": 2008, + "acquired_month": 1, + "acquired_day": 31, + "company": + {"name": "Maven Networks", + "permalink": "maven-networks"}}, + {"price_amount": 800000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.techcrunch.com/2007/04/29/panama-not-enough-to-battle-google-yahoo-acquires-rightmedia/", + "source_description": "Panama Not Enough To Battle Google: Yahoo Acquires RightMedia", + "acquired_year": 2007, + "acquired_month": 4, + "acquired_day": null, + "company": + {"name": "Right Media", + "permalink": "right-media"}}, + {"price_amount": 10000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.techcrunch.com/2007/01/08/yahoo-buys-mybloglog-no-they-didnt-wait-yes/", + "source_description": "", + "acquired_year": 2007, + "acquired_month": 1, + "acquired_day": null, + "company": + {"name": "MyBlogLog", + "permalink": "mybloglog"}}, + {"price_amount": 40000000.0, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2008/02/04/yahoo-acquires-israeli-foxytunes/", + "source_description": "TechCrunch", + "acquired_year": 2008, + "acquired_month": 2, + "acquired_day": 4, + "company": + {"name": "FoxyTunes", + "permalink": "foxytunes"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2006/09/27/yahoo-has-acquired-jumpcut/", + "source_description": "Yahoo! has acquired Jumpcut", + "acquired_year": 2006, + "acquired_month": 10, + "acquired_day": 2, + "company": + {"name": "Jumpcut", + "permalink": "jumpcut"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.ysearchblog.com/archives/000581.html", + "source_description": "Inquisitor Joins the Yahoo! Search Team", + "acquired_year": 2008, + "acquired_month": 5, + "acquired_day": 9, + "company": + {"name": "Inquisitor", + "permalink": "inquisitor"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.thealarmclock.com/mt/archives/2008/04/yahoo_buys_ad_a.html", + "source_description": "Yahoo! Buys Ad Analytics Firm Indextools", + "acquired_year": 2008, + "acquired_month": 4, + "acquired_day": 10, + "company": + {"name": "Indextools", + "permalink": "indextools"}}], + "offices": + [{"description": null, + "address1": "701 First Avenue", + "address2": "", + "zip_code": "94089", + "city": "Sunnyvale", + "state_code": "CA", + "country_code": "USA", + "latitude": 37.418531, + "longitude": -122.025485}], + "milestones": + [], + "ipo": + {"valuation_amount": null, + "valuation_currency_code": "USD", + "pub_year": 1996, + "pub_month": 4, + "pub_day": 12, + "stock_symbol": "YHOO"} +} \ No newline at end of file diff --git a/res/.svn/tmp/tempfile.2.tmp b/res/.svn/tmp/tempfile.2.tmp new file mode 100644 index 0000000..6d8645d --- /dev/null +++ b/res/.svn/tmp/tempfile.2.tmp @@ -0,0 +1,240 @@ +/* + An XPath 1.0 grammar derived from the XPath 1.0 Specification: + + http://www.w3.org/TR/xpath + +*/ + +@start = locationPath; + +@symbols = '//' + '..' + '!=' + '::' + '<=' + '>='; + + +// [1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath + + locationPath = relativeLocationPath | absoluteLocationPath; + + + +// [2] AbsoluteLocationPath ::= '/' RelativeLocationPath? | AbbreviatedAbsoluteLocationPath + + absoluteLocationPath = '/' relativeLocationPath? | abbreviatedAbsoluteLocationPath; + + +// [3] RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | AbbreviatedRelativeLocationPath +// avoiding left recursion + + relativeLocationPath = step slashStep* | abbreviatedRelativeLocationPath; + + +// [4] Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep + + step = axisSpecifier nodeTest predicate* | abbreviatedStep; + + +// [5] AxisSpecifier ::= AxisName '::' | AbbreviatedAxisSpecifier + + axisSpecifier = axisName '::' | abbreviatedAxisSpecifier; + + +// [6] AxisName ::= 'ancestor' | 'ancestor-or-self' | 'attribute' | 'child' | 'descendant' | 'descendant-or-self' +// | 'following' | 'following-sibling' | 'namespace' | 'parent' | 'preceding' | 'preceding-sibling' | 'self' + + axisName = 'ancestor' | 'ancestor-or-self' | 'attribute' | 'child' | 'descendant' | 'descendant-or-self' + | 'following' | 'following-sibling' | 'namespace' | 'parent' | 'preceding' | 'preceding-sibling' | 'self'; + + +// [7] NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' + + nodeTest = nameTest | nodeType '(' ')' | 'processing-instruction' '(' literal ')'; + + +// [8] Predicate ::= '[' PredicateExpr ']' + + predicate = '[' predicateExpr ']'; + + +// [9] PredicateExpr ::= Expr + + predicateExpr = expr; + + +// [10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath + + abbreviatedAbsoluteLocationPath = '//' relativeLocationPath; + + +// [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step + + abbreviatedRelativeLocationPath = relativeLocationPath '//' step; + + +// [12] AbbreviatedStep ::= '.' | '..' + + abbreviatedStep = '.' | '..'; + + +// [13] AbbreviatedAxisSpecifier ::= '@'? + + abbreviatedAxisSpecifier = '@'?; + + +// [14] Expr ::= OrExpr + + expr = orExpr; + + +// [15] PrimaryExpr ::= VariableReference | '(' Expr ')' | Literal | Number | FunctionCall + + primaryExpr = variableReference | '(' expr ')' | literal | Num | functionCall; + + + +// [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' + + functionCall ::= functionName '(' (argument (',' argument)* )? ')'; + + +// [17] Argument ::= Expr + + argument = expr; + + +// [18] UnionExpr ::= PathExpr | UnionExpr '|' PathExpr +// avoiding Left recursion + + unionExpr = pathExpr ('|' pathExpr)*; + + +// [19] PathExpr ::= LocationPath +// | FilterExpr +// | FilterExpr '/' RelativeLocationPath +// | FilterExpr '//' RelativeLocationPath + + pathExpr = locationPath | filterExpr (('/'| '//') relativeLocationPath)?; + + +// [20] FilterExpr ::= PrimaryExpr | FilterExpr Predicate +// avoiding Left recursion ?? + + filterExpr = primaryExpr predicate? + + +// [21] OrExpr ::= AndExpr | OrExpr 'or' AndExpr +// avoiding Left recursion + + orExpr = andExpr ('or' andExpr)*; + + +// [22] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr +// avoiding Left recursion + + andExpr = equalityExpr ('and' equalityExpr)*; + + +// [23] EqualityExpr ::= RelationalExpr | EqualityExpr '=' RelationalExpr | EqualityExpr '!=' RelationalExpr +// avoiding Left recursion + + equalityExpr = relationalExpr (('='|'!=') relationalExpr)?; + // TODO repetition or alternation? + + +// [24] RelationalExpr ::= AdditiveExpr +// | RelationalExpr '<' AdditiveExpr +// | RelationalExpr '>' AdditiveExpr +// | RelationalExpr '<=' AdditiveExpr +// | RelationalExpr '>=' AdditiveExpr +// avoiding Left recursion + + relationalExpr = additiveExpr ('<' additiveExpr | '>' additiveExpr | '<=' additiveExpr | '>=' additiveExpr)?; + + +// [25] AdditiveExpr ::= MultiplicativeExpr +// | AdditiveExpr '+' MultiplicativeExpr +// | AdditiveExpr '-' MultiplicativeExpr +// avoiding Left recursion + + additiveExpr = multiplicativeExpr ('+' multiplicativeExpr | '-' multiplicativeExpr)?; + + +// [26] MultiplicativeExpr ::= UnaryExpr +// | MultiplicativeExpr MultiplyOperator UnaryExpr +// | MultiplicativeExpr 'div' UnaryExpr +// | MultiplicativeExpr 'mod' UnaryExpr +// avoiding Left recursion + + multiplicativeExpr = unaryExpr (multiplyOperator unaryExpr | 'div' unaryExpr | 'mod' unaryExpr)?; + + +// [27] UnaryExpr ::= UnionExpr | '-' UnaryExpr +// avoiding Left recursion + + unaryExpr = '-'? unionExpr; + + +// [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' +// | NameTest +// | NodeType +// | Operator +// | FunctionName +// | AxisName +// | Literal +// | Number +// | VariableReference + + exprToken = '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' + | nameTest + | nodeType + | operator + | functionName + | axisName + | literal + | number + | variableReference; + + +// [32] Operator ::= OperatorName | MultiplyOperator | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' + + operator = operatorName | multiplyOperator | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>='; + + +// [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div' + + operatorName = 'and' | 'or' | 'mod' | 'div'; + + +// [34] MultiplyOperator ::= '*' + + multiplyOperator = '*'; + + +// [7] QName ::= PrefixedName| UnprefixedName +// [8] PrefixedName ::= Prefix ':' LocalPart +// [9] UnprefixedName ::= LocalPart +// [10] Prefix ::= NCName + + prefix = /[^:]+/; + + +// [11] LocalPart ::= NCName + + localPart = /[^:]+/; + + +// [35] FunctionName ::= QName - NodeType + +// [36] VariableReference ::= '$' QName + + +// [37] NameTest ::= '*' | NCName ':' '*' | QName + + +// [38] NodeType ::= 'comment' +// | 'text' +// | 'processing-instruction' +// | 'node' diff --git a/res/.svn/tmp/tempfile.3.tmp b/res/.svn/tmp/tempfile.3.tmp new file mode 100644 index 0000000..28a825e --- /dev/null +++ b/res/.svn/tmp/tempfile.3.tmp @@ -0,0 +1,266 @@ +/* + An XPath 1.0 grammar derived from the XPath 1.0 Specification: + + http://www.w3.org/TR/xpath + +*/ + +@start = expr; + +@symbols = '//' '..' '!=' '::' '<=' '>='; + +@wordState = '_'; +@wordChars = '_' '.' ':' '-'; + +name = Word; + +ncName = name & /[^:]+/; + + + +// [1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath + + locationPath = relativeLocationPath | absoluteLocationPath; + + + +// [2] AbsoluteLocationPath ::= '/' RelativeLocationPath? | AbbreviatedAbsoluteLocationPath + + absoluteLocationPath = '/' relativeLocationPath? | abbreviatedAbsoluteLocationPath; + + +// [3] RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | AbbreviatedRelativeLocationPath +// avoiding left recursion + + // avoiding infinite loop + relativeLocationPath = step slashStep*; // | abbreviatedRelativeLocationPath; + + +// [4] Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep + + step = axisSpecifier nodeTest predicate* | abbreviatedStep; + + +// [5] AxisSpecifier ::= AxisName '::' | AbbreviatedAxisSpecifier + + axisSpecifier = axisName '::' | abbreviatedAxisSpecifier; + + +// [6] AxisName ::= 'ancestor' | 'ancestor-or-self' | 'attribute' | 'child' | 'descendant' | 'descendant-or-self' +// | 'following' | 'following-sibling' | 'namespace' | 'parent' | 'preceding' | 'preceding-sibling' | 'self' + + axisName = 'ancestor' | 'ancestor-or-self' | 'attribute' | 'child' | 'descendant' | 'descendant-or-self' + | 'following' | 'following-sibling' | 'namespace' | 'parent' | 'preceding' | 'preceding-sibling' | 'self'; + + +// [7] NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' + + nodeTest = nameTest | nodeType '(' ')' | 'processing-instruction' '(' literal ')'; + + +// [8] Predicate ::= '[' PredicateExpr ']' + + predicate = '[' predicateExpr ']'; + + +// [9] PredicateExpr ::= Expr + + predicateExpr = expr; + + +// [10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath + + abbreviatedAbsoluteLocationPath = '//' relativeLocationPath; + + +// [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step + + abbreviatedRelativeLocationPath = relativeLocationPath '//' step; + + +// [12] AbbreviatedStep ::= '.' | '..' + + abbreviatedStep = '.' | '..'; + + +// [13] AbbreviatedAxisSpecifier ::= '@'? + + abbreviatedAxisSpecifier = '@'?; + + +// [14] Expr ::= OrExpr + + expr = orExpr; + + +// [15] PrimaryExpr ::= VariableReference | '(' Expr ')' | Literal | Number | FunctionCall + + primaryExpr = variableReference | '(' expr ')' | literal | Num | functionCall; + literal = QuotedString; + variableReference = '$' Word; + +// [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' + + functionCall = functionName '(' (argument (',' argument)* )? ')'; + + +// [17] Argument ::= Expr + + argument = expr; + + +// [18] UnionExpr ::= PathExpr | UnionExpr '|' PathExpr +// avoiding Left recursion + + unionExpr = pathExpr ('|' pathExpr)*; + + +// [19] PathExpr ::= LocationPath +// | FilterExpr +// | FilterExpr '/' RelativeLocationPath +// | FilterExpr '//' RelativeLocationPath + + pathExpr = locationPath | filterExpr (('/'| '//') relativeLocationPath)?; + + +// [20] FilterExpr ::= PrimaryExpr | FilterExpr Predicate +// avoiding Left recursion ?? + + filterExpr = primaryExpr predicate?; + + +// [21] OrExpr ::= AndExpr | OrExpr 'or' AndExpr +// avoiding Left recursion + + orExpr = andExpr ('or' andExpr)*; + + +// [22] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr +// avoiding Left recursion + + andExpr = equalityExpr ('and' equalityExpr)*; + + +// [23] EqualityExpr ::= RelationalExpr | EqualityExpr '=' RelationalExpr | EqualityExpr '!=' RelationalExpr +// avoiding Left recursion + + equalityExpr = relationalExpr (('=' | '!=') relationalExpr)*; + + +// [24] RelationalExpr ::= AdditiveExpr +// | RelationalExpr '<' AdditiveExpr +// | RelationalExpr '>' AdditiveExpr +// | RelationalExpr '<=' AdditiveExpr +// | RelationalExpr '>=' AdditiveExpr +// avoiding Left recursion + + relationalExpr = additiveExpr (('<' | '>' | '<=' | '>=') additiveExpr)*; + + +// [25] AdditiveExpr ::= MultiplicativeExpr +// | AdditiveExpr '+' MultiplicativeExpr +// | AdditiveExpr '-' MultiplicativeExpr +// avoiding Left recursion + + additiveExpr = multiplicativeExpr (('+' | '-') multiplicativeExpr)*; + + +// [26] MultiplicativeExpr ::= UnaryExpr +// | MultiplicativeExpr MultiplyOperator UnaryExpr +// | MultiplicativeExpr 'div' UnaryExpr +// | MultiplicativeExpr 'mod' UnaryExpr +// avoiding Left recursion + + multiplicativeExpr = unaryExpr ((multiplyOperator | 'div' | 'mod') unaryExpr)*; + + +// [27] UnaryExpr ::= UnionExpr | '-' UnaryExpr +// avoiding Left recursion + + unaryExpr = '-'? unionExpr; + + +// [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' +// | NameTest +// | NodeType +// | Operator +// | FunctionName +// | AxisName +// | Literal +// | Number +// | VariableReference + +// exprToken = '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' +// | nameTest +// | nodeType +// | operator +// | functionName +// | axisName +// | literal +// | number +// | variableReference; + + +// [32] Operator ::= OperatorName | MultiplyOperator | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' + +// operator = operatorName | multiplyOperator | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>='; + + +// [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div' + +// operatorName = 'and' | 'or' | 'mod' | 'div'; + + +// [34] MultiplyOperator ::= '*' + + multiplyOperator = '*'; + + +// [7] QName ::= PrefixedName | UnprefixedName + + qName = prefixedName | unprefixedName; + + +// [8] PrefixedName ::= Prefix ':' LocalPart + + prefixedName = prefix ':' locaPart; + + +// [9] UnprefixedName ::= LocalPart + + unprefixedName = localPart; + + +// [10] Prefix ::= NCName + + prefix = ncName; + + +// [11] LocalPart ::= NCName + + localPart = ncName; + + +// [35] FunctionName ::= QName - NodeType + + functionName = qName - nodeType; + + +// [36] VariableReference ::= '$' QName + + variableReferece = '$' qName; + + +// [37] NameTest ::= '*' | NCName ':' '*' | QName + + nameTest = '*' | ncName ':' '*' | qName; + + +// [38] NodeType ::= 'comment' +// | 'text' +// | 'processing-instruction' +// | 'node' + + nodeType = 'comment' | 'text' | 'processing-instruction' | 'node'; + + \ No newline at end of file diff --git a/res/.svn/tmp/tempfile.tmp b/res/.svn/tmp/tempfile.tmp new file mode 100644 index 0000000..f90921a --- /dev/null +++ b/res/.svn/tmp/tempfile.tmp @@ -0,0 +1,108 @@ +""" +A Grammar for Apple's NSPredicate String Format Syntax + +See: http://developer.apple.com/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html + +""" + +@wordState = '#'; +@wordChars = '.' '[' ']'; + +@symbols = '==' '>=' '=>' '<=' '=<' '!=' '<>' '&&' '||'; + +@start = expr; + +# Expressions + expr = orTerm orOrTerm*; + orOrTerm = or orTerm; + orTerm = andTerm andAndTerm*; + andAndTerm = and andTerm; + andTerm = primaryExpr | compoundExpr; + compoundExpr = '('.discard expr ')'.discard; + primaryExpr = predicate | negatedPredicate; + negatedPredicate = not predicate; + + predicate = aggregateOp? actualPredicate; + actualPredicate = boolPredicate | comparisonPredicate | stringTestPredicate | collectionTestPredicate; + + +# values + value = keyPath | string | num | bool | array; + + string = QuotedString; + num = Num; + bool = true | false; + true = 'true'.discard; + false = 'false'.discard; + +# arrays + array = '{' arrayContentsOpt '}'.discard; + arrayContentsOpt = Empty | arrayContents; + arrayContents = value commaValue*; + commaValue = ','.discard value; + + +# keyPaths + keyPath = Word; + +# keyPath = key dotKey*; +# key = name memberAccess?; +# name = Word; +# dotKey = '.' key; +# memberAccess = '[' (num | 'FIRST' | 'LAST' | 'SIZE') ']'; + + +# Comparison Tests + comparisonPredicate = comparisonValue comparisonOp comparisonValue; + comparisonValue = keyPath | num; + + comparisonOp = eq | gt | lt | gtEq | ltEq | notEq | between; + + eq = '=' | '=='; + gt = '>'; + lt = '<'; + gtEq = '>=' | '=>'; + ltEq = '<=' | '=<'; + notEq = '!=' | '<>'; + between = 'BETWEEN'; + +# Boolean Value Predicates + boolPredicate = truePredicate | falsePredicate; + + truePredicate = 'TRUEPREDICATE'.discard; + falsePredicate = 'FALSEPREDICATE'.discard; + + + +# Compound Expressions + and = 'AND'.discard | '&&'.discard; + or = 'OR'.discard | '||'.discard; + not = 'NOT'.discard | '!'.discard; + + + +# String Tests + stringTestPredicate = string stringTestOp value; + + stringTestOp = beginswith | contains | endswith | like | matches; + + beginswith = 'BEGINSWITH'; + contains = 'CONTAINS'; + endswith = 'ENDSWITH'; + like = 'LIKE'; + matches = 'MATCHES'; + + +# Collection Tests + collectionTestPredicate = value in collection; + collection = keyPath | array; + in = 'IN'.discard; + + +# Aggregate Operators + aggregateOp = any | some | all | none; + any = 'ANY'; + some = 'SOME'; + all = 'ALL'; + none = 'NONE'; + diff --git a/res/SRGSGrammar.txt b/res/SRGSGrammar.txt new file mode 100644 index 0000000..d894c82 --- /dev/null +++ b/res/SRGSGrammar.txt @@ -0,0 +1,218 @@ +selfIdentHeader ::= + '#ABNF' #x20 VersionNumber (#x20 CharEncoding)? ';' + [Additional constraints: + - The semicolon (';') must immediately be followed + by an end-of-line. + ] + +VersionNumber ::= + '1.0' + +CharEncoding ::= + Nmtoken + +BaseURI ::= + ABNF_URI + +LanguageCode ::= + Nmtoken + [Additional constraints: + - The language code must be a valid language identifier. + ] + +RuleName ::= + '$' ConstrainedName + +ConstrainedName ::= + Name - (Char* ('.' | ':' | '-') Char*) + +TagFormat ::= + ABNF_URI + +LexiconURI ::= + ABNF_URI | ABNF_URI_with_Media_Type + +SingleQuotedCharacters ::= + ''' [^']* ''' + +DoubleQuotedCharacters ::= + '"' [^"]* '"' + +QuotedCharacters ::= + SingleQuotedCharacters | DoubleQuotedCharacters + +Weight ::= + '/' Number '/' + + +Repeat ::= + [0-9]+ ('-' [0-9]*)? + [Additional constraints: + - A number to the right of the hyphen must not be + greater than the number to the left of the hyphen. + ] + + +Probability ::= + '/' Number '/' + [Additional constraints: + - The float value must be in the range of "0.0" + to "1.0" (inclusive). + ] + +Number ::= + [0-9]+ | [0-9]+ '.' [0-9]* | [0-9]* '.' [0-9]+ + +ExternalRuleRef ::= + '$' ABNF_URI | '$' ABNF_URI_with_Media_Type + [Additional constraints: + - The referenced grammar must have the same mode + ("voice" or "dtmf") as the referencing grammar. + - If the URI reference contains a fragment + identifier, the referenced rule must be a + public rule of another grammar. + - If the URI reference does not contain a fragment + identifier, i.e. if it is an implicit root rule reference, + then the referenced grammar must declare a root + rule. + ] + +Token ::= + Nmtoken | DoubleQuotedCharacters + +LanguageAttachment ::= + '!' LanguageCode + +Tag ::= + '{' [^}]* '}' + | '{!{' (Char* - (Char* '}!}' Char*)) '}!}' + +------------------------------------------------------------ + +ABNF_URI + and ABNF_URI_with_Media_Type + are defined +in Section 1.6 Terminology. + +Name is defined by the XML Name production [XML §2.3]. + +Nmtoken is defined by the XML Nmtoken production [XML §2.3]. + +NameChar is defined by the XML NameChar production [XML §2.3]. + +Char is defined by the XML Char production [XML §2.2]. + + + + + + + + + + + + + +grammar ::= + selfIdentHeader declaration* ruleDefinition* + +declaration ::= + baseDecl | languageDecl | modeDecl | rootRuleDecl + | tagFormatDecl | lexiconDecl | metaDecl | tagDecl + +baseDecl ::= + 'base' BaseURI ';' + [Additional constraints: + - A base declaration must not appear more than + once in grammar. + ] + +languageDecl ::= + 'language' LanguageCode ';' + [Additional constraints: + - A language declaration must not appear more than + once in grammar. + - A language declaration is required if the + grammar mode is "voice". + ] + +modeDecl ::= + 'mode' 'voice' ';' | 'mode' 'dtmf' ';' + [Additional constraints: + - A mode declaration must not appear more than + once in grammar. + ] + +rootRuleDecl ::= + 'root' RuleName ';' + [Additional constraints: + - A root rule declaration must not appear more + than once in grammar. + - The root rule must be a rule that is defined + within the grammar. + ] + +tagFormatDecl ::= + 'tag-format' TagFormat ';' + [Additional constraints: + - A tag-format declaration must not appear more + than once in grammar. + ] + +lexiconDecl ::= + 'lexicon' LexiconURI ';' + +metaDecl ::= + 'http-equiv' QuotedCharacters 'is' QuotedCharacters ';' + | 'meta' QuotedCharacters 'is' QuotedCharacters ';' + + +tagDecl ::= + Tag ';' + + +ruleDefinition ::= + scope? RuleName '=' ruleExpansion ';' + [Additional constraints: + - The rule name must be unique within a grammar, + i.e. no rule must be defined more than once + within a grammar. + ] + +scope ::= + 'private' | 'public' + +ruleExpansion ::= + ruleAlternative ( '|' ruleAlternative )* + +ruleAlternative ::= + Weight? sequenceElement+ + +sequenceElement ::= + subexpansion | subexpansion repeatOperator + +subexpansion ::= + Token LanguageAttachment? + | ruleRef + | Tag + | '(' ')' + | '(' ruleExpansion ')' LanguageAttachment? + | '[' ruleExpansion ']' LanguageAttachment? + +ruleRef ::= + localRuleRef | ExternalRuleRef | specialRuleRef + +localRuleRef ::= + RuleName + [Additional constraints: + - The referenced rule must be defined within the + same grammar. + ] + +specialRuleRef ::= + '$NULL' | '$VOID' | '$GARBAGE' + + +repeatOperator ::= + '<' Repeat Probability? '>' \ No newline at end of file diff --git a/res/apple-boss.json b/res/apple-boss.json new file mode 100644 index 0000000..a082201 --- /dev/null +++ b/res/apple-boss.json @@ -0,0 +1,80 @@ +{"ysearchresponse": + {"responsecode":"200", + "nextpage":"\/ysearch\/web\/v1\/apple?appid=LcU4qWbV34HAOHTXXZbYfB1_AgYH5_AhlzYZ6Qvm4hdEDw6B1MicVEIYPtQLOTnb&format=json&start=10", + "totalhits":"50793319", + "deephits":"1510000000", + "count":"10", + "start":"0", + "resultset_web": + [{"abstract":"Macintosh hardware, software, and Internet tools. Offering Quicktime info, developer resources, and other items related to Apple<\/b> computers.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnNTdsamw3BGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzAEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=10qut2vvd\/**http%3A\/\/www.apple.com\/","date":"2008\/08\/12", + "dispurl":"www.apple.com<\/b>", + "size":"10765", + "title":"Apple<\/b>, Inc.", + "url":"http:\/\/www.apple.com\/"}, + {"abstract":"The official online store for iPods, Mac laptops and Macintosh computers, with free shipping over $50. Also featuring software such as Final Cut and Office 2008 for Mac.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnaTZsYjRpBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzEEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=1fufchaio\/**http%3A\/\/rdrw1.yahoo.com\/click%3Fu=http%3A\/\/feedpoint.net\/r\/redir.jsp%253Fengine%253DINK%2526pcid%253D597997%2526fid%253D-2%2526url%253Dhttp%3A\/\/store.apple.com\/1-800-MY-APPLE\/WebObjects\/AppleStore%253Faosid%253Dp210%2526cid%253DOAS-US-YPI%2526src%253Dyssp%26y=04C664CB0EAC6A0CE6%26i=1473%26c=59131%26q=02%255ESSHPM%255BL7~oosz6%26e=utf-8%26r=1%26d=wow~LcU4qWbV34HAOHTXXZbYfB1_AgYH5_AhlzYZ6Qvm4hdEDw6B1MicVEIYPtQLOTnb-en-us%26n=LN94K1HIB6HKGRUL%26s=1%26t=%26m=48A3A234%26x=051726E3806650ACD5A44E8C8BD13ADACC", + "date":"2008\/08\/13", + "dispurl":"store.apple.com<\/b>", + "size":"49418", + "title":"Mac Laptops, iPods and Macintosh Computers | Apple<\/b> Online Store", + "url":"http:\/\/store.apple.com\/"}, + {"abstract":"Encyclopedia article about the computer company, including history, product lines, and corporate affairs. ...<\/b> Apple's<\/b> software products include the Mac OS X ...<\/b>", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnNHB0OGduBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzIEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=11c328ll9\/**http%3A\/\/en.wikipedia.org\/wiki\/Apple_Inc.", + "date":"2008\/08\/10", + "dispurl":"en.wikipedia.org<\/b>\/wiki\/Apple<\/b>_Inc.", + "size":"285957", + "title":"Apple<\/b> Inc. - Wikipedia, the free encyclopedia", + "url":"http:\/\/en.wikipedia.org\/wiki\/Apple_Inc."}, + {"abstract":"Detailed overview of the apple's<\/b> origins, flavors, and health benefits.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnMmh1a3BkBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzMEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=117d3a7f6\/**http%3A\/\/en.wikipedia.org\/wiki\/Apple", + "date":"2008\/08\/11", + "dispurl":"en.wikipedia.org<\/b>\/wiki\/Apple<\/b>", + "size":"128319", + "title":"Apple<\/b> - Wikipedia", + "url":"http:\/\/en.wikipedia.org\/wiki\/Apple"}, + {"abstract":"Your complete guide to all things Macintosh. Get the latest reviews, news, videos, downloads, tips, and more for Mac laptops, desktops, and OS X 10.5 (Leopard)", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnNWR1czdzBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzQEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=117n1p7jv\/**http%3A\/\/www.cnet.com\/apple-mac.html", + "date":"2008\/08\/09", + "dispurl":"www.cnet.com<\/b>\/apple<\/b>-mac.html", + "size":"102719", + "title":"Apple<\/b> Mac: Mac OS, Mac laptop, Mac desktop - CNET.com", + "url":"http:\/\/www.cnet.com\/apple-mac.html"}, + {"abstract":"Watch Apple<\/b> CEO Steve Jobs unveil iPhone 3G, the App Store, MobileMe, and more ...<\/b> Copyright \u00a9 2008 Apple<\/b> Inc. All rights reserved. Terms of Use | Privacy Policy ...<\/b>", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnbjkwdjF0BGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzUEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=1272or2mo\/**http%3A\/\/events.apple.com.edgesuite.net\/0806wdt546x\/event\/index.html", + "date":"2008\/07\/16", + "dispurl":"events.apple.com.edgesuite.net<\/b>\/0806wdt546x\/event\/index.html", + "size":"17259", + "title":"Apple<\/b> - QuickTime - WWDC 2008 Keynote", + "url":"http:\/\/events.apple.com.edgesuite.net\/0806wdt546x\/event\/index.html"}, + {"abstract":"Apple's<\/b> GrayShare technology gives you the ability to print over 130 shades of ...<\/b> are part of the CSW 4000 Series Update 1.0 posted on Apple<\/b> Software Updates. ...<\/b>", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRndXBuYjJ1BGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzYEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=11r2bnul4\/**http%3A\/\/docs.info.apple.com\/article.html%3Fartnum=30153", + "date":"2004\/09\/20", + "dispurl":"docs.info.apple.com<\/b>\/article.html?artnum=30153", + "size":"37078", + "title":"StyleWriter Printers: Print Drivers and Cable Matrix", + "url":"http:\/\/docs.info.apple.com\/article.html?artnum=30153"}, + {"abstract":"8 Jumps Apple<\/b> releases firmware 2.0 for iPhone, iPod Touch ...<\/b> Apple<\/b> underestimated the load on their servers, which left many users stuck on ...<\/b>", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnY3I0MWFoBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzcEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=10pb88a2t\/**http%3A\/\/apple.qj.net\/", + "date":"2008\/07\/14", + "dispurl":"apple.qj.net<\/b>", + "size":"82416", + "title":"QJ.NET - QuickJump Home - Apple<\/b> News - QJ.NET", + "url":"http:\/\/apple.qj.net\/"}, + {"abstract":"Daily Apple<\/b> news updates, forums, reviews, and features.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnN2tqM2ZpBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzgEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=111js1asj\/**http%3A\/\/www.appleinsider.com\/", + "date":"2008\/08\/12", + "dispurl":"www.appleinsider.com<\/b>", + "size":"82410", + "title":"AppleInsider", + "url":"http:\/\/www.appleinsider.com\/"}, + {"abstract":"Offers threaded discussions related to news for Apple<\/b> users.", + "clickurl":"http:\/\/us.lrd.yahoo.com\/_ylc=X3oDMTRnaTlmZm5iBGFwcGlkA0xjVTRxV2JWMzRIQU9IVFhYWmJZZkIxX0FnWUg1X0FobHpZWjZRdm00aGRFRHc2QjFNaWNWRUlZUHRRTE9UbmIEcG9zAzkEc2VydmljZQNZU2VhcmNoV2ViBHNyY3B2aWQDa0Z2c25VTGFSV3o2WVEyZnBObGVyUURwWXMucUJVaWpvalFBQlJuZw--\/SIG=10vvqn6ao\/**http%3A\/\/apple.slashdot.org\/", + "date":"2008\/08\/13", + "dispurl":"apple.slashdot.org<\/b>", + "size":"43683", + "title":"apple<\/b>.slashdot.org", + "url":"http:\/\/apple.slashdot.org\/"} + ] + } +} \ No newline at end of file diff --git a/res/apple-boss.xml b/res/apple-boss.xml new file mode 100644 index 0000000..14a3187 --- /dev/null +++ b/res/apple-boss.xml @@ -0,0 +1,96 @@ + + + + + + Apple computers.]]> + + 2008/08/17 + apple.com]]> + 10765 + <![CDATA[<b>Apple</b>, Inc.]]> + http://www.apple.com/ + + + The official online store for iPods, Mac laptops and Macintosh computers, with free shipping over $50. Also featuring software such as Final Cut and Office 2008 for Mac. + + 2008/08/18 + store.apple.com]]> + 101744 + <![CDATA[Mac Laptops, iPods and Macintosh Computers | <b>Apple</b> Online Store]]> + http://store.apple.com/ + + + ... Apple's software products include the Mac OS X ...]]> + + 2008/08/10 + en.wikipedia.org/wiki/Apple_Inc.]]> + 285957 + <![CDATA[<b>Apple</b> Inc. - Wikipedia, the free encyclopedia]]> + http://en.wikipedia.org/wiki/Apple_Inc. + + + Apple's software products include the Mac OS X operating system, iTunes media ... Apple was established on April 1, 1976 by Steve Jobs, Steve Wozniak, and Ronald ...]]> + + 2008/08/18 + en.wikipedia.org/wiki/Apple_Computer]]> + 249715 + <![CDATA[<b>Apple</b> Inc. - Wikipedia, the free encyclopedia]]> + http://en.wikipedia.org/wiki/Apple_Computer + + + Your complete guide to all things Macintosh. Get the latest reviews, news, videos, downloads, tips, and more for Mac laptops, desktops, and OS X 10.5 (Leopard) + + 2008/08/18 + cnet.com/apple-mac.html]]> + 100558 + <![CDATA[<b>Apple</b> Mac: Mac OS, Mac laptop, Mac desktop - CNET.com]]> + http://www.cnet.com/apple-mac.html + + + Apple CEO Steve Jobs unveil iPhone 3G, the App Store, MobileMe, and more ... Copyright © 2008 Apple Inc. All rights reserved. Terms of Use | Privacy Policy ...]]> + + 2008/07/16 + events.apple.com.edgesuite.net/0806wdt546x/event/index.html]]> + 17259 + <![CDATA[<b>Apple</b> - QuickTime - WWDC 2008 Keynote]]> + http://events.apple.com.edgesuite.net/0806wdt546x/event/index.html + + + Apple's GrayShare technology gives you the ability to print over 130 shades of ... are part of the CSW 4000 Series Update 1.0 posted on Apple Software Updates. ...]]> + + 2004/09/20 + docs.info.apple.com/article.html?artnum=30153]]> + 37078 + StyleWriter Printers: Print Drivers and Cable Matrix + http://docs.info.apple.com/article.html?artnum=30153 + + + Apple releases firmware 2.0 for iPhone, iPod Touch ... Apple underestimated the load on their servers, which left many users stuck on ...]]> + + 2008/07/14 + apple.qj.net]]> + 82416 + <![CDATA[QJ.NET - QuickJump Home - <b>Apple</b> News - QJ.NET]]> + http://apple.qj.net/ + + + Apple users.]]> + + 2008/08/18 + apple.slashdot.org]]> + 44408 + <![CDATA[<b>apple</b>.slashdot.org]]> + http://apple.slashdot.org/ + + + Apple Authorized Training Centers offer Mac OS X and Pro Apps exams ... Publicize your certifications on Apple's website, and connect with clients and employers ...]]> + + 2008/07/25 + prometric.com/apple/default.htm]]> + 13318 + <![CDATA[Prometric: <b>Apple</b> Certification]]> + http://www.prometric.com/apple/default.htm + + + diff --git a/res/arithmetic.grammar b/res/arithmetic.grammar new file mode 100644 index 0000000..9b2e038 --- /dev/null +++ b/res/arithmetic.grammar @@ -0,0 +1,10 @@ +@start = expr; +expr = term (plusTerm | minusTerm)*; +term = factor (timesFactor | divFactor)*; +plusTerm = '+' term; +minusTerm = '-' term; +factor = phrase exponentFactor | phrase; +timesFactor = '*' factor; +divFactor = '/' factor; +exponentFactor = '^' factor; +phrase = '(' expr ')' | Number; diff --git a/res/c.grammar b/res/c.grammar new file mode 100644 index 0000000..03fa75f --- /dev/null +++ b/res/c.grammar @@ -0,0 +1,314 @@ + translation-unit: + external-declaration + translation-unit external-declaration + + external-declaration: + function-definition + declaration + + function-definition: + declaration-specifiersopt declarator declaration-listopt compound-statement + + declaration: + declaration-specifiers init-declarator-listopt; + + declaration-list: + declaration + declaration-list declaration + + declaration-specifiers: + storage-class-specifier declaration-specifiersopt + type-specifier declaration-specifiersopt + type-qualifier declaration-specifiersopt + + storage-class specifier: one of + auto register static extern typedef + + type specifier: one of + void char short int long float double signed + unsigned struct-or-union-specifier enum-specifier typedef-name + + type-qualifier: one of + const volatile + + struct-or-union-specifier: + struct-or-union identifieropt { struct-declaration-list } + struct-or-union identifier + + struct-or-union: one of + struct union + + struct-declaration-list: + struct declaration + struct-declaration-list struct declaration + + init-declarator-list: + init-declarator + init-declarator-list, init-declarator + + init-declarator: + declarator + declarator = initializer + + struct-declaration: + specifier-qualifier-list struct-declarator-list; + + specifier-qualifier-list: + type-specifier specifier-qualifier-listopt + type-qualifier specifier-qualifier-listopt + + struct-declarator-list: + struct-declarator + struct-declarator-list , struct-declarator + + struct-declarator: + declarator + declaratoropt : constant-expression + + enum-specifier: + enum identifieropt { enumerator-list } + enum identifier + + enumerator-list: + enumerator + enumerator-list , enumerator + + enumerator: + identifier + identifier = constant-expression + + declarator: + pointeropt direct-declarator + + direct-declarator: + identifier + (declarator) + direct-declarator [ constant-expressionopt ] + direct-declarator ( parameter-type-list ) + direct-declarator ( identifier-listopt ) + + pointer: + * type-qualifier-listopt + * type-qualifier-listopt pointer + + type-qualifier-list: + type-qualifier + type-qualifier-list type-qualifier + + parameter-type-list: + parameter-list + parameter-list , ... + + parameter-list: + parameter-declaration + parameter-list , parameter-declaration + + parameter-declaration: + declaration-specifiers declarator + declaration-specifiers abstract-declaratoropt + + identifier-list: + identifier + identifier-list , identifier + + initializer: + assignment-expression + { initializer-list } + { initializer-list , } + + initializer-list: + initializer + initializer-list , initializer + + type-name: + specifier-qualifier-list abstract-declaratoropt + + abstract-declarator: + pointer + pointeropt direct-abstract-declarator + + direct-abstract-declarator: + ( abstract-declarator ) + direct-abstract-declaratoropt [constant-expressionopt] + direct-abstract-declaratoropt (parameter-type-listopt) + + typedef-name: + identifier + + statement: + labeled-statement + expression-statement + compound-statement + selection-statement + iteration-statement + jump-statement + + labeled-statement: + identifier : statement + case constant-expression : statement + default : statement + + expression-statement: + expressionopt; + + compound-statement: + { declaration-listopt statement-listopt } + + statement-list: + statement + statement-list statement + + selection-statement: + if (expression) statement + if (expression) statement else statement + switch (expression) statement + + iteration-statement: + while (expression) statement + do statement while (expression); + for (expressionopt; expressionopt; expressionopt) statement + + jump-statement: + goto identifier; + continue; + break; + return expressionopt; + + expression: + assignment-expression + expression , assignment-expression + + assignment-expression: + conditional-expression + unary-expression assignment-operator assignment-expression + + assignment-operator: one of + = *= /= %= += -= <<= >>= &= ^= |= + + conditional-expression: + logical-OR-expression + logical-OR-expression ? expression : conditional-expression + + constant-expression: + conditional-expression + + logical-OR-expression: + logical-AND-expression + logical-OR-expression || logical-AND-expression + + logical-AND-expression: + inclusive-OR-expression + logical-AND-expression && inclusive-OR-expression + + inclusive-OR-expression: + exclusive-OR-expression + inclusive-OR-expression | exclusive-OR-expression + + exclusive-OR-expression: + AND-expression + exclusive-OR-expression ^ AND-expression + + AND-expression: + equality-expression + AND-expression & equality-expression + + equality-expression: + relational-expression + equality-expression == relational-expression + equality-expression != relational-expression + + relational-expression: + shift-expression + relational-expression < shift-expression + relational-expression > shift-expression + relational-expression <= shift-expression + relational-expression >= shift-expression + + shift-expression: + additive-expression + shift-expression << additive-expression + shift-expression >> additive-expression + + additive-expression: + multiplicative-expression + additive-expression + multiplicative-expression + additive-expression - multiplicative-expression + + multiplicative-expression: + multiplicative-expression * cast-expression + multiplicative-expression / cast-expression + multiplicative-expression % cast-expression + + cast-expression: + unary expression + (type-name) cast-expression + + unary-expression: + postfix expression + ++unary expression + --unary expression + unary-operator cast-expression + sizeof unary-expression + sizeof (type-name) + + unary operator: one of + & * + - ~ ! + + postfix-expression: + primary-expression + postfix-expression[expression] + postfix-expression(argument-expression-listopt) + postfix-expression.identifier + postfix-expression->+identifier + postfix-expression++ + postfix-expression-- + primary-expression: + identifier + constant + string + (expression) + + argument-expression-list: + assignment-expression + assignment-expression-list , assignment-expression + + constant: + integer-constant + character-constant + floating-constant + enumeration-constant + +# The following grammar for the preprocessor summarizes the structure of control lines, but is not suitable for mechanized parsing. It includes the symbol text, which means ordinary program text, non-conditional preprocessor control lines, or complete preprocessor conditional instructions. + + control-line: + # define identifier token-sequence + # define identifier(identifier, ... , identifier) token-sequence + # undef identifier + # include + # include "filename" + # line constant "filename" + # line constant + # error token-sequenceopt + # pragma token-sequenceopt + # + preprocessor-conditional + + preprocessor-conditional: + if-line text elif-parts else-partopt #endif + + if-line: + # if constant-expression + # ifdef identifier + # ifndef identifier + + elif-parts: + elif-line text + elif-partsopt + + elif-line: + # elif constant-expression + + else-part: + else-line text + else-line: + #else \ No newline at end of file diff --git a/res/css.css b/res/css.css new file mode 100644 index 0000000..0c139b9 --- /dev/null +++ b/res/css.css @@ -0,0 +1,71 @@ +openCurly, +closeCurly, +openBracket, +closeBracket, +eq, +comma, +colon, +semi, +openParen, +closeParen, +gt, +tilde, +pipe, +fwdSlash, +hash, +dot { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +selectorWord { + color:rgb(255, 255, 255); + background-color:rgb(20, 20, 26); + font-family:'Georgia'; + font-size:15px; +} + +selectorQuotedString { + color:rgb(196.35, 45.9, 51.0); + background-color:rgb(20, 20, 26); + font-family:'Georgia'; + font-size:15px; +} + +constant, string, semi { + color:rgb(196.35, 45.9, 51.0); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +property { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +num { + color:rgb(22.95, 158.1, 188.7); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +//text { +// color:rgb(61.2, 178.5, 68.85); +// background-color:rgb(30, 30, 36); +// font-family:'Monaco'; +// font-size:11px; +//} + +word { + color:rgb(255, 255, 255); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + diff --git a/res/css.grammar b/res/css.grammar new file mode 100644 index 0000000..e414a53 --- /dev/null +++ b/res/css.grammar @@ -0,0 +1,44 @@ +/** + A Grammar for CSS + + This grammar is intentionally lenient/forgiving. + The purpose is to highlight, not validate (possibly invalid) CSS. + +*/ + +@multiLineComments = '/*' '*/'; +@wordState = '-'; + +@start = ruleset*; +ruleset = selectors openCurly decls closeCurly; +selectors = selector commaSelector*; +selector = (selectorWord | hash | dot |colon | gt | openBracket | closeBracket | eq | selectorQuotedString | tilde | pipe)+; +selectorWord = Word; +selectorQuotedString = QuotedString; +commaSelector = comma selector; +decls = Empty | actualDecls; +actualDecls = decl decl*; +decl = property colon expr semi; +property = Word; +expr = (string | constant | num | openParen | closeParen | comma | fwdSlash)+; +string = QuotedString; +constant = Word; + +openCurly = '{'; +closeCurly = '}'; +openBracket = '['; +closeBracket = ']'; +eq = '='; +comma = ','; +colon = ':'; +semi = ';'; +openParen = '('; +closeParen = ')'; +gt = '>'; +tilde = '~'; +pipe = '|'; +fwdSlash = '/'; +hash = '#'; +dot = '.'; + +num = Number; \ No newline at end of file diff --git a/res/css2_1.grammar b/res/css2_1.grammar new file mode 100644 index 0000000..7e412ca --- /dev/null +++ b/res/css2_1.grammar @@ -0,0 +1,203 @@ +/* + This is an attempt to convert the official CSS 2.1 grammar to TDParseKit +*/ + + +@start = stylesheet; + +// stylesheet +// : [ CHARSET_SYM S* STRING S* ';' ]? +// [S|CDO|CDC]* [ import [S|CDO|CDC]* ]* +// [ [ ruleset | media | page | font_face ] [S|CDO|CDC]* ]* +// ; +charsetSymbol = '@' 'charset'; +charset = (charsetSymbol Word ';'); +stylesheet = charset? import* contents; +contents = (ruleset | media | page | fontFace)*; +stuff = (cdo|cdc)*; + + +// import +// : IMPORT_SYM S* +// [STRING|URI] S* [ medium [ ',' S* medium]* ]? ';' S* +// ; +mediaList = medium commaMedium*; +commaMedium = ',' medium; +importSymbol = '@' 'import'; +import = importSymbol (Word | uri) mediaList? ';'; + + +// media +// : MEDIA_SYM S* medium [ ',' S* medium ]* '{' S* ruleset* '}' S* +// ; + +mediaSymbol = '@' 'media'; +media = mediaSymbol mediaList '{' ruleset* '}'; + + + +// medium +// : IDENT S* +// ; +medium = identifier; + + + +// page +// : PAGE_SYM S* IDENT? pseudo_page? S* +// '{' S* declaration [ ';' S* declaration ]* '}' S* +// ; +pageSymbol = '@' 'page'; +page = pagePrefix pageBody; +pagePrefix = pageSymbol identifier? pseudoPage?; +pageBody = '{' decl decl* '}'; + + +// pseudo_page +// : ':' IDENT +// ; +pseudoPage = ':' identifier; + + +// font_face +// : FONT_FACE_SYM S* +// '{' S* declaration [ ';' S* declaration ]* '}' S* +// ; +fontFaceSymbol = '@' fontFace; +fontFace = fontFaceSymbol '{' decl decl* '}'; + + +// operator +// : '/' S* | ',' S* | /* empty * / +// ; +operator = '/' | ',' | Empty; + + + +// combinator +// : '+' S* | '>' S* | /* empty * / +// ; +combinator = '+' | '>' | Empty; + + + +// unary_operator +// : '-' | '+' +// ; +unaryOperator = '-' | '+'; + + +// property +// : IDENT S* +// ; +property = identifier; + + +// ruleset +// : selector [ ',' S* selector ]* +// '{' S* declaration [ ';' S* declaration ]* '}' S* +// ; +ruleset = selector commaSelector* '{' decl decl* '}'; +commaSelector = ',' selector; + + +// selector +// : simple_selector [ combinator simple_selector ]* +// ; +selector = simpleSelector (combinator simpleSelector)*; + + +// simple_selector +// : element_name? [ HASH | class | attrib | pseudo ]* S* +// ; +simpleSelector = elementName? (hash | class | attrib | pseudo)*; + + +// class +// : '.' IDENT +// ; +class = '.' identifier; + + +// element_name +// : IDENT | '*' +// ; +elementName = identifier | '*'; + + +// attrib +// : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* +// [ IDENT | STRING ] S* ]? ']' +// ; +attrib = '[' identifier (('=' | includes | dashmatch) (identifier | Word))? ']'; + + +// pseudo +// : ':' [ IDENT | FUNCTION S* IDENT S* ')' ] +// ; +pseudo = ':' identifier | function identifier ')'; + + +// declaration +// : property ':' S* expr prio? +// | /* empty * / +// ; +decl = (property ':' expr prio?) | Empty; + + +// prio +// : IMPORTANT_SYM S* +// ; +prio = '!' 'important'; + + +// expr +// : term [ operator term ]* +// ; +expr = term (operator term)*; + + +// term +// : unary_operator? +// [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* | +// TIME S* | FREQ S* | function ] +// | STRING S* | IDENT S* | URI S* | RGB S* | UNICODERANGE S* | hexcolor +// ; +term = unaryOperator? (Number | percentage | length | ems | exs | angle | time | freq | function) + | Word | identifier | uri | hexcolor; + + +// function +// : FUNCTION S* expr ')' S* +// ; +function = XXX expr ')'; + + +// * +// * There is a constraint on the color that it must +// * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) +// * after the "#"; e.g., "#000" is OK, but "#abcd" is not. +// * +// hexcolor +// : HASH S* +// ; +hexcolor = hash; + +cdo = ''; +includes = '~='; +dashmatch = '|='; + +identifier = Word; + +hash = '#' (Word|Number); +ems = Number 'em'; +exs = Number 'ex'; +length = Number ('px'|'cm'|'mm'|'in'|'pt'|'pc'); +angle = Number ('deg'|'rad'|'grad'); +time = Number ('s'|'ms'); +freq = Number ('hz'|'khz'); +dimension = Number identifier; +percentage = Number '%'; +uri = 'url' '(' (Word|Symbol|Number)+ ')'; +function = identifier '('; diff --git a/res/date.grammar b/res/date.grammar new file mode 100644 index 0000000..b1084a9 --- /dev/null +++ b/res/date.grammar @@ -0,0 +1,40 @@ +/* + + TDParseKit Grammar Syntax now supports regular expressions (powered by RegExKit Lite) + + So, as a trivial (and useless) example, the following TDPK grammar + specifies a tiny language which allows dates in the format of: + + 2009-06-21 + +*/ + +@start = date; // the 'date' production is the outermost production in this grammar + +date = /\d{4}/ '-' /\d{2}/ '-' /\d{2}/; // will match any sequence of tokens whose `stringValue` property matches these regexes + // separated by two '-' chars + + + + + + + + +/* +NOTE: +An equivalent grammar could be expressed in many ways. Here's an equivalent grammar with explicit ObjC assembler callbacks added: + + +@start = year dash month dash day; + +dash = '-'; + +year (matchedYear:) = /\d{4}/; // when matched, your specified `assembler` object (think delegate) will receive a + // callback to it's `-matchedYear:` method with a `PKAssembly` argument. + // the token matched by the regex will on the top of the assebly's stack ready for you + +month (matchedMonth:) = /\d{2}/; +day (matchedDay:) = /\d{2}/; + +*/ \ No newline at end of file diff --git a/res/erb.grammar b/res/erb.grammar new file mode 100644 index 0000000..a8ff87a --- /dev/null +++ b/res/erb.grammar @@ -0,0 +1,15 @@ +@symbols = '<@' '<@=' '@>'; + +@start = (ignored | importantStuff)*; +ignored = ~startMarker; + +importantStuff = print | eval; +print = printStartMarker keyPath endMarker; +eval = evalStartMarker keyPath endMarker; + +keyPath = Word dotWord*; +dotWord = ('.' Word); + +printStartMarker = '<@='; +evalStartMarker = '<@'; +endMarker = '@>'; \ No newline at end of file diff --git a/res/example.css b/res/example.css new file mode 100644 index 0000000..790775a --- /dev/null +++ b/res/example.css @@ -0,0 +1,54 @@ +.openCurly > closeCurly, +#comma[foo], +colon[foo=bar] bat, +openParen[foo="bar"], +closeParen, +name:psuedo-name, +foo[bar|=baz] +px, +px, +rgb { + -webkit-border-radius:12px; + color: rgb(178.5, 35.7, 135.15); + background-color: rgb(30, 30, 36); + font-family: 'Monaco'; + font-size: 11 em; + font-weight: bold; +} + +body { + font:14px/1.4 "Lucida Grande", LucidaGrande, Verdana, Helvetica, Arial; +} + +#content { + position:relative; + width:650px; + margin:20px auto; +} + +#icon { + float:left; + margin-right:15px; +} + +h1 { + padding-top:15px; + font-size:48px; +} + +#desc { + position:absolute; + left:170px; top:75px; +} + +#screenshot { + display:block; + width:500px; + margin:80px auto 35px; + border:1px solid silver; +} + +#copyright, #credits, #hostedby { + font-size:small; + text-align:center; +} diff --git a/res/example.html b/res/example.html new file mode 100644 index 0000000..beb23a0 --- /dev/null +++ b/res/example.html @@ -0,0 +1,28 @@ + + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + + CFBundleName + ${PRODUCT_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.parsekit.ParseKit + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.4 + NSPrincipalClass + + + \ No newline at end of file diff --git a/res/example1.srgs b/res/example1.srgs new file mode 100644 index 0000000..2549db4 --- /dev/null +++ b/res/example1.srgs @@ -0,0 +1,24 @@ +#ABNF 1.0 ISO-8859-1; + +// Default grammar language is US English +language en-US; + +// Single language attachment to tokens +// Note that "fr-CA" (Canadian French) is applied to only +// the word "oui" because of precedence rules +$yes = yes | oui!fr-CA; + +// Single language attachment to an expansion +$people1 = (Michel Tremblay | André Roy)!fr-CA; + +// Handling language-specific pronunciations of the same word +// A capable speech recognizer will listen for Mexican Spanish and +// US English pronunciations. +$people2 = Jose!en-US | Jose!es-MX; + +/** + * Multi-lingual input possible + * @example may I speak to André Roy + * @example may I speak to Jose + */ +public $request = may I speak to ($people1 | $people2); \ No newline at end of file diff --git a/res/html.css b/res/html.css new file mode 100644 index 0000000..43d3ba0 --- /dev/null +++ b/res/html.css @@ -0,0 +1,63 @@ +lt, gt, fwdSlash, endTagStart, eq { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +eq { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +tagName { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +attrValue { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +attrName { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(20, 20, 26); + font-family:'Monaco'; + font-size:11px; +} + +text { +// color:rgb(61.2, 178.5, 68.85); + color:rgb(255, 255, 255); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +comment { + color:rgb(61.2, 178.5, 68.85); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +pi { + color:rgb(22.95, 158.1, 188.7); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +doctype { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} \ No newline at end of file diff --git a/res/html.grammar b/res/html.grammar new file mode 100644 index 0000000..4754f8d --- /dev/null +++ b/res/html.grammar @@ -0,0 +1,41 @@ +/* + An HTML grammar for use with TDParseKit + + this grammar is intentionally very forgiving (non-strict) + the point here is to highlight, not validate, HTML. +*/ + +@multiLineComments = ''; +@commentState = '<'; +@commentState.fallbackState = delimitState; + +@delimitedString = '' nil; +@delimitedString = '' nil; +@delimitState.fallbackState = symbolState; + +@start = any*; +any = element | text | doctype | pi | comment; + +pi = DelimitedString(''); + +doctype = DelimitedString(''); +element = emptyTag | startTag elementContent* endTag; +elementContent = element | text | comment | pi; +text = /[^<]+/; + +emptyTag = lt tagName attr* fwdSlash gt; +startTag = lt junk? tagName attr* gt; +endTag = lt fwdSlash tagName gt; + +tagName = Word; + +attr = attrName (eq attrValue)?; +attrName = Word; +attrValue = QuotedString; + +eq = '='; +lt = '<'; +gt = '>'; +fwdSlash = '/'; + +comment = Comment; diff --git a/res/javascript.grammar b/res/javascript.grammar new file mode 100644 index 0000000..af9032f --- /dev/null +++ b/res/javascript.grammar @@ -0,0 +1,430 @@ +@symbols = '||' '&&' '!=' '!==' '==' '===' '<=' '>=' '++' '--' '+=' '-=' '*=' '/=' '%=' '<<' '>>' '>>>' '<<=' '>>=' '>>>=' '&=' '^=' '|='; + +@reportsCommentTokens = YES; +@commentState = '/'; +@singleLineComments = '//'; +@multiLineComments = '/*' '*/'; + +@start = program; + +if = 'if'; +else = 'else'; +while = 'while'; +for = 'for'; +in = 'in'; +break = 'break'; +continue = 'continue'; +with = 'with'; +return = 'return'; +var = 'var'; +delete = 'delete'; +new = 'new'; +this = 'this'; +false = 'false'; +true = 'true'; +null = 'null'; +undefined = 'undefined'; +void = 'void'; +typeof = 'typeof'; +instanceof = 'instanceof'; +function = 'function'; + +openCurly = '{'; +closeCurly = '}'; +openParen = '('; +closeParen = ')'; +openBracket = '['; +closeBracket = ']'; +comma = ','; +dot = '.'; +semi = ';'; +colon = ':'; +equals = '='; +not = '!'; +lt = '<'; +gt = '>'; +amp = '&'; +pipe = '|'; +caret = '^'; +tilde = '~'; +question = '?'; +plus = '+'; +minus = '-'; +times = '*'; +div = '/'; +mod = '%'; + +or = '||'; +and = '&&'; +ne = '!='; +isnot = '!=='; +eq = '=='; +is = '==='; +le = '<='; +ge = '>='; +plusPlus = '++'; +minusMinus = '--'; +plusEq = '+='; +minusEq = '-='; +timesEq = '*='; +divEq = '/='; +modEq = '%='; +shiftLeft = '<<'; +shiftRight = '>>'; +shiftRightExt = '>>>'; +shiftLeftEq = '<<='; +shiftRightEq = '>>='; +shiftRightExtEq = '>>>='; +andEq = '&='; +xorEq = '^='; +orEq = '|='; + +assignmentOperator = equals | plusEq | minusEq | timesEq | divEq | modEq | shiftLeftEq | shiftRightEq | shiftRightExtEq | andEq | xorEq | orEq; + +relationalOperator = lt | gt | ge | le | instanceof; +equalityOperator = eq | ne | is | isnot; + +shiftOperator = shiftLeft | shiftRight | shiftRightExt; +incrementOperator = plusPlus | minusMinus; +unaryOperator = tilde | delete | typeof | void; + +multiplicativeOperator = times | div | mod; + + + +// Program: +// empty +// Element Program + +program = element+; + + + +// Element: +// function Identifier ( ParameterListOpt ) CompoundStatement +// Statement + +element = func | stmt; +func = function identifier openParen paramListOpt closeParen compoundStmt; + + + +// ParameterListOpt: +// empty +// ParameterList + +paramListOpt = Empty | paramList; + + + +// ParameterList: +// Identifier +// Identifier , ParameterList + +paramList = identifier commaIdentifier*; +commaIdentifier = comma identifier; + + + +// CompoundStatement: +// { Statements } + +compoundStmt = openCurly stmts closeCurly; + + + +// Statements: +// empty +// Statement Statements + +stmts = stmt*; + + + +// Statement: +// ; +// if Condition Statement +// if Condition Statement else Statement +// while Condition Statement +// ForParen ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin in Expression ) Statement +// break ; +// continue ; +// with ( Expression ) Statement +// return ExpressionOpt ; +// CompoundStatement +// VariablesOrExpression ; + +stmt = semi | ifStmt | ifElseStmt | whileStmt | forParenStmt | forBeginStmt | forInStmt | breakStmt | continueStmt | withStmt | returnStmt | compoundStmt | variablesOrExprStmt; +ifStmt = if condition stmt; +ifElseStmt = if condition stmt else stmt; +whileStmt = while condition stmt; +forParenStmt = forParen semi exprOpt semi exprOpt closeParen stmt; +forBeginStmt = forBegin semi exprOpt semi exprOpt closeParen stmt; +forInStmt = forBegin in expr closeParen stmt; +breakStmt = break semi; +continueStmt = continue semi; +withStmt = with openParen expr closeParen stmt; +returnStmt = return exprOpt semi; +variablesOrExprStmt = variablesOrExpr semi; + + + +// Condition: +// ( Expression ) + +condition = openParen expr closeParen; + + + +// ForParen: +// for ( + +forParen = for openParen; + + + +// ForBegin: +// ForParen VariablesOrExpression + +forBegin = forParen variablesOrExpr; + + + +// VariablesOrExpression: +// var Variables +// Expression + +variablesOrExpr = varVariables | expr; +varVariables = var variables; + + + +// Variables: +// Variable +// Variable , Variables + +variables = variable commaVariable*; +commaVariable = comma variable; + + + +// Variable: +// Identifier +// Identifier = AssignmentExpression + +variable = identifier assignment?; +assignment = equals assignmentExpr; + + + +// ExpressionOpt: +// empty +// Expression + +exprOpt = Empty | expr; // TODO -- Empty | expr; + + + +// Expression: +// AssignmentExpression +// AssignmentExpression , Expression + +expr = assignmentExpr commaExpr?; +commaExpr = comma expr; + + + +// AssignmentExpression: +// ConditionalExpression +// ConditionalExpression AssignmentOperator AssignmentExpression + +assignmentExpr = conditionalExpr extraAssignment?; +extraAssignment = assignmentOperator assignmentExpr; + + + +// ConditionalExpression: +// OrExpression +// OrExpression ? AssignmentExpression : AssignmentExpression + +conditionalExpr = orExpr ternaryExpr?; +ternaryExpr = question assignmentExpr colon assignmentExpr; + + + +// OrExpression: +// AndExpression +// AndExpression || OrExpression + +orExpr = andExpr orAndExpr*; +orAndExpr = or andExpr; + + + +// AndExpression: +// BitwiseOrExpression +// BitwiseOrExpression && AndExpression + +andExpr = bitwiseOrExpr andAndExpr?; +andAndExpr = and andExpr; + + + +// BitwiseOrExpression: +// BitwiseXorExpression +// BitwiseXorExpression | BitwiseOrExpression + +bitwiseOrExpr = bitwiseXorExpr pipeBitwiseOrExpr?; +pipeBitwiseOrExpr = pipe bitwiseOrExpr; + + + +// BitwiseXorExpression: +// BitwiseAndExpression +// BitwiseAndExpression ^ BitwiseXorExpression + +bitwiseXorExpr = bitwiseAndExpr caretBitwiseXorExpr?; +caretBitwiseXorExpr = caret bitwiseXorExpr; + + + +// BitwiseAndExpression: +// EqualityExpression +// EqualityExpression & BitwiseAndExpression + +bitwiseAndExpr = equalityExpr ampBitwiseAndExpression?; +ampBitwiseAndExpression = amp bitwiseAndExpr; + + + +// EqualityExpression: +// RelationalExpression +// RelationalExpression EqualityualityOperator EqualityExpression + +equalityExpr = relationalExpr equalityOpEqualityExpr?; +equalityOpEqualityExpr = equalityOperator equalityExpr; + + + +// RelationalExpression: +// ShiftExpression +// RelationalExpression RelationalationalOperator ShiftExpression + +relationalExpr = shiftExpr | relationalExprRHS; +relationalExprRHS = relationalExpr relationalOperator shiftExpr; + + + +// ShiftExpression: +// AdditiveExpression +// AdditiveExpression ShiftOperator ShiftExpression + +shiftExpr = additiveExpr shiftOpShiftExpr?; +shiftOpShiftExpr = shiftOperator shiftExpr; + + + +// AdditiveExpression: +// MultiplicativeExpression +// MultiplicativeExpression + AdditiveExpression +// MultiplicativeExpression - AdditiveExpression + +additiveExpr = multiplicativeExpr plusOrMinusExpr?; +plusOrMinusExpr = plusExpr | minusExpr; +plusExpr = plus additiveExpr; +minusExpr = minus additiveExpr; + + + +// MultiplicativeExpression: +// UnaryExpression +// UnaryExpression MultiplicativeOperator MultiplicativeExpression + +multiplicativeExpr = unaryExpr (multiplicativeOperator multiplicativeExpr)?; + + + +// UnaryExpression: +// MemberExpression +// UnaryOperator UnaryExpression +// - UnaryExpression +// IncrementOperator MemberExpression +// MemberExpression IncrementOperator +// new Constructor +// delete MemberExpression + +unaryExpr = memberExpr | unaryExpr1 | unaryExpr2 | unaryExpr3 | unaryExpr4 | unaryExpr5 | unaryExpr6; +unaryExpr1 = unaryOperator unaryExpr; +unaryExpr2 = minus unaryExpr; +unaryExpr3 = incrementOperator memberExpr; +unaryExpr4 = memberExpr incrementOperator; +unaryExpr5 = new constructor; +unaryExpr6 = delete memberExpr; + + + +// Constructor: +// this . ConstructorCall +// ConstructorCall + +constructor = constructorCall; // TODO ??? + + + +// ConstructorCall: +// Identifier +// Identifier ( ArgumentListOpt ) +// Identifier . ConstructorCall + +constructorCall = identifier parenArgListParen?; // TODO +parenArgListParen = openParen argListOpt closeParen; + + + +// MemberExpression: +// PrimaryExpression +// PrimaryExpression . MemberExpression +// PrimaryExpression [ Expression ] +// PrimaryExpression ( ArgumentListOpt ) + +memberExpr = primaryExpr dotBracketOrParenExpr?; +dotBracketOrParenExpr = dotMemberExpr | bracketMemberExpr | parenMemberExpr; +dotMemberExpr = dot memberExpr; +bracketMemberExpr = openBracket expr closeBracket; +parenMemberExpr = openParen argListOpt closeParen; + + + +// ArgumentListOpt: +// empty +// ArgumentList + +argListOpt = argList?; + + + +// ArgumentList: +// AssignmentExpression +// AssignmentExpression , ArgumentList + +argList = assignmentExpr commaAssignmentExpr*; +commaAssignmentExpr = comma assignmentExpr; + + + +// PrimaryExpression: +// ( Expression ) +// Identifier +// IntegerLiteral +// FloatingPointLiteral +// StringLiteral +// false +// true +// null +// this + +primaryExpr = parenExprParen | identifier | Number | QuotedString | false | true | null | undefined | this; +parenExprParen = openParen expr closeParen; +identifier = Word; diff --git a/res/javascript_ll.txt b/res/javascript_ll.txt new file mode 100644 index 0000000..9ddb815 --- /dev/null +++ b/res/javascript_ll.txt @@ -0,0 +1,133 @@ + +JavaScript LL(1) Grammar + +This appendix contains the NQLL(1) grammar (Not Quite LL(1)) for JavaScript. +NOTE: This appendix is missing the algorithm for recovering from missing semicolon errors. + + +Program: + empty + Element Program + Element: + function Identifier ( ParameterListOpt ) CompoundStatement + Statement + ParameterListOpt: + empty + ParameterList + ParameterList: + Identifier + Identifier , ParameterList + CompoundStatement: + { Statements } + Statements: + empty + Statement Statements + Statement: + ; + if Condition Statement + if Condition Statement else Statement + while Condition Statement + ForParen ; ExpressionOpt ; ExpressionOpt ) Statement + ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement + ForBegin in Expression ) Statement + break ; + continue ; + with ( Expression ) Statement + return ExpressionOpt ; + CompoundStatement + VariablesOrExpression ; + Condition: + ( Expression ) + ForParen: + for ( + ForBegin: + ForParen VariablesOrExpression + VariablesOrExpression: + var Variables + Expression + Variables: + Variable + Variable , Variables + Variable: + Identifier + Identifier = AssignmentExpression + ExpressionOpt: + empty + Expression + Expression: + AssignmentExpression + AssignmentExpression , Expression + AssignmentExpression: + ConditionalExpression + ConditionalExpression AssignmentOperator AssignmentExpression + ConditionalExpression: + OrExpression + OrExpression ? AssignmentExpression : AssignmentExpression + OrExpression: + AndExpression + AndExpression || OrExpression + AndExpression: + BitwiseOrExpression + BitwiseOrExpression && AndExpression + BitwiseOrExpression: + BitwiseXorExpression + BitwiseXorExpression | BitwiseOrExpression + BitwiseXorExpression: + BitwiseAndExpression + BitwiseAndExpression ^ BitwiseXorExpression + BitwiseAndExpression: + EqualityExpression + EqualityExpression & BitwiseAndExpression + EqualityExpression: + RelationalExpression + RelationalExpression EqualityualityOperator EqualityExpression + RelationalExpression: + ShiftExpression + RelationalExpression RelationalationalOperator ShiftExpression + ShiftExpression: + AdditiveExpression + AdditiveExpression ShiftOperator ShiftExpression + AdditiveExpression: + MultiplicativeExpression + MultiplicativeExpression + AdditiveExpression + MultiplicativeExpression - AdditiveExpression + MultiplicativeExpression: + UnaryExpression + UnaryExpression MultiplicativeOperator MultiplicativeExpression + UnaryExpression: + MemberExpression + UnaryOperator UnaryExpression + - UnaryExpression + IncrementOperator MemberExpression + MemberExpression IncrementOperator + new Constructor + delete MemberExpression + Constructor: + this . ConstructorCall + ConstructorCall + ConstructorCall: + Identifier + Identifier ( ArgumentListOpt ) + Identifier . ConstructorCall + MemberExpression: + PrimaryExpression + PrimaryExpression . MemberExpression + PrimaryExpression [ Expression ] + PrimaryExpression ( ArgumentListOpt ) + ArgumentListOpt: + empty + ArgumentList + ArgumentList: + AssignmentExpression + AssignmentExpression , ArgumentList + PrimaryExpression: + ( Expression ) + Identifier + IntegerLiteral + FloatingPointLiteral + StringLiteral + false + true + null + this +[Previous] [First] \ No newline at end of file diff --git a/res/json-old.grammar b/res/json-old.grammar new file mode 100644 index 0000000..782543c --- /dev/null +++ b/res/json-old.grammar @@ -0,0 +1,26 @@ +/** + A Grammar for JSON + + NOTE: This grammar has a fatal flaw. it does not allow for the heirarchical nature of + JSON. Objects and arrays may only be one level deep according to this grammar. + This is a limitation of my grammar parser: it does not allow circular references. + That wll be fixed soon + + */ +null = 'null'; +true = 'true'; +false = 'false'; +value = null | true | false | Num | QuotedString; // here's the flaw. should include: "array | object" + +commaValue = ',' value; +actualArray = value commaValue*; +arrayContent = Empty | actualArray; +array = '[' arrayContent ']'; + +property = QuotedString ':' value; // NOTE: property names are quoted in JSON +commaProperty = ',' property; +actualObject = property commaProperty*; +objectContent = Empty | actualObject; +object = '{' objectContent '}'; + +start = (array | object); \ No newline at end of file diff --git a/res/json.css b/res/json.css new file mode 100644 index 0000000..b5083e7 --- /dev/null +++ b/res/json.css @@ -0,0 +1,43 @@ +/** + +A CSS Stylesheet that matches the JSON grammar + +note that each terminal production from json.grammar is listed in a CSS selector below. +text that matches any of these productions will display with the css properties listed here + +*/ + +openCurly, closeCurly, openBracket, closeBracket, comma, colon { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +null, true, false { + color:rgb(196.35, 45.9, 51.0); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +propertyName { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +string { + color:rgb(61.2, 178.5, 68.85); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +number { + color:rgb(22.95, 158.1, 188.7); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} diff --git a/res/json.grammar b/res/json.grammar new file mode 100644 index 0000000..decd888 --- /dev/null +++ b/res/json.grammar @@ -0,0 +1,60 @@ +/* + A Grammar for JSON. + +*/ + +@start = Empty | array | object; + +object = openCurly (Empty | objectContent) closeCurly; +objectContent = property commaProperty*; +property = propertyName colon value; +commaProperty = comma property; +propertyName = QuotedString; // NOTE: property names are quoted in JSON + +array = openBracket (Empty | arrayContent) closeBracket; +arrayContent = value commaValue*; +commaValue = comma value; + +value = null | boolean | array | object | number | string; + +string = QuotedString; +number = Number; +null = 'null'; +boolean = 'true' | 'false'; + +openCurly = '{'; +closeCurly = '}'; +openBracket = '['; +closeBracket = ']'; +comma = ','; +colon = ':'; + + +/* + + The built-in terminal production types are (note titlecase) : Empty, Number, QuotedString, Word, UppercaseWord, LowercaseWord + You define collections (alternations, repetitions or sequences) and literal terminals (in quotes). These should be lowercase. + The special '@start' production is the outermost production. + + you can discard tokens by following them with a bang ('!') like: + + closeCurly = '}'!; + + Feed this grammar to -[PKParserFactory parserFromGrammar:assembler:] along with a reference + to an assembler (a call back delegate), and it will return a PKParser object which can + parse strings conforming to this language/grammar. + + The when the returned parser is used, the provided assembler will receive method callbacks for each production matched, like: + + -didMatchObjectAssembly: + -didMatchObjectContentAssembly: + -didMatchPropertyAssembly: + -didMatchArrayAssembly: + -didMatchOpenCurlyAssembly: + etc. + + Each callback method must accept a single PKAssembly argument. This assembly argument + will contain information about the progress made on the the string currently being parsed. + Also the assembly's stack will contain the tokens parsed so far in the current statement. + +*/ \ No newline at end of file diff --git a/res/json_with_comments.css b/res/json_with_comments.css new file mode 100644 index 0000000..b0c9d02 --- /dev/null +++ b/res/json_with_comments.css @@ -0,0 +1,50 @@ +/** + +A CSS Stylesheet that matches the JSON grammar + +note that each terminal production from json.grammar is listed in a CSS selector below. +text that matches any of these productions will display with the css properties listed here + +*/ + +openCurly, closeCurly, openBracket, closeBracket, comma, colon { + color:rgb(178.5, 35.7, 135.15); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +null, true, false { + color:rgb(196.35, 45.9, 51.0); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +propertyName { + color:rgb(84.15, 114.75, 122.4); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +string { + color:rgb(61.2, 178.5, 68.85); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +number { + color:rgb(22.95, 158.1, 188.7); + background-color:rgb(30, 30, 36); + font-family:'Monaco'; + font-size:11px; +} + +comment { + color:rgb(72.95, 208.1, 238.7); + background-color:rgb(0, 0, 0); + font-family:'Monaco'; + font-size:11px; +} diff --git a/res/json_with_comments.grammar b/res/json_with_comments.grammar new file mode 100644 index 0000000..a397488 --- /dev/null +++ b/res/json_with_comments.grammar @@ -0,0 +1,67 @@ +/* + A Fake Grammar for JSON with comments (JSON does not have comments). + +*/ + +@singleLineComments = '#'; +@multiLineComments = '/*' '*/'; + +@start = (Empty | array | object) comment?; + +object = openCurly comment? objectContent closeCurly; +objectContent = Empty | actualObject; +actualObject = property commaProperty*; +property = propertyName colon comment? value; +commaProperty = comma comment? property; +propertyName = QuotedString; // NOTE: property names are quoted in JSON + +array = openBracket comment? arrayContent closeBracket; +arrayContent = Empty | actualArray; +actualArray = value commaValue*; +commaValue = comma comment? value; + +value = (null | true | false | number | string | array | object) comment?; + +comment = Comment; +string = QuotedString; +number = Number; +null = 'null'; +true = 'true'; +false = 'false'; + +openCurly = '{'; +closeCurly = '}'; +openBracket = '['; +closeBracket = ']'; +comma = ','; +colon = ':'; + + +/* + + The built-in terminal production types are (note titlecase) : Empty, Number, QuotedString, Word, UppercaseWord, LowercaseWord + You define collections (alternations, repetitions or sequences) and literal terminals (in quotes). These should be lowercase. + The special '@start' production is the outermost production. + + you can discard tokens by following them with a bang ('!') like: + + closeCurly = '}'!; + + Feed this grammar to -[PKParserFactory parserFromGrammar:assembler:] along with a reference + to an assembler (a call back delegate), and it will return a PKParser object which can + parse strings conforming to this language/grammar. + + The when the returned parser is used, the provided assembler will receive method callbacks for each production matched, like: + + -didMatchObjectAssembly: + -didMatchObjectContentAssembly: + -didMatchPropertyAssembly: + -didMatchArrayAssembly: + -didMatchOpenCurlyAssembly: + etc. + + Each callback method must accept a single PKAssembly argument. This assembly argument + will contain information about the progress made on the the string currently being parsed. + Also the assembly's stack will contain the tokens parsed so far in the current statement. + +*/ \ No newline at end of file diff --git a/res/json_with_discards.grammar b/res/json_with_discards.grammar new file mode 100644 index 0000000..f2afb83 --- /dev/null +++ b/res/json_with_discards.grammar @@ -0,0 +1,39 @@ +/* + A Grammar for JSON which specifies which tokens should be discarded + + Feed this to -[PKParserFactory parserFromGrammar:assembler:] along with a reference + to an assembler (a call back delegate), and it will return a PKParser object which can + parse strings conforming to this language/grammar. + + The when the returned parser is used, the provided assembler will receive method callbacks like: + + -didMatchStart: + -didMatchObject: + -didMatchProperty: + -didMatchArray: + etc. + + whenever a grammar production of the corresponding name has been matched. + + Each callback method must accept a single PKAssembly argument. The provided assembly + will contain information about the progress made on the the string currently being parsed. + Also the assembly's stack will contain the tokens parsed so far in the current statement. +*/ + +@start = Empty | array | object; + +object = '{' objectContent '}'!; +objectContent = Empty | actualObject; +actualObject = property commaProperty*; +commaProperty = ','! property; +property = QuotedString ':'! value; // NOTE: property names are quoted in JSON + +array = '[' arrayContent ']'!; +arrayContent = Empty | actualArray; +actualArray = value commaValue*; +commaValue = ','! value; + +value = null | true | false | array | object | Number | QuotedString; +null = 'null'!; +true = 'true'!; +false = 'false'!; diff --git a/res/mini_css.grammar b/res/mini_css.grammar new file mode 100644 index 0000000..12f6ecf --- /dev/null +++ b/res/mini_css.grammar @@ -0,0 +1,18 @@ +/* + A Grammar for a small subset of CSS useful for syntax highlighting in an NSTextView + NSAttributedString +*/ + +@start = ruleset*; +ruleset = selectors '{' decls '}'!; +selectors = selector commaSelector*; +selector = LowercaseWord; // forcing selectors to be lowercase words for use in a future syntax-highlight framework where i want that +commaSelector = ','! selector; +decls = Empty | actualDecls; +actualDecls = decl decl*; +decl = property ':'! expr ';'!?; +property = 'color' | 'background-color' | 'font-family' | 'font-size'; +expr = pixelValue | rgb | string | constants; +pixelValue = Number 'px'!; +rgb = 'rgb'! '(' Number ','! Number ','! Number ')'!; +string = QuotedString; +constants = 'bold' | 'normal' | 'italic'; \ No newline at end of file diff --git a/res/nasty.html b/res/nasty.html new file mode 100644 index 0000000..fa9aceb --- /dev/null +++ b/res/nasty.html @@ -0,0 +1,68 @@ + + + +http://www.apple.com/ + + + +< + + url + xmls:foo="bar" baz + + = + + "foobar">yes maam + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/nonascii.html b/res/nonascii.html new file mode 100644 index 0000000..f39658d --- /dev/null +++ b/res/nonascii.html @@ -0,0 +1 @@ +ア \ No newline at end of file diff --git a/res/nspredicate.grammar b/res/nspredicate.grammar new file mode 100644 index 0000000..8022439 --- /dev/null +++ b/res/nspredicate.grammar @@ -0,0 +1,121 @@ +/* +A Grammar for Apple's NSPredicate String Format Syntax + +See: http://developer.apple.com/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html + +*/ + +@wordState = '#'; +@wordChars = '.' '[' ']'; + +@symbols = '==' '>=' '=>' '<=' '=<' '!=' '<>' '&&' '||'; + +@start = expr; + +// Expressions + expr = orTerm orOrTerm*; + orOrTerm = or orTerm; + orTerm = andTerm andAndTerm*; + andAndTerm = and andTerm; + andTerm = primaryExpr | compoundExpr; + compoundExpr = '('! expr ')'!; + primaryExpr = predicate | negatedPredicate; + negatedPredicate = not predicate; + + predicate = boolPredicate | comparisonPredicate | stringTestPredicate | collectionTestPredicate; + + +// values + value = keyPath | string | num | bool | array; + + string = QuotedString; + num = Number; + bool = true | false; + true = 'true'!; + false = 'false'!; + +// arrays + array = '{' arrayContentsOpt '}'!; + arrayContentsOpt = Empty | arrayContents; + arrayContents = value commaValue*; + commaValue = ','! value; + + +// keyPaths + keyPath = Word; + +// keyPath = key dotKey*; +// key = name memberAccess?; +// name = Word; +// dotKey = '.' key; +// memberAccess = '[' (num | 'FIRST' | 'LAST' | 'SIZE') ']'; + + +// Comparison Tests + comparisonPredicate = numComparisonPredicate | collectionComparisonPredicate; + + numComparisonPredicate = numComparisonValue comparisonOp numComparisonValue; + numComparisonValue = keyPath | num; + + comparisonOp = eq | gt | lt | gtEq | ltEq | notEq | between; + + eq = '=' | '=='; + gt = '>'; + lt = '<'; + gtEq = '>=' | '=>'; + ltEq = '<=' | '=<'; + notEq = '!=' | '<>'; + between = 'BETWEEN'; + +// breaking these out to make the assembler callbacks simpler + collectionComparisonPredicate = collectionLtPredicate | collectionGtPredicate | collectionLtEqPredicate | collectionGtEqPredicate | collectionEqPredicate | collectionNotEqPredicate; + + collectionLtPredicate = aggregateOp collection lt value; + collectionGtPredicate = aggregateOp collection gt value; + collectionLtEqPredicate = aggregateOp collection ltEq value; + collectionGtEqPredicate = aggregateOp collection gtEq value; + collectionEqPredicate = aggregateOp collection eq value; + collectionNotEqPredicate = aggregateOp collection notEq value; + + + +// Boolean Value Predicates + boolPredicate = truePredicate | falsePredicate; + + truePredicate = 'TRUEPREDICATE'!; + falsePredicate = 'FALSEPREDICATE'!; + + + +// Compound Expressions + and = 'AND'! | '&&'!; + or = 'OR'! | '||'!; + not = 'NOT'! | '!'!; + + + +// String Tests + stringTestPredicate = string stringTestOp value; + + stringTestOp = beginswith | contains | endswith | like | matches; + + beginswith = 'BEGINSWITH'; + contains = 'CONTAINS'; + endswith = 'ENDSWITH'; + like = 'LIKE'; + matches = 'MATCHES'; + + +// Collection Tests + collectionTestPredicate = value in collection; + collection = keyPath | array; + in = 'IN'!; + + +// Aggregate Operators + aggregateOp = any | some | all | none; + any = 'ANY'; + some = 'SOME'; + all = 'ALL'; + none = 'NONE'; + diff --git a/res/nyt.html b/res/nyt.html new file mode 100644 index 0000000..3cd9c5d --- /dev/null +++ b/res/nyt.html @@ -0,0 +1,1843 @@ + + + + + + + + + + + + + + + + +The New York Times - Breaking News, World News & Multimedia + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ +
+
+ + +
+
+ + +
+ +
Wednesday, September 17, 2008 Last Update: 2:12 PM ET
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + +
+ + + + + + +
+ +
+ + + + + +
+
+
+ + + + + +

+Stocks Drop Sharply Despite Bailout of Big Insurer +

+
+ +

+The Fed’s rescue of A.I.G. failed to placate investors, and a report showing a further decline in housing starts added to the gloom. +

+ + + + +
+ + + + +
+
Q & A
+
The A.I.G. Rescue
+

+David Leonhardt answers questions about the implications of the A.I.G. bailout and the economy. +

+ +
+ +
+
+ + +
+
+
+ + +
+
+ +
+ + + +
+ +
Yuriko Nakao/Reuters
+
+ +
+

A board in Tokyo displayed rising stock prices. Stock markets rallied across much of Asia in early trading in response to the rescue of A.I.G.

+ + +
+ + +
+
+ +
+ +
+ + + +
+
+In Asia, the Bloom Is Off the A.I.G. Rose +
+ +

If A.I.G.’s reputation suffers heavily, the company will face an uphill battle in Asia and its other global markets.

+ + + +
+ +
+ + + + + + + + + + +
+
+
+
+
+
+ +
+ + + +
+
American Exception
+
+Supreme Court’s Global Influence Is Waning +
+ +

A diminishing number of foreign courts seem to pay attention to the writings of American justices.

+ + + + +
+ + + + +
+
+16 Are Killed in Attack on U.S. Embassy in Yemen +
+ +

Militants opened fire on the embassy in Sana and detonated a car bomb at its gates, but no Americans were killed or injured, a Yemeni official said.

+ + + + +
+ +
+ +
+
+ + +

2008 Campaign

+ + +
+ + + +
+
+Abortion Issue Again Dividing Catholic Votes +
+ +

A struggle on how Catholics should apply their beliefs in politics is reaching swing cities like Scranton, Pa.

+ + + + +
+ + + + +
+
+New York Settles Lawsuit Over Homeless Families +
+ +

The costly litigation, over homeless families’ access to shelter in New York City, has dragged on since 1983.

+ + + +
+ +
+ + +
+
+
MORE NEWS
+ +
+
+ + + + + + +
+
+
+ +
 
+
+
+
+ +
+ + + + +
+ + +
+
+
+
+ +
+
GUEST Q & A
+
Wheels: Questions for Motocross Champion
+

James Stewart, winner of both the World Supercross and AMA Supercross championships, is taking questions from readers.

+ +
+
+ +
National Correspondent
+

+Amy Harmon, who covers the impact of science and technology on American life, is answering questions. +

+
+ +
+ +
+
+
+ + +
+ + + +
+
+
+ + +

Travel »

+
A Cultural Cornerstone

A Cultural CornerstoneCasco Viejo seems poised to become a hotbed of nightclubs, cafes, and hotels.

+ +
+
36 Hours in San Francisco

36 Hours in San Francisco Prosperity hasn’t sapped the Mission District of its eclecticism.

+
+
+ + +
+
+
+ + +
+ + + + + +
+
+ +
+ +

My Portfolios »

+ + + +
+ +
+ + +
+ +
+
+ + + + + +
+ + +
+ + +
+ + +
+
+ +
+ +
+
+ +
A Scottish House, Traditional Yet Modern
+

BerlinThe “Upside-Down House”, designed in 1959 by James Morris and Robert Steedman, holds a prominent place in Edinburgh’s recent architectural history.

+ +
+
+
+
+Find Properties +
+
+ + +Advanced Search » +
+ + +
+ + + + +
+ + +
+
+
+
General Motors at 100
+

Chevrolet VoltThe Chevrolet Volt, which G.M. unveiled on Tuesday, is intended to provide a jump-start for General Motors’ second century.

+ +
+
+ +

+Submit photos and view and comment on other readers’ cars. Also, view and submit events to the +Automotive Events Calendar. +

+ +
+
+ +
+ + +
+
+Search for new cars +
+
+ + + +
+
+
+
+Search for used cars +
+
+ + + + +
+
+
+More in Automobiles +
+ +
+ +
+
+ + +
+ + +
+

+NYtimes.com / Monster +

+
+
+
Fresh Starts
+
Navigators for the College Bound
+

Navigators for the College BoundPrivate educational consultants take up where overburdened high school guidance counselors leave off.

+
+
ADVERTISEMENT
+
+
+
+

+Find the best job in the +New York metro area +and beyond. +

+
+ + + + Advanced Search » +
+
+Tools +
+ +
+Employers +
+ +
+
+ +
+ + + + + +
+ +
+ + + + + + + + +
+ +
+ + +
+
+  +
+

Inside NYTimes.com

+
+ + + + + + + + + + + + + + + + + + + + + +

Media & Advertising »

World »

Opinion »

Music »

Opinion »

Dining & Wine »

+
+
+ +Chrysler Is Loyal to Its Pickup in a Cold Market + +
+
Chrysler Is Loyal to Its Pickup in a Cold Market
+
+
+
+
+ +Friction as India Converts Farmland Into Factories + +
+
Friction as India Converts Farmland Into Factories
+
+
+
+
+ + + +
+
+
+
+
+
+ +When Julian Schnabel Met Plácido Domingo + +
+
When Julian Schnabel Met Plácido Domingo
+
+
+
+
+ +Op-Ed: Another Country + +
+
Op-Ed: Another Country
+
+
+
+
+ +Instead of Eating to Diet, They’re Eating to Enjoy + +
+
Instead of Eating to Diet, They’re Eating to Enjoy
+
+
+ +
+ +
+ + + + + + + + + +
+ + + + + + + + + +
+ +
+ + + + + +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ + + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/objc.grammar b/res/objc.grammar new file mode 100644 index 0000000..5dec845 --- /dev/null +++ b/res/objc.grammar @@ -0,0 +1,236 @@ + +@symbol = '@interface'; +@symbol = '@implementation'; +@symbol = '@end'; +@symbol = '@class'; +@symbol = '@protocol'; + +// external-declaration: +// function-definition +// declaration +// class-interface +// class-implementation +// category-interface +// category-implementation +// protocol-declaration +// class-declaration-list + +externalDecl = functionDef | decl | classInterface | classImpl | categoryInterface | categoryImpl | protocolDecl | classDeclList; + +// class-interface: +// @interface class-name [ : superclass-name ] +// [ protocol-reference-list ] +// [ instance-variables ] +// [ interface-declaration-list ] +// @end + +classInterface = '@interface' className (':' superclassName)? protocolRefList? ivars? interfaceDeclList? '@end'; + +// class-implementation: +// @implementation class-name [ : superclass-name ] +// [ instance-variables ] +// [ implementation-definition-list ] +// @end + +classImpl = '@implementation' className (':' superclassName)? ivars? implementationDefList? '@end'; + +// category-interface: +// @interface class-name ( category-name ) +// [ protocol-reference-list ] +// [ interface-declaration-list ] +// @end + +categoryInterface = '@interface' className '(' categoryName ')' protocolRefList? interfaceDeclList? '@end'; + +category-implementation: +@implementation class-name ( category-name ) +[ implementation-definition-list ] +@end + +protocol-declaration: +@protocol protocol-name +[ protocol-reference-list ] +[ interface-declaration-list ] +@end + +class-declaration-list: +@class class-list ; + +class-list: +class-name +class-list , class-name + +protocol-reference-list: +< protocol-list > + +protocol-list: +protocol-name +protocol-list , protocol-name + +class-name: +identifier + +superclass-name: +identifier + +category-name: +identifier + +protocol-name: +identifier + +instance-variables: +{ [ visibility-specification ] struct-declaration-list [ instance-variables ] } + +visibility-specification: +@private +@protected +@public + +interface-declaration-list: +declaration +method-declaration +interface-declaration-list declaration +interface-declaration-list method-declaration + +method-declaration: +class-method-declaration +instance-method-declaration + +class-method-declaration: ++ [ method-type ] method-selector ; + +instance-method-declaration: +- [ method-type ] method-selector ; + +implementation-definition-list: +function-definition +declaration +method-definition +implementation-definition-list function-definition +implementation-definition-list declaration +implementation-definition-list method-definition + +method-definition: +class-method-definition +instance-method-definition + +class-method-definition: ++ [ method-type ] method-selector [ declaration-list ] compound-statement + +instance-method-definition: +- [ method-type ] method-selector [ declaration-list ] compound-statement + +method-selector: +unary-selector +keyword-selector [ , ... ] +keyword-selector [ , parameter-type-list ] + +unary-selector: +selector + +keyword-selector: +keyword-declarator +keyword-selector keyword-declarator + +keyword-declarator: +: [ method-type ] identifier +selector : [ method-type ] identifier + +selector: +identifier + +method-type: +( type-name ) + + +Type Specifiers +type-specifier: +void +char +short +int +long +float +double +signed +unsigned +id [ protocol-reference-list ] +class-name [ protocol-reference-list ] +struct-or-union-specifier +enum-specifier +typedef-name + +struct-or-union-specifier: +struct-or-union [ identifier ] { struct-declaration-list } +struct-or-union [ identifier ] { @defs ( class-name ) } +struct-or-union identifier + + +Type Qualifiers +type-qualifier: +const +volatile +protocol-qualifier + +protocol-qualifier: +in +out +inout +bycopy +byref +oneway + + +Primary Expressions +primary-expression: +identifier +constant +string +( expression ) +self +message-expression +selector-expression +protocol-expression +encode-expression + +message-expression: +[ receiver message-selector ] + +receiver: +expression +class-name +super + +message-selector: +selector +keyword-argument-list + +keyword-argument-list: +keyword-argument +keyword-argument-list keyword-argument + +keyword-argument: +selector : expression +: expression + +selector-expression: +@selector ( selector-name ) + +selector-name: +selector +keyword-name-list + +keyword-name-list: +keyword-name +keyword-name-list keyword-name + +keyword-name: +selector : +: + +protocol-expression: +@protocol ( protocol-name ) + +encode-expression: +@encode ( type-name ) \ No newline at end of file diff --git a/res/proto.grammar b/res/proto.grammar new file mode 100644 index 0000000..e9adbb7 --- /dev/null +++ b/res/proto.grammar @@ -0,0 +1,93 @@ +// proto ::= ( message | extend | enum | import | package | option | ";" )* +proto = ( message | extend | enum | import | package | option | ";" )*; + +// import ::= "import" strLit ";" +import = "import" strLit ";"; + +// package ::= "package" ident ";" +package = "package" ident ";"; + +// option ::= "option" optionBody ";" +option = "option" optionBody ";"; + +// optionBody ::= ident ( "." ident )* "=" constant +optionBody = ident ( "." ident )* "=" constant; + +// message ::= "message" ident messageBody +message = "message" ident messageBody; + +// extend ::= "extend" userType messageBody +extend = "extend" userType messageBody; + +// enum ::= "enum" ident "{" ( option | enumField | ";" )* "}" +enum = "enum" ident "{" ( option | enumField | ";" )* "}"; + +// enumField ::= ident "=" intLit ";" +enumField = ident "=" intLit ";"; + +// service ::= "service" ident "{" ( option | rpc | ";" )* "}" +service = "service" ident "{" ( option | rpc | ";" )* "}"; + +// rpc ::= "rpc" ident "(" userType ")" "returns" "(" userType ")" ";" +rpc = "rpc" ident "(" userType ")" "returns" "(" userType ")" ";"; + +// messageBody ::= "{" ( field | enum | message | extend | extensions | group | option | ":" )* "}" +messageBody = "{" ( field | enum | message | extend | extensions | group | option | ":" )* "}"; + +// group ::= modifier "group" camelIdent "=" intLit messageBody +group = modifier "group" camelIdent "=" intLit messageBody; + +// // tag number must be 2^28-1 or lower + +// field ::= modifier type ident "=" intLit ( "[" fieldOption ( "," fieldOption )* "]" )? ";" +field = modifier type ident "=" intLit ( "[" fieldOption ( "," fieldOption )* "]" )? ";"; + +// fieldOption ::= optionBody | "default" "=" constant +fieldOption = optionBody | "default" "=" constant; + +// extensions ::= "extensions" intLit "to" ( intLit | "max" ) ";" +extensions = "extensions" intLit "to" ( intLit | "max" ) ";"; + +// modifier ::= "required" | "optional" | "repeated" +modifier ::= "required" | "optional" | "repeated"; + +// type ::= "double" | "float" | "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string" | "bytes" | userType +type = "double" | "float" | "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string" | "bytes" | userType; + +// // leading dot for identifiers means they're fully qualified + +// userType ::= ( "."? ident )+ +userType = ( "."? ident )+; + +// constant ::= ident | intLit | floatLit | strLit | boolLit +constant = ident | numLit | strLit | boolLit; + +// ident ::= /[A-Za-z_][\w_]*/ +ident = /[A-Za-z_][\w_]*/; + +// // according to parser.cc, group names must start with a capital letter as a +// // hack for backwards-compatibility + +// camelIdent ::= /[A-Z][\w_]*/ +camelIdent = /[A-Z][\w_]*/; + +// intLit ::= decInt | hexInt | octInt +// decInt ::= /\d+/ +// hexInt ::= /0[xX]([A-Fa-f0-9])+/ +// octInt ::= /0[0-7]+/ +// floatLit ::= /\d+(\.\d+)?([Ee][\+-]?\d+)?/ // allow_f_after_float_ is +numLit = Number; + +// disabled by default in tokenizer.cc + +// boolLit ::= "true" | "false" +boolLit = "true" | "false"; + +// strLit ::= quote ( hexEscape | octEscape | charEscape | /[^\0\n]/ )* +strLit = QuotedString; + +// quote +// quote ::= /["']/ +// hexEscape ::= /\\[Xx][A-Fa-f0-9]{1,2}/ +// octEscape ::= /\\0?[0-7]{1,3}/ +// charEscape ::= /\\[abfnrtv\\\?'"]/ diff --git a/res/rubyhash.grammar b/res/rubyhash.grammar new file mode 100644 index 0000000..e66161c --- /dev/null +++ b/res/rubyhash.grammar @@ -0,0 +1,35 @@ +/* + {"brand"=>{"name"=>"something", + "logo"=>#, + "summary"=>"wee", "content"=>"woopy doo"}, "commit"=>"Save", + "authenticity_token"=>"43a94d60304a7fb13a4ff61a5960461ce714e92b", + "action"=>"create", "controller"=>"admin/brands"} +*/ + +@reportsCommentTokens = YES; +@commentState = '#'; +@multiLineComments = '#<' '>'; +@symbols = '=>'; + +@start = Empty | object; + +object = openCurly objectContent closeCurly; +objectContent = Empty | actualObject; +actualObject = property commaProperty*; +property = propertyName arrow value; +commaProperty = comma property; +propertyName = QuotedString; // NOTE: property names are quoted + +value = null | true | false | object | number | string | fileRef; + +string = QuotedString; +number = Number; +fileRef = Comment; +null = 'null'; +true = 'true'; +false = 'false'; + +openCurly = '{'; +closeCurly = '}'; +comma = ','; +arrow = '=>'; diff --git a/res/small-xml-file.xml b/res/small-xml-file.xml new file mode 100644 index 0000000..da49760 --- /dev/null +++ b/res/small-xml-file.xml @@ -0,0 +1,6 @@ + +http://www.apple.com/ +yes maam + + + \ No newline at end of file diff --git a/res/stuff.txt b/res/stuff.txt new file mode 100644 index 0000000..17690e4 --- /dev/null +++ b/res/stuff.txt @@ -0,0 +1,8 @@ + + + +sudo /Users/itod/Downloads/checker-60/scan-build -o Desktop xcodebuild \ No newline at end of file diff --git a/res/svn-commands.txt b/res/svn-commands.txt new file mode 100644 index 0000000..9abc1e8 --- /dev/null +++ b/res/svn-commands.txt @@ -0,0 +1,23 @@ +svn copy -r1392 https://todparsekit.googlecode.com/svn/trunk/ \ + https://todparsekit.googlecode.com/svn/tags/release-1.5-tag \ + -m "Creating 1.5 release tag from -r1392" + +svn copy -r1392 https://todparsekit.googlecode.com/svn/tags/release-1.5-tag \ + https://todparsekit.googlecode.com/svn/branches/release-1.5-branch \ + -m "Creating 1.5 release branch from -r1392" + + + + +svn delete https://todparsekit.googlecode.com/svn/tags/release-1.4.2-tag \ + -m "deleting first 1.4.2 release tag" + +svn delete https://todparsekit.googlecode.com/svn/branches/release-1.4.2-branch \ + -m "deleting first 1.4.2 release branch" + + + +svn copy -r1361 https://todparsekit.googlecode.com/svn/trunk/ \ + https://todparsekit.googlecode.com/svn/branches/dev-gcd-branch \ + -m "Creating a dev branch for testing GCD stuff. from -r1361" + \ No newline at end of file diff --git a/res/xml.grammar b/res/xml.grammar new file mode 100644 index 0000000..15979d6 --- /dev/null +++ b/res/xml.grammar @@ -0,0 +1,388 @@ +/** + This is a relatively complete TDParseKit grammar for XML 1.0 derived from the XML specification: + + http://www.w3.org/TR/REC-xml/ + + You can create the parser in ObjC like: + + NSString *g = .. // fetch this grammar from disk or wherever + PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self]; + + NSString *XMLString = .. // fetch some XML + [p parse:XMLString]; + + If implemented, your assembler object will receive callbacks for each production in this grammar, like: + + - (void)didMatchElement:(PKAssembly *)a; + - (void)didMatchAttribute:(PKAssembly *)a; + + + This parser is running successfully on some non-trivial real-world XML documents, + but i'm sure there are bugs (espcially in the DTD stuff). + + It's also a little too lenient about a few quoted string values in the spec, and doesnt yet forbid some chars it should. + + I have some tests, But will need many more if this is to be a serious parser: + + http://code.google.com/p/todparsekit/source/browse/trunk/test/TDXMLParserTest.m + + + (I'd like to write an ObjC SAX interface to this parser) + + (Is this the first XML parser implemented directly in Objective-C?) +*/ + +@start = document; + +@reportsWhitespaceTokens = YES; + +@symbols = '&#' '&#x' '' '' '' nil; +@delimitedString = '' nil; + + +// [1] document ::= prolog element Misc* + + document = prolog element misc*; + + +// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */ +// [3] S ::= (#x20 | #x9 | #xD | #xA)+ +// [4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] +// [4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] +// [5] Name ::= NameStartChar (NameChar)* +// [6] Names ::= Name (#x20 Name)* +// [7] Nmtoken ::= (NameChar)+ +// [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)* + + @wordState = ':' '.' '-' '_'; + @wordChars = ':' '.' '-' '_'; + + nmtoken = Word; + + name = Word & /[^-:\.].*/; + + // names = name (S name)*; + // nmtokens = nmtoken (S nmtoken)*; + + + +// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'" +// [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" +// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") + + entityValue = QuotedString; // TODO + attValue = QuotedString; // TODO + systemLiteral = QuotedString; + + +// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" +// [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] + + pubidLiteral = QuotedString; // TODO + + +// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) + + charData = /[^<\&]+/; + + +// [15] Comment ::= '' + + comment = DelimitedString(''); + + +// [16] PI ::= '' Char*)))? '?>' +// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) + + pi = '/* '?>'; + piTarget = name - /xml/i; + + +// [18] CDSect ::= CDStart CData CDEnd +// [19] CDStart ::= '' Char*)) +// [21] CDEnd ::= ']]>' + + cdSect = DelimitedString(''); + + +// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? + + prolog = xmlDecl? misc* (doctypedecl misc*)?; + + +// [23] XMLDecl ::= '' + + xmlDecl = ''; + + +// [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') +// [26] VersionNum ::= '1.' [0-9]+ + + versionNum = /(['"])1\.[0-9]\1/; + versionInfo = S 'version' eq versionNum; + + +// [25] Eq ::= S? '=' S? + + eq = S? '=' S?; + + +// [27] Misc ::= Comment | PI | S + + misc = comment | pi | S; + + +// [28] doctypedecl ::= '' + + doctypedecl = ''; + + +// [28a] DeclSep ::= PEReference | S + + declSep = peReference | S; + + +// [28b] intSubset ::= (markupdecl | DeclSep)* + + intSubset = (markupdecl | declSep)*; + + +// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment + + markupdecl = elementdecl | attlistDecl | entityDecl | notationDecl | pi | comment; + + +// [30] extSubset ::= TextDecl? extSubsetDecl + + extSubset = textDecl? extSubsetDecl; + +// [31] extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)* + + extSubsetDecl = (markupdecl | conditionalSect | declSep)*; + + +// [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) + + sdDecl = S 'standalone' eq /(["'])(yes|no)\1/; + +// [39] element ::= EmptyElemTag | STag content ETag + + element = emptyElemTag | sTag content eTag; + + +// [40] STag ::= '<' Name (S Attribute)* S? '>' + + sTag = '<' name (S attribute)* S? '>'; + + +// [41] Attribute ::= Name Eq AttValue + + attribute = name eq attValue; + + +// [42] ETag ::= '' + + eTag = ''; + + +// [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* + + content = Empty | (element | reference | cdSect | pi | comment | charData)+; + + +// [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' + + emptyElemTag = '<' name (S attribute)* S? '/>'; + + +// [45] elementdecl ::= '' + + elementdecl = ''; + + +// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children + + contentspec = 'EMPTY' | 'ANY' | mixed | children; + + +// [47] children ::= (choice | seq) ('?' | '*' | '+')? + + children = (choice | seq) ('?' | '*' | '+')?; + + +// [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')? + + cp = (name) ('?' | '*' | '+')?; // TODO !!!!!!!!!!!!!! + + +// [49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')' + + choice = '(' S? cp ( S? '|' S? cp )+ S? ')'; + + +// [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')' + + seq = '(' S? cp ( S? ',' S? cp )* S? ')'; + + +// [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')' + + mixed = '(' S? '#PCDATA' (S? '|' S? name)* S? ')*' | '(' S? '#PCDATA' S? ')'; + + +// [52] AttlistDecl ::= '' + + attlistDecl = ''; + + +// AttDef ::= S Name S AttType S DefaultDecl + + attDef = S name S attType S defaultDecl; + + +// [54] AttType ::= StringType | TokenizedType | EnumeratedType + + attType = stringType | tokenizedType | enumeratedType; + + +// [55] StringType ::= 'CDATA' + + stringType = 'CDATA'; + + +// [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS' + + tokenizedType = 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'; + + +// [57] EnumeratedType ::= NotationType | Enumeration + + enumeratedType = notationType | enumeration; + + +// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')' + + notationType = 'NOTATION' S '(' S? name (S? '|' S? name)* S? ')'; + + +// [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')' + + enumeration = '(' S? nmtoken (S? '|' S? nmtoken)* S? ')'; + + +// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue) + + defaultDecl = '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? attValue); + + +// [61] conditionalSect ::= includeSect | ignoreSect + + conditionalSect = includeSect | ignoreSect; + + +// [62] includeSect ::= '' + + includeSect = ''; + + +// [63] ignoreSect ::= '' + + ignoreSect = ''; + + +// [64] ignoreSectContents ::= Ignore ('' Ignore)* + + ignoreSectContents = ignore ('' ignore)*; + + +// [65] Ignore ::= Char* - (Char* ('') Char*) + + ignore = Word - /[^<]*().*/; + + +// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';' + + charRef = '&#' /[0-9]+/ ';' | '&#x' /[0-9a-fA-F]+/ ';'; + + +// [67] Reference ::= EntityRef | CharRef + + reference = entityRef | charRef; + + +// [68] EntityRef ::= '&' Name ';' + + entityRef = '&' name ';'; + + +// [69] PEReference ::= '%' Name ';' + + peReference = '%' name ';'; + + +// [70] EntityDecl ::= GEDecl | PEDecl + + entityDecl = geDecl | peDecl; + + +// [71] GEDecl ::= '' + + geDecl = ''; + + +// [72] PEDecl ::= '' + + peDecl = ''; + + +// [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?) + + entityDef = entityValue | (externalID nDataDecl?); + + +// [74] PEDef ::= EntityValue | ExternalID + + peDef = entityValue | externalID; + + +// [75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral + + externalID = 'SYSTEM' S systemLiteral | 'PUBLIC' S pubidLiteral S systemLiteral; + + +// [76] NDataDecl ::= S 'NDATA' S Name + + nDataDecl = S 'NDATA' S name; + + +// [77] TextDecl ::= '' + + textDecl = ''; + + +// [78] extParsedEnt ::= TextDecl? content + + extParsedEnt = textDecl? content; + + +// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ) +// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* + + encName = /[A-Za-z][-A-Za-z0-9._]*/+; + encodingDecl = S 'encoding' eq QuotedString; + + +// [82] NotationDecl ::= '' + + notationDecl = ''; + + +// [83] PublicID ::= 'PUBLIC' S PubidLiteral + + publicID = 'PUBLIC' S pubidLiteral; diff --git a/res/xml_grammar.txt b/res/xml_grammar.txt new file mode 100644 index 0000000..bd01b6b --- /dev/null +++ b/res/xml_grammar.txt @@ -0,0 +1,78 @@ +[1] document ::= prolog element Misc* +[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]/* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */ +[3] S ::= (#x20 | #x9 | #xD | #xA)+ +[4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender +[5] Name ::= (Letter | '_' | ':') (NameChar)* +[6] Names ::= Name (#x20 Name)* +[7] Nmtoken ::= (NameChar)+ +[8] Nmtokens ::= Nmtoken (#x20 Nmtoken)* +[9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'" +[10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" +[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") +[12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" +[13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] +[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) +[15] Comment ::= '' +[16] PI ::= '' Char*)))? '?>' +[17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) +[18] CDSect ::= CDStart CData CDEnd +[19] CDStart ::= '' Char*)) +[21] CDEnd ::= ']]>' +[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? +[23] XMLDecl ::= '' +[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') +[25] Eq ::= S? '=' S? +[26] VersionNum ::= '1.0' +[27] Misc ::= Comment | PI | S +[28] doctypedecl ::= ''[VC: Root Element Type] +[28a] DeclSep ::= PEReference | S[WFC: PE Between Declarations] +[28b] intSubset ::= (markupdecl | DeclSep)* +[29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment[VC: Proper Declaration/PE Nesting] +[30] extSubset ::= TextDecl? extSubsetDecl +[31] extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)* +[32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))[VC: Standalone Document Declaration] +[39] element ::= EmptyElemTag | STag content ETag[WFC: Element Type Match] +[40] STag ::= '<' Name (S Attribute)* S? '>'[WFC: Unique Att Spec] +[41] Attribute ::= Name Eq AttValue[VC: Attribute Value Type] +[42] ETag ::= '' +[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* +[44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'[WFC: Unique Att Spec] +[45] elementdecl ::= ''[VC: Unique Element Type Declaration] +[46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children +[47] children ::= (choice | seq) ('?' | '*' | '+')? +[48] cp ::= (Name | choice | seq) ('?' | '*' | '+')? +[49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')'[VC: Proper Group/PE Nesting] +[50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'[VC: Proper Group/PE Nesting] +[51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'[VC: Proper Group/PE Nesting] +[52] AttlistDecl ::= '' +[53] AttDef ::= S Name S AttType S DefaultDecl +[54] AttType ::= StringType | TokenizedType | EnumeratedType +[55] StringType ::= 'CDATA' +[56] TokenizedType ::= 'ID'[VC: ID] +[57] EnumeratedType ::= NotationType | Enumeration +[58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'[VC: Notation Attributes] +[59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'[VC: Enumeration] +[60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)[VC: Required Attribute] +[61] conditionalSect ::= includeSect | ignoreSect +[62] includeSect ::= ''[VC: Proper Conditional Section/PE Nesting] +[63] ignoreSect ::= ''[VC: Proper Conditional Section/PE Nesting] +[64] ignoreSectContents ::= Ignore ('' Ignore)* +[65] Ignore ::= Char* - (Char* ('') Char*) +[66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'[WFC: Legal Character] +[67] Reference ::= EntityRef | CharRef +[68] EntityRef ::= '&' Name ';'[WFC: Entity Declared] +[69] PEReference ::= '%' Name ';'[VC: Entity Declared] +[70] EntityDecl ::= GEDecl | PEDecl +[71] GEDecl ::= '' +[72] PEDecl ::= '' +[73] EntityDef ::= EntityValue | (ExternalID NDataDecl?) +[74] PEDef ::= EntityValue | ExternalID +[75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral +[76] NDataDecl ::= S 'NDATA' S Name[VC: Notation Declared] +[77] TextDecl ::= '' +[78] extParsedEnt ::= TextDecl? content +[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ) +[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*/* Encoding name contains only Latin characters */ +[82] NotationDecl ::= ''[VC: Unique Notation Name] +[83] PublicID ::= 'PUBLIC' S PubidLiteral \ No newline at end of file diff --git a/res/xpath1_0.grammar b/res/xpath1_0.grammar new file mode 100644 index 0000000..12e37f8 --- /dev/null +++ b/res/xpath1_0.grammar @@ -0,0 +1,80 @@ +/* + An XPath 1.0 grammar derived from the XPath 1.0 Specification: + + http://www.w3.org/TR/xpath + + + + NOTE-TO-SELF: to avoid infinite recursion, I had to eliminate this production: + + abbreviatedRelativeLocationPath = relativeLocationPath '//' step; + + and therefore remove `abbreviatedRelativeLocationPath` from `relativeLocationPath` which changed from + + relativeLocationPath = step ('/' step)* | abbreviatedRelativeLocationPath; + + to: + + relativeLocationPath = '//'? step ('/' step)*; + + +*/ + +@start = expr; + +@symbols = '//' '..' '!=' '::' '<=' '>='; + +@wordState = '_'; +@wordChars = '_' '.' '-'; + +@numberState = '.'; // numbers may start with dot +@allowsTrailingDot = YES; // numbers may end with dot +@symbolState = '+' '-'; // numbers may not start with a plus or minus sign. they're actually unary operators +@allowsScientificNotation = NO; // exponents not allowed +@allowsOctalNotation = NO; // octal not allowed +@allowsHexidecimalNotation = NO; // hex not allowed + + +expr = orExpr; + orExpr = andExpr ('or' andExpr)*; + andExpr = equalityExpr ('and' equalityExpr)*; + equalityExpr = relationalExpr (('=' | '!=') relationalExpr)*; + relationalExpr = additiveExpr (('<' | '>' | '<=' | '>=') additiveExpr)*; + additiveExpr = multiplicativeExpr (('+' | '-') multiplicativeExpr)*; + multiplicativeExpr = unaryExpr ((multiplyOperator | 'div' | 'mod') unaryExpr)*; + multiplyOperator = '*'; + unaryExpr = '-'* unionExpr; + unionExpr = pathExpr ('|' pathExpr)*; + + +pathExpr = locationPath | filterExpr (('/'| '//') relativeLocationPath)?; + locationPath = relativeLocationPath | absoluteLocationPath; + relativeLocationPath = '//'? step ('/' step)*; + absoluteLocationPath = '/' relativeLocationPath? | abbreviatedAbsoluteLocationPath; + abbreviatedAbsoluteLocationPath = '//' relativeLocationPath; + + filterExpr = primaryExpr predicate*; + primaryExpr = variableReference | literal | number | functionCall | '(' expr ')'; + variableReference = '$' qName; // note whitespace is not allowed here. also qName is optional + literal = QuotedString; + number = Number; + functionCall = functionName '(' (argument (',' argument)* )? ')'; + functionName = qName - nodeType; + qName = (prefix ':')? localPart; + prefix = ncName; + localPart = ncName; + ncName = Word; + argument = expr; + predicate = '[' predicateExpr ']'; + predicateExpr = expr; + + + step = axisSpecifier nodeTest predicate* | abbreviatedStep; + axisSpecifier = axisName '::' | abbreviatedAxisSpecifier; + axisName = 'ancestor' | 'ancestor-or-self' | 'attribute' | 'child' | 'descendant' | 'descendant-or-self' | 'following' | 'following-sibling' | 'namespace' | 'parent' | 'preceding' | 'preceding-sibling' | 'self'; + abbreviatedAxisSpecifier = '@'?; + nodeTest = nameTest | nodeType '(' ')' | 'processing-instruction' '(' literal ')'; + nameTest = '*' | ncName ':' '*' | qName; // note whitespace should not be allowed in second alt here + nodeType = 'comment' | 'text' | 'processing-instruction' | 'node'; + abbreviatedStep = '.' | '..'; + diff --git a/res/xpath_grammar.txt b/res/xpath_grammar.txt new file mode 100644 index 0000000..5aacfcf --- /dev/null +++ b/res/xpath_grammar.txt @@ -0,0 +1,88 @@ +[1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath +[2] AbsoluteLocationPath ::= '/' RelativeLocationPath? | AbbreviatedAbsoluteLocationPath +[3] RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | AbbreviatedRelativeLocationPath +[4] Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep +[5] AxisSpecifier ::= AxisName '::' | AbbreviatedAxisSpecifier +[6] AxisName ::= 'ancestor' + | 'ancestor-or-self' + | 'attribute' + | 'child' + | 'descendant' + | 'descendant-or-self' + | 'following' + | 'following-sibling' + | 'namespace' + | 'parent' + | 'preceding' + | 'preceding-sibling' + | 'self' +[7] NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' +[8] Predicate ::= '[' PredicateExpr ']' +[9] PredicateExpr ::= Expr +[10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath +[11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step +[12] AbbreviatedStep ::= '.' | '..' +[13] AbbreviatedAxisSpecifier ::= '@'? +[14] Expr ::= OrExpr +[15] PrimaryExpr ::= VariableReference + | '(' Expr ')' + | Literal + | Number + | FunctionCall +[16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' +[17] Argument ::= Expr +[18] UnionExpr ::= PathExpr | UnionExpr '|' PathExpr +[19] PathExpr ::= LocationPath + | FilterExpr + | FilterExpr '/' RelativeLocationPath + | FilterExpr '//' RelativeLocationPath +[20] FilterExpr ::= PrimaryExpr | FilterExpr Predicate +[21] OrExpr ::= AndExpr | OrExpr 'or' AndExpr +[22] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr +[23] EqualityExpr ::= RelationalExpr + | EqualityExpr '=' RelationalExpr + | EqualityExpr '!=' RelationalExpr +[24] RelationalExpr ::= AdditiveExpr + | RelationalExpr '<' AdditiveExpr + | RelationalExpr '>' AdditiveExpr + | RelationalExpr '<=' AdditiveExpr + | RelationalExpr '>=' AdditiveExpr +[25] AdditiveExpr ::= MultiplicativeExpr + | AdditiveExpr '+' MultiplicativeExpr + | AdditiveExpr '-' MultiplicativeExpr +[26] MultiplicativeExpr ::= UnaryExpr + | MultiplicativeExpr MultiplyOperator UnaryExpr + | MultiplicativeExpr 'div' UnaryExpr + | MultiplicativeExpr 'mod' UnaryExpr +[27] UnaryExpr ::= UnionExpr + | '-' UnaryExpr + +[28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' + | NameTest + | NodeType + | Operator + | FunctionName + | AxisName + | Literal + | Number + | VariableReference +[29] Literal ::= '"' [^"]* '"' + | "'" [^']* "'" +[30] Number ::= Digits ('.' Digits?)? + | '.' Digits +[31] Digits ::= [0-9]+ +[32] Operator ::= OperatorName + | MultiplyOperator + | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' +[33] OperatorName ::= 'and' | 'or' | 'mod' | 'div' +[34] MultiplyOperator ::= '*' +[35] FunctionName ::= QName - NodeType +[36] VariableReference ::= '$' QName +[37] NameTest ::= '*' + | NCName ':' '*' + | QName +[38] NodeType ::= 'comment' + | 'text' + | 'processing-instruction' + | 'node' +[39] ExprWhitespace ::= S \ No newline at end of file diff --git a/res/yahoo-small.json b/res/yahoo-small.json new file mode 100755 index 0000000..210bf96 --- /dev/null +++ b/res/yahoo-small.json @@ -0,0 +1,18 @@ +{"name": "Yahoo!", + "permalink": "yahoo", + "homepage_url": "http://www.yahoo.com", + "blog_url": "http://yodel.yahoo.com/", + "blog_feed_url": "http://ycorpblog.com/feed/", + "category_code": "web", + "number_of_employees": 13600, + "founded_year": 1994, + "founded_month": null, + "founded_day": null, + "deadpooled_year": null, + "deadpooled_month": null, + "deadpooled_day": null, + "deadpooled_url": null, + "tag_list": "search, portal, webmail, photos", + "email_address": "", + "phone_number": "(408) 349-3300" +} \ No newline at end of file diff --git a/res/yahoo.json b/res/yahoo.json new file mode 100644 index 0000000..aab012a --- /dev/null +++ b/res/yahoo.json @@ -0,0 +1,370 @@ +{"name": "Yahoo!", + "permalink": "yahoo", + "homepage_url": "http://www.yahoo.com", + "blog_url": "http://yodel.yahoo.com/", + "blog_feed_url": "http://ycorpblog.com/feed/", + "category_code": "web", + "number_of_employees": 13600, + "founded_year": 1994, + "founded_month": null, + "founded_day": null, + "deadpooled_year": null, + "deadpooled_month": null, + "deadpooled_day": null, + "deadpooled_url": null, + "tag_list": "search, portal, webmail, photos", + "email_address": "", + "phone_number": "(408) 349-3300", + "overview": "Yahoo was founded in 1994 by Stanford Ph.D. students David Filo and Jerry Yang. It has since evolved into a major internet brand with search, content verticals, and other web services.", + "image": + {"available_sizes": + [[[150, + 37], + "assets/images/resized/0001/0836/10836v1-max-250x150.png"], + [[200, + 50], + "assets/images/resized/0001/0836/10836v1-max-250x250.png"], + [[200, + 50], + "assets/images/resized/0001/0836/10836v1-max-450x450.png"]], + "attribution": null}, + "products": + [{"name": "Yahoo.com", + "permalink": "yahoo-com"}, + {"name": "Yahoo! Mail", + "permalink": "yahoo-mail"}, + {"name": "Yahoo! Search", + "permalink": "yahoo-search"}, + {"name": "Yahoo! Directory", + "permalink": "yahoo-directory"}, + {"name": "Yahoo! Finance", + "permalink": "yahoo-finance"}, + {"name": "My Yahoo", + "permalink": "my-yahoo"}, + {"name": "Yahoo! News", + "permalink": "yahoo-news"}, + {"name": "Yahoo! Groups", + "permalink": "yahoo-groups"}, + {"name": "Yahoo! Messenger", + "permalink": "yahoo-messenger"}, + {"name": "Yahoo! Games", + "permalink": "yahoo-games"}, + {"name": "Yahoo! People Search", + "permalink": "yahoo-people-search"}, + {"name": "Yahoo! Movies", + "permalink": "yahoo-movies"}, + {"name": "Yahoo! Weather", + "permalink": "yahoo-weather"}, + {"name": "Yahoo! Video", + "permalink": "yahoo-video"}, + {"name": "Yahoo! Music", + "permalink": "yahoo-music"}, + {"name": "Yahoo! Sports", + "permalink": "yahoo-sports"}, + {"name": "Yahoo! Maps", + "permalink": "yahoo-maps"}, + {"name": "Yahoo! Auctions", + "permalink": "yahoo-auctions"}, + {"name": "Yahoo! Widgets", + "permalink": "yahoo-widgets"}, + {"name": "Yahoo! Shopping", + "permalink": "yahoo-shopping"}, + {"name": "Yahoo! Real Estate", + "permalink": "yahoo-real-estate"}, + {"name": "Yahoo! Travel", + "permalink": "yahoo-travel"}, + {"name": "Yahoo! Classifieds", + "permalink": "yahoo-classifieds"}, + {"name": "Yahoo! Answers", + "permalink": "yahoo-answers"}, + {"name": "Yahoo! Mobile", + "permalink": "yahoo-mobile"}, + {"name": "Yahoo! Buzz", + "permalink": "yahoo-buzz"}, + {"name": "Yahoo! Open Search Platform", + "permalink": "yahoo-open-search-platform"}, + {"name": "Fire Eagle", + "permalink": "fireeagle"}, + {"name": "Shine", + "permalink": "shine"}, + {"name": "Yahoo! Shortcuts", + "permalink": "yahoo-shortcuts"}], + "competitions": + [{"competitor": + {"name": "Google", + "permalink": "google"}}, + {"competitor": + {"name": "seesmic", + "permalink": "seesmic"}}, + {"competitor": + {"name": "BricaBox", + "permalink": "bricabox"}}, + {"competitor": + {"name": "Clickpass", + "permalink": "clickpass"}}, + {"competitor": + {"name": "Tencent", + "permalink": "tencent"}}, + {"competitor": + {"name": "Hurdan", + "permalink": "better-searcher"}}, + {"competitor": + {"name": "Powerset", + "permalink": "powerset"}}, + {"competitor": + {"name": "Baidu", + "permalink": "baidu"}}, + {"competitor": + {"name": "Zenbe", + "permalink": "zenbe"}}, + {"competitor": + {"name": "Yandex", + "permalink": "yandex"}}, + {"competitor": + {"name": "Placebase", + "permalink": "placebase"}}, + {"competitor": + {"name": "AOL", + "permalink": "aol"}}], + "providerships": + [{"title": "", + "is_past": false, + "provider": + {"name": "OutCast Communications", + "permalink": "outcast-communications"}}, + {"title": "Investment Banking", + "is_past": null, + "provider": + {"name": "Moelis \u0026 Company", + "permalink": "moelis-company"}}, + {"title": "Public Relations", + "is_past": false, + "provider": + {"name": "Powerscourt", + "permalink": "powerscourt"}}], + "funding_rounds": + [], + "investments": + [{"funding_round": + {"round_code": "c", + "source_url": "http://sanjose.bizjournals.com/sanjose/stories/2004/05/24/daily3.html", + "source_description": "Plaxo connects to more funding", + "raised_amount": 7000000.0, + "raised_currency_code": "USD", + "funded_year": 2004, + "funded_month": 4, + "funded_day": 1, + "company": + {"name": "Plaxo", + "permalink": "plaxo"}}}, + {"funding_round": + {"round_code": "b", + "source_url": "http://www.techcrunch.com/2007/08/21/vlingo-voice-enable-any-mobile-application/", + "source_description": "", + "raised_amount": 20000000.0, + "raised_currency_code": "USD", + "funded_year": 2008, + "funded_month": 4, + "funded_day": 2, + "company": + {"name": "Vlingo", + "permalink": "vlingo"}}}, + {"funding_round": + {"round_code": "b", + "source_url": "http://www.paidcontent.org/entry/419-india-deals-ebay-sells-stake-in-indian-ops-bharatmatrimony-gets-2175-mi/", + "source_description": "India Deals: eBay Sells Stake In Indian Ops; Bharatmatrimony Gets $11.75 Million From Yahoo \u0026 Others", + "raised_amount": 11750000.0, + "raised_currency_code": "USD", + "funded_year": 2008, + "funded_month": 2, + "funded_day": 5, + "company": + {"name": "Bharat Matrimony", + "permalink": "bharat-matrimony"}}}], + "acquisition": null, + "acquisitions": + [{"price_amount": null, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 12, + "acquired_day": 1, + "company": + {"name": "delicious", + "permalink": "delicious"}}, + {"price_amount": 1000000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 8, + "acquired_day": 1, + "company": + {"name": "Alibaba", + "permalink": "alibaba"}}, + {"price_amount": 160000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2004, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "Musicmatch", + "permalink": "musicmatch"}}, + {"price_amount": 350000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2007, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "Zimbra", + "permalink": "zimbra"}}, + {"price_amount": 670000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2004, + "acquired_month": 4, + "acquired_day": 1, + "company": + {"name": "Kelkoo", + "permalink": "kelkoo"}}, + {"price_amount": 35000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://arstechnica.com/news.ars/post/20050324-4732.html", + "source_description": "", + "acquired_year": 2005, + "acquired_month": 3, + "acquired_day": 1, + "company": + {"name": "Flickr", + "permalink": "flickr"}}, + {"price_amount": 1000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 10, + "acquired_day": 1, + "company": + {"name": "Upcoming", + "permalink": "upcoming"}}, + {"price_amount": 300000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2007, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "BlueLithium", + "permalink": "bluelithium"}}, + {"price_amount": 160000000.0, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2008/02/12/yahoo-confirms-maven-networks-acquisition/", + "source_description": "Yahoo Confirms Maven Networks Acquisition", + "acquired_year": 2008, + "acquired_month": 1, + "acquired_day": 31, + "company": + {"name": "Maven Networks", + "permalink": "maven-networks"}}, + {"price_amount": 800000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.techcrunch.com/2007/04/29/panama-not-enough-to-battle-google-yahoo-acquires-rightmedia/", + "source_description": "Panama Not Enough To Battle Google: Yahoo Acquires RightMedia", + "acquired_year": 2007, + "acquired_month": 4, + "acquired_day": null, + "company": + {"name": "Right Media", + "permalink": "right-media"}}, + {"price_amount": 10000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.techcrunch.com/2007/01/08/yahoo-buys-mybloglog-no-they-didnt-wait-yes/", + "source_description": "", + "acquired_year": 2007, + "acquired_month": 1, + "acquired_day": null, + "company": + {"name": "MyBlogLog", + "permalink": "mybloglog"}}, + {"price_amount": 40000000.0, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2008/02/04/yahoo-acquires-israeli-foxytunes/", + "source_description": "TechCrunch", + "acquired_year": 2008, + "acquired_month": 2, + "acquired_day": 4, + "company": + {"name": "FoxyTunes", + "permalink": "foxytunes"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2006/09/27/yahoo-has-acquired-jumpcut/", + "source_description": "Yahoo! has acquired Jumpcut", + "acquired_year": 2006, + "acquired_month": 10, + "acquired_day": 2, + "company": + {"name": "Jumpcut", + "permalink": "jumpcut"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.ysearchblog.com/archives/000581.html", + "source_description": "Inquisitor Joins the Yahoo! Search Team", + "acquired_year": 2008, + "acquired_month": 5, + "acquired_day": 9, + "company": + {"name": "Inquisitor", + "permalink": "inquisitor"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.thealarmclock.com/mt/archives/2008/04/yahoo_buys_ad_a.html", + "source_description": "Yahoo! Buys Ad Analytics Firm Indextools", + "acquired_year": 2008, + "acquired_month": 4, + "acquired_day": 10, + "company": + {"name": "Indextools", + "permalink": "indextools"}}], + "offices": + [{"description": null, + "address1": "701 First Avenue", + "address2": "", + "zip_code": "94089", + "city": "Sunnyvale", + "state_code": "CA", + "country_code": "USA", + "latitude": 37.418531, + "longitude": -122.025485}], + "milestones": + [], + "ipo": + {"valuation_amount": null, + "valuation_currency_code": "USD", + "pub_year": 1996, + "pub_month": 4, + "pub_day": 12, + "stock_symbol": "YHOO"} +} \ No newline at end of file diff --git a/res/yahoo_with_comments.json b/res/yahoo_with_comments.json new file mode 100644 index 0000000..9d11005 --- /dev/null +++ b/res/yahoo_with_comments.json @@ -0,0 +1,370 @@ +{"name": "Yahoo!" /* foo bar */ , + "permalink": "yahoo", + "homepage_url": "http://www.yahoo.com", + "blog_url": "http://yodel.yahoo.com/", + "blog_feed_url": "http://ycorpblog.com/feed/", + "category_code": "web", + "number_of_employees": 13600, + "founded_year": 1994, + "founded_month": null, + "founded_day": null, + "deadpooled_year": null, + "deadpooled_month": null, + "deadpooled_day": null, + "deadpooled_url": null, + "tag_list": "search, portal, webmail, photos", + "email_address": "", + "phone_number": "(408) 349-3300", + "overview": "Yahoo was founded in 1994 by Stanford Ph.D. students David Filo and Jerry Yang. It has since evolved into a major internet brand with search, content verticals, and other web services.", + "image": + {"available_sizes": + [[[150, + 37], + "assets/images/resized/0001/0836/10836v1-max-250x150.png"], + [[200, + 50], + "assets/images/resized/0001/0836/10836v1-max-250x250.png"], + [[200, + 50], + "assets/images/resized/0001/0836/10836v1-max-450x450.png"]], + "attribution": null}, + "products": + [{"name": "Yahoo.com", + "permalink": "yahoo-com"}, + {"name": "Yahoo! Mail", + "permalink": "yahoo-mail"}, + {"name": "Yahoo! Search", + "permalink": "yahoo-search"}, + {"name": "Yahoo! Directory", + "permalink": "yahoo-directory"}, + {"name": "Yahoo! Finance", + "permalink": "yahoo-finance"}, + {"name": "My Yahoo", + "permalink": "my-yahoo"}, + {"name": "Yahoo! News", + "permalink": "yahoo-news"}, + {"name": "Yahoo! Groups", + "permalink": "yahoo-groups"}, + {"name": "Yahoo! Messenger", + "permalink": "yahoo-messenger"}, + {"name": "Yahoo! Games", + "permalink": "yahoo-games"}, + {"name": "Yahoo! People Search", + "permalink": "yahoo-people-search"}, + {"name": "Yahoo! Movies", + "permalink": "yahoo-movies"}, + {"name": "Yahoo! Weather", + "permalink": "yahoo-weather"}, + {"name": "Yahoo! Video", + "permalink": "yahoo-video"}, + {"name": "Yahoo! Music", + "permalink": "yahoo-music"}, + {"name": "Yahoo! Sports", + "permalink": "yahoo-sports"}, + {"name": "Yahoo! Maps", + "permalink": "yahoo-maps"}, + {"name": "Yahoo! Auctions", + "permalink": "yahoo-auctions"}, + {"name": "Yahoo! Widgets", + "permalink": "yahoo-widgets"}, + {"name": "Yahoo! Shopping", + "permalink": "yahoo-shopping"}, + {"name": "Yahoo! Real Estate", + "permalink": "yahoo-real-estate"}, + {"name": "Yahoo! Travel", + "permalink": "yahoo-travel"}, + {"name": "Yahoo! Classifieds", + "permalink": "yahoo-classifieds"}, + {"name": "Yahoo! Answers", + "permalink": "yahoo-answers"}, + {"name": "Yahoo! Mobile", + "permalink": "yahoo-mobile"}, + {"name": "Yahoo! Buzz", + "permalink": "yahoo-buzz"}, + {"name": "Yahoo! Open Search Platform", + "permalink": "yahoo-open-search-platform"}, + {"name": "Fire Eagle", + "permalink": "fireeagle"}, + {"name": "Shine", + "permalink": "shine"}, + {"name": "Yahoo! Shortcuts", + "permalink": "yahoo-shortcuts"}], + "competitions": + [{"competitor": + {"name": "Google", + "permalink": "google"}}, + {"competitor": + {"name": "seesmic", + "permalink": "seesmic"}}, + {"competitor": + {"name": "BricaBox", + "permalink": "bricabox"}}, + {"competitor": + {"name": "Clickpass", + "permalink": "clickpass"}}, + {"competitor": + {"name": "Tencent", + "permalink": "tencent"}}, + {"competitor": + {"name": "Hurdan", + "permalink": "better-searcher"}}, + {"competitor": + {"name": "Powerset", + "permalink": "powerset"}}, + {"competitor": + {"name": "Baidu", + "permalink": "baidu"}}, + {"competitor": + {"name": "Zenbe", + "permalink": "zenbe"}}, + {"competitor": + {"name": "Yandex", + "permalink": "yandex"}}, + {"competitor": + {"name": "Placebase", + "permalink": "placebase"}}, + {"competitor": + {"name": "AOL", + "permalink": "aol"}}], + "providerships": + [{"title": "", + "is_past": false, + "provider": + {"name": "OutCast Communications", + "permalink": "outcast-communications"}}, + {"title": "Investment Banking", + "is_past": null, + "provider": + {"name": "Moelis \u0026 Company", + "permalink": "moelis-company"}}, + {"title": "Public Relations", + "is_past": false, + "provider": + {"name": "Powerscourt", + "permalink": "powerscourt"}}], + "funding_rounds": + [], + "investments": + [{"funding_round": + {"round_code": "c", + "source_url": "http://sanjose.bizjournals.com/sanjose/stories/2004/05/24/daily3.html", + "source_description": "Plaxo connects to more funding", + "raised_amount": 7000000.0, + "raised_currency_code": "USD", + "funded_year": 2004, + "funded_month": 4, + "funded_day": 1, + "company": + {"name": "Plaxo", + "permalink": "plaxo"}}}, + {"funding_round": + {"round_code": "b", + "source_url": "http://www.techcrunch.com/2007/08/21/vlingo-voice-enable-any-mobile-application/", + "source_description": "", + "raised_amount": 20000000.0, + "raised_currency_code": "USD", + "funded_year": 2008, + "funded_month": 4, + "funded_day": 2, + "company": + {"name": "Vlingo", + "permalink": "vlingo"}}}, + {"funding_round": + {"round_code": "b", + "source_url": "http://www.paidcontent.org/entry/419-india-deals-ebay-sells-stake-in-indian-ops-bharatmatrimony-gets-2175-mi/", + "source_description": "India Deals: eBay Sells Stake In Indian Ops; Bharatmatrimony Gets $11.75 Million From Yahoo \u0026 Others", + "raised_amount": 11750000.0, + "raised_currency_code": "USD", + "funded_year": 2008, + "funded_month": 2, + "funded_day": 5, + "company": + {"name": "Bharat Matrimony", + "permalink": "bharat-matrimony"}}}], + "acquisition": null, + "acquisitions": + [{"price_amount": null, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 12, + "acquired_day": 1, + "company": + {"name": "delicious", + "permalink": "delicious"}}, + {"price_amount": 1000000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 8, + "acquired_day": 1, + "company": + {"name": "Alibaba", + "permalink": "alibaba"}}, + {"price_amount": 160000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2004, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "Musicmatch", + "permalink": "musicmatch"}}, + {"price_amount": 350000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2007, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "Zimbra", + "permalink": "zimbra"}}, + {"price_amount": 670000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2004, + "acquired_month": 4, + "acquired_day": 1, + "company": + {"name": "Kelkoo", + "permalink": "kelkoo"}}, + {"price_amount": 35000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://arstechnica.com/news.ars/post/20050324-4732.html", + "source_description": "", + "acquired_year": 2005, + "acquired_month": 3, + "acquired_day": 1, + "company": + {"name": "Flickr", + "permalink": "flickr"}}, + {"price_amount": 1000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2005, + "acquired_month": 10, + "acquired_day": 1, + "company": + {"name": "Upcoming", + "permalink": "upcoming"}}, + {"price_amount": 300000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": null, + "source_description": null, + "acquired_year": 2007, + "acquired_month": 9, + "acquired_day": 1, + "company": + {"name": "BlueLithium", + "permalink": "bluelithium"}}, + {"price_amount": 160000000.0, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2008/02/12/yahoo-confirms-maven-networks-acquisition/", + "source_description": "Yahoo Confirms Maven Networks Acquisition", + "acquired_year": 2008, + "acquired_month": 1, + "acquired_day": 31, + "company": + {"name": "Maven Networks", + "permalink": "maven-networks"}}, + {"price_amount": 800000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.techcrunch.com/2007/04/29/panama-not-enough-to-battle-google-yahoo-acquires-rightmedia/", + "source_description": "Panama Not Enough To Battle Google: Yahoo Acquires RightMedia", + "acquired_year": 2007, + "acquired_month": 4, + "acquired_day": null, + "company": + {"name": "Right Media", + "permalink": "right-media"}}, + {"price_amount": 10000000.0, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.techcrunch.com/2007/01/08/yahoo-buys-mybloglog-no-they-didnt-wait-yes/", + "source_description": "", + "acquired_year": 2007, + "acquired_month": 1, + "acquired_day": null, + "company": + {"name": "MyBlogLog", + "permalink": "mybloglog"}}, + {"price_amount": 40000000.0, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2008/02/04/yahoo-acquires-israeli-foxytunes/", + "source_description": "TechCrunch", + "acquired_year": 2008, + "acquired_month": 2, + "acquired_day": 4, + "company": + {"name": "FoxyTunes", + "permalink": "foxytunes"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.techcrunch.com/2006/09/27/yahoo-has-acquired-jumpcut/", + "source_description": "Yahoo! has acquired Jumpcut", + "acquired_year": 2006, + "acquired_month": 10, + "acquired_day": 2, + "company": + {"name": "Jumpcut", + "permalink": "jumpcut"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": null, + "source_url": "http://www.ysearchblog.com/archives/000581.html", + "source_description": "Inquisitor Joins the Yahoo! Search Team", + "acquired_year": 2008, + "acquired_month": 5, + "acquired_day": 9, + "company": + {"name": "Inquisitor", + "permalink": "inquisitor"}}, + {"price_amount": null, + "price_currency_code": "USD", + "term_code": "cash", + "source_url": "http://www.thealarmclock.com/mt/archives/2008/04/yahoo_buys_ad_a.html", + "source_description": "Yahoo! Buys Ad Analytics Firm Indextools", + "acquired_year": 2008, + "acquired_month": 4, + "acquired_day": 10, + "company": + {"name": "Indextools", + "permalink": "indextools"}}], + "offices": + [{"description": null, + "address1": "701 First Avenue", + "address2": "", + "zip_code": "94089", + "city": "Sunnyvale", + "state_code": "CA", + "country_code": "USA", + "latitude": 37.418531, + "longitude": -122.025485}], + "milestones": + [], + "ipo": + {"valuation_amount": null, + "valuation_currency_code": "USD", + "pub_year": 1996, + "pub_month": 4, + "pub_day": 12, + "stock_symbol": "YHOO"} +} \ No newline at end of file diff --git a/src/.svn/all-wcprops b/src/.svn/all-wcprops new file mode 100644 index 0000000..71c835b --- /dev/null +++ b/src/.svn/all-wcprops @@ -0,0 +1,347 @@ +K 25 +svn:wc:ra_dav:version-url +V 28 +/svn/!svn/ver/1410/trunk/src +END +NSString+ParseKitAdditions.m +K 25 +svn:wc:ra_dav:version-url +V 57 +/svn/!svn/ver/1404/trunk/src/NSString+ParseKitAdditions.m +END +PKDifference.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1398/trunk/src/PKDifference.m +END +PKCharacterAssembly.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1405/trunk/src/PKCharacterAssembly.m +END +PKWhitespace.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1115/trunk/src/PKWhitespace.m +END +PKParser.m +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/1404/trunk/src/PKParser.m +END +PKLiteral.m +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1404/trunk/src/PKLiteral.m +END +PKWhitespaceState.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1405/trunk/src/PKWhitespaceState.m +END +PKEmpty.m +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/1171/trunk/src/PKEmpty.m +END +PKLetter.m +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/1171/trunk/src/PKLetter.m +END +RegexKitLite.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/862/trunk/src/RegexKitLite.h +END +PKTokenArraySource.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1171/trunk/src/PKTokenArraySource.m +END +PKDigit.m +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/1170/trunk/src/PKDigit.m +END +PKReader.m +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/1404/trunk/src/PKReader.m +END +RegexKitLite.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1404/trunk/src/RegexKitLite.m +END +PKSymbol.m +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/1404/trunk/src/PKSymbol.m +END +PKIntersection.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1398/trunk/src/PKIntersection.m +END +PKCaseInsensitiveLiteral.m +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1170/trunk/src/PKCaseInsensitiveLiteral.m +END +PKTokenizer.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1400/trunk/src/PKTokenizer.m +END +PKSymbolNode.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1170/trunk/src/PKSymbolNode.m +END +PKTokenizerState.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1213/trunk/src/PKTokenizerState.m +END +PKWordState.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1405/trunk/src/PKWordState.m +END +PKPattern.m +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1404/trunk/src/PKPattern.m +END +PKSymbolRootNode.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1404/trunk/src/PKSymbolRootNode.m +END +PKAssembly.m +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1405/trunk/src/PKAssembly.m +END +PKAlternation.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1225/trunk/src/PKAlternation.m +END +PKToken.m +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/1170/trunk/src/PKToken.m +END +PKTrackException.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1171/trunk/src/PKTrackException.m +END +PKUppercaseWord.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1404/trunk/src/PKUppercaseWord.m +END +PKSpecificChar.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1170/trunk/src/PKSpecificChar.m +END +PKQuotedString.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1170/trunk/src/PKQuotedString.m +END +PKDelimitState.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1404/trunk/src/PKDelimitState.m +END +PKNumber.m +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/1177/trunk/src/PKNumber.m +END +PKNumberState.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1252/trunk/src/PKNumberState.m +END +NSArray+ParseKitAdditions.h +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1170/trunk/src/NSArray+ParseKitAdditions.h +END +PKQuoteState.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1170/trunk/src/PKQuoteState.m +END +PKGrammarParser.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1275/trunk/src/PKGrammarParser.h +END +NSArray+ParseKitAdditions.m +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1405/trunk/src/NSArray+ParseKitAdditions.m +END +PKComment.m +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1170/trunk/src/PKComment.m +END +PKCommentState.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1409/trunk/src/PKCommentState.m +END +PKGrammarParser.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1276/trunk/src/PKGrammarParser.m +END +PKNegation.m +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1152/trunk/src/PKNegation.m +END +PKTrack.m +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/1405/trunk/src/PKTrack.m +END +PKSymbolState.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1410/trunk/src/PKSymbolState.m +END +PKCollectionParser.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1225/trunk/src/PKCollectionParser.m +END +PKSequence.m +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1405/trunk/src/PKSequence.m +END +PKTerminal.m +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1403/trunk/src/PKTerminal.m +END +PKWord.m +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/1170/trunk/src/PKWord.m +END +PKSingleLineCommentState.m +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1404/trunk/src/PKSingleLineCommentState.m +END +PKChar.m +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/1170/trunk/src/PKChar.m +END +PKTokenAssembly.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1405/trunk/src/PKTokenAssembly.m +END +PKLowercaseWord.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1404/trunk/src/PKLowercaseWord.m +END +PKRepetition.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1405/trunk/src/PKRepetition.m +END +NSString+ParseKitAdditions.h +K 25 +svn:wc:ra_dav:version-url +V 57 +/svn/!svn/ver/1171/trunk/src/NSString+ParseKitAdditions.h +END +PKParserFactory.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1405/trunk/src/PKParserFactory.m +END +PKMultiLineCommentState.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1404/trunk/src/PKMultiLineCommentState.m +END +PKDelimitedString.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1404/trunk/src/PKDelimitedString.m +END +PKAny.m +K 25 +svn:wc:ra_dav:version-url +V 36 +/svn/!svn/ver/1178/trunk/src/PKAny.m +END diff --git a/src/.svn/entries b/src/.svn/entries new file mode 100644 index 0000000..0c268a7 --- /dev/null +++ b/src/.svn/entries @@ -0,0 +1,1966 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/src +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-11-06T01:42:40.664388Z +1410 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +NSString+ParseKitAdditions.m +file + + + + +2009-11-13T07:14:28.000000Z +5d802dc05031ec359341f5c3395c8263 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +766 + +PKDifference.m +file + + + + +2009-09-22T06:22:42.000000Z +d346a0251a0f5ecbaa3e167b088ae91d +2009-09-22T06:46:43.186228Z +1398 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2145 + +PKCharacterAssembly.m +file + + + + +2009-11-13T07:14:28.000000Z +035c20938a350b837060af3f448b41b0 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2447 + +PKWhitespace.m +file + + + + +2009-06-30T06:13:14.000000Z +660d60e2b231f6b0d83278f19d1089a5 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +411 + +PKParser.m +file + + + + +2009-11-13T07:14:28.000000Z +7f5c0f95b0d5600002c55766b5daa51f +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4554 + +PKLiteral.m +file + + + + +2009-11-13T07:14:29.000000Z +2f177fff66e256f4577e7007ef0db940 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1219 + +PKWhitespaceState.m +file + + + + +2009-11-13T07:14:29.000000Z +5a1e3bdb5968e3e77c44c320184ffc83 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2643 + +PKEmpty.m +file + + + + +2009-07-03T19:31:18.000000Z +f06bf77fcee5905d4d623426f14a12d5 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +460 + +PKLetter.m +file + + + + +2009-07-03T19:31:16.000000Z +0467837ae9f7c846694708d8f874384b +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +398 + +RegexKitLite.h +file + + + + +2009-05-03T00:29:43.000000Z +ae5b46f2e4026b75c043053e405a3a6a +2009-06-01T01:34:02.930802Z +862 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +10196 + +PKDigit.m +file + + + + +2009-07-03T19:31:15.000000Z +148d857ec471e3756986c1d71d7625d2 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +394 + +PKTokenArraySource.m +file + + + + +2009-07-03T19:42:56.000000Z +bb44ba94ee34d93389909092d7af9f87 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1660 + +PKReader.m +file + + + + +2009-11-13T07:14:29.000000Z +fa6d0417a05dfa2c6f8fa85e1d635150 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1056 + +PKSymbol.m +file + + + + +2009-11-13T07:14:29.000000Z +f29733fcdd1d798bca1bf6ac167a7d8f +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1586 + +RegexKitLite.m +file + + + + +2009-11-13T07:14:29.000000Z +b919a5f7a23d6baebd96f532427de327 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +111385 + +PKIntersection.m +file + + + + +2009-09-22T06:21:51.000000Z +e34af22e50502e583d655127a9d49186 +2009-09-22T06:46:43.186228Z +1398 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1723 + +PKCaseInsensitiveLiteral.m +file + + + + +2009-07-03T19:31:15.000000Z +c384f4ca66162d1a8d78b439d3d776b7 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +450 + +PKTokenizer.m +file + + + + +2009-09-26T03:40:29.000000Z +d5dd2cae79fa03616ef8953ef31257fc +2009-09-26T03:50:36.795525Z +1400 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +7019 + +PKTokenizerState.m +file + + + + +2009-07-13T05:29:20.000000Z +a33121d90a0fe7f507b61c09e562b752 +2009-07-12T23:22:41.730758Z +1213 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2703 + +PKSymbolNode.m +file + + + + +2009-07-03T19:42:56.000000Z +d9d8824ece419e38d2c76b898f7886ed +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2069 + +PKWordState.m +file + + + + +2009-11-13T07:14:29.000000Z +3c1a42d8dddd4d0040b7c6bd32d3d502 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +3133 + +PKPattern.m +file + + + + +2009-11-13T07:14:29.000000Z +1a6a3d57fe08b7e809170f0e1fa1854a +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1015 + +PKAssembly.m +file + + + + +2009-11-13T07:14:28.000000Z +4ea581f12c55911ba898e00c2aa3af0e +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4996 + +PKSymbolRootNode.m +file + + + + +2009-11-13T07:14:29.000000Z +d005e03935581e79e8d878e40efc9424 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4368 + +PKToken.m +file + + + + +2009-07-03T19:42:56.000000Z +258a174923071fe022286c6ba0344cfd +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +5240 + +PKAlternation.m +file + + + + +2009-07-14T03:17:31.000000Z +3e5e481bbf6c40073fa372b259b02fdd +2009-07-14T03:32:39.769371Z +1225 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1057 + +PKUppercaseWord.m +file + + + + +2009-11-13T07:14:29.000000Z +ef05ad208e6e2cc8bd0a46931506347c +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +464 + +PKSpecificChar.m +file + + + + +2009-07-03T19:31:16.000000Z +2a91818aa10c4ac979cd0b6f45beadcb +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +626 + +PKTrackException.m +file + + + + +2009-07-03T19:31:18.000000Z +81391434739d55de9fbcfe5d1cf041ca +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +279 + +PKQuotedString.m +file + + + + +2009-07-03T19:31:14.000000Z +20e2d7d1ce0f72e28623d2013a22527e +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +431 + +PKDelimitState.m +file + + + + +2009-11-13T07:14:29.000000Z +4ea1de55442a1c9aca4f958b7cec7a90 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +6646 + +PKNumber.m +file + + + + +2009-07-03T22:05:22.000000Z +2c180d893d01cce39dc8883d79d0837f +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +400 + +PKNumberState.m +file + + + + +2009-07-20T00:14:56.000000Z +b9c939ec40e779fa9cbf4c6a134a401a +2009-07-20T00:15:49.775288Z +1252 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +6024 + +NSArray+ParseKitAdditions.h +file + + + + +2009-07-03T19:31:16.000000Z +b060603f004d407b06cda05530b21b0e +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +307 + +PKQuoteState.m +file + + + + +2009-07-03T19:42:56.000000Z +11b7ca1ea0db989b5f8916839280952e +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1238 + +PKGrammarParser.h +file + + + + +2009-08-06T04:02:04.000000Z +dbfc87a2410dc1aab9f85d320f756fec +2009-08-02T22:59:20.682429Z +1275 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3546 + +NSArray+ParseKitAdditions.m +file + + + + +2009-11-13T07:14:29.000000Z +94eae1412be9f1511129aeb165950ed3 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +575 + +PKComment.m +file + + + + +2009-07-03T19:31:15.000000Z +722d3d70383bb3046e7fd2667a834190 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +406 + +PKCommentState.m +file + + + + +2009-11-13T07:14:29.000000Z +d128cb12d367971ce3630cdf81de3f0e +2009-11-06T01:14:46.569140Z +1409 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +4196 + +PKGrammarParser.m +file + + + + +2009-08-06T04:02:04.000000Z +249e47f3e4bc9630d06ac16abfe28854 +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +21972 + +PKTrack.m +file + + + + +2009-11-13T07:14:28.000000Z +7b49792a547941214f6d1324fdcab5cc +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2474 + +PKNegation.m +file + + + + +2009-07-03T19:42:56.000000Z +7d53fe34fd243d12761108deb29046d7 +2009-07-03T03:31:46.326363Z +1152 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1314 + +PKSymbolState.m +file + + + + +2009-11-13T07:14:29.000000Z +7b6d72ea6215baa32543302587d0321c +2009-11-06T01:42:40.664388Z +1410 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2625 + +PKCollectionParser.m +file + + + + +2009-07-14T03:27:02.000000Z +1eee840b8123c8b63b814857d199db89 +2009-07-14T03:32:39.769371Z +1225 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2007 + +PKSequence.m +file + + + + +2009-11-13T07:14:29.000000Z +3483d760d9c39cf92a6e5c2c1df6782f +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1034 + +PKWord.m +file + + + + +2009-07-03T19:31:12.000000Z +fb533a93566e87ea6fb63a428c43d6f0 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +391 + +PKTerminal.m +file + + + + +2009-09-26T05:52:15.000000Z +5224feed13854fe6ff34454091b6b50d +2009-09-26T19:12:29.746961Z +1403 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1813 + +PKSingleLineCommentState.m +file + + + + +2009-11-13T07:14:29.000000Z +555abbb5014e293ded6c2503e25f12c6 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2341 + +PKChar.m +file + + + + +2009-07-03T19:31:15.000000Z +ee423bfcfbb21aa5c4b8ae001c3e758e +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +320 + +PKTokenAssembly.m +file + + + + +2009-11-13T07:14:29.000000Z +1d383db70f727d232516a3e5360bcdc1 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4257 + +PKLowercaseWord.m +file + + + + +2009-11-13T07:14:29.000000Z +6a0b11034a616262951715ff41835728 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +464 + +PKRepetition.m +file + + + + +2009-11-13T07:14:29.000000Z +7f2bb72595003f49123dd3020ee73684 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1453 + +NSString+ParseKitAdditions.h +file + + + + +2009-07-03T19:31:17.000000Z +7edce56b8eeb7c7d062702562961bdf0 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +276 + +PKParserFactory.m +file + + + + +2009-11-13T07:14:29.000000Z +57f6eb71488f2e8788c6e7d515a000fa +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +32473 + +PKMultiLineCommentState.m +file + + + + +2009-11-13T07:14:29.000000Z +ba9ecf7e58d5a5d9350cf00523036069 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +4034 + +PKDelimitedString.m +file + + + + +2009-11-13T07:14:29.000000Z +39e0d7dc6a1604338c37e30de626e6da +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1334 + +PKAny.m +file + + + + +2009-07-03T22:27:32.000000Z +01c6c4a2f249eba58ef8c0cb46f4683e +2009-07-03T22:28:26.763415Z +1178 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +380 + diff --git a/src/.svn/prop-base/PKAlternation.m.svn-base b/src/.svn/prop-base/PKAlternation.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKAlternation.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKAssembly.m.svn-base b/src/.svn/prop-base/PKAssembly.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKAssembly.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKCaseInsensitiveLiteral.m.svn-base b/src/.svn/prop-base/PKCaseInsensitiveLiteral.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKCaseInsensitiveLiteral.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKChar.m.svn-base b/src/.svn/prop-base/PKChar.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKChar.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKCharacterAssembly.m.svn-base b/src/.svn/prop-base/PKCharacterAssembly.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKCharacterAssembly.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKCollectionParser.m.svn-base b/src/.svn/prop-base/PKCollectionParser.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKCollectionParser.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKDigit.m.svn-base b/src/.svn/prop-base/PKDigit.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKDigit.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKEmpty.m.svn-base b/src/.svn/prop-base/PKEmpty.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKEmpty.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKLetter.m.svn-base b/src/.svn/prop-base/PKLetter.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKLetter.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKLiteral.m.svn-base b/src/.svn/prop-base/PKLiteral.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKLiteral.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKLowercaseWord.m.svn-base b/src/.svn/prop-base/PKLowercaseWord.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKLowercaseWord.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKNumberState.m.svn-base b/src/.svn/prop-base/PKNumberState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKNumberState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKParser.m.svn-base b/src/.svn/prop-base/PKParser.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKParser.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKParserFactory.m.svn-base b/src/.svn/prop-base/PKParserFactory.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKParserFactory.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKQuoteState.m.svn-base b/src/.svn/prop-base/PKQuoteState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKQuoteState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKQuotedString.m.svn-base b/src/.svn/prop-base/PKQuotedString.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKQuotedString.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKReader.m.svn-base b/src/.svn/prop-base/PKReader.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKReader.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKRepetition.m.svn-base b/src/.svn/prop-base/PKRepetition.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKRepetition.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKSequence.m.svn-base b/src/.svn/prop-base/PKSequence.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKSequence.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKSpecificChar.m.svn-base b/src/.svn/prop-base/PKSpecificChar.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKSpecificChar.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKSymbol.m.svn-base b/src/.svn/prop-base/PKSymbol.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKSymbol.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKSymbolNode.m.svn-base b/src/.svn/prop-base/PKSymbolNode.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKSymbolNode.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKSymbolRootNode.m.svn-base b/src/.svn/prop-base/PKSymbolRootNode.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKSymbolRootNode.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKSymbolState.m.svn-base b/src/.svn/prop-base/PKSymbolState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKSymbolState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKTerminal.m.svn-base b/src/.svn/prop-base/PKTerminal.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKTerminal.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKToken.m.svn-base b/src/.svn/prop-base/PKToken.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKToken.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKTokenArraySource.m.svn-base b/src/.svn/prop-base/PKTokenArraySource.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKTokenArraySource.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKTokenAssembly.m.svn-base b/src/.svn/prop-base/PKTokenAssembly.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKTokenAssembly.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKTokenizer.m.svn-base b/src/.svn/prop-base/PKTokenizer.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKTokenizer.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKTokenizerState.m.svn-base b/src/.svn/prop-base/PKTokenizerState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKTokenizerState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKTrack.m.svn-base b/src/.svn/prop-base/PKTrack.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKTrack.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKUppercaseWord.m.svn-base b/src/.svn/prop-base/PKUppercaseWord.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKUppercaseWord.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKWhitespaceState.m.svn-base b/src/.svn/prop-base/PKWhitespaceState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKWhitespaceState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKWord.m.svn-base b/src/.svn/prop-base/PKWord.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKWord.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/prop-base/PKWordState.m.svn-base b/src/.svn/prop-base/PKWordState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/PKWordState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/text-base/NSArray+ParseKitAdditions.h.svn-base b/src/.svn/text-base/NSArray+ParseKitAdditions.h.svn-base new file mode 100644 index 0000000..3d11f54 --- /dev/null +++ b/src/.svn/text-base/NSArray+ParseKitAdditions.h.svn-base @@ -0,0 +1,14 @@ +// +// NSArray+ParseKitAdditions.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface NSArray (ParseKitAdditions) +- (NSArray *)reversedArray; +- (NSMutableArray *)reversedMutableArray; +@end diff --git a/src/.svn/text-base/NSArray+ParseKitAdditions.m.svn-base b/src/.svn/text-base/NSArray+ParseKitAdditions.m.svn-base new file mode 100644 index 0000000..1399c35 --- /dev/null +++ b/src/.svn/text-base/NSArray+ParseKitAdditions.m.svn-base @@ -0,0 +1,26 @@ +// +// NSArray+ParseKitAdditions.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "NSArray+ParseKitAdditions.h" + +@implementation NSArray (ParseKitAdditions) + +- (NSArray *)reversedArray { + return [[[self reversedMutableArray] copy] autorelease]; +} + + +- (NSMutableArray *)reversedMutableArray { + NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]]; + for (id obj in [self reverseObjectEnumerator]) { + [result addObject:obj]; + } + return result; +} + +@end diff --git a/src/.svn/text-base/NSString+ParseKitAdditions.h.svn-base b/src/.svn/text-base/NSString+ParseKitAdditions.h.svn-base new file mode 100644 index 0000000..55d02a8 --- /dev/null +++ b/src/.svn/text-base/NSString+ParseKitAdditions.h.svn-base @@ -0,0 +1,13 @@ +// +// NSString+ParseKitAdditions.h +// ParseKit +// +// Created by Todd Ditchendorf on 11/5/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface NSString (ParseKitAdditions) +- (NSString *)stringByTrimmingQuotes; +@end diff --git a/src/.svn/text-base/NSString+ParseKitAdditions.m.svn-base b/src/.svn/text-base/NSString+ParseKitAdditions.m.svn-base new file mode 100644 index 0000000..304a432 --- /dev/null +++ b/src/.svn/text-base/NSString+ParseKitAdditions.m.svn-base @@ -0,0 +1,38 @@ +// +// NSString+ParseKitAdditions.m +// ParseKit +// +// Created by Todd Ditchendorf on 11/5/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "NSString+ParseKitAdditions.h" + +@implementation NSString (ParseKitAdditions) + +- (NSString *)stringByTrimmingQuotes { + NSUInteger len = [self length]; + + if (len < 2) { + return self; + } + + NSRange r = NSMakeRange(0, len); + + unichar c = [self characterAtIndex:0]; + if (!isalnum(c)) { + unichar quoteChar = c; + r.location = 1; + r.length -= 1; + + c = [self characterAtIndex:len - 1]; + if (c == quoteChar) { + r.length -= 1; + } + return [self substringWithRange:r]; + } else { + return self; + } +} + +@end diff --git a/src/.svn/text-base/PKAlternation.m.svn-base b/src/.svn/text-base/PKAlternation.m.svn-base new file mode 100644 index 0000000..73b1a93 --- /dev/null +++ b/src/.svn/text-base/PKAlternation.m.svn-base @@ -0,0 +1,48 @@ +// +// PKAlternation.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; +@end + +@implementation PKAlternation + ++ (id)alternation { + return [self alternationWithSubparsers:nil]; +} + + ++ (id)alternationWithSubparsers:(PKParser *)p1, ... { + va_list vargs; + va_start(vargs, p1); + PKAlternation *alt = [self collectionParserWithFirst:p1 rest:vargs]; + va_end(vargs); + return alt; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSMutableSet *outAssemblies = [NSMutableSet set]; + + for (PKParser *p in subparsers) { + [outAssemblies unionSet:[p matchAndAssemble:inAssemblies]]; + } + + return outAssemblies; +} + +@end diff --git a/src/.svn/text-base/PKAny.m.svn-base b/src/.svn/text-base/PKAny.m.svn-base new file mode 100644 index 0000000..f4665c5 --- /dev/null +++ b/src/.svn/text-base/PKAny.m.svn-base @@ -0,0 +1,23 @@ +// +// PKAny.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKAny + ++ (id)any { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + return [obj isMemberOfClass:[PKToken class]]; +} + +@end diff --git a/src/.svn/text-base/PKAssembly.m.svn-base b/src/.svn/text-base/PKAssembly.m.svn-base new file mode 100644 index 0000000..de47d3e --- /dev/null +++ b/src/.svn/text-base/PKAssembly.m.svn-base @@ -0,0 +1,225 @@ +// +// PKAssembly.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +static NSString * const PKAssemblyDefaultDelimiter = @"/"; + +@interface PKAssembly () +- (id)peek; +- (id)next; +- (BOOL)hasMore; +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter; +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter; + +@property (nonatomic, readwrite, retain) NSMutableArray *stack; +@property (nonatomic) NSUInteger index; +@property (nonatomic, retain) NSString *string; +@property (nonatomic, readwrite, retain) NSString *defaultDelimiter; +@property (nonatomic, readonly) NSUInteger length; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@property (nonatomic, readonly) NSUInteger objectsRemaining; +@end + +@implementation PKAssembly + ++ (id)assemblyWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + if (self = [super init]) { + self.stack = [NSMutableArray array]; + self.string = s; + } + return self; +} + + +- (void)dealloc { + self.stack = nil; + self.string = nil; + self.target = nil; + self.defaultDelimiter = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + // use of NSAllocateObject() below is a *massive* optimization over calling the designated initializer -initWithString: here. + // this line (and this method in general) is *vital* to the overall performance of the framework. dont fuck with it. + PKAssembly *a = NSAllocateObject([self class], 0, zone); + a->stack = [stack mutableCopyWithZone:zone]; + a->string = [string retain]; + if (defaultDelimiter) { + a->defaultDelimiter = [defaultDelimiter retain]; + } else { + a->defaultDelimiter = nil; + } + + if (target) { + if ([target conformsToProtocol:@protocol(NSMutableCopying)]) { + a->target = [target mutableCopyWithZone:zone]; + } else { + a->target = [target copyWithZone:zone]; + } + } else { + a->target = nil; + } + + a->index = index; + return a; +} + + +- (BOOL)isEqual:(id)obj { + if (![obj isMemberOfClass:[self class]]) { + return NO; + } + + PKAssembly *a = (PKAssembly *)obj; + if ([a length] != [self length]) { + return NO; + } + + if (a->index != index) { + return NO; + } + + if ([a.stack count] != [stack count]) { + return NO; + } + + return [[self description] isEqualToString:[obj description]]; +} + + +- (id)next { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return nil; +} + + +- (BOOL)hasMore { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return NO; +} + + +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return nil; +} + + +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return nil; +} + + +- (NSUInteger)length { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return 0; +} + + +- (NSUInteger)objectsConsumed { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return 0; +} + + +- (NSUInteger)objectsRemaining { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return 0; +} + + +- (id)peek { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return nil; +} + + +- (id)pop { + id result = nil; + if (![self isStackEmpty]) { + result = [[[stack lastObject] retain] autorelease]; + [stack removeLastObject]; + } + return result; +} + + +- (void)push:(id)object { + if (object) { + [stack addObject:object]; + } +} + + +- (BOOL)isStackEmpty { + return 0 == [stack count]; +} + + +- (NSArray *)objectsAbove:(id)fence { + NSMutableArray *result = [NSMutableArray array]; + + while (![self isStackEmpty]) { + id obj = [self pop]; + + if ([obj isEqual:fence]) { + [self push:obj]; + break; + } else { + [result addObject:obj]; + } + } + + return result; +} + + +- (NSString *)description { + NSMutableString *s = [NSMutableString string]; + [s appendString:@"["]; + + NSUInteger i = 0; + NSUInteger len = [stack count]; + + for (id obj in stack) { + [s appendString:[obj description]]; + if (len - 1 != i++) { + [s appendString:@", "]; + } + } + + [s appendString:@"]"]; + + NSString *d = defaultDelimiter ? defaultDelimiter : PKAssemblyDefaultDelimiter; + [s appendString:[self consumedObjectsJoinedByString:d]]; + [s appendString:@"^"]; + [s appendString:[self remainingObjectsJoinedByString:d]]; + + return [[s copy] autorelease]; +} + +@synthesize stack; +@synthesize target; +@synthesize index; +@synthesize string; +@synthesize defaultDelimiter; +@end diff --git a/src/.svn/text-base/PKCaseInsensitiveLiteral.m.svn-base b/src/.svn/text-base/PKCaseInsensitiveLiteral.m.svn-base new file mode 100644 index 0000000..99ba2ca --- /dev/null +++ b/src/.svn/text-base/PKCaseInsensitiveLiteral.m.svn-base @@ -0,0 +1,19 @@ +// +// PKCaseInsensitiveLiteral.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKCaseInsensitiveLiteral + +- (BOOL)qualifies:(id)obj { + return NSOrderedSame == [literal.stringValue caseInsensitiveCompare:[obj stringValue]]; +// return [literal isEqualIgnoringCase:obj]; +} + +@end diff --git a/src/.svn/text-base/PKChar.m.svn-base b/src/.svn/text-base/PKChar.m.svn-base new file mode 100644 index 0000000..e663813 --- /dev/null +++ b/src/.svn/text-base/PKChar.m.svn-base @@ -0,0 +1,22 @@ +// +// PKChar.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@implementation PKChar + ++ (id)char { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + return YES; +} + +@end diff --git a/src/.svn/text-base/PKCharacterAssembly.m.svn-base b/src/.svn/text-base/PKCharacterAssembly.m.svn-base new file mode 100644 index 0000000..3baddd9 --- /dev/null +++ b/src/.svn/text-base/PKCharacterAssembly.m.svn-base @@ -0,0 +1,121 @@ +// +// PKCharacterAssembly.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKAssembly () +@property (nonatomic, readwrite, retain) NSString *defaultDelimiter; +@end + +@implementation PKCharacterAssembly + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.defaultDelimiter = @""; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKCharacterAssembly *a = (PKCharacterAssembly *)[super copyWithZone:zone]; + return a; +} + + +- (id)peek { + if (index >= [string length]) { + return nil; + } + PKUniChar c = [string characterAtIndex:index]; + return [NSNumber numberWithInt:c]; +} + + +- (id)next { + id obj = [self peek]; + if (obj) { + index++; + } + return obj; +} + + +- (BOOL)hasMore { + return (index < [string length]); +} + + +- (NSUInteger)length { + return [string length]; +} + + +- (NSUInteger)objectsConsumed { + return index; +} + + +- (NSUInteger)objectsRemaining { + return ([string length] - index); +} + + +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter { + NSParameterAssert(delimiter); + return [string substringToIndex:self.objectsConsumed]; +} + + +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter { + NSParameterAssert(delimiter); + return [string substringFromIndex:self.objectsConsumed]; +} + + +// overriding simply to print NSNumber objects as their unichar values +- (NSString *)description { + NSMutableString *s = [NSMutableString string]; + [s appendString:@"["]; + + NSUInteger i = 0; + NSUInteger len = [stack count]; + + for (id obj in self.stack) { + if ([obj isKindOfClass:[NSNumber class]]) { // ***this is needed for Char Assemblies + [s appendFormat:@"%C", [obj integerValue]]; + } else { + [s appendString:[obj description]]; + } + if (len - 1 != i++) { + [s appendString:@", "]; + } + } + + [s appendString:@"]"]; + + [s appendString:[self consumedObjectsJoinedByString:self.defaultDelimiter]]; + [s appendString:@"^"]; + [s appendString:[self remainingObjectsJoinedByString:self.defaultDelimiter]]; + + return [[s copy] autorelease]; +} + +@end diff --git a/src/.svn/text-base/PKCollectionParser.m.svn-base b/src/.svn/text-base/PKCollectionParser.m.svn-base new file mode 100644 index 0000000..6fabdb8 --- /dev/null +++ b/src/.svn/text-base/PKCollectionParser.m.svn-base @@ -0,0 +1,98 @@ +// +// PKCollectionParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; + +@property (nonatomic, readwrite, retain) NSMutableArray *subparsers; +@end + +@implementation PKCollectionParser + ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest { + PKCollectionParser *cp = [[[self alloc] init] autorelease]; + + if (p1) { + [cp add:p1]; + + PKParser *p = nil; + while (p = va_arg(rest, PKParser *)) { + [cp add:p]; + } + } + + return cp; +} + + +- (id)init { + return [self initWithSubparsers:nil]; +} + + +- (id)initWithSubparsers:(PKParser *)p1, ... { + if (self = [super init]) { + self.subparsers = [NSMutableArray array]; + + if (p1) { + [subparsers addObject:p1]; + + va_list vargs; + va_start(vargs, p1); + + PKParser *p = nil; + while (p = va_arg(vargs, PKParser *)) { + [subparsers addObject:p]; + } + + va_end(vargs); + } + } + return self; +} + + +- (void)dealloc { + self.subparsers = nil; + [super dealloc]; +} + + +- (void)add:(PKParser *)p { + if (![p isKindOfClass:[PKParser class]]) { + NSLog(@"p: %@", p); + } + NSParameterAssert([p isKindOfClass:[PKParser class]]); + [subparsers addObject:p]; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } else { + // do bredth-first search + for (PKParser *p in subparsers) { + if ([p.name isEqualToString:s]) { + return p; + } + } + for (PKParser *p in subparsers) { + PKParser *sub = [p parserNamed:s]; + if (sub) { + return sub; + } + } + } + return nil; +} + +@synthesize subparsers; +@end diff --git a/src/.svn/text-base/PKComment.m.svn-base b/src/.svn/text-base/PKComment.m.svn-base new file mode 100644 index 0000000..0d0eb1f --- /dev/null +++ b/src/.svn/text-base/PKComment.m.svn-base @@ -0,0 +1,24 @@ +// +// PKComment.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/31/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKComment + ++ (id)comment { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isComment; +} + +@end \ No newline at end of file diff --git a/src/.svn/text-base/PKCommentState.m.svn-base b/src/.svn/text-base/PKCommentState.m.svn-base new file mode 100644 index 0000000..9eeb341 --- /dev/null +++ b/src/.svn/text-base/PKCommentState.m.svn-base @@ -0,0 +1,141 @@ +// +// PKCommentState.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; +@end + +@interface PKCommentState () +@property (nonatomic, retain) PKSymbolRootNode *rootNode; +@property (nonatomic, retain) PKSingleLineCommentState *singleLineState; +@property (nonatomic, retain) PKMultiLineCommentState *multiLineState; +@end + +@interface PKSingleLineCommentState () +- (void)addStartMarker:(NSString *)start; +- (void)removeStartMarker:(NSString *)start; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSString *currentStartMarker; +@end + +@interface PKMultiLineCommentState () +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end; +- (void)removeStartMarker:(NSString *)start; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSMutableArray *endMarkers; +@property (nonatomic, copy) NSString *currentStartMarker; +@end + +@implementation PKCommentState + +- (id)init { + if (self = [super init]) { + self.rootNode = [[[PKSymbolRootNode alloc] init] autorelease]; + self.singleLineState = [[[PKSingleLineCommentState alloc] init] autorelease]; + self.multiLineState = [[[PKMultiLineCommentState alloc] init] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.rootNode = nil; + self.singleLineState = nil; + self.multiLineState = nil; + [super dealloc]; +} + + +- (void)addSingleLineStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [rootNode add:start]; + [singleLineState addStartMarker:start]; +} + + +- (void)removeSingleLineStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [rootNode remove:start]; + [singleLineState removeStartMarker:start]; +} + + +- (void)addMultiLineStartMarker:(NSString *)start endMarker:(NSString *)end { + NSParameterAssert([start length]); + NSParameterAssert([end length]); + [rootNode add:start]; + [rootNode add:end]; + [multiLineState addStartMarker:start endMarker:end]; +} + + +- (void)removeMultiLineStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [rootNode remove:start]; + [multiLineState removeStartMarker:start]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + [self resetWithReader:r]; + + NSString *symbol = [rootNode nextSymbol:r startingWith:cin]; + PKToken *tok = nil; + + while ([symbol length]) { + if ([multiLineState.startMarkers containsObject:symbol]) { + multiLineState.currentStartMarker = symbol; + tok = [multiLineState nextTokenFromReader:r startingWith:cin tokenizer:t]; + if (tok.isComment) { + tok.offset = offset; + } + } else if ([singleLineState.startMarkers containsObject:symbol]) { + singleLineState.currentStartMarker = symbol; + tok = [singleLineState nextTokenFromReader:r startingWith:cin tokenizer:t]; + if (tok.isComment) { + tok.offset = offset; + } + } + + if (tok) { + return tok; + } else { + if ([symbol length] > 1) { + symbol = [symbol substringToIndex:[symbol length] -1]; + } else { + break; + } + [r unread:1]; + } + } + + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; +} + +@synthesize rootNode; +@synthesize singleLineState; +@synthesize multiLineState; +@synthesize reportsCommentTokens; +@synthesize balancesEOFTerminatedComments; +@end diff --git a/src/.svn/text-base/PKDelimitState.m.svn-base b/src/.svn/text-base/PKDelimitState.m.svn-base new file mode 100644 index 0000000..ce2896e --- /dev/null +++ b/src/.svn/text-base/PKDelimitState.m.svn-base @@ -0,0 +1,208 @@ +// +// PKDelimitState.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/21/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (void)appendString:(NSString *)s; +- (NSString *)bufferedString; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; +@end + +@interface PKDelimitState () +- (NSString *)endMarkerForStartMarker:(NSString *)startMarker; +- (NSCharacterSet *)allowedCharacterSetForStartMarker:(NSString *)startMarker; +@property (nonatomic, retain) PKSymbolRootNode *rootNode; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSMutableArray *endMarkers; +@property (nonatomic, retain) NSMutableArray *characterSets; +@end + +@implementation PKDelimitState + +- (id)init { + if (self = [super init]) { + self.rootNode = [[[PKSymbolRootNode alloc] init] autorelease]; + self.startMarkers = [NSMutableArray array]; + self.endMarkers = [NSMutableArray array]; + self.characterSets = [NSMutableArray array]; + } + return self; +} + + +- (void)dealloc { + self.rootNode = nil; + self.startMarkers = nil; + self.endMarkers = nil; + self.characterSets = nil; + [super dealloc]; +} + + +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end allowedCharacterSet:(NSCharacterSet *)set { + NSParameterAssert([start length]); + [rootNode add:start]; + [startMarkers addObject:start]; + + if ([end length]) { + [rootNode add:end]; + [endMarkers addObject:end]; + } else { + [endMarkers addObject:[NSNull null]]; + } + + if (set) { + [characterSets addObject:set]; + } else { + [characterSets addObject:[NSNull null]]; + } +} + + +- (void)removeStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [rootNode remove:start]; + NSUInteger i = [startMarkers indexOfObject:start]; + if (NSNotFound != i) { + [startMarkers removeObject:start]; + [characterSets removeObjectAtIndex:i]; + + id endOrNull = [endMarkers objectAtIndex:i]; + if ([NSNull null] != endOrNull) { + [rootNode remove:endOrNull]; + } + [endMarkers removeObjectAtIndex:i]; // this should always be in range. + } +} + + +- (NSString *)endMarkerForStartMarker:(NSString *)startMarker { + NSParameterAssert([startMarkers containsObject:startMarker]); + NSUInteger i = [startMarkers indexOfObject:startMarker]; + return [endMarkers objectAtIndex:i]; +} + + +- (NSCharacterSet *)allowedCharacterSetForStartMarker:(NSString *)startMarker { + NSParameterAssert([startMarkers containsObject:startMarker]); + NSCharacterSet *characterSet = nil; + NSUInteger i = [startMarkers indexOfObject:startMarker]; + id csOrNull = [characterSets objectAtIndex:i]; + if ([NSNull null] != csOrNull) { + characterSet = csOrNull; + } + return characterSet; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + NSString *startMarker = [rootNode nextSymbol:r startingWith:cin]; + + if (![startMarker length] || ![startMarkers containsObject:startMarker]) { + [r unread:[startMarker length] - 1]; + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + + [self resetWithReader:r]; + [self appendString:startMarker]; + + id endMarkerOrNull = [self endMarkerForStartMarker:startMarker]; + NSString *endMarker = nil; + NSCharacterSet *characterSet = [self allowedCharacterSetForStartMarker:startMarker]; + + PKUniChar c, e; + if ([NSNull null] == endMarkerOrNull) { + e = PKEOF; + } else { + endMarker = endMarkerOrNull; + e = [endMarker characterAtIndex:0]; + } + while (1) { + c = [r read]; + if (PKEOF == c) { + if (balancesEOFTerminatedStrings && endMarker) { + [self appendString:endMarker]; + } else if (endMarker && !allowsUnbalancedStrings) { + [r unread:[[self bufferedString] length] - 1]; + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + break; + } + + if (!endMarker && [t.whitespaceState isWhitespaceChar:c]) { + // if only the start marker was matched, dont return delimited string token. instead, defer tokenization + if ([startMarker isEqualToString:[self bufferedString]]) { + [r unread:[startMarker length] - 1]; + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + // else, return delimited string tok + break; + } + + if (e == c) { + NSString *peek = [rootNode nextSymbol:r startingWith:e]; + if (endMarker && [endMarker isEqualToString:peek]) { + [self appendString:endMarker]; + c = [r read]; + break; + } else { + [r unread:[peek length] - 1]; + if (e != [peek characterAtIndex:0]) { + [self append:c]; + c = [r read]; + } + } + } + + + // check if char is not in allowed character set (if given) + if (characterSet && ![characterSet characterIsMember:c]) { + if (allowsUnbalancedStrings) { + break; + } else { + // if not, unwind and return a symbol tok for cin + [r unread:[[self bufferedString] length]]; + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + } + + [self append:c]; + } + + if (PKEOF != c) { + [r unread]; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeDelimitedString stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; +} + +@synthesize rootNode; +@synthesize balancesEOFTerminatedStrings; +@synthesize allowsUnbalancedStrings; +@synthesize startMarkers; +@synthesize endMarkers; +@synthesize characterSets; +@end diff --git a/src/.svn/text-base/PKDelimitedString.m.svn-base b/src/.svn/text-base/PKDelimitedString.m.svn-base new file mode 100644 index 0000000..1b3186e --- /dev/null +++ b/src/.svn/text-base/PKDelimitedString.m.svn-base @@ -0,0 +1,58 @@ +// +// PKDelimitedString.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/21/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKDelimitedString () +@property (nonatomic, retain) NSString *startMarker; +@property (nonatomic, retain) NSString *endMarker; +@end + +@implementation PKDelimitedString + ++ (id)delimitedString { + return [self delimitedStringWithStartMarker:nil]; +} + + ++ (id)delimitedStringWithStartMarker:(NSString *)start { + return [self delimitedStringWithStartMarker:start endMarker:nil]; +} + + ++ (id)delimitedStringWithStartMarker:(NSString *)start endMarker:(NSString *)end { + PKDelimitedString *ds = [[[self alloc] initWithString:nil] autorelease]; + ds.startMarker = start; + ds.endMarker = end; + return ds; +} + + +- (void)dealloc { + self.startMarker = nil; + self.endMarker = nil; + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + BOOL result = tok.isDelimitedString; + if (result && [startMarker length]) { + result = [tok.stringValue hasPrefix:startMarker]; + if (result && [endMarker length]) { + result = [tok.stringValue hasSuffix:endMarker]; + } + } + return result; +} + +@synthesize startMarker; +@synthesize endMarker; +@end \ No newline at end of file diff --git a/src/.svn/text-base/PKDifference.m.svn-base b/src/.svn/text-base/PKDifference.m.svn-base new file mode 100644 index 0000000..a8b6f9a --- /dev/null +++ b/src/.svn/text-base/PKDifference.m.svn-base @@ -0,0 +1,98 @@ +// +// PKDifference.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/26/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKDifference.h" + +@interface NSMutableSet (PKDifferenceAdditions) +- (void)minusSetTestingEquality:(NSSet *)s; +@end + +@implementation NSMutableSet (PKDifferenceAdditions) + +- (void)minusSetTestingEquality:(NSSet *)s { + for (id a1 in self) { + for (id a2 in s) { + if ([a1 isEqual:a2]) { + [self removeObject:a1]; + } + } + } +} + +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@interface PKDifference () +@property (nonatomic, retain, readwrite) PKParser *subparser; +@property (nonatomic, retain, readwrite) PKParser *minus; +@end + +@implementation PKDifference + ++ (id)differenceWithSubparser:(PKParser *)s minus:(PKParser *)m { + return [[[self alloc] initWithSubparser:s minus:m] autorelease]; +} + + +- (id)initWithSubparser:(PKParser *)s minus:(PKParser *)m { + if (self = [super init]) { + self.subparser = s; + self.minus = m; + } + return self; +} + + +- (void)dealloc { + self.subparser = nil; + self.minus = nil; + [super dealloc]; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } else { + // do bredth-first search + if ([subparser.name isEqualToString:s]) { + return subparser; + } + if ([minus.name isEqualToString:s]) { + return minus; + } + + PKParser *sub = [subparser parserNamed:s]; + if (sub) { + return sub; + } + sub = [minus parserNamed:s]; + if (sub) { + return sub; + } + } + return nil; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + + NSMutableSet *outAssemblies = [[[subparser matchAndAssemble:inAssemblies] mutableCopy] autorelease]; + [outAssemblies minusSetTestingEquality:[minus allMatchesFor:inAssemblies]]; + + return outAssemblies; +} + +@synthesize subparser; +@synthesize minus; +@end diff --git a/src/.svn/text-base/PKDigit.m.svn-base b/src/.svn/text-base/PKDigit.m.svn-base new file mode 100644 index 0000000..d1e9798 --- /dev/null +++ b/src/.svn/text-base/PKDigit.m.svn-base @@ -0,0 +1,24 @@ +// +// PKDigit.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKDigit + ++ (id)digit { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKUniChar c = [obj intValue]; + return isdigit(c); +} + +@end diff --git a/src/.svn/text-base/PKEmpty.m.svn-base b/src/.svn/text-base/PKEmpty.m.svn-base new file mode 100644 index 0000000..7dcc3fb --- /dev/null +++ b/src/.svn/text-base/PKEmpty.m.svn-base @@ -0,0 +1,24 @@ +// +// PKEmpty.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@implementation PKEmpty + ++ (id)empty { + return [[[self alloc] init] autorelease]; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + //return [[[NSSet alloc] initWithSet:inAssemblies copyItems:YES] autorelease]; + return inAssemblies; +} + +@end diff --git a/src/.svn/text-base/PKGrammarParser.h.svn-base b/src/.svn/text-base/PKGrammarParser.h.svn-base new file mode 100644 index 0000000..8a4ba4a --- /dev/null +++ b/src/.svn/text-base/PKGrammarParser.h.svn-base @@ -0,0 +1,77 @@ +// +// PKGrammarParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface PKGrammarParser : NSObject { + id assembler; + PKCollectionParser *statementParser; + PKCollectionParser *declarationParser; + PKCollectionParser *callbackParser; + PKCollectionParser *selectorParser; + PKCollectionParser *exprParser; + PKCollectionParser *termParser; + PKCollectionParser *orTermParser; + PKCollectionParser *factorParser; + PKCollectionParser *nextFactorParser; + PKCollectionParser *phraseParser; + PKCollectionParser *phraseStarParser; + PKCollectionParser *phrasePlusParser; + PKCollectionParser *phraseQuestionParser; + PKCollectionParser *phraseCardinalityParser; + PKCollectionParser *cardinalityParser; + PKCollectionParser *primaryExprParser; + PKCollectionParser *negatedPrimaryExprParser; + PKCollectionParser *barePrimaryExprParser; + PKCollectionParser *predicateParser; + PKCollectionParser *intersectionParser; + PKCollectionParser *differenceParser; + PKCollectionParser *atomicValueParser; + PKCollectionParser *parserParser; + PKCollectionParser *discardParser; + PKCollectionParser *patternParser; + PKCollectionParser *delimitedStringParser; + PKParser *literalParser; + PKParser *variableParser; + PKParser *constantParser; +} + +- (id)initWithAssembler:(id)a; + +@property (nonatomic, retain) PKCollectionParser *statementParser; +@property (nonatomic, retain) PKCollectionParser *declarationParser; +@property (nonatomic, retain) PKCollectionParser *callbackParser; +@property (nonatomic, retain) PKCollectionParser *selectorParser; +@property (nonatomic, retain) PKCollectionParser *exprParser; +@property (nonatomic, retain) PKCollectionParser *termParser; +@property (nonatomic, retain) PKCollectionParser *orTermParser; +@property (nonatomic, retain) PKCollectionParser *factorParser; +@property (nonatomic, retain) PKCollectionParser *nextFactorParser; +@property (nonatomic, retain) PKCollectionParser *phraseParser; +@property (nonatomic, retain) PKCollectionParser *phraseStarParser; +@property (nonatomic, retain) PKCollectionParser *phrasePlusParser; +@property (nonatomic, retain) PKCollectionParser *phraseQuestionParser; +@property (nonatomic, retain) PKCollectionParser *phraseCardinalityParser; +@property (nonatomic, retain) PKCollectionParser *cardinalityParser; +@property (nonatomic, retain) PKCollectionParser *primaryExprParser; +@property (nonatomic, retain) PKCollectionParser *negatedPrimaryExprParser; +@property (nonatomic, retain) PKCollectionParser *barePrimaryExprParser; +@property (nonatomic, retain) PKCollectionParser *predicateParser; +@property (nonatomic, retain) PKCollectionParser *intersectionParser; +@property (nonatomic, retain) PKCollectionParser *differenceParser; +@property (nonatomic, retain) PKCollectionParser *atomicValueParser; +@property (nonatomic, retain) PKCollectionParser *parserParser; +@property (nonatomic, retain) PKCollectionParser *discardParser; +@property (nonatomic, retain) PKCollectionParser *patternParser; +@property (nonatomic, retain) PKCollectionParser *delimitedStringParser; +@property (nonatomic, retain) PKParser *literalParser; +@property (nonatomic, retain) PKParser *variableParser; +@property (nonatomic, retain) PKParser *constantParser; +@property (nonatomic, retain, readonly) PKParser *whitespaceParser; +@property (nonatomic, retain, readonly) PKCollectionParser *optionalWhitespaceParser; +@end diff --git a/src/.svn/text-base/PKGrammarParser.m.svn-base b/src/.svn/text-base/PKGrammarParser.m.svn-base new file mode 100644 index 0000000..132af55 --- /dev/null +++ b/src/.svn/text-base/PKGrammarParser.m.svn-base @@ -0,0 +1,640 @@ +// +// PKGrammarParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKGrammarParser.h" +#import + +@interface NSObject (PKGrammarParserAdditions) +- (void)didMatchStatement:(PKAssembly *)a; +- (void)didMatchCallback:(PKAssembly *)a; +- (void)didMatchExpression:(PKAssembly *)a; +- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchIntersection:(PKAssembly *)a; +- (void)didMatchDifference:(PKAssembly *)a; +- (void)didMatchPatternOptions:(PKAssembly *)a; +- (void)didMatchPattern:(PKAssembly *)a; +- (void)didMatchDiscard:(PKAssembly *)a; +- (void)didMatchLiteral:(PKAssembly *)a; +- (void)didMatchVariable:(PKAssembly *)a; +- (void)didMatchConstant:(PKAssembly *)a; +- (void)didMatchDelimitedString:(PKAssembly *)a; +- (void)didMatchNum:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchPlus:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +- (void)didMatchPhraseCardinality:(PKAssembly *)a; +- (void)didMatchCardinality:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchNegation:(PKAssembly *)a; +@end + +@interface PKGrammarParser () +- (PKAlternation *)zeroOrOne:(PKParser *)p; +- (PKSequence *)oneOrMore:(PKParser *)p; +@end + +@implementation PKGrammarParser + +- (id)initWithAssembler:(id)a { + if (self = [super init]) { + assembler = a; + } + return self; +} + + +- (void)dealloc { + assembler = nil; // appease clang static analyzer + + PKReleaseSubparserTree(statementParser); + PKReleaseSubparserTree(exprParser); + + self.statementParser = nil; + self.declarationParser = nil; + self.callbackParser = nil; + self.selectorParser = nil; + self.exprParser = nil; + self.termParser = nil; + self.orTermParser = nil; + self.factorParser = nil; + self.nextFactorParser = nil; + self.phraseParser = nil; + self.phraseStarParser = nil; + self.phrasePlusParser = nil; + self.phraseQuestionParser = nil; + self.phraseCardinalityParser = nil; + self.cardinalityParser = nil; + self.primaryExprParser = nil; + self.negatedPrimaryExprParser = nil; + self.barePrimaryExprParser = nil; + self.predicateParser = nil; + self.intersectionParser = nil; + self.differenceParser = nil; + self.atomicValueParser = nil; + self.parserParser = nil; + self.discardParser = nil; + self.patternParser = nil; + self.delimitedStringParser = nil; + self.literalParser = nil; + self.variableParser = nil; + self.constantParser = nil; + [super dealloc]; +} + + +- (PKAlternation *)zeroOrOne:(PKParser *)p { + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:p]; + return a; +} + + +- (PKSequence *)oneOrMore:(PKParser *)p { + PKSequence *s = [PKSequence sequence]; + [s add:p]; + [s add:[PKRepetition repetitionWithSubparser:p]]; + return s; +} + + +// @start = statement*; +// satement = S* declaration S* '=' expr; +// callback = S* '(' S* selector S* ')'; +// selector = Word ':'; +// expr = S* term orTerm* S*; +// term = factor nextFactor*; +// orTerm = S* '|' S* term; +// factor = phrase | phraseStar | phrasePlus | phraseQuestion | phraseCardinality; +// nextFactor = S factor; + +// phrase = primaryExpr predicate*; +// phraseStar = phrase S* '*'; +// phrasePlus = phrase S* '+'; +// phraseQuestion = phrase S* '?'; +// phraseCardinality = phrase S* cardinality; +// cardinality = '{' S* Number (S* ',' S* Number)? S* '}'; + +// predicate = S* (intersection | difference); +// intersection = '&' S* primaryExpr; +// difference = '-' S* primaryExpr; + +// primaryExpr = negatedPrimaryExpr | barePrimaryExpr; +// negatedPrimaryExpr = '~' barePrimaryExpr; +// barePrimaryExpr = atomicValue | '(' expr ')'; +// atomicValue = parser discard?; +// parser = pattern | literal | variable | constant | delimitedString; +// discard = S* '!'; +// pattern = DelimitedString('/', '/') (Word & /[imxsw]+/)?; +// delimitedString = 'DelimitedString' S* '(' S* QuotedString (S* ',' QuotedString)? S* ')'; +// literal = QuotedString; +// variable = LowercaseWord; +// constant = UppercaseWord; + + +// satement = S* declaration S* '=' expr; +- (PKCollectionParser *)statementParser { + if (!statementParser) { + self.statementParser = [PKSequence sequence]; + statementParser.name = @"statement"; + [statementParser add:self.optionalWhitespaceParser]; + + PKTrack *tr = [PKTrack track]; + [tr add:self.declarationParser]; + [tr add:self.optionalWhitespaceParser]; + [tr add:[PKSymbol symbolWithString:@"="]]; + + // accept any tokens in the parser expr the first time around. just gather tokens for later + [tr add:[self oneOrMore:[PKAny any]]]; + + [statementParser add:tr]; + [statementParser setAssembler:assembler selector:@selector(didMatchStatement:)]; + } + return statementParser; +} + + +// declaration = Word callback?; +- (PKCollectionParser *)declarationParser { + if (!declarationParser) { + self.declarationParser = [PKSequence sequence]; + declarationParser.name = @"declaration"; + [declarationParser add:[PKWord word]]; + [declarationParser add:[self zeroOrOne:self.callbackParser]]; + } + return declarationParser; +} + + +// callback = S* '(' S* selector S* ')'; +- (PKCollectionParser *)callbackParser { + if (!callbackParser) { + self.callbackParser = [PKSequence sequence]; + callbackParser.name = @"callback"; + [callbackParser add:self.optionalWhitespaceParser]; + + PKTrack *tr = [PKTrack track]; + [tr add:[[PKSymbol symbolWithString:@"("] discard]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:self.selectorParser]; + [tr add:self.optionalWhitespaceParser]; + [tr add:[[PKSymbol symbolWithString:@")"] discard]]; + + [callbackParser add:tr]; + [callbackParser setAssembler:assembler selector:@selector(didMatchCallback:)]; + } + return callbackParser; +} + + +// selector = Word ':'; +- (PKCollectionParser *)selectorParser { + if (!selectorParser) { + self.selectorParser = [PKTrack track]; + selectorParser.name = @"selector"; + [selectorParser add:[PKLowercaseWord word]]; + [selectorParser add:[[PKSymbol symbolWithString:@":"] discard]]; + } + return selectorParser; +} + + +// expr = S* term orTerm* S*; +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + exprParser.name = @"expr"; + [exprParser add:self.optionalWhitespaceParser]; + [exprParser add:self.termParser]; + [exprParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + [exprParser add:self.optionalWhitespaceParser]; + [exprParser setAssembler:assembler selector:@selector(didMatchExpression:)]; + } + return exprParser; +} + + +// term = factor nextFactor*; +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + termParser.name = @"term"; + [termParser add:self.factorParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.nextFactorParser]]; + [termParser setAssembler:assembler selector:@selector(didMatchAnd:)]; + } + return termParser; +} + + +// orTerm = S* '|' S* term; +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKSequence sequence]; + orTermParser.name = @"orTerm"; + [orTermParser add:self.optionalWhitespaceParser]; + + PKTrack *tr = [PKTrack track]; + [tr add:[PKSymbol symbolWithString:@"|"]]; // preserve as fence + [tr add:self.optionalWhitespaceParser]; + [tr add:self.termParser]; + + [orTermParser add:tr]; + [orTermParser setAssembler:assembler selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// factor = phrase | phraseStar | phrasePlus | phraseQuestion | phraseCardinality; +- (PKCollectionParser *)factorParser { + if (!factorParser) { + self.factorParser = [PKAlternation alternation]; + factorParser.name = @"factor"; + [factorParser add:self.phraseParser]; + [factorParser add:self.phraseStarParser]; + [factorParser add:self.phrasePlusParser]; + [factorParser add:self.phraseQuestionParser]; + [factorParser add:self.phraseCardinalityParser]; + } + return factorParser; +} + + +// nextFactor = S factor; +- (PKCollectionParser *)nextFactorParser { + if (!nextFactorParser) { + self.nextFactorParser = [PKSequence sequence]; + nextFactorParser.name = @"nextFactor"; + [nextFactorParser add:self.whitespaceParser]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:self.phraseParser]; + [a add:self.phraseStarParser]; + [a add:self.phrasePlusParser]; + [a add:self.phraseQuestionParser]; + [a add:self.phraseCardinalityParser]; + + [nextFactorParser add:a]; + } + return nextFactorParser; +} + + +// phrase = primaryExpr predicate*; +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + self.phraseParser = [PKSequence sequence]; + phraseParser.name = @"phrase"; + [phraseParser add:self.primaryExprParser]; + [phraseParser add:[PKRepetition repetitionWithSubparser:self.predicateParser]]; + } + return phraseParser; +} + + +// primaryExpr = negatedPrimaryExpr | barePrimaryExpr; +- (PKCollectionParser *)primaryExprParser { + if (!primaryExprParser) { + self.primaryExprParser = [PKAlternation alternation]; + primaryExprParser.name = @"primaryExpr"; + [primaryExprParser add:self.negatedPrimaryExprParser]; + [primaryExprParser add:self.barePrimaryExprParser]; + } + return primaryExprParser; +} + + +// negatedPrimaryExpr = '~' barePrimaryExpr; +- (PKCollectionParser *)negatedPrimaryExprParser { + if (!negatedPrimaryExprParser) { + self.negatedPrimaryExprParser = [PKSequence sequence]; + negatedPrimaryExprParser.name = @"negatedPrimaryExpr"; + [negatedPrimaryExprParser add:[[PKLiteral literalWithString:@"~"] discard]]; + [negatedPrimaryExprParser add:self.barePrimaryExprParser]; + [negatedPrimaryExprParser setAssembler:assembler selector:@selector(didMatchNegation:)]; + } + return negatedPrimaryExprParser; +} + + +// barePrimaryExpr = atomicValue | '(' expr ')'; +- (PKCollectionParser *)barePrimaryExprParser { + if (!barePrimaryExprParser) { + self.barePrimaryExprParser = [PKAlternation alternation]; + barePrimaryExprParser.name = @"barePrimaryExpr"; + [barePrimaryExprParser add:self.atomicValueParser]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:self.exprParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + [barePrimaryExprParser add:s]; + } + return barePrimaryExprParser; +} + + +// predicate = S* (intersection | difference); +- (PKCollectionParser *)predicateParser { + if (!predicateParser) { + self.predicateParser = [PKSequence sequence]; + predicateParser.name = @"predicate"; + [predicateParser add:self.optionalWhitespaceParser]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:self.intersectionParser]; + [a add:self.differenceParser]; + + [predicateParser add:a]; + } + return predicateParser; +} + + +// intersection = '&' S* primaryExpr; +- (PKCollectionParser *)intersectionParser { + if (!intersectionParser) { + self.intersectionParser = [PKTrack track]; + intersectionParser.name = @"intersection"; + + PKTrack *tr = [PKTrack track]; + [tr add:[[PKSymbol symbolWithString:@"&"] discard]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:self.primaryExprParser]; + + [intersectionParser add:tr]; + [intersectionParser setAssembler:assembler selector:@selector(didMatchIntersection:)]; + } + return intersectionParser; +} + + +// difference = '-' S* primaryExpr; +- (PKCollectionParser *)differenceParser { + if (!differenceParser) { + self.differenceParser = [PKTrack track]; + differenceParser.name = @"difference"; + + PKTrack *tr = [PKTrack track]; + [tr add:[[PKSymbol symbolWithString:@"-"] discard]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:self.primaryExprParser]; + + [differenceParser add:tr]; + [differenceParser setAssembler:assembler selector:@selector(didMatchDifference:)]; + } + return differenceParser; +} + + +// phraseStar = phrase S* '*'; +- (PKCollectionParser *)phraseStarParser { + if (!phraseStarParser) { + self.phraseStarParser = [PKSequence sequence]; + phraseStarParser.name = @"phraseStar"; + [phraseStarParser add:self.phraseParser]; + [phraseStarParser add:self.optionalWhitespaceParser]; + [phraseStarParser add:[[PKSymbol symbolWithString:@"*"] discard]]; + [phraseStarParser setAssembler:assembler selector:@selector(didMatchStar:)]; + } + return phraseStarParser; +} + + +// phrasePlus = phrase S* '+'; +- (PKCollectionParser *)phrasePlusParser { + if (!phrasePlusParser) { + self.phrasePlusParser = [PKSequence sequence]; + phrasePlusParser.name = @"phrasePlus"; + [phrasePlusParser add:self.phraseParser]; + [phrasePlusParser add:self.optionalWhitespaceParser]; + [phrasePlusParser add:[[PKSymbol symbolWithString:@"+"] discard]]; + [phrasePlusParser setAssembler:assembler selector:@selector(didMatchPlus:)]; + } + return phrasePlusParser; +} + + +// phraseQuestion = phrase S* '?'; +- (PKCollectionParser *)phraseQuestionParser { + if (!phraseQuestionParser) { + self.phraseQuestionParser = [PKSequence sequence]; + phraseQuestionParser.name = @"phraseQuestion"; + [phraseQuestionParser add:self.phraseParser]; + [phraseQuestionParser add:self.optionalWhitespaceParser]; + [phraseQuestionParser add:[[PKSymbol symbolWithString:@"?"] discard]]; + [phraseQuestionParser setAssembler:assembler selector:@selector(didMatchQuestion:)]; + } + return phraseQuestionParser; +} + + +// phraseCardinality = phrase S* cardinality; +- (PKCollectionParser *)phraseCardinalityParser { + if (!phraseCardinalityParser) { + self.phraseCardinalityParser = [PKSequence sequence]; + phraseCardinalityParser.name = @"phraseCardinality"; + [phraseCardinalityParser add:self.phraseParser]; + [phraseCardinalityParser add:self.optionalWhitespaceParser]; + [phraseCardinalityParser add:self.cardinalityParser]; + [phraseCardinalityParser setAssembler:assembler selector:@selector(didMatchPhraseCardinality:)]; + } + return phraseCardinalityParser; +} + + +// cardinality = '{' S* Number (S* ',' S* Number)? S* '}'; +- (PKCollectionParser *)cardinalityParser { + if (!cardinalityParser) { + self.cardinalityParser = [PKSequence sequence]; + cardinalityParser.name = @"cardinality"; + + PKTrack *commaNum = [PKSequence sequence]; + [commaNum add:self.optionalWhitespaceParser]; + [commaNum add:[[PKSymbol symbolWithString:@","] discard]]; + [commaNum add:self.optionalWhitespaceParser]; + [commaNum add:[PKNumber number]]; + + PKTrack *tr = [PKTrack track]; + [tr add:[PKSymbol symbolWithString:@"{"]]; // serves as fence. dont discard + [tr add:self.optionalWhitespaceParser]; + [tr add:[PKNumber number]]; + [tr add:[self zeroOrOne:commaNum]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:[[PKSymbol symbolWithString:@"}"] discard]]; + + [cardinalityParser add:tr]; + [cardinalityParser setAssembler:assembler selector:@selector(didMatchCardinality:)]; + } + return cardinalityParser; +} + + +// atomicValue = parser discard?; +- (PKCollectionParser *)atomicValueParser { + if (!atomicValueParser) { + self.atomicValueParser = [PKSequence sequence]; + atomicValueParser.name = @"atomicValue"; + [atomicValueParser add:self.parserParser]; + [atomicValueParser add:[self zeroOrOne:self.discardParser]]; + } + return atomicValueParser; +} + + +// parser = pattern | literal | variable | constant | delimitedString; +- (PKCollectionParser *)parserParser { + if (!parserParser) { + self.parserParser = [PKAlternation alternation]; + parserParser.name = @"parser"; + [parserParser add:self.patternParser]; + [parserParser add:self.literalParser]; + [parserParser add:self.variableParser]; + [parserParser add:self.constantParser]; + [parserParser add:self.delimitedStringParser]; + } + return parserParser; +} + + +// discard = S* '!'; +- (PKCollectionParser *)discardParser { + if (!discardParser) { + self.discardParser = [PKSequence sequence]; + discardParser.name = @"discard"; + [discardParser add:self.optionalWhitespaceParser]; + [discardParser add:[[PKSymbol symbolWithString:@"!"] discard]]; + [discardParser setAssembler:assembler selector:@selector(didMatchDiscard:)]; + } + return discardParser; +} + + +// pattern = DelimitedString('/', '/') (Word & /[imxsw]+/)?; +- (PKCollectionParser *)patternParser { + if (!patternParser) { + patternParser.name = @"pattern"; + self.patternParser = [PKSequence sequence]; + [patternParser add:[PKDelimitedString delimitedStringWithStartMarker:@"/" endMarker:@"/"]]; + + PKParser *opts = [PKPattern patternWithString:@"[imxsw]+" options:PKPatternOptionsNone]; + PKIntersection *inter = [PKIntersection intersection]; + [inter add:[PKWord word]]; + [inter add:opts]; + [inter setAssembler:assembler selector:@selector(didMatchPatternOptions:)]; + + [patternParser add:[self zeroOrOne:inter]]; + [patternParser setAssembler:assembler selector:@selector(didMatchPattern:)]; + } + return patternParser; +} + + +// delimitedString = 'DelimitedString' S* '(' S* QuotedString (S* ',' QuotedString)? S* ')'; +- (PKCollectionParser *)delimitedStringParser { + if (!delimitedStringParser) { + self.delimitedStringParser = [PKTrack track]; + delimitedStringParser.name = @"delimitedString"; + + PKSequence *secondArg = [PKSequence sequence]; + [secondArg add:self.optionalWhitespaceParser]; + + PKTrack *tr = [PKTrack track]; + [tr add:[[PKSymbol symbolWithString:@","] discard]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:[PKQuotedString quotedString]]; // endMarker + [secondArg add:tr]; + + [delimitedStringParser add:[[PKLiteral literalWithString:@"DelimitedString"] discard]]; + [delimitedStringParser add:self.optionalWhitespaceParser]; + [delimitedStringParser add:[PKSymbol symbolWithString:@"("]]; // preserve as fence + [delimitedStringParser add:self.optionalWhitespaceParser]; + [delimitedStringParser add:[PKQuotedString quotedString]]; // startMarker + [delimitedStringParser add:[self zeroOrOne:secondArg]]; + [delimitedStringParser add:self.optionalWhitespaceParser]; + [delimitedStringParser add:[[PKSymbol symbolWithString:@")"] discard]]; + + [delimitedStringParser setAssembler:assembler selector:@selector(didMatchDelimitedString:)]; + } + return delimitedStringParser; +} + + +// literal = QuotedString; +- (PKParser *)literalParser { + if (!literalParser) { + self.literalParser = [PKQuotedString quotedString]; + [literalParser setAssembler:assembler selector:@selector(didMatchLiteral:)]; + } + return literalParser; +} + + +// variable = LowercaseWord; +- (PKParser *)variableParser { + if (!variableParser) { + self.variableParser = [PKLowercaseWord word]; + variableParser.name = @"variable"; + [variableParser setAssembler:assembler selector:@selector(didMatchVariable:)]; + } + return variableParser; +} + + +// constant = UppercaseWord; +- (PKParser *)constantParser { + if (!constantParser) { + self.constantParser = [PKUppercaseWord word]; + constantParser.name = @"constant"; + [constantParser setAssembler:assembler selector:@selector(didMatchConstant:)]; + } + return constantParser; +} + + +- (PKParser *)whitespaceParser { + return [[PKWhitespace whitespace] discard]; +} + + +- (PKCollectionParser *)optionalWhitespaceParser { + return [PKRepetition repetitionWithSubparser:self.whitespaceParser]; +} + +@synthesize statementParser; +@synthesize declarationParser; +@synthesize callbackParser; +@synthesize selectorParser; +@synthesize exprParser; +@synthesize termParser; +@synthesize orTermParser; +@synthesize factorParser; +@synthesize nextFactorParser; +@synthesize phraseParser; +@synthesize phraseStarParser; +@synthesize phrasePlusParser; +@synthesize phraseQuestionParser; +@synthesize phraseCardinalityParser; +@synthesize cardinalityParser; +@synthesize primaryExprParser; +@synthesize negatedPrimaryExprParser; +@synthesize barePrimaryExprParser; +@synthesize predicateParser; +@synthesize intersectionParser; +@synthesize differenceParser; +@synthesize atomicValueParser; +@synthesize parserParser; +@synthesize discardParser; +@synthesize patternParser; +@synthesize delimitedStringParser; +@synthesize literalParser; +@synthesize variableParser; +@synthesize constantParser; +@end diff --git a/src/.svn/text-base/PKIntersection.m.svn-base b/src/.svn/text-base/PKIntersection.m.svn-base new file mode 100644 index 0000000..926f354 --- /dev/null +++ b/src/.svn/text-base/PKIntersection.m.svn-base @@ -0,0 +1,76 @@ +// +// PKIntersection.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/27/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKIntersection.h" +#import + +@interface NSMutableSet (PKIntersectionAdditions) +- (void)intersectSetTestingEquality:(NSSet *)s; +@end + +@implementation NSMutableSet (PKIntersectionAdditions) + +- (void)intersectSetTestingEquality:(NSSet *)s { + for (id a1 in self) { + BOOL found = NO; + for (id a2 in s) { + if ([a1 isEqual:a2]) { + found = YES; + break; + } + } + if (!found) { + [self removeObject:a1]; + } + } +} + +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; +@end + +@implementation PKIntersection + ++ (id)intersection { + return [self intersectionWithSubparsers:nil]; +} + + ++ (id)intersectionWithSubparsers:(PKParser *)p1, ... { + va_list vargs; + va_start(vargs, p1); + PKIntersection *inter = [self collectionParserWithFirst:p1 rest:vargs]; + va_end(vargs); + return inter; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSMutableSet *outAssemblies = [NSMutableSet set]; + + NSInteger i = 0; + for (PKParser *p in subparsers) { + if (0 == i++) { + outAssemblies = [[[p matchAndAssemble:inAssemblies] mutableCopy] autorelease]; + } else { + [outAssemblies intersectSetTestingEquality:[p allMatchesFor:inAssemblies]]; + } + } + + return outAssemblies; +} + +@end diff --git a/src/.svn/text-base/PKLetter.m.svn-base b/src/.svn/text-base/PKLetter.m.svn-base new file mode 100644 index 0000000..9fbf2fe --- /dev/null +++ b/src/.svn/text-base/PKLetter.m.svn-base @@ -0,0 +1,24 @@ +// +// PKLetter.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKLetter + ++ (id)letter { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKUniChar c = [obj intValue]; + return isalpha(c); +} + +@end diff --git a/src/.svn/text-base/PKLiteral.m.svn-base b/src/.svn/text-base/PKLiteral.m.svn-base new file mode 100644 index 0000000..2ac0e87 --- /dev/null +++ b/src/.svn/text-base/PKLiteral.m.svn-base @@ -0,0 +1,55 @@ +// +// PKLiteral.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKLiteral () +@property (nonatomic, retain) PKToken *literal; +@end + +@implementation PKLiteral + ++ (id)literalWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + //NSParameterAssert(s); + self = [super initWithString:s]; + if (self) { + self.literal = [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:s floatValue:0.0]; + } + return self; +} + + +- (void)dealloc { + self.literal = nil; + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + return [literal.stringValue isEqualToString:[obj stringValue]]; + //return [literal isEqual:obj]; +} + + +- (NSString *)description { + NSString *className = [NSStringFromClass([self class]) substringFromIndex:2]; + if ([name length]) { + return [NSString stringWithFormat:@"%@ (%@) %@", className, name, literal.stringValue]; + } else { + return [NSString stringWithFormat:@"%@ %@", className, literal.stringValue]; + } +} + +@synthesize literal; +@end diff --git a/src/.svn/text-base/PKLowercaseWord.m.svn-base b/src/.svn/text-base/PKLowercaseWord.m.svn-base new file mode 100644 index 0000000..bef5385 --- /dev/null +++ b/src/.svn/text-base/PKLowercaseWord.m.svn-base @@ -0,0 +1,24 @@ +// +// PKLowercaseWord.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKLowercaseWord + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + NSString *s = tok.stringValue; + return [s length] && islower([s characterAtIndex:0]); +} + +@end diff --git a/src/.svn/text-base/PKMultiLineCommentState.m.svn-base b/src/.svn/text-base/PKMultiLineCommentState.m.svn-base new file mode 100644 index 0000000..643d8d0 --- /dev/null +++ b/src/.svn/text-base/PKMultiLineCommentState.m.svn-base @@ -0,0 +1,146 @@ +// +// PKMultiLineCommentState.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (void)appendString:(NSString *)s; +- (NSString *)bufferedString; +@end + +@interface PKCommentState () +@property (nonatomic, retain) PKSymbolRootNode *rootNode; +@end + +@interface PKMultiLineCommentState () +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end; +- (void)removeStartMarker:(NSString *)start; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSMutableArray *endMarkers; +@property (nonatomic, copy) NSString *currentStartMarker; +@end + +@implementation PKMultiLineCommentState + +- (id)init { + if (self = [super init]) { + self.startMarkers = [NSMutableArray array]; + self.endMarkers = [NSMutableArray array]; + } + return self; +} + + +- (void)dealloc { + self.startMarkers = nil; + self.endMarkers = nil; + self.currentStartMarker = nil; + [super dealloc]; +} + + +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end { + NSParameterAssert([start length]); + NSParameterAssert([end length]); + [startMarkers addObject:start]; + [endMarkers addObject:end]; +} + + +- (void)removeStartMarker:(NSString *)start { + NSParameterAssert([start length]); + NSUInteger i = [startMarkers indexOfObject:start]; + if (NSNotFound != i) { + [startMarkers removeObject:start]; + [endMarkers removeObjectAtIndex:i]; // this should always be in range. + } +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + BOOL balanceEOF = t.commentState.balancesEOFTerminatedComments; + BOOL reportTokens = t.commentState.reportsCommentTokens; + if (reportTokens) { + [self resetWithReader:r]; + [self appendString:currentStartMarker]; + } + + NSUInteger i = [startMarkers indexOfObject:currentStartMarker]; + NSString *currentEndSymbol = [endMarkers objectAtIndex:i]; + PKUniChar e = [currentEndSymbol characterAtIndex:0]; + + // get the definitions of all multi-char comment start and end symbols from the commentState + PKSymbolRootNode *rootNode = t.commentState.rootNode; + + PKUniChar c; + while (1) { + c = [r read]; + if (PKEOF == c) { + if (balanceEOF) { + [self appendString:currentEndSymbol]; + } + break; + } + + if (e == c) { + NSString *peek = [rootNode nextSymbol:r startingWith:e]; + if ([currentEndSymbol isEqualToString:peek]) { + if (reportTokens) { + [self appendString:currentEndSymbol]; + } + c = [r read]; + break; + } else { + [r unread:[peek length] - 1]; + if (e != [peek characterAtIndex:0]) { + if (reportTokens) { + [self append:c]; + } + c = [r read]; + } + } + } + if (reportTokens) { + [self append:c]; + } + } + + if (PKEOF != c) { + [r unread]; + } + + self.currentStartMarker = nil; + + if (reportTokens) { + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeComment stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; + } else { + return [t nextToken]; + } +} + +@synthesize startMarkers; +@synthesize endMarkers; +@synthesize currentStartMarker; +@end diff --git a/src/.svn/text-base/PKNegation.m.svn-base b/src/.svn/text-base/PKNegation.m.svn-base new file mode 100644 index 0000000..6761bd3 --- /dev/null +++ b/src/.svn/text-base/PKNegation.m.svn-base @@ -0,0 +1,63 @@ +// +// PKNegation.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKNegation.h" +#import +#import + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@interface PKNegation () +@property (nonatomic, retain, readwrite) PKParser *subparser; +@property (nonatomic, retain) PKParser *difference; +@end + +@implementation PKNegation + ++ (id)negationWithSubparser:(PKParser *)s { + return [[[self alloc] initWithSubparser:s] autorelease]; +} + + +- (id)initWithSubparser:(PKParser *)s { + if (self = [super init]) { + self.subparser = s; + self.difference = [PKDifference differenceWithSubparser:[PKAny any] minus:subparser]; + } + return self; +} + + +- (void)dealloc { + self.subparser = nil; + self.difference = nil; + [super dealloc]; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } else { + return [subparser parserNamed:s]; + } +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + + return [difference allMatchesFor:inAssemblies]; +} + +@synthesize subparser; +@synthesize difference; +@end diff --git a/src/.svn/text-base/PKNumber.m.svn-base b/src/.svn/text-base/PKNumber.m.svn-base new file mode 100644 index 0000000..914a61c --- /dev/null +++ b/src/.svn/text-base/PKNumber.m.svn-base @@ -0,0 +1,24 @@ +// +// PKNumber.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKNumber + ++ (id)number { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isNumber; +} + +@end \ No newline at end of file diff --git a/src/.svn/text-base/PKNumberState.m.svn-base b/src/.svn/text-base/PKNumberState.m.svn-base new file mode 100644 index 0000000..90e8f73 --- /dev/null +++ b/src/.svn/text-base/PKNumberState.m.svn-base @@ -0,0 +1,258 @@ +// +// PKNumberState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface PKNumberState () +- (CGFloat)absorbDigitsFromReader:(PKReader *)r; +- (CGFloat)value; +- (void)parseLeftSideFromReader:(PKReader *)r; +- (void)parseRightSideFromReader:(PKReader *)r; +- (void)parseExponentFromReader:(PKReader *)r; +- (void)reset:(PKUniChar)cin; +- (void)checkForHex:(PKReader *)r; +- (void)checkForOctal; +@end + +@implementation PKNumberState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + [self resetWithReader:r]; + isNegative = NO; + originalCin = cin; + + if ('-' == cin) { + isNegative = YES; + cin = [r read]; + [self append:'-']; + } else if ('+' == cin) { + cin = [r read]; + [self append:'+']; + } + + [self reset:cin]; + if ('.' == c) { + [self parseRightSideFromReader:r]; + } else { + [self parseLeftSideFromReader:r]; + if (isDecimal) { + [self parseRightSideFromReader:r]; + } + } + + // erroneous ., +, -, or 0x + if (!gotADigit) { + if (isHex) { + [r unread]; + return [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:@"0" floatValue:0.0]; + } else { + if (isNegative && PKEOF != c) { // ?? + [r unread]; + } + return [t.symbolState nextTokenFromReader:r startingWith:originalCin tokenizer:t]; + } + } + + if (PKEOF != c) { + [r unread]; + } + + if (isNegative) { + floatValue = -floatValue; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:[self bufferedString] floatValue:[self value]]; + tok.offset = offset; + return tok; +} + + +- (CGFloat)value { + CGFloat result = (CGFloat)floatValue; + + NSUInteger i = 0; + for ( ; i < exp; i++) { + if (isNegativeExp) { + result /= (CGFloat)10.0; + } else { + result *= (CGFloat)10.0; + } + } + + return (CGFloat)result; +} + + +- (CGFloat)absorbDigitsFromReader:(PKReader *)r { + CGFloat divideBy = 1.0; + CGFloat v = 0.0; + BOOL isHexAlpha = NO; + + while (1) { + isHexAlpha = NO; + if (allowsHexadecimalNotation) { + [self checkForHex:r]; + if (c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F') { + isHexAlpha = YES; + } + } + + if (isdigit(c) || isHexAlpha) { + [self append:c]; + len++; + gotADigit = YES; + + if (allowsOctalNotation) { + [self checkForOctal]; + } + + if (isHexAlpha) { + if (c >= 'a' && c <= 'f') { + c = toupper(c); + } + c -= 7; + } + v = v * base + (c - '0'); + c = [r read]; + if (isFraction) { + divideBy *= base; + } + } else { + break; + } + } + + if (isFraction) { + v = v / divideBy; + } + + return (CGFloat)v; +} + + +- (void)parseLeftSideFromReader:(PKReader *)r { + isFraction = NO; + floatValue = [self absorbDigitsFromReader:r]; +} + + +- (void)parseRightSideFromReader:(PKReader *)r { + if ('.' == c) { + PKUniChar n = [r read]; + BOOL nextIsDigit = isdigit(n); + if (PKEOF != n) { + [r unread]; + } + + if (nextIsDigit || allowsTrailingDot) { + [self append:'.']; + if (nextIsDigit) { + c = [r read]; + isFraction = YES; + floatValue += [self absorbDigitsFromReader:r]; + } + } + } + + if (allowsScientificNotation) { + [self parseExponentFromReader:r]; + } +} + + +- (void)parseExponentFromReader:(PKReader *)r { + NSParameterAssert(r); + if ('e' == c || 'E' == c) { + PKUniChar e = c; + c = [r read]; + + BOOL hasExp = isdigit(c); + isNegativeExp = ('-' == c); + BOOL positiveExp = ('+' == c); + + if (!hasExp && (isNegativeExp || positiveExp)) { + c = [r read]; + hasExp = isdigit(c); + } + if (PKEOF != c) { + [r unread]; + } + if (hasExp) { + [self append:e]; + if (isNegativeExp) { + [self append:'-']; + } else if (positiveExp) { + [self append:'+']; + } + c = [r read]; + isFraction = NO; + exp = [self absorbDigitsFromReader:r]; + } + } +} + + +- (void)reset:(PKUniChar)cin { + c = cin; + firstNum = cin; + gotADigit = NO; + isFraction = NO; + isDecimal = YES; + isHex = NO; + len = 0; + base = (CGFloat)10.0; + floatValue = (CGFloat)0.0; + exp = (CGFloat)0.0; + isNegativeExp = NO; +} + + +- (void)checkForHex:(PKReader *)r { + if ('x' == c && '0' == firstNum && !isFraction && 1 == len) { + [self append:c]; + len++; + c = [r read]; + isDecimal = NO; + base = (CGFloat)16.0; + isHex = YES; + gotADigit = NO; + } +} + + +- (void)checkForOctal { + if ('0' == firstNum && !isFraction && isDecimal && 2 == len) { + isDecimal = NO; + base = (CGFloat)8.0; + } +} + +@synthesize allowsTrailingDot; +@synthesize allowsScientificNotation; +@synthesize allowsOctalNotation; +@synthesize allowsHexadecimalNotation; +@end diff --git a/src/.svn/text-base/PKParser.m.svn-base b/src/.svn/text-base/PKParser.m.svn-base new file mode 100644 index 0000000..b43bc15 --- /dev/null +++ b/src/.svn/text-base/PKParser.m.svn-base @@ -0,0 +1,197 @@ +// +// PKParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import + +@interface PKAssembly () +- (BOOL)hasMore; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (PKAssembly *)best:(NSSet *)inAssemblies; +@end + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@implementation PKParser + ++ (id)parser { + return [[[self alloc] init] autorelease]; +} + + +- (void)dealloc { +#ifdef TARGET_OS_SNOW_LEOPARD + self.assemblerBlock = nil; + self.preassemblerBlock = nil; +#endif + self.assembler = nil; + self.assemblerSelector = nil; + self.preassembler = nil; + self.preassemblerSelector = nil; + self.name = nil; + self.tokenizer = nil; + [super dealloc]; +} + + +- (void)setAssembler:(id)a selector:(SEL)sel { + self.assembler = a; + self.assemblerSelector = sel; +} + + +- (void)setPreassembler:(id)a selector:(SEL)sel { + self.preassembler = a; + self.preassemblerSelector = sel; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } + return nil; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSAssert1(0, @"-[PKParser %s] must be overriden", _cmd); + return nil; +} + + +- (PKAssembly *)bestMatchFor:(PKAssembly *)a { + NSParameterAssert(a); + NSSet *initialState = [NSSet setWithObject:a]; + NSSet *finalState = [self matchAndAssemble:initialState]; + return [self best:finalState]; +} + + +- (PKAssembly *)completeMatchFor:(PKAssembly *)a { + NSParameterAssert(a); + PKAssembly *best = [self bestMatchFor:a]; + if (best && ![best hasMore]) { + return best; + } + return nil; +} + + +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + +#ifdef TARGET_OS_SNOW_LEOPARD + if (preassemblerBlock) { + for (PKAssembly *a in inAssemblies) { + preassemblerBlock(a); + } + } else +#endif + if (preassembler) { + NSAssert2([preassembler respondsToSelector:preassemblerSelector], @"provided preassembler %@ should respond to %s", preassembler, preassemblerSelector); + for (PKAssembly *a in inAssemblies) { + [preassembler performSelector:preassemblerSelector withObject:a]; + } + } + + NSSet *outAssemblies = [self allMatchesFor:inAssemblies]; + +#ifdef TARGET_OS_SNOW_LEOPARD + if (assemblerBlock) { + for (PKAssembly *a in outAssemblies) { + assemblerBlock(a); + } + } else +#endif + if (assembler) { + NSAssert2([assembler respondsToSelector:assemblerSelector], @"provided assembler %@ should respond to %s", assembler, assemblerSelector); + for (PKAssembly *a in outAssemblies) { + [assembler performSelector:assemblerSelector withObject:a]; + } + } + return outAssemblies; +} + + +- (PKAssembly *)best:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + PKAssembly *best = nil; + + for (PKAssembly *a in inAssemblies) { + if (![a hasMore]) { + best = a; + break; + } + if (!best || a.objectsConsumed > best.objectsConsumed) { + best = a; + } + } + + return best; +} + + +- (NSString *)description { + NSString *className = [NSStringFromClass([self class]) substringFromIndex:2]; + if ([name length]) { + return [NSString stringWithFormat:@"%@ (%@)", className, name]; + } else { + return [NSString stringWithFormat:@"%@", className]; + } +} + +#ifdef TARGET_OS_SNOW_LEOPARD +@synthesize assemblerBlock; +@synthesize preassemblerBlock; +#endif +@synthesize assembler; +@synthesize assemblerSelector; +@synthesize preassembler; +@synthesize preassemblerSelector; +@synthesize name; +@end + +@implementation PKParser (PKParserFactoryAdditions) + +- (id)parse:(NSString *)s { + PKTokenizer *t = self.tokenizer; + if (!t) { + t = [PKTokenizer tokenizer]; + } + t.string = s; + PKAssembly *a = [self completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + if (a.target) { + return a.target; + } else { + return [a pop]; + } +} + + +- (PKTokenizer *)tokenizer { + return [[tokenizer retain] autorelease]; +} + + +- (void)setTokenizer:(PKTokenizer *)t { + if (tokenizer != t) { + [tokenizer autorelease]; + tokenizer = [t retain]; + } +} + +@end diff --git a/src/.svn/text-base/PKParserFactory.m.svn-base b/src/.svn/text-base/PKParserFactory.m.svn-base new file mode 100644 index 0000000..4f16b59 --- /dev/null +++ b/src/.svn/text-base/PKParserFactory.m.svn-base @@ -0,0 +1,979 @@ +// +// PKParserFactory.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf All rights reserved. +// + +#import "PKParserFactory.h" +#import +#import "PKGrammarParser.h" +#import "NSString+ParseKitAdditions.h" +#import "NSArray+ParseKitAdditions.h" + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface PKCollectionParser () +@property (nonatomic, readwrite, retain) NSMutableArray *subparsers; +@end + +@interface PKRepetition () +@property (nonatomic, readwrite, retain) PKParser *subparser; +@end + +@interface PKNegation () +@property (nonatomic, readwrite, retain) PKParser *subparser; +@end + +@interface PKDifference () +@property (nonatomic, readwrite, retain) PKParser *subparser; +@property (nonatomic, readwrite, retain) PKParser *minus; +@end + +@interface PKPattern () +@property (nonatomic, assign) PKTokenType tokenType; +@end + +void PKReleaseSubparserTree(PKParser *p) { + if ([p isKindOfClass:[PKCollectionParser class]]) { + PKCollectionParser *c = (PKCollectionParser *)p; + NSArray *subs = c.subparsers; + if (subs) { + [subs retain]; + c.subparsers = nil; + for (PKParser *s in subs) { + PKReleaseSubparserTree(s); + } + [subs release]; + } + } else if ([p isMemberOfClass:[PKRepetition class]]) { + PKRepetition *r = (PKRepetition *)p; + PKParser *sub = r.subparser; + if (sub) { + [sub retain]; + r.subparser = nil; + PKReleaseSubparserTree(sub); + [sub release]; + } + } else if ([p isMemberOfClass:[PKNegation class]]) { + PKNegation *n = (PKNegation *)p; + PKParser *sub = n.subparser; + if (sub) { + [sub retain]; + n.subparser = nil; + PKReleaseSubparserTree(sub); + [sub release]; + } + } else if ([p isMemberOfClass:[PKDifference class]]) { + PKDifference *d = (PKDifference *)p; + PKParser *sub = d.subparser; + if (sub) { + [sub retain]; + d.subparser = nil; + PKReleaseSubparserTree(sub); + [sub release]; + } + PKParser *m = d.minus; + if (m) { + [m retain]; + d.minus = nil; + PKReleaseSubparserTree(m); + [m release]; + } + } +} + +@interface PKParserFactory () +- (PKTokenizer *)tokenizerForParsingGrammar; +- (BOOL)isAllWhitespace:(NSArray *)toks; +- (id)parserTokensTableFromParsingStatementsInString:(NSString *)s; +- (void)gatherParserClassNamesFromTokens; +- (NSString *)parserClassNameFromTokenArray:(NSArray *)toks; + +- (PKTokenizer *)tokenizerFromGrammarSettings; +- (BOOL)boolForTokenForKey:(NSString *)key; +- (void)setTokenizerState:(PKTokenizerState *)state onTokenizer:(PKTokenizer *)t forTokensForKey:(NSString *)key; +- (void)setFallbackStateOn:(PKTokenizerState *)state withTokenizer:(PKTokenizer *)t forTokensForKey:(NSString *)key; + +- (id)expandParser:(PKParser *)p fromTokenArray:(NSArray *)toks; +- (PKParser *)expandedParserForName:(NSString *)parserName; +- (void)setAssemblerForParser:(PKParser *)p; +- (NSArray *)tokens:(NSArray *)toks byRemovingTokensOfType:(PKTokenType)tt; +- (NSString *)defaultAssemblerSelectorNameForParserName:(NSString *)parserName; +- (NSString *)defaultPreassemblerSelectorNameForParserName:(NSString *)parserName; + +// this is only for unit tests? can it go away? +- (PKSequence *)parserFromExpression:(NSString *)s; + +- (PKAlternation *)zeroOrOne:(PKParser *)p; +- (PKSequence *)oneOrMore:(PKParser *)p; + +- (void)didMatchStatement:(PKAssembly *)a; +- (void)didMatchCallback:(PKAssembly *)a; +- (void)didMatchExpression:(PKAssembly *)a; +- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchIntersection:(PKAssembly *)a; +- (void)didMatchDifference:(PKAssembly *)a; +- (void)didMatchPatternOptions:(PKAssembly *)a; +- (void)didMatchPattern:(PKAssembly *)a; +- (void)didMatchDiscard:(PKAssembly *)a; +- (void)didMatchLiteral:(PKAssembly *)a; +- (void)didMatchVariable:(PKAssembly *)a; +- (void)didMatchConstant:(PKAssembly *)a; +- (void)didMatchDelimitedString:(PKAssembly *)a; +- (void)didMatchNum:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchPlus:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +- (void)didMatchPhraseCardinality:(PKAssembly *)a; +- (void)didMatchCardinality:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchNegation:(PKAssembly *)a; + +@property (nonatomic, retain) PKGrammarParser *grammarParser; +@property (nonatomic, assign) id assembler; +@property (nonatomic, assign) id preassembler; +@property (nonatomic, retain) NSMutableDictionary *parserTokensTable; +@property (nonatomic, retain) NSMutableDictionary *parserClassTable; +@property (nonatomic, retain) NSMutableDictionary *selectorTable; +@property (nonatomic, retain) PKToken *equals; +@property (nonatomic, retain) PKToken *curly; +@property (nonatomic, retain) PKToken *paren; +@end + +@implementation PKParserFactory + ++ (id)factory { + return [[[PKParserFactory alloc] init] autorelease]; +} + + +- (id)init { + if (self = [super init]) { + self.grammarParser = [[[PKGrammarParser alloc] initWithAssembler:self] autorelease]; + self.equals = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"=" floatValue:0.0]; + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.0]; + self.paren = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"(" floatValue:0.0]; + self.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnAll; + } + return self; +} + + +- (void)dealloc { + self.grammarParser = nil; + self.assembler = nil; + self.preassembler = nil; + self.parserTokensTable = nil; + self.parserClassTable = nil; + self.selectorTable = nil; + self.equals = nil; + self.curly = nil; + self.paren = nil; + [super dealloc]; +} + + +- (PKCollectionParser *)exprParser { + return grammarParser.exprParser; +} + + +- (PKParser *)parserFromGrammar:(NSString *)s assembler:(id)a { + return [self parserFromGrammar:s assembler:a preassembler:nil]; +} + + +- (PKParser *)parserFromGrammar:(NSString *)s assembler:(id)a preassembler:(id)pa { + self.assembler = a; + self.preassembler = pa; + self.selectorTable = [NSMutableDictionary dictionary]; + self.parserClassTable = [NSMutableDictionary dictionary]; + self.parserTokensTable = [self parserTokensTableFromParsingStatementsInString:s]; + + PKTokenizer *t = [self tokenizerFromGrammarSettings]; + + [self gatherParserClassNamesFromTokens]; + + PKParser *start = [self expandedParserForName:@"@start"]; + + assembler = nil; + self.selectorTable = nil; + self.parserClassTable = nil; + self.parserTokensTable = nil; + + if (start && [start isKindOfClass:[PKParser class]]) { + start.tokenizer = t; + return start; + } else { + [NSException raise:@"GrammarException" format:@"The provided language grammar was invalid"]; + return nil; + } +} + + +- (PKTokenizer *)tokenizerForParsingGrammar { + PKTokenizer *t = [PKTokenizer tokenizer]; + + t.whitespaceState.reportsWhitespaceTokens = YES; + + // customize tokenizer to find tokenizer customization directives + [t setTokenizerState:t.wordState from:'@' to:'@']; + + // add support for tokenizer directives like @commentState.fallbackState + [t.wordState setWordChars:YES from:'.' to:'.']; + [t.wordState setWordChars:NO from:'-' to:'-']; + + // setup comments + [t setTokenizerState:t.commentState from:'/' to:'/']; + [t.commentState addSingleLineStartMarker:@"//"]; + [t.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + // comment state should fallback to delimit state to match regex delimited strings + t.commentState.fallbackState = t.delimitState; + + // regex delimited strings + [t.delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:[[NSCharacterSet whitespaceCharacterSet] invertedSet]]; + + return t; +} + + +- (BOOL)isAllWhitespace:(NSArray *)toks { + for (PKToken *tok in toks) { + if (PKTokenTypeWhitespace != tok.tokenType) { + return NO; + } + } + return YES; +} + + +- (id)parserTokensTableFromParsingStatementsInString:(NSString *)s { + PKTokenizer *t = [self tokenizerForParsingGrammar]; + t.string = s; + + PKTokenArraySource *src = [[PKTokenArraySource alloc] initWithTokenizer:t delimiter:@";"]; + id target = [NSMutableDictionary dictionary]; // setup the variable lookup table + + while ([src hasMore]) { + NSArray *toks = [src nextTokenArray]; + if (![self isAllWhitespace:toks]) { + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenArray:toks]; + //a.preservesWhitespaceTokens = YES; + a.target = target; + PKAssembly *res = [grammarParser.statementParser completeMatchFor:a]; + target = res.target; + } + } + + [src release]; + + return target; +} + + +- (void)gatherParserClassNamesFromTokens { + isGatheringClasses = YES; + // discover the actual parser class types + for (NSString *parserName in parserTokensTable) { + NSString *className = [self parserClassNameFromTokenArray:[parserTokensTable objectForKey:parserName]]; + NSAssert1([className length], @"Could not build ClassName from token array for parserName: %@", parserName); + [parserClassTable setObject:className forKey:parserName]; + } + isGatheringClasses = NO; +} + + +- (NSString *)parserClassNameFromTokenArray:(NSArray *)toks { + PKAssembly *a = [PKTokenAssembly assemblyWithTokenArray:toks]; + a.target = parserTokensTable; + a = [grammarParser.exprParser completeMatchFor:a]; + PKParser *res = [a pop]; + a.target = nil; + return NSStringFromClass([res class]); +} + + +- (PKTokenizer *)tokenizerFromGrammarSettings { + PKTokenizer *t = [PKTokenizer tokenizer]; + [t.commentState removeSingleLineStartMarker:@"//"]; + [t.commentState removeMultiLineStartMarker:@"/*"]; + + t.whitespaceState.reportsWhitespaceTokens = [self boolForTokenForKey:@"@reportsWhitespaceTokens"]; + t.commentState.reportsCommentTokens = [self boolForTokenForKey:@"@reportsCommentTokens"]; + t.commentState.balancesEOFTerminatedComments = [self boolForTokenForKey:@"balancesEOFTerminatedComments"]; + t.quoteState.balancesEOFTerminatedQuotes = [self boolForTokenForKey:@"@balancesEOFTerminatedQuotes"]; + t.delimitState.balancesEOFTerminatedStrings = [self boolForTokenForKey:@"@balancesEOFTerminatedStrings"]; + t.numberState.allowsTrailingDot = [self boolForTokenForKey:@"@allowsTrailingDot"]; + t.numberState.allowsScientificNotation = [self boolForTokenForKey:@"@allowsScientificNotation"]; + t.numberState.allowsOctalNotation = [self boolForTokenForKey:@"@allowsOctalNotation"]; + t.numberState.allowsHexadecimalNotation = [self boolForTokenForKey:@"@allowsHexadecimalNotation"]; + + [self setTokenizerState:t.wordState onTokenizer:t forTokensForKey:@"@wordState"]; + [self setTokenizerState:t.numberState onTokenizer:t forTokensForKey:@"@numberState"]; + [self setTokenizerState:t.quoteState onTokenizer:t forTokensForKey:@"@quoteState"]; + [self setTokenizerState:t.delimitState onTokenizer:t forTokensForKey:@"@delimitState"]; + [self setTokenizerState:t.symbolState onTokenizer:t forTokensForKey:@"@symbolState"]; + [self setTokenizerState:t.commentState onTokenizer:t forTokensForKey:@"@commentState"]; + [self setTokenizerState:t.whitespaceState onTokenizer:t forTokensForKey:@"@whitespaceState"]; + + [self setFallbackStateOn:t.commentState withTokenizer:t forTokensForKey:@"@commentState.fallbackState"]; + [self setFallbackStateOn:t.delimitState withTokenizer:t forTokensForKey:@"@delimitState.fallbackState"]; + + NSArray *toks = nil; + + // muli-char symbols + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@symbol"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@symbols"]]; + [parserTokensTable removeObjectForKey:@"@symbol"]; + [parserTokensTable removeObjectForKey:@"@symbols"]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + [t.symbolState add:[tok.stringValue stringByTrimmingQuotes]]; + } + } + + // wordChars + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@wordChar"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@wordChars"]]; + [parserTokensTable removeObjectForKey:@"@wordChar"]; + [parserTokensTable removeObjectForKey:@"@wordChars"]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + if ([s length]) { + NSInteger c = [s characterAtIndex:0]; + [t.wordState setWordChars:YES from:c to:c]; + } + } + } + + // whitespaceChars + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@whitespaceChar"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@whitespaceChars"]]; + [parserTokensTable removeObjectForKey:@"@whitespaceChar"]; + [parserTokensTable removeObjectForKey:@"@whitespaceChars"]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + if ([s length]) { + NSInteger c = 0; + if ([s hasPrefix:@"#x"]) { + c = [s integerValue]; + } else { + c = [s characterAtIndex:0]; + } + [t.whitespaceState setWhitespaceChars:YES from:c to:c]; + } + } + } + + // single-line comments + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@singleLineComment"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@singleLineComments"]]; + [parserTokensTable removeObjectForKey:@"@singleLineComment"]; + [parserTokensTable removeObjectForKey:@"@singleLineComments"]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + [t.commentState addSingleLineStartMarker:s]; + } + } + + // multi-line comments + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@multiLineComment"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@multiLineComments"]]; + NSAssert(0 == [toks count] % 2, @"@multiLineComments must be specified as quoted strings in multiples of 2"); + [parserTokensTable removeObjectForKey:@"@multiLineComment"]; + [parserTokensTable removeObjectForKey:@"@multiLineComments"]; + if ([toks count] > 1) { + NSInteger i = 0; + for ( ; i < [toks count] - 1; i++) { + PKToken *startTok = [toks objectAtIndex:i]; + PKToken *endTok = [toks objectAtIndex:++i]; + if (startTok.isQuotedString && endTok.isQuotedString) { + NSString *start = [startTok.stringValue stringByTrimmingQuotes]; + NSString *end = [endTok.stringValue stringByTrimmingQuotes]; + [t.commentState addMultiLineStartMarker:start endMarker:end]; + } + } + } + + // delimited strings + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@delimitedString"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@delimitedStrings"]]; + NSAssert(0 == [toks count] % 3, @"@delimitedString must be specified as quoted strings in multiples of 3"); + [parserTokensTable removeObjectForKey:@"@delimitedString"]; + [parserTokensTable removeObjectForKey:@"@delimitedStrings"]; + if ([toks count] > 1) { + NSInteger i = 0; + for ( ; i < [toks count] - 2; i++) { + PKToken *startTok = [toks objectAtIndex:i]; + PKToken *endTok = [toks objectAtIndex:++i]; + PKToken *charSetTok = [toks objectAtIndex:++i]; + if (startTok.isQuotedString && endTok.isQuotedString) { + NSString *start = [startTok.stringValue stringByTrimmingQuotes]; + NSString *end = [endTok.stringValue stringByTrimmingQuotes]; + NSCharacterSet *charSet = nil; + if (charSetTok.isQuotedString) { + charSet = [NSCharacterSet characterSetWithCharactersInString:[charSetTok.stringValue stringByTrimmingQuotes]]; + } + [t.delimitState addStartMarker:start endMarker:end allowedCharacterSet:charSet]; + } + } + } + + return t; +} + + +- (BOOL)boolForTokenForKey:(NSString *)key { + BOOL result = NO; + NSArray *toks = [parserTokensTable objectForKey:key]; + if ([toks count]) { + PKToken *tok = [toks objectAtIndex:0]; + if (tok.isWord && [tok.stringValue isEqualToString:@"YES"]) { + result = YES; + } + } + [parserTokensTable removeObjectForKey:key]; + return result; +} + + +- (void)setTokenizerState:(PKTokenizerState *)state onTokenizer:(PKTokenizer *)t forTokensForKey:(NSString *)key { + NSArray *toks = [parserTokensTable objectForKey:key]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + if (1 == [s length]) { + NSInteger c = [s characterAtIndex:0]; + [t setTokenizerState:state from:c to:c]; + } + } + } + [parserTokensTable removeObjectForKey:key]; +} + + +- (void)setFallbackStateOn:(PKTokenizerState *)state withTokenizer:(PKTokenizer *)t forTokensForKey:(NSString *)key { + NSArray *toks = [parserTokensTable objectForKey:key]; + if ([toks count]) { + PKToken *tok = [toks objectAtIndex:0]; + if (tok.isWord) { + PKTokenizerState *fallbackState = [t valueForKey:tok.stringValue]; + if (state != fallbackState) { + state.fallbackState = fallbackState; + } + } + } + [parserTokensTable removeObjectForKey:key]; +} + + +- (PKParser *)expandedParserForName:(NSString *)parserName { + id obj = [parserTokensTable objectForKey:parserName]; + if ([obj isKindOfClass:[PKParser class]]) { + return obj; + } else { + // prevent infinite loops by creating a parser of the correct type first, and putting it in the table + NSString *className = [parserClassTable objectForKey:parserName]; + + PKParser *p = [[NSClassFromString(className) alloc] init]; + [parserTokensTable setObject:p forKey:parserName]; + [p release]; + + p = [self expandParser:p fromTokenArray:obj]; + p.name = parserName; + + [self setAssemblerForParser:p]; + + [parserTokensTable setObject:p forKey:parserName]; + return p; + } +} + + +- (void)setAssemblerForParser:(PKParser *)p { + NSString *parserName = p.name; + NSString *selName = [selectorTable objectForKey:parserName]; + + BOOL setOnAll = (assemblerSettingBehavior & PKParserFactoryAssemblerSettingBehaviorOnAll); + + if (setOnAll) { + // continue + } else { + BOOL setOnExplicit = (assemblerSettingBehavior & PKParserFactoryAssemblerSettingBehaviorOnExplicit); + if (setOnExplicit && selName) { + // continue + } else { + BOOL isTerminal = [p isKindOfClass:[PKTerminal class]]; + if (!isTerminal && !setOnExplicit) return; + + BOOL setOnTerminals = (assemblerSettingBehavior & PKParserFactoryAssemblerSettingBehaviorOnTerminals); + if (setOnTerminals && isTerminal) { + // continue + } else { + return; + } + } + } + + if (!selName) { + selName = [self defaultAssemblerSelectorNameForParserName:parserName]; + } + + if (selName) { + SEL sel = NSSelectorFromString(selName); + if (assembler && [assembler respondsToSelector:sel]) { + [p setAssembler:assembler selector:sel]; + } + if (preassembler && [preassembler respondsToSelector:sel]) { + NSString *selName = [self defaultPreassemblerSelectorNameForParserName:parserName]; + [p setPreassembler:preassembler selector:NSSelectorFromString(selName)]; + } + } +} + + +- (id)expandParser:(PKParser *)p fromTokenArray:(NSArray *)toks { + PKAssembly *a = [PKTokenAssembly assemblyWithTokenArray:toks]; + a.target = parserTokensTable; + a = [grammarParser.exprParser completeMatchFor:a]; + PKParser *res = [a pop]; + if ([p isKindOfClass:[PKCollectionParser class]]) { + PKCollectionParser *cp = (PKCollectionParser *)p; + [cp add:res]; + return cp; + } else { + return res; + } +} + + +// this is just a utility for unit-testing +- (PKSequence *)parserFromExpression:(NSString *)s { + PKTokenizer *t = [self tokenizerForParsingGrammar]; + t.string = s; + PKAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; + a.target = [NSMutableDictionary dictionary]; // setup the variable lookup table + a = [grammarParser.exprParser completeMatchFor:a]; + return [a pop]; +} + + +- (PKAlternation *)zeroOrOne:(PKParser *)p { + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:p]; + return a; +} + + +- (PKSequence *)oneOrMore:(PKParser *)p { + PKSequence *s = [PKSequence sequence]; + [s add:p]; + [s add:[PKRepetition repetitionWithSubparser:p]]; + return s; +} + + +- (void)didMatchStatement:(PKAssembly *)a { + NSArray *toks = [[a objectsAbove:equals] reversedArray]; + [a pop]; // discard '=' tok + + NSString *parserName = nil; + NSString *selName = nil; + id obj = [a pop]; + if ([obj isKindOfClass:[NSString class]]) { // a callback was provided + selName = obj; + parserName = [[a pop] stringValue]; + } else { + parserName = [obj stringValue]; + } + + if (selName) { + NSAssert([selName length], @""); + [selectorTable setObject:selName forKey:parserName]; + } + NSMutableDictionary *d = a.target; + //NSLog(@"parserName: %@", parserName); + NSAssert([toks count], @""); + + // support for multiple @delimitedString = ... tokenizer directives + if ([parserName hasPrefix:@"@"]) { + // remove whitespace toks from tokenizer directives + if (![parserName isEqualToString:@"@start"]) { + toks = [self tokens:toks byRemovingTokensOfType:PKTokenTypeWhitespace]; + } + + NSArray *existingToks = [d objectForKey:parserName]; + if ([existingToks count]) { + toks = [toks arrayByAddingObjectsFromArray:existingToks]; + } + } + + [d setObject:toks forKey:parserName]; +} + + +- (NSArray *)tokens:(NSArray *)toks byRemovingTokensOfType:(PKTokenType)tt { + NSMutableArray *res = [NSMutableArray array]; + for (PKToken *tok in toks) { + if (PKTokenTypeWhitespace != tok.tokenType) { + [res addObject:tok]; + } + } + return res; +} + + +- (NSString *)defaultAssemblerSelectorNameForParserName:(NSString *)parserName { + NSString *prefix = nil; + if ([parserName hasPrefix:@"@"]) { + // parserName = [parserName substringFromIndex:1]; + // prefix = @"didMatch_"; + return nil; + } else { + prefix = @"didMatch"; + } + NSString *s = [NSString stringWithFormat:@"%@%@", [[parserName substringToIndex:1] uppercaseString], [parserName substringFromIndex:1]]; + return [NSString stringWithFormat:@"%@%@:", prefix, s]; +} + + +- (NSString *)defaultPreassemblerSelectorNameForParserName:(NSString *)parserName { + NSString *prefix = nil; + if ([parserName hasPrefix:@"@"]) { + return nil; + } else { + prefix = @"willMatch"; + } + NSString *s = [NSString stringWithFormat:@"%@%@", [[parserName substringToIndex:1] uppercaseString], [parserName substringFromIndex:1]]; + return [NSString stringWithFormat:@"%@%@:", prefix, s]; +} + + +- (void)didMatchCallback:(PKAssembly *)a { + PKToken *selNameTok = [a pop]; + NSString *selName = [NSString stringWithFormat:@"%@:", selNameTok.stringValue]; + [a push:selName]; +} + + +- (void)didMatchExpression:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:paren]; + NSAssert([objs count], @""); + [a pop]; // pop '(' + + if ([objs count] > 1) { + PKSequence *seq = [PKSequence sequence]; + for (id obj in [objs reverseObjectEnumerator]) { + [seq add:obj]; + } + [a push:seq]; + } else if ([objs count]) { + [a push:[objs objectAtIndex:0]]; + } +} + + +- (void)didMatchDifference:(PKAssembly *)a { + PKParser *minus = [a pop]; + PKParser *sub = [a pop]; + NSAssert([minus isKindOfClass:[PKParser class]], @""); + NSAssert([sub isKindOfClass:[PKParser class]], @""); + + [a push:[PKDifference differenceWithSubparser:sub minus:minus]]; +} + + +- (void)didMatchIntersection:(PKAssembly *)a { + PKParser *predicate = [a pop]; + PKParser *sub = [a pop]; + NSAssert([predicate isKindOfClass:[PKParser class]], @""); + NSAssert([sub isKindOfClass:[PKParser class]], @""); + + PKIntersection *inter = [PKIntersection intersection]; + [inter add:sub]; + [inter add:predicate]; + + [a push:inter]; +} + + +- (void)didMatchPatternOptions:(PKAssembly *)a { + PKToken *tok = [a pop]; + NSAssert(tok.isWord, @""); + + NSString *s = tok.stringValue; + NSAssert([s length] > 0, @""); + + PKPatternOptions opts = PKPatternOptionsNone; + if (NSNotFound != [s rangeOfString:@"i"].location) { + opts |= PKPatternOptionsIgnoreCase; + } + if (NSNotFound != [s rangeOfString:@"m"].location) { + opts |= PKPatternOptionsMultiline; + } + if (NSNotFound != [s rangeOfString:@"x"].location) { + opts |= PKPatternOptionsComments; + } + if (NSNotFound != [s rangeOfString:@"s"].location) { + opts |= PKPatternOptionsDotAll; + } + if (NSNotFound != [s rangeOfString:@"w"].location) { + opts |= PKPatternOptionsUnicodeWordBoundaries; + } + + [a push:[NSNumber numberWithInteger:opts]]; +} + + +- (void)didMatchPattern:(PKAssembly *)a { + id obj = [a pop]; // opts (as Number*) or DelimitedString('/', '/') + + PKPatternOptions opts = PKPatternOptionsNone; + if ([obj isKindOfClass:[NSNumber class]]) { + opts = [obj integerValue]; + obj = [a pop]; + } + + NSAssert([obj isMemberOfClass:[PKToken class]], @""); + PKToken *tok = (PKToken *)obj; + NSAssert(tok.isDelimitedString, @""); + + NSString *s = tok.stringValue; + NSAssert([s length] > 2, @""); + + NSAssert([s hasPrefix:@"/"], @""); + NSAssert([s hasSuffix:@"/"], @""); + + NSString *re = [s stringByTrimmingQuotes]; + + PKTerminal *t = [PKPattern patternWithString:re options:opts]; + + [a push:t]; +} + + +- (void)didMatchDiscard:(PKAssembly *)a { + id obj = [a pop]; + if ([obj isKindOfClass:[PKTerminal class]]) { + PKTerminal *t = (PKTerminal *)obj; + [t discard]; + } + [a push:obj]; +} + + +- (void)didMatchLiteral:(PKAssembly *)a { + PKToken *tok = [a pop]; + + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + PKTerminal *t = [PKCaseInsensitiveLiteral literalWithString:s]; + + [a push:t]; +} + + +- (void)didMatchVariable:(PKAssembly *)a { + PKToken *tok = [a pop]; + NSString *parserName = tok.stringValue; + PKParser *p = nil; + if (isGatheringClasses) { + // lookup the actual possible parser. + // if its not there, or still a token array, just spoof it with a sequence + NSMutableDictionary *d = a.target; + p = [d objectForKey:parserName]; + if (![p isKindOfClass:[PKParser parser]]) { + p = [PKSequence sequence]; + } + } else { + if ([parserTokensTable objectForKey:parserName]) { + p = [self expandedParserForName:parserName]; + } + } + [a push:p]; +} + + +- (void)didMatchConstant:(PKAssembly *)a { + PKToken *tok = [a pop]; + NSString *s = tok.stringValue; + id p = nil; + if ([s isEqualToString:@"Word"]) { + p = [PKWord word]; + } else if ([s isEqualToString:@"LowercaseWord"]) { + p = [PKLowercaseWord word]; + } else if ([s isEqualToString:@"UppercaseWord"]) { + p = [PKUppercaseWord word]; + } else if ([s isEqualToString:@"Number"]) { + p = [PKNumber number]; + } else if ([s isEqualToString:@"S"]) { + p = [PKWhitespace whitespace]; + } else if ([s isEqualToString:@"QuotedString"]) { + p = [PKQuotedString quotedString]; + } else if ([s isEqualToString:@"Symbol"]) { + p = [PKSymbol symbol]; + } else if ([s isEqualToString:@"Comment"]) { + p = [PKComment comment]; + } else if ([s isEqualToString:@"Any"]) { + p = [PKAny any]; + } else if ([s isEqualToString:@"Empty"]) { + p = [PKEmpty empty]; + } else if ([s isEqualToString:@"Pattern"]) { + p = tok; + } else if ([s isEqualToString:@"DelimitedString"]) { + p = tok; + } else if ([s isEqualToString:@"YES"] || [s isEqualToString:@"NO"]) { + p = tok; + } else { + [NSException raise:@"Grammar Exception" format: + @"User Grammar referenced a constant parser name (uppercase word) which is not supported: %@. Must be one of: Word, LowercaseWord, UppercaseWord, QuotedString, Number, Symbol, Empty.", s]; + } + + [a push:p]; +} + + +- (void)didMatchDelimitedString:(PKAssembly *)a { + NSArray *toks = [a objectsAbove:paren]; + [a pop]; // discard '(' fence + + NSAssert([toks count] > 0 && [toks count] < 3, @""); + NSString *start = [[[toks lastObject] stringValue] stringByTrimmingQuotes]; + NSString *end = nil; + if ([toks count] > 1) { + end = [[[toks objectAtIndex:0] stringValue] stringByTrimmingQuotes]; + } + + PKTerminal *t = [PKDelimitedString delimitedStringWithStartMarker:start endMarker:end]; + + [a push:t]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchStar:(PKAssembly *)a { + id top = [a pop]; + PKRepetition *rep = [PKRepetition repetitionWithSubparser:top]; + [a push:rep]; +} + + +- (void)didMatchPlus:(PKAssembly *)a { + id top = [a pop]; + [a push:[self oneOrMore:top]]; +} + + +- (void)didMatchQuestion:(PKAssembly *)a { + id top = [a pop]; + [a push:[self zeroOrOne:top]]; +} + + +- (void)didMatchPhraseCardinality:(PKAssembly *)a { + NSRange r = [[a pop] rangeValue]; + PKParser *p = [a pop]; + PKSequence *s = [PKSequence sequence]; + + NSInteger start = r.location; + NSInteger end = r.length; + + NSInteger i = 0; + for ( ; i < start; i++) { + [s add:p]; + } + + for ( ; i < end; i++) { + [s add:[self zeroOrOne:p]]; + } + + [a push:s]; +} + + +- (void)didMatchCardinality:(PKAssembly *)a { + NSArray *toks = [a objectsAbove:self.curly]; + [a pop]; // discard '{' tok + + NSAssert([toks count] > 0, @""); + + PKToken *tok = [toks lastObject]; + CGFloat start = tok.floatValue; + CGFloat end = start; + if ([toks count] > 1) { + tok = [toks objectAtIndex:0]; + end = tok.floatValue; + } + + NSAssert(start <= end, @""); + + NSRange r = NSMakeRange(start, end); + [a push:[NSValue valueWithRange:r]]; +} + + +- (void)didMatchOr:(PKAssembly *)a { + id second = [a pop]; + [a pop]; // pop '|' + id first = [a pop]; + PKAlternation *p = [PKAlternation alternation]; + [p add:first]; + [p add:second]; + [a push:p]; +} + + +- (void)didMatchAnd:(PKAssembly *)a { + NSMutableArray *parsers = [NSMutableArray array]; + while (![a isStackEmpty]) { + id obj = [a pop]; + if ([obj isKindOfClass:[PKParser class]]) { + [parsers addObject:obj]; + } else { + [a push:obj]; + break; + } + } + + if ([parsers count] > 1) { + PKSequence *seq = [PKSequence sequence]; + for (PKParser *p in [parsers reverseObjectEnumerator]) { + [seq add:p]; + } + + [a push:seq]; + } else if (1 == [parsers count]) { + [a push:[parsers objectAtIndex:0]]; + } +} + + +- (void)didMatchNegation:(PKAssembly *)a { + PKParser *p = [a pop]; + [a push:[PKNegation negationWithSubparser:p]]; +} + +@synthesize grammarParser; +@synthesize assembler; +@synthesize preassembler; +@synthesize parserTokensTable; +@synthesize parserClassTable; +@synthesize selectorTable; +@synthesize equals; +@synthesize curly; +@synthesize paren; +@synthesize assemblerSettingBehavior; +@end diff --git a/src/.svn/text-base/PKPattern.m.svn-base b/src/.svn/text-base/PKPattern.m.svn-base new file mode 100644 index 0000000..014e7b1 --- /dev/null +++ b/src/.svn/text-base/PKPattern.m.svn-base @@ -0,0 +1,45 @@ +// +// PKPattern.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/31/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import "RegexKitLite.h" + +@implementation PKPattern + ++ (id)patternWithString:(NSString *)s { + return [self patternWithString:s options:PKPatternOptionsNone]; +} + + ++ (id)patternWithString:(NSString *)s options:(PKPatternOptions)opts { + return [[[self alloc] initWithString:s options:opts] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + return [self initWithString:s options:PKPatternOptionsNone]; +} + + +- (id)initWithString:(NSString *)s options:(PKPatternOptions)opts { + if (self = [super initWithString:s]) { + options = opts; + } + return self; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + + NSRange r = NSMakeRange(0, [tok.stringValue length]); + + return NSEqualRanges(r, [tok.stringValue rangeOfRegex:self.string options:(uint32_t)options inRange:r capture:0 error:nil]); +} + +@end diff --git a/src/.svn/text-base/PKQuoteState.m.svn-base b/src/.svn/text-base/PKQuoteState.m.svn-base new file mode 100644 index 0000000..36c006c --- /dev/null +++ b/src/.svn/text-base/PKQuoteState.m.svn-base @@ -0,0 +1,56 @@ +// +// PKQuoteState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation PKQuoteState + +- (void)dealloc { + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + [self append:cin]; + PKUniChar c; + do { + c = [r read]; + if (PKEOF == c) { + c = cin; + if (balancesEOFTerminatedQuotes) { + [self append:c]; + } + } else { + [self append:c]; + } + + } while (c != cin); + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeQuotedString stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; +} + +@synthesize balancesEOFTerminatedQuotes; +@end diff --git a/src/.svn/text-base/PKQuotedString.m.svn-base b/src/.svn/text-base/PKQuotedString.m.svn-base new file mode 100644 index 0000000..358d7d9 --- /dev/null +++ b/src/.svn/text-base/PKQuotedString.m.svn-base @@ -0,0 +1,24 @@ +// +// PKQuotedString.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKQuotedString + ++ (id)quotedString { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isQuotedString; +} + +@end diff --git a/src/.svn/text-base/PKReader.m.svn-base b/src/.svn/text-base/PKReader.m.svn-base new file mode 100644 index 0000000..477f207 --- /dev/null +++ b/src/.svn/text-base/PKReader.m.svn-base @@ -0,0 +1,69 @@ +// +// PKReader.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/21/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@implementation PKReader + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + if (self = [super init]) { + self.string = s; + } + return self; +} + + +- (void)dealloc { + self.string = nil; + [super dealloc]; +} + + +- (NSString *)string { + return [[string retain] autorelease]; +} + + +- (void)setString:(NSString *)s { + if (string != s) { + [string autorelease]; + string = [s copy]; + length = [string length]; + } + // reset cursor + offset = 0; +} + + +- (PKUniChar)read { + if (0 == length || offset > length - 1) { + return PKEOF; + } + return [string characterAtIndex:offset++]; +} + + +- (void)unread { + offset = (0 == offset) ? 0 : offset - 1; +} + + +- (void)unread:(NSUInteger)count { + NSUInteger i = 0; + for ( ; i < count; i++) { + [self unread]; + } +} + +@synthesize offset; +@end diff --git a/src/.svn/text-base/PKRepetition.m.svn-base b/src/.svn/text-base/PKRepetition.m.svn-base new file mode 100644 index 0000000..96b1491 --- /dev/null +++ b/src/.svn/text-base/PKRepetition.m.svn-base @@ -0,0 +1,71 @@ +// +// PKRepetition.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +@end + +@interface PKRepetition () +@property (nonatomic, readwrite, retain) PKParser *subparser; +@end + +@implementation PKRepetition + ++ (id)repetitionWithSubparser:(PKParser *)p { + return [[[self alloc] initWithSubparser:p] autorelease]; +} + + +- (id)init { + return [self initWithSubparser:nil]; +} + + +- (id)initWithSubparser:(PKParser *)p { + //NSParameterAssert(p); + if (self = [super init]) { + self.subparser = p; + } + return self; +} + + +- (void)dealloc { + self.subparser = nil; + [super dealloc]; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } else { + return [subparser parserNamed:s]; + } +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + //NSMutableSet *outAssemblies = [[[NSMutableSet alloc] initWithSet:inAssemblies copyItems:YES] autorelease]; + NSMutableSet *outAssemblies = [[inAssemblies mutableCopy] autorelease]; + + NSSet *s = inAssemblies; + while ([s count]) { + s = [subparser matchAndAssemble:s]; + [outAssemblies unionSet:s]; + } + + return outAssemblies; +} + +@synthesize subparser; +@end diff --git a/src/.svn/text-base/PKSequence.m.svn-base b/src/.svn/text-base/PKSequence.m.svn-base new file mode 100644 index 0000000..5c7fb4f --- /dev/null +++ b/src/.svn/text-base/PKSequence.m.svn-base @@ -0,0 +1,50 @@ +// +// PKSequence.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +@end + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; +@end + +@implementation PKSequence + ++ (id)sequence { + return [self sequenceWithSubparsers:nil]; +} + + ++ (id)sequenceWithSubparsers:(PKParser *)p1, ... { + va_list vargs; + va_start(vargs, p1); + PKSequence *seq = [self collectionParserWithFirst:p1 rest:vargs]; + va_end(vargs); + return seq; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSSet *outAssemblies = inAssemblies; + + for (PKParser *p in subparsers) { + outAssemblies = [p matchAndAssemble:outAssemblies]; + if (![outAssemblies count]) { + break; + } + } + + return outAssemblies; +} + +@end diff --git a/src/.svn/text-base/PKSingleLineCommentState.m.svn-base b/src/.svn/text-base/PKSingleLineCommentState.m.svn-base new file mode 100644 index 0000000..49c0feb --- /dev/null +++ b/src/.svn/text-base/PKSingleLineCommentState.m.svn-base @@ -0,0 +1,101 @@ +// +// PKSingleLineCommentState.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (void)appendString:(NSString *)s; +- (NSString *)bufferedString; +@end + +@interface PKSingleLineCommentState () +- (void)addStartMarker:(NSString *)start; +- (void)removeStartMarker:(NSString *)start; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSString *currentStartMarker; +@end + +@implementation PKSingleLineCommentState + +- (id)init { + if (self = [super init]) { + self.startMarkers = [NSMutableArray array]; + } + return self; +} + + +- (void)dealloc { + self.startMarkers = nil; + self.currentStartMarker = nil; + [super dealloc]; +} + + +- (void)addStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [startMarkers addObject:start]; +} + + +- (void)removeStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [startMarkers removeObject:start]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + BOOL reportTokens = t.commentState.reportsCommentTokens; + if (reportTokens) { + [self resetWithReader:r]; + [self appendString:currentStartMarker]; + } + + PKUniChar c; + while (1) { + c = [r read]; + if ('\n' == c || '\r' == c || PKEOF == c) { + break; + } + if (reportTokens) { + [self append:c]; + } + } + + if (PKEOF != c) { + [r unread]; + } + + self.currentStartMarker = nil; + + if (reportTokens) { + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeComment stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; + } else { + return [t nextToken]; + } +} + +@synthesize startMarkers; +@synthesize currentStartMarker; +@end diff --git a/src/.svn/text-base/PKSpecificChar.m.svn-base b/src/.svn/text-base/PKSpecificChar.m.svn-base new file mode 100644 index 0000000..47941e0 --- /dev/null +++ b/src/.svn/text-base/PKSpecificChar.m.svn-base @@ -0,0 +1,32 @@ +// +// PKSpecificChar.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKSpecificChar + ++ (id)specificCharWithChar:(PKUniChar)c { + return [[[self alloc] initWithSpecificChar:c] autorelease]; +} + + +- (id)initWithSpecificChar:(PKUniChar)c { + self = [super initWithString:[NSString stringWithFormat:@"%C", c]]; + if (self) { + } + return self; +} + + +- (BOOL)qualifies:(id)obj { + PKUniChar c = [obj intValue]; + return c == [string characterAtIndex:0]; +} + +@end diff --git a/src/.svn/text-base/PKSymbol.m.svn-base b/src/.svn/text-base/PKSymbol.m.svn-base new file mode 100644 index 0000000..237a311 --- /dev/null +++ b/src/.svn/text-base/PKSymbol.m.svn-base @@ -0,0 +1,73 @@ +// +// PKSymbol.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKSymbol () +@property (nonatomic, retain) PKToken *symbol; +@end + +@implementation PKSymbol + ++ (id)symbol { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)symbolWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + if ([s length]) { + self.symbol = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:s floatValue:0.0]; + } + } + return self; +} + + +- (void)dealloc { + self.symbol = nil; + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + if (symbol) { + return [symbol isEqual:obj]; + } else { + PKToken *tok = (PKToken *)obj; + return tok.isSymbol; + } +} + + +- (NSString *)description { + NSString *className = [NSStringFromClass([self class]) substringFromIndex:2]; + if ([name length]) { + if (symbol) { + return [NSString stringWithFormat:@"%@ (%@) %@", className, name, symbol.stringValue]; + } else { + return [NSString stringWithFormat:@"%@ (%@)", className, name]; + } + } else { + if (symbol) { + return [NSString stringWithFormat:@"%@ %@", className, symbol.stringValue]; + } else { + return [NSString stringWithFormat:@"%@", className]; + } + } +} + +@synthesize symbol; +@end diff --git a/src/.svn/text-base/PKSymbolNode.m.svn-base b/src/.svn/text-base/PKSymbolNode.m.svn-base new file mode 100644 index 0000000..20ba02e --- /dev/null +++ b/src/.svn/text-base/PKSymbolNode.m.svn-base @@ -0,0 +1,76 @@ +// +// PKSymbolNode.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKSymbolNode () +@property (nonatomic, readwrite, retain) NSString *ancestry; +@property (nonatomic, assign) PKSymbolNode *parent; // this must be 'assign' to avoid retain loop leak +@property (nonatomic, retain) NSMutableDictionary *children; +@property (nonatomic) PKUniChar character; +@property (nonatomic, retain) NSString *string; + +- (void)determineAncestry; +@end + +@implementation PKSymbolNode + +- (id)initWithParent:(PKSymbolNode *)p character:(PKUniChar)c { + if (self = [super init]) { + self.parent = p; + self.character = c; + self.children = [NSMutableDictionary dictionary]; + + // this private property is an optimization. + // cache the NSString for the char to prevent it being constantly recreated in -determinAncestry + self.string = [NSString stringWithFormat:@"%C", character]; + + [self determineAncestry]; + } + return self; +} + + +- (void)dealloc { + parent = nil; // makes clang static analyzer happy + self.ancestry = nil; + self.string = nil; + self.children = nil; + [super dealloc]; +} + + +- (void)determineAncestry { + if (PKEOF == parent.character) { // optimization for sinlge-char symbol (parent is symbol root node) + self.ancestry = string; + } else { + NSMutableString *result = [NSMutableString string]; + + PKSymbolNode *n = self; + while (PKEOF != n.character) { + [result insertString:n.string atIndex:0]; + n = n.parent; + } + + //self.ancestry = [[result copy] autorelease]; // assign an immutable copy + self.ancestry = result; // optimization + } +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", self.ancestry]; +} + +@synthesize ancestry; +@synthesize parent; +@synthesize character; +@synthesize string; +@synthesize children; +@end diff --git a/src/.svn/text-base/PKSymbolRootNode.m.svn-base b/src/.svn/text-base/PKSymbolRootNode.m.svn-base new file mode 100644 index 0000000..5a9d259 --- /dev/null +++ b/src/.svn/text-base/PKSymbolRootNode.m.svn-base @@ -0,0 +1,147 @@ +// +// PKSymbolRootNode.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKSymbolNode () +@property (nonatomic, retain) NSMutableDictionary *children; +@end + +@interface PKSymbolRootNode () +- (void)addWithFirst:(PKUniChar)c rest:(NSString *)s parent:(PKSymbolNode *)p; +- (void)removeWithFirst:(PKUniChar)c rest:(NSString *)s parent:(PKSymbolNode *)p; +- (NSString *)nextWithFirst:(PKUniChar)c rest:(PKReader *)r parent:(PKSymbolNode *)p; +@end + +@implementation PKSymbolRootNode + +- (id)init { + self = [super initWithParent:nil character:PKEOF]; + if (self) { + + } + return self; +} + + +- (void)add:(NSString *)s { + NSParameterAssert(s); + if ([s length] < 2) return; + + [self addWithFirst:[s characterAtIndex:0] rest:[s substringFromIndex:1] parent:self]; +} + + +- (void)remove:(NSString *)s { + NSParameterAssert(s); + if ([s length] < 2) return; + + [self removeWithFirst:[s characterAtIndex:0] rest:[s substringFromIndex:1] parent:self]; +} + + +- (void)addWithFirst:(PKUniChar)c rest:(NSString *)s parent:(PKSymbolNode *)p { + NSParameterAssert(p); + NSNumber *key = [NSNumber numberWithInteger:c]; + PKSymbolNode *child = [p.children objectForKey:key]; + if (!child) { + child = [[PKSymbolNode alloc] initWithParent:p character:c]; + [p.children setObject:child forKey:key]; + [child release]; + } + + NSString *rest = nil; + + if (0 == [s length]) { + return; + } else if ([s length] > 1) { + rest = [s substringFromIndex:1]; + } + + [self addWithFirst:[s characterAtIndex:0] rest:rest parent:child]; +} + + +- (void)removeWithFirst:(PKUniChar)c rest:(NSString *)s parent:(PKSymbolNode *)p { + NSParameterAssert(p); + NSNumber *key = [NSNumber numberWithInteger:c]; + PKSymbolNode *child = [p.children objectForKey:key]; + if (child) { + NSString *rest = nil; + + if (0 == [s length]) { + return; + } else if ([s length] > 1) { + rest = [s substringFromIndex:1]; + [self removeWithFirst:[s characterAtIndex:0] rest:rest parent:child]; + } + + [p.children removeObjectForKey:key]; + } +} + + +- (NSString *)nextSymbol:(PKReader *)r startingWith:(PKUniChar)cin { + NSParameterAssert(r); + return [self nextWithFirst:cin rest:r parent:self]; +} + + +- (NSString *)nextWithFirst:(PKUniChar)c rest:(PKReader *)r parent:(PKSymbolNode *)p { + NSParameterAssert(p); + NSString *result = [NSString stringWithFormat:@"%C", c]; + + // this also works. +// NSString *result = [[[NSString alloc] initWithCharacters:(const unichar *)&c length:1] autorelease]; + + // none of these work. + //NSString *result = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSUTF8StringEncoding] autorelease]; + +// NSLog(@"c: %d", c); +// NSLog(@"string for c: %@", result); +// NSString *chars = [[[NSString alloc] initWithCharacters:(const unichar *)&c length:1] autorelease]; +// NSString *utfs = [[[NSString alloc] initWithUTF8String:(const char *)&c] autorelease]; +// NSString *utf8 = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSUTF8StringEncoding] autorelease]; +// NSString *utf16 = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSUTF16StringEncoding] autorelease]; +// NSString *ascii = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSASCIIStringEncoding] autorelease]; +// NSString *iso = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSISOLatin1StringEncoding] autorelease]; +// +// NSLog(@"chars: '%@'", chars); +// NSLog(@"utfs: '%@'", utfs); +// NSLog(@"utf8: '%@'", utf8); +// NSLog(@"utf16: '%@'", utf16); +// NSLog(@"ascii: '%@'", ascii); +// NSLog(@"iso: '%@'", iso); + + NSNumber *key = [NSNumber numberWithInteger:c]; + PKSymbolNode *child = [p.children objectForKey:key]; + + if (!child) { + if (p == self) { + return result; + } else { + [r unread]; + return @""; + } + } + + c = [r read]; + if (PKEOF == c) { + return result; + } + + return [result stringByAppendingString:[self nextWithFirst:c rest:r parent:child]]; +} + + +- (NSString *)description { + return @""; +} + +@end diff --git a/src/.svn/text-base/PKSymbolState.m.svn-base b/src/.svn/text-base/PKSymbolState.m.svn-base new file mode 100644 index 0000000..c406d57 --- /dev/null +++ b/src/.svn/text-base/PKSymbolState.m.svn-base @@ -0,0 +1,107 @@ +// +// PKSymbolState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; +@end + +@interface PKSymbolState () +- (PKToken *)symbolTokenWith:(PKUniChar)cin; +- (PKToken *)symbolTokenWithSymbol:(NSString *)s; + +@property (nonatomic, retain) PKSymbolRootNode *rootNode; +@property (nonatomic, retain) NSMutableArray *addedSymbols; +@end + +@implementation PKSymbolState + +- (id)init { + if (self = [super init]) { + self.rootNode = [[[PKSymbolRootNode alloc] init] autorelease]; + self.addedSymbols = [NSMutableArray array]; + } + return self; +} + + +- (void)dealloc { + self.rootNode = nil; + self.addedSymbols = nil; + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + NSString *symbol = [rootNode nextSymbol:r startingWith:cin]; + NSUInteger len = [symbol length]; + + while (len > 1) { + if ([addedSymbols containsObject:symbol]) { + return [self symbolTokenWithSymbol:symbol]; + } + + symbol = [symbol substringToIndex:[symbol length] - 1]; + len = [symbol length]; + [r unread:1]; + } + + if (1 == len) { + return [self symbolTokenWith:cin]; + } else { + PKTokenizerState *state = [self nextTokenizerStateFor:cin tokenizer:t]; + if (!state || state == self) { + return [self symbolTokenWith:cin]; + } else { + return [state nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + } +} + + +- (void)add:(NSString *)s { + NSParameterAssert(s); + [rootNode add:s]; + [addedSymbols addObject:s]; +} + + +- (void)remove:(NSString *)s { + NSParameterAssert(s); + [rootNode remove:s]; + [addedSymbols removeObject:s]; +} + + +- (PKToken *)symbolTokenWith:(PKUniChar)cin { + return [self symbolTokenWithSymbol:[NSString stringWithFormat:@"%C", cin]]; +} + + +- (PKToken *)symbolTokenWithSymbol:(NSString *)s { + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:s floatValue:0.0]; + tok.offset = offset; + return tok; +} + +@synthesize rootNode; +@synthesize addedSymbols; +@end diff --git a/src/.svn/text-base/PKTerminal.m.svn-base b/src/.svn/text-base/PKTerminal.m.svn-base new file mode 100644 index 0000000..ce0e7df --- /dev/null +++ b/src/.svn/text-base/PKTerminal.m.svn-base @@ -0,0 +1,95 @@ +// +// PKTerminal.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import + +@interface PKAssembly () +- (id)peek; +- (id)next; +- (BOOL)hasMore; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@end + +@interface PKTerminal () +- (PKAssembly *)matchOneAssembly:(PKAssembly *)inAssembly; +- (BOOL)qualifies:(id)obj; + +@property (nonatomic, readwrite, copy) NSString *string; +@end + +@implementation PKTerminal + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + if (self = [super init]) { + self.string = s; + } + return self; +} + + +- (void)dealloc { + self.string = nil; + [super dealloc]; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSMutableSet *outAssemblies = [NSMutableSet set]; + + for (PKAssembly *a in inAssemblies) { + PKAssembly *b = [self matchOneAssembly:a]; + if (b) { + [outAssemblies addObject:b]; + } + } + + return outAssemblies; +} + + +- (PKAssembly *)matchOneAssembly:(PKAssembly *)inAssembly { + NSParameterAssert(inAssembly); + if (![inAssembly hasMore]) { + return nil; + } + + PKAssembly *outAssembly = nil; + + if ([self qualifies:[inAssembly peek]]) { + outAssembly = [[inAssembly copy] autorelease]; + id obj = [outAssembly next]; + if (!discardFlag) { + [outAssembly push:obj]; + } + } + + return outAssembly; +} + + +- (BOOL)qualifies:(id)obj { + NSAssert1(0, @"-[PKTerminal %s] must be overriden", _cmd); + return NO; +} + + +- (PKTerminal *)discard { + discardFlag = YES; + return self; +} + +@synthesize string; +@end diff --git a/src/.svn/text-base/PKToken.m.svn-base b/src/.svn/text-base/PKToken.m.svn-base new file mode 100644 index 0000000..7ac0adf --- /dev/null +++ b/src/.svn/text-base/PKToken.m.svn-base @@ -0,0 +1,233 @@ +// +// PKToken.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface PKTokenEOF : PKToken {} ++ (PKTokenEOF *)instance; +@end + +@implementation PKTokenEOF + +static PKTokenEOF *EOFToken = nil; + ++ (PKTokenEOF *)instance { + @synchronized(self) { + if (!EOFToken) { + [[self alloc] init]; // assignment not done here + } + } + return EOFToken; +} + + ++ (id)allocWithZone:(NSZone *)zone { + @synchronized(self) { + if (!EOFToken) { + EOFToken = [super allocWithZone:zone]; + return EOFToken; // assignment and return on first allocation + } + } + return nil; //on subsequent allocation attempts return nil +} + + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + + +- (id)retain { + return self; +} + + +- (void)release { + // do nothing +} + + +- (id)autorelease { + return self; +} + + +- (NSUInteger)retainCount { + return UINT_MAX; // denotes an object that cannot be released +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", self]; +} + + +- (NSString *)debugDescription { + return [self description]; +} + + +- (NSUInteger)offset { + return -1; +} + +@end + +@interface PKToken () +- (BOOL)isEqual:(id)obj ignoringCase:(BOOL)ignoringCase; + +@property (nonatomic, readwrite, getter=isNumber) BOOL number; +@property (nonatomic, readwrite, getter=isQuotedString) BOOL quotedString; +@property (nonatomic, readwrite, getter=isSymbol) BOOL symbol; +@property (nonatomic, readwrite, getter=isWord) BOOL word; +@property (nonatomic, readwrite, getter=isWhitespace) BOOL whitespace; +@property (nonatomic, readwrite, getter=isComment) BOOL comment; +@property (nonatomic, readwrite, getter=isDelimitedString) BOOL delimitedString; + +@property (nonatomic, readwrite) CGFloat floatValue; +@property (nonatomic, readwrite, copy) NSString *stringValue; +@property (nonatomic, readwrite) PKTokenType tokenType; +@property (nonatomic, readwrite, copy) id value; + +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@implementation PKToken + ++ (PKToken *)EOFToken { + return [PKTokenEOF instance]; +} + + ++ (id)tokenWithTokenType:(PKTokenType)t stringValue:(NSString *)s floatValue:(CGFloat)n { + return [[[self alloc] initWithTokenType:t stringValue:s floatValue:n] autorelease]; +} + + +// designated initializer +- (id)initWithTokenType:(PKTokenType)t stringValue:(NSString *)s floatValue:(CGFloat)n { + //NSParameterAssert(s); + if (self = [super init]) { + self.tokenType = t; + self.stringValue = s; + self.floatValue = n; + + self.number = (PKTokenTypeNumber == t); + self.quotedString = (PKTokenTypeQuotedString == t); + self.symbol = (PKTokenTypeSymbol == t); + self.word = (PKTokenTypeWord == t); + self.whitespace = (PKTokenTypeWhitespace == t); + self.comment = (PKTokenTypeComment == t); + self.delimitedString = (PKTokenTypeDelimitedString == t); + } + return self; +} + + +- (void)dealloc { + self.stringValue = nil; + self.value = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + return [self retain]; // tokens are immutable +} + + +- (NSUInteger)hash { + return [stringValue hash]; +} + + +- (BOOL)isEqual:(id)obj { + return [self isEqual:obj ignoringCase:NO]; +} + + +- (BOOL)isEqualIgnoringCase:(id)obj { + return [self isEqual:obj ignoringCase:YES]; +} + + +- (BOOL)isEqual:(id)obj ignoringCase:(BOOL)ignoringCase { + if (![obj isMemberOfClass:[PKToken class]]) { + return NO; + } + + PKToken *tok = (PKToken *)obj; + if (tokenType != tok.tokenType) { + return NO; + } + + if (self.isNumber) { + return floatValue == tok.floatValue; + } else { + if (ignoringCase) { + return (NSOrderedSame == [stringValue caseInsensitiveCompare:tok.stringValue]); + } else { + return [stringValue isEqualToString:tok.stringValue]; + } + } +} + + +- (id)value { + if (!value) { + id v = nil; + if (self.isNumber) { + v = [NSNumber numberWithFloat:floatValue]; + } else { + v = stringValue; + } + self.value = v; + } + return value; +} + + +- (NSString *)debugDescription { + NSString *typeString = nil; + if (self.isNumber) { + typeString = @"Number"; + } else if (self.isQuotedString) { + typeString = @"Quoted String"; + } else if (self.isSymbol) { + typeString = @"Symbol"; + } else if (self.isWord) { + typeString = @"Word"; + } else if (self.isWhitespace) { + typeString = @"Whitespace"; + } else if (self.isComment) { + typeString = @"Comment"; + } else if (self.isDelimitedString) { + typeString = @"Delimited String"; + } + return [NSString stringWithFormat:@"<%@ %C%@%C>", typeString, 0x00AB, self.value, 0x00BB]; +} + + +- (NSString *)description { + return stringValue; +} + +@synthesize number; +@synthesize quotedString; +@synthesize symbol; +@synthesize word; +@synthesize whitespace; +@synthesize comment; +@synthesize delimitedString; +@synthesize floatValue; +@synthesize stringValue; +@synthesize tokenType; +@synthesize value; +@synthesize offset; +@end diff --git a/src/.svn/text-base/PKTokenArraySource.m.svn-base b/src/.svn/text-base/PKTokenArraySource.m.svn-base new file mode 100644 index 0000000..916c6da --- /dev/null +++ b/src/.svn/text-base/PKTokenArraySource.m.svn-base @@ -0,0 +1,79 @@ +// +// PKTokenArraySource.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/11/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import + +@interface PKTokenArraySource () +@property (nonatomic, retain) PKTokenizer *tokenizer; +@property (nonatomic, retain) NSString *delimiter; +@property (nonatomic, retain) PKToken *nextToken; +@end + +@implementation PKTokenArraySource + +- (id)init { + return [self initWithTokenizer:nil delimiter:nil]; +} + + +- (id)initWithTokenizer:(PKTokenizer *)t delimiter:(NSString *)s { + NSParameterAssert(t); + NSParameterAssert(s); + if (self = [super init]) { + self.tokenizer = t; + self.delimiter = s; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.delimiter = nil; + self.nextToken = nil; + [super dealloc]; +} + + +- (BOOL)hasMore { + if (!nextToken) { + self.nextToken = [tokenizer nextToken]; + } + + return ([PKToken EOFToken] != nextToken); +} + + +- (NSArray *)nextTokenArray { + if (![self hasMore]) { + return nil; + } + + NSMutableArray *res = [NSMutableArray arrayWithObject:nextToken]; + self.nextToken = nil; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + while ((tok = [tokenizer nextToken]) != eof) { + if ([tok.stringValue isEqualToString:delimiter]) { + break; // discard delimiter tok + } + [res addObject:tok]; + } + + //return [[res copy] autorelease]; + return res; // optimization +} + +@synthesize tokenizer; +@synthesize delimiter; +@synthesize nextToken; +@end diff --git a/src/.svn/text-base/PKTokenAssembly.m.svn-base b/src/.svn/text-base/PKTokenAssembly.m.svn-base new file mode 100644 index 0000000..52d5774 --- /dev/null +++ b/src/.svn/text-base/PKTokenAssembly.m.svn-base @@ -0,0 +1,198 @@ +// +// PKTokenAssembly.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import + +@interface PKTokenAssembly () +- (id)initWithString:(NSString *)s tokenzier:(PKTokenizer *)t tokenArray:(NSArray *)a; +- (void)tokenize; +- (NSString *)objectsFrom:(PKUniChar)start to:(PKUniChar)end separatedBy:(NSString *)delimiter; + +@property (nonatomic, retain) PKTokenizer *tokenizer; +@property (nonatomic, copy) NSArray *tokens; +@end + +@implementation PKTokenAssembly + ++ (id)assemblyWithTokenizer:(PKTokenizer *)t { + return [[[self alloc] initWithTokenzier:t] autorelease]; +} + + +- (id)initWithTokenzier:(PKTokenizer *)t { + return [self initWithString:t.string tokenzier:t tokenArray:nil]; +} + + ++ (id)assemblyWithTokenArray:(NSArray *)a { + return [[[self alloc] initWithTokenArray:a] autorelease]; +} + + +- (id)initWithTokenArray:(NSArray *)a { + return [self initWithString:[a componentsJoinedByString:@""] tokenzier:nil tokenArray:a]; +} + + +- (id)initWithString:(NSString *)s { + return [self initWithTokenzier:[[[PKTokenizer alloc] initWithString:s] autorelease]]; +} + + +// designated initializer. this method is private and should not be called from other classes +- (id)initWithString:(NSString *)s tokenzier:(PKTokenizer *)t tokenArray:(NSArray *)a { + self = [super initWithString:s]; + if (self) { + if (t) { + self.tokenizer = t; + } else { + self.tokens = a; + } + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.tokens = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKTokenAssembly *a = (PKTokenAssembly *)[super copyWithZone:zone]; + a->tokenizer = nil; // optimization + if (tokens) { + a->tokens = [tokens copyWithZone:zone]; + } else { + a->tokens = nil; + } + + a->preservesWhitespaceTokens = preservesWhitespaceTokens; + return a; +} + + +- (NSArray *)tokens { + if (!tokens) { + [self tokenize]; + } + return tokens; +} + + +- (id)peek { + PKToken *tok = nil; + NSArray *toks = self.tokens; + + while (1) { + if (index >= [toks count]) { + tok = nil; + break; + } + + tok = [toks objectAtIndex:index]; + if (!preservesWhitespaceTokens) { + break; + } + if (PKTokenTypeWhitespace == tok.tokenType) { + [self push:tok]; + index++; + } else { + break; + } + } + + return tok; +} + + +- (id)next { + id tok = [self peek]; + if (tok) { + index++; + } + return tok; +} + + +- (BOOL)hasMore { + return (index < [self.tokens count]); +} + + +- (NSUInteger)length { + return [self.tokens count]; +} + + +- (NSUInteger)objectsConsumed { + return index; +} + + +- (NSUInteger)objectsRemaining { + return ([self.tokens count] - index); +} + + +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter { + NSParameterAssert(delimiter); + return [self objectsFrom:0 to:self.objectsConsumed separatedBy:delimiter]; +} + + +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter { + NSParameterAssert(delimiter); + return [self objectsFrom:self.objectsConsumed to:[self length] separatedBy:delimiter]; +} + + +#pragma mark - +#pragma mark Private + +- (void)tokenize { + if (!tokenizer) { + self.tokenizer = [PKTokenizer tokenizerWithString:string]; + } + + NSMutableArray *a = [NSMutableArray array]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + while ((tok = [tokenizer nextToken]) != eof) { + [a addObject:tok]; + } + + self.tokens = a; +} + + +- (NSString *)objectsFrom:(PKUniChar)start to:(PKUniChar)end separatedBy:(NSString *)delimiter { + NSMutableString *s = [NSMutableString string]; + NSArray *toks = self.tokens; + + NSInteger i = start; + for ( ; i < end; i++) { + PKToken *tok = [toks objectAtIndex:i]; + [s appendString:tok.stringValue]; + if (end - 1 != i) { + [s appendString:delimiter]; + } + } + + return [[s copy] autorelease]; +} + +@synthesize tokenizer; +@synthesize tokens; +@synthesize preservesWhitespaceTokens; +@end diff --git a/src/.svn/text-base/PKTokenizer.m.svn-base b/src/.svn/text-base/PKTokenizer.m.svn-base new file mode 100644 index 0000000..e9b3efc --- /dev/null +++ b/src/.svn/text-base/PKTokenizer.m.svn-base @@ -0,0 +1,233 @@ +// +// ParseKit.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +#define STATE_COUNT 256 + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizer () +- (PKTokenizerState *)tokenizerStateFor:(PKUniChar)c; +- (PKTokenizerState *)defaultTokenizerStateFor:(PKUniChar)c; +@property (nonatomic, retain) PKReader *reader; +@property (nonatomic, retain) NSMutableArray *tokenizerStates; +@end + +@implementation PKTokenizer + ++ (id)tokenizer { + return [self tokenizerWithString:nil]; +} + + ++ (id)tokenizerWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + if (self = [super init]) { + self.string = s; + self.reader = [[[PKReader alloc] init] autorelease]; + + self.numberState = [[[PKNumberState alloc] init] autorelease]; + self.quoteState = [[[PKQuoteState alloc] init] autorelease]; + self.commentState = [[[PKCommentState alloc] init] autorelease]; + self.symbolState = [[[PKSymbolState alloc] init] autorelease]; + self.whitespaceState = [[[PKWhitespaceState alloc] init] autorelease]; + self.wordState = [[[PKWordState alloc] init] autorelease]; + self.delimitState = [[[PKDelimitState alloc] init] autorelease]; + + self.tokenizerStates = [NSMutableArray arrayWithCapacity:STATE_COUNT]; + + NSInteger i = 0; + for ( ; i < STATE_COUNT; i++) { + [tokenizerStates addObject:[self defaultTokenizerStateFor:i]]; + } + + [symbolState add:@"<="]; + [symbolState add:@">="]; + [symbolState add:@"!="]; + [symbolState add:@"=="]; + + [commentState addSingleLineStartMarker:@"//"]; + [commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + [self setTokenizerState:commentState from:'/' to:'/']; + } + return self; +} + + +- (void)dealloc { + self.string = nil; + self.reader = nil; + self.tokenizerStates = nil; + self.numberState = nil; + self.quoteState = nil; + self.commentState = nil; + self.symbolState = nil; + self.whitespaceState = nil; + self.wordState = nil; + self.delimitState = nil; + [super dealloc]; +} + + +- (PKToken *)nextToken { + PKUniChar c = [reader read]; + + PKToken *result = nil; + + if (PKEOF == c) { + result = [PKToken EOFToken]; + } else { + PKTokenizerState *state = [self tokenizerStateFor:c]; + if (state) { + result = [state nextTokenFromReader:reader startingWith:c tokenizer:self]; + } else { + result = [PKToken EOFToken]; + } + } + + return result; +} + + +#ifdef TARGET_OS_SNOW_LEOPARD +- (void)enumerateTokensUsingBlock:(void (^)(PKToken *tok, BOOL *stop))block { + PKToken *eof = [PKToken EOFToken]; + + PKToken *tok = nil; + BOOL stop = NO; + + while ((tok = [self nextToken]) != eof) { + block(tok, &stop); + if (stop) break; + } +} +#endif + + +- (void)setTokenizerState:(PKTokenizerState *)state from:(PKUniChar)start to:(PKUniChar)end { + NSParameterAssert(state); + + NSInteger i = start; + for ( ; i <= end; i++) { + [tokenizerStates replaceObjectAtIndex:i withObject:state]; + } +} + + +- (void)setReader:(PKReader *)r { + if (reader != r) { + [reader release]; + reader = [r retain]; + reader.string = string; + } +} + + +- (void)setString:(NSString *)s { + if (string != s) { + [string release]; + string = [s retain]; + } + reader.string = string; +} + + +#pragma mark - + +- (PKTokenizerState *)tokenizerStateFor:(PKUniChar)c { + if (c < 0 || c > 255) { + // customization above 255 is not supported, so fetch default. + return [self defaultTokenizerStateFor:c]; + } else { + // customization below 255 is supported, so be sure to get the (possibly) customized state from `tokenizerStates` + return [tokenizerStates objectAtIndex:c]; + } +} + +- (PKTokenizerState *)defaultTokenizerStateFor:(PKUniChar)c { + if (c >= 0 && c <= ' ') { // From: 0 to: 32 From:0x00 to:0x20 + return whitespaceState; + } else if (c == 33) { + return symbolState; + } else if (c == '"') { // From: 34 to: 34 From:0x22 to:0x22 + return quoteState; + } else if (c >= 35 && c <= 38) { + return symbolState; + } else if (c == '\'') { // From: 39 to: 39 From:0x27 to:0x27 + return quoteState; + } else if (c >= 40 && c <= 42) { + return symbolState; + } else if (c == '+') { // From: 43 to: 43 From:0x2B to:0x2B + return symbolState; + } else if (c == 44) { + return symbolState; + } else if (c == '-') { // From: 45 to: 45 From:0x2D to:0x2D + return numberState; + } else if (c == '.') { // From: 46 to: 46 From:0x2E to:0x2E + return numberState; + } else if (c == '/') { // From: 47 to: 47 From:0x2F to:0x2F + return symbolState; + } else if (c >= '0' && c <= '9') { // From: 48 to: 57 From:0x30 to:0x39 + return numberState; + } else if (c >= 58 && c <= 64) { + return symbolState; + } else if (c >= 'A' && c <= 'Z') { // From: 65 to: 90 From:0x41 to:0x5A + return wordState; + } else if (c >= 91 && c <= 96) { + return symbolState; + } else if (c >= 'a' && c <= 'z') { // From: 97 to:122 From:0x61 to:0x7A + return wordState; + } else if (c >= 123 && c <= 191) { + return symbolState; + } else if (c >= 0xC0 && c <= 0xFF) { // From:192 to:255 From:0xC0 to:0xFF + return wordState; + } else if (c >= 0x19E0 && c <= 0x19FF) { // khmer symbols + return symbolState; + } else if (c >= 0x2000 && c <= 0x2BFF) { // various symbols + return symbolState; + } else if (c >= 0x2E00 && c <= 0x2E7F) { // supplemental punctuation + return symbolState; + } else if (c >= 0x3000 && c <= 0x303F) { // cjk symbols & punctuation + return symbolState; + } else if (c >= 0x3200 && c <= 0x33FF) { // enclosed cjk letters and months, cjk compatibility + return symbolState; + } else if (c >= 0x4DC0 && c <= 0x4DFF) { // yijing hexagram symbols + return symbolState; + } else if (c >= 0xFE30 && c <= 0xFE6F) { // cjk compatibility forms, small form variants + return symbolState; + } else if (c >= 0xFF00 && c <= 0xFFFF) { // hiragana & katakana halfwitdh & fullwidth forms, Specials + return symbolState; + } else { + return wordState; + } +} + +@synthesize numberState; +@synthesize quoteState; +@synthesize commentState; +@synthesize symbolState; +@synthesize whitespaceState; +@synthesize wordState; +@synthesize delimitState; +@synthesize string; +@synthesize reader; +@synthesize tokenizerStates; +@end diff --git a/src/.svn/text-base/PKTokenizerState.m.svn-base b/src/.svn/text-base/PKTokenizerState.m.svn-base new file mode 100644 index 0000000..f700b15 --- /dev/null +++ b/src/.svn/text-base/PKTokenizerState.m.svn-base @@ -0,0 +1,113 @@ +// +// PKTokenizerState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import + +#define STATE_COUNT 256 + +@interface PKTokenizer () +- (PKTokenizerState *)defaultTokenizerStateFor:(PKUniChar)c; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (void)appendString:(NSString *)s; +- (NSString *)bufferedString; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; + +@property (nonatomic, retain) NSMutableString *stringbuf; +@property (nonatomic) NSUInteger offset; +@property (nonatomic, retain) NSMutableArray *fallbackStates; +@end + +@implementation PKTokenizerState + +- (void)dealloc { + self.stringbuf = nil; + self.fallbackState = nil; + self.fallbackStates = nil; + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSAssert1(0, @"PKTokenizerState is an abstract classs. %s must be overriden", _cmd); + return nil; +} + + +- (void)setFallbackState:(PKTokenizerState *)state from:(PKUniChar)start to:(PKUniChar)end { + NSParameterAssert(start >= 0 && start < STATE_COUNT); + NSParameterAssert(end >= 0 && end < STATE_COUNT); + + if (!fallbackStates) { + self.fallbackStates = [NSMutableArray arrayWithCapacity:STATE_COUNT]; + + NSInteger i = 0; + for ( ; i < STATE_COUNT; i++) { + [fallbackStates addObject:[NSNull null]]; + } + + } + + NSInteger i = start; + for ( ; i <= end; i++) { + [fallbackStates replaceObjectAtIndex:i withObject:state]; + } +} + + +- (void)resetWithReader:(PKReader *)r { + self.stringbuf = [NSMutableString string]; + self.offset = r.offset - 1; +} + + +- (void)append:(PKUniChar)c { + NSParameterAssert(c > -1); + [stringbuf appendFormat:@"%C", c]; +} + + +- (void)appendString:(NSString *)s { + NSParameterAssert(s); + [stringbuf appendString:s]; +} + + +- (NSString *)bufferedString { + return [[stringbuf copy] autorelease]; +} + + +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t { + NSParameterAssert(c < STATE_COUNT); + + if (fallbackStates) { + id obj = [fallbackStates objectAtIndex:c]; + if ([NSNull null] != obj) { + return obj; + } + } + + if (fallbackState) { + return fallbackState; + } else { + return [t defaultTokenizerStateFor:c]; + } +} + +@synthesize stringbuf; +@synthesize offset; +@synthesize fallbackState; +@synthesize fallbackStates; +@end diff --git a/src/.svn/text-base/PKTrack.m.svn-base b/src/.svn/text-base/PKTrack.m.svn-base new file mode 100644 index 0000000..2599575 --- /dev/null +++ b/src/.svn/text-base/PKTrack.m.svn-base @@ -0,0 +1,91 @@ +// +// PKTrack.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import + +@interface PKAssembly () +- (id)peek; +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter; +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (PKAssembly *)best:(NSSet *)inAssemblies; +@end + +@interface PKTrack () +- (void)throwTrackExceptionWithPreviousState:(NSSet *)inAssemblies parser:(PKParser *)p; +@end + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; +@end + +@implementation PKTrack + ++ (id)track { + return [self trackWithSubparsers:nil]; +} + + ++ (id)trackWithSubparsers:(PKParser *)p1, ... { + va_list vargs; + va_start(vargs, p1); + PKTrack *tr = [self collectionParserWithFirst:p1 rest:vargs]; + va_end(vargs); + return tr; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + BOOL inTrack = NO; + NSSet *lastAssemblies = inAssemblies; + NSSet *outAssemblies = inAssemblies; + + for (PKParser *p in subparsers) { + outAssemblies = [p matchAndAssemble:outAssemblies]; + if (![outAssemblies count]) { + if (inTrack) { + [self throwTrackExceptionWithPreviousState:lastAssemblies parser:p]; + } + break; + } + inTrack = YES; + lastAssemblies = outAssemblies; + } + + return outAssemblies; +} + + +- (void)throwTrackExceptionWithPreviousState:(NSSet *)inAssemblies parser:(PKParser *)p { + PKAssembly *best = [self best:inAssemblies]; + + NSString *after = [best consumedObjectsJoinedByString:@" "]; + if (![after length]) { + after = @"-nothing-"; + } + + NSString *expected = [p description]; + + id next = [best peek]; + NSString *found = next ? [next description] : @"-nothing-"; + + NSString *reason = [NSString stringWithFormat:@"\n\nAfter : %@\nExpected : %@\nFound : %@\n\n", after, expected, found]; + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: + after, @"after", + expected, @"expected", + found, @"found", + nil]; + [[PKTrackException exceptionWithName:PKTrackExceptionName reason:reason userInfo:userInfo] raise]; +} + +@end diff --git a/src/.svn/text-base/PKTrackException.m.svn-base b/src/.svn/text-base/PKTrackException.m.svn-base new file mode 100644 index 0000000..6e2a9a5 --- /dev/null +++ b/src/.svn/text-base/PKTrackException.m.svn-base @@ -0,0 +1,15 @@ +// +// PKTrackException.m +// ParseKit +// +// Created by Todd Ditchendorf on 10/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKTrackException.h" + +NSString * const PKTrackExceptionName = @"Track Exception"; + +@implementation PKTrackException + +@end diff --git a/src/.svn/text-base/PKUppercaseWord.m.svn-base b/src/.svn/text-base/PKUppercaseWord.m.svn-base new file mode 100644 index 0000000..e816465 --- /dev/null +++ b/src/.svn/text-base/PKUppercaseWord.m.svn-base @@ -0,0 +1,24 @@ +// +// PKUppercaseWord.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKUppercaseWord + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + NSString *s = tok.stringValue; + return [s length] && isupper([s characterAtIndex:0]); +} + +@end diff --git a/src/.svn/text-base/PKWhitespace.m.svn-base b/src/.svn/text-base/PKWhitespace.m.svn-base new file mode 100644 index 0000000..91c16af --- /dev/null +++ b/src/.svn/text-base/PKWhitespace.m.svn-base @@ -0,0 +1,24 @@ +// +// PKWhitespace.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/19/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKWhitespace.h" +#import + +@implementation PKWhitespace + ++ (id)whitespace { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isWhitespace; +} + +@end \ No newline at end of file diff --git a/src/.svn/text-base/PKWhitespaceState.m.svn-base b/src/.svn/text-base/PKWhitespaceState.m.svn-base new file mode 100644 index 0000000..a7b1ac4 --- /dev/null +++ b/src/.svn/text-base/PKWhitespaceState.m.svn-base @@ -0,0 +1,106 @@ +// +// PKWhitespaceState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import + +#define PKTRUE (id)kCFBooleanTrue +#define PKFALSE (id)kCFBooleanFalse + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface PKWhitespaceState () +@property (nonatomic, retain) NSMutableArray *whitespaceChars; +@end + +@implementation PKWhitespaceState + +- (id)init { + if (self = [super init]) { + const NSUInteger len = 255; + self.whitespaceChars = [NSMutableArray arrayWithCapacity:len]; + NSUInteger i = 0; + for ( ; i <= len; i++) { + [whitespaceChars addObject:PKFALSE]; + } + + [self setWhitespaceChars:YES from:0 to:' ']; + } + return self; +} + + +- (void)dealloc { + self.whitespaceChars = nil; + [super dealloc]; +} + + +- (void)setWhitespaceChars:(BOOL)yn from:(PKUniChar)start to:(PKUniChar)end { + NSUInteger len = [whitespaceChars count]; + if (start > len || end > len || start < 0 || end < 0) { + [NSException raise:@"PKWhitespaceStateNotSupportedException" format:@"PKWhitespaceState only supports setting word chars for chars in the latin1 set (under 256)"]; + } + + id obj = yn ? PKTRUE : PKFALSE; + NSUInteger i = start; + for ( ; i <= end; i++) { + [whitespaceChars replaceObjectAtIndex:i withObject:obj]; + } +} + + +- (BOOL)isWhitespaceChar:(PKUniChar)cin { + if (cin < 0 || cin > [whitespaceChars count] - 1) { + return NO; + } + return PKTRUE == [whitespaceChars objectAtIndex:cin]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + if (reportsWhitespaceTokens) { + [self resetWithReader:r]; + } + + PKUniChar c = cin; + while ([self isWhitespaceChar:c]) { + if (reportsWhitespaceTokens) { + [self append:c]; + } + c = [r read]; + } + if (PKEOF != c) { + [r unread]; + } + + if (reportsWhitespaceTokens) { + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeWhitespace stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; + } else { + return [t nextToken]; + } +} + +@synthesize whitespaceChars; +@synthesize reportsWhitespaceTokens; +@end + diff --git a/src/.svn/text-base/PKWord.m.svn-base b/src/.svn/text-base/PKWord.m.svn-base new file mode 100644 index 0000000..6756f1e --- /dev/null +++ b/src/.svn/text-base/PKWord.m.svn-base @@ -0,0 +1,24 @@ +// +// PKWord.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@implementation PKWord + ++ (id)word { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isWord; +} + +@end diff --git a/src/.svn/text-base/PKWordState.m.svn-base b/src/.svn/text-base/PKWordState.m.svn-base new file mode 100644 index 0000000..0f3d984 --- /dev/null +++ b/src/.svn/text-base/PKWordState.m.svn-base @@ -0,0 +1,120 @@ +// +// PKWordState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import + +#define PKTRUE (id)kCFBooleanTrue +#define PKFALSE (id)kCFBooleanFalse + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface PKWordState () +- (BOOL)isWordChar:(PKUniChar)c; + +@property (nonatomic, retain) NSMutableArray *wordChars; +@end + +@implementation PKWordState + +- (id)init { + if (self = [super init]) { + self.wordChars = [NSMutableArray arrayWithCapacity:256]; + NSInteger i = 0; + for ( ; i < 256; i++) { + [wordChars addObject:PKFALSE]; + } + + [self setWordChars:YES from: 'a' to: 'z']; + [self setWordChars:YES from: 'A' to: 'Z']; + [self setWordChars:YES from: '0' to: '9']; + [self setWordChars:YES from: '-' to: '-']; + [self setWordChars:YES from: '_' to: '_']; + [self setWordChars:YES from:'\'' to:'\'']; + [self setWordChars:YES from:0xC0 to:0xFF]; + } + return self; +} + + +- (void)dealloc { + self.wordChars = nil; + [super dealloc]; +} + + +- (void)setWordChars:(BOOL)yn from:(PKUniChar)start to:(PKUniChar)end { + NSUInteger len = [wordChars count]; + if (start > len || end > len || start < 0 || end < 0) { + [NSException raise:@"PKWordStateNotSupportedException" format:@"PKWordState only supports setting word chars for chars in the latin1 set (under 256)"]; + } + + id obj = yn ? PKTRUE : PKFALSE; + NSInteger i = start; + for ( ; i <= end; i++) { + [wordChars replaceObjectAtIndex:i withObject:obj]; + } +} + + +- (BOOL)isWordChar:(PKUniChar)c { + if (c > PKEOF && c < [wordChars count] - 1) { + return (PKTRUE == [wordChars objectAtIndex:c]); + } + + if (c >= 0x2000 && c <= 0x2BFF) { // various symbols + return NO; + } else if (c >= 0xFE30 && c <= 0xFE6F) { // general punctuation + return NO; + } else if (c >= 0xFE30 && c <= 0xFE6F) { // western musical symbols + return NO; + } else if (c >= 0xFF00 && c <= 0xFF65) { // symbols within Hiragana & Katakana + return NO; + } else if (c >= 0xFFF0 && c <= 0xFFFF) { // specials + return NO; + } else if (c < 0) { + return NO; + } else { + return YES; + } +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + PKUniChar c = cin; + do { + [self append:c]; + c = [r read]; + } while ([self isWordChar:c]); + + if (PKEOF != c) { + [r unread]; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; +} + + +@synthesize wordChars; +@end diff --git a/src/.svn/text-base/Reader.h.svn-base b/src/.svn/text-base/Reader.h.svn-base new file mode 100644 index 0000000..16f3983 --- /dev/null +++ b/src/.svn/text-base/Reader.h.svn-base @@ -0,0 +1,60 @@ +// +// TDReader.h +// TDParseKit +// +// Created by Todd Ditchendorf on 1/21/06. +// Copyright 2008 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class TDReader + @brief A character-stream reader that allows characters to be pushed back into the stream. +*/ +@interface TDReader : NSObject { + NSString *string; + NSUInteger offset; + NSUInteger length; +} + +/*! + @brief Designated Initializer. Initializes a reader with a given string. + @details Designated Initializer. + @param s string from which to read + @result an initialized reader +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief Read a single UTF-16 unicode character + @result The character read, or TDEOF (-1) if the end of the stream has been reached +*/ +- (TDUniChar)read; + +/*! + @brief Push back a single character + @details moves the offset back one position +*/ +- (void)unread; + +/*! + @brief Push back count characters + @param count of characters to push back + @details moves the offset back count positions +*/ +- (void)unread:(NSUInteger)count; + +/*! + @property string + @brief This reader's string. +*/ +@property (nonatomic, retain) NSString *string; + +/*! + @property offset + @brief This reader's current offset in string +*/ +@property (nonatomic, readonly) NSUInteger offset; +@end diff --git a/src/.svn/text-base/RegexKitLite.h.svn-base b/src/.svn/text-base/RegexKitLite.h.svn-base new file mode 100644 index 0000000..0161a71 --- /dev/null +++ b/src/.svn/text-base/RegexKitLite.h.svn-base @@ -0,0 +1,220 @@ +// +// RegexKitLite.h +// http://regexkit.sourceforge.net/ +// Licensed under the terms of the BSD License, as specified below. +// + +/* + Copyright (c) 2008-2009, John Engelhart + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the Zang Industries nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef __OBJC__ +#import +#import +#import +#import +#import +#endif // __OBJC__ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef REGEXKITLITE_VERSION_DEFINED +#define REGEXKITLITE_VERSION_DEFINED + +#define _RKL__STRINGIFY(b) #b +#define _RKL_STRINGIFY(a) _RKL__STRINGIFY(a) +#define _RKL_JOIN_VERSION(a,b) _RKL_STRINGIFY(a##.##b) +#define _RKL_VERSION_STRING(a,b) _RKL_JOIN_VERSION(a,b) + +#define REGEXKITLITE_VERSION_MAJOR 3 +#define REGEXKITLITE_VERSION_MINOR 0 + +#define REGEXKITLITE_VERSION_CSTRING _RKL_VERSION_STRING(REGEXKITLITE_VERSION_MAJOR, REGEXKITLITE_VERSION_MINOR) +#define REGEXKITLITE_VERSION_NSSTRING @REGEXKITLITE_VERSION_CSTRING + +#endif // REGEXKITLITE_VERSION_DEFINED + +// For Mac OS X < 10.5. +#ifndef NSINTEGER_DEFINED +#define NSINTEGER_DEFINED +#if defined(__LP64__) || defined(NS_BUILD_32_LIKE_64) +typedef long NSInteger; +typedef unsigned long NSUInteger; +#define NSIntegerMin LONG_MIN +#define NSIntegerMax LONG_MAX +#define NSUIntegerMax ULONG_MAX +#else // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64) +typedef int NSInteger; +typedef unsigned int NSUInteger; +#define NSIntegerMin INT_MIN +#define NSIntegerMax INT_MAX +#define NSUIntegerMax UINT_MAX +#endif // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64) +#endif // NSINTEGER_DEFINED + +#ifndef RKLREGEXOPTIONS_DEFINED +#define RKLREGEXOPTIONS_DEFINED + +// These must be idential to their ICU regex counterparts. See http://www.icu-project.org/userguide/regexp.html +enum { + RKLNoOptions = 0, + RKLCaseless = 2, + RKLComments = 4, + RKLDotAll = 32, + RKLMultiline = 8, + RKLUnicodeWordBoundaries = 256 +}; +typedef uint32_t RKLRegexOptions; // This must be identical to the ICU 'flags' argument type. + +#endif // RKLREGEXOPTIONS_DEFINED + +#ifndef _REGEXKITLITE_H_ +#define _REGEXKITLITE_H_ + +#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__APPLE_CC__) && (__APPLE_CC__ >= 5465) +#define RKL_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) +#else +#define RKL_DEPRECATED_ATTRIBUTE +#endif + +// This requires a few levels of rewriting to get the desired results. +#define _RKL_CONCAT_2(c,d) c ## d +#define _RKL_CONCAT(a,b) _RKL_CONCAT_2(a,b) + +#ifdef RKL_PREPEND_TO_METHODS +#define RKL_METHOD_PREPEND(x) _RKL_CONCAT(RKL_PREPEND_TO_METHODS, x) +#else // RKL_PREPEND_TO_METHODS +#define RKL_METHOD_PREPEND(x) x +#endif // RKL_PREPEND_TO_METHODS + +// If it looks like low memory notifications might be available, add code to register and respond to them. +// This is (should be) harmless if it turns out that this isn't the case, since the notification that we register for, +// UIApplicationDidReceiveMemoryWarningNotification, is dynamically looked up via dlsym(). +#if ((defined(TARGET_OS_EMBEDDED) && (TARGET_OS_EMBEDDED != 0)) || (defined(TARGET_OS_IPHONE) && (TARGET_OS_IPHONE != 0))) && (!defined(RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS) || (RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS != 0)) +#define RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS 1 +#endif + +#ifdef __OBJC__ + +// NSException exception name. +extern NSString * const RKLICURegexException; + +// NSError error domains and user info keys. +extern NSString * const RKLICURegexErrorDomain; + +extern NSString * const RKLICURegexErrorCodeErrorKey; +extern NSString * const RKLICURegexErrorNameErrorKey; +extern NSString * const RKLICURegexLineErrorKey; +extern NSString * const RKLICURegexOffsetErrorKey; +extern NSString * const RKLICURegexPreContextErrorKey; +extern NSString * const RKLICURegexPostContextErrorKey; +extern NSString * const RKLICURegexRegexErrorKey; +extern NSString * const RKLICURegexRegexOptionsErrorKey; + +@interface NSString (RegexKitLiteAdditions) + ++ (void)RKL_METHOD_PREPEND(clearStringCache); + +// Although these are marked as deprecated, a bug in GCC prevents a warning from being issues for + class methods. Filed bug with Apple, #6736857. ++ (NSInteger)RKL_METHOD_PREPEND(captureCountForRegex):(NSString *)regex RKL_DEPRECATED_ATTRIBUTE; ++ (NSInteger)RKL_METHOD_PREPEND(captureCountForRegex):(NSString *)regex options:(RKLRegexOptions)options error:(NSError **)error RKL_DEPRECATED_ATTRIBUTE; + +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex; +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex range:(NSRange)range; +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error; + +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex; +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex inRange:(NSRange)range; +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range error:(NSError **)error; + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex; +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex capture:(NSInteger)capture; +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex inRange:(NSRange)range; +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range capture:(NSInteger)capture error:(NSError **)error; + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex; +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex capture:(NSInteger)capture; +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex inRange:(NSRange)range; +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range capture:(NSInteger)capture error:(NSError **)error; + +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement; +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement range:(NSRange)searchRange; +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement options:(RKLRegexOptions)options range:(NSRange)searchRange error:(NSError **)error; + + //// + +- (NSInteger)RKL_METHOD_PREPEND(captureCount); +- (NSInteger)RKL_METHOD_PREPEND(captureCountWithOptions):(RKLRegexOptions)options error:(NSError **)error; + +- (BOOL)RKL_METHOD_PREPEND(isRegexValid); +- (BOOL)RKL_METHOD_PREPEND(isRegexValidWithOptions):(RKLRegexOptions)options error:(NSError **)error; + +- (void)RKL_METHOD_PREPEND(flushCachedRegexData); + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex; +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex capture:(NSInteger)capture; +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex range:(NSRange)range; +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range capture:(NSInteger)capture error:(NSError **)error; + + +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex; +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex range:(NSRange)range; +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error; + +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex; +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex range:(NSRange)range; +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error; + +@end + +@interface NSMutableString (RegexKitLiteAdditions) + +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement; +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement range:(NSRange)searchRange; +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement options:(RKLRegexOptions)options range:(NSRange)searchRange error:(NSError **)error; + +@end + +#endif // __OBJC__ + +#endif // _REGEXKITLITE_H_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/.svn/text-base/RegexKitLite.m.svn-base b/src/.svn/text-base/RegexKitLite.m.svn-base new file mode 100644 index 0000000..de1eca4 --- /dev/null +++ b/src/.svn/text-base/RegexKitLite.m.svn-base @@ -0,0 +1,1634 @@ +// +// RegexKitLite.m +// http://regexkit.sourceforge.net/ +// Licensed under the terms of the BSD License, as specified below. +// + +/* + Copyright (c) 2008-2009, John Engelhart + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the Zang Industries nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#import +#import +#import +#import +#import +#import +#ifdef __OBJC_GC__ +#import +#define RKL_STRONG_REF __strong +#else // __OBJC_GC__ +#define RKL_STRONG_REF +#endif // __OBJC_GC__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#import "RegexKitLite.h" + +// If the gcc flag -mmacosx-version-min is used with, for example, '=10.2', give a warning that the libicucore.dylib is only available on >= 10.3. +// If you are reading this comment because of this warning, this is to let you know that linking to /usr/lib/libicucore.dylib will cause your executable to fail on < 10.3. +// You will need to build your own version of the ICU library and link to that in order for RegexKitLite to work successfully on < 10.3. This is not simple. + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030 +#warning The ICU dynamic shared library, /usr/lib/libicucore.dylib, is only available on Mac OS X 10.3 and later. +#warning You will need to supply a version of the ICU library to use RegexKitLite on Mac OS X 10.2 and earlier. +#endif + +//////////// +#pragma mark Compile time tuneables + +#ifndef RKL_CACHE_SIZE +#define RKL_CACHE_SIZE (23UL) +#endif + +#ifndef RKL_FIXED_LENGTH +#define RKL_FIXED_LENGTH (2048UL) +#endif + +#ifndef RKL_STACK_LIMIT +#define RKL_STACK_LIMIT (128UL * 1024UL) +#endif + +#ifdef RKL_APPEND_TO_ICU_FUNCTIONS +#define RKL_ICU_FUNCTION_APPEND(x) _RKL_CONCAT(x, RKL_APPEND_TO_ICU_FUNCTIONS) +#else // RKL_APPEND_TO_ICU_FUNCTIONS +#define RKL_ICU_FUNCTION_APPEND(x) x +#endif // RKL_APPEND_TO_ICU_FUNCTIONS + +#if defined(RKL_DTRACE) && (RKL_DTRACE != 0) +#define _RKL_DTRACE_ENABLED +#endif // defined(RKL_DTRACE) && (RKL_DTRACE != 0) + +// These are internal, non-public tuneables. +#define RKL_SCRATCH_BUFFERS (4UL) +#define RKL_CACHE_LINE_SIZE (64UL) +#define RKL_DTRACE_REGEXUTF8_SIZE (64UL) + +////////////// +#pragma mark - +#pragma mark GCC / Compiler macros + +#if defined (__GNUC__) && (__GNUC__ >= 4) +#define RKL_ATTRIBUTES(attr, ...) __attribute__((attr, ##__VA_ARGS__)) +#define RKL_EXPECTED(cond, expect) __builtin_expect((long)(cond), (expect)) +#define RKL_PREFETCH(ptr) __builtin_prefetch(ptr) +#define RKL_PREFETCH_UNICHAR(ptr, off) { const char *p = ((const char *)(ptr)) + ((off) * sizeof(UniChar)) + RKL_CACHE_LINE_SIZE; RKL_PREFETCH(p); RKL_PREFETCH(p + RKL_CACHE_LINE_SIZE); } +#define RKL_HAVE_CLEANUP +#define RKL_CLEANUP(func) __attribute__((cleanup(func))) +#else // defined (__GNUC__) && (__GNUC__ >= 4) +#define RKL_ATTRIBUTES(attr, ...) +#define RKL_EXPECTED(cond, expect) cond +#define RKL_PREFETCH(ptr) +#define RKL_PREFETCH_UNICHAR(ptr, off) +#define RKL_CLEANUP(func) +#endif // defined (__GNUC__) && (__GNUC__ >= 4) + +#define RKL_STATIC_INLINE static __inline__ RKL_ATTRIBUTES(always_inline) +#define RKL_UNUSED_ARG RKL_ATTRIBUTES(unused) +#define RKL_NONNULL_ARGS(arg, ...) RKL_ATTRIBUTES(nonnull(arg, ##__VA_ARGS__)) +#define RKL_NONNULL_ARGS_WARN_UNUSED(arg, ...) RKL_ATTRIBUTES(warn_unused_result, nonnull(arg, ##__VA_ARGS__)) + +#if defined (__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) +#define RKL_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(as, nn, ...) RKL_ATTRIBUTES(warn_unused_result, nonnull(nn, ##__VA_ARGS__), alloc_size(as)) +#else // defined (__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) +#define RKL_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(as, nn, ...) RKL_ATTRIBUTES(warn_unused_result, nonnull(nn, ##__VA_ARGS__)) +#endif // defined (__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) + + +//////////// +#pragma mark - +#pragma mark Assertion macros + +// These macros are nearly identical to their NSCParameterAssert siblings. +// This is required because nearly everything is done while cacheSpinLock is locked. +// We need to safely unlock before throwing any of these exceptions. +// @try {} @finally {} significantly slows things down so it's not used. + +#define RKLCAssertDictionary(d, ...) rkl_makeAssertDictionary(__PRETTY_FUNCTION__, __FILE__, __LINE__, (d), ##__VA_ARGS__) +#define RKLCDelayedHardAssert(c, e, g) do { id *_e=(e); int _c=(c); if(RKL_EXPECTED(_e == NULL, 0L) || RKL_EXPECTED(*_e != NULL, 0L)) { goto g; } if(RKL_EXPECTED(!_c, 0L)) { *_e = RKLCAssertDictionary(@"Invalid parameter not satisfying: %s", #c); goto g; } } while(0) + +#ifdef NS_BLOCK_ASSERTIONS +#define RKLCDelayedAssert(c, e, g) +#define RKL_UNUSED_ASSERTION_ARG RKL_ATTRIBUTES(unused) +#else // NS_BLOCK_ASSERTIONS +#define RKLCDelayedAssert(c, e, g) RKLCDelayedHardAssert(c, e, g) +#define RKL_UNUSED_ASSERTION_ARG +#endif // NS_BLOCK_ASSERTIONS + +#define RKL_EXCEPTION(e, f, ...) [NSException exceptionWithName:(e) reason:rkl_stringFromClassAndMethod((self), (_cmd), (f), ##__VA_ARGS__) userInfo:NULL] +#define RKL_RAISE_EXCEPTION(e, f, ...) [RKL_EXCEPTION(e, f, ##__VA_ARGS__) raise] + +//////////// +#pragma mark - +#pragma mark Utility functions and macros + +RKL_STATIC_INLINE BOOL NSRangeInsideRange(NSRange cin, NSRange win) RKL_ATTRIBUTES(warn_unused_result); +RKL_STATIC_INLINE BOOL NSRangeInsideRange(NSRange cin, NSRange win) { return((((cin.location - win.location) <= win.length) && ((NSMaxRange(cin) - win.location) <= win.length)) ? YES : NO); } + +#define NSMakeRange(loc, len) ((NSRange){.location=(NSUInteger)(loc), .length=(NSUInteger)(len)}) +#define CFMakeRange(loc, len) ((CFRange){.location= (CFIndex)(loc), .length= (CFIndex)(len)}) +#define NSNotFoundRange ((NSRange){.location= NSNotFound, .length= 0UL}) +#define NSMaxiumRange ((NSRange){.location= 0UL, .length= NSUIntegerMax}) + +//////////// +#pragma mark - +#pragma mark Exported NSString symbols for exception names, error domains, error keys, etc + +NSString * const RKLICURegexException = @"RKLICURegexException"; + +NSString * const RKLICURegexErrorDomain = @"RKLICURegexErrorDomain"; + +NSString * const RKLICURegexErrorCodeErrorKey = @"RKLICURegexErrorCode"; +NSString * const RKLICURegexErrorNameErrorKey = @"RKLICURegexErrorName"; +NSString * const RKLICURegexLineErrorKey = @"RKLICURegexLine"; +NSString * const RKLICURegexOffsetErrorKey = @"RKLICURegexOffset"; +NSString * const RKLICURegexPreContextErrorKey = @"RKLICURegexPreContext"; +NSString * const RKLICURegexPostContextErrorKey = @"RKLICURegexPostContext"; +NSString * const RKLICURegexRegexErrorKey = @"RKLICURegexRegex"; +NSString * const RKLICURegexRegexOptionsErrorKey = @"RKLICURegexRegexOptions"; + +//////////// +#pragma mark - +#pragma mark Type / struct definitions + +// In general, the ICU bits and pieces here must exactly match the definition in the ICU sources. + +#define U_ZERO_ERROR 0 +#define U_INDEX_OUTOFBOUNDS_ERROR 8 +#define U_BUFFER_OVERFLOW_ERROR 15 + +#define U_PARSE_CONTEXT_LEN 16 + +typedef struct uregex uregex; // Opaque ICU regex type. + +typedef struct UParseError { // This must be exactly the same as the 'real' ICU declaration. + int32_t line; + int32_t offset; + UniChar preContext[U_PARSE_CONTEXT_LEN]; + UniChar postContext[U_PARSE_CONTEXT_LEN]; +} UParseError; + +// For use with GCC's cleanup() __attribute__. +#define RKLLockedCacheSpinLock ((NSUInteger)(1UL<<0)) +#define RKLUnlockedCacheSpinLock ((NSUInteger)(1UL<<1)) + +enum { + RKLSplitOp = 1, + RKLReplaceOp = 2, + RKLRangeOp = 3, + RKLArrayOfStringsOp = 4, + RKLArrayOfCapturesOp = 5, + RKLCapturesArrayOp = 6, + RKLMaskOp = 0xf, + RKLReplaceMutable = 1 << 4, + RKLSubcapturesArray = 1 << 5, +}; +typedef NSUInteger RKLRegexOp; + +typedef struct { + NSRange *ranges, findInRange; + NSInteger capacity, found, findUpTo, capture; + size_t size, stackUsed; + void **rangesScratchBuffer; + RKL_STRONG_REF void **stringsScratchBuffer; + RKL_STRONG_REF void **arraysScratchBuffer; +} RKLFindAll; + +typedef struct { + CFStringRef string; + CFHashCode hash; + CFIndex length; + RKL_STRONG_REF UniChar *uniChar; +} RKLBuffer; + +typedef struct { + CFStringRef regexString; + RKLRegexOptions options; + uregex *icu_regex; + NSInteger captureCount; + + CFStringRef setToString; + CFHashCode setToHash; + CFIndex setToLength; + NSUInteger setToIsImmutable:1; + NSUInteger setToNeedsConversion:1; + const UniChar *setToUniChar; + NSRange setToRange, lastFindRange, lastMatchRange; +#ifndef __LP64__ + NSUInteger pad[1]; // For 32 bits, this makes the struct 64 bytes exactly, which is good for cache line alignment. +#endif // __LP64__ +} RKLCacheSlot; + +//////////// +#pragma mark - +#pragma mark Translation unit scope global variables + +static UniChar fixedUniChar[(RKL_FIXED_LENGTH)]; // This is the fixed sized UTF-16 conversion buffer. +static RKLCacheSlot rkl_cacheSlots[(RKL_CACHE_SIZE)], *lastCacheSlot; +static OSSpinLock cacheSpinLock = OS_SPINLOCK_INIT; +static RKLBuffer dynamicBuffer, fixedBuffer = {NULL, 0UL, 0L, &fixedUniChar[0]}; +static const UniChar emptyUniCharString[1]; // For safety, icu_regexes are 'set' to this when the string they were searched is cleared. +static RKL_STRONG_REF void *scratchBuffer[(RKL_SCRATCH_BUFFERS)]; // Used to hold temporary allocations that are allocated via reallocf(). + +//////////// +#pragma mark - +#pragma mark CFArray call backs + +// These are used when running under manual memory management for the array that rkl_splitArray creates. +// The split strings are created, but not autoreleased. The (immutable) array is created using these callbacks, which skips the CFRetain() call, effectively transferring ownership to the CFArray object. +// For each split string this saves the overhead of an autorelease, then an array retain, then an NSAutoreleasePool release. This is good for a ~30% speed increase. + +static void RKLCFArrayRelease (CFAllocatorRef allocator RKL_UNUSED_ARG, const void *ptr) { CFRelease((CFTypeRef)ptr); } +static CFArrayCallBacks transferOwnershipArrayCallBacks = { (CFIndex)0L, NULL, RKLCFArrayRelease, CFCopyDescription, CFEqual }; + +#if defined(__OBJC_GC__) || defined(RKL_FORCE_GC) +//////////// +#pragma mark - +#pragma mark Low-level Garbage Collection aware memory/resource allocation utilities +// If compiled with Garbage Collection, we need to be able to do a few things slightly differently. +// The basic premiss is that under GC we use a trampoline function pointer which is set to a _start function to catch the first invocation. +// The _start function checks if GC is running and then overwrites the function pointer with the appropriate routine. Think of it as 'lazy linking'. + +enum { RKLScannedOption = NSScannedOption }; + +// rkl_collectingEnabled uses objc_getClass() to get the NSGarbageCollector class, which doesn't exist on earlier systems. +// This allows for graceful failure should we find ourselves running on an earlier version of the OS without NSGarbageCollector. +static BOOL rkl_collectingEnabled_first (void); +static BOOL rkl_collectingEnabled_yes (void) { return(YES); } +static BOOL rkl_collectingEnabled_no (void) { return(NO); } +static BOOL(*rkl_collectingEnabled) (void) = rkl_collectingEnabled_first; +static BOOL rkl_collectingEnabled_first (void) { + BOOL gcEnabled = ([objc_getClass("NSGarbageCollector") defaultCollector] != NULL) ? YES : NO; + if(gcEnabled == YES) { + // This section of code is required due to what I consider to be a fundamental design flaw in Cocoas GC system. + // Earlier versions of "Garbage Collection Programming Guide" stated that (paraphrased) "all globals are automatically roots". + // Current versions of the guide now include the following warning: + // "You may pass addresses of strong globals or statics into routines expecting pointers to object pointers (such as id* or NSError**) + // only if they have first been assigned to directly, rather than through a pointer dereference." + // This is a surprisingly non-trivial condition to actually meet in practice and is a recipe for impossible to debug race condition bugs. + // We just happen to be very, very, very lucky in the fact that we can initilize our root set before the first use. + int x; + for(x = 0; x < (int)(RKL_SCRATCH_BUFFERS); x++) { scratchBuffer[x] = NSAllocateCollectable(16UL, 0UL); scratchBuffer[x] = NULL; } + dynamicBuffer.uniChar = (RKL_STRONG_REF UniChar *)NSAllocateCollectable(16UL, 0UL); dynamicBuffer.uniChar = NULL; + } + return((rkl_collectingEnabled = (gcEnabled == YES) ? rkl_collectingEnabled_yes : rkl_collectingEnabled_no)()); +} + +// rkl_realloc() +static void *rkl_realloc_first (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags); +static void *rkl_realloc_std (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags RKL_UNUSED_ARG) { return((*ptr = reallocf(*ptr, size))); } +static void *rkl_realloc_gc (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags) { return((*ptr = NSReallocateCollectable(*ptr, (NSUInteger)size, flags))); } +static void *(*rkl_realloc) (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags) RKL_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(2,1) = rkl_realloc_first; +static void *rkl_realloc_first (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags) { return((rkl_realloc = (rkl_collectingEnabled()==YES) ? rkl_realloc_gc : rkl_realloc_std)(ptr, size, flags)); } + +// rkl_free() +static void * rkl_free_first (RKL_STRONG_REF void **ptr); +static void * rkl_free_std (RKL_STRONG_REF void **ptr) { if(*ptr != NULL) { free(*ptr); *ptr = NULL; } return(NULL); } +static void * rkl_free_gc (RKL_STRONG_REF void **ptr) { if(*ptr != NULL) { *ptr = NULL; } return(NULL); } +static void *(*rkl_free) (RKL_STRONG_REF void **ptr) RKL_NONNULL_ARGS(1) = rkl_free_first; +static void * rkl_free_first (RKL_STRONG_REF void **ptr) { return((rkl_free = (rkl_collectingEnabled()==YES) ? rkl_free_gc : rkl_free_std)(ptr)); } + +// rkl_CFAutorelease() +static id rkl_CFAutorelease_first (CFTypeRef obj); +static id rkl_CFAutorelease_std (CFTypeRef obj) { return([(id)obj autorelease]); } +static id rkl_CFAutorelease_gc (CFTypeRef obj) { return(NSMakeCollectable(obj)); } +static id(*rkl_CFAutorelease) (CFTypeRef obj) = rkl_CFAutorelease_first; +static id rkl_CFAutorelease_first (CFTypeRef obj) { return((rkl_CFAutorelease = (rkl_collectingEnabled()==YES) ? rkl_CFAutorelease_gc : rkl_CFAutorelease_std)(obj)); } + +// rkl_CreateStringWithSubstring() +static id rkl_CreateStringWithSubstring_first (id string, NSRange range); +static id rkl_CreateStringWithSubstring_std (id string, NSRange range) { return((id)CFStringCreateWithSubstring(NULL, (CFStringRef)string, CFMakeRange((CFIndex)range.location, (CFIndex)range.length))); } +static id rkl_CreateStringWithSubstring_gc (id string, NSRange range) { return([string substringWithRange:range]); } +static id(*rkl_CreateStringWithSubstring) (id string, NSRange range) RKL_NONNULL_ARGS_WARN_UNUSED(1) = rkl_CreateStringWithSubstring_first; +static id rkl_CreateStringWithSubstring_first (id string, NSRange range) { return((rkl_CreateStringWithSubstring = (rkl_collectingEnabled()==YES) ? rkl_CreateStringWithSubstring_gc : rkl_CreateStringWithSubstring_std)(string, range)); } + +// rkl_ReleaseObject() +static id rkl_ReleaseObject_first (id obj); +static id rkl_ReleaseObject_std (id obj) { CFRelease((CFTypeRef)obj); return(NULL); } +static id rkl_ReleaseObject_gc (id obj RKL_UNUSED_ARG) { return(NULL); } +static id (*rkl_ReleaseObject) (id obj) RKL_NONNULL_ARGS(1) = rkl_ReleaseObject_first; +static id rkl_ReleaseObject_first (id obj) { return((rkl_ReleaseObject = (rkl_collectingEnabled()==YES) ? rkl_ReleaseObject_gc : rkl_ReleaseObject_std)(obj)); } + +// rkl_CreateArrayWithObjects() +static id rkl_CreateArrayWithObjects_first (void **objects, NSUInteger count); +static id rkl_CreateArrayWithObjects_std (void **objects, NSUInteger count) { return((id)CFArrayCreate(NULL, (const void **)objects, (CFIndex)count, &transferOwnershipArrayCallBacks)); } +static id rkl_CreateArrayWithObjects_gc (void **objects, NSUInteger count) { return([NSArray arrayWithObjects:(const id *)objects count:count]); } +static id(*rkl_CreateArrayWithObjects) (void **objects, NSUInteger count) RKL_NONNULL_ARGS_WARN_UNUSED(1) = rkl_CreateArrayWithObjects_first; +static id rkl_CreateArrayWithObjects_first (void **objects, NSUInteger count) { return((rkl_CreateArrayWithObjects = (rkl_collectingEnabled()==YES) ? rkl_CreateArrayWithObjects_gc : rkl_CreateArrayWithObjects_std)(objects, count)); } + +// rkl_CreateAutoreleasedArray() +static id rkl_CreateAutoreleasedArray_first (void **objects, NSUInteger count); +static id rkl_CreateAutoreleasedArray_std (void **objects, NSUInteger count) { return((id)rkl_CFAutorelease(rkl_CreateArrayWithObjects(objects, count))); } +static id rkl_CreateAutoreleasedArray_gc (void **objects, NSUInteger count) { return(rkl_CreateArrayWithObjects(objects, count)); } +static id(*rkl_CreateAutoreleasedArray) (void **objects, NSUInteger count) RKL_NONNULL_ARGS_WARN_UNUSED(1) = rkl_CreateAutoreleasedArray_first; +static id rkl_CreateAutoreleasedArray_first (void **objects, NSUInteger count) { return((rkl_CreateAutoreleasedArray = (rkl_collectingEnabled()==YES) ? rkl_CreateAutoreleasedArray_gc : rkl_CreateAutoreleasedArray_std)(objects, count)); } + +#else // __OBJC_GC__ not defined +//////////// +#pragma mark - +#pragma mark Low-level explicit memory/resource allocation utilities + +enum { RKLScannedOption = 0 }; + +#define rkl_collectingEnabled() (NO) + +RKL_STATIC_INLINE void *rkl_realloc (void **ptr, size_t size, NSUInteger flags) RKL_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(2,1); +RKL_STATIC_INLINE void *rkl_free (void **ptr) RKL_NONNULL_ARGS(1); +RKL_STATIC_INLINE id rkl_CFAutorelease (CFTypeRef obj); +RKL_STATIC_INLINE id rkl_CreateAutoreleasedArray (void **objects, NSUInteger count) RKL_NONNULL_ARGS_WARN_UNUSED(1); +RKL_STATIC_INLINE id rkl_CreateArrayWithObjects (void **objects, NSUInteger count) RKL_NONNULL_ARGS_WARN_UNUSED(1); +RKL_STATIC_INLINE id rkl_CreateStringWithSubstring (id string, NSRange range) RKL_NONNULL_ARGS_WARN_UNUSED(1); +RKL_STATIC_INLINE id rkl_ReleaseObject (id obj) RKL_NONNULL_ARGS(1); + +RKL_STATIC_INLINE void *rkl_realloc (void **ptr, size_t size, NSUInteger flags RKL_UNUSED_ARG) { return((*ptr = reallocf(*ptr, size))); } +RKL_STATIC_INLINE void *rkl_free (void **ptr) { if(*ptr != NULL) { free(*ptr); *ptr = NULL; } return(NULL); } +RKL_STATIC_INLINE id rkl_CFAutorelease (CFTypeRef obj) { return([(id)obj autorelease]); } +RKL_STATIC_INLINE id rkl_CreateArrayWithObjects (void **objects, NSUInteger count) { return((id)CFArrayCreate(NULL, (const void **)objects, (CFIndex)count, &transferOwnershipArrayCallBacks)); } +RKL_STATIC_INLINE id rkl_CreateAutoreleasedArray (void **objects, NSUInteger count) { return(rkl_CFAutorelease(rkl_CreateArrayWithObjects(objects, count))); } +RKL_STATIC_INLINE id rkl_CreateStringWithSubstring (id string, NSRange range) { return((id)CFStringCreateWithSubstring(NULL, (CFStringRef)string, CFMakeRange((CFIndex)range.location, (CFIndex)[range length]))); } +RKL_STATIC_INLINE id rkl_ReleaseObject (id obj) { CFRelease((CFTypeRef)obj); return(NULL); } + +#endif // __OBJC_GC__ + +//////////// +#pragma mark - +#pragma mark ICU function prototypes + +// ICU functions. See http://www.icu-project.org/apiref/icu4c/uregex_8h.html Tweaked slightly from the originals, but functionally identical. +const char *RKL_ICU_FUNCTION_APPEND(u_errorName) (int32_t status) RKL_ATTRIBUTES(pure); +int32_t RKL_ICU_FUNCTION_APPEND(u_strlen) (const UniChar *s) RKL_ATTRIBUTES(nonnull(1), pure); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_appendReplacement) (uregex *regexp, const UniChar *replacementText, int32_t replacementLength, UniChar **destBuf, int32_t *destCapacity, int32_t *status) RKL_NONNULL_ARGS(1,2,4,5,6); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_appendTail) (uregex *regexp, UniChar **destBuf, int32_t *destCapacity, int32_t *status) RKL_NONNULL_ARGS(1,2,3,4); +void RKL_ICU_FUNCTION_APPEND(uregex_close) (uregex *regexp) RKL_NONNULL_ARGS(1); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_end) (uregex *regexp, int32_t groupNum, int32_t *status) RKL_NONNULL_ARGS(1,3); +BOOL RKL_ICU_FUNCTION_APPEND(uregex_find) (uregex *regexp, int32_t location, int32_t *status) RKL_NONNULL_ARGS(1,3); +BOOL RKL_ICU_FUNCTION_APPEND(uregex_findNext) (uregex *regexp, int32_t *status) RKL_NONNULL_ARGS(1,2); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_groupCount) (uregex *regexp, int32_t *status) RKL_NONNULL_ARGS(1,2); +uregex *RKL_ICU_FUNCTION_APPEND(uregex_open) (const UniChar *pattern, int32_t patternLength, RKLRegexOptions flags, UParseError *parseError, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,4,5); +void RKL_ICU_FUNCTION_APPEND(uregex_reset) (uregex *regexp, int32_t newIndex, int32_t *status) RKL_NONNULL_ARGS(1,3); +void RKL_ICU_FUNCTION_APPEND(uregex_setText) (uregex *regexp, const UniChar *text, int32_t textLength, int32_t *status) RKL_NONNULL_ARGS(1,2,4); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_start) (uregex *regexp, int32_t groupNum, int32_t *status) RKL_NONNULL_ARGS(1,3); + +//////////// +#pragma mark - +#pragma mark RegexKitLite internal, private function prototypes + +static RKLCacheSlot *rkl_getCachedRegex (NSString *regexString, RKLRegexOptions options, NSError **error, id *exception) RKL_NONNULL_ARGS_WARN_UNUSED(1,4); +static NSUInteger rkl_setCacheSlotToString (RKLCacheSlot *cacheSlot, const NSRange *range, int32_t *status, id *exception RKL_UNUSED_ASSERTION_ARG) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,3,4); +static RKLCacheSlot *rkl_getCachedRegexSetToString (NSString *regexString, RKLRegexOptions options, NSString *matchString, NSUInteger *matchLengthPtr, NSRange *matchRange, NSError **error, id *exception, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,3,4,5,7,8); +static id rkl_performRegexOp (id self, SEL _cmd, RKLRegexOp regexOp, NSString *regexString, RKLRegexOptions options, NSInteger capture, id matchString, NSRange *matchRange, NSString *replacementString, NSError **error, void *result) RKL_NONNULL_ARGS(1,2); +static void rkl_handleDelayedAssert (id self, SEL _cmd, id exception) RKL_NONNULL_ARGS(1,2,3); + +static NSUInteger rkl_search (RKLCacheSlot *cacheSlot, NSRange *searchRange, NSUInteger updateSearchRange, id *exception RKL_UNUSED_ASSERTION_ARG, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4,5); + +static BOOL rkl_findRanges (RKLCacheSlot *cacheSlot, RKLRegexOp regexOp, RKLFindAll *findAll, id *exception, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,3,4,5); +static NSUInteger rkl_growFindRanges (RKLCacheSlot *cacheSlot, NSUInteger lastLocation, RKLFindAll *findAll, id *exception RKL_UNUSED_ASSERTION_ARG) RKL_NONNULL_ARGS_WARN_UNUSED(1,3,4); +static NSArray *rkl_makeArray (RKLCacheSlot *cacheSlot, RKLRegexOp regexOp, RKLFindAll *findAll, id *exception RKL_UNUSED_ASSERTION_ARG) RKL_NONNULL_ARGS_WARN_UNUSED(1,3,4); + +static NSString *rkl_replaceString (RKLCacheSlot *cacheSlot, id searchString, NSUInteger searchU16Length, NSString *replacementString, NSUInteger replacementU16Length, NSUInteger *replacedCount, NSUInteger replaceMutable, id *exception, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4,8,9); +static int32_t rkl_replaceAll (RKLCacheSlot *cacheSlot, const UniChar *replacementUniChar, int32_t replacementU16Length, UniChar *replacedUniChar, int32_t replacedU16Capacity, NSUInteger *replacedCount, id *exception RKL_UNUSED_ASSERTION_ARG, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4,7,8); + +static NSUInteger rkl_isRegexValid (id self, SEL _cmd, NSString *regex, RKLRegexOptions options, NSInteger *captureCountPtr, NSError **error) RKL_NONNULL_ARGS(1,2); + +static void rkl_clearStringCache (void); +static void rkl_clearBuffer (RKLBuffer *buffer, NSUInteger freeDynamicBuffer) RKL_NONNULL_ARGS(1); +static void rkl_clearCacheSlotRegex (RKLCacheSlot *cacheSlot) RKL_NONNULL_ARGS(1); +static void rkl_clearCacheSlotSetTo (RKLCacheSlot *cacheSlot) RKL_NONNULL_ARGS(1); + +static NSDictionary *rkl_userInfoDictionary (NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status, ...) RKL_ATTRIBUTES(sentinel, nonnull(1), warn_unused_result); +static NSError *rkl_NSErrorForRegex (NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status) RKL_NONNULL_ARGS_WARN_UNUSED(1); +static NSException *rkl_NSExceptionForRegex (NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status) RKL_NONNULL_ARGS_WARN_UNUSED(1); +static NSDictionary *rkl_makeAssertDictionary (const char *function, const char *file, int line, NSString *format, ...) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4); +static NSString *rkl_stringFromClassAndMethod (id object, SEL selector, NSString *format, ...) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,3); + +RKL_STATIC_INLINE int32_t rkl_getRangeForCapture(RKLCacheSlot *cs, int32_t *s, int32_t c, NSRange *r) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4); +RKL_STATIC_INLINE int32_t rkl_getRangeForCapture(RKLCacheSlot *cs, int32_t *s, int32_t c, NSRange *r) { uregex *re = cs->icu_regex; int32_t start = RKL_ICU_FUNCTION_APPEND(uregex_start)(re, c, s); if(RKL_EXPECTED((*s > U_ZERO_ERROR), 0L) || (start == -1)) { *r = NSNotFoundRange; } else { r->location = (NSUInteger)start; r->length = (NSUInteger)RKL_ICU_FUNCTION_APPEND(uregex_end)(re, c, s) - r->location; r->location += cs->setToRange.location; } return(*s); } + +RKL_STATIC_INLINE RKLFindAll rkl_makeFindAll(NSRange *r, NSRange fir, NSInteger c, size_t s, size_t su, void **rsb, RKL_STRONG_REF void **ssb, RKL_STRONG_REF void **asb, NSInteger f, NSInteger cap, NSInteger fut) RKL_ATTRIBUTES(warn_unused_result); +RKL_STATIC_INLINE RKLFindAll rkl_makeFindAll(NSRange *r, NSRange fir, NSInteger c, size_t s, size_t su, void **rsb, RKL_STRONG_REF void **ssb, RKL_STRONG_REF void **asb, NSInteger f, NSInteger cap, NSInteger fut) { return(((RKLFindAll){ .ranges=r, .findInRange=fir, .capacity=c, .found=f, .findUpTo=fut, .capture=cap, .size=s, .stackUsed=su, .rangesScratchBuffer=rsb, .stringsScratchBuffer=ssb, .arraysScratchBuffer=asb})); } + +//////////// +#pragma mark - +#pragma mark RKL_FAST_MUTABLE_CHECK implementation + +#ifdef RKL_FAST_MUTABLE_CHECK +// We use a trampoline function pointer to check at run time if the function __CFStringIsMutable is available. +// If it is, the trampoline function pointer is replaced with the address of that function. +// Otherwise, we assume the worst case that every string is mutable. +// This hopefully helps to protect us since we're using an undocumented, non-public API call. +// We will keep on working if it ever does go away, just with a bit less performance due to the overhead of mutable checks. + +static BOOL rkl_CFStringIsMutable_first (CFStringRef str); +static BOOL rkl_CFStringIsMutable_yes (CFStringRef str RKL_UNUSED_ARG) { return(YES); } +static BOOL(*rkl_CFStringIsMutable) (CFStringRef str) = rkl_CFStringIsMutable_first; +static BOOL rkl_CFStringIsMutable_first (CFStringRef str) { if((rkl_CFStringIsMutable = (BOOL(*)(CFStringRef))dlsym(RTLD_DEFAULT, "__CFStringIsMutable")) == NULL) { rkl_CFStringIsMutable = rkl_CFStringIsMutable_yes; } return(rkl_CFStringIsMutable(str)); } +#else // RKL_FAST_MUTABLE_CHECK is not defined. Assume that all strings are potentially mutable. +#define rkl_CFStringIsMutable(s) (YES) +#endif // RKL_FAST_MUTABLE_CHECK + + +//////////// +#pragma mark - +#pragma mark iPhone / iPod touch low memory notification handler + +#if defined(RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS) && (RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS == 1) + +// The next few lines are specifically for the iPhone to catch low memory conditions. +// The basic idea is that rkl_RegisterForLowMemoryNotifications() is set to be run once by the linker at load time via __attribute((constructor)). +// rkl_RegisterForLowMemoryNotifications() tries to find the iPhone low memory notification symbol. If it can find it, +// it registers with the default NSNotificationCenter to call the RKLLowMemoryWarningObserver class method +lowMemoryWarning:. +// rkl_RegisterForLowMemoryNotifications() uses an atomic compare and swap to guarantee that it initalizes exactly once. +// +lowMemoryWarning tries to acquire the cache lock. If it gets the lock, it clears the cache. If it can't, it calls performSelector: +// with a delay of half a second to try again. This will hopefully prevent any deadlocks, such as a RegexKitLite request for +// memory triggering a notifcation while the lock is held. + +static void rkl_RegisterForLowMemoryNotifications(void) RKL_ATTRIBUTES(used); + +@interface RKLLowMemoryWarningObserver : NSObject +(void)lowMemoryWarning:(id)notification; @end +@implementation RKLLowMemoryWarningObserver ++(void)lowMemoryWarning:(id)notification { + if(OSSpinLockTry(&cacheSpinLock)) { rkl_clearStringCache(); OSSpinLockUnlock(&cacheSpinLock); } + else { [[RKLLowMemoryWarningObserver class] performSelector:@selector(lowMemoryWarning:) withObject:NULL afterDelay:(NSTimeInterval)0.1]; } +} +@end + +static int rkl_HaveRegisteredForLowMemoryNotifications = 0; + +__attribute__((constructor)) static void rkl_RegisterForLowMemoryNotifications(void) { + void **memoryWarningNotification = NULL; + + if(OSAtomicCompareAndSwapIntBarrier(0, 1, &rkl_HaveRegisteredForLowMemoryNotifications)) { + if((memoryWarningNotification = (void **)dlsym(RTLD_DEFAULT, "UIApplicationDidReceiveMemoryWarningNotification")) != NULL) { + [[NSNotificationCenter defaultCenter] addObserver:[RKLLowMemoryWarningObserver class] selector:@selector(lowMemoryWarning:) name:(NSString *)*memoryWarningNotification object:NULL]; + } + } +} + +#endif // defined(RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS) && (RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS == 1) + +#ifdef _RKL_DTRACE_ENABLED + +// compiledRegexCache(unsigned long eventID, const char *regexUTF8, int options, int captures, int hitMiss, int icuStatusCode, const char *icuErrorMessage, double *hitRate); +// utf16ConversionCache(unsigned long eventID, unsigned int lookupResultFlags, double *hitRate, const void *string, unsigned long NSRange.location, unsigned long [NSRange length], long length); + +/* +provider RegexKitLite { + probe compiledRegexCache(unsigned long, const char *, unsigned int, int, int, int, const char *, double *); + probe utf16ConversionCache(unsigned long, unsigned int, double *, const void *, unsigned long, unsigned long, long); +}; + +#pragma D attributes Unstable/Unstable/Common provider RegexKitLite provider +#pragma D attributes Private/Private/Common provider RegexKitLite module +#pragma D attributes Private/Private/Common provider RegexKitLite function +#pragma D attributes Unstable/Unstable/Common provider RegexKitLite name +#pragma D attributes Unstable/Unstable/Common provider RegexKitLite args +*/ + +#define REGEXKITLITE_STABILITY "___dtrace_stability$RegexKitLite$v1$4_4_5_1_1_5_1_1_5_4_4_5_4_4_5" +#define REGEXKITLITE_TYPEDEFS "___dtrace_typedefs$RegexKitLite$v1" +#define REGEXKITLITE_COMPILEDREGEXCACHE(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { __asm__ volatile(".reference " REGEXKITLITE_TYPEDEFS); __dtrace_probe$RegexKitLite$compiledRegexCache$v1$756e7369676e6564206c6f6e67$63686172202a$756e7369676e656420696e74$696e74$696e74$696e74$63686172202a$646f75626c65202a(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); __asm__ volatile(".reference " REGEXKITLITE_STABILITY); } +#define REGEXKITLITE_COMPILEDREGEXCACHE_ENABLED() __dtrace_isenabled$RegexKitLite$compiledRegexCache$v1() +#define REGEXKITLITE_CONVERTEDSTRINGU16CACHE(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { __asm__ volatile(".reference " REGEXKITLITE_TYPEDEFS); __dtrace_probe$RegexKitLite$utf16ConversionCache$v1$756e7369676e6564206c6f6e67$756e7369676e656420696e74$646f75626c65202a$766f6964202a$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$6c6f6e67(arg0, arg1, arg2, arg3, arg4, arg5, arg6); __asm__ volatile(".reference " REGEXKITLITE_STABILITY); } +#define REGEXKITLITE_CONVERTEDSTRINGU16CACHE_ENABLED() __dtrace_isenabled$RegexKitLite$utf16ConversionCache$v1() + +extern void __dtrace_probe$RegexKitLite$compiledRegexCache$v1$756e7369676e6564206c6f6e67$63686172202a$756e7369676e656420696e74$696e74$696e74$696e74$63686172202a$646f75626c65202a(unsigned long, const char *, unsigned int, int, int, int, const char *, double *); +extern int __dtrace_isenabled$RegexKitLite$compiledRegexCache$v1(void); +extern void __dtrace_probe$RegexKitLite$utf16ConversionCache$v1$756e7369676e6564206c6f6e67$756e7369676e656420696e74$646f75626c65202a$766f6964202a$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$6c6f6e67(unsigned long, unsigned int, double *, const void *, unsigned long, unsigned long, long); +extern int __dtrace_isenabled$RegexKitLite$utf16ConversionCache$v1(void); + +//////////////////////////// + +enum { + RKLCacheHitLookupFlag = 1 << 0, + RKLConversionRequiredLookupFlag = 1 << 1, + RKLSetTextLookupFlag = 1 << 2, + RKLDynamicBufferLookupFlag = 1 << 3, + RKLErrorLookupFlag = 1 << 4, +}; + +#define rkl_dtrace_addLookupFlag(a,b) do { a |= (unsigned int)(b); } while(0) + +static char rkl_dtrace_regexUTF8[(RKL_CACHE_SIZE) + 1][(RKL_DTRACE_REGEXUTF8_SIZE)]; +static NSUInteger rkl_dtrace_eventID, rkl_dtrace_compiledCacheLookups, rkl_dtrace_compiledCacheHits, rkl_dtrace_conversionBufferLookups, rkl_dtrace_conversionBufferHits; + +#define rkl_dtrace_incrementEventID() do { rkl_dtrace_eventID++; } while(0) +#define rkl_dtrace_compiledRegexCache(a0, a1, a2, a3, a4, a5) do { int _a3 = (a3); rkl_dtrace_compiledCacheLookups++; if(_a3 == 1) { rkl_dtrace_compiledCacheHits++; } if(RKL_EXPECTED(REGEXKITLITE_COMPILEDREGEXCACHE_ENABLED(), 0L)) { double hitRate = 0.0; if(rkl_dtrace_compiledCacheLookups > 0UL) { hitRate = ((double)rkl_dtrace_compiledCacheHits / (double)rkl_dtrace_compiledCacheLookups) * 100.0; } REGEXKITLITE_COMPILEDREGEXCACHE(rkl_dtrace_eventID, a0, a1, a2, _a3, a4, a5, &hitRate); } } while(0) +#define rkl_dtrace_utf16ConversionCache(a0, a1, a2, a3, a4) do { unsigned int _a0 = (a0); if((_a0 & RKLConversionRequiredLookupFlag) != 0U) { rkl_dtrace_conversionBufferLookups++; if((_a0 & RKLCacheHitLookupFlag) != 0U) { rkl_dtrace_conversionBufferHits++; } } if(RKL_EXPECTED(REGEXKITLITE_CONVERTEDSTRINGU16CACHE_ENABLED(), 0L)) { double hitRate = 0.0; if(rkl_dtrace_conversionBufferLookups > 0UL) { hitRate = ((double)rkl_dtrace_conversionBufferHits / (double)rkl_dtrace_conversionBufferLookups) * 100.0; } REGEXKITLITE_CONVERTEDSTRINGU16CACHE(rkl_dtrace_eventID, _a0, &hitRate, a1, a2, a3, a4); } } while(0) + + +// \342\200\246 == UTF8 for HORIZONTAL ELLIPSIS, aka triple dots '...' +#define RKL_UTF8_ELLIPSE "\342\200\246" + +// rkl_dtrace_getRegexUTF8 will copy the str argument to utf8Buffer using UTF8 as the string encoding. +// If the utf8 encoding would take up more bytes than the utf8Buffers length, then the unicode character 'HORIZONTAL ELLIPSIS' ('...') is appened to indicate truncation occured. +static void rkl_dtrace_getRegexUTF8(CFStringRef str, char *utf8Buffer) RKL_NONNULL_ARGS(2); +static void rkl_dtrace_getRegexUTF8(CFStringRef str, char *utf8Buffer) { + if((str == NULL) || (utf8Buffer == NULL)) { return; } + CFIndex maxLength = ((CFIndex)(RKL_DTRACE_REGEXUTF8_SIZE) - 2L), maxBytes = (maxLength - (CFIndex)sizeof(RKL_UTF8_ELLIPSE) - 1L), stringU16Length = CFStringGetLength(str), usedBytes = 0L; + CFStringGetBytes(str, CFMakeRange(0L, ((stringU16Length < maxLength) ? stringU16Length : maxLength)), kCFStringEncodingUTF8, (UInt8)'?', (Boolean)0, (UInt8 *)utf8Buffer, maxBytes, &usedBytes); + if(usedBytes == maxBytes) { strncpy(utf8Buffer + usedBytes, RKL_UTF8_ELLIPSE, ((size_t)(RKL_DTRACE_REGEXUTF8_SIZE) - (size_t)usedBytes) - 2UL); } else { utf8Buffer[usedBytes] = (char)0; } +} + +#else // _RKL_DTRACE_ENABLED + +#define rkl_dtrace_incrementEventID() +#define rkl_dtrace_compiledRegexCache(a0, a1, a2, a3, a4, a5) +#define rkl_dtrace_utf16ConversionCache(a0, a1, a2, a3, a4) +#define rkl_dtrace_getRegexUTF8(str, buf) +#define rkl_dtrace_addLookupFlag(a,b) + +#endif // _RKL_DTRACE_ENABLED + +//////////// +#pragma mark - +#pragma mark RegexKitLite low-level internal functions + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called with cacheSpinLock already locked! +// ---------- + +static RKLCacheSlot *rkl_getCachedRegex(NSString *regexString, RKLRegexOptions options, NSError **error, id *exception) { + RKLCacheSlot *cacheSlot = NULL; + CFHashCode regexHash = 0UL; + int32_t status = 0; + + RKLCDelayedAssert((cacheSpinLock != 0) && (regexString != NULL), exception, exitNow); + + // Fast path the common case where this regex is exactly the same one used last time. + // The pointer equality test is valid under these circumstances since the cacheSlot->regexString is an immutable copy. + // If the regexString argument is mutable, this test will fail, and we'll use the the slow path cache check below. + if(RKL_EXPECTED(lastCacheSlot != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->options == options, 1L) && RKL_EXPECTED(lastCacheSlot->icu_regex != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->regexString != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->regexString == (CFStringRef)regexString, 1L)) { + rkl_dtrace_compiledRegexCache(&rkl_dtrace_regexUTF8[(lastCacheSlot - &rkl_cacheSlots[0])][0], lastCacheSlot->options, (int)lastCacheSlot->captureCount, 1, 0, NULL); + return(lastCacheSlot); + } + + lastCacheSlot = NULL; + regexHash = CFHash((CFTypeRef)regexString); + cacheSlot = &rkl_cacheSlots[(regexHash % (CFHashCode)(RKL_CACHE_SIZE))]; // Retrieve the cache slot for this regex. + + // Return the cached entry if it's a match, otherwise clear the slot and create a new ICU regex in its place. + // If regexString is mutable, the pointer equality test will fail, and CFEqual() is used to determine true + // equality with the immutable cacheSlot copy. CFEqual() performs a slow character by character check. + if(RKL_EXPECTED(cacheSlot->options == options, 1L) && RKL_EXPECTED(cacheSlot->icu_regex != NULL, 1L) && RKL_EXPECTED(cacheSlot->regexString != NULL, 1L) && (RKL_EXPECTED(cacheSlot->regexString == (CFStringRef)regexString, 1L) || RKL_EXPECTED(CFEqual((CFTypeRef)regexString, (CFTypeRef)cacheSlot->regexString) == YES, 1L))) { + lastCacheSlot = cacheSlot; + rkl_dtrace_compiledRegexCache(&rkl_dtrace_regexUTF8[(lastCacheSlot - &rkl_cacheSlots[0])][0], lastCacheSlot->options, (int)lastCacheSlot->captureCount, 1, 0, NULL); + return(cacheSlot); + } + + rkl_clearCacheSlotRegex(cacheSlot); + + if(RKL_EXPECTED((cacheSlot->regexString = CFStringCreateCopy(NULL, (CFStringRef)regexString)) == NULL, 0L)) { goto exitNow; } ; // Get a cheap immutable copy. + rkl_dtrace_getRegexUTF8(cacheSlot->regexString, &rkl_dtrace_regexUTF8[(cacheSlot - &rkl_cacheSlots[0])][0]); + cacheSlot->options = options; + + CFIndex regexStringU16Length = CFStringGetLength(cacheSlot->regexString); // In UTF16 code units. + UParseError parseError = (UParseError){-1, -1, {0}, {0}}; + const UniChar *regexUniChar = NULL; + + if(RKL_EXPECTED(regexStringU16Length >= (CFIndex)INT_MAX, 0L)) { *exception = [NSException exceptionWithName:NSRangeException reason:@"Regex string length exceeds INT_MAX" userInfo:NULL]; goto exitNow; } + + // Try to quickly obtain regexString in UTF16 format. + if((regexUniChar = CFStringGetCharactersPtr(cacheSlot->regexString)) == NULL) { // We didn't get the UTF16 pointer quickly and need to perform a full conversion in a temp buffer. + UniChar *uniCharBuffer = NULL; + if(((size_t)regexStringU16Length * sizeof(UniChar)) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((uniCharBuffer = (UniChar *)alloca( (size_t)regexStringU16Length * sizeof(UniChar) )) == NULL, 0L)) { goto exitNow; } } // Try to use the stack. + else { if(RKL_EXPECTED((uniCharBuffer = (UniChar *)rkl_realloc(&scratchBuffer[0], (size_t)regexStringU16Length * sizeof(UniChar), 0UL)) == NULL, 0L)) { goto exitNow; } } // Otherwise use the heap. + CFStringGetCharacters(cacheSlot->regexString, CFMakeRange(0L, regexStringU16Length), uniCharBuffer); // Convert regexString to UTF16. + regexUniChar = uniCharBuffer; + } + + // Create the ICU regex. + if(RKL_EXPECTED((cacheSlot->icu_regex = RKL_ICU_FUNCTION_APPEND(uregex_open)(regexUniChar, (int32_t)regexStringU16Length, options, &parseError, &status)) == NULL, 0L)) { goto exitNow; } + if(RKL_EXPECTED(status <= U_ZERO_ERROR, 1L)) { cacheSlot->captureCount = (NSInteger)RKL_ICU_FUNCTION_APPEND(uregex_groupCount)(cacheSlot->icu_regex, &status); } + if(RKL_EXPECTED(status <= U_ZERO_ERROR, 1L)) { lastCacheSlot = cacheSlot; } + +exitNow: + if(RKL_EXPECTED(scratchBuffer[0] != NULL, 0L)) { scratchBuffer[0] = rkl_free(&scratchBuffer[0]); } + if(RKL_EXPECTED(status > U_ZERO_ERROR, 0L)) { rkl_clearCacheSlotRegex(cacheSlot); cacheSlot = NULL; if(error != NULL) { *error = rkl_NSErrorForRegex(regexString, options, &parseError, status); } } + +#ifdef _RKL_DTRACE_ENABLED + if(RKL_EXPECTED(cacheSlot != NULL, 1L)) { rkl_dtrace_compiledRegexCache(&rkl_dtrace_regexUTF8[(cacheSlot - &rkl_cacheSlots[0])][0], cacheSlot->options, (int)cacheSlot->captureCount, 0, status, NULL); } + else { char regexUTF8[(RKL_DTRACE_REGEXUTF8_SIZE)]; const char *err = NULL; if(status != U_ZERO_ERROR) { err = RKL_ICU_FUNCTION_APPEND(u_errorName)(status); } rkl_dtrace_getRegexUTF8((CFStringRef)regexString, regexUTF8); rkl_dtrace_compiledRegexCache(regexUTF8, options, -1, -1, status, err); } +#endif // _RKL_DTRACE_ENABLED + + return(cacheSlot); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called with cacheSpinLock already locked! +// ---------- + +static NSUInteger rkl_setCacheSlotToString(RKLCacheSlot *cacheSlot, const NSRange *range, int32_t *status, id *exception RKL_UNUSED_ASSERTION_ARG) { + RKLCDelayedAssert((cacheSlot != NULL) && (cacheSlot->setToString != NULL) && ((range != NULL) && (NSEqualRanges(*range, NSNotFoundRange) == NO)) && (status != NULL), exception, exitNow); + const UniChar *stringUniChar = NULL; +#ifdef _RKL_DTRACE_ENABLED + unsigned int lookupResultFlags = 0U; +#endif + + if(cacheSlot->setToNeedsConversion == 0U) { + if(RKL_EXPECTED((stringUniChar = CFStringGetCharactersPtr(cacheSlot->setToString)) == NULL, 0L)) { cacheSlot->setToNeedsConversion = 1U; } + else { if(RKL_EXPECTED(cacheSlot->setToUniChar != stringUniChar, 0L)) { cacheSlot->setToRange = NSNotFoundRange; cacheSlot->setToUniChar = stringUniChar; } goto setRegexText; } + } + rkl_dtrace_addLookupFlag(lookupResultFlags, RKLConversionRequiredLookupFlag); + + NSUInteger useFixedBuffer = (cacheSlot->setToLength < (CFIndex)(RKL_FIXED_LENGTH)) ? 1UL : 0UL; + RKLBuffer *buffer = useFixedBuffer ? &fixedBuffer : &dynamicBuffer; + rkl_dtrace_addLookupFlag(lookupResultFlags, (useFixedBuffer ? 0U : RKLDynamicBufferLookupFlag)); + + if((cacheSlot->setToUniChar != NULL) && ((cacheSlot->setToString == buffer->string) || ((cacheSlot->setToLength == buffer->length) && (cacheSlot->setToHash == buffer->hash)))) { rkl_dtrace_addLookupFlag(lookupResultFlags, RKLCacheHitLookupFlag); goto setRegexText; } + + if(RKL_EXPECTED((stringUniChar = CFStringGetCharactersPtr(cacheSlot->setToString)) != NULL, 0L)) { cacheSlot->setToNeedsConversion = 0U; cacheSlot->setToRange = NSNotFoundRange; cacheSlot->setToUniChar = stringUniChar; goto setRegexText; } + + rkl_clearBuffer(buffer, 0UL); + + if(useFixedBuffer == 0U) { + RKLCDelayedAssert(buffer == &dynamicBuffer, exception, exitNow); + RKL_STRONG_REF void *p = (RKL_STRONG_REF void *)dynamicBuffer.uniChar; + if(RKL_EXPECTED((dynamicBuffer.uniChar = (RKL_STRONG_REF UniChar *)rkl_realloc(&p, ((size_t)cacheSlot->setToLength * sizeof(UniChar)), 0UL)) == NULL, 0L)) { goto exitNow; } // Resize the buffer. + } + + RKLCDelayedAssert(buffer->uniChar != NULL, exception, exitNow); + CFStringGetCharacters(cacheSlot->setToString, CFMakeRange(0L, cacheSlot->setToLength), (UniChar *)buffer->uniChar); // Convert to a UTF16 string. + + RKLCDelayedAssert(buffer->string == NULL, exception, exitNow); + if(RKL_EXPECTED((buffer->string = (CFStringRef)CFRetain((CFTypeRef)cacheSlot->setToString)) == NULL, 0L)) { goto exitNow; } + buffer->hash = cacheSlot->setToHash; + buffer->length = cacheSlot->setToLength; + + cacheSlot->setToUniChar = buffer->uniChar; + cacheSlot->setToRange = NSNotFoundRange; + +setRegexText: + if(NSEqualRanges(cacheSlot->setToRange, *range) == NO) { + RKLCDelayedAssert((cacheSlot->icu_regex != NULL) && (cacheSlot->setToUniChar != NULL) && (NSMaxRange(*range) <= (NSUInteger)cacheSlot->setToLength) && (cacheSlot->setToRange.length <= INT_MAX), exception, exitNow); + cacheSlot->lastFindRange = cacheSlot->lastMatchRange = NSNotFoundRange; + cacheSlot->setToRange = *range; + RKL_ICU_FUNCTION_APPEND(uregex_setText)(cacheSlot->icu_regex, cacheSlot->setToUniChar + cacheSlot->setToRange.location, (int32_t)cacheSlot->setToRange.length, status); + rkl_dtrace_addLookupFlag(lookupResultFlags, RKLSetTextLookupFlag); + if(RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto exitNow; } + } + + rkl_dtrace_utf16ConversionCache(lookupResultFlags, cacheSlot->setToString, cacheSlot->setToRange.location, cacheSlot->setToRange.length, cacheSlot->setToLength); + return(1UL); + +exitNow: + return(0UL); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called with cacheSpinLock already locked! +// ---------- + +static RKLCacheSlot *rkl_getCachedRegexSetToString(NSString *regexString, RKLRegexOptions options, NSString *matchString, NSUInteger *matchLengthPtr, NSRange *matchRange, NSError **error, id *exception, int32_t *status) { + RKLCacheSlot *cacheSlot = NULL; + RKLCDelayedAssert((regexString != NULL) && (exception != NULL) && (status != NULL) && (matchLengthPtr != NULL), exception, exitNow); + + // Fast path the common case where this regex is exactly the same one used last time. + if(RKL_EXPECTED(lastCacheSlot != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->icu_regex != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->regexString == (CFStringRef)regexString, 1L) && RKL_EXPECTED(lastCacheSlot->options == options, 1L)) { cacheSlot = lastCacheSlot; rkl_dtrace_compiledRegexCache(&rkl_dtrace_regexUTF8[(cacheSlot - &rkl_cacheSlots[0])][0], cacheSlot->options, (int)cacheSlot->captureCount, 1, 0, NULL); } + else { lastCacheSlot = NULL; if(RKL_EXPECTED((cacheSlot = rkl_getCachedRegex(regexString, options, error, exception)) == NULL, 0L)) { goto exitNow; } } + RKLCDelayedAssert((cacheSlot != NULL) && (cacheSlot->icu_regex != NULL) && (cacheSlot->regexString != NULL) && (cacheSlot->captureCount >= 0L) && (cacheSlot == lastCacheSlot), exception, exitNow); + + // Optimize the case where the string to search (matchString) is immutable and the setToString immutable copy is the same string with its reference count incremented. + NSUInteger isSetTo = ((cacheSlot->setToString != NULL) && (cacheSlot->setToString == (CFStringRef)matchString)) ? 1UL : 0UL; + CFIndex matchLength = ((isSetTo == 1UL) && (cacheSlot->setToIsImmutable == 1U)) ? cacheSlot->setToLength : CFStringGetLength((CFStringRef)matchString); + + *matchLengthPtr = (NSUInteger)matchLength; + if(matchRange->length == NSUIntegerMax) { matchRange->length = (NSUInteger)matchLength; } // For convenience, allow NSUIntegerMax == string length. + + if(RKL_EXPECTED((NSUInteger)matchLength < NSMaxRange(*matchRange), 0L)) { goto exitNow; } // The match range is out of bounds for the string. performRegexOp will catch and report the problem. + + if((cacheSlot->setToIsImmutable == 0U) && (cacheSlot->setToString != NULL) && ((cacheSlot->setToLength != CFStringGetLength(cacheSlot->setToString)) || (cacheSlot->setToHash != CFHash((CFTypeRef)cacheSlot->setToString)))) { isSetTo = 0UL; } + else { // If the first pointer equality check failed, check the hash and length. + if(((isSetTo == 0UL) || (cacheSlot->setToIsImmutable == 0U)) && (cacheSlot->setToString != NULL)) { isSetTo = ((cacheSlot->setToLength == matchLength) && (cacheSlot->setToHash == CFHash((CFTypeRef)matchString))) ? 1UL : 0UL; } + + if(isSetTo == 1UL) { if(RKL_EXPECTED(rkl_setCacheSlotToString(cacheSlot, matchRange, status, exception) == 0UL, 0L)) { cacheSlot = NULL; if(*exception == NULL) { *exception = (id)RKLCAssertDictionary(@"Failed to set up UTF16 buffer."); } } goto exitNow; } + } + + // Sometimes the range that the regex is set to isn't right, in which case we don't want to clear the cache slot. Otherwise, flush it out. + if((cacheSlot->setToString != NULL) && (isSetTo == 0UL)) { rkl_clearCacheSlotSetTo(cacheSlot); } + + if(cacheSlot->setToString == NULL) { + cacheSlot->setToString = (CFStringRef)CFRetain((CFTypeRef)matchString); + RKLCDelayedAssert(cacheSlot->setToString != NULL, exception, exitNow); + cacheSlot->setToUniChar = CFStringGetCharactersPtr(cacheSlot->setToString); + cacheSlot->setToNeedsConversion = (cacheSlot->setToUniChar == NULL) ? 1U : 0U; + cacheSlot->setToIsImmutable = (rkl_CFStringIsMutable(cacheSlot->setToString) == YES) ? 0U : 1U; // If RKL_FAST_MUTABLE_CHECK is not defined then setToIsImmutable will always be set to '0', or in other words mutable.. + cacheSlot->setToHash = CFHash((CFTypeRef)cacheSlot->setToString); + cacheSlot->setToRange = NSNotFoundRange; + cacheSlot->setToLength = matchLength; + } + + if(RKL_EXPECTED(rkl_setCacheSlotToString(cacheSlot, matchRange, status, exception) == 0UL, 0L)) { cacheSlot = NULL; if(*exception == NULL) { *exception = (id)RKLCAssertDictionary(@"Failed to set up UTF16 buffer."); } goto exitNow; } + +exitNow: + return(cacheSlot); +} + +#ifdef RKL_HAVE_CLEANUP + +// rkl_cleanup_cacheSpinLockStatus takes advantage of GCC's 'cleanup' variable attribute. When an 'auto' variable with the 'cleanup' attribute goes out of scope, +// GCC arranges to have the designated function called. In this case, we make sure that if rkl_cacheSpinLock was locked that it was also unlocked. +// If rkl_cacheSpinLock was locked, but the cacheSpinLockStatus unlocked flag was not set, we force cacheSpinLock unlocked with a call to OSSpinLockUnlock. +// This is not a panacea for preventing mutex usage errors. Old style ObjC exceptions will bypass the cleanup call, but newer C++ style ObjC exceptions should cause the cleanup function to be called during the stack unwind. + +// We do not depend on this cleanup function being called. It is used only as an extra safety net. It is probably a bug in RegexKitLite if it is ever invoked and forced to take some kind of protective action. + +volatile NSUInteger rkl_debugCacheSpinLockCount = 0UL; + +void rkl_debugCacheSpinLock (void) RKL_ATTRIBUTES(used, noinline, visibility("default")); +static void rkl_cleanup_cacheSpinLockStatus (volatile NSUInteger *cacheSpinLockStatusPtr) RKL_ATTRIBUTES(used); + +void rkl_debugCacheSpinLock(void) { + rkl_debugCacheSpinLockCount++; // This is here primarily to prevent the optimizer from optimizing away the function. +} + +static void rkl_cleanup_cacheSpinLockStatus(volatile NSUInteger *cacheSpinLockStatusPtr) { + static NSUInteger didPrintForcedUnlockWarning = 0UL, didPrintNotLockedWarning = 0UL; + NSUInteger cacheSpinLockStatus = *cacheSpinLockStatusPtr; + + if(RKL_EXPECTED((cacheSpinLockStatus & RKLUnlockedCacheSpinLock) == 0UL, 0L) && RKL_EXPECTED((cacheSpinLockStatus & RKLLockedCacheSpinLock) != 0UL, 1L)) { + if(cacheSpinLock != 0) { + if(didPrintForcedUnlockWarning == 0UL) { didPrintForcedUnlockWarning = 1UL; NSLog(@"[RegexKitLite] Unusual condition detected: Recorded that cacheSpinLock was locked, but for some reason it was not unlocked. Forcibly unlocking cacheSpinLock. Set a breakpoint at rkl_debugCacheSpinLock to debug. This warning is only printed once."); } + rkl_debugCacheSpinLock(); // Since this is an unusual condition, offer an attempt to catch it before we unlock. + OSSpinLockUnlock(&cacheSpinLock); + } else { + if(didPrintNotLockedWarning == 0UL) { didPrintNotLockedWarning = 1UL; NSLog(@"[RegexKitLite] Unusual condition detected: Recorded that cacheSpinLock was locked, but for some reason it was not unlocked, yet cacheSpinLock is currently not locked? Set a breakpoint at rkl_debugCacheSpinLock to debug. This warning is only printed once."); } + rkl_debugCacheSpinLock(); + } + } +} + +#endif // RKL_HAVE_CLEANUP + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// ---------- + +static id rkl_performRegexOp(id self, SEL _cmd, RKLRegexOp regexOp, NSString *regexString, RKLRegexOptions options, NSInteger capture, id matchString, NSRange *matchRange, NSString *replacementString, NSError **error, void *result) { + volatile NSUInteger RKL_CLEANUP(rkl_cleanup_cacheSpinLockStatus) cacheSpinLockStatus = 0UL; + + NSUInteger replaceMutable = 0UL; + RKLRegexOp maskedRegexOp = (regexOp & RKLMaskOp); + + if((error != NULL) && (*error != NULL)) { *error = NULL; } + + if(RKL_EXPECTED(regexString == NULL, 0L)) { RKL_RAISE_EXCEPTION(NSInvalidArgumentException, @"The regular expression argument is NULL."); } + if(RKL_EXPECTED(matchString == NULL, 0L)) { RKL_RAISE_EXCEPTION(NSInternalInconsistencyException, @"The match string argument is NULL."); } + if((maskedRegexOp == RKLReplaceOp) && (replacementString == NULL)) { RKL_RAISE_EXCEPTION(NSInvalidArgumentException, @"The replacement string argument is NULL."); } + + id resultObject = NULL, exception = NULL; + int32_t status = U_ZERO_ERROR; + RKLCacheSlot *cacheSlot = NULL; + NSUInteger stringU16Length = 0UL; + NSRange stackRanges[2048]; + RKLFindAll findAll; + + + // IMPORTANT! Once we have obtained the lock, code MUST exit via 'goto exitNow;' to unlock the lock! NO EXCEPTIONS! + // ---------- + OSSpinLockLock(&cacheSpinLock); // Grab the lock and get cache entry. + cacheSpinLockStatus |= RKLLockedCacheSpinLock; + rkl_dtrace_incrementEventID(); + + if(RKL_EXPECTED((cacheSlot = rkl_getCachedRegexSetToString(regexString, options, matchString, &stringU16Length, matchRange, error, &exception, &status)) == NULL, 0L)) { stringU16Length = (NSUInteger)CFStringGetLength((CFStringRef)matchString); } + if(RKL_EXPECTED(matchRange->length == NSUIntegerMax, 1L)) { matchRange->length = stringU16Length; } // For convenience. + if(RKL_EXPECTED(stringU16Length < NSMaxRange(*matchRange), 0L) && RKL_EXPECTED(exception == NULL, 1L)) { exception = (id)RKL_EXCEPTION(NSRangeException, @"Range or index out of bounds"); goto exitNow; } + if(RKL_EXPECTED(stringU16Length >= (NSUInteger)INT_MAX, 0L) && RKL_EXPECTED(exception == NULL, 1L)) { exception = (id)RKL_EXCEPTION(NSRangeException, @"String length exceeds INT_MAX"); goto exitNow; } + if(((maskedRegexOp == RKLRangeOp) || (maskedRegexOp == RKLArrayOfStringsOp)) && RKL_EXPECTED(cacheSlot != NULL, 1L) && (RKL_EXPECTED(capture < 0L, 0L) || RKL_EXPECTED(capture > cacheSlot->captureCount, 0L)) && RKL_EXPECTED(exception == NULL, 1L)) { exception = (id)RKL_EXCEPTION(NSInvalidArgumentException, @"The capture argument is not valid."); goto exitNow; } + if(RKL_EXPECTED(cacheSlot == NULL, 0L) || RKL_EXPECTED(status > U_ZERO_ERROR, 0L) || RKL_EXPECTED(exception != NULL, 0L)) { goto exitNow; } + + RKLCDelayedAssert((cacheSlot != NULL) && (cacheSlot->icu_regex != NULL) && (cacheSlot->regexString != NULL) && (cacheSlot->captureCount >= 0L) && (cacheSlot->setToString != NULL) && (cacheSlot->setToLength >= 0L) && (cacheSlot->setToUniChar != NULL) && ((CFIndex)NSMaxRange(cacheSlot->setToRange) <= cacheSlot->setToLength), &exception, exitNow); + +#ifndef NS_BLOCK_ASSERTIONS + if(cacheSlot->setToNeedsConversion == 0U) { RKLCDelayedAssert((cacheSlot->setToUniChar == CFStringGetCharactersPtr(cacheSlot->setToString)), &exception, exitNow); } + else { + RKLBuffer *buffer = (cacheSlot->setToLength < (CFIndex)(RKL_FIXED_LENGTH)) ? &fixedBuffer : &dynamicBuffer; + RKLCDelayedAssert((cacheSlot->setToHash == buffer->hash) && (cacheSlot->setToLength == buffer->length) && (cacheSlot->setToUniChar == buffer->uniChar), &exception, exitNow); + } +#endif + + switch(maskedRegexOp) { + case RKLRangeOp: + if((rkl_search(cacheSlot, matchRange, 0UL, &exception, &status) == NO) || (RKL_EXPECTED(status > U_ZERO_ERROR, 0L))) { *(NSRange *)result = NSNotFoundRange; goto exitNow; } + if(RKL_EXPECTED(capture == 0L, 1L)) { *(NSRange *)result = cacheSlot->lastMatchRange; } else { if(RKL_EXPECTED(rkl_getRangeForCapture(cacheSlot, &status, (int32_t)capture, (NSRange *)result) > U_ZERO_ERROR, 0L)) { goto exitNow; } } + break; + + case RKLSplitOp: // Fall-thru... + case RKLArrayOfStringsOp: // Fall-thru... + case RKLCapturesArrayOp: // Fall-thru... + case RKLArrayOfCapturesOp: + findAll = rkl_makeFindAll(stackRanges, *matchRange, 2048L, (2048UL * sizeof(NSRange)), 0UL, (void **)&scratchBuffer[0], &scratchBuffer[1], &scratchBuffer[2], 0L, capture, ((maskedRegexOp == RKLCapturesArrayOp) ? 1L : NSIntegerMax)); + + if(RKL_EXPECTED(rkl_findRanges(cacheSlot, regexOp, &findAll, &exception, &status) == NO, 1L)) { + if(RKL_EXPECTED(findAll.found == 0L, 0L)) { resultObject = [NSArray array]; } else { resultObject = rkl_makeArray(cacheSlot, regexOp, &findAll, &exception); } + } + + if(RKL_EXPECTED(scratchBuffer[0] != NULL, 0L)) { scratchBuffer[0] = rkl_free(&scratchBuffer[0]); } + if(RKL_EXPECTED(scratchBuffer[1] != NULL, 0L)) { scratchBuffer[1] = rkl_free(&scratchBuffer[1]); } + if(RKL_EXPECTED(scratchBuffer[2] != NULL, 0L)) { scratchBuffer[2] = rkl_free(&scratchBuffer[2]); } + + break; + + case RKLReplaceOp: resultObject = rkl_replaceString(cacheSlot, matchString, stringU16Length, replacementString, (NSUInteger)CFStringGetLength((CFStringRef)replacementString), (NSUInteger *)result, (replaceMutable = (((regexOp & RKLReplaceMutable) != 0) ? 1UL : 0UL)), &exception, &status); break; + default: exception = RKLCAssertDictionary(@"Unknown regexOp code."); break; + } + +exitNow: + OSSpinLockUnlock(&cacheSpinLock); + cacheSpinLockStatus |= RKLUnlockedCacheSpinLock; + + if(RKL_EXPECTED(status > U_ZERO_ERROR, 0L) && RKL_EXPECTED(exception == NULL, 0L)) { exception = rkl_NSExceptionForRegex(regexString, options, NULL, status); } // If we had a problem, prepare an exception to be thrown. + if(RKL_EXPECTED(exception != NULL, 0L)) { rkl_handleDelayedAssert(self, _cmd, exception); } // If there is an exception, throw it at this point. + // If we're working on a mutable string and there were successful matches/replacements, then we still have work to do. + // This is done outside the cache lock and with the objc replaceCharactersInRange:withString: method because Core Foundation + // does not assert that the string we are attempting to update is actually a mutable string, whereas Foundation ensures + // the object receiving the message is a mutable string and throws an exception if we're attempting to modify an immutable string. + if(RKL_EXPECTED(replaceMutable == 1UL, 0L) && RKL_EXPECTED(*((NSUInteger *)result) > 0UL, 1L)) { NSCParameterAssert(resultObject != NULL); [matchString replaceCharactersInRange:*matchRange withString:resultObject]; } + + return(resultObject); +} + +static void rkl_handleDelayedAssert(id self, SEL _cmd, id exception) { + if(RKL_EXPECTED(exception != NULL, 0L)) { + if([exception isKindOfClass:[NSException class]]) { [[NSException exceptionWithName:[exception name] reason:rkl_stringFromClassAndMethod(self, _cmd, [exception reason]) userInfo:[exception userInfo]] raise]; } + else { + id functionString = [exception objectForKey:@"function"], fileString = [exception objectForKey:@"file"], descriptionString = [exception objectForKey:@"description"], lineNumber = [exception objectForKey:@"line"]; + NSCParameterAssert((functionString != NULL) && (fileString != NULL) && (descriptionString != NULL) && (lineNumber != NULL)); + [[NSAssertionHandler currentHandler] handleFailureInFunction:functionString file:fileString lineNumber:(NSInteger)[lineNumber longValue] description:descriptionString]; + } + } +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_performRegexOp() or rkl_findRanges(). +// ---------- + +static NSUInteger rkl_search(RKLCacheSlot *cacheSlot, NSRange *searchRange, NSUInteger updateSearchRange, id *exception RKL_UNUSED_ASSERTION_ARG, int32_t *status) { + NSUInteger foundMatch = 0UL, searchEqualsEndOfRange = (RKL_EXPECTED(NSEqualRanges(*searchRange, NSMakeRange(NSMaxRange(cacheSlot->setToRange), 0UL)) == YES, 0L) ? 1UL : 0UL); + + if((NSEqualRanges(*searchRange, cacheSlot->lastFindRange) == YES) || (searchEqualsEndOfRange == 1UL)) { foundMatch = (((cacheSlot->lastMatchRange.location == NSNotFound) || (searchEqualsEndOfRange == 1UL)) ? 0UL : 1UL);} + else { // Only perform an expensive 'find' operation iff the current find range is different than the last find range. + NSUInteger findLocation = (searchRange->location - cacheSlot->setToRange.location); + RKLCDelayedAssert(((searchRange->location >= cacheSlot->setToRange.location)) && (NSRangeInsideRange(*searchRange, cacheSlot->setToRange) == YES) && (findLocation < INT_MAX) && (findLocation <= cacheSlot->setToRange.length), exception, exitNow); + + RKL_PREFETCH_UNICHAR(cacheSlot->setToUniChar, searchRange->location); // Spool up the CPU caches. + + // Using uregex_findNext can be a slight performance win. + NSUInteger useFindNext = ((searchRange->location == (NSMaxRange(cacheSlot->lastMatchRange) + (((cacheSlot->lastMatchRange.length == 0UL) && (cacheSlot->lastMatchRange.location < NSMaxRange(cacheSlot->setToRange))) ? 1UL : 0UL))) ? 1UL : 0UL); + + cacheSlot->lastFindRange = *searchRange; + if(RKL_EXPECTED(useFindNext == 0UL, 0L)) { if(RKL_EXPECTED((RKL_ICU_FUNCTION_APPEND(uregex_find) (cacheSlot->icu_regex, (int32_t)findLocation, status) == NO), 0L) || RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto finishedFind; } } + else { if(RKL_EXPECTED((RKL_ICU_FUNCTION_APPEND(uregex_findNext)(cacheSlot->icu_regex, status) == NO), 0L) || RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto finishedFind; } } + foundMatch = 1UL; + + if(RKL_EXPECTED(rkl_getRangeForCapture(cacheSlot, status, 0, &cacheSlot->lastMatchRange) > U_ZERO_ERROR, 0L)) { goto finishedFind; } + RKLCDelayedAssert(NSRangeInsideRange(cacheSlot->lastMatchRange, *searchRange) == YES, exception, exitNow); + } + +finishedFind: + if(RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { foundMatch = 0UL; cacheSlot->lastFindRange = NSNotFoundRange; } + + if(foundMatch == 0UL) { cacheSlot->lastMatchRange = NSNotFoundRange; if(updateSearchRange == 1UL) { *searchRange = NSMakeRange(NSMaxRange(*searchRange), 0UL); } } + else { + RKLCDelayedAssert(NSRangeInsideRange(cacheSlot->lastMatchRange, *searchRange) == YES, exception, exitNow); + if(updateSearchRange == 1UL) { + NSUInteger nextLocation = (NSMaxRange(cacheSlot->lastMatchRange) + (((cacheSlot->lastMatchRange.length == 0UL) && (cacheSlot->lastMatchRange.location < NSMaxRange(cacheSlot->setToRange))) ? 1UL : 0UL)), locationDiff = nextLocation - searchRange->location; + RKLCDelayedAssert((((locationDiff > 0UL) || ((locationDiff == 0UL) && (cacheSlot->lastMatchRange.location == NSMaxRange(cacheSlot->setToRange)))) && (locationDiff <= searchRange->length)), exception, exitNow); + searchRange->location = nextLocation; + searchRange->length -= locationDiff; + } + } + +#ifndef NS_BLOCK_ASSERTIONS +exitNow: +#endif + return(foundMatch); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_doFindOp(). +// ---------- + +static BOOL rkl_findRanges(RKLCacheSlot *cacheSlot, RKLRegexOp regexOp, RKLFindAll *findAll, id *exception, int32_t *status) { + BOOL returnWithError = YES; + RKLCDelayedAssert((((cacheSlot != NULL) && (cacheSlot->icu_regex != NULL) && (cacheSlot->setToUniChar != NULL) && (cacheSlot->captureCount >= 0L) && (cacheSlot->setToRange.location != NSNotFound)) && (status != NULL) && ((findAll != NULL) && (findAll->found == 0L) && ((findAll->capacity >= 0L) && (((findAll->capacity > 0L) || (findAll->size > 0UL)) ? ((findAll->ranges != NULL) && (findAll->capacity > 0L) && (findAll->size > 0UL)) : 1)) && (findAll->rangesScratchBuffer != NULL) && ((findAll->capture >= 0L) && (findAll->capture <= cacheSlot->captureCount)))), exception, exitNow); + + if(RKL_EXPECTED(cacheSlot->setToLength == 0L, 0L) || RKL_EXPECTED(cacheSlot->setToRange.length == 0UL, 0L)) { returnWithError = NO; goto exitNow; } + + NSInteger captureCount = cacheSlot->captureCount; + RKLRegexOp maskedRegexOp = (regexOp & RKLMaskOp); + NSUInteger lastLocation = findAll->findInRange.location; + NSRange searchRange = findAll->findInRange; + + for(findAll->found = 0L; (findAll->found < findAll->findUpTo) && ((findAll->found < findAll->capacity) || (findAll->found == 0L)); findAll->found++) { + NSInteger loopCapture, shouldBreak = 0L; + + if(RKL_EXPECTED(findAll->found >= ((findAll->capacity - ((captureCount + 2L) * 4L)) - 4L), 0L)) { if(RKL_EXPECTED(rkl_growFindRanges(cacheSlot, lastLocation, findAll, exception) == 0UL, 0L)) { goto exitNow; } } + + RKLCDelayedAssert((searchRange.location != NSNotFound) && (NSRangeInsideRange(searchRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(findAll->findInRange, cacheSlot->setToRange) == YES), exception, exitNow); + + // This fixes a 'bug' that is also present in ICU's uregex_split(). 'Bug', in this case, means that the results of a split operation can differ from those that perl's split() creates for the same input. + // "I|at|ice I eat rice" split using the regex "\b\s*" demonstrates the problem. ICU bug http://bugs.icu-project.org/trac/ticket/6826 + // ICU : "", "I", "|", "at", "|", "ice", "", "I", "", "eat", "", "rice" <- Results that RegexKitLite used to produce. + // PERL: "I", "|", "at", "|", "ice", "I", "eat", "rice" <- Results that RegexKitLite now produces. + do { if((rkl_search(cacheSlot, &searchRange, 1UL, exception, status) == NO) || (RKL_EXPECTED(*status > U_ZERO_ERROR, 0L))) { shouldBreak = 1L; } } + while((maskedRegexOp == RKLSplitOp) && RKL_EXPECTED(shouldBreak == 0L, 1L) && RKL_EXPECTED(cacheSlot->lastMatchRange.length == 0UL, 0L) && RKL_EXPECTED((cacheSlot->lastMatchRange.location - lastLocation) == 0UL, 0L)); + if(RKL_EXPECTED(shouldBreak == 1L, 0L)) { break; } + + RKLCDelayedAssert((searchRange.location != NSNotFound) && (NSRangeInsideRange(searchRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(findAll->findInRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(searchRange, findAll->findInRange) == YES), exception, exitNow); + RKLCDelayedAssert((NSRangeInsideRange(cacheSlot->lastFindRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(cacheSlot->lastMatchRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(cacheSlot->lastMatchRange, findAll->findInRange) == YES), exception, exitNow); + RKLCDelayedAssert((findAll->ranges != NULL) && (findAll->found >= 0L) && (findAll->capacity >= 0L) && ((findAll->found + (captureCount + 3L) + 1L) < (findAll->capacity - 2L)), exception, exitNow); + + switch(maskedRegexOp) { + case RKLArrayOfStringsOp: + if(findAll->capture == 0L) { findAll->ranges[findAll->found] = cacheSlot->lastMatchRange; } else { if(RKL_EXPECTED(rkl_getRangeForCapture(cacheSlot, status, (int32_t)findAll->capture, &findAll->ranges[findAll->found]) > U_ZERO_ERROR, 0L)) { goto exitNow; } } + break; + + case RKLSplitOp: // Fall-thru... + case RKLCapturesArrayOp: // Fall-thru... + case RKLArrayOfCapturesOp: + findAll->ranges[findAll->found] = ((maskedRegexOp == RKLSplitOp) ? NSMakeRange(lastLocation, cacheSlot->lastMatchRange.location - lastLocation) : cacheSlot->lastMatchRange); + + for(loopCapture = 1L; loopCapture <= captureCount; loopCapture++) { + RKLCDelayedAssert((findAll->found >= 0L) && (findAll->found < (findAll->capacity - 2L)) && (loopCapture < INT_MAX), exception, exitNow); + if(RKL_EXPECTED(rkl_getRangeForCapture(cacheSlot, status, (int32_t)loopCapture, &findAll->ranges[++findAll->found]) > U_ZERO_ERROR, 0L)) { goto exitNow; } + } + break; + + default: if(*exception != NULL) { *exception = RKLCAssertDictionary(@"Unknown regexOp."); } goto exitNow; break; + } + + lastLocation = NSMaxRange(cacheSlot->lastMatchRange); + } + + if(RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto exitNow; } + + RKLCDelayedAssert((findAll->ranges != NULL) && (findAll->found >= 0L) && (findAll->found < (findAll->capacity - 2L)), exception, exitNow); + if((maskedRegexOp == RKLSplitOp) && (lastLocation != NSMaxRange(findAll->findInRange))) { findAll->ranges[findAll->found++] = NSMakeRange(lastLocation, NSMaxRange(findAll->findInRange) - lastLocation); } + + RKLCDelayedAssert((findAll->ranges != NULL) && (findAll->found >= 0L) && (findAll->found < (findAll->capacity - 2L)), exception, exitNow); + returnWithError = NO; + +exitNow: + return(returnWithError); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_findRanges(). +// ---------- + +static NSUInteger rkl_growFindRanges(RKLCacheSlot *cacheSlot, NSUInteger lastLocation, RKLFindAll *findAll, id *exception RKL_UNUSED_ASSERTION_ARG) { + NSUInteger didGrowRanges = 0UL; + RKLCDelayedAssert((((cacheSlot != NULL) && (cacheSlot->captureCount >= 0L)) && ((findAll != NULL) && (findAll->capacity >= 0L) && (findAll->rangesScratchBuffer != NULL) && (findAll->found >= 0L) && (((findAll->capacity > 0L) || (findAll->size > 0UL) || (findAll->ranges != NULL)) ? ((findAll->capacity > 0L) && (findAll->size > 0UL) && (findAll->ranges != NULL) && (((size_t)findAll->capacity * sizeof(NSRange)) == findAll->size)) : 1))), exception, exitNow); + + // Attempt to guesstimate the required capacity based on: the total length needed to search / (length we've searched so far / ranges found so far). + NSInteger newCapacity = (findAll->capacity + (findAll->capacity / 2L)), estimate = (NSInteger)((float)cacheSlot->setToLength / (((float)lastLocation + 1.0f) / ((float)findAll->found + 1.0f))); + newCapacity = (((newCapacity + ((estimate > newCapacity) ? estimate : newCapacity)) / 2L) + ((cacheSlot->captureCount + 2L) * 4L) + 4L); + + NSUInteger needToCopy = ((findAll->ranges != NULL) && (*findAll->rangesScratchBuffer != findAll->ranges)) ? 1UL : 0UL; // If findAll->ranges is set to a stack allocation then we need to manually copy the data from the stack to the new heap allocation. + size_t newSize = ((size_t)newCapacity * sizeof(NSRange)); + NSRange *newRanges = NULL; + + if(RKL_EXPECTED((newRanges = (NSRange *)rkl_realloc((RKL_STRONG_REF void **)findAll->rangesScratchBuffer, newSize, 0UL)) == NULL, 0L)) { findAll->capacity = 0L; findAll->size = 0UL; findAll->ranges = NULL; *findAll->rangesScratchBuffer = rkl_free((RKL_STRONG_REF void **)findAll->rangesScratchBuffer); goto exitNow; } else { didGrowRanges = 1UL; } + if(needToCopy == 1UL) { memcpy(newRanges, findAll->ranges, findAll->size); } // If necessary, copy the existing data to the new heap allocation. + + findAll->capacity = newCapacity; + findAll->size = newSize; + findAll->ranges = newRanges; + +exitNow: + return(didGrowRanges); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_doFindOp(). +// ---------- + +static NSArray *rkl_makeArray(RKLCacheSlot *cacheSlot, RKLRegexOp regexOp, RKLFindAll *findAll, id *exception RKL_UNUSED_ASSERTION_ARG) { + NSUInteger createdStringsCount = 0UL, createdArraysCount = 0UL, transferedStringsCount = 0UL; + id *matchedStrings = NULL, *subcaptureArrays = NULL, emptyString = @""; + NSArray *resultArray = NULL; + + RKLCDelayedAssert((cacheSlot != NULL) && ((findAll != NULL) && (findAll->found >= 0L) && (findAll->stringsScratchBuffer != NULL) && (findAll->arraysScratchBuffer != NULL)), exception, exitNow); + + size_t matchedStringsSize = ((size_t)findAll->found * sizeof(id)); + CFStringRef setToString = cacheSlot->setToString; + + if((findAll->stackUsed + matchedStringsSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((matchedStrings = (id *)alloca(matchedStringsSize)) == NULL, 0L)) { goto exitNow; } findAll->stackUsed += matchedStringsSize; } + else { if(RKL_EXPECTED((matchedStrings = (id *)rkl_realloc(findAll->stringsScratchBuffer, matchedStringsSize, (NSUInteger)RKLScannedOption)) == NULL, 0L)) { goto exitNow; } } + + { // This sub-block (and its local variables) is here for the benefit of the optimizer. + NSUInteger found = (NSUInteger)findAll->found; + const NSRange *rangePtr = findAll->ranges; + id *matchedStringsPtr = matchedStrings; + + for(createdStringsCount = 0UL; createdStringsCount < found; createdStringsCount++) { + NSRange range = *rangePtr++; + if(RKL_EXPECTED(((*matchedStringsPtr++ = RKL_EXPECTED(range.length == 0UL, 0L) ? emptyString : rkl_CreateStringWithSubstring((id)setToString, range)) == NULL), 0L)) { goto exitNow; } + } + } + + NSUInteger arrayCount = createdStringsCount; + id *arrayObjects = matchedStrings; + + if((regexOp & RKLSubcapturesArray) != 0UL) { + RKLCDelayedAssert(((createdStringsCount % ((NSUInteger)cacheSlot->captureCount + 1UL)) == 0UL) && (createdArraysCount == 0UL), exception, exitNow); + + NSUInteger captureCount = ((NSUInteger)cacheSlot->captureCount + 1UL); + NSUInteger subcaptureArraysCount = (createdStringsCount / captureCount); + size_t subcaptureArraysSize = ((size_t)subcaptureArraysCount * sizeof(id)); + + if((findAll->stackUsed + subcaptureArraysSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((subcaptureArrays = (id *)alloca(subcaptureArraysSize)) == NULL, 0L)) { goto exitNow; } findAll->stackUsed += subcaptureArraysSize; } + else { if(RKL_EXPECTED((subcaptureArrays = (id *)rkl_realloc(findAll->arraysScratchBuffer, subcaptureArraysSize, (NSUInteger)RKLScannedOption)) == NULL, 0L)) { goto exitNow; } } + + { // This sub-block (and its local variables) is here for the benefit of the optimizer. + id *subcaptureArraysPtr = subcaptureArrays; + id *matchedStringsPtr = matchedStrings; + + for(createdArraysCount = 0UL; createdArraysCount < subcaptureArraysCount; createdArraysCount++) { + if(RKL_EXPECTED((*subcaptureArraysPtr++ = rkl_CreateArrayWithObjects((void **)matchedStringsPtr, captureCount)) == NULL, 0L)) { goto exitNow; } + matchedStringsPtr += captureCount; + transferedStringsCount += captureCount; + } + } + + RKLCDelayedAssert((transferedStringsCount == createdStringsCount), exception, exitNow); + arrayCount = createdArraysCount; + arrayObjects = subcaptureArrays; + } + + RKLCDelayedAssert((arrayObjects != NULL), exception, exitNow); + resultArray = rkl_CreateAutoreleasedArray((void **)arrayObjects, (NSUInteger)arrayCount); + +exitNow: + if(RKL_EXPECTED(resultArray == NULL, 0L) && (rkl_collectingEnabled() == NO)) { // If we did not create an array then we need to make sure that we release any objects we created. + NSUInteger x; + if(matchedStrings != NULL) { for(x = transferedStringsCount; x < createdStringsCount; x++) { if((matchedStrings[x] != NULL) && (matchedStrings[x] != emptyString)) { matchedStrings[x] = rkl_ReleaseObject(matchedStrings[x]); } } } + if(subcaptureArrays != NULL) { for(x = 0UL; x < createdArraysCount; x++) { if(subcaptureArrays[x] != NULL) { subcaptureArrays[x] = rkl_ReleaseObject(subcaptureArrays[x]); } } } + } + + return(resultArray); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_performRegexOp(). +// ---------- + +static NSString *rkl_replaceString(RKLCacheSlot *cacheSlot, id searchString, NSUInteger searchU16Length, NSString *replacementString, NSUInteger replacementU16Length, NSUInteger *replacedCountPtr, NSUInteger replaceMutable, id *exception, int32_t *status) { + uint64_t searchU16Length64 = (uint64_t)searchU16Length, replacementU16Length64 = (uint64_t)replacementU16Length; + int32_t resultU16Length = 0, tempUniCharBufferU16Capacity = 0; + UniChar *tempUniCharBuffer = NULL; + const UniChar *replacementUniChar = NULL; + id resultObject = NULL; + NSUInteger replacedCount = 0UL; + + if((RKL_EXPECTED(replacementU16Length64 >= (uint64_t)INT_MAX, 0L) || RKL_EXPECTED(((searchU16Length64 / 2ULL) + (replacementU16Length64 * 2ULL)) >= (uint64_t)INT_MAX, 0L))) { *exception = [NSException exceptionWithName:NSRangeException reason:@"Replacement string length exceeds INT_MAX" userInfo:NULL]; goto exitNow; } + + RKLCDelayedAssert((searchU16Length64 < (uint64_t)INT_MAX) && (replacementU16Length64 < (uint64_t)INT_MAX) && (((searchU16Length64 / 2ULL) + (replacementU16Length64 * 2ULL)) < (uint64_t)INT_MAX), exception, exitNow); + + // Zero order approximation of the buffer sizes for holding the replaced string or split strings and split strings pointer offsets. As UTF16 code units. + tempUniCharBufferU16Capacity = (int32_t)(16UL + (searchU16Length + (searchU16Length / 2UL)) + (replacementU16Length * 2UL)); + + // Buffer sizes converted from native units to bytes. + size_t stackSize = 0UL, replacementSize = ((size_t)replacementU16Length * sizeof(UniChar)), tempUniCharBufferSize = ((size_t)tempUniCharBufferU16Capacity * sizeof(UniChar)); + + // For the various buffers we require, we first try to allocate from the stack if we're not over the RKL_STACK_LIMIT. If we are, switch to using the heap for the buffer. + if((stackSize + tempUniCharBufferSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((tempUniCharBuffer = (UniChar *)alloca(tempUniCharBufferSize)) == NULL, 0L)) { goto exitNow; } stackSize += tempUniCharBufferSize; } + else { if(RKL_EXPECTED((tempUniCharBuffer = (UniChar *)rkl_realloc(&scratchBuffer[0], tempUniCharBufferSize, 0UL)) == NULL, 0L)) { goto exitNow; } } + + // Try to get the pointer to the replacement strings UTF16 data. If we can't, allocate some buffer space, then covert to UTF16. + if((replacementUniChar = CFStringGetCharactersPtr((CFStringRef)replacementString)) == NULL) { + UniChar *uniCharBuffer = NULL; + if((stackSize + replacementSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((uniCharBuffer = (UniChar *)alloca(replacementSize)) == NULL, 0L)) { goto exitNow; } stackSize += replacementSize; } + else { if(RKL_EXPECTED((uniCharBuffer = (UniChar *)rkl_realloc(&scratchBuffer[1], replacementSize, 0UL)) == NULL, 0L)) { goto exitNow; } } + CFStringGetCharacters((CFStringRef)replacementString, CFMakeRange(0L, replacementU16Length), uniCharBuffer); // Convert to a UTF16 string. + replacementUniChar = uniCharBuffer; + } + + resultU16Length = rkl_replaceAll(cacheSlot, replacementUniChar, (int32_t)replacementU16Length, tempUniCharBuffer, tempUniCharBufferU16Capacity, &replacedCount, exception, status); + + if(RKL_EXPECTED(*status == U_BUFFER_OVERFLOW_ERROR, 0L)) { // Our buffer guess(es) were too small. Resize the buffers and try again. + tempUniCharBufferSize = ((size_t)(tempUniCharBufferU16Capacity = resultU16Length + 4) * sizeof(UniChar)); + if((stackSize + tempUniCharBufferSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((tempUniCharBuffer = (UniChar *)alloca(tempUniCharBufferSize)) == NULL, 0L)) { goto exitNow; } stackSize += tempUniCharBufferSize; } + else { if(RKL_EXPECTED((tempUniCharBuffer = (UniChar *)rkl_realloc(&scratchBuffer[0], tempUniCharBufferSize, 0UL)) == NULL, 0L)) { goto exitNow; } } + + *status = U_ZERO_ERROR; // Make sure the status var is cleared and try again. + resultU16Length = rkl_replaceAll(cacheSlot, replacementUniChar, (int32_t)replacementU16Length, tempUniCharBuffer, tempUniCharBufferU16Capacity, &replacedCount, exception, status); + } + + if(RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto exitNow; } // Something went wrong. + + if(resultU16Length == 0) { resultObject = @""; } // Optimize the case where the replaced text length == 0 with a @"" string. + else if(((NSUInteger)resultU16Length == searchU16Length) && (replacedCount == 0UL)) { // Optimize the case where the replacement == original by creating a copy. Very fast if self is immutable. + if(replaceMutable == 0UL) { resultObject = rkl_CFAutorelease(CFStringCreateCopy(NULL, (CFStringRef)searchString)); } // .. but only if this is not replacing a mutable self. + } else { resultObject = rkl_CFAutorelease(CFStringCreateWithCharacters(NULL, tempUniCharBuffer, (CFIndex)resultU16Length)); } // otherwise, create a new string. + + // If replaceMutable == 1UL, we don't do the replacement here. We wait until after we return and unlock the cache lock. + // This is because we may be trying to mutate an immutable string object. + if((replacedCount > 0UL) && (replaceMutable == 1UL)) { // We're working on a mutable string and there were successfull matches with replaced text, so there's work to do. + rkl_clearBuffer((cacheSlot->setToLength < (CFIndex)(RKL_FIXED_LENGTH)) ? &fixedBuffer : &dynamicBuffer, 0UL); + rkl_clearCacheSlotSetTo(cacheSlot); // Flush any cached information about this string since it will mutate. + } + +exitNow: + if(scratchBuffer[0] != NULL) { scratchBuffer[0] = rkl_free(&scratchBuffer[0]); } + if(scratchBuffer[1] != NULL) { scratchBuffer[1] = rkl_free(&scratchBuffer[1]); } + if(replacedCountPtr != NULL) { *replacedCountPtr = replacedCount; } + return(resultObject); +} + +// IMPORTANT! Should only be called from rkl_replaceString(). +// ---------- +// Modified version of the ICU libraries uregex_replaceAll() that keeps count of the number of replacements made. + +static int32_t rkl_replaceAll(RKLCacheSlot *cacheSlot, const UniChar *replacementUniChar, int32_t replacementU16Length, UniChar *replacedUniChar, int32_t replacedU16Capacity, NSUInteger *replacedCount, id *exception RKL_UNUSED_ASSERTION_ARG, int32_t *status) { + NSUInteger replaced = 0UL, bufferOverflowed = 0UL; + int32_t u16Length = 0; + RKLCDelayedAssert((cacheSlot != NULL) && (replacementUniChar != NULL) && (replacedUniChar != NULL) && (status != NULL) && (replacementU16Length >= 0) && (replacedU16Capacity >= 0), exception, exitNow); + + cacheSlot->lastFindRange = cacheSlot->lastMatchRange = NSNotFoundRange; // Clear the cached find information for this regex so a subsequent find works correctly. + RKL_ICU_FUNCTION_APPEND(uregex_reset)(cacheSlot->icu_regex, 0, status); + + // Work around for ICU uregex_reset() bug, see http://bugs.icu-project.org/trac/ticket/6545 + // http://sourceforge.net/tracker/index.php?func=detail&aid=2105213&group_id=204582&atid=990188 + if(RKL_EXPECTED(cacheSlot->setToRange.length == 0L, 0L) && (*status == U_INDEX_OUTOFBOUNDS_ERROR)) { *status = U_ZERO_ERROR; } + + // This loop originally came from ICU source/i18n/uregex.cpp, uregex_replaceAll. + // There is a bug in that code which causes the size of the buffer required for the replaced text to not be calculated correctly. + // This contains a work around using the variable bufferOverflowed. + // ICU bug: http://bugs.icu-project.org/trac/ticket/6656 + // http://sourceforge.net/tracker/index.php?func=detail&aid=2408447&group_id=204582&atid=990188 + while(RKL_ICU_FUNCTION_APPEND(uregex_findNext)(cacheSlot->icu_regex, status)) { + replaced++; + u16Length += RKL_ICU_FUNCTION_APPEND(uregex_appendReplacement)(cacheSlot->icu_regex, replacementUniChar, replacementU16Length, &replacedUniChar, &replacedU16Capacity, status); + if(RKL_EXPECTED(*status == U_BUFFER_OVERFLOW_ERROR, 0L)) { bufferOverflowed = 1UL; *status = U_ZERO_ERROR; } + } + if(RKL_EXPECTED(*status == U_BUFFER_OVERFLOW_ERROR, 0L)) { bufferOverflowed = 1UL; *status = U_ZERO_ERROR; } + u16Length += RKL_ICU_FUNCTION_APPEND(uregex_appendTail)(cacheSlot->icu_regex, &replacedUniChar, &replacedU16Capacity, status); + + if(RKL_EXPECTED(*status == U_ZERO_ERROR, 1L) && RKL_EXPECTED(bufferOverflowed == 1UL, 0L)) { *status = U_BUFFER_OVERFLOW_ERROR; } + if(replacedCount != NULL) { *replacedCount = replaced; } + +#ifndef NS_BLOCK_ASSERTIONS +exitNow: +#endif + return(u16Length); +} + +static NSUInteger rkl_isRegexValid(id self, SEL _cmd, NSString *regex, RKLRegexOptions options, NSInteger *captureCountPtr, NSError **error) { + volatile NSUInteger RKL_CLEANUP(rkl_cleanup_cacheSpinLockStatus) cacheSpinLockStatus = 0UL; + + RKLCacheSlot *cacheSlot = NULL; + NSUInteger gotCacheSlot = 0UL; + NSInteger captureCount = -1L; + id exception = NULL; + + if((error != NULL) && (*error != NULL)) { *error = NULL; } + if(regex == NULL) { RKL_RAISE_EXCEPTION(NSInvalidArgumentException, @"The regular expression argument is NULL."); } + + OSSpinLockLock(&cacheSpinLock); + cacheSpinLockStatus |= RKLLockedCacheSpinLock; + rkl_dtrace_incrementEventID(); + if((cacheSlot = rkl_getCachedRegex(regex, options, error, &exception)) != NULL) { gotCacheSlot = 1UL; captureCount = cacheSlot->captureCount; } + cacheSlot = NULL; + OSSpinLockUnlock(&cacheSpinLock); + cacheSpinLockStatus |= RKLUnlockedCacheSpinLock; + + if(captureCountPtr != NULL) { *captureCountPtr = captureCount; } + if(RKL_EXPECTED(exception != NULL, 0L)) { rkl_handleDelayedAssert(self, _cmd, exception); } + return(gotCacheSlot); +} + +static void rkl_clearStringCache(void) { + NSCParameterAssert(cacheSpinLock != 0); + lastCacheSlot = NULL; + NSUInteger x = 0UL; + for(x = 0UL; x < (NSUInteger)(RKL_SCRATCH_BUFFERS); x++) { if(scratchBuffer[x] != NULL) { scratchBuffer[x] = rkl_free(&scratchBuffer[x]); } } + for(x = 0UL; x < (NSUInteger)(RKL_CACHE_SIZE); x++) { rkl_clearCacheSlotRegex(&rkl_cacheSlots[x]); } + rkl_clearBuffer(&fixedBuffer, 0UL); + rkl_clearBuffer(&dynamicBuffer, 1UL); +} + +static void rkl_clearBuffer(RKLBuffer *buffer, NSUInteger freeDynamicBuffer) { + if(buffer == NULL) { return; } + if((freeDynamicBuffer == 1UL) && (buffer->uniChar != NULL) && (buffer == &dynamicBuffer)) { RKL_STRONG_REF void *p = (RKL_STRONG_REF void *)dynamicBuffer.uniChar; dynamicBuffer.uniChar = (RKL_STRONG_REF UniChar *)rkl_free(&p); } + if(buffer->string != NULL) { CFRelease((CFTypeRef)buffer->string); buffer->string = NULL; } + buffer->length = 0L; + buffer->hash = 0UL; +} + +static void rkl_clearCacheSlotRegex(RKLCacheSlot *cacheSlot) { + if(cacheSlot == NULL) { return; } + if(cacheSlot->setToString != NULL) { rkl_clearCacheSlotSetTo(cacheSlot); } + if(cacheSlot->icu_regex != NULL) { RKL_ICU_FUNCTION_APPEND(uregex_close)(cacheSlot->icu_regex); cacheSlot->icu_regex = NULL; cacheSlot->captureCount = -1L; } + if(cacheSlot->regexString != NULL) { CFRelease((CFTypeRef)cacheSlot->regexString); cacheSlot->regexString = NULL; cacheSlot->options = 0U; } +} + +static void rkl_clearCacheSlotSetTo(RKLCacheSlot *cacheSlot) { + if(cacheSlot == NULL) { return; } + if(cacheSlot->icu_regex != NULL) { int32_t status = 0; RKL_ICU_FUNCTION_APPEND(uregex_setText)(cacheSlot->icu_regex, &emptyUniCharString[0], 0, &status); } + if(cacheSlot->setToString != NULL) { CFRelease((CFTypeRef)cacheSlot->setToString); cacheSlot->setToString = NULL; } + cacheSlot->lastFindRange = cacheSlot->lastMatchRange = cacheSlot->setToRange = NSNotFoundRange; + cacheSlot->setToIsImmutable = cacheSlot->setToNeedsConversion = 0U; + cacheSlot->setToUniChar = NULL; + cacheSlot->setToHash = 0UL; + cacheSlot->setToLength = 0L; +} + +// Helps to keep things tidy. +#define addKeyAndObject(objs, keys, i, k, o) ({id _o=(o), _k=(k); if((_o != NULL) && (_k != NULL)) { objs[i] = _o; keys[i] = _k; i++; } }) + +static NSDictionary *rkl_userInfoDictionary(NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status, ...) { + va_list varArgsList; + va_start(varArgsList, status); + if(regexString == NULL) { va_end(varArgsList); return(NULL); } + + id objects[64], keys[64]; + NSUInteger count = 0UL; + + NSString *errorNameString = [NSString stringWithUTF8String:RKL_ICU_FUNCTION_APPEND(u_errorName)(status)]; + + addKeyAndObject(objects, keys, count, RKLICURegexRegexErrorKey, regexString); + addKeyAndObject(objects, keys, count, RKLICURegexRegexOptionsErrorKey, [NSNumber numberWithUnsignedInt:options]); + addKeyAndObject(objects, keys, count, RKLICURegexErrorCodeErrorKey, [NSNumber numberWithInt:status]); + addKeyAndObject(objects, keys, count, RKLICURegexErrorNameErrorKey, errorNameString); + + if((parseError != NULL) && (parseError->line != -1)) { + NSString *preContextString = [NSString stringWithCharacters:&parseError->preContext[0] length:(NSUInteger)RKL_ICU_FUNCTION_APPEND(u_strlen)(&parseError->preContext[0])]; + NSString *postContextString = [NSString stringWithCharacters:&parseError->postContext[0] length:(NSUInteger)RKL_ICU_FUNCTION_APPEND(u_strlen)(&parseError->postContext[0])]; + + addKeyAndObject(objects, keys, count, RKLICURegexLineErrorKey, [NSNumber numberWithInt:parseError->line]); + addKeyAndObject(objects, keys, count, RKLICURegexOffsetErrorKey, [NSNumber numberWithInt:parseError->offset]); + addKeyAndObject(objects, keys, count, RKLICURegexPreContextErrorKey, preContextString); + addKeyAndObject(objects, keys, count, RKLICURegexPostContextErrorKey, postContextString); + addKeyAndObject(objects, keys, count, @"NSLocalizedFailureReason", ([NSString stringWithFormat:@"The error %@ occurred at line %d, column %d: %@<>%@", errorNameString, parseError->line, parseError->offset, preContextString, postContextString])); + } else { + addKeyAndObject(objects, keys, count, @"NSLocalizedFailureReason", ([NSString stringWithFormat:@"The error %@ occurred.", errorNameString])); + } + + while(count < 62UL) { id obj = va_arg(varArgsList, id), key = va_arg(varArgsList, id); if((obj != NULL) && (key != NULL)) { addKeyAndObject(objects, keys, count, key, obj); } else { break; } } + va_end(varArgsList); + + return([NSDictionary dictionaryWithObjects:&objects[0] forKeys:&keys[0] count:count]); +} + +static NSError *rkl_NSErrorForRegex(NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status) { + return([NSError errorWithDomain:RKLICURegexErrorDomain code:(NSInteger)status userInfo:rkl_userInfoDictionary(regexString, options, parseError, status, @"There was an error compiling the regular expression.", @"NSLocalizedDescription", NULL)]); +} + +static NSException *rkl_NSExceptionForRegex(NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status) { + return([NSException exceptionWithName:RKLICURegexException reason:[NSString stringWithFormat:@"ICU regular expression error #%d, %s", status, RKL_ICU_FUNCTION_APPEND(u_errorName)(status)] userInfo:rkl_userInfoDictionary(regexString, options, parseError, status, NULL)]); +} + +static NSDictionary *rkl_makeAssertDictionary(const char *function, const char *file, int line, NSString *format, ...) { + va_list varArgsList; + va_start(varArgsList, format); + NSString *formatString = [[[NSString alloc] initWithFormat:format arguments:varArgsList] autorelease]; + va_end(varArgsList); + NSString *functionString = [NSString stringWithUTF8String:function], *fileString = [NSString stringWithUTF8String:file]; + return([NSDictionary dictionaryWithObjectsAndKeys:formatString, @"description", functionString, @"function", fileString, @"file", [NSNumber numberWithInt:line], @"line", NSInternalInconsistencyException, @"exceptionName", NULL]); +} + +static NSString *rkl_stringFromClassAndMethod(id object, SEL selector, NSString *format, ...) { + va_list varArgsList; + va_start(varArgsList, format); + NSString *formatString = [[[NSString alloc] initWithFormat:format arguments:varArgsList] autorelease]; + va_end(varArgsList); + Class objectsClass = [object class]; + return([NSString stringWithFormat:@"*** %c[%@ %@]: %@", (object == objectsClass) ? '+' : '-', NSStringFromClass(objectsClass), NSStringFromSelector(selector), formatString]); +} + +#pragma mark - +#pragma mark Objective-C Public Interface +#pragma mark - + +@implementation NSString (RegexKitLiteAdditions) + +#pragma mark +clearStringCache + ++ (void)RKL_METHOD_PREPEND(clearStringCache) +{ + volatile NSUInteger RKL_CLEANUP(rkl_cleanup_cacheSpinLockStatus) cacheSpinLockStatus = 0UL; + OSSpinLockLock(&cacheSpinLock); + cacheSpinLockStatus |= RKLLockedCacheSpinLock; + rkl_clearStringCache(); + OSSpinLockUnlock(&cacheSpinLock); + cacheSpinLockStatus |= RKLUnlockedCacheSpinLock; +} + +#pragma mark +captureCountForRegex: + ++ (NSInteger)RKL_METHOD_PREPEND(captureCountForRegex):(NSString *)regex +{ + NSInteger captureCount = -1L; + rkl_isRegexValid(self, _cmd, regex, RKLNoOptions, &captureCount, NULL); + return(captureCount); +} + ++ (NSInteger)RKL_METHOD_PREPEND(captureCountForRegex):(NSString *)regex options:(RKLRegexOptions)options error:(NSError **)error +{ + NSInteger captureCount = -1L; + rkl_isRegexValid(self, _cmd, regex, options, &captureCount, error); + return(captureCount); +} + +#pragma mark -captureCount: + +- (NSInteger)RKL_METHOD_PREPEND(captureCount) +{ + NSInteger captureCount = -1L; + rkl_isRegexValid(self, _cmd, self, RKLNoOptions, &captureCount, NULL); + return(captureCount); +} + +- (NSInteger)RKL_METHOD_PREPEND(captureCountWithOptions):(RKLRegexOptions)options error:(NSError **)error +{ + NSInteger captureCount = -1L; + rkl_isRegexValid(self, _cmd, self, options, &captureCount, error); + return(captureCount); +} + +#pragma mark -componentsSeparatedByRegex: + +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex +{ + NSRange range = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLSplitOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex range:(NSRange)range +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLSplitOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLSplitOp, regex, options, 0L, self, &range, NULL, error, NULL)); +} + +#pragma mark -isMatchedByRegex: + +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex +{ + NSRange result = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &result); + return((result.location == NSNotFound) ? NO : YES); +} + +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex inRange:(NSRange)range +{ + NSRange result = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &result); + return((result.location == NSNotFound) ? NO : YES); +} + +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range error:(NSError **)error +{ + NSRange result = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, options, 0L, self, &range, NULL, error, &result); + return((result.location == NSNotFound) ? NO : YES); +} + +#pragma mark -isRegexValid + +- (BOOL)RKL_METHOD_PREPEND(isRegexValid) +{ + return(rkl_isRegexValid(self, _cmd, self, RKLNoOptions, NULL, NULL) == 1UL ? YES : NO); +} + +- (BOOL)RKL_METHOD_PREPEND(isRegexValidWithOptions):(RKLRegexOptions)options error:(NSError **)error +{ + return(rkl_isRegexValid(self, _cmd, self, options, NULL, error) == 1UL ? YES : NO); +} + +#pragma mark -flushCachedRegexData + +- (void)RKL_METHOD_PREPEND(flushCachedRegexData) +{ + volatile NSUInteger RKL_CLEANUP(rkl_cleanup_cacheSpinLockStatus) cacheSpinLockStatus = 0UL; + + CFIndex selfLength = CFStringGetLength((CFStringRef)self); + CFHashCode selfHash = CFHash((CFTypeRef)self); + + OSSpinLockLock(&cacheSpinLock); + cacheSpinLockStatus |= RKLLockedCacheSpinLock; + rkl_dtrace_incrementEventID(); + + NSUInteger slot; + for(slot = 0UL; slot < (NSUInteger)(RKL_CACHE_SIZE); slot++) { + RKLCacheSlot *cacheSlot = &rkl_cacheSlots[slot]; + if((cacheSlot->setToString != NULL) && ( (cacheSlot->setToString == (CFStringRef)self) || ((cacheSlot->setToLength == selfLength) && (cacheSlot->setToHash == selfHash)) ) ) { rkl_clearCacheSlotSetTo(cacheSlot); } + } + + RKLBuffer *buffer = (selfLength < (CFIndex)(RKL_FIXED_LENGTH)) ? &fixedBuffer : &dynamicBuffer; + if((buffer->string != NULL) && ((buffer->string == (CFStringRef)self) || ((buffer->length == selfLength) && (buffer->hash == selfHash)))) { rkl_clearBuffer(buffer, 0UL); } + + OSSpinLockUnlock(&cacheSpinLock); + cacheSpinLockStatus |= RKLUnlockedCacheSpinLock; +} + +#pragma mark -rangeOfRegex: + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex +{ + NSRange result = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &result); + return(result); +} + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex capture:(NSInteger)capture +{ + NSRange result = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, capture, self, &range, NULL, NULL, &result); + return(result); +} + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex inRange:(NSRange)range +{ + NSRange result = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &result); + return(result); +} + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range capture:(NSInteger)capture error:(NSError **)error +{ + NSRange result = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, options, capture, self, &range, NULL, error, &result); + return(result); +} + +#pragma mark -stringByMatching: + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex +{ + NSRange matchedRange = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &matchedRange); + return((matchedRange.location == NSNotFound) ? NULL : rkl_CFAutorelease(CFStringCreateWithSubstring(NULL, (CFStringRef)self, CFMakeRange(matchedRange.location, matchedRange.length)))); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex capture:(NSInteger)capture +{ + NSRange matchedRange = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, capture, self, &range, NULL, NULL, &matchedRange); + return((matchedRange.location == NSNotFound) ? NULL : rkl_CFAutorelease(CFStringCreateWithSubstring(NULL, (CFStringRef)self, CFMakeRange(matchedRange.location, matchedRange.length)))); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex inRange:(NSRange)range +{ + NSRange matchedRange = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &matchedRange); + return((matchedRange.location == NSNotFound) ? NULL : rkl_CFAutorelease(CFStringCreateWithSubstring(NULL, (CFStringRef)self, CFMakeRange(matchedRange.location, matchedRange.length)))); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range capture:(NSInteger)capture error:(NSError **)error +{ + NSRange matchedRange = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, options, capture, self, &range, NULL, error, &matchedRange); + return((matchedRange.location == NSNotFound) ? NULL : rkl_CFAutorelease(CFStringCreateWithSubstring(NULL, (CFStringRef)self, CFMakeRange(matchedRange.location, matchedRange.length)))); +} + +#pragma mark -stringByReplacingOccurrencesOfRegex: + +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLReplaceOp, regex, RKLNoOptions, 0L, self, &searchRange, replacement, NULL, NULL)); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement range:(NSRange)searchRange +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLReplaceOp, regex, RKLNoOptions, 0L, self, &searchRange, replacement, NULL, NULL)); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement options:(RKLRegexOptions)options range:(NSRange)searchRange error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLReplaceOp, regex, options, 0L, self, &searchRange, replacement, error, NULL)); +} + +#pragma mark -componentsMatchedByRegex: + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLArrayOfStringsOp, regex, RKLNoOptions, 0L, self, &searchRange, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex capture:(NSInteger)capture +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLArrayOfStringsOp, regex, RKLNoOptions, capture, self, &searchRange, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex range:(NSRange)range +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLArrayOfStringsOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range capture:(NSInteger)capture error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLArrayOfStringsOp, regex, options, capture, self, &range, NULL, error, NULL)); +} + +#pragma mark -captureComponentsMatchedByRegex: + +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLCapturesArrayOp, regex, RKLNoOptions, 0L, self, &searchRange, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex range:(NSRange)range +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLCapturesArrayOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLCapturesArrayOp, regex, options, 0L, self, &range, NULL, error, NULL)); +} + +#pragma mark -arrayOfCaptureComponentsMatchedByRegex: + +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLArrayOfCapturesOp | RKLSubcapturesArray), regex, RKLNoOptions, 0L, self, &searchRange, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex range:(NSRange)range +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLArrayOfCapturesOp | RKLSubcapturesArray), regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLArrayOfCapturesOp | RKLSubcapturesArray), regex, options, 0L, self, &range, NULL, error, NULL)); +} + +@end + + +@implementation NSMutableString (RegexKitLiteAdditions) + +#pragma mark -replaceOccurrencesOfRegex: + +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement +{ + NSRange searchRange = NSMaxiumRange; + NSUInteger replacedCount = 0UL; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLReplaceOp | RKLReplaceMutable), regex, RKLNoOptions, 0L, self, &searchRange, replacement, NULL, (void **)((void *)&replacedCount)); + return(replacedCount); +} + +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement range:(NSRange)searchRange +{ + NSUInteger replacedCount = 0UL; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLReplaceOp | RKLReplaceMutable), regex, RKLNoOptions, 0L, self, &searchRange, replacement, NULL, (void **)((void *)&replacedCount)); + return(replacedCount); +} + +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement options:(RKLRegexOptions)options range:(NSRange)searchRange error:(NSError **)error +{ + NSUInteger replacedCount = 0UL; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLReplaceOp | RKLReplaceMutable), regex, options, 0L, self, &searchRange, replacement, error, (void **)((void *)&replacedCount)); + return(replacedCount); +} + +@end diff --git a/src/.svn/text-base/TAssembly.h.svn-base b/src/.svn/text-base/TAssembly.h.svn-base new file mode 100644 index 0000000..8ce5efe --- /dev/null +++ b/src/.svn/text-base/TAssembly.h.svn-base @@ -0,0 +1,138 @@ +// +// TDAssembly.h +// TDParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2008 Todd Ditchendorf. All rights reserved. +// + +#import + +/*! + @class TDAssembly + @brief An Abstract class. A TDAssembly maintains a stream of language elements along with stack and target objects. + @details

Parsers use assemblers to record progress at recognizing language elements from assembly's string.

+

Note that TDAssembly is an abstract class and may not be instantiated directly. Subclasses include TDTokenAssembly and TDCharAssembly.

+*/ +@interface TDAssembly : NSObject { + NSMutableArray *stack; + id target; + NSUInteger index; + NSString *string; + NSString *defaultDelimiter; +} + +/*! + @brief Convenience factory method for initializing an autoreleased assembly. + @param s string to be worked on + @result an initialized autoreleased assembly +*/ ++ (id)assemblyWithString:(NSString *)s; + +/*! + @brief Designated Initializer. Initializes an assembly with a given string. + @details Designated Initializer. + @param s string to be worked on + @result an initialized assembly +*/ +- (id)initWithString:(NSString *)s; + +/*! + @brief Shows the next object in the assembly, without removing it + @details Note this is not the next object in this assembly's stack, but rather the next object from this assembly's stream of elements (tokens or chars depending on the type of concrete TDAssembly subclass of this object). + @result the next object in the assembly. +*/ +- (id)peek; + +/*! + @brief Returns the next object in the assembly. + @details Note this is not the next object in this assembly's stack, but rather the next object from this assembly's stream of elements (tokens or chars depending on the type of concrete TDAssembly subclass of this object). + @result the next object in the assembly. +*/ +- (id)next; + +/*! + @brief Returns true if this assembly has unconsumed elements. + @result true, if this assembly has unconsumed elements +*/ +- (BOOL)hasMore; + +/*! + @brief Returns the elements of this assembly that have been consumed, separated by the specified delimiter. + @param delimiter string with which to separate elements of this assembly + @result string representing the elements of this assembly that have been consumed, separated by the specified delimiter +*/ +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter; + +/*! + @brief Returns the elements of this assembly that remain to be consumed, separated by the specified delimiter. + @param delimiter string with which to separate elements of this assembly + @result string representing the elements of this assembly that remain to be consumed, separated by the specified delimiter +*/ +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter; + +/*! + @brief Removes the object at the top of this assembly's stack and returns it. + @details Note this returns an object from this assembly's stack, not from its stream of elements (tokens or chars depending on the type of concrete TDAssembly subclass of this object). + @result the object at the top of this assembly's stack +*/ +- (id)pop; + +/*! + @brief Pushes an object onto the top of this assembly's stack. + @param object object to push +*/ +- (void)push:(id)object; + +/*! + @brief Returns true if this assembly's stack is empty. + @result true, if this assembly's stack is empty +*/ +- (BOOL)isStackEmpty; + +/*! + @brief Returns a vector of the elements on this assembly's stack that appear before a specified fence. + @details

Returns a vector of the elements on this assembly's stack that appear before a specified fence.

+

Sometimes a parser will recognize a list from within a pair of parentheses or brackets. The parser can mark the beginning of the list with a fence, and then retrieve all the items that come after the fence with this method.

+ @param fence object that indicates the limit of elements returned from this assembly's stack + @result Array of the elements above the specified fence +*/ +- (NSArray *)objectsAbove:(id)fence; + +/*! + @property length + @brief The number of elements in this assembly. +*/ +@property (nonatomic, readonly) NSUInteger length; + +/*! + @property objectsConsumed + @brief The number of elements that have been consumed. +*/ +@property (nonatomic, readonly) NSUInteger objectsConsumed; + +/*! + @property objectsRemaining + @brief The number of elements that have not been consumed +*/ +@property (nonatomic, readonly) NSUInteger objectsRemaining; + +/*! + @property defaultDelimiter + @brief The default string to show between elements +*/ +@property (nonatomic, readonly, retain) NSString *defaultDelimiter; + +/*! + @property stack + @brief This assembly's stack. +*/ +@property (nonatomic, readonly, retain) NSMutableArray *stack; + +/*! + @property target + @brief This assembly's target. + @details The object identified as this assembly's "target". Clients can set and retrieve a target, which can be a convenient supplement as a place to work, in addition to the assembly's stack. For example, a parser for an HTML file might use a web page object as its "target". As the parser recognizes markup commands like <head>, it could apply its findings to the target. +*/ +@property (nonatomic, retain) id target; +@end diff --git a/src/NSArray+ParseKitAdditions.h b/src/NSArray+ParseKitAdditions.h new file mode 100644 index 0000000..3d11f54 --- /dev/null +++ b/src/NSArray+ParseKitAdditions.h @@ -0,0 +1,14 @@ +// +// NSArray+ParseKitAdditions.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface NSArray (ParseKitAdditions) +- (NSArray *)reversedArray; +- (NSMutableArray *)reversedMutableArray; +@end diff --git a/src/NSArray+ParseKitAdditions.m b/src/NSArray+ParseKitAdditions.m new file mode 100644 index 0000000..1399c35 --- /dev/null +++ b/src/NSArray+ParseKitAdditions.m @@ -0,0 +1,26 @@ +// +// NSArray+ParseKitAdditions.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "NSArray+ParseKitAdditions.h" + +@implementation NSArray (ParseKitAdditions) + +- (NSArray *)reversedArray { + return [[[self reversedMutableArray] copy] autorelease]; +} + + +- (NSMutableArray *)reversedMutableArray { + NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]]; + for (id obj in [self reverseObjectEnumerator]) { + [result addObject:obj]; + } + return result; +} + +@end diff --git a/src/NSString+ParseKitAdditions.h b/src/NSString+ParseKitAdditions.h new file mode 100644 index 0000000..55d02a8 --- /dev/null +++ b/src/NSString+ParseKitAdditions.h @@ -0,0 +1,13 @@ +// +// NSString+ParseKitAdditions.h +// ParseKit +// +// Created by Todd Ditchendorf on 11/5/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface NSString (ParseKitAdditions) +- (NSString *)stringByTrimmingQuotes; +@end diff --git a/src/NSString+ParseKitAdditions.m b/src/NSString+ParseKitAdditions.m new file mode 100644 index 0000000..304a432 --- /dev/null +++ b/src/NSString+ParseKitAdditions.m @@ -0,0 +1,38 @@ +// +// NSString+ParseKitAdditions.m +// ParseKit +// +// Created by Todd Ditchendorf on 11/5/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "NSString+ParseKitAdditions.h" + +@implementation NSString (ParseKitAdditions) + +- (NSString *)stringByTrimmingQuotes { + NSUInteger len = [self length]; + + if (len < 2) { + return self; + } + + NSRange r = NSMakeRange(0, len); + + unichar c = [self characterAtIndex:0]; + if (!isalnum(c)) { + unichar quoteChar = c; + r.location = 1; + r.length -= 1; + + c = [self characterAtIndex:len - 1]; + if (c == quoteChar) { + r.length -= 1; + } + return [self substringWithRange:r]; + } else { + return self; + } +} + +@end diff --git a/src/PKAlternation.m b/src/PKAlternation.m new file mode 100644 index 0000000..d866307 --- /dev/null +++ b/src/PKAlternation.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; +@end + +@implementation PKAlternation + ++ (id)alternation { + return [self alternationWithSubparsers:nil]; +} + + ++ (id)alternationWithSubparsers:(PKParser *)p1, ... { + va_list vargs; + va_start(vargs, p1); + PKAlternation *alt = [self collectionParserWithFirst:p1 rest:vargs]; + va_end(vargs); + return alt; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSMutableSet *outAssemblies = [NSMutableSet set]; + + for (PKParser *p in subparsers) { + [outAssemblies unionSet:[p matchAndAssemble:inAssemblies]]; + } + + return outAssemblies; +} + +@end diff --git a/src/PKAny.m b/src/PKAny.m new file mode 100644 index 0000000..dcd8bfd --- /dev/null +++ b/src/PKAny.m @@ -0,0 +1,29 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKAny + ++ (id)any { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + return [obj isMemberOfClass:[PKToken class]]; +} + +@end diff --git a/src/PKAssembly.m b/src/PKAssembly.m new file mode 100644 index 0000000..8f56302 --- /dev/null +++ b/src/PKAssembly.m @@ -0,0 +1,231 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +static NSString * const PKAssemblyDefaultDelimiter = @"/"; + +@interface PKAssembly () +- (id)peek; +- (id)next; +- (BOOL)hasMore; +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter; +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter; + +@property (nonatomic, readwrite, retain) NSMutableArray *stack; +@property (nonatomic) NSUInteger index; +@property (nonatomic, retain) NSString *string; +@property (nonatomic, readwrite, retain) NSString *defaultDelimiter; +@property (nonatomic, readonly) NSUInteger length; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@property (nonatomic, readonly) NSUInteger objectsRemaining; +@end + +@implementation PKAssembly + ++ (id)assemblyWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + if (self = [super init]) { + self.stack = [NSMutableArray array]; + self.string = s; + } + return self; +} + + +- (void)dealloc { + self.stack = nil; + self.string = nil; + self.target = nil; + self.defaultDelimiter = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + // use of NSAllocateObject() below is a *massive* optimization over calling the designated initializer -initWithString: here. + // this line (and this method in general) is *vital* to the overall performance of the framework. dont fuck with it. + PKAssembly *a = NSAllocateObject([self class], 0, zone); + a->stack = [stack mutableCopyWithZone:zone]; + a->string = [string retain]; + if (defaultDelimiter) { + a->defaultDelimiter = [defaultDelimiter retain]; + } else { + a->defaultDelimiter = nil; + } + + if (target) { + if ([target conformsToProtocol:@protocol(NSMutableCopying)]) { + a->target = [target mutableCopyWithZone:zone]; + } else { + a->target = [target copyWithZone:zone]; + } + } else { + a->target = nil; + } + + a->index = index; + return a; +} + + +- (BOOL)isEqual:(id)obj { + if (![obj isMemberOfClass:[self class]]) { + return NO; + } + + PKAssembly *a = (PKAssembly *)obj; + if ([a length] != [self length]) { + return NO; + } + + if (a->index != index) { + return NO; + } + + if ([a.stack count] != [stack count]) { + return NO; + } + + return [[self description] isEqualToString:[obj description]]; +} + + +- (id)next { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return nil; +} + + +- (BOOL)hasMore { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return NO; +} + + +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return nil; +} + + +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return nil; +} + + +- (NSUInteger)length { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return 0; +} + + +- (NSUInteger)objectsConsumed { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return 0; +} + + +- (NSUInteger)objectsRemaining { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return 0; +} + + +- (id)peek { + NSAssert1(0, @"-[PKAssembly %s] must be overriden", _cmd); + return nil; +} + + +- (id)pop { + id result = nil; + if (![self isStackEmpty]) { + result = [[[stack lastObject] retain] autorelease]; + [stack removeLastObject]; + } + return result; +} + + +- (void)push:(id)object { + if (object) { + [stack addObject:object]; + } +} + + +- (BOOL)isStackEmpty { + return 0 == [stack count]; +} + + +- (NSArray *)objectsAbove:(id)fence { + NSMutableArray *result = [NSMutableArray array]; + + while (![self isStackEmpty]) { + id obj = [self pop]; + + if ([obj isEqual:fence]) { + [self push:obj]; + break; + } else { + [result addObject:obj]; + } + } + + return result; +} + + +- (NSString *)description { + NSMutableString *s = [NSMutableString string]; + [s appendString:@"["]; + + NSUInteger i = 0; + NSUInteger len = [stack count]; + + for (id obj in stack) { + [s appendString:[obj description]]; + if (len - 1 != i++) { + [s appendString:@", "]; + } + } + + [s appendString:@"]"]; + + NSString *d = defaultDelimiter ? defaultDelimiter : PKAssemblyDefaultDelimiter; + [s appendString:[self consumedObjectsJoinedByString:d]]; + [s appendString:@"^"]; + [s appendString:[self remainingObjectsJoinedByString:d]]; + + return [[s copy] autorelease]; +} + +@synthesize stack; +@synthesize target; +@synthesize index; +@synthesize string; +@synthesize defaultDelimiter; +@end diff --git a/src/PKCaseInsensitiveLiteral.m b/src/PKCaseInsensitiveLiteral.m new file mode 100644 index 0000000..25dcf59 --- /dev/null +++ b/src/PKCaseInsensitiveLiteral.m @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKCaseInsensitiveLiteral + +- (BOOL)qualifies:(id)obj { + return NSOrderedSame == [literal.stringValue caseInsensitiveCompare:[obj stringValue]]; +// return [literal isEqualIgnoringCase:obj]; +} + +@end diff --git a/src/PKChar.m b/src/PKChar.m new file mode 100644 index 0000000..e194788 --- /dev/null +++ b/src/PKChar.m @@ -0,0 +1,28 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@implementation PKChar + ++ (id)char { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + return YES; +} + +@end diff --git a/src/PKCharacterAssembly.m b/src/PKCharacterAssembly.m new file mode 100644 index 0000000..ffffd2b --- /dev/null +++ b/src/PKCharacterAssembly.m @@ -0,0 +1,127 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKAssembly () +@property (nonatomic, readwrite, retain) NSString *defaultDelimiter; +@end + +@implementation PKCharacterAssembly + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.defaultDelimiter = @""; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKCharacterAssembly *a = (PKCharacterAssembly *)[super copyWithZone:zone]; + return a; +} + + +- (id)peek { + if (index >= [string length]) { + return nil; + } + PKUniChar c = [string characterAtIndex:index]; + return [NSNumber numberWithInt:c]; +} + + +- (id)next { + id obj = [self peek]; + if (obj) { + index++; + } + return obj; +} + + +- (BOOL)hasMore { + return (index < [string length]); +} + + +- (NSUInteger)length { + return [string length]; +} + + +- (NSUInteger)objectsConsumed { + return index; +} + + +- (NSUInteger)objectsRemaining { + return ([string length] - index); +} + + +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter { + NSParameterAssert(delimiter); + return [string substringToIndex:self.objectsConsumed]; +} + + +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter { + NSParameterAssert(delimiter); + return [string substringFromIndex:self.objectsConsumed]; +} + + +// overriding simply to print NSNumber objects as their unichar values +- (NSString *)description { + NSMutableString *s = [NSMutableString string]; + [s appendString:@"["]; + + NSUInteger i = 0; + NSUInteger len = [stack count]; + + for (id obj in self.stack) { + if ([obj isKindOfClass:[NSNumber class]]) { // ***this is needed for Char Assemblies + [s appendFormat:@"%C", [obj integerValue]]; + } else { + [s appendString:[obj description]]; + } + if (len - 1 != i++) { + [s appendString:@", "]; + } + } + + [s appendString:@"]"]; + + [s appendString:[self consumedObjectsJoinedByString:self.defaultDelimiter]]; + [s appendString:@"^"]; + [s appendString:[self remainingObjectsJoinedByString:self.defaultDelimiter]]; + + return [[s copy] autorelease]; +} + +@end diff --git a/src/PKCollectionParser.m b/src/PKCollectionParser.m new file mode 100644 index 0000000..d949474 --- /dev/null +++ b/src/PKCollectionParser.m @@ -0,0 +1,104 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; + +@property (nonatomic, readwrite, retain) NSMutableArray *subparsers; +@end + +@implementation PKCollectionParser + ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest { + PKCollectionParser *cp = [[[self alloc] init] autorelease]; + + if (p1) { + [cp add:p1]; + + PKParser *p = nil; + while (p = va_arg(rest, PKParser *)) { + [cp add:p]; + } + } + + return cp; +} + + +- (id)init { + return [self initWithSubparsers:nil]; +} + + +- (id)initWithSubparsers:(PKParser *)p1, ... { + if (self = [super init]) { + self.subparsers = [NSMutableArray array]; + + if (p1) { + [subparsers addObject:p1]; + + va_list vargs; + va_start(vargs, p1); + + PKParser *p = nil; + while (p = va_arg(vargs, PKParser *)) { + [subparsers addObject:p]; + } + + va_end(vargs); + } + } + return self; +} + + +- (void)dealloc { + self.subparsers = nil; + [super dealloc]; +} + + +- (void)add:(PKParser *)p { + if (![p isKindOfClass:[PKParser class]]) { + NSLog(@"p: %@", p); + } + NSParameterAssert([p isKindOfClass:[PKParser class]]); + [subparsers addObject:p]; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } else { + // do bredth-first search + for (PKParser *p in subparsers) { + if ([p.name isEqualToString:s]) { + return p; + } + } + for (PKParser *p in subparsers) { + PKParser *sub = [p parserNamed:s]; + if (sub) { + return sub; + } + } + } + return nil; +} + +@synthesize subparsers; +@end diff --git a/src/PKComment.m b/src/PKComment.m new file mode 100644 index 0000000..fc6165b --- /dev/null +++ b/src/PKComment.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKComment + ++ (id)comment { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isComment; +} + +@end \ No newline at end of file diff --git a/src/PKCommentState.m b/src/PKCommentState.m new file mode 100644 index 0000000..a320bdb --- /dev/null +++ b/src/PKCommentState.m @@ -0,0 +1,147 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; +@end + +@interface PKCommentState () +@property (nonatomic, retain) PKSymbolRootNode *rootNode; +@property (nonatomic, retain) PKSingleLineCommentState *singleLineState; +@property (nonatomic, retain) PKMultiLineCommentState *multiLineState; +@end + +@interface PKSingleLineCommentState () +- (void)addStartMarker:(NSString *)start; +- (void)removeStartMarker:(NSString *)start; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSString *currentStartMarker; +@end + +@interface PKMultiLineCommentState () +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end; +- (void)removeStartMarker:(NSString *)start; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSMutableArray *endMarkers; +@property (nonatomic, copy) NSString *currentStartMarker; +@end + +@implementation PKCommentState + +- (id)init { + if (self = [super init]) { + self.rootNode = [[[PKSymbolRootNode alloc] init] autorelease]; + self.singleLineState = [[[PKSingleLineCommentState alloc] init] autorelease]; + self.multiLineState = [[[PKMultiLineCommentState alloc] init] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.rootNode = nil; + self.singleLineState = nil; + self.multiLineState = nil; + [super dealloc]; +} + + +- (void)addSingleLineStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [rootNode add:start]; + [singleLineState addStartMarker:start]; +} + + +- (void)removeSingleLineStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [rootNode remove:start]; + [singleLineState removeStartMarker:start]; +} + + +- (void)addMultiLineStartMarker:(NSString *)start endMarker:(NSString *)end { + NSParameterAssert([start length]); + NSParameterAssert([end length]); + [rootNode add:start]; + [rootNode add:end]; + [multiLineState addStartMarker:start endMarker:end]; +} + + +- (void)removeMultiLineStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [rootNode remove:start]; + [multiLineState removeStartMarker:start]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + [self resetWithReader:r]; + + NSString *symbol = [rootNode nextSymbol:r startingWith:cin]; + PKToken *tok = nil; + + while ([symbol length]) { + if ([multiLineState.startMarkers containsObject:symbol]) { + multiLineState.currentStartMarker = symbol; + tok = [multiLineState nextTokenFromReader:r startingWith:cin tokenizer:t]; + if (tok.isComment) { + tok.offset = offset; + } + } else if ([singleLineState.startMarkers containsObject:symbol]) { + singleLineState.currentStartMarker = symbol; + tok = [singleLineState nextTokenFromReader:r startingWith:cin tokenizer:t]; + if (tok.isComment) { + tok.offset = offset; + } + } + + if (tok) { + return tok; + } else { + if ([symbol length] > 1) { + symbol = [symbol substringToIndex:[symbol length] -1]; + } else { + break; + } + [r unread:1]; + } + } + + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; +} + +@synthesize rootNode; +@synthesize singleLineState; +@synthesize multiLineState; +@synthesize reportsCommentTokens; +@synthesize balancesEOFTerminatedComments; +@end diff --git a/src/PKDelimitState.m b/src/PKDelimitState.m new file mode 100644 index 0000000..0e1003c --- /dev/null +++ b/src/PKDelimitState.m @@ -0,0 +1,214 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (void)appendString:(NSString *)s; +- (NSString *)bufferedString; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; +@end + +@interface PKDelimitState () +- (NSString *)endMarkerForStartMarker:(NSString *)startMarker; +- (NSCharacterSet *)allowedCharacterSetForStartMarker:(NSString *)startMarker; +@property (nonatomic, retain) PKSymbolRootNode *rootNode; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSMutableArray *endMarkers; +@property (nonatomic, retain) NSMutableArray *characterSets; +@end + +@implementation PKDelimitState + +- (id)init { + if (self = [super init]) { + self.rootNode = [[[PKSymbolRootNode alloc] init] autorelease]; + self.startMarkers = [NSMutableArray array]; + self.endMarkers = [NSMutableArray array]; + self.characterSets = [NSMutableArray array]; + } + return self; +} + + +- (void)dealloc { + self.rootNode = nil; + self.startMarkers = nil; + self.endMarkers = nil; + self.characterSets = nil; + [super dealloc]; +} + + +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end allowedCharacterSet:(NSCharacterSet *)set { + NSParameterAssert([start length]); + [rootNode add:start]; + [startMarkers addObject:start]; + + if ([end length]) { + [rootNode add:end]; + [endMarkers addObject:end]; + } else { + [endMarkers addObject:[NSNull null]]; + } + + if (set) { + [characterSets addObject:set]; + } else { + [characterSets addObject:[NSNull null]]; + } +} + + +- (void)removeStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [rootNode remove:start]; + NSUInteger i = [startMarkers indexOfObject:start]; + if (NSNotFound != i) { + [startMarkers removeObject:start]; + [characterSets removeObjectAtIndex:i]; + + id endOrNull = [endMarkers objectAtIndex:i]; + if ([NSNull null] != endOrNull) { + [rootNode remove:endOrNull]; + } + [endMarkers removeObjectAtIndex:i]; // this should always be in range. + } +} + + +- (NSString *)endMarkerForStartMarker:(NSString *)startMarker { + NSParameterAssert([startMarkers containsObject:startMarker]); + NSUInteger i = [startMarkers indexOfObject:startMarker]; + return [endMarkers objectAtIndex:i]; +} + + +- (NSCharacterSet *)allowedCharacterSetForStartMarker:(NSString *)startMarker { + NSParameterAssert([startMarkers containsObject:startMarker]); + NSCharacterSet *characterSet = nil; + NSUInteger i = [startMarkers indexOfObject:startMarker]; + id csOrNull = [characterSets objectAtIndex:i]; + if ([NSNull null] != csOrNull) { + characterSet = csOrNull; + } + return characterSet; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + NSString *startMarker = [rootNode nextSymbol:r startingWith:cin]; + + if (![startMarker length] || ![startMarkers containsObject:startMarker]) { + [r unread:[startMarker length] - 1]; + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + + [self resetWithReader:r]; + [self appendString:startMarker]; + + id endMarkerOrNull = [self endMarkerForStartMarker:startMarker]; + NSString *endMarker = nil; + NSCharacterSet *characterSet = [self allowedCharacterSetForStartMarker:startMarker]; + + PKUniChar c, e; + if ([NSNull null] == endMarkerOrNull) { + e = PKEOF; + } else { + endMarker = endMarkerOrNull; + e = [endMarker characterAtIndex:0]; + } + while (1) { + c = [r read]; + if (PKEOF == c) { + if (balancesEOFTerminatedStrings && endMarker) { + [self appendString:endMarker]; + } else if (endMarker && !allowsUnbalancedStrings) { + [r unread:[[self bufferedString] length] - 1]; + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + break; + } + + if (!endMarker && [t.whitespaceState isWhitespaceChar:c]) { + // if only the start marker was matched, dont return delimited string token. instead, defer tokenization + if ([startMarker isEqualToString:[self bufferedString]]) { + [r unread:[startMarker length] - 1]; + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + // else, return delimited string tok + break; + } + + if (e == c) { + NSString *peek = [rootNode nextSymbol:r startingWith:e]; + if (endMarker && [endMarker isEqualToString:peek]) { + [self appendString:endMarker]; + c = [r read]; + break; + } else { + [r unread:[peek length] - 1]; + if (e != [peek characterAtIndex:0]) { + [self append:c]; + c = [r read]; + } + } + } + + + // check if char is not in allowed character set (if given) + if (characterSet && ![characterSet characterIsMember:c]) { + if (allowsUnbalancedStrings) { + break; + } else { + // if not, unwind and return a symbol tok for cin + [r unread:[[self bufferedString] length]]; + return [[self nextTokenizerStateFor:cin tokenizer:t] nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + } + + [self append:c]; + } + + if (PKEOF != c) { + [r unread]; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeDelimitedString stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; +} + +@synthesize rootNode; +@synthesize balancesEOFTerminatedStrings; +@synthesize allowsUnbalancedStrings; +@synthesize startMarkers; +@synthesize endMarkers; +@synthesize characterSets; +@end diff --git a/src/PKDelimitedString.m b/src/PKDelimitedString.m new file mode 100644 index 0000000..2c2b847 --- /dev/null +++ b/src/PKDelimitedString.m @@ -0,0 +1,64 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKDelimitedString () +@property (nonatomic, retain) NSString *startMarker; +@property (nonatomic, retain) NSString *endMarker; +@end + +@implementation PKDelimitedString + ++ (id)delimitedString { + return [self delimitedStringWithStartMarker:nil]; +} + + ++ (id)delimitedStringWithStartMarker:(NSString *)start { + return [self delimitedStringWithStartMarker:start endMarker:nil]; +} + + ++ (id)delimitedStringWithStartMarker:(NSString *)start endMarker:(NSString *)end { + PKDelimitedString *ds = [[[self alloc] initWithString:nil] autorelease]; + ds.startMarker = start; + ds.endMarker = end; + return ds; +} + + +- (void)dealloc { + self.startMarker = nil; + self.endMarker = nil; + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + BOOL result = tok.isDelimitedString; + if (result && [startMarker length]) { + result = [tok.stringValue hasPrefix:startMarker]; + if (result && [endMarker length]) { + result = [tok.stringValue hasSuffix:endMarker]; + } + } + return result; +} + +@synthesize startMarker; +@synthesize endMarker; +@end \ No newline at end of file diff --git a/src/PKDifference.m b/src/PKDifference.m new file mode 100644 index 0000000..ca4dc39 --- /dev/null +++ b/src/PKDifference.m @@ -0,0 +1,104 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKDifference.h" + +@interface NSMutableSet (PKDifferenceAdditions) +- (void)minusSetTestingEquality:(NSSet *)s; +@end + +@implementation NSMutableSet (PKDifferenceAdditions) + +- (void)minusSetTestingEquality:(NSSet *)s { + for (id a1 in self) { + for (id a2 in s) { + if ([a1 isEqual:a2]) { + [self removeObject:a1]; + } + } + } +} + +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@interface PKDifference () +@property (nonatomic, retain, readwrite) PKParser *subparser; +@property (nonatomic, retain, readwrite) PKParser *minus; +@end + +@implementation PKDifference + ++ (id)differenceWithSubparser:(PKParser *)s minus:(PKParser *)m { + return [[[self alloc] initWithSubparser:s minus:m] autorelease]; +} + + +- (id)initWithSubparser:(PKParser *)s minus:(PKParser *)m { + if (self = [super init]) { + self.subparser = s; + self.minus = m; + } + return self; +} + + +- (void)dealloc { + self.subparser = nil; + self.minus = nil; + [super dealloc]; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } else { + // do bredth-first search + if ([subparser.name isEqualToString:s]) { + return subparser; + } + if ([minus.name isEqualToString:s]) { + return minus; + } + + PKParser *sub = [subparser parserNamed:s]; + if (sub) { + return sub; + } + sub = [minus parserNamed:s]; + if (sub) { + return sub; + } + } + return nil; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + + NSMutableSet *outAssemblies = [[[subparser matchAndAssemble:inAssemblies] mutableCopy] autorelease]; + [outAssemblies minusSetTestingEquality:[minus allMatchesFor:inAssemblies]]; + + return outAssemblies; +} + +@synthesize subparser; +@synthesize minus; +@end diff --git a/src/PKDigit.m b/src/PKDigit.m new file mode 100644 index 0000000..448b91e --- /dev/null +++ b/src/PKDigit.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKDigit + ++ (id)digit { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKUniChar c = [obj intValue]; + return isdigit(c); +} + +@end diff --git a/src/PKEmpty.m b/src/PKEmpty.m new file mode 100644 index 0000000..6d16c3f --- /dev/null +++ b/src/PKEmpty.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@implementation PKEmpty + ++ (id)empty { + return [[[self alloc] init] autorelease]; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + //return [[[NSSet alloc] initWithSet:inAssemblies copyItems:YES] autorelease]; + return inAssemblies; +} + +@end diff --git a/src/PKGrammarParser.h b/src/PKGrammarParser.h new file mode 100644 index 0000000..e15e733 --- /dev/null +++ b/src/PKGrammarParser.h @@ -0,0 +1,83 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface PKGrammarParser : NSObject { + id assembler; + PKCollectionParser *statementParser; + PKCollectionParser *declarationParser; + PKCollectionParser *callbackParser; + PKCollectionParser *selectorParser; + PKCollectionParser *exprParser; + PKCollectionParser *termParser; + PKCollectionParser *orTermParser; + PKCollectionParser *factorParser; + PKCollectionParser *nextFactorParser; + PKCollectionParser *phraseParser; + PKCollectionParser *phraseStarParser; + PKCollectionParser *phrasePlusParser; + PKCollectionParser *phraseQuestionParser; + PKCollectionParser *phraseCardinalityParser; + PKCollectionParser *cardinalityParser; + PKCollectionParser *primaryExprParser; + PKCollectionParser *negatedPrimaryExprParser; + PKCollectionParser *barePrimaryExprParser; + PKCollectionParser *predicateParser; + PKCollectionParser *intersectionParser; + PKCollectionParser *differenceParser; + PKCollectionParser *atomicValueParser; + PKCollectionParser *parserParser; + PKCollectionParser *discardParser; + PKCollectionParser *patternParser; + PKCollectionParser *delimitedStringParser; + PKParser *literalParser; + PKParser *variableParser; + PKParser *constantParser; +} + +- (id)initWithAssembler:(id)a; + +@property (nonatomic, retain) PKCollectionParser *statementParser; +@property (nonatomic, retain) PKCollectionParser *declarationParser; +@property (nonatomic, retain) PKCollectionParser *callbackParser; +@property (nonatomic, retain) PKCollectionParser *selectorParser; +@property (nonatomic, retain) PKCollectionParser *exprParser; +@property (nonatomic, retain) PKCollectionParser *termParser; +@property (nonatomic, retain) PKCollectionParser *orTermParser; +@property (nonatomic, retain) PKCollectionParser *factorParser; +@property (nonatomic, retain) PKCollectionParser *nextFactorParser; +@property (nonatomic, retain) PKCollectionParser *phraseParser; +@property (nonatomic, retain) PKCollectionParser *phraseStarParser; +@property (nonatomic, retain) PKCollectionParser *phrasePlusParser; +@property (nonatomic, retain) PKCollectionParser *phraseQuestionParser; +@property (nonatomic, retain) PKCollectionParser *phraseCardinalityParser; +@property (nonatomic, retain) PKCollectionParser *cardinalityParser; +@property (nonatomic, retain) PKCollectionParser *primaryExprParser; +@property (nonatomic, retain) PKCollectionParser *negatedPrimaryExprParser; +@property (nonatomic, retain) PKCollectionParser *barePrimaryExprParser; +@property (nonatomic, retain) PKCollectionParser *predicateParser; +@property (nonatomic, retain) PKCollectionParser *intersectionParser; +@property (nonatomic, retain) PKCollectionParser *differenceParser; +@property (nonatomic, retain) PKCollectionParser *atomicValueParser; +@property (nonatomic, retain) PKCollectionParser *parserParser; +@property (nonatomic, retain) PKCollectionParser *discardParser; +@property (nonatomic, retain) PKCollectionParser *patternParser; +@property (nonatomic, retain) PKCollectionParser *delimitedStringParser; +@property (nonatomic, retain) PKParser *literalParser; +@property (nonatomic, retain) PKParser *variableParser; +@property (nonatomic, retain) PKParser *constantParser; +@property (nonatomic, retain, readonly) PKParser *whitespaceParser; +@property (nonatomic, retain, readonly) PKCollectionParser *optionalWhitespaceParser; +@end diff --git a/src/PKGrammarParser.m b/src/PKGrammarParser.m new file mode 100644 index 0000000..e07292a --- /dev/null +++ b/src/PKGrammarParser.m @@ -0,0 +1,646 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKGrammarParser.h" +#import + +@interface NSObject (PKGrammarParserAdditions) +- (void)didMatchStatement:(PKAssembly *)a; +- (void)didMatchCallback:(PKAssembly *)a; +- (void)didMatchExpression:(PKAssembly *)a; +- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchIntersection:(PKAssembly *)a; +- (void)didMatchDifference:(PKAssembly *)a; +- (void)didMatchPatternOptions:(PKAssembly *)a; +- (void)didMatchPattern:(PKAssembly *)a; +- (void)didMatchDiscard:(PKAssembly *)a; +- (void)didMatchLiteral:(PKAssembly *)a; +- (void)didMatchVariable:(PKAssembly *)a; +- (void)didMatchConstant:(PKAssembly *)a; +- (void)didMatchDelimitedString:(PKAssembly *)a; +- (void)didMatchNum:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchPlus:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +- (void)didMatchPhraseCardinality:(PKAssembly *)a; +- (void)didMatchCardinality:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchNegation:(PKAssembly *)a; +@end + +@interface PKGrammarParser () +- (PKAlternation *)zeroOrOne:(PKParser *)p; +- (PKSequence *)oneOrMore:(PKParser *)p; +@end + +@implementation PKGrammarParser + +- (id)initWithAssembler:(id)a { + if (self = [super init]) { + assembler = a; + } + return self; +} + + +- (void)dealloc { + assembler = nil; // appease clang static analyzer + + PKReleaseSubparserTree(statementParser); + PKReleaseSubparserTree(exprParser); + + self.statementParser = nil; + self.declarationParser = nil; + self.callbackParser = nil; + self.selectorParser = nil; + self.exprParser = nil; + self.termParser = nil; + self.orTermParser = nil; + self.factorParser = nil; + self.nextFactorParser = nil; + self.phraseParser = nil; + self.phraseStarParser = nil; + self.phrasePlusParser = nil; + self.phraseQuestionParser = nil; + self.phraseCardinalityParser = nil; + self.cardinalityParser = nil; + self.primaryExprParser = nil; + self.negatedPrimaryExprParser = nil; + self.barePrimaryExprParser = nil; + self.predicateParser = nil; + self.intersectionParser = nil; + self.differenceParser = nil; + self.atomicValueParser = nil; + self.parserParser = nil; + self.discardParser = nil; + self.patternParser = nil; + self.delimitedStringParser = nil; + self.literalParser = nil; + self.variableParser = nil; + self.constantParser = nil; + [super dealloc]; +} + + +- (PKAlternation *)zeroOrOne:(PKParser *)p { + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:p]; + return a; +} + + +- (PKSequence *)oneOrMore:(PKParser *)p { + PKSequence *s = [PKSequence sequence]; + [s add:p]; + [s add:[PKRepetition repetitionWithSubparser:p]]; + return s; +} + + +// @start = statement*; +// satement = S* declaration S* '=' expr; +// callback = S* '(' S* selector S* ')'; +// selector = Word ':'; +// expr = S* term orTerm* S*; +// term = factor nextFactor*; +// orTerm = S* '|' S* term; +// factor = phrase | phraseStar | phrasePlus | phraseQuestion | phraseCardinality; +// nextFactor = S factor; + +// phrase = primaryExpr predicate*; +// phraseStar = phrase S* '*'; +// phrasePlus = phrase S* '+'; +// phraseQuestion = phrase S* '?'; +// phraseCardinality = phrase S* cardinality; +// cardinality = '{' S* Number (S* ',' S* Number)? S* '}'; + +// predicate = S* (intersection | difference); +// intersection = '&' S* primaryExpr; +// difference = '-' S* primaryExpr; + +// primaryExpr = negatedPrimaryExpr | barePrimaryExpr; +// negatedPrimaryExpr = '~' barePrimaryExpr; +// barePrimaryExpr = atomicValue | '(' expr ')'; +// atomicValue = parser discard?; +// parser = pattern | literal | variable | constant | delimitedString; +// discard = S* '!'; +// pattern = DelimitedString('/', '/') (Word & /[imxsw]+/)?; +// delimitedString = 'DelimitedString' S* '(' S* QuotedString (S* ',' QuotedString)? S* ')'; +// literal = QuotedString; +// variable = LowercaseWord; +// constant = UppercaseWord; + + +// satement = S* declaration S* '=' expr; +- (PKCollectionParser *)statementParser { + if (!statementParser) { + self.statementParser = [PKSequence sequence]; + statementParser.name = @"statement"; + [statementParser add:self.optionalWhitespaceParser]; + + PKTrack *tr = [PKTrack track]; + [tr add:self.declarationParser]; + [tr add:self.optionalWhitespaceParser]; + [tr add:[PKSymbol symbolWithString:@"="]]; + + // accept any tokens in the parser expr the first time around. just gather tokens for later + [tr add:[self oneOrMore:[PKAny any]]]; + + [statementParser add:tr]; + [statementParser setAssembler:assembler selector:@selector(didMatchStatement:)]; + } + return statementParser; +} + + +// declaration = Word callback?; +- (PKCollectionParser *)declarationParser { + if (!declarationParser) { + self.declarationParser = [PKSequence sequence]; + declarationParser.name = @"declaration"; + [declarationParser add:[PKWord word]]; + [declarationParser add:[self zeroOrOne:self.callbackParser]]; + } + return declarationParser; +} + + +// callback = S* '(' S* selector S* ')'; +- (PKCollectionParser *)callbackParser { + if (!callbackParser) { + self.callbackParser = [PKSequence sequence]; + callbackParser.name = @"callback"; + [callbackParser add:self.optionalWhitespaceParser]; + + PKTrack *tr = [PKTrack track]; + [tr add:[[PKSymbol symbolWithString:@"("] discard]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:self.selectorParser]; + [tr add:self.optionalWhitespaceParser]; + [tr add:[[PKSymbol symbolWithString:@")"] discard]]; + + [callbackParser add:tr]; + [callbackParser setAssembler:assembler selector:@selector(didMatchCallback:)]; + } + return callbackParser; +} + + +// selector = Word ':'; +- (PKCollectionParser *)selectorParser { + if (!selectorParser) { + self.selectorParser = [PKTrack track]; + selectorParser.name = @"selector"; + [selectorParser add:[PKLowercaseWord word]]; + [selectorParser add:[[PKSymbol symbolWithString:@":"] discard]]; + } + return selectorParser; +} + + +// expr = S* term orTerm* S*; +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + exprParser.name = @"expr"; + [exprParser add:self.optionalWhitespaceParser]; + [exprParser add:self.termParser]; + [exprParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + [exprParser add:self.optionalWhitespaceParser]; + [exprParser setAssembler:assembler selector:@selector(didMatchExpression:)]; + } + return exprParser; +} + + +// term = factor nextFactor*; +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + termParser.name = @"term"; + [termParser add:self.factorParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.nextFactorParser]]; + [termParser setAssembler:assembler selector:@selector(didMatchAnd:)]; + } + return termParser; +} + + +// orTerm = S* '|' S* term; +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKSequence sequence]; + orTermParser.name = @"orTerm"; + [orTermParser add:self.optionalWhitespaceParser]; + + PKTrack *tr = [PKTrack track]; + [tr add:[PKSymbol symbolWithString:@"|"]]; // preserve as fence + [tr add:self.optionalWhitespaceParser]; + [tr add:self.termParser]; + + [orTermParser add:tr]; + [orTermParser setAssembler:assembler selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// factor = phrase | phraseStar | phrasePlus | phraseQuestion | phraseCardinality; +- (PKCollectionParser *)factorParser { + if (!factorParser) { + self.factorParser = [PKAlternation alternation]; + factorParser.name = @"factor"; + [factorParser add:self.phraseParser]; + [factorParser add:self.phraseStarParser]; + [factorParser add:self.phrasePlusParser]; + [factorParser add:self.phraseQuestionParser]; + [factorParser add:self.phraseCardinalityParser]; + } + return factorParser; +} + + +// nextFactor = S factor; +- (PKCollectionParser *)nextFactorParser { + if (!nextFactorParser) { + self.nextFactorParser = [PKSequence sequence]; + nextFactorParser.name = @"nextFactor"; + [nextFactorParser add:self.whitespaceParser]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:self.phraseParser]; + [a add:self.phraseStarParser]; + [a add:self.phrasePlusParser]; + [a add:self.phraseQuestionParser]; + [a add:self.phraseCardinalityParser]; + + [nextFactorParser add:a]; + } + return nextFactorParser; +} + + +// phrase = primaryExpr predicate*; +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + self.phraseParser = [PKSequence sequence]; + phraseParser.name = @"phrase"; + [phraseParser add:self.primaryExprParser]; + [phraseParser add:[PKRepetition repetitionWithSubparser:self.predicateParser]]; + } + return phraseParser; +} + + +// primaryExpr = negatedPrimaryExpr | barePrimaryExpr; +- (PKCollectionParser *)primaryExprParser { + if (!primaryExprParser) { + self.primaryExprParser = [PKAlternation alternation]; + primaryExprParser.name = @"primaryExpr"; + [primaryExprParser add:self.negatedPrimaryExprParser]; + [primaryExprParser add:self.barePrimaryExprParser]; + } + return primaryExprParser; +} + + +// negatedPrimaryExpr = '~' barePrimaryExpr; +- (PKCollectionParser *)negatedPrimaryExprParser { + if (!negatedPrimaryExprParser) { + self.negatedPrimaryExprParser = [PKSequence sequence]; + negatedPrimaryExprParser.name = @"negatedPrimaryExpr"; + [negatedPrimaryExprParser add:[[PKLiteral literalWithString:@"~"] discard]]; + [negatedPrimaryExprParser add:self.barePrimaryExprParser]; + [negatedPrimaryExprParser setAssembler:assembler selector:@selector(didMatchNegation:)]; + } + return negatedPrimaryExprParser; +} + + +// barePrimaryExpr = atomicValue | '(' expr ')'; +- (PKCollectionParser *)barePrimaryExprParser { + if (!barePrimaryExprParser) { + self.barePrimaryExprParser = [PKAlternation alternation]; + barePrimaryExprParser.name = @"barePrimaryExpr"; + [barePrimaryExprParser add:self.atomicValueParser]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:self.exprParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + [barePrimaryExprParser add:s]; + } + return barePrimaryExprParser; +} + + +// predicate = S* (intersection | difference); +- (PKCollectionParser *)predicateParser { + if (!predicateParser) { + self.predicateParser = [PKSequence sequence]; + predicateParser.name = @"predicate"; + [predicateParser add:self.optionalWhitespaceParser]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:self.intersectionParser]; + [a add:self.differenceParser]; + + [predicateParser add:a]; + } + return predicateParser; +} + + +// intersection = '&' S* primaryExpr; +- (PKCollectionParser *)intersectionParser { + if (!intersectionParser) { + self.intersectionParser = [PKTrack track]; + intersectionParser.name = @"intersection"; + + PKTrack *tr = [PKTrack track]; + [tr add:[[PKSymbol symbolWithString:@"&"] discard]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:self.primaryExprParser]; + + [intersectionParser add:tr]; + [intersectionParser setAssembler:assembler selector:@selector(didMatchIntersection:)]; + } + return intersectionParser; +} + + +// difference = '-' S* primaryExpr; +- (PKCollectionParser *)differenceParser { + if (!differenceParser) { + self.differenceParser = [PKTrack track]; + differenceParser.name = @"difference"; + + PKTrack *tr = [PKTrack track]; + [tr add:[[PKSymbol symbolWithString:@"-"] discard]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:self.primaryExprParser]; + + [differenceParser add:tr]; + [differenceParser setAssembler:assembler selector:@selector(didMatchDifference:)]; + } + return differenceParser; +} + + +// phraseStar = phrase S* '*'; +- (PKCollectionParser *)phraseStarParser { + if (!phraseStarParser) { + self.phraseStarParser = [PKSequence sequence]; + phraseStarParser.name = @"phraseStar"; + [phraseStarParser add:self.phraseParser]; + [phraseStarParser add:self.optionalWhitespaceParser]; + [phraseStarParser add:[[PKSymbol symbolWithString:@"*"] discard]]; + [phraseStarParser setAssembler:assembler selector:@selector(didMatchStar:)]; + } + return phraseStarParser; +} + + +// phrasePlus = phrase S* '+'; +- (PKCollectionParser *)phrasePlusParser { + if (!phrasePlusParser) { + self.phrasePlusParser = [PKSequence sequence]; + phrasePlusParser.name = @"phrasePlus"; + [phrasePlusParser add:self.phraseParser]; + [phrasePlusParser add:self.optionalWhitespaceParser]; + [phrasePlusParser add:[[PKSymbol symbolWithString:@"+"] discard]]; + [phrasePlusParser setAssembler:assembler selector:@selector(didMatchPlus:)]; + } + return phrasePlusParser; +} + + +// phraseQuestion = phrase S* '?'; +- (PKCollectionParser *)phraseQuestionParser { + if (!phraseQuestionParser) { + self.phraseQuestionParser = [PKSequence sequence]; + phraseQuestionParser.name = @"phraseQuestion"; + [phraseQuestionParser add:self.phraseParser]; + [phraseQuestionParser add:self.optionalWhitespaceParser]; + [phraseQuestionParser add:[[PKSymbol symbolWithString:@"?"] discard]]; + [phraseQuestionParser setAssembler:assembler selector:@selector(didMatchQuestion:)]; + } + return phraseQuestionParser; +} + + +// phraseCardinality = phrase S* cardinality; +- (PKCollectionParser *)phraseCardinalityParser { + if (!phraseCardinalityParser) { + self.phraseCardinalityParser = [PKSequence sequence]; + phraseCardinalityParser.name = @"phraseCardinality"; + [phraseCardinalityParser add:self.phraseParser]; + [phraseCardinalityParser add:self.optionalWhitespaceParser]; + [phraseCardinalityParser add:self.cardinalityParser]; + [phraseCardinalityParser setAssembler:assembler selector:@selector(didMatchPhraseCardinality:)]; + } + return phraseCardinalityParser; +} + + +// cardinality = '{' S* Number (S* ',' S* Number)? S* '}'; +- (PKCollectionParser *)cardinalityParser { + if (!cardinalityParser) { + self.cardinalityParser = [PKSequence sequence]; + cardinalityParser.name = @"cardinality"; + + PKTrack *commaNum = [PKSequence sequence]; + [commaNum add:self.optionalWhitespaceParser]; + [commaNum add:[[PKSymbol symbolWithString:@","] discard]]; + [commaNum add:self.optionalWhitespaceParser]; + [commaNum add:[PKNumber number]]; + + PKTrack *tr = [PKTrack track]; + [tr add:[PKSymbol symbolWithString:@"{"]]; // serves as fence. dont discard + [tr add:self.optionalWhitespaceParser]; + [tr add:[PKNumber number]]; + [tr add:[self zeroOrOne:commaNum]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:[[PKSymbol symbolWithString:@"}"] discard]]; + + [cardinalityParser add:tr]; + [cardinalityParser setAssembler:assembler selector:@selector(didMatchCardinality:)]; + } + return cardinalityParser; +} + + +// atomicValue = parser discard?; +- (PKCollectionParser *)atomicValueParser { + if (!atomicValueParser) { + self.atomicValueParser = [PKSequence sequence]; + atomicValueParser.name = @"atomicValue"; + [atomicValueParser add:self.parserParser]; + [atomicValueParser add:[self zeroOrOne:self.discardParser]]; + } + return atomicValueParser; +} + + +// parser = pattern | literal | variable | constant | delimitedString; +- (PKCollectionParser *)parserParser { + if (!parserParser) { + self.parserParser = [PKAlternation alternation]; + parserParser.name = @"parser"; + [parserParser add:self.patternParser]; + [parserParser add:self.literalParser]; + [parserParser add:self.variableParser]; + [parserParser add:self.constantParser]; + [parserParser add:self.delimitedStringParser]; + } + return parserParser; +} + + +// discard = S* '!'; +- (PKCollectionParser *)discardParser { + if (!discardParser) { + self.discardParser = [PKSequence sequence]; + discardParser.name = @"discard"; + [discardParser add:self.optionalWhitespaceParser]; + [discardParser add:[[PKSymbol symbolWithString:@"!"] discard]]; + [discardParser setAssembler:assembler selector:@selector(didMatchDiscard:)]; + } + return discardParser; +} + + +// pattern = DelimitedString('/', '/') (Word & /[imxsw]+/)?; +- (PKCollectionParser *)patternParser { + if (!patternParser) { + patternParser.name = @"pattern"; + self.patternParser = [PKSequence sequence]; + [patternParser add:[PKDelimitedString delimitedStringWithStartMarker:@"/" endMarker:@"/"]]; + + PKParser *opts = [PKPattern patternWithString:@"[imxsw]+" options:PKPatternOptionsNone]; + PKIntersection *inter = [PKIntersection intersection]; + [inter add:[PKWord word]]; + [inter add:opts]; + [inter setAssembler:assembler selector:@selector(didMatchPatternOptions:)]; + + [patternParser add:[self zeroOrOne:inter]]; + [patternParser setAssembler:assembler selector:@selector(didMatchPattern:)]; + } + return patternParser; +} + + +// delimitedString = 'DelimitedString' S* '(' S* QuotedString (S* ',' QuotedString)? S* ')'; +- (PKCollectionParser *)delimitedStringParser { + if (!delimitedStringParser) { + self.delimitedStringParser = [PKTrack track]; + delimitedStringParser.name = @"delimitedString"; + + PKSequence *secondArg = [PKSequence sequence]; + [secondArg add:self.optionalWhitespaceParser]; + + PKTrack *tr = [PKTrack track]; + [tr add:[[PKSymbol symbolWithString:@","] discard]]; + [tr add:self.optionalWhitespaceParser]; + [tr add:[PKQuotedString quotedString]]; // endMarker + [secondArg add:tr]; + + [delimitedStringParser add:[[PKLiteral literalWithString:@"DelimitedString"] discard]]; + [delimitedStringParser add:self.optionalWhitespaceParser]; + [delimitedStringParser add:[PKSymbol symbolWithString:@"("]]; // preserve as fence + [delimitedStringParser add:self.optionalWhitespaceParser]; + [delimitedStringParser add:[PKQuotedString quotedString]]; // startMarker + [delimitedStringParser add:[self zeroOrOne:secondArg]]; + [delimitedStringParser add:self.optionalWhitespaceParser]; + [delimitedStringParser add:[[PKSymbol symbolWithString:@")"] discard]]; + + [delimitedStringParser setAssembler:assembler selector:@selector(didMatchDelimitedString:)]; + } + return delimitedStringParser; +} + + +// literal = QuotedString; +- (PKParser *)literalParser { + if (!literalParser) { + self.literalParser = [PKQuotedString quotedString]; + [literalParser setAssembler:assembler selector:@selector(didMatchLiteral:)]; + } + return literalParser; +} + + +// variable = LowercaseWord; +- (PKParser *)variableParser { + if (!variableParser) { + self.variableParser = [PKLowercaseWord word]; + variableParser.name = @"variable"; + [variableParser setAssembler:assembler selector:@selector(didMatchVariable:)]; + } + return variableParser; +} + + +// constant = UppercaseWord; +- (PKParser *)constantParser { + if (!constantParser) { + self.constantParser = [PKUppercaseWord word]; + constantParser.name = @"constant"; + [constantParser setAssembler:assembler selector:@selector(didMatchConstant:)]; + } + return constantParser; +} + + +- (PKParser *)whitespaceParser { + return [[PKWhitespace whitespace] discard]; +} + + +- (PKCollectionParser *)optionalWhitespaceParser { + return [PKRepetition repetitionWithSubparser:self.whitespaceParser]; +} + +@synthesize statementParser; +@synthesize declarationParser; +@synthesize callbackParser; +@synthesize selectorParser; +@synthesize exprParser; +@synthesize termParser; +@synthesize orTermParser; +@synthesize factorParser; +@synthesize nextFactorParser; +@synthesize phraseParser; +@synthesize phraseStarParser; +@synthesize phrasePlusParser; +@synthesize phraseQuestionParser; +@synthesize phraseCardinalityParser; +@synthesize cardinalityParser; +@synthesize primaryExprParser; +@synthesize negatedPrimaryExprParser; +@synthesize barePrimaryExprParser; +@synthesize predicateParser; +@synthesize intersectionParser; +@synthesize differenceParser; +@synthesize atomicValueParser; +@synthesize parserParser; +@synthesize discardParser; +@synthesize patternParser; +@synthesize delimitedStringParser; +@synthesize literalParser; +@synthesize variableParser; +@synthesize constantParser; +@end diff --git a/src/PKIntersection.m b/src/PKIntersection.m new file mode 100644 index 0000000..08e9b8a --- /dev/null +++ b/src/PKIntersection.m @@ -0,0 +1,82 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKIntersection.h" +#import + +@interface NSMutableSet (PKIntersectionAdditions) +- (void)intersectSetTestingEquality:(NSSet *)s; +@end + +@implementation NSMutableSet (PKIntersectionAdditions) + +- (void)intersectSetTestingEquality:(NSSet *)s { + for (id a1 in self) { + BOOL found = NO; + for (id a2 in s) { + if ([a1 isEqual:a2]) { + found = YES; + break; + } + } + if (!found) { + [self removeObject:a1]; + } + } +} + +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; +@end + +@implementation PKIntersection + ++ (id)intersection { + return [self intersectionWithSubparsers:nil]; +} + + ++ (id)intersectionWithSubparsers:(PKParser *)p1, ... { + va_list vargs; + va_start(vargs, p1); + PKIntersection *inter = [self collectionParserWithFirst:p1 rest:vargs]; + va_end(vargs); + return inter; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSMutableSet *outAssemblies = [NSMutableSet set]; + + NSInteger i = 0; + for (PKParser *p in subparsers) { + if (0 == i++) { + outAssemblies = [[[p matchAndAssemble:inAssemblies] mutableCopy] autorelease]; + } else { + [outAssemblies intersectSetTestingEquality:[p allMatchesFor:inAssemblies]]; + } + } + + return outAssemblies; +} + +@end diff --git a/src/PKLetter.m b/src/PKLetter.m new file mode 100644 index 0000000..6aab51b --- /dev/null +++ b/src/PKLetter.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKLetter + ++ (id)letter { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKUniChar c = [obj intValue]; + return isalpha(c); +} + +@end diff --git a/src/PKLiteral.m b/src/PKLiteral.m new file mode 100644 index 0000000..e502bc1 --- /dev/null +++ b/src/PKLiteral.m @@ -0,0 +1,61 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKLiteral () +@property (nonatomic, retain) PKToken *literal; +@end + +@implementation PKLiteral + ++ (id)literalWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + //NSParameterAssert(s); + self = [super initWithString:s]; + if (self) { + self.literal = [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:s floatValue:0.0]; + } + return self; +} + + +- (void)dealloc { + self.literal = nil; + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + return [literal.stringValue isEqualToString:[obj stringValue]]; + //return [literal isEqual:obj]; +} + + +- (NSString *)description { + NSString *className = [NSStringFromClass([self class]) substringFromIndex:2]; + if ([name length]) { + return [NSString stringWithFormat:@"%@ (%@) %@", className, name, literal.stringValue]; + } else { + return [NSString stringWithFormat:@"%@ %@", className, literal.stringValue]; + } +} + +@synthesize literal; +@end diff --git a/src/PKLowercaseWord.m b/src/PKLowercaseWord.m new file mode 100644 index 0000000..ddb49d1 --- /dev/null +++ b/src/PKLowercaseWord.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKLowercaseWord + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + NSString *s = tok.stringValue; + return [s length] && islower([s characterAtIndex:0]); +} + +@end diff --git a/src/PKMultiLineCommentState.m b/src/PKMultiLineCommentState.m new file mode 100644 index 0000000..87e2ec9 --- /dev/null +++ b/src/PKMultiLineCommentState.m @@ -0,0 +1,152 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (void)appendString:(NSString *)s; +- (NSString *)bufferedString; +@end + +@interface PKCommentState () +@property (nonatomic, retain) PKSymbolRootNode *rootNode; +@end + +@interface PKMultiLineCommentState () +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end; +- (void)removeStartMarker:(NSString *)start; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSMutableArray *endMarkers; +@property (nonatomic, copy) NSString *currentStartMarker; +@end + +@implementation PKMultiLineCommentState + +- (id)init { + if (self = [super init]) { + self.startMarkers = [NSMutableArray array]; + self.endMarkers = [NSMutableArray array]; + } + return self; +} + + +- (void)dealloc { + self.startMarkers = nil; + self.endMarkers = nil; + self.currentStartMarker = nil; + [super dealloc]; +} + + +- (void)addStartMarker:(NSString *)start endMarker:(NSString *)end { + NSParameterAssert([start length]); + NSParameterAssert([end length]); + [startMarkers addObject:start]; + [endMarkers addObject:end]; +} + + +- (void)removeStartMarker:(NSString *)start { + NSParameterAssert([start length]); + NSUInteger i = [startMarkers indexOfObject:start]; + if (NSNotFound != i) { + [startMarkers removeObject:start]; + [endMarkers removeObjectAtIndex:i]; // this should always be in range. + } +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + BOOL balanceEOF = t.commentState.balancesEOFTerminatedComments; + BOOL reportTokens = t.commentState.reportsCommentTokens; + if (reportTokens) { + [self resetWithReader:r]; + [self appendString:currentStartMarker]; + } + + NSUInteger i = [startMarkers indexOfObject:currentStartMarker]; + NSString *currentEndSymbol = [endMarkers objectAtIndex:i]; + PKUniChar e = [currentEndSymbol characterAtIndex:0]; + + // get the definitions of all multi-char comment start and end symbols from the commentState + PKSymbolRootNode *rootNode = t.commentState.rootNode; + + PKUniChar c; + while (1) { + c = [r read]; + if (PKEOF == c) { + if (balanceEOF) { + [self appendString:currentEndSymbol]; + } + break; + } + + if (e == c) { + NSString *peek = [rootNode nextSymbol:r startingWith:e]; + if ([currentEndSymbol isEqualToString:peek]) { + if (reportTokens) { + [self appendString:currentEndSymbol]; + } + c = [r read]; + break; + } else { + [r unread:[peek length] - 1]; + if (e != [peek characterAtIndex:0]) { + if (reportTokens) { + [self append:c]; + } + c = [r read]; + } + } + } + if (reportTokens) { + [self append:c]; + } + } + + if (PKEOF != c) { + [r unread]; + } + + self.currentStartMarker = nil; + + if (reportTokens) { + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeComment stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; + } else { + return [t nextToken]; + } +} + +@synthesize startMarkers; +@synthesize endMarkers; +@synthesize currentStartMarker; +@end diff --git a/src/PKNegation.m b/src/PKNegation.m new file mode 100644 index 0000000..1f68afe --- /dev/null +++ b/src/PKNegation.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKNegation.h" +#import +#import + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@interface PKNegation () +@property (nonatomic, retain, readwrite) PKParser *subparser; +@property (nonatomic, retain) PKParser *difference; +@end + +@implementation PKNegation + ++ (id)negationWithSubparser:(PKParser *)s { + return [[[self alloc] initWithSubparser:s] autorelease]; +} + + +- (id)initWithSubparser:(PKParser *)s { + if (self = [super init]) { + self.subparser = s; + self.difference = [PKDifference differenceWithSubparser:[PKAny any] minus:subparser]; + } + return self; +} + + +- (void)dealloc { + self.subparser = nil; + self.difference = nil; + [super dealloc]; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } else { + return [subparser parserNamed:s]; + } +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + + return [difference allMatchesFor:inAssemblies]; +} + +@synthesize subparser; +@synthesize difference; +@end diff --git a/src/PKNumber.m b/src/PKNumber.m new file mode 100644 index 0000000..82b8a63 --- /dev/null +++ b/src/PKNumber.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKNumber + ++ (id)number { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isNumber; +} + +@end \ No newline at end of file diff --git a/src/PKNumberState.m b/src/PKNumberState.m new file mode 100644 index 0000000..f941f12 --- /dev/null +++ b/src/PKNumberState.m @@ -0,0 +1,264 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface PKNumberState () +- (CGFloat)absorbDigitsFromReader:(PKReader *)r; +- (CGFloat)value; +- (void)parseLeftSideFromReader:(PKReader *)r; +- (void)parseRightSideFromReader:(PKReader *)r; +- (void)parseExponentFromReader:(PKReader *)r; +- (void)reset:(PKUniChar)cin; +- (void)checkForHex:(PKReader *)r; +- (void)checkForOctal; +@end + +@implementation PKNumberState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + [self resetWithReader:r]; + isNegative = NO; + originalCin = cin; + + if ('-' == cin) { + isNegative = YES; + cin = [r read]; + [self append:'-']; + } else if ('+' == cin) { + cin = [r read]; + [self append:'+']; + } + + [self reset:cin]; + if ('.' == c) { + [self parseRightSideFromReader:r]; + } else { + [self parseLeftSideFromReader:r]; + if (isDecimal) { + [self parseRightSideFromReader:r]; + } + } + + // erroneous ., +, -, or 0x + if (!gotADigit) { + if (isHex) { + [r unread]; + return [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:@"0" floatValue:0.0]; + } else { + if (isNegative && PKEOF != c) { // ?? + [r unread]; + } + return [t.symbolState nextTokenFromReader:r startingWith:originalCin tokenizer:t]; + } + } + + if (PKEOF != c) { + [r unread]; + } + + if (isNegative) { + floatValue = -floatValue; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:[self bufferedString] floatValue:[self value]]; + tok.offset = offset; + return tok; +} + + +- (CGFloat)value { + CGFloat result = (CGFloat)floatValue; + + NSUInteger i = 0; + for ( ; i < exp; i++) { + if (isNegativeExp) { + result /= (CGFloat)10.0; + } else { + result *= (CGFloat)10.0; + } + } + + return (CGFloat)result; +} + + +- (CGFloat)absorbDigitsFromReader:(PKReader *)r { + CGFloat divideBy = 1.0; + CGFloat v = 0.0; + BOOL isHexAlpha = NO; + + while (1) { + isHexAlpha = NO; + if (allowsHexadecimalNotation) { + [self checkForHex:r]; + if (c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F') { + isHexAlpha = YES; + } + } + + if (isdigit(c) || isHexAlpha) { + [self append:c]; + len++; + gotADigit = YES; + + if (allowsOctalNotation) { + [self checkForOctal]; + } + + if (isHexAlpha) { + if (c >= 'a' && c <= 'f') { + c = toupper(c); + } + c -= 7; + } + v = v * base + (c - '0'); + c = [r read]; + if (isFraction) { + divideBy *= base; + } + } else { + break; + } + } + + if (isFraction) { + v = v / divideBy; + } + + return (CGFloat)v; +} + + +- (void)parseLeftSideFromReader:(PKReader *)r { + isFraction = NO; + floatValue = [self absorbDigitsFromReader:r]; +} + + +- (void)parseRightSideFromReader:(PKReader *)r { + if ('.' == c) { + PKUniChar n = [r read]; + BOOL nextIsDigit = isdigit(n); + if (PKEOF != n) { + [r unread]; + } + + if (nextIsDigit || allowsTrailingDot) { + [self append:'.']; + if (nextIsDigit) { + c = [r read]; + isFraction = YES; + floatValue += [self absorbDigitsFromReader:r]; + } + } + } + + if (allowsScientificNotation) { + [self parseExponentFromReader:r]; + } +} + + +- (void)parseExponentFromReader:(PKReader *)r { + NSParameterAssert(r); + if ('e' == c || 'E' == c) { + PKUniChar e = c; + c = [r read]; + + BOOL hasExp = isdigit(c); + isNegativeExp = ('-' == c); + BOOL positiveExp = ('+' == c); + + if (!hasExp && (isNegativeExp || positiveExp)) { + c = [r read]; + hasExp = isdigit(c); + } + if (PKEOF != c) { + [r unread]; + } + if (hasExp) { + [self append:e]; + if (isNegativeExp) { + [self append:'-']; + } else if (positiveExp) { + [self append:'+']; + } + c = [r read]; + isFraction = NO; + exp = [self absorbDigitsFromReader:r]; + } + } +} + + +- (void)reset:(PKUniChar)cin { + c = cin; + firstNum = cin; + gotADigit = NO; + isFraction = NO; + isDecimal = YES; + isHex = NO; + len = 0; + base = (CGFloat)10.0; + floatValue = (CGFloat)0.0; + exp = (CGFloat)0.0; + isNegativeExp = NO; +} + + +- (void)checkForHex:(PKReader *)r { + if ('x' == c && '0' == firstNum && !isFraction && 1 == len) { + [self append:c]; + len++; + c = [r read]; + isDecimal = NO; + base = (CGFloat)16.0; + isHex = YES; + gotADigit = NO; + } +} + + +- (void)checkForOctal { + if ('0' == firstNum && !isFraction && isDecimal && 2 == len) { + isDecimal = NO; + base = (CGFloat)8.0; + } +} + +@synthesize allowsTrailingDot; +@synthesize allowsScientificNotation; +@synthesize allowsOctalNotation; +@synthesize allowsHexadecimalNotation; +@end diff --git a/src/PKParser.m b/src/PKParser.m new file mode 100644 index 0000000..a3add8f --- /dev/null +++ b/src/PKParser.m @@ -0,0 +1,203 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import + +@interface PKAssembly () +- (BOOL)hasMore; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (PKAssembly *)best:(NSSet *)inAssemblies; +@end + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@implementation PKParser + ++ (id)parser { + return [[[self alloc] init] autorelease]; +} + + +- (void)dealloc { +#ifdef TARGET_OS_SNOW_LEOPARD + self.assemblerBlock = nil; + self.preassemblerBlock = nil; +#endif + self.assembler = nil; + self.assemblerSelector = nil; + self.preassembler = nil; + self.preassemblerSelector = nil; + self.name = nil; + self.tokenizer = nil; + [super dealloc]; +} + + +- (void)setAssembler:(id)a selector:(SEL)sel { + self.assembler = a; + self.assemblerSelector = sel; +} + + +- (void)setPreassembler:(id)a selector:(SEL)sel { + self.preassembler = a; + self.preassemblerSelector = sel; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } + return nil; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSAssert1(0, @"-[PKParser %s] must be overriden", _cmd); + return nil; +} + + +- (PKAssembly *)bestMatchFor:(PKAssembly *)a { + NSParameterAssert(a); + NSSet *initialState = [NSSet setWithObject:a]; + NSSet *finalState = [self matchAndAssemble:initialState]; + return [self best:finalState]; +} + + +- (PKAssembly *)completeMatchFor:(PKAssembly *)a { + NSParameterAssert(a); + PKAssembly *best = [self bestMatchFor:a]; + if (best && ![best hasMore]) { + return best; + } + return nil; +} + + +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + +#ifdef TARGET_OS_SNOW_LEOPARD + if (preassemblerBlock) { + for (PKAssembly *a in inAssemblies) { + preassemblerBlock(a); + } + } else +#endif + if (preassembler) { + NSAssert2([preassembler respondsToSelector:preassemblerSelector], @"provided preassembler %@ should respond to %s", preassembler, preassemblerSelector); + for (PKAssembly *a in inAssemblies) { + [preassembler performSelector:preassemblerSelector withObject:a]; + } + } + + NSSet *outAssemblies = [self allMatchesFor:inAssemblies]; + +#ifdef TARGET_OS_SNOW_LEOPARD + if (assemblerBlock) { + for (PKAssembly *a in outAssemblies) { + assemblerBlock(a); + } + } else +#endif + if (assembler) { + NSAssert2([assembler respondsToSelector:assemblerSelector], @"provided assembler %@ should respond to %s", assembler, assemblerSelector); + for (PKAssembly *a in outAssemblies) { + [assembler performSelector:assemblerSelector withObject:a]; + } + } + return outAssemblies; +} + + +- (PKAssembly *)best:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + PKAssembly *best = nil; + + for (PKAssembly *a in inAssemblies) { + if (![a hasMore]) { + best = a; + break; + } + if (!best || a.objectsConsumed > best.objectsConsumed) { + best = a; + } + } + + return best; +} + + +- (NSString *)description { + NSString *className = [NSStringFromClass([self class]) substringFromIndex:2]; + if ([name length]) { + return [NSString stringWithFormat:@"%@ (%@)", className, name]; + } else { + return [NSString stringWithFormat:@"%@", className]; + } +} + +#ifdef TARGET_OS_SNOW_LEOPARD +@synthesize assemblerBlock; +@synthesize preassemblerBlock; +#endif +@synthesize assembler; +@synthesize assemblerSelector; +@synthesize preassembler; +@synthesize preassemblerSelector; +@synthesize name; +@end + +@implementation PKParser (PKParserFactoryAdditions) + +- (id)parse:(NSString *)s { + PKTokenizer *t = self.tokenizer; + if (!t) { + t = [PKTokenizer tokenizer]; + } + t.string = s; + PKAssembly *a = [self completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + if (a.target) { + return a.target; + } else { + return [a pop]; + } +} + + +- (PKTokenizer *)tokenizer { + return [[tokenizer retain] autorelease]; +} + + +- (void)setTokenizer:(PKTokenizer *)t { + if (tokenizer != t) { + [tokenizer autorelease]; + tokenizer = [t retain]; + } +} + +@end diff --git a/src/PKParserFactory.m b/src/PKParserFactory.m new file mode 100644 index 0000000..4f16b59 --- /dev/null +++ b/src/PKParserFactory.m @@ -0,0 +1,979 @@ +// +// PKParserFactory.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf All rights reserved. +// + +#import "PKParserFactory.h" +#import +#import "PKGrammarParser.h" +#import "NSString+ParseKitAdditions.h" +#import "NSArray+ParseKitAdditions.h" + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface PKCollectionParser () +@property (nonatomic, readwrite, retain) NSMutableArray *subparsers; +@end + +@interface PKRepetition () +@property (nonatomic, readwrite, retain) PKParser *subparser; +@end + +@interface PKNegation () +@property (nonatomic, readwrite, retain) PKParser *subparser; +@end + +@interface PKDifference () +@property (nonatomic, readwrite, retain) PKParser *subparser; +@property (nonatomic, readwrite, retain) PKParser *minus; +@end + +@interface PKPattern () +@property (nonatomic, assign) PKTokenType tokenType; +@end + +void PKReleaseSubparserTree(PKParser *p) { + if ([p isKindOfClass:[PKCollectionParser class]]) { + PKCollectionParser *c = (PKCollectionParser *)p; + NSArray *subs = c.subparsers; + if (subs) { + [subs retain]; + c.subparsers = nil; + for (PKParser *s in subs) { + PKReleaseSubparserTree(s); + } + [subs release]; + } + } else if ([p isMemberOfClass:[PKRepetition class]]) { + PKRepetition *r = (PKRepetition *)p; + PKParser *sub = r.subparser; + if (sub) { + [sub retain]; + r.subparser = nil; + PKReleaseSubparserTree(sub); + [sub release]; + } + } else if ([p isMemberOfClass:[PKNegation class]]) { + PKNegation *n = (PKNegation *)p; + PKParser *sub = n.subparser; + if (sub) { + [sub retain]; + n.subparser = nil; + PKReleaseSubparserTree(sub); + [sub release]; + } + } else if ([p isMemberOfClass:[PKDifference class]]) { + PKDifference *d = (PKDifference *)p; + PKParser *sub = d.subparser; + if (sub) { + [sub retain]; + d.subparser = nil; + PKReleaseSubparserTree(sub); + [sub release]; + } + PKParser *m = d.minus; + if (m) { + [m retain]; + d.minus = nil; + PKReleaseSubparserTree(m); + [m release]; + } + } +} + +@interface PKParserFactory () +- (PKTokenizer *)tokenizerForParsingGrammar; +- (BOOL)isAllWhitespace:(NSArray *)toks; +- (id)parserTokensTableFromParsingStatementsInString:(NSString *)s; +- (void)gatherParserClassNamesFromTokens; +- (NSString *)parserClassNameFromTokenArray:(NSArray *)toks; + +- (PKTokenizer *)tokenizerFromGrammarSettings; +- (BOOL)boolForTokenForKey:(NSString *)key; +- (void)setTokenizerState:(PKTokenizerState *)state onTokenizer:(PKTokenizer *)t forTokensForKey:(NSString *)key; +- (void)setFallbackStateOn:(PKTokenizerState *)state withTokenizer:(PKTokenizer *)t forTokensForKey:(NSString *)key; + +- (id)expandParser:(PKParser *)p fromTokenArray:(NSArray *)toks; +- (PKParser *)expandedParserForName:(NSString *)parserName; +- (void)setAssemblerForParser:(PKParser *)p; +- (NSArray *)tokens:(NSArray *)toks byRemovingTokensOfType:(PKTokenType)tt; +- (NSString *)defaultAssemblerSelectorNameForParserName:(NSString *)parserName; +- (NSString *)defaultPreassemblerSelectorNameForParserName:(NSString *)parserName; + +// this is only for unit tests? can it go away? +- (PKSequence *)parserFromExpression:(NSString *)s; + +- (PKAlternation *)zeroOrOne:(PKParser *)p; +- (PKSequence *)oneOrMore:(PKParser *)p; + +- (void)didMatchStatement:(PKAssembly *)a; +- (void)didMatchCallback:(PKAssembly *)a; +- (void)didMatchExpression:(PKAssembly *)a; +- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchIntersection:(PKAssembly *)a; +- (void)didMatchDifference:(PKAssembly *)a; +- (void)didMatchPatternOptions:(PKAssembly *)a; +- (void)didMatchPattern:(PKAssembly *)a; +- (void)didMatchDiscard:(PKAssembly *)a; +- (void)didMatchLiteral:(PKAssembly *)a; +- (void)didMatchVariable:(PKAssembly *)a; +- (void)didMatchConstant:(PKAssembly *)a; +- (void)didMatchDelimitedString:(PKAssembly *)a; +- (void)didMatchNum:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchPlus:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +- (void)didMatchPhraseCardinality:(PKAssembly *)a; +- (void)didMatchCardinality:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchNegation:(PKAssembly *)a; + +@property (nonatomic, retain) PKGrammarParser *grammarParser; +@property (nonatomic, assign) id assembler; +@property (nonatomic, assign) id preassembler; +@property (nonatomic, retain) NSMutableDictionary *parserTokensTable; +@property (nonatomic, retain) NSMutableDictionary *parserClassTable; +@property (nonatomic, retain) NSMutableDictionary *selectorTable; +@property (nonatomic, retain) PKToken *equals; +@property (nonatomic, retain) PKToken *curly; +@property (nonatomic, retain) PKToken *paren; +@end + +@implementation PKParserFactory + ++ (id)factory { + return [[[PKParserFactory alloc] init] autorelease]; +} + + +- (id)init { + if (self = [super init]) { + self.grammarParser = [[[PKGrammarParser alloc] initWithAssembler:self] autorelease]; + self.equals = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"=" floatValue:0.0]; + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.0]; + self.paren = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"(" floatValue:0.0]; + self.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnAll; + } + return self; +} + + +- (void)dealloc { + self.grammarParser = nil; + self.assembler = nil; + self.preassembler = nil; + self.parserTokensTable = nil; + self.parserClassTable = nil; + self.selectorTable = nil; + self.equals = nil; + self.curly = nil; + self.paren = nil; + [super dealloc]; +} + + +- (PKCollectionParser *)exprParser { + return grammarParser.exprParser; +} + + +- (PKParser *)parserFromGrammar:(NSString *)s assembler:(id)a { + return [self parserFromGrammar:s assembler:a preassembler:nil]; +} + + +- (PKParser *)parserFromGrammar:(NSString *)s assembler:(id)a preassembler:(id)pa { + self.assembler = a; + self.preassembler = pa; + self.selectorTable = [NSMutableDictionary dictionary]; + self.parserClassTable = [NSMutableDictionary dictionary]; + self.parserTokensTable = [self parserTokensTableFromParsingStatementsInString:s]; + + PKTokenizer *t = [self tokenizerFromGrammarSettings]; + + [self gatherParserClassNamesFromTokens]; + + PKParser *start = [self expandedParserForName:@"@start"]; + + assembler = nil; + self.selectorTable = nil; + self.parserClassTable = nil; + self.parserTokensTable = nil; + + if (start && [start isKindOfClass:[PKParser class]]) { + start.tokenizer = t; + return start; + } else { + [NSException raise:@"GrammarException" format:@"The provided language grammar was invalid"]; + return nil; + } +} + + +- (PKTokenizer *)tokenizerForParsingGrammar { + PKTokenizer *t = [PKTokenizer tokenizer]; + + t.whitespaceState.reportsWhitespaceTokens = YES; + + // customize tokenizer to find tokenizer customization directives + [t setTokenizerState:t.wordState from:'@' to:'@']; + + // add support for tokenizer directives like @commentState.fallbackState + [t.wordState setWordChars:YES from:'.' to:'.']; + [t.wordState setWordChars:NO from:'-' to:'-']; + + // setup comments + [t setTokenizerState:t.commentState from:'/' to:'/']; + [t.commentState addSingleLineStartMarker:@"//"]; + [t.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + // comment state should fallback to delimit state to match regex delimited strings + t.commentState.fallbackState = t.delimitState; + + // regex delimited strings + [t.delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:[[NSCharacterSet whitespaceCharacterSet] invertedSet]]; + + return t; +} + + +- (BOOL)isAllWhitespace:(NSArray *)toks { + for (PKToken *tok in toks) { + if (PKTokenTypeWhitespace != tok.tokenType) { + return NO; + } + } + return YES; +} + + +- (id)parserTokensTableFromParsingStatementsInString:(NSString *)s { + PKTokenizer *t = [self tokenizerForParsingGrammar]; + t.string = s; + + PKTokenArraySource *src = [[PKTokenArraySource alloc] initWithTokenizer:t delimiter:@";"]; + id target = [NSMutableDictionary dictionary]; // setup the variable lookup table + + while ([src hasMore]) { + NSArray *toks = [src nextTokenArray]; + if (![self isAllWhitespace:toks]) { + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenArray:toks]; + //a.preservesWhitespaceTokens = YES; + a.target = target; + PKAssembly *res = [grammarParser.statementParser completeMatchFor:a]; + target = res.target; + } + } + + [src release]; + + return target; +} + + +- (void)gatherParserClassNamesFromTokens { + isGatheringClasses = YES; + // discover the actual parser class types + for (NSString *parserName in parserTokensTable) { + NSString *className = [self parserClassNameFromTokenArray:[parserTokensTable objectForKey:parserName]]; + NSAssert1([className length], @"Could not build ClassName from token array for parserName: %@", parserName); + [parserClassTable setObject:className forKey:parserName]; + } + isGatheringClasses = NO; +} + + +- (NSString *)parserClassNameFromTokenArray:(NSArray *)toks { + PKAssembly *a = [PKTokenAssembly assemblyWithTokenArray:toks]; + a.target = parserTokensTable; + a = [grammarParser.exprParser completeMatchFor:a]; + PKParser *res = [a pop]; + a.target = nil; + return NSStringFromClass([res class]); +} + + +- (PKTokenizer *)tokenizerFromGrammarSettings { + PKTokenizer *t = [PKTokenizer tokenizer]; + [t.commentState removeSingleLineStartMarker:@"//"]; + [t.commentState removeMultiLineStartMarker:@"/*"]; + + t.whitespaceState.reportsWhitespaceTokens = [self boolForTokenForKey:@"@reportsWhitespaceTokens"]; + t.commentState.reportsCommentTokens = [self boolForTokenForKey:@"@reportsCommentTokens"]; + t.commentState.balancesEOFTerminatedComments = [self boolForTokenForKey:@"balancesEOFTerminatedComments"]; + t.quoteState.balancesEOFTerminatedQuotes = [self boolForTokenForKey:@"@balancesEOFTerminatedQuotes"]; + t.delimitState.balancesEOFTerminatedStrings = [self boolForTokenForKey:@"@balancesEOFTerminatedStrings"]; + t.numberState.allowsTrailingDot = [self boolForTokenForKey:@"@allowsTrailingDot"]; + t.numberState.allowsScientificNotation = [self boolForTokenForKey:@"@allowsScientificNotation"]; + t.numberState.allowsOctalNotation = [self boolForTokenForKey:@"@allowsOctalNotation"]; + t.numberState.allowsHexadecimalNotation = [self boolForTokenForKey:@"@allowsHexadecimalNotation"]; + + [self setTokenizerState:t.wordState onTokenizer:t forTokensForKey:@"@wordState"]; + [self setTokenizerState:t.numberState onTokenizer:t forTokensForKey:@"@numberState"]; + [self setTokenizerState:t.quoteState onTokenizer:t forTokensForKey:@"@quoteState"]; + [self setTokenizerState:t.delimitState onTokenizer:t forTokensForKey:@"@delimitState"]; + [self setTokenizerState:t.symbolState onTokenizer:t forTokensForKey:@"@symbolState"]; + [self setTokenizerState:t.commentState onTokenizer:t forTokensForKey:@"@commentState"]; + [self setTokenizerState:t.whitespaceState onTokenizer:t forTokensForKey:@"@whitespaceState"]; + + [self setFallbackStateOn:t.commentState withTokenizer:t forTokensForKey:@"@commentState.fallbackState"]; + [self setFallbackStateOn:t.delimitState withTokenizer:t forTokensForKey:@"@delimitState.fallbackState"]; + + NSArray *toks = nil; + + // muli-char symbols + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@symbol"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@symbols"]]; + [parserTokensTable removeObjectForKey:@"@symbol"]; + [parserTokensTable removeObjectForKey:@"@symbols"]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + [t.symbolState add:[tok.stringValue stringByTrimmingQuotes]]; + } + } + + // wordChars + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@wordChar"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@wordChars"]]; + [parserTokensTable removeObjectForKey:@"@wordChar"]; + [parserTokensTable removeObjectForKey:@"@wordChars"]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + if ([s length]) { + NSInteger c = [s characterAtIndex:0]; + [t.wordState setWordChars:YES from:c to:c]; + } + } + } + + // whitespaceChars + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@whitespaceChar"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@whitespaceChars"]]; + [parserTokensTable removeObjectForKey:@"@whitespaceChar"]; + [parserTokensTable removeObjectForKey:@"@whitespaceChars"]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + if ([s length]) { + NSInteger c = 0; + if ([s hasPrefix:@"#x"]) { + c = [s integerValue]; + } else { + c = [s characterAtIndex:0]; + } + [t.whitespaceState setWhitespaceChars:YES from:c to:c]; + } + } + } + + // single-line comments + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@singleLineComment"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@singleLineComments"]]; + [parserTokensTable removeObjectForKey:@"@singleLineComment"]; + [parserTokensTable removeObjectForKey:@"@singleLineComments"]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + [t.commentState addSingleLineStartMarker:s]; + } + } + + // multi-line comments + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@multiLineComment"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@multiLineComments"]]; + NSAssert(0 == [toks count] % 2, @"@multiLineComments must be specified as quoted strings in multiples of 2"); + [parserTokensTable removeObjectForKey:@"@multiLineComment"]; + [parserTokensTable removeObjectForKey:@"@multiLineComments"]; + if ([toks count] > 1) { + NSInteger i = 0; + for ( ; i < [toks count] - 1; i++) { + PKToken *startTok = [toks objectAtIndex:i]; + PKToken *endTok = [toks objectAtIndex:++i]; + if (startTok.isQuotedString && endTok.isQuotedString) { + NSString *start = [startTok.stringValue stringByTrimmingQuotes]; + NSString *end = [endTok.stringValue stringByTrimmingQuotes]; + [t.commentState addMultiLineStartMarker:start endMarker:end]; + } + } + } + + // delimited strings + toks = [NSArray arrayWithArray:[parserTokensTable objectForKey:@"@delimitedString"]]; + toks = [toks arrayByAddingObjectsFromArray:[parserTokensTable objectForKey:@"@delimitedStrings"]]; + NSAssert(0 == [toks count] % 3, @"@delimitedString must be specified as quoted strings in multiples of 3"); + [parserTokensTable removeObjectForKey:@"@delimitedString"]; + [parserTokensTable removeObjectForKey:@"@delimitedStrings"]; + if ([toks count] > 1) { + NSInteger i = 0; + for ( ; i < [toks count] - 2; i++) { + PKToken *startTok = [toks objectAtIndex:i]; + PKToken *endTok = [toks objectAtIndex:++i]; + PKToken *charSetTok = [toks objectAtIndex:++i]; + if (startTok.isQuotedString && endTok.isQuotedString) { + NSString *start = [startTok.stringValue stringByTrimmingQuotes]; + NSString *end = [endTok.stringValue stringByTrimmingQuotes]; + NSCharacterSet *charSet = nil; + if (charSetTok.isQuotedString) { + charSet = [NSCharacterSet characterSetWithCharactersInString:[charSetTok.stringValue stringByTrimmingQuotes]]; + } + [t.delimitState addStartMarker:start endMarker:end allowedCharacterSet:charSet]; + } + } + } + + return t; +} + + +- (BOOL)boolForTokenForKey:(NSString *)key { + BOOL result = NO; + NSArray *toks = [parserTokensTable objectForKey:key]; + if ([toks count]) { + PKToken *tok = [toks objectAtIndex:0]; + if (tok.isWord && [tok.stringValue isEqualToString:@"YES"]) { + result = YES; + } + } + [parserTokensTable removeObjectForKey:key]; + return result; +} + + +- (void)setTokenizerState:(PKTokenizerState *)state onTokenizer:(PKTokenizer *)t forTokensForKey:(NSString *)key { + NSArray *toks = [parserTokensTable objectForKey:key]; + for (PKToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + if (1 == [s length]) { + NSInteger c = [s characterAtIndex:0]; + [t setTokenizerState:state from:c to:c]; + } + } + } + [parserTokensTable removeObjectForKey:key]; +} + + +- (void)setFallbackStateOn:(PKTokenizerState *)state withTokenizer:(PKTokenizer *)t forTokensForKey:(NSString *)key { + NSArray *toks = [parserTokensTable objectForKey:key]; + if ([toks count]) { + PKToken *tok = [toks objectAtIndex:0]; + if (tok.isWord) { + PKTokenizerState *fallbackState = [t valueForKey:tok.stringValue]; + if (state != fallbackState) { + state.fallbackState = fallbackState; + } + } + } + [parserTokensTable removeObjectForKey:key]; +} + + +- (PKParser *)expandedParserForName:(NSString *)parserName { + id obj = [parserTokensTable objectForKey:parserName]; + if ([obj isKindOfClass:[PKParser class]]) { + return obj; + } else { + // prevent infinite loops by creating a parser of the correct type first, and putting it in the table + NSString *className = [parserClassTable objectForKey:parserName]; + + PKParser *p = [[NSClassFromString(className) alloc] init]; + [parserTokensTable setObject:p forKey:parserName]; + [p release]; + + p = [self expandParser:p fromTokenArray:obj]; + p.name = parserName; + + [self setAssemblerForParser:p]; + + [parserTokensTable setObject:p forKey:parserName]; + return p; + } +} + + +- (void)setAssemblerForParser:(PKParser *)p { + NSString *parserName = p.name; + NSString *selName = [selectorTable objectForKey:parserName]; + + BOOL setOnAll = (assemblerSettingBehavior & PKParserFactoryAssemblerSettingBehaviorOnAll); + + if (setOnAll) { + // continue + } else { + BOOL setOnExplicit = (assemblerSettingBehavior & PKParserFactoryAssemblerSettingBehaviorOnExplicit); + if (setOnExplicit && selName) { + // continue + } else { + BOOL isTerminal = [p isKindOfClass:[PKTerminal class]]; + if (!isTerminal && !setOnExplicit) return; + + BOOL setOnTerminals = (assemblerSettingBehavior & PKParserFactoryAssemblerSettingBehaviorOnTerminals); + if (setOnTerminals && isTerminal) { + // continue + } else { + return; + } + } + } + + if (!selName) { + selName = [self defaultAssemblerSelectorNameForParserName:parserName]; + } + + if (selName) { + SEL sel = NSSelectorFromString(selName); + if (assembler && [assembler respondsToSelector:sel]) { + [p setAssembler:assembler selector:sel]; + } + if (preassembler && [preassembler respondsToSelector:sel]) { + NSString *selName = [self defaultPreassemblerSelectorNameForParserName:parserName]; + [p setPreassembler:preassembler selector:NSSelectorFromString(selName)]; + } + } +} + + +- (id)expandParser:(PKParser *)p fromTokenArray:(NSArray *)toks { + PKAssembly *a = [PKTokenAssembly assemblyWithTokenArray:toks]; + a.target = parserTokensTable; + a = [grammarParser.exprParser completeMatchFor:a]; + PKParser *res = [a pop]; + if ([p isKindOfClass:[PKCollectionParser class]]) { + PKCollectionParser *cp = (PKCollectionParser *)p; + [cp add:res]; + return cp; + } else { + return res; + } +} + + +// this is just a utility for unit-testing +- (PKSequence *)parserFromExpression:(NSString *)s { + PKTokenizer *t = [self tokenizerForParsingGrammar]; + t.string = s; + PKAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; + a.target = [NSMutableDictionary dictionary]; // setup the variable lookup table + a = [grammarParser.exprParser completeMatchFor:a]; + return [a pop]; +} + + +- (PKAlternation *)zeroOrOne:(PKParser *)p { + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:p]; + return a; +} + + +- (PKSequence *)oneOrMore:(PKParser *)p { + PKSequence *s = [PKSequence sequence]; + [s add:p]; + [s add:[PKRepetition repetitionWithSubparser:p]]; + return s; +} + + +- (void)didMatchStatement:(PKAssembly *)a { + NSArray *toks = [[a objectsAbove:equals] reversedArray]; + [a pop]; // discard '=' tok + + NSString *parserName = nil; + NSString *selName = nil; + id obj = [a pop]; + if ([obj isKindOfClass:[NSString class]]) { // a callback was provided + selName = obj; + parserName = [[a pop] stringValue]; + } else { + parserName = [obj stringValue]; + } + + if (selName) { + NSAssert([selName length], @""); + [selectorTable setObject:selName forKey:parserName]; + } + NSMutableDictionary *d = a.target; + //NSLog(@"parserName: %@", parserName); + NSAssert([toks count], @""); + + // support for multiple @delimitedString = ... tokenizer directives + if ([parserName hasPrefix:@"@"]) { + // remove whitespace toks from tokenizer directives + if (![parserName isEqualToString:@"@start"]) { + toks = [self tokens:toks byRemovingTokensOfType:PKTokenTypeWhitespace]; + } + + NSArray *existingToks = [d objectForKey:parserName]; + if ([existingToks count]) { + toks = [toks arrayByAddingObjectsFromArray:existingToks]; + } + } + + [d setObject:toks forKey:parserName]; +} + + +- (NSArray *)tokens:(NSArray *)toks byRemovingTokensOfType:(PKTokenType)tt { + NSMutableArray *res = [NSMutableArray array]; + for (PKToken *tok in toks) { + if (PKTokenTypeWhitespace != tok.tokenType) { + [res addObject:tok]; + } + } + return res; +} + + +- (NSString *)defaultAssemblerSelectorNameForParserName:(NSString *)parserName { + NSString *prefix = nil; + if ([parserName hasPrefix:@"@"]) { + // parserName = [parserName substringFromIndex:1]; + // prefix = @"didMatch_"; + return nil; + } else { + prefix = @"didMatch"; + } + NSString *s = [NSString stringWithFormat:@"%@%@", [[parserName substringToIndex:1] uppercaseString], [parserName substringFromIndex:1]]; + return [NSString stringWithFormat:@"%@%@:", prefix, s]; +} + + +- (NSString *)defaultPreassemblerSelectorNameForParserName:(NSString *)parserName { + NSString *prefix = nil; + if ([parserName hasPrefix:@"@"]) { + return nil; + } else { + prefix = @"willMatch"; + } + NSString *s = [NSString stringWithFormat:@"%@%@", [[parserName substringToIndex:1] uppercaseString], [parserName substringFromIndex:1]]; + return [NSString stringWithFormat:@"%@%@:", prefix, s]; +} + + +- (void)didMatchCallback:(PKAssembly *)a { + PKToken *selNameTok = [a pop]; + NSString *selName = [NSString stringWithFormat:@"%@:", selNameTok.stringValue]; + [a push:selName]; +} + + +- (void)didMatchExpression:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:paren]; + NSAssert([objs count], @""); + [a pop]; // pop '(' + + if ([objs count] > 1) { + PKSequence *seq = [PKSequence sequence]; + for (id obj in [objs reverseObjectEnumerator]) { + [seq add:obj]; + } + [a push:seq]; + } else if ([objs count]) { + [a push:[objs objectAtIndex:0]]; + } +} + + +- (void)didMatchDifference:(PKAssembly *)a { + PKParser *minus = [a pop]; + PKParser *sub = [a pop]; + NSAssert([minus isKindOfClass:[PKParser class]], @""); + NSAssert([sub isKindOfClass:[PKParser class]], @""); + + [a push:[PKDifference differenceWithSubparser:sub minus:minus]]; +} + + +- (void)didMatchIntersection:(PKAssembly *)a { + PKParser *predicate = [a pop]; + PKParser *sub = [a pop]; + NSAssert([predicate isKindOfClass:[PKParser class]], @""); + NSAssert([sub isKindOfClass:[PKParser class]], @""); + + PKIntersection *inter = [PKIntersection intersection]; + [inter add:sub]; + [inter add:predicate]; + + [a push:inter]; +} + + +- (void)didMatchPatternOptions:(PKAssembly *)a { + PKToken *tok = [a pop]; + NSAssert(tok.isWord, @""); + + NSString *s = tok.stringValue; + NSAssert([s length] > 0, @""); + + PKPatternOptions opts = PKPatternOptionsNone; + if (NSNotFound != [s rangeOfString:@"i"].location) { + opts |= PKPatternOptionsIgnoreCase; + } + if (NSNotFound != [s rangeOfString:@"m"].location) { + opts |= PKPatternOptionsMultiline; + } + if (NSNotFound != [s rangeOfString:@"x"].location) { + opts |= PKPatternOptionsComments; + } + if (NSNotFound != [s rangeOfString:@"s"].location) { + opts |= PKPatternOptionsDotAll; + } + if (NSNotFound != [s rangeOfString:@"w"].location) { + opts |= PKPatternOptionsUnicodeWordBoundaries; + } + + [a push:[NSNumber numberWithInteger:opts]]; +} + + +- (void)didMatchPattern:(PKAssembly *)a { + id obj = [a pop]; // opts (as Number*) or DelimitedString('/', '/') + + PKPatternOptions opts = PKPatternOptionsNone; + if ([obj isKindOfClass:[NSNumber class]]) { + opts = [obj integerValue]; + obj = [a pop]; + } + + NSAssert([obj isMemberOfClass:[PKToken class]], @""); + PKToken *tok = (PKToken *)obj; + NSAssert(tok.isDelimitedString, @""); + + NSString *s = tok.stringValue; + NSAssert([s length] > 2, @""); + + NSAssert([s hasPrefix:@"/"], @""); + NSAssert([s hasSuffix:@"/"], @""); + + NSString *re = [s stringByTrimmingQuotes]; + + PKTerminal *t = [PKPattern patternWithString:re options:opts]; + + [a push:t]; +} + + +- (void)didMatchDiscard:(PKAssembly *)a { + id obj = [a pop]; + if ([obj isKindOfClass:[PKTerminal class]]) { + PKTerminal *t = (PKTerminal *)obj; + [t discard]; + } + [a push:obj]; +} + + +- (void)didMatchLiteral:(PKAssembly *)a { + PKToken *tok = [a pop]; + + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + PKTerminal *t = [PKCaseInsensitiveLiteral literalWithString:s]; + + [a push:t]; +} + + +- (void)didMatchVariable:(PKAssembly *)a { + PKToken *tok = [a pop]; + NSString *parserName = tok.stringValue; + PKParser *p = nil; + if (isGatheringClasses) { + // lookup the actual possible parser. + // if its not there, or still a token array, just spoof it with a sequence + NSMutableDictionary *d = a.target; + p = [d objectForKey:parserName]; + if (![p isKindOfClass:[PKParser parser]]) { + p = [PKSequence sequence]; + } + } else { + if ([parserTokensTable objectForKey:parserName]) { + p = [self expandedParserForName:parserName]; + } + } + [a push:p]; +} + + +- (void)didMatchConstant:(PKAssembly *)a { + PKToken *tok = [a pop]; + NSString *s = tok.stringValue; + id p = nil; + if ([s isEqualToString:@"Word"]) { + p = [PKWord word]; + } else if ([s isEqualToString:@"LowercaseWord"]) { + p = [PKLowercaseWord word]; + } else if ([s isEqualToString:@"UppercaseWord"]) { + p = [PKUppercaseWord word]; + } else if ([s isEqualToString:@"Number"]) { + p = [PKNumber number]; + } else if ([s isEqualToString:@"S"]) { + p = [PKWhitespace whitespace]; + } else if ([s isEqualToString:@"QuotedString"]) { + p = [PKQuotedString quotedString]; + } else if ([s isEqualToString:@"Symbol"]) { + p = [PKSymbol symbol]; + } else if ([s isEqualToString:@"Comment"]) { + p = [PKComment comment]; + } else if ([s isEqualToString:@"Any"]) { + p = [PKAny any]; + } else if ([s isEqualToString:@"Empty"]) { + p = [PKEmpty empty]; + } else if ([s isEqualToString:@"Pattern"]) { + p = tok; + } else if ([s isEqualToString:@"DelimitedString"]) { + p = tok; + } else if ([s isEqualToString:@"YES"] || [s isEqualToString:@"NO"]) { + p = tok; + } else { + [NSException raise:@"Grammar Exception" format: + @"User Grammar referenced a constant parser name (uppercase word) which is not supported: %@. Must be one of: Word, LowercaseWord, UppercaseWord, QuotedString, Number, Symbol, Empty.", s]; + } + + [a push:p]; +} + + +- (void)didMatchDelimitedString:(PKAssembly *)a { + NSArray *toks = [a objectsAbove:paren]; + [a pop]; // discard '(' fence + + NSAssert([toks count] > 0 && [toks count] < 3, @""); + NSString *start = [[[toks lastObject] stringValue] stringByTrimmingQuotes]; + NSString *end = nil; + if ([toks count] > 1) { + end = [[[toks objectAtIndex:0] stringValue] stringByTrimmingQuotes]; + } + + PKTerminal *t = [PKDelimitedString delimitedStringWithStartMarker:start endMarker:end]; + + [a push:t]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchStar:(PKAssembly *)a { + id top = [a pop]; + PKRepetition *rep = [PKRepetition repetitionWithSubparser:top]; + [a push:rep]; +} + + +- (void)didMatchPlus:(PKAssembly *)a { + id top = [a pop]; + [a push:[self oneOrMore:top]]; +} + + +- (void)didMatchQuestion:(PKAssembly *)a { + id top = [a pop]; + [a push:[self zeroOrOne:top]]; +} + + +- (void)didMatchPhraseCardinality:(PKAssembly *)a { + NSRange r = [[a pop] rangeValue]; + PKParser *p = [a pop]; + PKSequence *s = [PKSequence sequence]; + + NSInteger start = r.location; + NSInteger end = r.length; + + NSInteger i = 0; + for ( ; i < start; i++) { + [s add:p]; + } + + for ( ; i < end; i++) { + [s add:[self zeroOrOne:p]]; + } + + [a push:s]; +} + + +- (void)didMatchCardinality:(PKAssembly *)a { + NSArray *toks = [a objectsAbove:self.curly]; + [a pop]; // discard '{' tok + + NSAssert([toks count] > 0, @""); + + PKToken *tok = [toks lastObject]; + CGFloat start = tok.floatValue; + CGFloat end = start; + if ([toks count] > 1) { + tok = [toks objectAtIndex:0]; + end = tok.floatValue; + } + + NSAssert(start <= end, @""); + + NSRange r = NSMakeRange(start, end); + [a push:[NSValue valueWithRange:r]]; +} + + +- (void)didMatchOr:(PKAssembly *)a { + id second = [a pop]; + [a pop]; // pop '|' + id first = [a pop]; + PKAlternation *p = [PKAlternation alternation]; + [p add:first]; + [p add:second]; + [a push:p]; +} + + +- (void)didMatchAnd:(PKAssembly *)a { + NSMutableArray *parsers = [NSMutableArray array]; + while (![a isStackEmpty]) { + id obj = [a pop]; + if ([obj isKindOfClass:[PKParser class]]) { + [parsers addObject:obj]; + } else { + [a push:obj]; + break; + } + } + + if ([parsers count] > 1) { + PKSequence *seq = [PKSequence sequence]; + for (PKParser *p in [parsers reverseObjectEnumerator]) { + [seq add:p]; + } + + [a push:seq]; + } else if (1 == [parsers count]) { + [a push:[parsers objectAtIndex:0]]; + } +} + + +- (void)didMatchNegation:(PKAssembly *)a { + PKParser *p = [a pop]; + [a push:[PKNegation negationWithSubparser:p]]; +} + +@synthesize grammarParser; +@synthesize assembler; +@synthesize preassembler; +@synthesize parserTokensTable; +@synthesize parserClassTable; +@synthesize selectorTable; +@synthesize equals; +@synthesize curly; +@synthesize paren; +@synthesize assemblerSettingBehavior; +@end diff --git a/src/PKPattern.m b/src/PKPattern.m new file mode 100644 index 0000000..e2632c7 --- /dev/null +++ b/src/PKPattern.m @@ -0,0 +1,51 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import "RegexKitLite.h" + +@implementation PKPattern + ++ (id)patternWithString:(NSString *)s { + return [self patternWithString:s options:PKPatternOptionsNone]; +} + + ++ (id)patternWithString:(NSString *)s options:(PKPatternOptions)opts { + return [[[self alloc] initWithString:s options:opts] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + return [self initWithString:s options:PKPatternOptionsNone]; +} + + +- (id)initWithString:(NSString *)s options:(PKPatternOptions)opts { + if (self = [super initWithString:s]) { + options = opts; + } + return self; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + + NSRange r = NSMakeRange(0, [tok.stringValue length]); + + return NSEqualRanges(r, [tok.stringValue rangeOfRegex:self.string options:(uint32_t)options inRange:r capture:0 error:nil]); +} + +@end diff --git a/src/PKQuoteState.m b/src/PKQuoteState.m new file mode 100644 index 0000000..3bb8427 --- /dev/null +++ b/src/PKQuoteState.m @@ -0,0 +1,62 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation PKQuoteState + +- (void)dealloc { + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + [self append:cin]; + PKUniChar c; + do { + c = [r read]; + if (PKEOF == c) { + c = cin; + if (balancesEOFTerminatedQuotes) { + [self append:c]; + } + } else { + [self append:c]; + } + + } while (c != cin); + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeQuotedString stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; +} + +@synthesize balancesEOFTerminatedQuotes; +@end diff --git a/src/PKQuotedString.m b/src/PKQuotedString.m new file mode 100644 index 0000000..13ab559 --- /dev/null +++ b/src/PKQuotedString.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKQuotedString + ++ (id)quotedString { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isQuotedString; +} + +@end diff --git a/src/PKReader.m b/src/PKReader.m new file mode 100644 index 0000000..75b83c7 --- /dev/null +++ b/src/PKReader.m @@ -0,0 +1,75 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@implementation PKReader + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + if (self = [super init]) { + self.string = s; + } + return self; +} + + +- (void)dealloc { + self.string = nil; + [super dealloc]; +} + + +- (NSString *)string { + return [[string retain] autorelease]; +} + + +- (void)setString:(NSString *)s { + if (string != s) { + [string autorelease]; + string = [s copy]; + length = [string length]; + } + // reset cursor + offset = 0; +} + + +- (PKUniChar)read { + if (0 == length || offset > length - 1) { + return PKEOF; + } + return [string characterAtIndex:offset++]; +} + + +- (void)unread { + offset = (0 == offset) ? 0 : offset - 1; +} + + +- (void)unread:(NSUInteger)count { + NSUInteger i = 0; + for ( ; i < count; i++) { + [self unread]; + } +} + +@synthesize offset; +@end diff --git a/src/PKRepetition.m b/src/PKRepetition.m new file mode 100644 index 0000000..d4e8fba --- /dev/null +++ b/src/PKRepetition.m @@ -0,0 +1,77 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +@end + +@interface PKRepetition () +@property (nonatomic, readwrite, retain) PKParser *subparser; +@end + +@implementation PKRepetition + ++ (id)repetitionWithSubparser:(PKParser *)p { + return [[[self alloc] initWithSubparser:p] autorelease]; +} + + +- (id)init { + return [self initWithSubparser:nil]; +} + + +- (id)initWithSubparser:(PKParser *)p { + //NSParameterAssert(p); + if (self = [super init]) { + self.subparser = p; + } + return self; +} + + +- (void)dealloc { + self.subparser = nil; + [super dealloc]; +} + + +- (PKParser *)parserNamed:(NSString *)s { + if ([name isEqualToString:s]) { + return self; + } else { + return [subparser parserNamed:s]; + } +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + //NSMutableSet *outAssemblies = [[[NSMutableSet alloc] initWithSet:inAssemblies copyItems:YES] autorelease]; + NSMutableSet *outAssemblies = [[inAssemblies mutableCopy] autorelease]; + + NSSet *s = inAssemblies; + while ([s count]) { + s = [subparser matchAndAssemble:s]; + [outAssemblies unionSet:s]; + } + + return outAssemblies; +} + +@synthesize subparser; +@end diff --git a/src/PKSequence.m b/src/PKSequence.m new file mode 100644 index 0000000..7ac6c1e --- /dev/null +++ b/src/PKSequence.m @@ -0,0 +1,56 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +@end + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; +@end + +@implementation PKSequence + ++ (id)sequence { + return [self sequenceWithSubparsers:nil]; +} + + ++ (id)sequenceWithSubparsers:(PKParser *)p1, ... { + va_list vargs; + va_start(vargs, p1); + PKSequence *seq = [self collectionParserWithFirst:p1 rest:vargs]; + va_end(vargs); + return seq; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSSet *outAssemblies = inAssemblies; + + for (PKParser *p in subparsers) { + outAssemblies = [p matchAndAssemble:outAssemblies]; + if (![outAssemblies count]) { + break; + } + } + + return outAssemblies; +} + +@end diff --git a/src/PKSingleLineCommentState.m b/src/PKSingleLineCommentState.m new file mode 100644 index 0000000..73fc32e --- /dev/null +++ b/src/PKSingleLineCommentState.m @@ -0,0 +1,107 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (void)appendString:(NSString *)s; +- (NSString *)bufferedString; +@end + +@interface PKSingleLineCommentState () +- (void)addStartMarker:(NSString *)start; +- (void)removeStartMarker:(NSString *)start; +@property (nonatomic, retain) NSMutableArray *startMarkers; +@property (nonatomic, retain) NSString *currentStartMarker; +@end + +@implementation PKSingleLineCommentState + +- (id)init { + if (self = [super init]) { + self.startMarkers = [NSMutableArray array]; + } + return self; +} + + +- (void)dealloc { + self.startMarkers = nil; + self.currentStartMarker = nil; + [super dealloc]; +} + + +- (void)addStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [startMarkers addObject:start]; +} + + +- (void)removeStartMarker:(NSString *)start { + NSParameterAssert([start length]); + [startMarkers removeObject:start]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + BOOL reportTokens = t.commentState.reportsCommentTokens; + if (reportTokens) { + [self resetWithReader:r]; + [self appendString:currentStartMarker]; + } + + PKUniChar c; + while (1) { + c = [r read]; + if ('\n' == c || '\r' == c || PKEOF == c) { + break; + } + if (reportTokens) { + [self append:c]; + } + } + + if (PKEOF != c) { + [r unread]; + } + + self.currentStartMarker = nil; + + if (reportTokens) { + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeComment stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; + } else { + return [t nextToken]; + } +} + +@synthesize startMarkers; +@synthesize currentStartMarker; +@end diff --git a/src/PKSpecificChar.m b/src/PKSpecificChar.m new file mode 100644 index 0000000..c4baa94 --- /dev/null +++ b/src/PKSpecificChar.m @@ -0,0 +1,38 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKSpecificChar + ++ (id)specificCharWithChar:(PKUniChar)c { + return [[[self alloc] initWithSpecificChar:c] autorelease]; +} + + +- (id)initWithSpecificChar:(PKUniChar)c { + self = [super initWithString:[NSString stringWithFormat:@"%C", c]]; + if (self) { + } + return self; +} + + +- (BOOL)qualifies:(id)obj { + PKUniChar c = [obj intValue]; + return c == [string characterAtIndex:0]; +} + +@end diff --git a/src/PKSymbol.m b/src/PKSymbol.m new file mode 100644 index 0000000..acd340f --- /dev/null +++ b/src/PKSymbol.m @@ -0,0 +1,79 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKSymbol () +@property (nonatomic, retain) PKToken *symbol; +@end + +@implementation PKSymbol + ++ (id)symbol { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)symbolWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + if ([s length]) { + self.symbol = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:s floatValue:0.0]; + } + } + return self; +} + + +- (void)dealloc { + self.symbol = nil; + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + if (symbol) { + return [symbol isEqual:obj]; + } else { + PKToken *tok = (PKToken *)obj; + return tok.isSymbol; + } +} + + +- (NSString *)description { + NSString *className = [NSStringFromClass([self class]) substringFromIndex:2]; + if ([name length]) { + if (symbol) { + return [NSString stringWithFormat:@"%@ (%@) %@", className, name, symbol.stringValue]; + } else { + return [NSString stringWithFormat:@"%@ (%@)", className, name]; + } + } else { + if (symbol) { + return [NSString stringWithFormat:@"%@ %@", className, symbol.stringValue]; + } else { + return [NSString stringWithFormat:@"%@", className]; + } + } +} + +@synthesize symbol; +@end diff --git a/src/PKSymbolNode.m b/src/PKSymbolNode.m new file mode 100644 index 0000000..a3d897a --- /dev/null +++ b/src/PKSymbolNode.m @@ -0,0 +1,82 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKSymbolNode () +@property (nonatomic, readwrite, retain) NSString *ancestry; +@property (nonatomic, assign) PKSymbolNode *parent; // this must be 'assign' to avoid retain loop leak +@property (nonatomic, retain) NSMutableDictionary *children; +@property (nonatomic) PKUniChar character; +@property (nonatomic, retain) NSString *string; + +- (void)determineAncestry; +@end + +@implementation PKSymbolNode + +- (id)initWithParent:(PKSymbolNode *)p character:(PKUniChar)c { + if (self = [super init]) { + self.parent = p; + self.character = c; + self.children = [NSMutableDictionary dictionary]; + + // this private property is an optimization. + // cache the NSString for the char to prevent it being constantly recreated in -determinAncestry + self.string = [NSString stringWithFormat:@"%C", character]; + + [self determineAncestry]; + } + return self; +} + + +- (void)dealloc { + parent = nil; // makes clang static analyzer happy + self.ancestry = nil; + self.string = nil; + self.children = nil; + [super dealloc]; +} + + +- (void)determineAncestry { + if (PKEOF == parent.character) { // optimization for sinlge-char symbol (parent is symbol root node) + self.ancestry = string; + } else { + NSMutableString *result = [NSMutableString string]; + + PKSymbolNode *n = self; + while (PKEOF != n.character) { + [result insertString:n.string atIndex:0]; + n = n.parent; + } + + //self.ancestry = [[result copy] autorelease]; // assign an immutable copy + self.ancestry = result; // optimization + } +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", self.ancestry]; +} + +@synthesize ancestry; +@synthesize parent; +@synthesize character; +@synthesize string; +@synthesize children; +@end diff --git a/src/PKSymbolRootNode.m b/src/PKSymbolRootNode.m new file mode 100644 index 0000000..ac361c5 --- /dev/null +++ b/src/PKSymbolRootNode.m @@ -0,0 +1,153 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKSymbolNode () +@property (nonatomic, retain) NSMutableDictionary *children; +@end + +@interface PKSymbolRootNode () +- (void)addWithFirst:(PKUniChar)c rest:(NSString *)s parent:(PKSymbolNode *)p; +- (void)removeWithFirst:(PKUniChar)c rest:(NSString *)s parent:(PKSymbolNode *)p; +- (NSString *)nextWithFirst:(PKUniChar)c rest:(PKReader *)r parent:(PKSymbolNode *)p; +@end + +@implementation PKSymbolRootNode + +- (id)init { + self = [super initWithParent:nil character:PKEOF]; + if (self) { + + } + return self; +} + + +- (void)add:(NSString *)s { + NSParameterAssert(s); + if ([s length] < 2) return; + + [self addWithFirst:[s characterAtIndex:0] rest:[s substringFromIndex:1] parent:self]; +} + + +- (void)remove:(NSString *)s { + NSParameterAssert(s); + if ([s length] < 2) return; + + [self removeWithFirst:[s characterAtIndex:0] rest:[s substringFromIndex:1] parent:self]; +} + + +- (void)addWithFirst:(PKUniChar)c rest:(NSString *)s parent:(PKSymbolNode *)p { + NSParameterAssert(p); + NSNumber *key = [NSNumber numberWithInteger:c]; + PKSymbolNode *child = [p.children objectForKey:key]; + if (!child) { + child = [[PKSymbolNode alloc] initWithParent:p character:c]; + [p.children setObject:child forKey:key]; + [child release]; + } + + NSString *rest = nil; + + if (0 == [s length]) { + return; + } else if ([s length] > 1) { + rest = [s substringFromIndex:1]; + } + + [self addWithFirst:[s characterAtIndex:0] rest:rest parent:child]; +} + + +- (void)removeWithFirst:(PKUniChar)c rest:(NSString *)s parent:(PKSymbolNode *)p { + NSParameterAssert(p); + NSNumber *key = [NSNumber numberWithInteger:c]; + PKSymbolNode *child = [p.children objectForKey:key]; + if (child) { + NSString *rest = nil; + + if (0 == [s length]) { + return; + } else if ([s length] > 1) { + rest = [s substringFromIndex:1]; + [self removeWithFirst:[s characterAtIndex:0] rest:rest parent:child]; + } + + [p.children removeObjectForKey:key]; + } +} + + +- (NSString *)nextSymbol:(PKReader *)r startingWith:(PKUniChar)cin { + NSParameterAssert(r); + return [self nextWithFirst:cin rest:r parent:self]; +} + + +- (NSString *)nextWithFirst:(PKUniChar)c rest:(PKReader *)r parent:(PKSymbolNode *)p { + NSParameterAssert(p); + NSString *result = [NSString stringWithFormat:@"%C", c]; + + // this also works. +// NSString *result = [[[NSString alloc] initWithCharacters:(const unichar *)&c length:1] autorelease]; + + // none of these work. + //NSString *result = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSUTF8StringEncoding] autorelease]; + +// NSLog(@"c: %d", c); +// NSLog(@"string for c: %@", result); +// NSString *chars = [[[NSString alloc] initWithCharacters:(const unichar *)&c length:1] autorelease]; +// NSString *utfs = [[[NSString alloc] initWithUTF8String:(const char *)&c] autorelease]; +// NSString *utf8 = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSUTF8StringEncoding] autorelease]; +// NSString *utf16 = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSUTF16StringEncoding] autorelease]; +// NSString *ascii = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSASCIIStringEncoding] autorelease]; +// NSString *iso = [[[NSString alloc] initWithBytes:&c length:1 encoding:NSISOLatin1StringEncoding] autorelease]; +// +// NSLog(@"chars: '%@'", chars); +// NSLog(@"utfs: '%@'", utfs); +// NSLog(@"utf8: '%@'", utf8); +// NSLog(@"utf16: '%@'", utf16); +// NSLog(@"ascii: '%@'", ascii); +// NSLog(@"iso: '%@'", iso); + + NSNumber *key = [NSNumber numberWithInteger:c]; + PKSymbolNode *child = [p.children objectForKey:key]; + + if (!child) { + if (p == self) { + return result; + } else { + [r unread]; + return @""; + } + } + + c = [r read]; + if (PKEOF == c) { + return result; + } + + return [result stringByAppendingString:[self nextWithFirst:c rest:r parent:child]]; +} + + +- (NSString *)description { + return @""; +} + +@end diff --git a/src/PKSymbolState.m b/src/PKSymbolState.m new file mode 100644 index 0000000..dfe75d4 --- /dev/null +++ b/src/PKSymbolState.m @@ -0,0 +1,113 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; +@end + +@interface PKSymbolState () +- (PKToken *)symbolTokenWith:(PKUniChar)cin; +- (PKToken *)symbolTokenWithSymbol:(NSString *)s; + +@property (nonatomic, retain) PKSymbolRootNode *rootNode; +@property (nonatomic, retain) NSMutableArray *addedSymbols; +@end + +@implementation PKSymbolState + +- (id)init { + if (self = [super init]) { + self.rootNode = [[[PKSymbolRootNode alloc] init] autorelease]; + self.addedSymbols = [NSMutableArray array]; + } + return self; +} + + +- (void)dealloc { + self.rootNode = nil; + self.addedSymbols = nil; + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + NSString *symbol = [rootNode nextSymbol:r startingWith:cin]; + NSUInteger len = [symbol length]; + + while (len > 1) { + if ([addedSymbols containsObject:symbol]) { + return [self symbolTokenWithSymbol:symbol]; + } + + symbol = [symbol substringToIndex:[symbol length] - 1]; + len = [symbol length]; + [r unread:1]; + } + + if (1 == len) { + return [self symbolTokenWith:cin]; + } else { + PKTokenizerState *state = [self nextTokenizerStateFor:cin tokenizer:t]; + if (!state || state == self) { + return [self symbolTokenWith:cin]; + } else { + return [state nextTokenFromReader:r startingWith:cin tokenizer:t]; + } + } +} + + +- (void)add:(NSString *)s { + NSParameterAssert(s); + [rootNode add:s]; + [addedSymbols addObject:s]; +} + + +- (void)remove:(NSString *)s { + NSParameterAssert(s); + [rootNode remove:s]; + [addedSymbols removeObject:s]; +} + + +- (PKToken *)symbolTokenWith:(PKUniChar)cin { + return [self symbolTokenWithSymbol:[NSString stringWithFormat:@"%C", cin]]; +} + + +- (PKToken *)symbolTokenWithSymbol:(NSString *)s { + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:s floatValue:0.0]; + tok.offset = offset; + return tok; +} + +@synthesize rootNode; +@synthesize addedSymbols; +@end diff --git a/src/PKTerminal.m b/src/PKTerminal.m new file mode 100644 index 0000000..f214521 --- /dev/null +++ b/src/PKTerminal.m @@ -0,0 +1,101 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import + +@interface PKAssembly () +- (id)peek; +- (id)next; +- (BOOL)hasMore; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@end + +@interface PKTerminal () +- (PKAssembly *)matchOneAssembly:(PKAssembly *)inAssembly; +- (BOOL)qualifies:(id)obj; + +@property (nonatomic, readwrite, copy) NSString *string; +@end + +@implementation PKTerminal + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + if (self = [super init]) { + self.string = s; + } + return self; +} + + +- (void)dealloc { + self.string = nil; + [super dealloc]; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSMutableSet *outAssemblies = [NSMutableSet set]; + + for (PKAssembly *a in inAssemblies) { + PKAssembly *b = [self matchOneAssembly:a]; + if (b) { + [outAssemblies addObject:b]; + } + } + + return outAssemblies; +} + + +- (PKAssembly *)matchOneAssembly:(PKAssembly *)inAssembly { + NSParameterAssert(inAssembly); + if (![inAssembly hasMore]) { + return nil; + } + + PKAssembly *outAssembly = nil; + + if ([self qualifies:[inAssembly peek]]) { + outAssembly = [[inAssembly copy] autorelease]; + id obj = [outAssembly next]; + if (!discardFlag) { + [outAssembly push:obj]; + } + } + + return outAssembly; +} + + +- (BOOL)qualifies:(id)obj { + NSAssert1(0, @"-[PKTerminal %s] must be overriden", _cmd); + return NO; +} + + +- (PKTerminal *)discard { + discardFlag = YES; + return self; +} + +@synthesize string; +@end diff --git a/src/PKToken.m b/src/PKToken.m new file mode 100644 index 0000000..69662be --- /dev/null +++ b/src/PKToken.m @@ -0,0 +1,239 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface PKTokenEOF : PKToken {} ++ (PKTokenEOF *)instance; +@end + +@implementation PKTokenEOF + +static PKTokenEOF *EOFToken = nil; + ++ (PKTokenEOF *)instance { + @synchronized(self) { + if (!EOFToken) { + [[self alloc] init]; // assignment not done here + } + } + return EOFToken; +} + + ++ (id)allocWithZone:(NSZone *)zone { + @synchronized(self) { + if (!EOFToken) { + EOFToken = [super allocWithZone:zone]; + return EOFToken; // assignment and return on first allocation + } + } + return nil; //on subsequent allocation attempts return nil +} + + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + + +- (id)retain { + return self; +} + + +- (void)release { + // do nothing +} + + +- (id)autorelease { + return self; +} + + +- (NSUInteger)retainCount { + return UINT_MAX; // denotes an object that cannot be released +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", self]; +} + + +- (NSString *)debugDescription { + return [self description]; +} + + +- (NSUInteger)offset { + return -1; +} + +@end + +@interface PKToken () +- (BOOL)isEqual:(id)obj ignoringCase:(BOOL)ignoringCase; + +@property (nonatomic, readwrite, getter=isNumber) BOOL number; +@property (nonatomic, readwrite, getter=isQuotedString) BOOL quotedString; +@property (nonatomic, readwrite, getter=isSymbol) BOOL symbol; +@property (nonatomic, readwrite, getter=isWord) BOOL word; +@property (nonatomic, readwrite, getter=isWhitespace) BOOL whitespace; +@property (nonatomic, readwrite, getter=isComment) BOOL comment; +@property (nonatomic, readwrite, getter=isDelimitedString) BOOL delimitedString; + +@property (nonatomic, readwrite) CGFloat floatValue; +@property (nonatomic, readwrite, copy) NSString *stringValue; +@property (nonatomic, readwrite) PKTokenType tokenType; +@property (nonatomic, readwrite, copy) id value; + +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@implementation PKToken + ++ (PKToken *)EOFToken { + return [PKTokenEOF instance]; +} + + ++ (id)tokenWithTokenType:(PKTokenType)t stringValue:(NSString *)s floatValue:(CGFloat)n { + return [[[self alloc] initWithTokenType:t stringValue:s floatValue:n] autorelease]; +} + + +// designated initializer +- (id)initWithTokenType:(PKTokenType)t stringValue:(NSString *)s floatValue:(CGFloat)n { + //NSParameterAssert(s); + if (self = [super init]) { + self.tokenType = t; + self.stringValue = s; + self.floatValue = n; + + self.number = (PKTokenTypeNumber == t); + self.quotedString = (PKTokenTypeQuotedString == t); + self.symbol = (PKTokenTypeSymbol == t); + self.word = (PKTokenTypeWord == t); + self.whitespace = (PKTokenTypeWhitespace == t); + self.comment = (PKTokenTypeComment == t); + self.delimitedString = (PKTokenTypeDelimitedString == t); + } + return self; +} + + +- (void)dealloc { + self.stringValue = nil; + self.value = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + return [self retain]; // tokens are immutable +} + + +- (NSUInteger)hash { + return [stringValue hash]; +} + + +- (BOOL)isEqual:(id)obj { + return [self isEqual:obj ignoringCase:NO]; +} + + +- (BOOL)isEqualIgnoringCase:(id)obj { + return [self isEqual:obj ignoringCase:YES]; +} + + +- (BOOL)isEqual:(id)obj ignoringCase:(BOOL)ignoringCase { + if (![obj isMemberOfClass:[PKToken class]]) { + return NO; + } + + PKToken *tok = (PKToken *)obj; + if (tokenType != tok.tokenType) { + return NO; + } + + if (self.isNumber) { + return floatValue == tok.floatValue; + } else { + if (ignoringCase) { + return (NSOrderedSame == [stringValue caseInsensitiveCompare:tok.stringValue]); + } else { + return [stringValue isEqualToString:tok.stringValue]; + } + } +} + + +- (id)value { + if (!value) { + id v = nil; + if (self.isNumber) { + v = [NSNumber numberWithFloat:floatValue]; + } else { + v = stringValue; + } + self.value = v; + } + return value; +} + + +- (NSString *)debugDescription { + NSString *typeString = nil; + if (self.isNumber) { + typeString = @"Number"; + } else if (self.isQuotedString) { + typeString = @"Quoted String"; + } else if (self.isSymbol) { + typeString = @"Symbol"; + } else if (self.isWord) { + typeString = @"Word"; + } else if (self.isWhitespace) { + typeString = @"Whitespace"; + } else if (self.isComment) { + typeString = @"Comment"; + } else if (self.isDelimitedString) { + typeString = @"Delimited String"; + } + return [NSString stringWithFormat:@"<%@ %C%@%C>", typeString, 0x00AB, self.value, 0x00BB]; +} + + +- (NSString *)description { + return stringValue; +} + +@synthesize number; +@synthesize quotedString; +@synthesize symbol; +@synthesize word; +@synthesize whitespace; +@synthesize comment; +@synthesize delimitedString; +@synthesize floatValue; +@synthesize stringValue; +@synthesize tokenType; +@synthesize value; +@synthesize offset; +@end diff --git a/src/PKTokenArraySource.m b/src/PKTokenArraySource.m new file mode 100644 index 0000000..20e1603 --- /dev/null +++ b/src/PKTokenArraySource.m @@ -0,0 +1,85 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import + +@interface PKTokenArraySource () +@property (nonatomic, retain) PKTokenizer *tokenizer; +@property (nonatomic, retain) NSString *delimiter; +@property (nonatomic, retain) PKToken *nextToken; +@end + +@implementation PKTokenArraySource + +- (id)init { + return [self initWithTokenizer:nil delimiter:nil]; +} + + +- (id)initWithTokenizer:(PKTokenizer *)t delimiter:(NSString *)s { + NSParameterAssert(t); + NSParameterAssert(s); + if (self = [super init]) { + self.tokenizer = t; + self.delimiter = s; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.delimiter = nil; + self.nextToken = nil; + [super dealloc]; +} + + +- (BOOL)hasMore { + if (!nextToken) { + self.nextToken = [tokenizer nextToken]; + } + + return ([PKToken EOFToken] != nextToken); +} + + +- (NSArray *)nextTokenArray { + if (![self hasMore]) { + return nil; + } + + NSMutableArray *res = [NSMutableArray arrayWithObject:nextToken]; + self.nextToken = nil; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + while ((tok = [tokenizer nextToken]) != eof) { + if ([tok.stringValue isEqualToString:delimiter]) { + break; // discard delimiter tok + } + [res addObject:tok]; + } + + //return [[res copy] autorelease]; + return res; // optimization +} + +@synthesize tokenizer; +@synthesize delimiter; +@synthesize nextToken; +@end diff --git a/src/PKTokenAssembly.m b/src/PKTokenAssembly.m new file mode 100644 index 0000000..70185c7 --- /dev/null +++ b/src/PKTokenAssembly.m @@ -0,0 +1,204 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import + +@interface PKTokenAssembly () +- (id)initWithString:(NSString *)s tokenzier:(PKTokenizer *)t tokenArray:(NSArray *)a; +- (void)tokenize; +- (NSString *)objectsFrom:(PKUniChar)start to:(PKUniChar)end separatedBy:(NSString *)delimiter; + +@property (nonatomic, retain) PKTokenizer *tokenizer; +@property (nonatomic, copy) NSArray *tokens; +@end + +@implementation PKTokenAssembly + ++ (id)assemblyWithTokenizer:(PKTokenizer *)t { + return [[[self alloc] initWithTokenzier:t] autorelease]; +} + + +- (id)initWithTokenzier:(PKTokenizer *)t { + return [self initWithString:t.string tokenzier:t tokenArray:nil]; +} + + ++ (id)assemblyWithTokenArray:(NSArray *)a { + return [[[self alloc] initWithTokenArray:a] autorelease]; +} + + +- (id)initWithTokenArray:(NSArray *)a { + return [self initWithString:[a componentsJoinedByString:@""] tokenzier:nil tokenArray:a]; +} + + +- (id)initWithString:(NSString *)s { + return [self initWithTokenzier:[[[PKTokenizer alloc] initWithString:s] autorelease]]; +} + + +// designated initializer. this method is private and should not be called from other classes +- (id)initWithString:(NSString *)s tokenzier:(PKTokenizer *)t tokenArray:(NSArray *)a { + self = [super initWithString:s]; + if (self) { + if (t) { + self.tokenizer = t; + } else { + self.tokens = a; + } + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.tokens = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKTokenAssembly *a = (PKTokenAssembly *)[super copyWithZone:zone]; + a->tokenizer = nil; // optimization + if (tokens) { + a->tokens = [tokens copyWithZone:zone]; + } else { + a->tokens = nil; + } + + a->preservesWhitespaceTokens = preservesWhitespaceTokens; + return a; +} + + +- (NSArray *)tokens { + if (!tokens) { + [self tokenize]; + } + return tokens; +} + + +- (id)peek { + PKToken *tok = nil; + NSArray *toks = self.tokens; + + while (1) { + if (index >= [toks count]) { + tok = nil; + break; + } + + tok = [toks objectAtIndex:index]; + if (!preservesWhitespaceTokens) { + break; + } + if (PKTokenTypeWhitespace == tok.tokenType) { + [self push:tok]; + index++; + } else { + break; + } + } + + return tok; +} + + +- (id)next { + id tok = [self peek]; + if (tok) { + index++; + } + return tok; +} + + +- (BOOL)hasMore { + return (index < [self.tokens count]); +} + + +- (NSUInteger)length { + return [self.tokens count]; +} + + +- (NSUInteger)objectsConsumed { + return index; +} + + +- (NSUInteger)objectsRemaining { + return ([self.tokens count] - index); +} + + +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter { + NSParameterAssert(delimiter); + return [self objectsFrom:0 to:self.objectsConsumed separatedBy:delimiter]; +} + + +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter { + NSParameterAssert(delimiter); + return [self objectsFrom:self.objectsConsumed to:[self length] separatedBy:delimiter]; +} + + +#pragma mark - +#pragma mark Private + +- (void)tokenize { + if (!tokenizer) { + self.tokenizer = [PKTokenizer tokenizerWithString:string]; + } + + NSMutableArray *a = [NSMutableArray array]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + while ((tok = [tokenizer nextToken]) != eof) { + [a addObject:tok]; + } + + self.tokens = a; +} + + +- (NSString *)objectsFrom:(PKUniChar)start to:(PKUniChar)end separatedBy:(NSString *)delimiter { + NSMutableString *s = [NSMutableString string]; + NSArray *toks = self.tokens; + + NSInteger i = start; + for ( ; i < end; i++) { + PKToken *tok = [toks objectAtIndex:i]; + [s appendString:tok.stringValue]; + if (end - 1 != i) { + [s appendString:delimiter]; + } + } + + return [[s copy] autorelease]; +} + +@synthesize tokenizer; +@synthesize tokens; +@synthesize preservesWhitespaceTokens; +@end diff --git a/src/PKTokenizer.m b/src/PKTokenizer.m new file mode 100644 index 0000000..a24722c --- /dev/null +++ b/src/PKTokenizer.m @@ -0,0 +1,239 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +#define STATE_COUNT 256 + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizer () +- (PKTokenizerState *)tokenizerStateFor:(PKUniChar)c; +- (PKTokenizerState *)defaultTokenizerStateFor:(PKUniChar)c; +@property (nonatomic, retain) PKReader *reader; +@property (nonatomic, retain) NSMutableArray *tokenizerStates; +@end + +@implementation PKTokenizer + ++ (id)tokenizer { + return [self tokenizerWithString:nil]; +} + + ++ (id)tokenizerWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)init { + return [self initWithString:nil]; +} + + +- (id)initWithString:(NSString *)s { + if (self = [super init]) { + self.string = s; + self.reader = [[[PKReader alloc] init] autorelease]; + + self.numberState = [[[PKNumberState alloc] init] autorelease]; + self.quoteState = [[[PKQuoteState alloc] init] autorelease]; + self.commentState = [[[PKCommentState alloc] init] autorelease]; + self.symbolState = [[[PKSymbolState alloc] init] autorelease]; + self.whitespaceState = [[[PKWhitespaceState alloc] init] autorelease]; + self.wordState = [[[PKWordState alloc] init] autorelease]; + self.delimitState = [[[PKDelimitState alloc] init] autorelease]; + + self.tokenizerStates = [NSMutableArray arrayWithCapacity:STATE_COUNT]; + + NSInteger i = 0; + for ( ; i < STATE_COUNT; i++) { + [tokenizerStates addObject:[self defaultTokenizerStateFor:i]]; + } + + [symbolState add:@"<="]; + [symbolState add:@">="]; + [symbolState add:@"!="]; + [symbolState add:@"=="]; + + [commentState addSingleLineStartMarker:@"//"]; + [commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + [self setTokenizerState:commentState from:'/' to:'/']; + } + return self; +} + + +- (void)dealloc { + self.string = nil; + self.reader = nil; + self.tokenizerStates = nil; + self.numberState = nil; + self.quoteState = nil; + self.commentState = nil; + self.symbolState = nil; + self.whitespaceState = nil; + self.wordState = nil; + self.delimitState = nil; + [super dealloc]; +} + + +- (PKToken *)nextToken { + PKUniChar c = [reader read]; + + PKToken *result = nil; + + if (PKEOF == c) { + result = [PKToken EOFToken]; + } else { + PKTokenizerState *state = [self tokenizerStateFor:c]; + if (state) { + result = [state nextTokenFromReader:reader startingWith:c tokenizer:self]; + } else { + result = [PKToken EOFToken]; + } + } + + return result; +} + + +#ifdef TARGET_OS_SNOW_LEOPARD +- (void)enumerateTokensUsingBlock:(void (^)(PKToken *tok, BOOL *stop))block { + PKToken *eof = [PKToken EOFToken]; + + PKToken *tok = nil; + BOOL stop = NO; + + while ((tok = [self nextToken]) != eof) { + block(tok, &stop); + if (stop) break; + } +} +#endif + + +- (void)setTokenizerState:(PKTokenizerState *)state from:(PKUniChar)start to:(PKUniChar)end { + NSParameterAssert(state); + + NSInteger i = start; + for ( ; i <= end; i++) { + [tokenizerStates replaceObjectAtIndex:i withObject:state]; + } +} + + +- (void)setReader:(PKReader *)r { + if (reader != r) { + [reader release]; + reader = [r retain]; + reader.string = string; + } +} + + +- (void)setString:(NSString *)s { + if (string != s) { + [string release]; + string = [s retain]; + } + reader.string = string; +} + + +#pragma mark - + +- (PKTokenizerState *)tokenizerStateFor:(PKUniChar)c { + if (c < 0 || c > 255) { + // customization above 255 is not supported, so fetch default. + return [self defaultTokenizerStateFor:c]; + } else { + // customization below 255 is supported, so be sure to get the (possibly) customized state from `tokenizerStates` + return [tokenizerStates objectAtIndex:c]; + } +} + +- (PKTokenizerState *)defaultTokenizerStateFor:(PKUniChar)c { + if (c >= 0 && c <= ' ') { // From: 0 to: 32 From:0x00 to:0x20 + return whitespaceState; + } else if (c == 33) { + return symbolState; + } else if (c == '"') { // From: 34 to: 34 From:0x22 to:0x22 + return quoteState; + } else if (c >= 35 && c <= 38) { + return symbolState; + } else if (c == '\'') { // From: 39 to: 39 From:0x27 to:0x27 + return quoteState; + } else if (c >= 40 && c <= 42) { + return symbolState; + } else if (c == '+') { // From: 43 to: 43 From:0x2B to:0x2B + return symbolState; + } else if (c == 44) { + return symbolState; + } else if (c == '-') { // From: 45 to: 45 From:0x2D to:0x2D + return numberState; + } else if (c == '.') { // From: 46 to: 46 From:0x2E to:0x2E + return numberState; + } else if (c == '/') { // From: 47 to: 47 From:0x2F to:0x2F + return symbolState; + } else if (c >= '0' && c <= '9') { // From: 48 to: 57 From:0x30 to:0x39 + return numberState; + } else if (c >= 58 && c <= 64) { + return symbolState; + } else if (c >= 'A' && c <= 'Z') { // From: 65 to: 90 From:0x41 to:0x5A + return wordState; + } else if (c >= 91 && c <= 96) { + return symbolState; + } else if (c >= 'a' && c <= 'z') { // From: 97 to:122 From:0x61 to:0x7A + return wordState; + } else if (c >= 123 && c <= 191) { + return symbolState; + } else if (c >= 0xC0 && c <= 0xFF) { // From:192 to:255 From:0xC0 to:0xFF + return wordState; + } else if (c >= 0x19E0 && c <= 0x19FF) { // khmer symbols + return symbolState; + } else if (c >= 0x2000 && c <= 0x2BFF) { // various symbols + return symbolState; + } else if (c >= 0x2E00 && c <= 0x2E7F) { // supplemental punctuation + return symbolState; + } else if (c >= 0x3000 && c <= 0x303F) { // cjk symbols & punctuation + return symbolState; + } else if (c >= 0x3200 && c <= 0x33FF) { // enclosed cjk letters and months, cjk compatibility + return symbolState; + } else if (c >= 0x4DC0 && c <= 0x4DFF) { // yijing hexagram symbols + return symbolState; + } else if (c >= 0xFE30 && c <= 0xFE6F) { // cjk compatibility forms, small form variants + return symbolState; + } else if (c >= 0xFF00 && c <= 0xFFFF) { // hiragana & katakana halfwitdh & fullwidth forms, Specials + return symbolState; + } else { + return wordState; + } +} + +@synthesize numberState; +@synthesize quoteState; +@synthesize commentState; +@synthesize symbolState; +@synthesize whitespaceState; +@synthesize wordState; +@synthesize delimitState; +@synthesize string; +@synthesize reader; +@synthesize tokenizerStates; +@end diff --git a/src/PKTokenizerState.m b/src/PKTokenizerState.m new file mode 100644 index 0000000..c217737 --- /dev/null +++ b/src/PKTokenizerState.m @@ -0,0 +1,119 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import + +#define STATE_COUNT 256 + +@interface PKTokenizer () +- (PKTokenizerState *)defaultTokenizerStateFor:(PKUniChar)c; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (void)appendString:(NSString *)s; +- (NSString *)bufferedString; +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t; + +@property (nonatomic, retain) NSMutableString *stringbuf; +@property (nonatomic) NSUInteger offset; +@property (nonatomic, retain) NSMutableArray *fallbackStates; +@end + +@implementation PKTokenizerState + +- (void)dealloc { + self.stringbuf = nil; + self.fallbackState = nil; + self.fallbackStates = nil; + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSAssert1(0, @"PKTokenizerState is an abstract classs. %s must be overriden", _cmd); + return nil; +} + + +- (void)setFallbackState:(PKTokenizerState *)state from:(PKUniChar)start to:(PKUniChar)end { + NSParameterAssert(start >= 0 && start < STATE_COUNT); + NSParameterAssert(end >= 0 && end < STATE_COUNT); + + if (!fallbackStates) { + self.fallbackStates = [NSMutableArray arrayWithCapacity:STATE_COUNT]; + + NSInteger i = 0; + for ( ; i < STATE_COUNT; i++) { + [fallbackStates addObject:[NSNull null]]; + } + + } + + NSInteger i = start; + for ( ; i <= end; i++) { + [fallbackStates replaceObjectAtIndex:i withObject:state]; + } +} + + +- (void)resetWithReader:(PKReader *)r { + self.stringbuf = [NSMutableString string]; + self.offset = r.offset - 1; +} + + +- (void)append:(PKUniChar)c { + NSParameterAssert(c > -1); + [stringbuf appendFormat:@"%C", c]; +} + + +- (void)appendString:(NSString *)s { + NSParameterAssert(s); + [stringbuf appendString:s]; +} + + +- (NSString *)bufferedString { + return [[stringbuf copy] autorelease]; +} + + +- (PKTokenizerState *)nextTokenizerStateFor:(PKUniChar)c tokenizer:(PKTokenizer *)t { + NSParameterAssert(c < STATE_COUNT); + + if (fallbackStates) { + id obj = [fallbackStates objectAtIndex:c]; + if ([NSNull null] != obj) { + return obj; + } + } + + if (fallbackState) { + return fallbackState; + } else { + return [t defaultTokenizerStateFor:c]; + } +} + +@synthesize stringbuf; +@synthesize offset; +@synthesize fallbackState; +@synthesize fallbackStates; +@end diff --git a/src/PKTrack.m b/src/PKTrack.m new file mode 100644 index 0000000..4c8fd43 --- /dev/null +++ b/src/PKTrack.m @@ -0,0 +1,97 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import + +@interface PKAssembly () +- (id)peek; +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter; +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (PKAssembly *)best:(NSSet *)inAssemblies; +@end + +@interface PKTrack () +- (void)throwTrackExceptionWithPreviousState:(NSSet *)inAssemblies parser:(PKParser *)p; +@end + +@interface PKCollectionParser () ++ (id)collectionParserWithFirst:(PKParser *)p1 rest:(va_list)rest; +@end + +@implementation PKTrack + ++ (id)track { + return [self trackWithSubparsers:nil]; +} + + ++ (id)trackWithSubparsers:(PKParser *)p1, ... { + va_list vargs; + va_start(vargs, p1); + PKTrack *tr = [self collectionParserWithFirst:p1 rest:vargs]; + va_end(vargs); + return tr; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + BOOL inTrack = NO; + NSSet *lastAssemblies = inAssemblies; + NSSet *outAssemblies = inAssemblies; + + for (PKParser *p in subparsers) { + outAssemblies = [p matchAndAssemble:outAssemblies]; + if (![outAssemblies count]) { + if (inTrack) { + [self throwTrackExceptionWithPreviousState:lastAssemblies parser:p]; + } + break; + } + inTrack = YES; + lastAssemblies = outAssemblies; + } + + return outAssemblies; +} + + +- (void)throwTrackExceptionWithPreviousState:(NSSet *)inAssemblies parser:(PKParser *)p { + PKAssembly *best = [self best:inAssemblies]; + + NSString *after = [best consumedObjectsJoinedByString:@" "]; + if (![after length]) { + after = @"-nothing-"; + } + + NSString *expected = [p description]; + + id next = [best peek]; + NSString *found = next ? [next description] : @"-nothing-"; + + NSString *reason = [NSString stringWithFormat:@"\n\nAfter : %@\nExpected : %@\nFound : %@\n\n", after, expected, found]; + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: + after, @"after", + expected, @"expected", + found, @"found", + nil]; + [[PKTrackException exceptionWithName:PKTrackExceptionName reason:reason userInfo:userInfo] raise]; +} + +@end diff --git a/src/PKTrackException.m b/src/PKTrackException.m new file mode 100644 index 0000000..a12d077 --- /dev/null +++ b/src/PKTrackException.m @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKTrackException.h" + +NSString * const PKTrackExceptionName = @"Track Exception"; + +@implementation PKTrackException + +@end diff --git a/src/PKUppercaseWord.m b/src/PKUppercaseWord.m new file mode 100644 index 0000000..5bf8549 --- /dev/null +++ b/src/PKUppercaseWord.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKUppercaseWord + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + NSString *s = tok.stringValue; + return [s length] && isupper([s characterAtIndex:0]); +} + +@end diff --git a/src/PKWhitespace.m b/src/PKWhitespace.m new file mode 100644 index 0000000..2473407 --- /dev/null +++ b/src/PKWhitespace.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKWhitespace.h" +#import + +@implementation PKWhitespace + ++ (id)whitespace { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isWhitespace; +} + +@end \ No newline at end of file diff --git a/src/PKWhitespaceState.m b/src/PKWhitespaceState.m new file mode 100644 index 0000000..53a3ef1 --- /dev/null +++ b/src/PKWhitespaceState.m @@ -0,0 +1,112 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import + +#define PKTRUE (id)kCFBooleanTrue +#define PKFALSE (id)kCFBooleanFalse + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface PKWhitespaceState () +@property (nonatomic, retain) NSMutableArray *whitespaceChars; +@end + +@implementation PKWhitespaceState + +- (id)init { + if (self = [super init]) { + const NSUInteger len = 255; + self.whitespaceChars = [NSMutableArray arrayWithCapacity:len]; + NSUInteger i = 0; + for ( ; i <= len; i++) { + [whitespaceChars addObject:PKFALSE]; + } + + [self setWhitespaceChars:YES from:0 to:' ']; + } + return self; +} + + +- (void)dealloc { + self.whitespaceChars = nil; + [super dealloc]; +} + + +- (void)setWhitespaceChars:(BOOL)yn from:(PKUniChar)start to:(PKUniChar)end { + NSUInteger len = [whitespaceChars count]; + if (start > len || end > len || start < 0 || end < 0) { + [NSException raise:@"PKWhitespaceStateNotSupportedException" format:@"PKWhitespaceState only supports setting word chars for chars in the latin1 set (under 256)"]; + } + + id obj = yn ? PKTRUE : PKFALSE; + NSUInteger i = start; + for ( ; i <= end; i++) { + [whitespaceChars replaceObjectAtIndex:i withObject:obj]; + } +} + + +- (BOOL)isWhitespaceChar:(PKUniChar)cin { + if (cin < 0 || cin > [whitespaceChars count] - 1) { + return NO; + } + return PKTRUE == [whitespaceChars objectAtIndex:cin]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + if (reportsWhitespaceTokens) { + [self resetWithReader:r]; + } + + PKUniChar c = cin; + while ([self isWhitespaceChar:c]) { + if (reportsWhitespaceTokens) { + [self append:c]; + } + c = [r read]; + } + if (PKEOF != c) { + [r unread]; + } + + if (reportsWhitespaceTokens) { + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeWhitespace stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; + } else { + return [t nextToken]; + } +} + +@synthesize whitespaceChars; +@synthesize reportsWhitespaceTokens; +@end + diff --git a/src/PKWord.m b/src/PKWord.m new file mode 100644 index 0000000..992871e --- /dev/null +++ b/src/PKWord.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@implementation PKWord + ++ (id)word { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isWord; +} + +@end diff --git a/src/PKWordState.m b/src/PKWordState.m new file mode 100644 index 0000000..c6a727a --- /dev/null +++ b/src/PKWordState.m @@ -0,0 +1,126 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import + +#define PKTRUE (id)kCFBooleanTrue +#define PKFALSE (id)kCFBooleanFalse + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface PKWordState () +- (BOOL)isWordChar:(PKUniChar)c; + +@property (nonatomic, retain) NSMutableArray *wordChars; +@end + +@implementation PKWordState + +- (id)init { + if (self = [super init]) { + self.wordChars = [NSMutableArray arrayWithCapacity:256]; + NSInteger i = 0; + for ( ; i < 256; i++) { + [wordChars addObject:PKFALSE]; + } + + [self setWordChars:YES from: 'a' to: 'z']; + [self setWordChars:YES from: 'A' to: 'Z']; + [self setWordChars:YES from: '0' to: '9']; + [self setWordChars:YES from: '-' to: '-']; + [self setWordChars:YES from: '_' to: '_']; + [self setWordChars:YES from:'\'' to:'\'']; + [self setWordChars:YES from:0xC0 to:0xFF]; + } + return self; +} + + +- (void)dealloc { + self.wordChars = nil; + [super dealloc]; +} + + +- (void)setWordChars:(BOOL)yn from:(PKUniChar)start to:(PKUniChar)end { + NSUInteger len = [wordChars count]; + if (start > len || end > len || start < 0 || end < 0) { + [NSException raise:@"PKWordStateNotSupportedException" format:@"PKWordState only supports setting word chars for chars in the latin1 set (under 256)"]; + } + + id obj = yn ? PKTRUE : PKFALSE; + NSInteger i = start; + for ( ; i <= end; i++) { + [wordChars replaceObjectAtIndex:i withObject:obj]; + } +} + + +- (BOOL)isWordChar:(PKUniChar)c { + if (c > PKEOF && c < [wordChars count] - 1) { + return (PKTRUE == [wordChars objectAtIndex:c]); + } + + if (c >= 0x2000 && c <= 0x2BFF) { // various symbols + return NO; + } else if (c >= 0xFE30 && c <= 0xFE6F) { // general punctuation + return NO; + } else if (c >= 0xFE30 && c <= 0xFE6F) { // western musical symbols + return NO; + } else if (c >= 0xFF00 && c <= 0xFF65) { // symbols within Hiragana & Katakana + return NO; + } else if (c >= 0xFFF0 && c <= 0xFFFF) { // specials + return NO; + } else if (c < 0) { + return NO; + } else { + return YES; + } +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + PKUniChar c = cin; + do { + [self append:c]; + c = [r read]; + } while ([self isWordChar:c]); + + if (PKEOF != c) { + [r unread]; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; +} + + +@synthesize wordChars; +@end diff --git a/src/RegexKitLite.h b/src/RegexKitLite.h new file mode 100644 index 0000000..0161a71 --- /dev/null +++ b/src/RegexKitLite.h @@ -0,0 +1,220 @@ +// +// RegexKitLite.h +// http://regexkit.sourceforge.net/ +// Licensed under the terms of the BSD License, as specified below. +// + +/* + Copyright (c) 2008-2009, John Engelhart + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the Zang Industries nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef __OBJC__ +#import +#import +#import +#import +#import +#endif // __OBJC__ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef REGEXKITLITE_VERSION_DEFINED +#define REGEXKITLITE_VERSION_DEFINED + +#define _RKL__STRINGIFY(b) #b +#define _RKL_STRINGIFY(a) _RKL__STRINGIFY(a) +#define _RKL_JOIN_VERSION(a,b) _RKL_STRINGIFY(a##.##b) +#define _RKL_VERSION_STRING(a,b) _RKL_JOIN_VERSION(a,b) + +#define REGEXKITLITE_VERSION_MAJOR 3 +#define REGEXKITLITE_VERSION_MINOR 0 + +#define REGEXKITLITE_VERSION_CSTRING _RKL_VERSION_STRING(REGEXKITLITE_VERSION_MAJOR, REGEXKITLITE_VERSION_MINOR) +#define REGEXKITLITE_VERSION_NSSTRING @REGEXKITLITE_VERSION_CSTRING + +#endif // REGEXKITLITE_VERSION_DEFINED + +// For Mac OS X < 10.5. +#ifndef NSINTEGER_DEFINED +#define NSINTEGER_DEFINED +#if defined(__LP64__) || defined(NS_BUILD_32_LIKE_64) +typedef long NSInteger; +typedef unsigned long NSUInteger; +#define NSIntegerMin LONG_MIN +#define NSIntegerMax LONG_MAX +#define NSUIntegerMax ULONG_MAX +#else // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64) +typedef int NSInteger; +typedef unsigned int NSUInteger; +#define NSIntegerMin INT_MIN +#define NSIntegerMax INT_MAX +#define NSUIntegerMax UINT_MAX +#endif // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64) +#endif // NSINTEGER_DEFINED + +#ifndef RKLREGEXOPTIONS_DEFINED +#define RKLREGEXOPTIONS_DEFINED + +// These must be idential to their ICU regex counterparts. See http://www.icu-project.org/userguide/regexp.html +enum { + RKLNoOptions = 0, + RKLCaseless = 2, + RKLComments = 4, + RKLDotAll = 32, + RKLMultiline = 8, + RKLUnicodeWordBoundaries = 256 +}; +typedef uint32_t RKLRegexOptions; // This must be identical to the ICU 'flags' argument type. + +#endif // RKLREGEXOPTIONS_DEFINED + +#ifndef _REGEXKITLITE_H_ +#define _REGEXKITLITE_H_ + +#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__APPLE_CC__) && (__APPLE_CC__ >= 5465) +#define RKL_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) +#else +#define RKL_DEPRECATED_ATTRIBUTE +#endif + +// This requires a few levels of rewriting to get the desired results. +#define _RKL_CONCAT_2(c,d) c ## d +#define _RKL_CONCAT(a,b) _RKL_CONCAT_2(a,b) + +#ifdef RKL_PREPEND_TO_METHODS +#define RKL_METHOD_PREPEND(x) _RKL_CONCAT(RKL_PREPEND_TO_METHODS, x) +#else // RKL_PREPEND_TO_METHODS +#define RKL_METHOD_PREPEND(x) x +#endif // RKL_PREPEND_TO_METHODS + +// If it looks like low memory notifications might be available, add code to register and respond to them. +// This is (should be) harmless if it turns out that this isn't the case, since the notification that we register for, +// UIApplicationDidReceiveMemoryWarningNotification, is dynamically looked up via dlsym(). +#if ((defined(TARGET_OS_EMBEDDED) && (TARGET_OS_EMBEDDED != 0)) || (defined(TARGET_OS_IPHONE) && (TARGET_OS_IPHONE != 0))) && (!defined(RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS) || (RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS != 0)) +#define RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS 1 +#endif + +#ifdef __OBJC__ + +// NSException exception name. +extern NSString * const RKLICURegexException; + +// NSError error domains and user info keys. +extern NSString * const RKLICURegexErrorDomain; + +extern NSString * const RKLICURegexErrorCodeErrorKey; +extern NSString * const RKLICURegexErrorNameErrorKey; +extern NSString * const RKLICURegexLineErrorKey; +extern NSString * const RKLICURegexOffsetErrorKey; +extern NSString * const RKLICURegexPreContextErrorKey; +extern NSString * const RKLICURegexPostContextErrorKey; +extern NSString * const RKLICURegexRegexErrorKey; +extern NSString * const RKLICURegexRegexOptionsErrorKey; + +@interface NSString (RegexKitLiteAdditions) + ++ (void)RKL_METHOD_PREPEND(clearStringCache); + +// Although these are marked as deprecated, a bug in GCC prevents a warning from being issues for + class methods. Filed bug with Apple, #6736857. ++ (NSInteger)RKL_METHOD_PREPEND(captureCountForRegex):(NSString *)regex RKL_DEPRECATED_ATTRIBUTE; ++ (NSInteger)RKL_METHOD_PREPEND(captureCountForRegex):(NSString *)regex options:(RKLRegexOptions)options error:(NSError **)error RKL_DEPRECATED_ATTRIBUTE; + +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex; +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex range:(NSRange)range; +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error; + +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex; +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex inRange:(NSRange)range; +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range error:(NSError **)error; + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex; +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex capture:(NSInteger)capture; +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex inRange:(NSRange)range; +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range capture:(NSInteger)capture error:(NSError **)error; + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex; +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex capture:(NSInteger)capture; +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex inRange:(NSRange)range; +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range capture:(NSInteger)capture error:(NSError **)error; + +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement; +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement range:(NSRange)searchRange; +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement options:(RKLRegexOptions)options range:(NSRange)searchRange error:(NSError **)error; + + //// + +- (NSInteger)RKL_METHOD_PREPEND(captureCount); +- (NSInteger)RKL_METHOD_PREPEND(captureCountWithOptions):(RKLRegexOptions)options error:(NSError **)error; + +- (BOOL)RKL_METHOD_PREPEND(isRegexValid); +- (BOOL)RKL_METHOD_PREPEND(isRegexValidWithOptions):(RKLRegexOptions)options error:(NSError **)error; + +- (void)RKL_METHOD_PREPEND(flushCachedRegexData); + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex; +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex capture:(NSInteger)capture; +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex range:(NSRange)range; +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range capture:(NSInteger)capture error:(NSError **)error; + + +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex; +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex range:(NSRange)range; +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error; + +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex; +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex range:(NSRange)range; +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error; + +@end + +@interface NSMutableString (RegexKitLiteAdditions) + +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement; +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement range:(NSRange)searchRange; +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement options:(RKLRegexOptions)options range:(NSRange)searchRange error:(NSError **)error; + +@end + +#endif // __OBJC__ + +#endif // _REGEXKITLITE_H_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/RegexKitLite.m b/src/RegexKitLite.m new file mode 100644 index 0000000..de1eca4 --- /dev/null +++ b/src/RegexKitLite.m @@ -0,0 +1,1634 @@ +// +// RegexKitLite.m +// http://regexkit.sourceforge.net/ +// Licensed under the terms of the BSD License, as specified below. +// + +/* + Copyright (c) 2008-2009, John Engelhart + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the Zang Industries nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#import +#import +#import +#import +#import +#import +#ifdef __OBJC_GC__ +#import +#define RKL_STRONG_REF __strong +#else // __OBJC_GC__ +#define RKL_STRONG_REF +#endif // __OBJC_GC__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#import "RegexKitLite.h" + +// If the gcc flag -mmacosx-version-min is used with, for example, '=10.2', give a warning that the libicucore.dylib is only available on >= 10.3. +// If you are reading this comment because of this warning, this is to let you know that linking to /usr/lib/libicucore.dylib will cause your executable to fail on < 10.3. +// You will need to build your own version of the ICU library and link to that in order for RegexKitLite to work successfully on < 10.3. This is not simple. + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030 +#warning The ICU dynamic shared library, /usr/lib/libicucore.dylib, is only available on Mac OS X 10.3 and later. +#warning You will need to supply a version of the ICU library to use RegexKitLite on Mac OS X 10.2 and earlier. +#endif + +//////////// +#pragma mark Compile time tuneables + +#ifndef RKL_CACHE_SIZE +#define RKL_CACHE_SIZE (23UL) +#endif + +#ifndef RKL_FIXED_LENGTH +#define RKL_FIXED_LENGTH (2048UL) +#endif + +#ifndef RKL_STACK_LIMIT +#define RKL_STACK_LIMIT (128UL * 1024UL) +#endif + +#ifdef RKL_APPEND_TO_ICU_FUNCTIONS +#define RKL_ICU_FUNCTION_APPEND(x) _RKL_CONCAT(x, RKL_APPEND_TO_ICU_FUNCTIONS) +#else // RKL_APPEND_TO_ICU_FUNCTIONS +#define RKL_ICU_FUNCTION_APPEND(x) x +#endif // RKL_APPEND_TO_ICU_FUNCTIONS + +#if defined(RKL_DTRACE) && (RKL_DTRACE != 0) +#define _RKL_DTRACE_ENABLED +#endif // defined(RKL_DTRACE) && (RKL_DTRACE != 0) + +// These are internal, non-public tuneables. +#define RKL_SCRATCH_BUFFERS (4UL) +#define RKL_CACHE_LINE_SIZE (64UL) +#define RKL_DTRACE_REGEXUTF8_SIZE (64UL) + +////////////// +#pragma mark - +#pragma mark GCC / Compiler macros + +#if defined (__GNUC__) && (__GNUC__ >= 4) +#define RKL_ATTRIBUTES(attr, ...) __attribute__((attr, ##__VA_ARGS__)) +#define RKL_EXPECTED(cond, expect) __builtin_expect((long)(cond), (expect)) +#define RKL_PREFETCH(ptr) __builtin_prefetch(ptr) +#define RKL_PREFETCH_UNICHAR(ptr, off) { const char *p = ((const char *)(ptr)) + ((off) * sizeof(UniChar)) + RKL_CACHE_LINE_SIZE; RKL_PREFETCH(p); RKL_PREFETCH(p + RKL_CACHE_LINE_SIZE); } +#define RKL_HAVE_CLEANUP +#define RKL_CLEANUP(func) __attribute__((cleanup(func))) +#else // defined (__GNUC__) && (__GNUC__ >= 4) +#define RKL_ATTRIBUTES(attr, ...) +#define RKL_EXPECTED(cond, expect) cond +#define RKL_PREFETCH(ptr) +#define RKL_PREFETCH_UNICHAR(ptr, off) +#define RKL_CLEANUP(func) +#endif // defined (__GNUC__) && (__GNUC__ >= 4) + +#define RKL_STATIC_INLINE static __inline__ RKL_ATTRIBUTES(always_inline) +#define RKL_UNUSED_ARG RKL_ATTRIBUTES(unused) +#define RKL_NONNULL_ARGS(arg, ...) RKL_ATTRIBUTES(nonnull(arg, ##__VA_ARGS__)) +#define RKL_NONNULL_ARGS_WARN_UNUSED(arg, ...) RKL_ATTRIBUTES(warn_unused_result, nonnull(arg, ##__VA_ARGS__)) + +#if defined (__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) +#define RKL_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(as, nn, ...) RKL_ATTRIBUTES(warn_unused_result, nonnull(nn, ##__VA_ARGS__), alloc_size(as)) +#else // defined (__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) +#define RKL_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(as, nn, ...) RKL_ATTRIBUTES(warn_unused_result, nonnull(nn, ##__VA_ARGS__)) +#endif // defined (__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) + + +//////////// +#pragma mark - +#pragma mark Assertion macros + +// These macros are nearly identical to their NSCParameterAssert siblings. +// This is required because nearly everything is done while cacheSpinLock is locked. +// We need to safely unlock before throwing any of these exceptions. +// @try {} @finally {} significantly slows things down so it's not used. + +#define RKLCAssertDictionary(d, ...) rkl_makeAssertDictionary(__PRETTY_FUNCTION__, __FILE__, __LINE__, (d), ##__VA_ARGS__) +#define RKLCDelayedHardAssert(c, e, g) do { id *_e=(e); int _c=(c); if(RKL_EXPECTED(_e == NULL, 0L) || RKL_EXPECTED(*_e != NULL, 0L)) { goto g; } if(RKL_EXPECTED(!_c, 0L)) { *_e = RKLCAssertDictionary(@"Invalid parameter not satisfying: %s", #c); goto g; } } while(0) + +#ifdef NS_BLOCK_ASSERTIONS +#define RKLCDelayedAssert(c, e, g) +#define RKL_UNUSED_ASSERTION_ARG RKL_ATTRIBUTES(unused) +#else // NS_BLOCK_ASSERTIONS +#define RKLCDelayedAssert(c, e, g) RKLCDelayedHardAssert(c, e, g) +#define RKL_UNUSED_ASSERTION_ARG +#endif // NS_BLOCK_ASSERTIONS + +#define RKL_EXCEPTION(e, f, ...) [NSException exceptionWithName:(e) reason:rkl_stringFromClassAndMethod((self), (_cmd), (f), ##__VA_ARGS__) userInfo:NULL] +#define RKL_RAISE_EXCEPTION(e, f, ...) [RKL_EXCEPTION(e, f, ##__VA_ARGS__) raise] + +//////////// +#pragma mark - +#pragma mark Utility functions and macros + +RKL_STATIC_INLINE BOOL NSRangeInsideRange(NSRange cin, NSRange win) RKL_ATTRIBUTES(warn_unused_result); +RKL_STATIC_INLINE BOOL NSRangeInsideRange(NSRange cin, NSRange win) { return((((cin.location - win.location) <= win.length) && ((NSMaxRange(cin) - win.location) <= win.length)) ? YES : NO); } + +#define NSMakeRange(loc, len) ((NSRange){.location=(NSUInteger)(loc), .length=(NSUInteger)(len)}) +#define CFMakeRange(loc, len) ((CFRange){.location= (CFIndex)(loc), .length= (CFIndex)(len)}) +#define NSNotFoundRange ((NSRange){.location= NSNotFound, .length= 0UL}) +#define NSMaxiumRange ((NSRange){.location= 0UL, .length= NSUIntegerMax}) + +//////////// +#pragma mark - +#pragma mark Exported NSString symbols for exception names, error domains, error keys, etc + +NSString * const RKLICURegexException = @"RKLICURegexException"; + +NSString * const RKLICURegexErrorDomain = @"RKLICURegexErrorDomain"; + +NSString * const RKLICURegexErrorCodeErrorKey = @"RKLICURegexErrorCode"; +NSString * const RKLICURegexErrorNameErrorKey = @"RKLICURegexErrorName"; +NSString * const RKLICURegexLineErrorKey = @"RKLICURegexLine"; +NSString * const RKLICURegexOffsetErrorKey = @"RKLICURegexOffset"; +NSString * const RKLICURegexPreContextErrorKey = @"RKLICURegexPreContext"; +NSString * const RKLICURegexPostContextErrorKey = @"RKLICURegexPostContext"; +NSString * const RKLICURegexRegexErrorKey = @"RKLICURegexRegex"; +NSString * const RKLICURegexRegexOptionsErrorKey = @"RKLICURegexRegexOptions"; + +//////////// +#pragma mark - +#pragma mark Type / struct definitions + +// In general, the ICU bits and pieces here must exactly match the definition in the ICU sources. + +#define U_ZERO_ERROR 0 +#define U_INDEX_OUTOFBOUNDS_ERROR 8 +#define U_BUFFER_OVERFLOW_ERROR 15 + +#define U_PARSE_CONTEXT_LEN 16 + +typedef struct uregex uregex; // Opaque ICU regex type. + +typedef struct UParseError { // This must be exactly the same as the 'real' ICU declaration. + int32_t line; + int32_t offset; + UniChar preContext[U_PARSE_CONTEXT_LEN]; + UniChar postContext[U_PARSE_CONTEXT_LEN]; +} UParseError; + +// For use with GCC's cleanup() __attribute__. +#define RKLLockedCacheSpinLock ((NSUInteger)(1UL<<0)) +#define RKLUnlockedCacheSpinLock ((NSUInteger)(1UL<<1)) + +enum { + RKLSplitOp = 1, + RKLReplaceOp = 2, + RKLRangeOp = 3, + RKLArrayOfStringsOp = 4, + RKLArrayOfCapturesOp = 5, + RKLCapturesArrayOp = 6, + RKLMaskOp = 0xf, + RKLReplaceMutable = 1 << 4, + RKLSubcapturesArray = 1 << 5, +}; +typedef NSUInteger RKLRegexOp; + +typedef struct { + NSRange *ranges, findInRange; + NSInteger capacity, found, findUpTo, capture; + size_t size, stackUsed; + void **rangesScratchBuffer; + RKL_STRONG_REF void **stringsScratchBuffer; + RKL_STRONG_REF void **arraysScratchBuffer; +} RKLFindAll; + +typedef struct { + CFStringRef string; + CFHashCode hash; + CFIndex length; + RKL_STRONG_REF UniChar *uniChar; +} RKLBuffer; + +typedef struct { + CFStringRef regexString; + RKLRegexOptions options; + uregex *icu_regex; + NSInteger captureCount; + + CFStringRef setToString; + CFHashCode setToHash; + CFIndex setToLength; + NSUInteger setToIsImmutable:1; + NSUInteger setToNeedsConversion:1; + const UniChar *setToUniChar; + NSRange setToRange, lastFindRange, lastMatchRange; +#ifndef __LP64__ + NSUInteger pad[1]; // For 32 bits, this makes the struct 64 bytes exactly, which is good for cache line alignment. +#endif // __LP64__ +} RKLCacheSlot; + +//////////// +#pragma mark - +#pragma mark Translation unit scope global variables + +static UniChar fixedUniChar[(RKL_FIXED_LENGTH)]; // This is the fixed sized UTF-16 conversion buffer. +static RKLCacheSlot rkl_cacheSlots[(RKL_CACHE_SIZE)], *lastCacheSlot; +static OSSpinLock cacheSpinLock = OS_SPINLOCK_INIT; +static RKLBuffer dynamicBuffer, fixedBuffer = {NULL, 0UL, 0L, &fixedUniChar[0]}; +static const UniChar emptyUniCharString[1]; // For safety, icu_regexes are 'set' to this when the string they were searched is cleared. +static RKL_STRONG_REF void *scratchBuffer[(RKL_SCRATCH_BUFFERS)]; // Used to hold temporary allocations that are allocated via reallocf(). + +//////////// +#pragma mark - +#pragma mark CFArray call backs + +// These are used when running under manual memory management for the array that rkl_splitArray creates. +// The split strings are created, but not autoreleased. The (immutable) array is created using these callbacks, which skips the CFRetain() call, effectively transferring ownership to the CFArray object. +// For each split string this saves the overhead of an autorelease, then an array retain, then an NSAutoreleasePool release. This is good for a ~30% speed increase. + +static void RKLCFArrayRelease (CFAllocatorRef allocator RKL_UNUSED_ARG, const void *ptr) { CFRelease((CFTypeRef)ptr); } +static CFArrayCallBacks transferOwnershipArrayCallBacks = { (CFIndex)0L, NULL, RKLCFArrayRelease, CFCopyDescription, CFEqual }; + +#if defined(__OBJC_GC__) || defined(RKL_FORCE_GC) +//////////// +#pragma mark - +#pragma mark Low-level Garbage Collection aware memory/resource allocation utilities +// If compiled with Garbage Collection, we need to be able to do a few things slightly differently. +// The basic premiss is that under GC we use a trampoline function pointer which is set to a _start function to catch the first invocation. +// The _start function checks if GC is running and then overwrites the function pointer with the appropriate routine. Think of it as 'lazy linking'. + +enum { RKLScannedOption = NSScannedOption }; + +// rkl_collectingEnabled uses objc_getClass() to get the NSGarbageCollector class, which doesn't exist on earlier systems. +// This allows for graceful failure should we find ourselves running on an earlier version of the OS without NSGarbageCollector. +static BOOL rkl_collectingEnabled_first (void); +static BOOL rkl_collectingEnabled_yes (void) { return(YES); } +static BOOL rkl_collectingEnabled_no (void) { return(NO); } +static BOOL(*rkl_collectingEnabled) (void) = rkl_collectingEnabled_first; +static BOOL rkl_collectingEnabled_first (void) { + BOOL gcEnabled = ([objc_getClass("NSGarbageCollector") defaultCollector] != NULL) ? YES : NO; + if(gcEnabled == YES) { + // This section of code is required due to what I consider to be a fundamental design flaw in Cocoas GC system. + // Earlier versions of "Garbage Collection Programming Guide" stated that (paraphrased) "all globals are automatically roots". + // Current versions of the guide now include the following warning: + // "You may pass addresses of strong globals or statics into routines expecting pointers to object pointers (such as id* or NSError**) + // only if they have first been assigned to directly, rather than through a pointer dereference." + // This is a surprisingly non-trivial condition to actually meet in practice and is a recipe for impossible to debug race condition bugs. + // We just happen to be very, very, very lucky in the fact that we can initilize our root set before the first use. + int x; + for(x = 0; x < (int)(RKL_SCRATCH_BUFFERS); x++) { scratchBuffer[x] = NSAllocateCollectable(16UL, 0UL); scratchBuffer[x] = NULL; } + dynamicBuffer.uniChar = (RKL_STRONG_REF UniChar *)NSAllocateCollectable(16UL, 0UL); dynamicBuffer.uniChar = NULL; + } + return((rkl_collectingEnabled = (gcEnabled == YES) ? rkl_collectingEnabled_yes : rkl_collectingEnabled_no)()); +} + +// rkl_realloc() +static void *rkl_realloc_first (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags); +static void *rkl_realloc_std (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags RKL_UNUSED_ARG) { return((*ptr = reallocf(*ptr, size))); } +static void *rkl_realloc_gc (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags) { return((*ptr = NSReallocateCollectable(*ptr, (NSUInteger)size, flags))); } +static void *(*rkl_realloc) (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags) RKL_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(2,1) = rkl_realloc_first; +static void *rkl_realloc_first (RKL_STRONG_REF void **ptr, size_t size, NSUInteger flags) { return((rkl_realloc = (rkl_collectingEnabled()==YES) ? rkl_realloc_gc : rkl_realloc_std)(ptr, size, flags)); } + +// rkl_free() +static void * rkl_free_first (RKL_STRONG_REF void **ptr); +static void * rkl_free_std (RKL_STRONG_REF void **ptr) { if(*ptr != NULL) { free(*ptr); *ptr = NULL; } return(NULL); } +static void * rkl_free_gc (RKL_STRONG_REF void **ptr) { if(*ptr != NULL) { *ptr = NULL; } return(NULL); } +static void *(*rkl_free) (RKL_STRONG_REF void **ptr) RKL_NONNULL_ARGS(1) = rkl_free_first; +static void * rkl_free_first (RKL_STRONG_REF void **ptr) { return((rkl_free = (rkl_collectingEnabled()==YES) ? rkl_free_gc : rkl_free_std)(ptr)); } + +// rkl_CFAutorelease() +static id rkl_CFAutorelease_first (CFTypeRef obj); +static id rkl_CFAutorelease_std (CFTypeRef obj) { return([(id)obj autorelease]); } +static id rkl_CFAutorelease_gc (CFTypeRef obj) { return(NSMakeCollectable(obj)); } +static id(*rkl_CFAutorelease) (CFTypeRef obj) = rkl_CFAutorelease_first; +static id rkl_CFAutorelease_first (CFTypeRef obj) { return((rkl_CFAutorelease = (rkl_collectingEnabled()==YES) ? rkl_CFAutorelease_gc : rkl_CFAutorelease_std)(obj)); } + +// rkl_CreateStringWithSubstring() +static id rkl_CreateStringWithSubstring_first (id string, NSRange range); +static id rkl_CreateStringWithSubstring_std (id string, NSRange range) { return((id)CFStringCreateWithSubstring(NULL, (CFStringRef)string, CFMakeRange((CFIndex)range.location, (CFIndex)range.length))); } +static id rkl_CreateStringWithSubstring_gc (id string, NSRange range) { return([string substringWithRange:range]); } +static id(*rkl_CreateStringWithSubstring) (id string, NSRange range) RKL_NONNULL_ARGS_WARN_UNUSED(1) = rkl_CreateStringWithSubstring_first; +static id rkl_CreateStringWithSubstring_first (id string, NSRange range) { return((rkl_CreateStringWithSubstring = (rkl_collectingEnabled()==YES) ? rkl_CreateStringWithSubstring_gc : rkl_CreateStringWithSubstring_std)(string, range)); } + +// rkl_ReleaseObject() +static id rkl_ReleaseObject_first (id obj); +static id rkl_ReleaseObject_std (id obj) { CFRelease((CFTypeRef)obj); return(NULL); } +static id rkl_ReleaseObject_gc (id obj RKL_UNUSED_ARG) { return(NULL); } +static id (*rkl_ReleaseObject) (id obj) RKL_NONNULL_ARGS(1) = rkl_ReleaseObject_first; +static id rkl_ReleaseObject_first (id obj) { return((rkl_ReleaseObject = (rkl_collectingEnabled()==YES) ? rkl_ReleaseObject_gc : rkl_ReleaseObject_std)(obj)); } + +// rkl_CreateArrayWithObjects() +static id rkl_CreateArrayWithObjects_first (void **objects, NSUInteger count); +static id rkl_CreateArrayWithObjects_std (void **objects, NSUInteger count) { return((id)CFArrayCreate(NULL, (const void **)objects, (CFIndex)count, &transferOwnershipArrayCallBacks)); } +static id rkl_CreateArrayWithObjects_gc (void **objects, NSUInteger count) { return([NSArray arrayWithObjects:(const id *)objects count:count]); } +static id(*rkl_CreateArrayWithObjects) (void **objects, NSUInteger count) RKL_NONNULL_ARGS_WARN_UNUSED(1) = rkl_CreateArrayWithObjects_first; +static id rkl_CreateArrayWithObjects_first (void **objects, NSUInteger count) { return((rkl_CreateArrayWithObjects = (rkl_collectingEnabled()==YES) ? rkl_CreateArrayWithObjects_gc : rkl_CreateArrayWithObjects_std)(objects, count)); } + +// rkl_CreateAutoreleasedArray() +static id rkl_CreateAutoreleasedArray_first (void **objects, NSUInteger count); +static id rkl_CreateAutoreleasedArray_std (void **objects, NSUInteger count) { return((id)rkl_CFAutorelease(rkl_CreateArrayWithObjects(objects, count))); } +static id rkl_CreateAutoreleasedArray_gc (void **objects, NSUInteger count) { return(rkl_CreateArrayWithObjects(objects, count)); } +static id(*rkl_CreateAutoreleasedArray) (void **objects, NSUInteger count) RKL_NONNULL_ARGS_WARN_UNUSED(1) = rkl_CreateAutoreleasedArray_first; +static id rkl_CreateAutoreleasedArray_first (void **objects, NSUInteger count) { return((rkl_CreateAutoreleasedArray = (rkl_collectingEnabled()==YES) ? rkl_CreateAutoreleasedArray_gc : rkl_CreateAutoreleasedArray_std)(objects, count)); } + +#else // __OBJC_GC__ not defined +//////////// +#pragma mark - +#pragma mark Low-level explicit memory/resource allocation utilities + +enum { RKLScannedOption = 0 }; + +#define rkl_collectingEnabled() (NO) + +RKL_STATIC_INLINE void *rkl_realloc (void **ptr, size_t size, NSUInteger flags) RKL_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(2,1); +RKL_STATIC_INLINE void *rkl_free (void **ptr) RKL_NONNULL_ARGS(1); +RKL_STATIC_INLINE id rkl_CFAutorelease (CFTypeRef obj); +RKL_STATIC_INLINE id rkl_CreateAutoreleasedArray (void **objects, NSUInteger count) RKL_NONNULL_ARGS_WARN_UNUSED(1); +RKL_STATIC_INLINE id rkl_CreateArrayWithObjects (void **objects, NSUInteger count) RKL_NONNULL_ARGS_WARN_UNUSED(1); +RKL_STATIC_INLINE id rkl_CreateStringWithSubstring (id string, NSRange range) RKL_NONNULL_ARGS_WARN_UNUSED(1); +RKL_STATIC_INLINE id rkl_ReleaseObject (id obj) RKL_NONNULL_ARGS(1); + +RKL_STATIC_INLINE void *rkl_realloc (void **ptr, size_t size, NSUInteger flags RKL_UNUSED_ARG) { return((*ptr = reallocf(*ptr, size))); } +RKL_STATIC_INLINE void *rkl_free (void **ptr) { if(*ptr != NULL) { free(*ptr); *ptr = NULL; } return(NULL); } +RKL_STATIC_INLINE id rkl_CFAutorelease (CFTypeRef obj) { return([(id)obj autorelease]); } +RKL_STATIC_INLINE id rkl_CreateArrayWithObjects (void **objects, NSUInteger count) { return((id)CFArrayCreate(NULL, (const void **)objects, (CFIndex)count, &transferOwnershipArrayCallBacks)); } +RKL_STATIC_INLINE id rkl_CreateAutoreleasedArray (void **objects, NSUInteger count) { return(rkl_CFAutorelease(rkl_CreateArrayWithObjects(objects, count))); } +RKL_STATIC_INLINE id rkl_CreateStringWithSubstring (id string, NSRange range) { return((id)CFStringCreateWithSubstring(NULL, (CFStringRef)string, CFMakeRange((CFIndex)range.location, (CFIndex)[range length]))); } +RKL_STATIC_INLINE id rkl_ReleaseObject (id obj) { CFRelease((CFTypeRef)obj); return(NULL); } + +#endif // __OBJC_GC__ + +//////////// +#pragma mark - +#pragma mark ICU function prototypes + +// ICU functions. See http://www.icu-project.org/apiref/icu4c/uregex_8h.html Tweaked slightly from the originals, but functionally identical. +const char *RKL_ICU_FUNCTION_APPEND(u_errorName) (int32_t status) RKL_ATTRIBUTES(pure); +int32_t RKL_ICU_FUNCTION_APPEND(u_strlen) (const UniChar *s) RKL_ATTRIBUTES(nonnull(1), pure); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_appendReplacement) (uregex *regexp, const UniChar *replacementText, int32_t replacementLength, UniChar **destBuf, int32_t *destCapacity, int32_t *status) RKL_NONNULL_ARGS(1,2,4,5,6); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_appendTail) (uregex *regexp, UniChar **destBuf, int32_t *destCapacity, int32_t *status) RKL_NONNULL_ARGS(1,2,3,4); +void RKL_ICU_FUNCTION_APPEND(uregex_close) (uregex *regexp) RKL_NONNULL_ARGS(1); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_end) (uregex *regexp, int32_t groupNum, int32_t *status) RKL_NONNULL_ARGS(1,3); +BOOL RKL_ICU_FUNCTION_APPEND(uregex_find) (uregex *regexp, int32_t location, int32_t *status) RKL_NONNULL_ARGS(1,3); +BOOL RKL_ICU_FUNCTION_APPEND(uregex_findNext) (uregex *regexp, int32_t *status) RKL_NONNULL_ARGS(1,2); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_groupCount) (uregex *regexp, int32_t *status) RKL_NONNULL_ARGS(1,2); +uregex *RKL_ICU_FUNCTION_APPEND(uregex_open) (const UniChar *pattern, int32_t patternLength, RKLRegexOptions flags, UParseError *parseError, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,4,5); +void RKL_ICU_FUNCTION_APPEND(uregex_reset) (uregex *regexp, int32_t newIndex, int32_t *status) RKL_NONNULL_ARGS(1,3); +void RKL_ICU_FUNCTION_APPEND(uregex_setText) (uregex *regexp, const UniChar *text, int32_t textLength, int32_t *status) RKL_NONNULL_ARGS(1,2,4); +int32_t RKL_ICU_FUNCTION_APPEND(uregex_start) (uregex *regexp, int32_t groupNum, int32_t *status) RKL_NONNULL_ARGS(1,3); + +//////////// +#pragma mark - +#pragma mark RegexKitLite internal, private function prototypes + +static RKLCacheSlot *rkl_getCachedRegex (NSString *regexString, RKLRegexOptions options, NSError **error, id *exception) RKL_NONNULL_ARGS_WARN_UNUSED(1,4); +static NSUInteger rkl_setCacheSlotToString (RKLCacheSlot *cacheSlot, const NSRange *range, int32_t *status, id *exception RKL_UNUSED_ASSERTION_ARG) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,3,4); +static RKLCacheSlot *rkl_getCachedRegexSetToString (NSString *regexString, RKLRegexOptions options, NSString *matchString, NSUInteger *matchLengthPtr, NSRange *matchRange, NSError **error, id *exception, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,3,4,5,7,8); +static id rkl_performRegexOp (id self, SEL _cmd, RKLRegexOp regexOp, NSString *regexString, RKLRegexOptions options, NSInteger capture, id matchString, NSRange *matchRange, NSString *replacementString, NSError **error, void *result) RKL_NONNULL_ARGS(1,2); +static void rkl_handleDelayedAssert (id self, SEL _cmd, id exception) RKL_NONNULL_ARGS(1,2,3); + +static NSUInteger rkl_search (RKLCacheSlot *cacheSlot, NSRange *searchRange, NSUInteger updateSearchRange, id *exception RKL_UNUSED_ASSERTION_ARG, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4,5); + +static BOOL rkl_findRanges (RKLCacheSlot *cacheSlot, RKLRegexOp regexOp, RKLFindAll *findAll, id *exception, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,3,4,5); +static NSUInteger rkl_growFindRanges (RKLCacheSlot *cacheSlot, NSUInteger lastLocation, RKLFindAll *findAll, id *exception RKL_UNUSED_ASSERTION_ARG) RKL_NONNULL_ARGS_WARN_UNUSED(1,3,4); +static NSArray *rkl_makeArray (RKLCacheSlot *cacheSlot, RKLRegexOp regexOp, RKLFindAll *findAll, id *exception RKL_UNUSED_ASSERTION_ARG) RKL_NONNULL_ARGS_WARN_UNUSED(1,3,4); + +static NSString *rkl_replaceString (RKLCacheSlot *cacheSlot, id searchString, NSUInteger searchU16Length, NSString *replacementString, NSUInteger replacementU16Length, NSUInteger *replacedCount, NSUInteger replaceMutable, id *exception, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4,8,9); +static int32_t rkl_replaceAll (RKLCacheSlot *cacheSlot, const UniChar *replacementUniChar, int32_t replacementU16Length, UniChar *replacedUniChar, int32_t replacedU16Capacity, NSUInteger *replacedCount, id *exception RKL_UNUSED_ASSERTION_ARG, int32_t *status) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4,7,8); + +static NSUInteger rkl_isRegexValid (id self, SEL _cmd, NSString *regex, RKLRegexOptions options, NSInteger *captureCountPtr, NSError **error) RKL_NONNULL_ARGS(1,2); + +static void rkl_clearStringCache (void); +static void rkl_clearBuffer (RKLBuffer *buffer, NSUInteger freeDynamicBuffer) RKL_NONNULL_ARGS(1); +static void rkl_clearCacheSlotRegex (RKLCacheSlot *cacheSlot) RKL_NONNULL_ARGS(1); +static void rkl_clearCacheSlotSetTo (RKLCacheSlot *cacheSlot) RKL_NONNULL_ARGS(1); + +static NSDictionary *rkl_userInfoDictionary (NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status, ...) RKL_ATTRIBUTES(sentinel, nonnull(1), warn_unused_result); +static NSError *rkl_NSErrorForRegex (NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status) RKL_NONNULL_ARGS_WARN_UNUSED(1); +static NSException *rkl_NSExceptionForRegex (NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status) RKL_NONNULL_ARGS_WARN_UNUSED(1); +static NSDictionary *rkl_makeAssertDictionary (const char *function, const char *file, int line, NSString *format, ...) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4); +static NSString *rkl_stringFromClassAndMethod (id object, SEL selector, NSString *format, ...) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,3); + +RKL_STATIC_INLINE int32_t rkl_getRangeForCapture(RKLCacheSlot *cs, int32_t *s, int32_t c, NSRange *r) RKL_NONNULL_ARGS_WARN_UNUSED(1,2,4); +RKL_STATIC_INLINE int32_t rkl_getRangeForCapture(RKLCacheSlot *cs, int32_t *s, int32_t c, NSRange *r) { uregex *re = cs->icu_regex; int32_t start = RKL_ICU_FUNCTION_APPEND(uregex_start)(re, c, s); if(RKL_EXPECTED((*s > U_ZERO_ERROR), 0L) || (start == -1)) { *r = NSNotFoundRange; } else { r->location = (NSUInteger)start; r->length = (NSUInteger)RKL_ICU_FUNCTION_APPEND(uregex_end)(re, c, s) - r->location; r->location += cs->setToRange.location; } return(*s); } + +RKL_STATIC_INLINE RKLFindAll rkl_makeFindAll(NSRange *r, NSRange fir, NSInteger c, size_t s, size_t su, void **rsb, RKL_STRONG_REF void **ssb, RKL_STRONG_REF void **asb, NSInteger f, NSInteger cap, NSInteger fut) RKL_ATTRIBUTES(warn_unused_result); +RKL_STATIC_INLINE RKLFindAll rkl_makeFindAll(NSRange *r, NSRange fir, NSInteger c, size_t s, size_t su, void **rsb, RKL_STRONG_REF void **ssb, RKL_STRONG_REF void **asb, NSInteger f, NSInteger cap, NSInteger fut) { return(((RKLFindAll){ .ranges=r, .findInRange=fir, .capacity=c, .found=f, .findUpTo=fut, .capture=cap, .size=s, .stackUsed=su, .rangesScratchBuffer=rsb, .stringsScratchBuffer=ssb, .arraysScratchBuffer=asb})); } + +//////////// +#pragma mark - +#pragma mark RKL_FAST_MUTABLE_CHECK implementation + +#ifdef RKL_FAST_MUTABLE_CHECK +// We use a trampoline function pointer to check at run time if the function __CFStringIsMutable is available. +// If it is, the trampoline function pointer is replaced with the address of that function. +// Otherwise, we assume the worst case that every string is mutable. +// This hopefully helps to protect us since we're using an undocumented, non-public API call. +// We will keep on working if it ever does go away, just with a bit less performance due to the overhead of mutable checks. + +static BOOL rkl_CFStringIsMutable_first (CFStringRef str); +static BOOL rkl_CFStringIsMutable_yes (CFStringRef str RKL_UNUSED_ARG) { return(YES); } +static BOOL(*rkl_CFStringIsMutable) (CFStringRef str) = rkl_CFStringIsMutable_first; +static BOOL rkl_CFStringIsMutable_first (CFStringRef str) { if((rkl_CFStringIsMutable = (BOOL(*)(CFStringRef))dlsym(RTLD_DEFAULT, "__CFStringIsMutable")) == NULL) { rkl_CFStringIsMutable = rkl_CFStringIsMutable_yes; } return(rkl_CFStringIsMutable(str)); } +#else // RKL_FAST_MUTABLE_CHECK is not defined. Assume that all strings are potentially mutable. +#define rkl_CFStringIsMutable(s) (YES) +#endif // RKL_FAST_MUTABLE_CHECK + + +//////////// +#pragma mark - +#pragma mark iPhone / iPod touch low memory notification handler + +#if defined(RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS) && (RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS == 1) + +// The next few lines are specifically for the iPhone to catch low memory conditions. +// The basic idea is that rkl_RegisterForLowMemoryNotifications() is set to be run once by the linker at load time via __attribute((constructor)). +// rkl_RegisterForLowMemoryNotifications() tries to find the iPhone low memory notification symbol. If it can find it, +// it registers with the default NSNotificationCenter to call the RKLLowMemoryWarningObserver class method +lowMemoryWarning:. +// rkl_RegisterForLowMemoryNotifications() uses an atomic compare and swap to guarantee that it initalizes exactly once. +// +lowMemoryWarning tries to acquire the cache lock. If it gets the lock, it clears the cache. If it can't, it calls performSelector: +// with a delay of half a second to try again. This will hopefully prevent any deadlocks, such as a RegexKitLite request for +// memory triggering a notifcation while the lock is held. + +static void rkl_RegisterForLowMemoryNotifications(void) RKL_ATTRIBUTES(used); + +@interface RKLLowMemoryWarningObserver : NSObject +(void)lowMemoryWarning:(id)notification; @end +@implementation RKLLowMemoryWarningObserver ++(void)lowMemoryWarning:(id)notification { + if(OSSpinLockTry(&cacheSpinLock)) { rkl_clearStringCache(); OSSpinLockUnlock(&cacheSpinLock); } + else { [[RKLLowMemoryWarningObserver class] performSelector:@selector(lowMemoryWarning:) withObject:NULL afterDelay:(NSTimeInterval)0.1]; } +} +@end + +static int rkl_HaveRegisteredForLowMemoryNotifications = 0; + +__attribute__((constructor)) static void rkl_RegisterForLowMemoryNotifications(void) { + void **memoryWarningNotification = NULL; + + if(OSAtomicCompareAndSwapIntBarrier(0, 1, &rkl_HaveRegisteredForLowMemoryNotifications)) { + if((memoryWarningNotification = (void **)dlsym(RTLD_DEFAULT, "UIApplicationDidReceiveMemoryWarningNotification")) != NULL) { + [[NSNotificationCenter defaultCenter] addObserver:[RKLLowMemoryWarningObserver class] selector:@selector(lowMemoryWarning:) name:(NSString *)*memoryWarningNotification object:NULL]; + } + } +} + +#endif // defined(RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS) && (RKL_REGISTER_FOR_IPHONE_LOWMEM_NOTIFICATIONS == 1) + +#ifdef _RKL_DTRACE_ENABLED + +// compiledRegexCache(unsigned long eventID, const char *regexUTF8, int options, int captures, int hitMiss, int icuStatusCode, const char *icuErrorMessage, double *hitRate); +// utf16ConversionCache(unsigned long eventID, unsigned int lookupResultFlags, double *hitRate, const void *string, unsigned long NSRange.location, unsigned long [NSRange length], long length); + +/* +provider RegexKitLite { + probe compiledRegexCache(unsigned long, const char *, unsigned int, int, int, int, const char *, double *); + probe utf16ConversionCache(unsigned long, unsigned int, double *, const void *, unsigned long, unsigned long, long); +}; + +#pragma D attributes Unstable/Unstable/Common provider RegexKitLite provider +#pragma D attributes Private/Private/Common provider RegexKitLite module +#pragma D attributes Private/Private/Common provider RegexKitLite function +#pragma D attributes Unstable/Unstable/Common provider RegexKitLite name +#pragma D attributes Unstable/Unstable/Common provider RegexKitLite args +*/ + +#define REGEXKITLITE_STABILITY "___dtrace_stability$RegexKitLite$v1$4_4_5_1_1_5_1_1_5_4_4_5_4_4_5" +#define REGEXKITLITE_TYPEDEFS "___dtrace_typedefs$RegexKitLite$v1" +#define REGEXKITLITE_COMPILEDREGEXCACHE(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { __asm__ volatile(".reference " REGEXKITLITE_TYPEDEFS); __dtrace_probe$RegexKitLite$compiledRegexCache$v1$756e7369676e6564206c6f6e67$63686172202a$756e7369676e656420696e74$696e74$696e74$696e74$63686172202a$646f75626c65202a(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); __asm__ volatile(".reference " REGEXKITLITE_STABILITY); } +#define REGEXKITLITE_COMPILEDREGEXCACHE_ENABLED() __dtrace_isenabled$RegexKitLite$compiledRegexCache$v1() +#define REGEXKITLITE_CONVERTEDSTRINGU16CACHE(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { __asm__ volatile(".reference " REGEXKITLITE_TYPEDEFS); __dtrace_probe$RegexKitLite$utf16ConversionCache$v1$756e7369676e6564206c6f6e67$756e7369676e656420696e74$646f75626c65202a$766f6964202a$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$6c6f6e67(arg0, arg1, arg2, arg3, arg4, arg5, arg6); __asm__ volatile(".reference " REGEXKITLITE_STABILITY); } +#define REGEXKITLITE_CONVERTEDSTRINGU16CACHE_ENABLED() __dtrace_isenabled$RegexKitLite$utf16ConversionCache$v1() + +extern void __dtrace_probe$RegexKitLite$compiledRegexCache$v1$756e7369676e6564206c6f6e67$63686172202a$756e7369676e656420696e74$696e74$696e74$696e74$63686172202a$646f75626c65202a(unsigned long, const char *, unsigned int, int, int, int, const char *, double *); +extern int __dtrace_isenabled$RegexKitLite$compiledRegexCache$v1(void); +extern void __dtrace_probe$RegexKitLite$utf16ConversionCache$v1$756e7369676e6564206c6f6e67$756e7369676e656420696e74$646f75626c65202a$766f6964202a$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$6c6f6e67(unsigned long, unsigned int, double *, const void *, unsigned long, unsigned long, long); +extern int __dtrace_isenabled$RegexKitLite$utf16ConversionCache$v1(void); + +//////////////////////////// + +enum { + RKLCacheHitLookupFlag = 1 << 0, + RKLConversionRequiredLookupFlag = 1 << 1, + RKLSetTextLookupFlag = 1 << 2, + RKLDynamicBufferLookupFlag = 1 << 3, + RKLErrorLookupFlag = 1 << 4, +}; + +#define rkl_dtrace_addLookupFlag(a,b) do { a |= (unsigned int)(b); } while(0) + +static char rkl_dtrace_regexUTF8[(RKL_CACHE_SIZE) + 1][(RKL_DTRACE_REGEXUTF8_SIZE)]; +static NSUInteger rkl_dtrace_eventID, rkl_dtrace_compiledCacheLookups, rkl_dtrace_compiledCacheHits, rkl_dtrace_conversionBufferLookups, rkl_dtrace_conversionBufferHits; + +#define rkl_dtrace_incrementEventID() do { rkl_dtrace_eventID++; } while(0) +#define rkl_dtrace_compiledRegexCache(a0, a1, a2, a3, a4, a5) do { int _a3 = (a3); rkl_dtrace_compiledCacheLookups++; if(_a3 == 1) { rkl_dtrace_compiledCacheHits++; } if(RKL_EXPECTED(REGEXKITLITE_COMPILEDREGEXCACHE_ENABLED(), 0L)) { double hitRate = 0.0; if(rkl_dtrace_compiledCacheLookups > 0UL) { hitRate = ((double)rkl_dtrace_compiledCacheHits / (double)rkl_dtrace_compiledCacheLookups) * 100.0; } REGEXKITLITE_COMPILEDREGEXCACHE(rkl_dtrace_eventID, a0, a1, a2, _a3, a4, a5, &hitRate); } } while(0) +#define rkl_dtrace_utf16ConversionCache(a0, a1, a2, a3, a4) do { unsigned int _a0 = (a0); if((_a0 & RKLConversionRequiredLookupFlag) != 0U) { rkl_dtrace_conversionBufferLookups++; if((_a0 & RKLCacheHitLookupFlag) != 0U) { rkl_dtrace_conversionBufferHits++; } } if(RKL_EXPECTED(REGEXKITLITE_CONVERTEDSTRINGU16CACHE_ENABLED(), 0L)) { double hitRate = 0.0; if(rkl_dtrace_conversionBufferLookups > 0UL) { hitRate = ((double)rkl_dtrace_conversionBufferHits / (double)rkl_dtrace_conversionBufferLookups) * 100.0; } REGEXKITLITE_CONVERTEDSTRINGU16CACHE(rkl_dtrace_eventID, _a0, &hitRate, a1, a2, a3, a4); } } while(0) + + +// \342\200\246 == UTF8 for HORIZONTAL ELLIPSIS, aka triple dots '...' +#define RKL_UTF8_ELLIPSE "\342\200\246" + +// rkl_dtrace_getRegexUTF8 will copy the str argument to utf8Buffer using UTF8 as the string encoding. +// If the utf8 encoding would take up more bytes than the utf8Buffers length, then the unicode character 'HORIZONTAL ELLIPSIS' ('...') is appened to indicate truncation occured. +static void rkl_dtrace_getRegexUTF8(CFStringRef str, char *utf8Buffer) RKL_NONNULL_ARGS(2); +static void rkl_dtrace_getRegexUTF8(CFStringRef str, char *utf8Buffer) { + if((str == NULL) || (utf8Buffer == NULL)) { return; } + CFIndex maxLength = ((CFIndex)(RKL_DTRACE_REGEXUTF8_SIZE) - 2L), maxBytes = (maxLength - (CFIndex)sizeof(RKL_UTF8_ELLIPSE) - 1L), stringU16Length = CFStringGetLength(str), usedBytes = 0L; + CFStringGetBytes(str, CFMakeRange(0L, ((stringU16Length < maxLength) ? stringU16Length : maxLength)), kCFStringEncodingUTF8, (UInt8)'?', (Boolean)0, (UInt8 *)utf8Buffer, maxBytes, &usedBytes); + if(usedBytes == maxBytes) { strncpy(utf8Buffer + usedBytes, RKL_UTF8_ELLIPSE, ((size_t)(RKL_DTRACE_REGEXUTF8_SIZE) - (size_t)usedBytes) - 2UL); } else { utf8Buffer[usedBytes] = (char)0; } +} + +#else // _RKL_DTRACE_ENABLED + +#define rkl_dtrace_incrementEventID() +#define rkl_dtrace_compiledRegexCache(a0, a1, a2, a3, a4, a5) +#define rkl_dtrace_utf16ConversionCache(a0, a1, a2, a3, a4) +#define rkl_dtrace_getRegexUTF8(str, buf) +#define rkl_dtrace_addLookupFlag(a,b) + +#endif // _RKL_DTRACE_ENABLED + +//////////// +#pragma mark - +#pragma mark RegexKitLite low-level internal functions + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called with cacheSpinLock already locked! +// ---------- + +static RKLCacheSlot *rkl_getCachedRegex(NSString *regexString, RKLRegexOptions options, NSError **error, id *exception) { + RKLCacheSlot *cacheSlot = NULL; + CFHashCode regexHash = 0UL; + int32_t status = 0; + + RKLCDelayedAssert((cacheSpinLock != 0) && (regexString != NULL), exception, exitNow); + + // Fast path the common case where this regex is exactly the same one used last time. + // The pointer equality test is valid under these circumstances since the cacheSlot->regexString is an immutable copy. + // If the regexString argument is mutable, this test will fail, and we'll use the the slow path cache check below. + if(RKL_EXPECTED(lastCacheSlot != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->options == options, 1L) && RKL_EXPECTED(lastCacheSlot->icu_regex != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->regexString != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->regexString == (CFStringRef)regexString, 1L)) { + rkl_dtrace_compiledRegexCache(&rkl_dtrace_regexUTF8[(lastCacheSlot - &rkl_cacheSlots[0])][0], lastCacheSlot->options, (int)lastCacheSlot->captureCount, 1, 0, NULL); + return(lastCacheSlot); + } + + lastCacheSlot = NULL; + regexHash = CFHash((CFTypeRef)regexString); + cacheSlot = &rkl_cacheSlots[(regexHash % (CFHashCode)(RKL_CACHE_SIZE))]; // Retrieve the cache slot for this regex. + + // Return the cached entry if it's a match, otherwise clear the slot and create a new ICU regex in its place. + // If regexString is mutable, the pointer equality test will fail, and CFEqual() is used to determine true + // equality with the immutable cacheSlot copy. CFEqual() performs a slow character by character check. + if(RKL_EXPECTED(cacheSlot->options == options, 1L) && RKL_EXPECTED(cacheSlot->icu_regex != NULL, 1L) && RKL_EXPECTED(cacheSlot->regexString != NULL, 1L) && (RKL_EXPECTED(cacheSlot->regexString == (CFStringRef)regexString, 1L) || RKL_EXPECTED(CFEqual((CFTypeRef)regexString, (CFTypeRef)cacheSlot->regexString) == YES, 1L))) { + lastCacheSlot = cacheSlot; + rkl_dtrace_compiledRegexCache(&rkl_dtrace_regexUTF8[(lastCacheSlot - &rkl_cacheSlots[0])][0], lastCacheSlot->options, (int)lastCacheSlot->captureCount, 1, 0, NULL); + return(cacheSlot); + } + + rkl_clearCacheSlotRegex(cacheSlot); + + if(RKL_EXPECTED((cacheSlot->regexString = CFStringCreateCopy(NULL, (CFStringRef)regexString)) == NULL, 0L)) { goto exitNow; } ; // Get a cheap immutable copy. + rkl_dtrace_getRegexUTF8(cacheSlot->regexString, &rkl_dtrace_regexUTF8[(cacheSlot - &rkl_cacheSlots[0])][0]); + cacheSlot->options = options; + + CFIndex regexStringU16Length = CFStringGetLength(cacheSlot->regexString); // In UTF16 code units. + UParseError parseError = (UParseError){-1, -1, {0}, {0}}; + const UniChar *regexUniChar = NULL; + + if(RKL_EXPECTED(regexStringU16Length >= (CFIndex)INT_MAX, 0L)) { *exception = [NSException exceptionWithName:NSRangeException reason:@"Regex string length exceeds INT_MAX" userInfo:NULL]; goto exitNow; } + + // Try to quickly obtain regexString in UTF16 format. + if((regexUniChar = CFStringGetCharactersPtr(cacheSlot->regexString)) == NULL) { // We didn't get the UTF16 pointer quickly and need to perform a full conversion in a temp buffer. + UniChar *uniCharBuffer = NULL; + if(((size_t)regexStringU16Length * sizeof(UniChar)) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((uniCharBuffer = (UniChar *)alloca( (size_t)regexStringU16Length * sizeof(UniChar) )) == NULL, 0L)) { goto exitNow; } } // Try to use the stack. + else { if(RKL_EXPECTED((uniCharBuffer = (UniChar *)rkl_realloc(&scratchBuffer[0], (size_t)regexStringU16Length * sizeof(UniChar), 0UL)) == NULL, 0L)) { goto exitNow; } } // Otherwise use the heap. + CFStringGetCharacters(cacheSlot->regexString, CFMakeRange(0L, regexStringU16Length), uniCharBuffer); // Convert regexString to UTF16. + regexUniChar = uniCharBuffer; + } + + // Create the ICU regex. + if(RKL_EXPECTED((cacheSlot->icu_regex = RKL_ICU_FUNCTION_APPEND(uregex_open)(regexUniChar, (int32_t)regexStringU16Length, options, &parseError, &status)) == NULL, 0L)) { goto exitNow; } + if(RKL_EXPECTED(status <= U_ZERO_ERROR, 1L)) { cacheSlot->captureCount = (NSInteger)RKL_ICU_FUNCTION_APPEND(uregex_groupCount)(cacheSlot->icu_regex, &status); } + if(RKL_EXPECTED(status <= U_ZERO_ERROR, 1L)) { lastCacheSlot = cacheSlot; } + +exitNow: + if(RKL_EXPECTED(scratchBuffer[0] != NULL, 0L)) { scratchBuffer[0] = rkl_free(&scratchBuffer[0]); } + if(RKL_EXPECTED(status > U_ZERO_ERROR, 0L)) { rkl_clearCacheSlotRegex(cacheSlot); cacheSlot = NULL; if(error != NULL) { *error = rkl_NSErrorForRegex(regexString, options, &parseError, status); } } + +#ifdef _RKL_DTRACE_ENABLED + if(RKL_EXPECTED(cacheSlot != NULL, 1L)) { rkl_dtrace_compiledRegexCache(&rkl_dtrace_regexUTF8[(cacheSlot - &rkl_cacheSlots[0])][0], cacheSlot->options, (int)cacheSlot->captureCount, 0, status, NULL); } + else { char regexUTF8[(RKL_DTRACE_REGEXUTF8_SIZE)]; const char *err = NULL; if(status != U_ZERO_ERROR) { err = RKL_ICU_FUNCTION_APPEND(u_errorName)(status); } rkl_dtrace_getRegexUTF8((CFStringRef)regexString, regexUTF8); rkl_dtrace_compiledRegexCache(regexUTF8, options, -1, -1, status, err); } +#endif // _RKL_DTRACE_ENABLED + + return(cacheSlot); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called with cacheSpinLock already locked! +// ---------- + +static NSUInteger rkl_setCacheSlotToString(RKLCacheSlot *cacheSlot, const NSRange *range, int32_t *status, id *exception RKL_UNUSED_ASSERTION_ARG) { + RKLCDelayedAssert((cacheSlot != NULL) && (cacheSlot->setToString != NULL) && ((range != NULL) && (NSEqualRanges(*range, NSNotFoundRange) == NO)) && (status != NULL), exception, exitNow); + const UniChar *stringUniChar = NULL; +#ifdef _RKL_DTRACE_ENABLED + unsigned int lookupResultFlags = 0U; +#endif + + if(cacheSlot->setToNeedsConversion == 0U) { + if(RKL_EXPECTED((stringUniChar = CFStringGetCharactersPtr(cacheSlot->setToString)) == NULL, 0L)) { cacheSlot->setToNeedsConversion = 1U; } + else { if(RKL_EXPECTED(cacheSlot->setToUniChar != stringUniChar, 0L)) { cacheSlot->setToRange = NSNotFoundRange; cacheSlot->setToUniChar = stringUniChar; } goto setRegexText; } + } + rkl_dtrace_addLookupFlag(lookupResultFlags, RKLConversionRequiredLookupFlag); + + NSUInteger useFixedBuffer = (cacheSlot->setToLength < (CFIndex)(RKL_FIXED_LENGTH)) ? 1UL : 0UL; + RKLBuffer *buffer = useFixedBuffer ? &fixedBuffer : &dynamicBuffer; + rkl_dtrace_addLookupFlag(lookupResultFlags, (useFixedBuffer ? 0U : RKLDynamicBufferLookupFlag)); + + if((cacheSlot->setToUniChar != NULL) && ((cacheSlot->setToString == buffer->string) || ((cacheSlot->setToLength == buffer->length) && (cacheSlot->setToHash == buffer->hash)))) { rkl_dtrace_addLookupFlag(lookupResultFlags, RKLCacheHitLookupFlag); goto setRegexText; } + + if(RKL_EXPECTED((stringUniChar = CFStringGetCharactersPtr(cacheSlot->setToString)) != NULL, 0L)) { cacheSlot->setToNeedsConversion = 0U; cacheSlot->setToRange = NSNotFoundRange; cacheSlot->setToUniChar = stringUniChar; goto setRegexText; } + + rkl_clearBuffer(buffer, 0UL); + + if(useFixedBuffer == 0U) { + RKLCDelayedAssert(buffer == &dynamicBuffer, exception, exitNow); + RKL_STRONG_REF void *p = (RKL_STRONG_REF void *)dynamicBuffer.uniChar; + if(RKL_EXPECTED((dynamicBuffer.uniChar = (RKL_STRONG_REF UniChar *)rkl_realloc(&p, ((size_t)cacheSlot->setToLength * sizeof(UniChar)), 0UL)) == NULL, 0L)) { goto exitNow; } // Resize the buffer. + } + + RKLCDelayedAssert(buffer->uniChar != NULL, exception, exitNow); + CFStringGetCharacters(cacheSlot->setToString, CFMakeRange(0L, cacheSlot->setToLength), (UniChar *)buffer->uniChar); // Convert to a UTF16 string. + + RKLCDelayedAssert(buffer->string == NULL, exception, exitNow); + if(RKL_EXPECTED((buffer->string = (CFStringRef)CFRetain((CFTypeRef)cacheSlot->setToString)) == NULL, 0L)) { goto exitNow; } + buffer->hash = cacheSlot->setToHash; + buffer->length = cacheSlot->setToLength; + + cacheSlot->setToUniChar = buffer->uniChar; + cacheSlot->setToRange = NSNotFoundRange; + +setRegexText: + if(NSEqualRanges(cacheSlot->setToRange, *range) == NO) { + RKLCDelayedAssert((cacheSlot->icu_regex != NULL) && (cacheSlot->setToUniChar != NULL) && (NSMaxRange(*range) <= (NSUInteger)cacheSlot->setToLength) && (cacheSlot->setToRange.length <= INT_MAX), exception, exitNow); + cacheSlot->lastFindRange = cacheSlot->lastMatchRange = NSNotFoundRange; + cacheSlot->setToRange = *range; + RKL_ICU_FUNCTION_APPEND(uregex_setText)(cacheSlot->icu_regex, cacheSlot->setToUniChar + cacheSlot->setToRange.location, (int32_t)cacheSlot->setToRange.length, status); + rkl_dtrace_addLookupFlag(lookupResultFlags, RKLSetTextLookupFlag); + if(RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto exitNow; } + } + + rkl_dtrace_utf16ConversionCache(lookupResultFlags, cacheSlot->setToString, cacheSlot->setToRange.location, cacheSlot->setToRange.length, cacheSlot->setToLength); + return(1UL); + +exitNow: + return(0UL); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called with cacheSpinLock already locked! +// ---------- + +static RKLCacheSlot *rkl_getCachedRegexSetToString(NSString *regexString, RKLRegexOptions options, NSString *matchString, NSUInteger *matchLengthPtr, NSRange *matchRange, NSError **error, id *exception, int32_t *status) { + RKLCacheSlot *cacheSlot = NULL; + RKLCDelayedAssert((regexString != NULL) && (exception != NULL) && (status != NULL) && (matchLengthPtr != NULL), exception, exitNow); + + // Fast path the common case where this regex is exactly the same one used last time. + if(RKL_EXPECTED(lastCacheSlot != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->icu_regex != NULL, 1L) && RKL_EXPECTED(lastCacheSlot->regexString == (CFStringRef)regexString, 1L) && RKL_EXPECTED(lastCacheSlot->options == options, 1L)) { cacheSlot = lastCacheSlot; rkl_dtrace_compiledRegexCache(&rkl_dtrace_regexUTF8[(cacheSlot - &rkl_cacheSlots[0])][0], cacheSlot->options, (int)cacheSlot->captureCount, 1, 0, NULL); } + else { lastCacheSlot = NULL; if(RKL_EXPECTED((cacheSlot = rkl_getCachedRegex(regexString, options, error, exception)) == NULL, 0L)) { goto exitNow; } } + RKLCDelayedAssert((cacheSlot != NULL) && (cacheSlot->icu_regex != NULL) && (cacheSlot->regexString != NULL) && (cacheSlot->captureCount >= 0L) && (cacheSlot == lastCacheSlot), exception, exitNow); + + // Optimize the case where the string to search (matchString) is immutable and the setToString immutable copy is the same string with its reference count incremented. + NSUInteger isSetTo = ((cacheSlot->setToString != NULL) && (cacheSlot->setToString == (CFStringRef)matchString)) ? 1UL : 0UL; + CFIndex matchLength = ((isSetTo == 1UL) && (cacheSlot->setToIsImmutable == 1U)) ? cacheSlot->setToLength : CFStringGetLength((CFStringRef)matchString); + + *matchLengthPtr = (NSUInteger)matchLength; + if(matchRange->length == NSUIntegerMax) { matchRange->length = (NSUInteger)matchLength; } // For convenience, allow NSUIntegerMax == string length. + + if(RKL_EXPECTED((NSUInteger)matchLength < NSMaxRange(*matchRange), 0L)) { goto exitNow; } // The match range is out of bounds for the string. performRegexOp will catch and report the problem. + + if((cacheSlot->setToIsImmutable == 0U) && (cacheSlot->setToString != NULL) && ((cacheSlot->setToLength != CFStringGetLength(cacheSlot->setToString)) || (cacheSlot->setToHash != CFHash((CFTypeRef)cacheSlot->setToString)))) { isSetTo = 0UL; } + else { // If the first pointer equality check failed, check the hash and length. + if(((isSetTo == 0UL) || (cacheSlot->setToIsImmutable == 0U)) && (cacheSlot->setToString != NULL)) { isSetTo = ((cacheSlot->setToLength == matchLength) && (cacheSlot->setToHash == CFHash((CFTypeRef)matchString))) ? 1UL : 0UL; } + + if(isSetTo == 1UL) { if(RKL_EXPECTED(rkl_setCacheSlotToString(cacheSlot, matchRange, status, exception) == 0UL, 0L)) { cacheSlot = NULL; if(*exception == NULL) { *exception = (id)RKLCAssertDictionary(@"Failed to set up UTF16 buffer."); } } goto exitNow; } + } + + // Sometimes the range that the regex is set to isn't right, in which case we don't want to clear the cache slot. Otherwise, flush it out. + if((cacheSlot->setToString != NULL) && (isSetTo == 0UL)) { rkl_clearCacheSlotSetTo(cacheSlot); } + + if(cacheSlot->setToString == NULL) { + cacheSlot->setToString = (CFStringRef)CFRetain((CFTypeRef)matchString); + RKLCDelayedAssert(cacheSlot->setToString != NULL, exception, exitNow); + cacheSlot->setToUniChar = CFStringGetCharactersPtr(cacheSlot->setToString); + cacheSlot->setToNeedsConversion = (cacheSlot->setToUniChar == NULL) ? 1U : 0U; + cacheSlot->setToIsImmutable = (rkl_CFStringIsMutable(cacheSlot->setToString) == YES) ? 0U : 1U; // If RKL_FAST_MUTABLE_CHECK is not defined then setToIsImmutable will always be set to '0', or in other words mutable.. + cacheSlot->setToHash = CFHash((CFTypeRef)cacheSlot->setToString); + cacheSlot->setToRange = NSNotFoundRange; + cacheSlot->setToLength = matchLength; + } + + if(RKL_EXPECTED(rkl_setCacheSlotToString(cacheSlot, matchRange, status, exception) == 0UL, 0L)) { cacheSlot = NULL; if(*exception == NULL) { *exception = (id)RKLCAssertDictionary(@"Failed to set up UTF16 buffer."); } goto exitNow; } + +exitNow: + return(cacheSlot); +} + +#ifdef RKL_HAVE_CLEANUP + +// rkl_cleanup_cacheSpinLockStatus takes advantage of GCC's 'cleanup' variable attribute. When an 'auto' variable with the 'cleanup' attribute goes out of scope, +// GCC arranges to have the designated function called. In this case, we make sure that if rkl_cacheSpinLock was locked that it was also unlocked. +// If rkl_cacheSpinLock was locked, but the cacheSpinLockStatus unlocked flag was not set, we force cacheSpinLock unlocked with a call to OSSpinLockUnlock. +// This is not a panacea for preventing mutex usage errors. Old style ObjC exceptions will bypass the cleanup call, but newer C++ style ObjC exceptions should cause the cleanup function to be called during the stack unwind. + +// We do not depend on this cleanup function being called. It is used only as an extra safety net. It is probably a bug in RegexKitLite if it is ever invoked and forced to take some kind of protective action. + +volatile NSUInteger rkl_debugCacheSpinLockCount = 0UL; + +void rkl_debugCacheSpinLock (void) RKL_ATTRIBUTES(used, noinline, visibility("default")); +static void rkl_cleanup_cacheSpinLockStatus (volatile NSUInteger *cacheSpinLockStatusPtr) RKL_ATTRIBUTES(used); + +void rkl_debugCacheSpinLock(void) { + rkl_debugCacheSpinLockCount++; // This is here primarily to prevent the optimizer from optimizing away the function. +} + +static void rkl_cleanup_cacheSpinLockStatus(volatile NSUInteger *cacheSpinLockStatusPtr) { + static NSUInteger didPrintForcedUnlockWarning = 0UL, didPrintNotLockedWarning = 0UL; + NSUInteger cacheSpinLockStatus = *cacheSpinLockStatusPtr; + + if(RKL_EXPECTED((cacheSpinLockStatus & RKLUnlockedCacheSpinLock) == 0UL, 0L) && RKL_EXPECTED((cacheSpinLockStatus & RKLLockedCacheSpinLock) != 0UL, 1L)) { + if(cacheSpinLock != 0) { + if(didPrintForcedUnlockWarning == 0UL) { didPrintForcedUnlockWarning = 1UL; NSLog(@"[RegexKitLite] Unusual condition detected: Recorded that cacheSpinLock was locked, but for some reason it was not unlocked. Forcibly unlocking cacheSpinLock. Set a breakpoint at rkl_debugCacheSpinLock to debug. This warning is only printed once."); } + rkl_debugCacheSpinLock(); // Since this is an unusual condition, offer an attempt to catch it before we unlock. + OSSpinLockUnlock(&cacheSpinLock); + } else { + if(didPrintNotLockedWarning == 0UL) { didPrintNotLockedWarning = 1UL; NSLog(@"[RegexKitLite] Unusual condition detected: Recorded that cacheSpinLock was locked, but for some reason it was not unlocked, yet cacheSpinLock is currently not locked? Set a breakpoint at rkl_debugCacheSpinLock to debug. This warning is only printed once."); } + rkl_debugCacheSpinLock(); + } + } +} + +#endif // RKL_HAVE_CLEANUP + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// ---------- + +static id rkl_performRegexOp(id self, SEL _cmd, RKLRegexOp regexOp, NSString *regexString, RKLRegexOptions options, NSInteger capture, id matchString, NSRange *matchRange, NSString *replacementString, NSError **error, void *result) { + volatile NSUInteger RKL_CLEANUP(rkl_cleanup_cacheSpinLockStatus) cacheSpinLockStatus = 0UL; + + NSUInteger replaceMutable = 0UL; + RKLRegexOp maskedRegexOp = (regexOp & RKLMaskOp); + + if((error != NULL) && (*error != NULL)) { *error = NULL; } + + if(RKL_EXPECTED(regexString == NULL, 0L)) { RKL_RAISE_EXCEPTION(NSInvalidArgumentException, @"The regular expression argument is NULL."); } + if(RKL_EXPECTED(matchString == NULL, 0L)) { RKL_RAISE_EXCEPTION(NSInternalInconsistencyException, @"The match string argument is NULL."); } + if((maskedRegexOp == RKLReplaceOp) && (replacementString == NULL)) { RKL_RAISE_EXCEPTION(NSInvalidArgumentException, @"The replacement string argument is NULL."); } + + id resultObject = NULL, exception = NULL; + int32_t status = U_ZERO_ERROR; + RKLCacheSlot *cacheSlot = NULL; + NSUInteger stringU16Length = 0UL; + NSRange stackRanges[2048]; + RKLFindAll findAll; + + + // IMPORTANT! Once we have obtained the lock, code MUST exit via 'goto exitNow;' to unlock the lock! NO EXCEPTIONS! + // ---------- + OSSpinLockLock(&cacheSpinLock); // Grab the lock and get cache entry. + cacheSpinLockStatus |= RKLLockedCacheSpinLock; + rkl_dtrace_incrementEventID(); + + if(RKL_EXPECTED((cacheSlot = rkl_getCachedRegexSetToString(regexString, options, matchString, &stringU16Length, matchRange, error, &exception, &status)) == NULL, 0L)) { stringU16Length = (NSUInteger)CFStringGetLength((CFStringRef)matchString); } + if(RKL_EXPECTED(matchRange->length == NSUIntegerMax, 1L)) { matchRange->length = stringU16Length; } // For convenience. + if(RKL_EXPECTED(stringU16Length < NSMaxRange(*matchRange), 0L) && RKL_EXPECTED(exception == NULL, 1L)) { exception = (id)RKL_EXCEPTION(NSRangeException, @"Range or index out of bounds"); goto exitNow; } + if(RKL_EXPECTED(stringU16Length >= (NSUInteger)INT_MAX, 0L) && RKL_EXPECTED(exception == NULL, 1L)) { exception = (id)RKL_EXCEPTION(NSRangeException, @"String length exceeds INT_MAX"); goto exitNow; } + if(((maskedRegexOp == RKLRangeOp) || (maskedRegexOp == RKLArrayOfStringsOp)) && RKL_EXPECTED(cacheSlot != NULL, 1L) && (RKL_EXPECTED(capture < 0L, 0L) || RKL_EXPECTED(capture > cacheSlot->captureCount, 0L)) && RKL_EXPECTED(exception == NULL, 1L)) { exception = (id)RKL_EXCEPTION(NSInvalidArgumentException, @"The capture argument is not valid."); goto exitNow; } + if(RKL_EXPECTED(cacheSlot == NULL, 0L) || RKL_EXPECTED(status > U_ZERO_ERROR, 0L) || RKL_EXPECTED(exception != NULL, 0L)) { goto exitNow; } + + RKLCDelayedAssert((cacheSlot != NULL) && (cacheSlot->icu_regex != NULL) && (cacheSlot->regexString != NULL) && (cacheSlot->captureCount >= 0L) && (cacheSlot->setToString != NULL) && (cacheSlot->setToLength >= 0L) && (cacheSlot->setToUniChar != NULL) && ((CFIndex)NSMaxRange(cacheSlot->setToRange) <= cacheSlot->setToLength), &exception, exitNow); + +#ifndef NS_BLOCK_ASSERTIONS + if(cacheSlot->setToNeedsConversion == 0U) { RKLCDelayedAssert((cacheSlot->setToUniChar == CFStringGetCharactersPtr(cacheSlot->setToString)), &exception, exitNow); } + else { + RKLBuffer *buffer = (cacheSlot->setToLength < (CFIndex)(RKL_FIXED_LENGTH)) ? &fixedBuffer : &dynamicBuffer; + RKLCDelayedAssert((cacheSlot->setToHash == buffer->hash) && (cacheSlot->setToLength == buffer->length) && (cacheSlot->setToUniChar == buffer->uniChar), &exception, exitNow); + } +#endif + + switch(maskedRegexOp) { + case RKLRangeOp: + if((rkl_search(cacheSlot, matchRange, 0UL, &exception, &status) == NO) || (RKL_EXPECTED(status > U_ZERO_ERROR, 0L))) { *(NSRange *)result = NSNotFoundRange; goto exitNow; } + if(RKL_EXPECTED(capture == 0L, 1L)) { *(NSRange *)result = cacheSlot->lastMatchRange; } else { if(RKL_EXPECTED(rkl_getRangeForCapture(cacheSlot, &status, (int32_t)capture, (NSRange *)result) > U_ZERO_ERROR, 0L)) { goto exitNow; } } + break; + + case RKLSplitOp: // Fall-thru... + case RKLArrayOfStringsOp: // Fall-thru... + case RKLCapturesArrayOp: // Fall-thru... + case RKLArrayOfCapturesOp: + findAll = rkl_makeFindAll(stackRanges, *matchRange, 2048L, (2048UL * sizeof(NSRange)), 0UL, (void **)&scratchBuffer[0], &scratchBuffer[1], &scratchBuffer[2], 0L, capture, ((maskedRegexOp == RKLCapturesArrayOp) ? 1L : NSIntegerMax)); + + if(RKL_EXPECTED(rkl_findRanges(cacheSlot, regexOp, &findAll, &exception, &status) == NO, 1L)) { + if(RKL_EXPECTED(findAll.found == 0L, 0L)) { resultObject = [NSArray array]; } else { resultObject = rkl_makeArray(cacheSlot, regexOp, &findAll, &exception); } + } + + if(RKL_EXPECTED(scratchBuffer[0] != NULL, 0L)) { scratchBuffer[0] = rkl_free(&scratchBuffer[0]); } + if(RKL_EXPECTED(scratchBuffer[1] != NULL, 0L)) { scratchBuffer[1] = rkl_free(&scratchBuffer[1]); } + if(RKL_EXPECTED(scratchBuffer[2] != NULL, 0L)) { scratchBuffer[2] = rkl_free(&scratchBuffer[2]); } + + break; + + case RKLReplaceOp: resultObject = rkl_replaceString(cacheSlot, matchString, stringU16Length, replacementString, (NSUInteger)CFStringGetLength((CFStringRef)replacementString), (NSUInteger *)result, (replaceMutable = (((regexOp & RKLReplaceMutable) != 0) ? 1UL : 0UL)), &exception, &status); break; + default: exception = RKLCAssertDictionary(@"Unknown regexOp code."); break; + } + +exitNow: + OSSpinLockUnlock(&cacheSpinLock); + cacheSpinLockStatus |= RKLUnlockedCacheSpinLock; + + if(RKL_EXPECTED(status > U_ZERO_ERROR, 0L) && RKL_EXPECTED(exception == NULL, 0L)) { exception = rkl_NSExceptionForRegex(regexString, options, NULL, status); } // If we had a problem, prepare an exception to be thrown. + if(RKL_EXPECTED(exception != NULL, 0L)) { rkl_handleDelayedAssert(self, _cmd, exception); } // If there is an exception, throw it at this point. + // If we're working on a mutable string and there were successful matches/replacements, then we still have work to do. + // This is done outside the cache lock and with the objc replaceCharactersInRange:withString: method because Core Foundation + // does not assert that the string we are attempting to update is actually a mutable string, whereas Foundation ensures + // the object receiving the message is a mutable string and throws an exception if we're attempting to modify an immutable string. + if(RKL_EXPECTED(replaceMutable == 1UL, 0L) && RKL_EXPECTED(*((NSUInteger *)result) > 0UL, 1L)) { NSCParameterAssert(resultObject != NULL); [matchString replaceCharactersInRange:*matchRange withString:resultObject]; } + + return(resultObject); +} + +static void rkl_handleDelayedAssert(id self, SEL _cmd, id exception) { + if(RKL_EXPECTED(exception != NULL, 0L)) { + if([exception isKindOfClass:[NSException class]]) { [[NSException exceptionWithName:[exception name] reason:rkl_stringFromClassAndMethod(self, _cmd, [exception reason]) userInfo:[exception userInfo]] raise]; } + else { + id functionString = [exception objectForKey:@"function"], fileString = [exception objectForKey:@"file"], descriptionString = [exception objectForKey:@"description"], lineNumber = [exception objectForKey:@"line"]; + NSCParameterAssert((functionString != NULL) && (fileString != NULL) && (descriptionString != NULL) && (lineNumber != NULL)); + [[NSAssertionHandler currentHandler] handleFailureInFunction:functionString file:fileString lineNumber:(NSInteger)[lineNumber longValue] description:descriptionString]; + } + } +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_performRegexOp() or rkl_findRanges(). +// ---------- + +static NSUInteger rkl_search(RKLCacheSlot *cacheSlot, NSRange *searchRange, NSUInteger updateSearchRange, id *exception RKL_UNUSED_ASSERTION_ARG, int32_t *status) { + NSUInteger foundMatch = 0UL, searchEqualsEndOfRange = (RKL_EXPECTED(NSEqualRanges(*searchRange, NSMakeRange(NSMaxRange(cacheSlot->setToRange), 0UL)) == YES, 0L) ? 1UL : 0UL); + + if((NSEqualRanges(*searchRange, cacheSlot->lastFindRange) == YES) || (searchEqualsEndOfRange == 1UL)) { foundMatch = (((cacheSlot->lastMatchRange.location == NSNotFound) || (searchEqualsEndOfRange == 1UL)) ? 0UL : 1UL);} + else { // Only perform an expensive 'find' operation iff the current find range is different than the last find range. + NSUInteger findLocation = (searchRange->location - cacheSlot->setToRange.location); + RKLCDelayedAssert(((searchRange->location >= cacheSlot->setToRange.location)) && (NSRangeInsideRange(*searchRange, cacheSlot->setToRange) == YES) && (findLocation < INT_MAX) && (findLocation <= cacheSlot->setToRange.length), exception, exitNow); + + RKL_PREFETCH_UNICHAR(cacheSlot->setToUniChar, searchRange->location); // Spool up the CPU caches. + + // Using uregex_findNext can be a slight performance win. + NSUInteger useFindNext = ((searchRange->location == (NSMaxRange(cacheSlot->lastMatchRange) + (((cacheSlot->lastMatchRange.length == 0UL) && (cacheSlot->lastMatchRange.location < NSMaxRange(cacheSlot->setToRange))) ? 1UL : 0UL))) ? 1UL : 0UL); + + cacheSlot->lastFindRange = *searchRange; + if(RKL_EXPECTED(useFindNext == 0UL, 0L)) { if(RKL_EXPECTED((RKL_ICU_FUNCTION_APPEND(uregex_find) (cacheSlot->icu_regex, (int32_t)findLocation, status) == NO), 0L) || RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto finishedFind; } } + else { if(RKL_EXPECTED((RKL_ICU_FUNCTION_APPEND(uregex_findNext)(cacheSlot->icu_regex, status) == NO), 0L) || RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto finishedFind; } } + foundMatch = 1UL; + + if(RKL_EXPECTED(rkl_getRangeForCapture(cacheSlot, status, 0, &cacheSlot->lastMatchRange) > U_ZERO_ERROR, 0L)) { goto finishedFind; } + RKLCDelayedAssert(NSRangeInsideRange(cacheSlot->lastMatchRange, *searchRange) == YES, exception, exitNow); + } + +finishedFind: + if(RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { foundMatch = 0UL; cacheSlot->lastFindRange = NSNotFoundRange; } + + if(foundMatch == 0UL) { cacheSlot->lastMatchRange = NSNotFoundRange; if(updateSearchRange == 1UL) { *searchRange = NSMakeRange(NSMaxRange(*searchRange), 0UL); } } + else { + RKLCDelayedAssert(NSRangeInsideRange(cacheSlot->lastMatchRange, *searchRange) == YES, exception, exitNow); + if(updateSearchRange == 1UL) { + NSUInteger nextLocation = (NSMaxRange(cacheSlot->lastMatchRange) + (((cacheSlot->lastMatchRange.length == 0UL) && (cacheSlot->lastMatchRange.location < NSMaxRange(cacheSlot->setToRange))) ? 1UL : 0UL)), locationDiff = nextLocation - searchRange->location; + RKLCDelayedAssert((((locationDiff > 0UL) || ((locationDiff == 0UL) && (cacheSlot->lastMatchRange.location == NSMaxRange(cacheSlot->setToRange)))) && (locationDiff <= searchRange->length)), exception, exitNow); + searchRange->location = nextLocation; + searchRange->length -= locationDiff; + } + } + +#ifndef NS_BLOCK_ASSERTIONS +exitNow: +#endif + return(foundMatch); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_doFindOp(). +// ---------- + +static BOOL rkl_findRanges(RKLCacheSlot *cacheSlot, RKLRegexOp regexOp, RKLFindAll *findAll, id *exception, int32_t *status) { + BOOL returnWithError = YES; + RKLCDelayedAssert((((cacheSlot != NULL) && (cacheSlot->icu_regex != NULL) && (cacheSlot->setToUniChar != NULL) && (cacheSlot->captureCount >= 0L) && (cacheSlot->setToRange.location != NSNotFound)) && (status != NULL) && ((findAll != NULL) && (findAll->found == 0L) && ((findAll->capacity >= 0L) && (((findAll->capacity > 0L) || (findAll->size > 0UL)) ? ((findAll->ranges != NULL) && (findAll->capacity > 0L) && (findAll->size > 0UL)) : 1)) && (findAll->rangesScratchBuffer != NULL) && ((findAll->capture >= 0L) && (findAll->capture <= cacheSlot->captureCount)))), exception, exitNow); + + if(RKL_EXPECTED(cacheSlot->setToLength == 0L, 0L) || RKL_EXPECTED(cacheSlot->setToRange.length == 0UL, 0L)) { returnWithError = NO; goto exitNow; } + + NSInteger captureCount = cacheSlot->captureCount; + RKLRegexOp maskedRegexOp = (regexOp & RKLMaskOp); + NSUInteger lastLocation = findAll->findInRange.location; + NSRange searchRange = findAll->findInRange; + + for(findAll->found = 0L; (findAll->found < findAll->findUpTo) && ((findAll->found < findAll->capacity) || (findAll->found == 0L)); findAll->found++) { + NSInteger loopCapture, shouldBreak = 0L; + + if(RKL_EXPECTED(findAll->found >= ((findAll->capacity - ((captureCount + 2L) * 4L)) - 4L), 0L)) { if(RKL_EXPECTED(rkl_growFindRanges(cacheSlot, lastLocation, findAll, exception) == 0UL, 0L)) { goto exitNow; } } + + RKLCDelayedAssert((searchRange.location != NSNotFound) && (NSRangeInsideRange(searchRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(findAll->findInRange, cacheSlot->setToRange) == YES), exception, exitNow); + + // This fixes a 'bug' that is also present in ICU's uregex_split(). 'Bug', in this case, means that the results of a split operation can differ from those that perl's split() creates for the same input. + // "I|at|ice I eat rice" split using the regex "\b\s*" demonstrates the problem. ICU bug http://bugs.icu-project.org/trac/ticket/6826 + // ICU : "", "I", "|", "at", "|", "ice", "", "I", "", "eat", "", "rice" <- Results that RegexKitLite used to produce. + // PERL: "I", "|", "at", "|", "ice", "I", "eat", "rice" <- Results that RegexKitLite now produces. + do { if((rkl_search(cacheSlot, &searchRange, 1UL, exception, status) == NO) || (RKL_EXPECTED(*status > U_ZERO_ERROR, 0L))) { shouldBreak = 1L; } } + while((maskedRegexOp == RKLSplitOp) && RKL_EXPECTED(shouldBreak == 0L, 1L) && RKL_EXPECTED(cacheSlot->lastMatchRange.length == 0UL, 0L) && RKL_EXPECTED((cacheSlot->lastMatchRange.location - lastLocation) == 0UL, 0L)); + if(RKL_EXPECTED(shouldBreak == 1L, 0L)) { break; } + + RKLCDelayedAssert((searchRange.location != NSNotFound) && (NSRangeInsideRange(searchRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(findAll->findInRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(searchRange, findAll->findInRange) == YES), exception, exitNow); + RKLCDelayedAssert((NSRangeInsideRange(cacheSlot->lastFindRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(cacheSlot->lastMatchRange, cacheSlot->setToRange) == YES) && (NSRangeInsideRange(cacheSlot->lastMatchRange, findAll->findInRange) == YES), exception, exitNow); + RKLCDelayedAssert((findAll->ranges != NULL) && (findAll->found >= 0L) && (findAll->capacity >= 0L) && ((findAll->found + (captureCount + 3L) + 1L) < (findAll->capacity - 2L)), exception, exitNow); + + switch(maskedRegexOp) { + case RKLArrayOfStringsOp: + if(findAll->capture == 0L) { findAll->ranges[findAll->found] = cacheSlot->lastMatchRange; } else { if(RKL_EXPECTED(rkl_getRangeForCapture(cacheSlot, status, (int32_t)findAll->capture, &findAll->ranges[findAll->found]) > U_ZERO_ERROR, 0L)) { goto exitNow; } } + break; + + case RKLSplitOp: // Fall-thru... + case RKLCapturesArrayOp: // Fall-thru... + case RKLArrayOfCapturesOp: + findAll->ranges[findAll->found] = ((maskedRegexOp == RKLSplitOp) ? NSMakeRange(lastLocation, cacheSlot->lastMatchRange.location - lastLocation) : cacheSlot->lastMatchRange); + + for(loopCapture = 1L; loopCapture <= captureCount; loopCapture++) { + RKLCDelayedAssert((findAll->found >= 0L) && (findAll->found < (findAll->capacity - 2L)) && (loopCapture < INT_MAX), exception, exitNow); + if(RKL_EXPECTED(rkl_getRangeForCapture(cacheSlot, status, (int32_t)loopCapture, &findAll->ranges[++findAll->found]) > U_ZERO_ERROR, 0L)) { goto exitNow; } + } + break; + + default: if(*exception != NULL) { *exception = RKLCAssertDictionary(@"Unknown regexOp."); } goto exitNow; break; + } + + lastLocation = NSMaxRange(cacheSlot->lastMatchRange); + } + + if(RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto exitNow; } + + RKLCDelayedAssert((findAll->ranges != NULL) && (findAll->found >= 0L) && (findAll->found < (findAll->capacity - 2L)), exception, exitNow); + if((maskedRegexOp == RKLSplitOp) && (lastLocation != NSMaxRange(findAll->findInRange))) { findAll->ranges[findAll->found++] = NSMakeRange(lastLocation, NSMaxRange(findAll->findInRange) - lastLocation); } + + RKLCDelayedAssert((findAll->ranges != NULL) && (findAll->found >= 0L) && (findAll->found < (findAll->capacity - 2L)), exception, exitNow); + returnWithError = NO; + +exitNow: + return(returnWithError); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_findRanges(). +// ---------- + +static NSUInteger rkl_growFindRanges(RKLCacheSlot *cacheSlot, NSUInteger lastLocation, RKLFindAll *findAll, id *exception RKL_UNUSED_ASSERTION_ARG) { + NSUInteger didGrowRanges = 0UL; + RKLCDelayedAssert((((cacheSlot != NULL) && (cacheSlot->captureCount >= 0L)) && ((findAll != NULL) && (findAll->capacity >= 0L) && (findAll->rangesScratchBuffer != NULL) && (findAll->found >= 0L) && (((findAll->capacity > 0L) || (findAll->size > 0UL) || (findAll->ranges != NULL)) ? ((findAll->capacity > 0L) && (findAll->size > 0UL) && (findAll->ranges != NULL) && (((size_t)findAll->capacity * sizeof(NSRange)) == findAll->size)) : 1))), exception, exitNow); + + // Attempt to guesstimate the required capacity based on: the total length needed to search / (length we've searched so far / ranges found so far). + NSInteger newCapacity = (findAll->capacity + (findAll->capacity / 2L)), estimate = (NSInteger)((float)cacheSlot->setToLength / (((float)lastLocation + 1.0f) / ((float)findAll->found + 1.0f))); + newCapacity = (((newCapacity + ((estimate > newCapacity) ? estimate : newCapacity)) / 2L) + ((cacheSlot->captureCount + 2L) * 4L) + 4L); + + NSUInteger needToCopy = ((findAll->ranges != NULL) && (*findAll->rangesScratchBuffer != findAll->ranges)) ? 1UL : 0UL; // If findAll->ranges is set to a stack allocation then we need to manually copy the data from the stack to the new heap allocation. + size_t newSize = ((size_t)newCapacity * sizeof(NSRange)); + NSRange *newRanges = NULL; + + if(RKL_EXPECTED((newRanges = (NSRange *)rkl_realloc((RKL_STRONG_REF void **)findAll->rangesScratchBuffer, newSize, 0UL)) == NULL, 0L)) { findAll->capacity = 0L; findAll->size = 0UL; findAll->ranges = NULL; *findAll->rangesScratchBuffer = rkl_free((RKL_STRONG_REF void **)findAll->rangesScratchBuffer); goto exitNow; } else { didGrowRanges = 1UL; } + if(needToCopy == 1UL) { memcpy(newRanges, findAll->ranges, findAll->size); } // If necessary, copy the existing data to the new heap allocation. + + findAll->capacity = newCapacity; + findAll->size = newSize; + findAll->ranges = newRanges; + +exitNow: + return(didGrowRanges); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_doFindOp(). +// ---------- + +static NSArray *rkl_makeArray(RKLCacheSlot *cacheSlot, RKLRegexOp regexOp, RKLFindAll *findAll, id *exception RKL_UNUSED_ASSERTION_ARG) { + NSUInteger createdStringsCount = 0UL, createdArraysCount = 0UL, transferedStringsCount = 0UL; + id *matchedStrings = NULL, *subcaptureArrays = NULL, emptyString = @""; + NSArray *resultArray = NULL; + + RKLCDelayedAssert((cacheSlot != NULL) && ((findAll != NULL) && (findAll->found >= 0L) && (findAll->stringsScratchBuffer != NULL) && (findAll->arraysScratchBuffer != NULL)), exception, exitNow); + + size_t matchedStringsSize = ((size_t)findAll->found * sizeof(id)); + CFStringRef setToString = cacheSlot->setToString; + + if((findAll->stackUsed + matchedStringsSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((matchedStrings = (id *)alloca(matchedStringsSize)) == NULL, 0L)) { goto exitNow; } findAll->stackUsed += matchedStringsSize; } + else { if(RKL_EXPECTED((matchedStrings = (id *)rkl_realloc(findAll->stringsScratchBuffer, matchedStringsSize, (NSUInteger)RKLScannedOption)) == NULL, 0L)) { goto exitNow; } } + + { // This sub-block (and its local variables) is here for the benefit of the optimizer. + NSUInteger found = (NSUInteger)findAll->found; + const NSRange *rangePtr = findAll->ranges; + id *matchedStringsPtr = matchedStrings; + + for(createdStringsCount = 0UL; createdStringsCount < found; createdStringsCount++) { + NSRange range = *rangePtr++; + if(RKL_EXPECTED(((*matchedStringsPtr++ = RKL_EXPECTED(range.length == 0UL, 0L) ? emptyString : rkl_CreateStringWithSubstring((id)setToString, range)) == NULL), 0L)) { goto exitNow; } + } + } + + NSUInteger arrayCount = createdStringsCount; + id *arrayObjects = matchedStrings; + + if((regexOp & RKLSubcapturesArray) != 0UL) { + RKLCDelayedAssert(((createdStringsCount % ((NSUInteger)cacheSlot->captureCount + 1UL)) == 0UL) && (createdArraysCount == 0UL), exception, exitNow); + + NSUInteger captureCount = ((NSUInteger)cacheSlot->captureCount + 1UL); + NSUInteger subcaptureArraysCount = (createdStringsCount / captureCount); + size_t subcaptureArraysSize = ((size_t)subcaptureArraysCount * sizeof(id)); + + if((findAll->stackUsed + subcaptureArraysSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((subcaptureArrays = (id *)alloca(subcaptureArraysSize)) == NULL, 0L)) { goto exitNow; } findAll->stackUsed += subcaptureArraysSize; } + else { if(RKL_EXPECTED((subcaptureArrays = (id *)rkl_realloc(findAll->arraysScratchBuffer, subcaptureArraysSize, (NSUInteger)RKLScannedOption)) == NULL, 0L)) { goto exitNow; } } + + { // This sub-block (and its local variables) is here for the benefit of the optimizer. + id *subcaptureArraysPtr = subcaptureArrays; + id *matchedStringsPtr = matchedStrings; + + for(createdArraysCount = 0UL; createdArraysCount < subcaptureArraysCount; createdArraysCount++) { + if(RKL_EXPECTED((*subcaptureArraysPtr++ = rkl_CreateArrayWithObjects((void **)matchedStringsPtr, captureCount)) == NULL, 0L)) { goto exitNow; } + matchedStringsPtr += captureCount; + transferedStringsCount += captureCount; + } + } + + RKLCDelayedAssert((transferedStringsCount == createdStringsCount), exception, exitNow); + arrayCount = createdArraysCount; + arrayObjects = subcaptureArrays; + } + + RKLCDelayedAssert((arrayObjects != NULL), exception, exitNow); + resultArray = rkl_CreateAutoreleasedArray((void **)arrayObjects, (NSUInteger)arrayCount); + +exitNow: + if(RKL_EXPECTED(resultArray == NULL, 0L) && (rkl_collectingEnabled() == NO)) { // If we did not create an array then we need to make sure that we release any objects we created. + NSUInteger x; + if(matchedStrings != NULL) { for(x = transferedStringsCount; x < createdStringsCount; x++) { if((matchedStrings[x] != NULL) && (matchedStrings[x] != emptyString)) { matchedStrings[x] = rkl_ReleaseObject(matchedStrings[x]); } } } + if(subcaptureArrays != NULL) { for(x = 0UL; x < createdArraysCount; x++) { if(subcaptureArrays[x] != NULL) { subcaptureArrays[x] = rkl_ReleaseObject(subcaptureArrays[x]); } } } + } + + return(resultArray); +} + +// IMPORTANT! This code is critical path code. Because of this, it has been written for speed, not clarity. +// IMPORTANT! Should only be called from rkl_performRegexOp(). +// ---------- + +static NSString *rkl_replaceString(RKLCacheSlot *cacheSlot, id searchString, NSUInteger searchU16Length, NSString *replacementString, NSUInteger replacementU16Length, NSUInteger *replacedCountPtr, NSUInteger replaceMutable, id *exception, int32_t *status) { + uint64_t searchU16Length64 = (uint64_t)searchU16Length, replacementU16Length64 = (uint64_t)replacementU16Length; + int32_t resultU16Length = 0, tempUniCharBufferU16Capacity = 0; + UniChar *tempUniCharBuffer = NULL; + const UniChar *replacementUniChar = NULL; + id resultObject = NULL; + NSUInteger replacedCount = 0UL; + + if((RKL_EXPECTED(replacementU16Length64 >= (uint64_t)INT_MAX, 0L) || RKL_EXPECTED(((searchU16Length64 / 2ULL) + (replacementU16Length64 * 2ULL)) >= (uint64_t)INT_MAX, 0L))) { *exception = [NSException exceptionWithName:NSRangeException reason:@"Replacement string length exceeds INT_MAX" userInfo:NULL]; goto exitNow; } + + RKLCDelayedAssert((searchU16Length64 < (uint64_t)INT_MAX) && (replacementU16Length64 < (uint64_t)INT_MAX) && (((searchU16Length64 / 2ULL) + (replacementU16Length64 * 2ULL)) < (uint64_t)INT_MAX), exception, exitNow); + + // Zero order approximation of the buffer sizes for holding the replaced string or split strings and split strings pointer offsets. As UTF16 code units. + tempUniCharBufferU16Capacity = (int32_t)(16UL + (searchU16Length + (searchU16Length / 2UL)) + (replacementU16Length * 2UL)); + + // Buffer sizes converted from native units to bytes. + size_t stackSize = 0UL, replacementSize = ((size_t)replacementU16Length * sizeof(UniChar)), tempUniCharBufferSize = ((size_t)tempUniCharBufferU16Capacity * sizeof(UniChar)); + + // For the various buffers we require, we first try to allocate from the stack if we're not over the RKL_STACK_LIMIT. If we are, switch to using the heap for the buffer. + if((stackSize + tempUniCharBufferSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((tempUniCharBuffer = (UniChar *)alloca(tempUniCharBufferSize)) == NULL, 0L)) { goto exitNow; } stackSize += tempUniCharBufferSize; } + else { if(RKL_EXPECTED((tempUniCharBuffer = (UniChar *)rkl_realloc(&scratchBuffer[0], tempUniCharBufferSize, 0UL)) == NULL, 0L)) { goto exitNow; } } + + // Try to get the pointer to the replacement strings UTF16 data. If we can't, allocate some buffer space, then covert to UTF16. + if((replacementUniChar = CFStringGetCharactersPtr((CFStringRef)replacementString)) == NULL) { + UniChar *uniCharBuffer = NULL; + if((stackSize + replacementSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((uniCharBuffer = (UniChar *)alloca(replacementSize)) == NULL, 0L)) { goto exitNow; } stackSize += replacementSize; } + else { if(RKL_EXPECTED((uniCharBuffer = (UniChar *)rkl_realloc(&scratchBuffer[1], replacementSize, 0UL)) == NULL, 0L)) { goto exitNow; } } + CFStringGetCharacters((CFStringRef)replacementString, CFMakeRange(0L, replacementU16Length), uniCharBuffer); // Convert to a UTF16 string. + replacementUniChar = uniCharBuffer; + } + + resultU16Length = rkl_replaceAll(cacheSlot, replacementUniChar, (int32_t)replacementU16Length, tempUniCharBuffer, tempUniCharBufferU16Capacity, &replacedCount, exception, status); + + if(RKL_EXPECTED(*status == U_BUFFER_OVERFLOW_ERROR, 0L)) { // Our buffer guess(es) were too small. Resize the buffers and try again. + tempUniCharBufferSize = ((size_t)(tempUniCharBufferU16Capacity = resultU16Length + 4) * sizeof(UniChar)); + if((stackSize + tempUniCharBufferSize) < (size_t)(RKL_STACK_LIMIT)) { if(RKL_EXPECTED((tempUniCharBuffer = (UniChar *)alloca(tempUniCharBufferSize)) == NULL, 0L)) { goto exitNow; } stackSize += tempUniCharBufferSize; } + else { if(RKL_EXPECTED((tempUniCharBuffer = (UniChar *)rkl_realloc(&scratchBuffer[0], tempUniCharBufferSize, 0UL)) == NULL, 0L)) { goto exitNow; } } + + *status = U_ZERO_ERROR; // Make sure the status var is cleared and try again. + resultU16Length = rkl_replaceAll(cacheSlot, replacementUniChar, (int32_t)replacementU16Length, tempUniCharBuffer, tempUniCharBufferU16Capacity, &replacedCount, exception, status); + } + + if(RKL_EXPECTED(*status > U_ZERO_ERROR, 0L)) { goto exitNow; } // Something went wrong. + + if(resultU16Length == 0) { resultObject = @""; } // Optimize the case where the replaced text length == 0 with a @"" string. + else if(((NSUInteger)resultU16Length == searchU16Length) && (replacedCount == 0UL)) { // Optimize the case where the replacement == original by creating a copy. Very fast if self is immutable. + if(replaceMutable == 0UL) { resultObject = rkl_CFAutorelease(CFStringCreateCopy(NULL, (CFStringRef)searchString)); } // .. but only if this is not replacing a mutable self. + } else { resultObject = rkl_CFAutorelease(CFStringCreateWithCharacters(NULL, tempUniCharBuffer, (CFIndex)resultU16Length)); } // otherwise, create a new string. + + // If replaceMutable == 1UL, we don't do the replacement here. We wait until after we return and unlock the cache lock. + // This is because we may be trying to mutate an immutable string object. + if((replacedCount > 0UL) && (replaceMutable == 1UL)) { // We're working on a mutable string and there were successfull matches with replaced text, so there's work to do. + rkl_clearBuffer((cacheSlot->setToLength < (CFIndex)(RKL_FIXED_LENGTH)) ? &fixedBuffer : &dynamicBuffer, 0UL); + rkl_clearCacheSlotSetTo(cacheSlot); // Flush any cached information about this string since it will mutate. + } + +exitNow: + if(scratchBuffer[0] != NULL) { scratchBuffer[0] = rkl_free(&scratchBuffer[0]); } + if(scratchBuffer[1] != NULL) { scratchBuffer[1] = rkl_free(&scratchBuffer[1]); } + if(replacedCountPtr != NULL) { *replacedCountPtr = replacedCount; } + return(resultObject); +} + +// IMPORTANT! Should only be called from rkl_replaceString(). +// ---------- +// Modified version of the ICU libraries uregex_replaceAll() that keeps count of the number of replacements made. + +static int32_t rkl_replaceAll(RKLCacheSlot *cacheSlot, const UniChar *replacementUniChar, int32_t replacementU16Length, UniChar *replacedUniChar, int32_t replacedU16Capacity, NSUInteger *replacedCount, id *exception RKL_UNUSED_ASSERTION_ARG, int32_t *status) { + NSUInteger replaced = 0UL, bufferOverflowed = 0UL; + int32_t u16Length = 0; + RKLCDelayedAssert((cacheSlot != NULL) && (replacementUniChar != NULL) && (replacedUniChar != NULL) && (status != NULL) && (replacementU16Length >= 0) && (replacedU16Capacity >= 0), exception, exitNow); + + cacheSlot->lastFindRange = cacheSlot->lastMatchRange = NSNotFoundRange; // Clear the cached find information for this regex so a subsequent find works correctly. + RKL_ICU_FUNCTION_APPEND(uregex_reset)(cacheSlot->icu_regex, 0, status); + + // Work around for ICU uregex_reset() bug, see http://bugs.icu-project.org/trac/ticket/6545 + // http://sourceforge.net/tracker/index.php?func=detail&aid=2105213&group_id=204582&atid=990188 + if(RKL_EXPECTED(cacheSlot->setToRange.length == 0L, 0L) && (*status == U_INDEX_OUTOFBOUNDS_ERROR)) { *status = U_ZERO_ERROR; } + + // This loop originally came from ICU source/i18n/uregex.cpp, uregex_replaceAll. + // There is a bug in that code which causes the size of the buffer required for the replaced text to not be calculated correctly. + // This contains a work around using the variable bufferOverflowed. + // ICU bug: http://bugs.icu-project.org/trac/ticket/6656 + // http://sourceforge.net/tracker/index.php?func=detail&aid=2408447&group_id=204582&atid=990188 + while(RKL_ICU_FUNCTION_APPEND(uregex_findNext)(cacheSlot->icu_regex, status)) { + replaced++; + u16Length += RKL_ICU_FUNCTION_APPEND(uregex_appendReplacement)(cacheSlot->icu_regex, replacementUniChar, replacementU16Length, &replacedUniChar, &replacedU16Capacity, status); + if(RKL_EXPECTED(*status == U_BUFFER_OVERFLOW_ERROR, 0L)) { bufferOverflowed = 1UL; *status = U_ZERO_ERROR; } + } + if(RKL_EXPECTED(*status == U_BUFFER_OVERFLOW_ERROR, 0L)) { bufferOverflowed = 1UL; *status = U_ZERO_ERROR; } + u16Length += RKL_ICU_FUNCTION_APPEND(uregex_appendTail)(cacheSlot->icu_regex, &replacedUniChar, &replacedU16Capacity, status); + + if(RKL_EXPECTED(*status == U_ZERO_ERROR, 1L) && RKL_EXPECTED(bufferOverflowed == 1UL, 0L)) { *status = U_BUFFER_OVERFLOW_ERROR; } + if(replacedCount != NULL) { *replacedCount = replaced; } + +#ifndef NS_BLOCK_ASSERTIONS +exitNow: +#endif + return(u16Length); +} + +static NSUInteger rkl_isRegexValid(id self, SEL _cmd, NSString *regex, RKLRegexOptions options, NSInteger *captureCountPtr, NSError **error) { + volatile NSUInteger RKL_CLEANUP(rkl_cleanup_cacheSpinLockStatus) cacheSpinLockStatus = 0UL; + + RKLCacheSlot *cacheSlot = NULL; + NSUInteger gotCacheSlot = 0UL; + NSInteger captureCount = -1L; + id exception = NULL; + + if((error != NULL) && (*error != NULL)) { *error = NULL; } + if(regex == NULL) { RKL_RAISE_EXCEPTION(NSInvalidArgumentException, @"The regular expression argument is NULL."); } + + OSSpinLockLock(&cacheSpinLock); + cacheSpinLockStatus |= RKLLockedCacheSpinLock; + rkl_dtrace_incrementEventID(); + if((cacheSlot = rkl_getCachedRegex(regex, options, error, &exception)) != NULL) { gotCacheSlot = 1UL; captureCount = cacheSlot->captureCount; } + cacheSlot = NULL; + OSSpinLockUnlock(&cacheSpinLock); + cacheSpinLockStatus |= RKLUnlockedCacheSpinLock; + + if(captureCountPtr != NULL) { *captureCountPtr = captureCount; } + if(RKL_EXPECTED(exception != NULL, 0L)) { rkl_handleDelayedAssert(self, _cmd, exception); } + return(gotCacheSlot); +} + +static void rkl_clearStringCache(void) { + NSCParameterAssert(cacheSpinLock != 0); + lastCacheSlot = NULL; + NSUInteger x = 0UL; + for(x = 0UL; x < (NSUInteger)(RKL_SCRATCH_BUFFERS); x++) { if(scratchBuffer[x] != NULL) { scratchBuffer[x] = rkl_free(&scratchBuffer[x]); } } + for(x = 0UL; x < (NSUInteger)(RKL_CACHE_SIZE); x++) { rkl_clearCacheSlotRegex(&rkl_cacheSlots[x]); } + rkl_clearBuffer(&fixedBuffer, 0UL); + rkl_clearBuffer(&dynamicBuffer, 1UL); +} + +static void rkl_clearBuffer(RKLBuffer *buffer, NSUInteger freeDynamicBuffer) { + if(buffer == NULL) { return; } + if((freeDynamicBuffer == 1UL) && (buffer->uniChar != NULL) && (buffer == &dynamicBuffer)) { RKL_STRONG_REF void *p = (RKL_STRONG_REF void *)dynamicBuffer.uniChar; dynamicBuffer.uniChar = (RKL_STRONG_REF UniChar *)rkl_free(&p); } + if(buffer->string != NULL) { CFRelease((CFTypeRef)buffer->string); buffer->string = NULL; } + buffer->length = 0L; + buffer->hash = 0UL; +} + +static void rkl_clearCacheSlotRegex(RKLCacheSlot *cacheSlot) { + if(cacheSlot == NULL) { return; } + if(cacheSlot->setToString != NULL) { rkl_clearCacheSlotSetTo(cacheSlot); } + if(cacheSlot->icu_regex != NULL) { RKL_ICU_FUNCTION_APPEND(uregex_close)(cacheSlot->icu_regex); cacheSlot->icu_regex = NULL; cacheSlot->captureCount = -1L; } + if(cacheSlot->regexString != NULL) { CFRelease((CFTypeRef)cacheSlot->regexString); cacheSlot->regexString = NULL; cacheSlot->options = 0U; } +} + +static void rkl_clearCacheSlotSetTo(RKLCacheSlot *cacheSlot) { + if(cacheSlot == NULL) { return; } + if(cacheSlot->icu_regex != NULL) { int32_t status = 0; RKL_ICU_FUNCTION_APPEND(uregex_setText)(cacheSlot->icu_regex, &emptyUniCharString[0], 0, &status); } + if(cacheSlot->setToString != NULL) { CFRelease((CFTypeRef)cacheSlot->setToString); cacheSlot->setToString = NULL; } + cacheSlot->lastFindRange = cacheSlot->lastMatchRange = cacheSlot->setToRange = NSNotFoundRange; + cacheSlot->setToIsImmutable = cacheSlot->setToNeedsConversion = 0U; + cacheSlot->setToUniChar = NULL; + cacheSlot->setToHash = 0UL; + cacheSlot->setToLength = 0L; +} + +// Helps to keep things tidy. +#define addKeyAndObject(objs, keys, i, k, o) ({id _o=(o), _k=(k); if((_o != NULL) && (_k != NULL)) { objs[i] = _o; keys[i] = _k; i++; } }) + +static NSDictionary *rkl_userInfoDictionary(NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status, ...) { + va_list varArgsList; + va_start(varArgsList, status); + if(regexString == NULL) { va_end(varArgsList); return(NULL); } + + id objects[64], keys[64]; + NSUInteger count = 0UL; + + NSString *errorNameString = [NSString stringWithUTF8String:RKL_ICU_FUNCTION_APPEND(u_errorName)(status)]; + + addKeyAndObject(objects, keys, count, RKLICURegexRegexErrorKey, regexString); + addKeyAndObject(objects, keys, count, RKLICURegexRegexOptionsErrorKey, [NSNumber numberWithUnsignedInt:options]); + addKeyAndObject(objects, keys, count, RKLICURegexErrorCodeErrorKey, [NSNumber numberWithInt:status]); + addKeyAndObject(objects, keys, count, RKLICURegexErrorNameErrorKey, errorNameString); + + if((parseError != NULL) && (parseError->line != -1)) { + NSString *preContextString = [NSString stringWithCharacters:&parseError->preContext[0] length:(NSUInteger)RKL_ICU_FUNCTION_APPEND(u_strlen)(&parseError->preContext[0])]; + NSString *postContextString = [NSString stringWithCharacters:&parseError->postContext[0] length:(NSUInteger)RKL_ICU_FUNCTION_APPEND(u_strlen)(&parseError->postContext[0])]; + + addKeyAndObject(objects, keys, count, RKLICURegexLineErrorKey, [NSNumber numberWithInt:parseError->line]); + addKeyAndObject(objects, keys, count, RKLICURegexOffsetErrorKey, [NSNumber numberWithInt:parseError->offset]); + addKeyAndObject(objects, keys, count, RKLICURegexPreContextErrorKey, preContextString); + addKeyAndObject(objects, keys, count, RKLICURegexPostContextErrorKey, postContextString); + addKeyAndObject(objects, keys, count, @"NSLocalizedFailureReason", ([NSString stringWithFormat:@"The error %@ occurred at line %d, column %d: %@<>%@", errorNameString, parseError->line, parseError->offset, preContextString, postContextString])); + } else { + addKeyAndObject(objects, keys, count, @"NSLocalizedFailureReason", ([NSString stringWithFormat:@"The error %@ occurred.", errorNameString])); + } + + while(count < 62UL) { id obj = va_arg(varArgsList, id), key = va_arg(varArgsList, id); if((obj != NULL) && (key != NULL)) { addKeyAndObject(objects, keys, count, key, obj); } else { break; } } + va_end(varArgsList); + + return([NSDictionary dictionaryWithObjects:&objects[0] forKeys:&keys[0] count:count]); +} + +static NSError *rkl_NSErrorForRegex(NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status) { + return([NSError errorWithDomain:RKLICURegexErrorDomain code:(NSInteger)status userInfo:rkl_userInfoDictionary(regexString, options, parseError, status, @"There was an error compiling the regular expression.", @"NSLocalizedDescription", NULL)]); +} + +static NSException *rkl_NSExceptionForRegex(NSString *regexString, RKLRegexOptions options, const UParseError *parseError, int32_t status) { + return([NSException exceptionWithName:RKLICURegexException reason:[NSString stringWithFormat:@"ICU regular expression error #%d, %s", status, RKL_ICU_FUNCTION_APPEND(u_errorName)(status)] userInfo:rkl_userInfoDictionary(regexString, options, parseError, status, NULL)]); +} + +static NSDictionary *rkl_makeAssertDictionary(const char *function, const char *file, int line, NSString *format, ...) { + va_list varArgsList; + va_start(varArgsList, format); + NSString *formatString = [[[NSString alloc] initWithFormat:format arguments:varArgsList] autorelease]; + va_end(varArgsList); + NSString *functionString = [NSString stringWithUTF8String:function], *fileString = [NSString stringWithUTF8String:file]; + return([NSDictionary dictionaryWithObjectsAndKeys:formatString, @"description", functionString, @"function", fileString, @"file", [NSNumber numberWithInt:line], @"line", NSInternalInconsistencyException, @"exceptionName", NULL]); +} + +static NSString *rkl_stringFromClassAndMethod(id object, SEL selector, NSString *format, ...) { + va_list varArgsList; + va_start(varArgsList, format); + NSString *formatString = [[[NSString alloc] initWithFormat:format arguments:varArgsList] autorelease]; + va_end(varArgsList); + Class objectsClass = [object class]; + return([NSString stringWithFormat:@"*** %c[%@ %@]: %@", (object == objectsClass) ? '+' : '-', NSStringFromClass(objectsClass), NSStringFromSelector(selector), formatString]); +} + +#pragma mark - +#pragma mark Objective-C Public Interface +#pragma mark - + +@implementation NSString (RegexKitLiteAdditions) + +#pragma mark +clearStringCache + ++ (void)RKL_METHOD_PREPEND(clearStringCache) +{ + volatile NSUInteger RKL_CLEANUP(rkl_cleanup_cacheSpinLockStatus) cacheSpinLockStatus = 0UL; + OSSpinLockLock(&cacheSpinLock); + cacheSpinLockStatus |= RKLLockedCacheSpinLock; + rkl_clearStringCache(); + OSSpinLockUnlock(&cacheSpinLock); + cacheSpinLockStatus |= RKLUnlockedCacheSpinLock; +} + +#pragma mark +captureCountForRegex: + ++ (NSInteger)RKL_METHOD_PREPEND(captureCountForRegex):(NSString *)regex +{ + NSInteger captureCount = -1L; + rkl_isRegexValid(self, _cmd, regex, RKLNoOptions, &captureCount, NULL); + return(captureCount); +} + ++ (NSInteger)RKL_METHOD_PREPEND(captureCountForRegex):(NSString *)regex options:(RKLRegexOptions)options error:(NSError **)error +{ + NSInteger captureCount = -1L; + rkl_isRegexValid(self, _cmd, regex, options, &captureCount, error); + return(captureCount); +} + +#pragma mark -captureCount: + +- (NSInteger)RKL_METHOD_PREPEND(captureCount) +{ + NSInteger captureCount = -1L; + rkl_isRegexValid(self, _cmd, self, RKLNoOptions, &captureCount, NULL); + return(captureCount); +} + +- (NSInteger)RKL_METHOD_PREPEND(captureCountWithOptions):(RKLRegexOptions)options error:(NSError **)error +{ + NSInteger captureCount = -1L; + rkl_isRegexValid(self, _cmd, self, options, &captureCount, error); + return(captureCount); +} + +#pragma mark -componentsSeparatedByRegex: + +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex +{ + NSRange range = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLSplitOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex range:(NSRange)range +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLSplitOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsSeparatedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLSplitOp, regex, options, 0L, self, &range, NULL, error, NULL)); +} + +#pragma mark -isMatchedByRegex: + +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex +{ + NSRange result = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &result); + return((result.location == NSNotFound) ? NO : YES); +} + +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex inRange:(NSRange)range +{ + NSRange result = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &result); + return((result.location == NSNotFound) ? NO : YES); +} + +- (BOOL)RKL_METHOD_PREPEND(isMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range error:(NSError **)error +{ + NSRange result = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, options, 0L, self, &range, NULL, error, &result); + return((result.location == NSNotFound) ? NO : YES); +} + +#pragma mark -isRegexValid + +- (BOOL)RKL_METHOD_PREPEND(isRegexValid) +{ + return(rkl_isRegexValid(self, _cmd, self, RKLNoOptions, NULL, NULL) == 1UL ? YES : NO); +} + +- (BOOL)RKL_METHOD_PREPEND(isRegexValidWithOptions):(RKLRegexOptions)options error:(NSError **)error +{ + return(rkl_isRegexValid(self, _cmd, self, options, NULL, error) == 1UL ? YES : NO); +} + +#pragma mark -flushCachedRegexData + +- (void)RKL_METHOD_PREPEND(flushCachedRegexData) +{ + volatile NSUInteger RKL_CLEANUP(rkl_cleanup_cacheSpinLockStatus) cacheSpinLockStatus = 0UL; + + CFIndex selfLength = CFStringGetLength((CFStringRef)self); + CFHashCode selfHash = CFHash((CFTypeRef)self); + + OSSpinLockLock(&cacheSpinLock); + cacheSpinLockStatus |= RKLLockedCacheSpinLock; + rkl_dtrace_incrementEventID(); + + NSUInteger slot; + for(slot = 0UL; slot < (NSUInteger)(RKL_CACHE_SIZE); slot++) { + RKLCacheSlot *cacheSlot = &rkl_cacheSlots[slot]; + if((cacheSlot->setToString != NULL) && ( (cacheSlot->setToString == (CFStringRef)self) || ((cacheSlot->setToLength == selfLength) && (cacheSlot->setToHash == selfHash)) ) ) { rkl_clearCacheSlotSetTo(cacheSlot); } + } + + RKLBuffer *buffer = (selfLength < (CFIndex)(RKL_FIXED_LENGTH)) ? &fixedBuffer : &dynamicBuffer; + if((buffer->string != NULL) && ((buffer->string == (CFStringRef)self) || ((buffer->length == selfLength) && (buffer->hash == selfHash)))) { rkl_clearBuffer(buffer, 0UL); } + + OSSpinLockUnlock(&cacheSpinLock); + cacheSpinLockStatus |= RKLUnlockedCacheSpinLock; +} + +#pragma mark -rangeOfRegex: + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex +{ + NSRange result = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &result); + return(result); +} + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex capture:(NSInteger)capture +{ + NSRange result = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, capture, self, &range, NULL, NULL, &result); + return(result); +} + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex inRange:(NSRange)range +{ + NSRange result = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &result); + return(result); +} + +- (NSRange)RKL_METHOD_PREPEND(rangeOfRegex):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range capture:(NSInteger)capture error:(NSError **)error +{ + NSRange result = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, options, capture, self, &range, NULL, error, &result); + return(result); +} + +#pragma mark -stringByMatching: + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex +{ + NSRange matchedRange = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &matchedRange); + return((matchedRange.location == NSNotFound) ? NULL : rkl_CFAutorelease(CFStringCreateWithSubstring(NULL, (CFStringRef)self, CFMakeRange(matchedRange.location, matchedRange.length)))); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex capture:(NSInteger)capture +{ + NSRange matchedRange = NSNotFoundRange, range = NSMaxiumRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, capture, self, &range, NULL, NULL, &matchedRange); + return((matchedRange.location == NSNotFound) ? NULL : rkl_CFAutorelease(CFStringCreateWithSubstring(NULL, (CFStringRef)self, CFMakeRange(matchedRange.location, matchedRange.length)))); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex inRange:(NSRange)range +{ + NSRange matchedRange = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, &matchedRange); + return((matchedRange.location == NSNotFound) ? NULL : rkl_CFAutorelease(CFStringCreateWithSubstring(NULL, (CFStringRef)self, CFMakeRange(matchedRange.location, matchedRange.length)))); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByMatching):(NSString *)regex options:(RKLRegexOptions)options inRange:(NSRange)range capture:(NSInteger)capture error:(NSError **)error +{ + NSRange matchedRange = NSNotFoundRange; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLRangeOp, regex, options, capture, self, &range, NULL, error, &matchedRange); + return((matchedRange.location == NSNotFound) ? NULL : rkl_CFAutorelease(CFStringCreateWithSubstring(NULL, (CFStringRef)self, CFMakeRange(matchedRange.location, matchedRange.length)))); +} + +#pragma mark -stringByReplacingOccurrencesOfRegex: + +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLReplaceOp, regex, RKLNoOptions, 0L, self, &searchRange, replacement, NULL, NULL)); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement range:(NSRange)searchRange +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLReplaceOp, regex, RKLNoOptions, 0L, self, &searchRange, replacement, NULL, NULL)); +} + +- (NSString *)RKL_METHOD_PREPEND(stringByReplacingOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement options:(RKLRegexOptions)options range:(NSRange)searchRange error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLReplaceOp, regex, options, 0L, self, &searchRange, replacement, error, NULL)); +} + +#pragma mark -componentsMatchedByRegex: + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLArrayOfStringsOp, regex, RKLNoOptions, 0L, self, &searchRange, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex capture:(NSInteger)capture +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLArrayOfStringsOp, regex, RKLNoOptions, capture, self, &searchRange, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex range:(NSRange)range +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLArrayOfStringsOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(componentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range capture:(NSInteger)capture error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLArrayOfStringsOp, regex, options, capture, self, &range, NULL, error, NULL)); +} + +#pragma mark -captureComponentsMatchedByRegex: + +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLCapturesArrayOp, regex, RKLNoOptions, 0L, self, &searchRange, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex range:(NSRange)range +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLCapturesArrayOp, regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(captureComponentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)RKLCapturesArrayOp, regex, options, 0L, self, &range, NULL, error, NULL)); +} + +#pragma mark -arrayOfCaptureComponentsMatchedByRegex: + +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex +{ + NSRange searchRange = NSMaxiumRange; + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLArrayOfCapturesOp | RKLSubcapturesArray), regex, RKLNoOptions, 0L, self, &searchRange, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex range:(NSRange)range +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLArrayOfCapturesOp | RKLSubcapturesArray), regex, RKLNoOptions, 0L, self, &range, NULL, NULL, NULL)); +} + +- (NSArray *)RKL_METHOD_PREPEND(arrayOfCaptureComponentsMatchedByRegex):(NSString *)regex options:(RKLRegexOptions)options range:(NSRange)range error:(NSError **)error +{ + return(rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLArrayOfCapturesOp | RKLSubcapturesArray), regex, options, 0L, self, &range, NULL, error, NULL)); +} + +@end + + +@implementation NSMutableString (RegexKitLiteAdditions) + +#pragma mark -replaceOccurrencesOfRegex: + +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement +{ + NSRange searchRange = NSMaxiumRange; + NSUInteger replacedCount = 0UL; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLReplaceOp | RKLReplaceMutable), regex, RKLNoOptions, 0L, self, &searchRange, replacement, NULL, (void **)((void *)&replacedCount)); + return(replacedCount); +} + +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement range:(NSRange)searchRange +{ + NSUInteger replacedCount = 0UL; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLReplaceOp | RKLReplaceMutable), regex, RKLNoOptions, 0L, self, &searchRange, replacement, NULL, (void **)((void *)&replacedCount)); + return(replacedCount); +} + +- (NSUInteger)RKL_METHOD_PREPEND(replaceOccurrencesOfRegex):(NSString *)regex withString:(NSString *)replacement options:(RKLRegexOptions)options range:(NSRange)searchRange error:(NSError **)error +{ + NSUInteger replacedCount = 0UL; + rkl_performRegexOp(self, _cmd, (RKLRegexOp)(RKLReplaceOp | RKLReplaceMutable), regex, options, 0L, self, &searchRange, replacement, error, (void **)((void *)&replacedCount)); + return(replacedCount); +} + +@end diff --git a/test/.svn/all-wcprops b/test/.svn/all-wcprops new file mode 100644 index 0000000..9cb0316 --- /dev/null +++ b/test/.svn/all-wcprops @@ -0,0 +1,1619 @@ +K 25 +svn:wc:ra_dav:version-url +V 29 +/svn/!svn/ver/1410/trunk/test +END +TDXmlTokenAssembly.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1171/trunk/test/TDXmlTokenAssembly.h +END +TDXmlNmtokenState.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1404/trunk/test/TDXmlNmtokenState.m +END +TDXmlCdata.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1404/trunk/test/TDXmlCdata.m +END +TDMiniCSSAssembler.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1171/trunk/test/TDMiniCSSAssembler.h +END +TDSymbolStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1171/trunk/test/TDSymbolStateTest.h +END +TDXmlTokenAssembly.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1405/trunk/test/TDXmlTokenAssembly.m +END +TDMiniCSSAssembler.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1405/trunk/test/TDMiniCSSAssembler.m +END +XPathParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1171/trunk/test/XPathParserTest.h +END +TDXmlStartTag.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDXmlStartTag.h +END +TDSymbolStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1410/trunk/test/TDSymbolStateTest.m +END +TDXmlWhitespace.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1171/trunk/test/TDXmlWhitespace.h +END +TDXMLParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1347/trunk/test/TDXMLParserTest.h +END +XPathParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1171/trunk/test/XPathParserTest.m +END +TDXmlStartTag.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1404/trunk/test/TDXmlStartTag.m +END +TDXMLParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1361/trunk/test/TDXMLParserTest.m +END +TDXmlWhitespace.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1404/trunk/test/TDXmlWhitespace.m +END +TDJavaScriptParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1115/trunk/test/TDJavaScriptParserTest.h +END +TDXmlAttribute.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/TDXmlAttribute.h +END +TDJavaScriptParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1115/trunk/test/TDJavaScriptParserTest.m +END +TDXmlAttribute.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1404/trunk/test/TDXmlAttribute.m +END +TDXmlEntityRef.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/TDXmlEntityRef.h +END +TDXmlTokenizer.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/TDXmlTokenizer.h +END +TDXmlEntityRef.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1404/trunk/test/TDXmlEntityRef.m +END +TDXmlTokenizer.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/TDXmlTokenizer.m +END +TDDigitTest.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1171/trunk/test/TDDigitTest.h +END +SRGSParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/SRGSParserTest.h +END +TDSyntaxHighlighter.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1171/trunk/test/TDSyntaxHighlighter.h +END +TDDigitTest.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1403/trunk/test/TDDigitTest.m +END +Tests-Info.plist +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1173/trunk/test/Tests-Info.plist +END +TDNSPredicateBuilderTest.h +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1115/trunk/test/TDNSPredicateBuilderTest.h +END +SRGSParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/SRGSParserTest.m +END +TDGenericAssemblerTest.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1171/trunk/test/TDGenericAssemblerTest.h +END +TDSyntaxHighlighter.m +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1263/trunk/test/TDSyntaxHighlighter.m +END +TDNSPredicateBuilderTest.m +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1115/trunk/test/TDNSPredicateBuilderTest.m +END +TDPatternTest.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1115/trunk/test/TDPatternTest.h +END +TDGenericAssemblerTest.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1171/trunk/test/TDGenericAssemblerTest.m +END +ERBTest.h +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/1260/trunk/test/ERBTest.h +END +TDRepetitionTest.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1171/trunk/test/TDRepetitionTest.h +END +TDPatternTest.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1179/trunk/test/TDPatternTest.m +END +TDPredicateEvaluatorTest.h +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1115/trunk/test/TDPredicateEvaluatorTest.h +END +ERBTest.m +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/1361/trunk/test/ERBTest.m +END +TDTokenizer+BlobState.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1115/trunk/test/TDTokenizer+BlobState.h +END +TDRepetitionTest.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1405/trunk/test/TDRepetitionTest.m +END +TDPredicateEvaluatorTest.m +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1370/trunk/test/TDPredicateEvaluatorTest.m +END +TDTokenizer+BlobState.m +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1115/trunk/test/TDTokenizer+BlobState.m +END +TDTrackTest.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1171/trunk/test/TDTrackTest.h +END +XPathParser.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1171/trunk/test/XPathParser.h +END +TDTrackTest.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1382/trunk/test/TDTrackTest.m +END +TDXMLParser.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1115/trunk/test/TDXMLParser.h +END +TDBlob.h +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/1115/trunk/test/TDBlob.h +END +XPathParser.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1276/trunk/test/XPathParser.m +END +PKRuleNode.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1331/trunk/test/PKRuleNode.h +END +TDXMLParser.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1115/trunk/test/TDXMLParser.m +END +TDBlob.m +K 25 +svn:wc:ra_dav:version-url +V 38 +/svn/!svn/ver/1115/trunk/test/TDBlob.m +END +TDNSPredicateEvaluator.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1115/trunk/test/TDNSPredicateEvaluator.h +END +TDParserFactoryTest.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1171/trunk/test/TDParserFactoryTest.h +END +PKRuleNode.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1331/trunk/test/PKRuleNode.m +END +TDDelimitStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1115/trunk/test/TDDelimitStateTest.h +END +PKTokenNode.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1331/trunk/test/PKTokenNode.h +END +TDNSPredicateEvaluator.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1405/trunk/test/TDNSPredicateEvaluator.m +END +TDParserFactoryTest.m +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1405/trunk/test/TDParserFactoryTest.m +END +TDParseTreeTest.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1331/trunk/test/TDParseTreeTest.h +END +PKNumberState.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1218/trunk/test/PKNumberState.h +END +TDCharacterAssemblyTest.h +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1171/trunk/test/TDCharacterAssemblyTest.h +END +TDDelimitStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1115/trunk/test/TDDelimitStateTest.m +END +TDXmlEntity.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1171/trunk/test/TDXmlEntity.h +END +PKTokenNode.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1331/trunk/test/PKTokenNode.m +END +TDParseTreeTest.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1315/trunk/test/TDParseTreeTest.m +END +PKNumberState.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1217/trunk/test/PKNumberState.m +END +TDCharacterAssemblyTest.m +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1404/trunk/test/TDCharacterAssemblyTest.m +END +TDXmlToken.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1171/trunk/test/TDXmlToken.h +END +TDXmlEntity.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1404/trunk/test/TDXmlEntity.m +END +TDFastJsonParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1171/trunk/test/TDFastJsonParserTest.h +END +TDXmlToken.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1171/trunk/test/TDXmlToken.m +END +TDFastJsonParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1171/trunk/test/TDFastJsonParserTest.m +END +TDSlashStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1170/trunk/test/TDSlashStateTest.h +END +TDSignificantWhitespaceState.h +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/1171/trunk/test/TDSignificantWhitespaceState.h +END +TDWordStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1171/trunk/test/TDWordStateTest.h +END +TDSlashStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1170/trunk/test/TDSlashStateTest.m +END +TDSignificantWhitespaceState.m +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/1171/trunk/test/TDSignificantWhitespaceState.m +END +TDWordStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1171/trunk/test/TDWordStateTest.m +END +PKScientificNumberState.h +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1217/trunk/test/PKScientificNumberState.h +END +TDXmlDocument.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDXmlDocument.h +END +PKScientificNumberState.m +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1217/trunk/test/PKScientificNumberState.m +END +TDReaderTest.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDReaderTest.h +END +TDXmlDocument.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1404/trunk/test/TDXmlDocument.m +END +TDReaderTest.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDReaderTest.m +END +TDLowercaseWordTest.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1171/trunk/test/TDLowercaseWordTest.h +END +TDLowercaseWordTest.m +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1171/trunk/test/TDLowercaseWordTest.m +END +TDXmlDecl.h +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1171/trunk/test/TDXmlDecl.h +END +TDToken+Blob.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1129/trunk/test/TDToken+Blob.h +END +TDScientificNumberStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1218/trunk/test/TDScientificNumberStateTest.h +END +TDParserBlocksTest.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1379/trunk/test/TDParserBlocksTest.h +END +TDXmlSignificantWhitespace.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1171/trunk/test/TDXmlSignificantWhitespace.h +END +TDXmlDecl.m +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1404/trunk/test/TDXmlDecl.m +END +TDQuoteStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1171/trunk/test/TDQuoteStateTest.h +END +TDScientificNumberStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/1372/trunk/test/TDScientificNumberStateTest.m +END +TDToken+Blob.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1129/trunk/test/TDToken+Blob.m +END +TDParserBlocksTest.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1400/trunk/test/TDParserBlocksTest.m +END +RelaxParser.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1115/trunk/test/RelaxParser.h +END +TDXmlSignificantWhitespace.m +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1404/trunk/test/TDXmlSignificantWhitespace.m +END +TDXmlNameTest.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDXmlNameTest.h +END +TDQuoteStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1171/trunk/test/TDQuoteStateTest.m +END +TDXmlText.h +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1171/trunk/test/TDXmlText.h +END +RelaxParser.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1115/trunk/test/RelaxParser.m +END +TDParserFactoryTest2.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1118/trunk/test/TDParserFactoryTest2.h +END +TDXmlNameTest.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDXmlNameTest.m +END +TDXmlText.m +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1404/trunk/test/TDXmlText.m +END +TDReservedWord.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/TDReservedWord.h +END +TDParserFactoryTest2.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1275/trunk/test/TDParserFactoryTest2.m +END +TDWordOrReservedState.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1170/trunk/test/TDWordOrReservedState.h +END +TDRegularParser.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1171/trunk/test/TDRegularParser.h +END +TDBlobState.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1115/trunk/test/TDBlobState.h +END +TDReservedWord.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1404/trunk/test/TDReservedWord.m +END +TDWordOrReservedState.m +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1171/trunk/test/TDWordOrReservedState.m +END +TDParserFactoryPatternTest.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1118/trunk/test/TDParserFactoryPatternTest.h +END +TDRegularParser.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1405/trunk/test/TDRegularParser.m +END +TDBlobState.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1129/trunk/test/TDBlobState.m +END +TDParserFactoryPatternTest.m +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1118/trunk/test/TDParserFactoryPatternTest.m +END +TDArithmeticAssembler.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1399/trunk/test/TDArithmeticAssembler.h +END +XMLReader.h +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1171/trunk/test/XMLReader.h +END +TDXmlTerminal.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDXmlTerminal.h +END +TDArithmeticAssembler.m +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1399/trunk/test/TDArithmeticAssembler.m +END +XMLReader.m +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/735/trunk/test/XMLReader.m +END +TDXmlTerminal.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDXmlTerminal.m +END +TDMiniCSSAssemblerTest.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1171/trunk/test/TDMiniCSSAssemblerTest.h +END +TDSymbolTest.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDSymbolTest.h +END +TDMiniCSSAssemblerTest.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1171/trunk/test/TDMiniCSSAssemblerTest.m +END +TDSymbolTest.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDSymbolTest.m +END +TDXmlEndEntity.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/TDXmlEndEntity.h +END +TDXmlEndEntity.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1404/trunk/test/TDXmlEndEntity.m +END +XPathAssembler.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/XPathAssembler.h +END +TDXmlTokenizerTest.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1171/trunk/test/TDXmlTokenizerTest.h +END +TDLiteralTest.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDLiteralTest.h +END +TDXmlNmtoken.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDXmlNmtoken.h +END +XPathAssembler.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1276/trunk/test/XPathAssembler.m +END +EBNFParser.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1368/trunk/test/EBNFParser.h +END +TDXmlTokenizerTest.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1171/trunk/test/TDXmlTokenizerTest.m +END +TDLiteralTest.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1177/trunk/test/TDLiteralTest.m +END +TDXmlName.h +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1171/trunk/test/TDXmlName.h +END +TDXmlNmtoken.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDXmlNmtoken.m +END +EBNFParser.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1404/trunk/test/EBNFParser.m +END +TDXmlName.m +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/1171/trunk/test/TDXmlName.m +END +TDParserFactoryTest3.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1266/trunk/test/TDParserFactoryTest3.h +END +TDNSPredicateBuilder.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1115/trunk/test/TDNSPredicateBuilder.h +END +TDXmlNotation.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDXmlNotation.h +END +TDParserFactoryTest3.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1276/trunk/test/TDParserFactoryTest3.m +END +TDNSPredicateBuilder.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1405/trunk/test/TDNSPredicateBuilder.m +END +TDRegularParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1171/trunk/test/TDRegularParserTest.h +END +TDTokenTest.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1171/trunk/test/TDTokenTest.h +END +TDXmlNotation.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1404/trunk/test/TDXmlNotation.m +END +TDRegularParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1405/trunk/test/TDRegularParserTest.m +END +TDUppercaseWordTest.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1171/trunk/test/TDUppercaseWordTest.h +END +TDXmlComment.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDXmlComment.h +END +TDTokenTest.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1171/trunk/test/TDTokenTest.m +END +TDUppercaseWordTest.m +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1171/trunk/test/TDUppercaseWordTest.m +END +TDXmlComment.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1404/trunk/test/TDXmlComment.m +END +TDParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDParserTest.h +END +TDTokenArraySourceTest.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1171/trunk/test/TDTokenArraySourceTest.h +END +TDParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1379/trunk/test/TDParserTest.m +END +TDTokenArraySourceTest.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1405/trunk/test/TDTokenArraySourceTest.m +END +XPathParserGrammarTest.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1115/trunk/test/XPathParserGrammarTest.h +END +XPathParserGrammarTest.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1361/trunk/test/XPathParserGrammarTest.m +END +XPathContext.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/XPathContext.h +END +TDXmlNameState.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/TDXmlNameState.h +END +TDFastJsonParser.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1171/trunk/test/TDFastJsonParser.h +END +XPathContext.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/XPathContext.m +END +TDXmlNameState.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/TDXmlNameState.m +END +TDPlistParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1171/trunk/test/TDPlistParserTest.h +END +TDFastJsonParser.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1405/trunk/test/TDFastJsonParser.m +END +TDTokenizerTest.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1374/trunk/test/TDTokenizerTest.h +END +TDPlistParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1382/trunk/test/TDPlistParserTest.m +END +TDTokenizerTest.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1171/trunk/test/TDTokenizerTest.m +END +TDHtmlSyntaxHighlighter.h +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1171/trunk/test/TDHtmlSyntaxHighlighter.h +END +TDHtmlSyntaxHighlighter.m +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/1405/trunk/test/TDHtmlSyntaxHighlighter.m +END +TDArithmeticParser.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1372/trunk/test/TDArithmeticParser.h +END +TDTokenizerBlocksTest.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1374/trunk/test/TDTokenizerBlocksTest.h +END +TDArithmeticParser.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1372/trunk/test/TDArithmeticParser.m +END +TDTokenizerBlocksTest.m +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1400/trunk/test/TDTokenizerBlocksTest.m +END +TDJavaScriptParser.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1115/trunk/test/TDJavaScriptParser.h +END +TDSpecificCharTest.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1171/trunk/test/TDSpecificCharTest.h +END +TDSpecificCharTest.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1403/trunk/test/TDSpecificCharTest.m +END +TDJavaScriptParser.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1218/trunk/test/TDJavaScriptParser.m +END +PKAST.h +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/1212/trunk/test/PKAST.h +END +PKAST.m +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/1212/trunk/test/PKAST.m +END +TDNCName.h +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1171/trunk/test/TDNCName.h +END +SRGSParser.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1171/trunk/test/SRGSParser.h +END +TDNCName.m +K 25 +svn:wc:ra_dav:version-url +V 40 +/svn/!svn/ver/1171/trunk/test/TDNCName.m +END +TDSequenceTest.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/TDSequenceTest.h +END +SRGSParser.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1276/trunk/test/SRGSParser.m +END +TDReservedWordTest.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1171/trunk/test/TDReservedWordTest.h +END +TDCharTest.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1171/trunk/test/TDCharTest.h +END +TDSequenceTest.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1405/trunk/test/TDSequenceTest.m +END +TDReservedWordTest.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1171/trunk/test/TDReservedWordTest.m +END +TDCharTest.m +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1403/trunk/test/TDCharTest.m +END +TDPredicateEvaluator.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1115/trunk/test/TDPredicateEvaluator.h +END +TDXmlFragment.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDXmlFragment.h +END +TDNonReservedWord.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1171/trunk/test/TDNonReservedWord.h +END +TDPredicateEvaluator.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1371/trunk/test/TDPredicateEvaluator.m +END +TDXmlFragment.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1404/trunk/test/TDXmlFragment.m +END +TDDifferenceTest.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1162/trunk/test/TDDifferenceTest.h +END +XMLReaderTest.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/XMLReaderTest.h +END +TDNonReservedWord.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1404/trunk/test/TDNonReservedWord.m +END +PKParseTreeAssembler.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1331/trunk/test/PKParseTreeAssembler.h +END +TDDifferenceTest.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1162/trunk/test/TDDifferenceTest.m +END +XMLReaderTest.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/XMLReaderTest.m +END +PKParseTreeAssembler.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1404/trunk/test/PKParseTreeAssembler.m +END +TDArithmeticParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1372/trunk/test/TDArithmeticParserTest.h +END +TDArithmeticParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/1372/trunk/test/TDArithmeticParserTest.m +END +TDTokenizerStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1213/trunk/test/TDTokenizerStateTest.h +END +TDTokenAssemblyTest.h +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1171/trunk/test/TDTokenAssemblyTest.h +END +TDTokenizerStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/1410/trunk/test/TDTokenizerStateTest.m +END +TDNSPredicateEvaluatorTest.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1115/trunk/test/TDNSPredicateEvaluatorTest.h +END +TDTokenAssemblyTest.m +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1404/trunk/test/TDTokenAssemblyTest.m +END +TDNSPredicateEvaluatorTest.m +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1405/trunk/test/TDNSPredicateEvaluatorTest.m +END +TDWhitespaceStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1171/trunk/test/TDWhitespaceStateTest.h +END +EBNFParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/EBNFParserTest.h +END +SAXAssembler.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1347/trunk/test/SAXAssembler.h +END +TDWhitespaceStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/1171/trunk/test/TDWhitespaceStateTest.m +END +TDNCNameState.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDNCNameState.h +END +TDCommentStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1171/trunk/test/TDCommentStateTest.h +END +EBNFParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1171/trunk/test/EBNFParserTest.m +END +TDNegationTest.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1162/trunk/test/TDNegationTest.h +END +SAXAssembler.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1354/trunk/test/SAXAssembler.m +END +TDNCNameState.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1171/trunk/test/TDNCNameState.m +END +TDCommentStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1410/trunk/test/TDCommentStateTest.m +END +TDNegationTest.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1162/trunk/test/TDNegationTest.m +END +TDSlashState.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1170/trunk/test/TDSlashState.h +END +TDSignificantWhitespaceStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 64 +/svn/!svn/ver/1171/trunk/test/TDSignificantWhitespaceStateTest.h +END +TDSlashState.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1170/trunk/test/TDSlashState.m +END +TDSignificantWhitespaceStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 64 +/svn/!svn/ver/1170/trunk/test/TDSignificantWhitespaceStateTest.m +END +TDJsonParser.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1367/trunk/test/TDJsonParser.h +END +TDNumberStateTest.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1171/trunk/test/TDNumberStateTest.h +END +TDJsonParser.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1405/trunk/test/TDJsonParser.m +END +PKParseTree.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1331/trunk/test/PKParseTree.h +END +TDNumberStateTest.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1171/trunk/test/TDNumberStateTest.m +END +TDLetterTest.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDLetterTest.h +END +PKParseTree.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1331/trunk/test/PKParseTree.m +END +TDLetterTest.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1403/trunk/test/TDLetterTest.m +END +TDSlashStarState.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1170/trunk/test/TDSlashStarState.h +END +TDSlashSlashState.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1170/trunk/test/TDSlashSlashState.h +END +TDSlashStarState.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1170/trunk/test/TDSlashStarState.m +END +TDSlashSlashState.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1170/trunk/test/TDSlashSlashState.m +END +PKExclusion.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1166/trunk/test/PKExclusion.h +END +TDTestScaffold.h +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1375/trunk/test/TDTestScaffold.h +END +PKExclusion.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1168/trunk/test/PKExclusion.m +END +TDTestScaffold.m +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/1400/trunk/test/TDTestScaffold.m +END +TDXmlDoctype.h +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1171/trunk/test/TDXmlDoctype.h +END +TDXmlDoctype.m +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1404/trunk/test/TDXmlDoctype.m +END +TDXmlProcessingInstruction.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1171/trunk/test/TDXmlProcessingInstruction.h +END +SAXTest.h +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/1347/trunk/test/SAXTest.h +END +TDXmlProcessingInstruction.m +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/1404/trunk/test/TDXmlProcessingInstruction.m +END +TDPlistParser.h +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1367/trunk/test/TDPlistParser.h +END +SAXTest.m +K 25 +svn:wc:ra_dav:version-url +V 39 +/svn/!svn/ver/1361/trunk/test/SAXTest.m +END +TDExclusionTest.h +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1153/trunk/test/TDExclusionTest.h +END +TDGenericAssembler.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1261/trunk/test/TDGenericAssembler.h +END +TDPlistParser.m +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1405/trunk/test/TDPlistParser.m +END +TDExclusionTest.m +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1153/trunk/test/TDExclusionTest.m +END +TDGenericAssembler.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1404/trunk/test/TDGenericAssembler.m +END +TDAlternationTest.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1171/trunk/test/TDAlternationTest.h +END +TDXmlEndTag.h +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1171/trunk/test/TDXmlEndTag.h +END +TDRobotCommandTest.h +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1171/trunk/test/TDRobotCommandTest.h +END +TDAlternationTest.m +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1225/trunk/test/TDAlternationTest.m +END +TDJsonParserTest.h +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1171/trunk/test/TDJsonParserTest.h +END +TDXmlEndTag.m +K 25 +svn:wc:ra_dav:version-url +V 43 +/svn/!svn/ver/1404/trunk/test/TDXmlEndTag.m +END +TDRobotCommandTest.m +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/1276/trunk/test/TDRobotCommandTest.m +END +TDJsonParserTest.m +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1405/trunk/test/TDJsonParserTest.m +END +TDXmlNmtokenState.h +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/1171/trunk/test/TDXmlNmtokenState.h +END +TDXmlCdata.h +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1171/trunk/test/TDXmlCdata.h +END diff --git a/test/.svn/entries b/test/.svn/entries new file mode 100644 index 0000000..7a66859 --- /dev/null +++ b/test/.svn/entries @@ -0,0 +1,9174 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/test +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-11-06T01:42:40.664388Z +1410 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +TDXmlTokenAssembly.h +file + + + + +2009-07-03T19:42:55.000000Z +6005e82f2437aeaabefd88a3876b3d6e +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +387 + +TDXmlCdata.m +file + + + + +2009-11-13T07:14:26.000000Z +db2a5628fa3d3464b36fe7f14da85992 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +832 + +TDXmlNmtokenState.m +file + + + + +2009-11-13T07:14:26.000000Z +9dce21433f87112f150c08bebe17b2c5 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1664 + +TDMiniCSSAssembler.h +file + + + + +2009-07-03T19:42:55.000000Z +06b6cb26ca1cdaee73184e4428a48109 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +485 + +TDXmlTokenAssembly.m +file + + + + +2009-11-13T07:14:26.000000Z +0bc3622d591adce015b0f1641453c920 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2843 + +TDSymbolStateTest.h +file + + + + +2009-07-03T19:31:27.000000Z +f8ca217adc51892b82bca91eddb761d5 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +295 + +TDMiniCSSAssembler.m +file + + + + +2009-11-13T07:14:26.000000Z +329c78a2a6d658d0e4f779715d4e62a1 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +5380 + +XPathParserTest.h +file + + + + +2009-07-03T19:31:20.000000Z +79234379e9638c5a36c960793048fbfd +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +331 + +TDXmlStartTag.h +file + + + + +2009-07-03T19:31:22.000000Z +0bb485a40bb38dd7e4aab2265bb4e004 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +279 + +TDSymbolStateTest.m +file + + + + +2009-11-13T07:14:26.000000Z +befb4b7c900af58fa50d20d0cf99c871 +2009-11-06T01:42:40.664388Z +1410 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +15484 + +TDXmlWhitespace.h +file + + + + +2009-07-03T19:31:21.000000Z +4367efb8015bba64dc884c61b07fb1f3 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +287 + +TDXMLParserTest.h +file + + + + +2009-08-17T07:55:20.000000Z +bfa766519c47938c2e3ec1dec89869f6 +2009-08-23T05:03:45.633098Z +1347 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +372 + +XPathParserTest.m +file + + + + +2009-07-03T19:31:20.000000Z +09982e53a108ba5f81a425bc01c0ee95 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +9019 + +TDXmlStartTag.m +file + + + + +2009-11-13T07:14:26.000000Z +d54815dfdf91ad353fc6ea183b792089 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +854 + +TDXMLParserTest.m +file + + + + +2009-08-29T06:09:29.000000Z +10812c40fc8ff8459033fb5d8cd9aff8 +2009-08-29T06:10:20.621428Z +1361 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +18854 + +TDXmlWhitespace.m +file + + + + +2009-11-13T07:14:26.000000Z +5a5540405eedfd508b80c334b866f964 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +867 + +TDJavaScriptParserTest.h +file + + + + +2009-06-30T06:13:13.000000Z +2d0edc3a37e4ceea310aa76b91980547 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +353 + +TDXmlAttribute.h +file + + + + +2009-07-03T19:31:23.000000Z +5baccf29289c34b835529e5815e9eca6 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +283 + +TDJavaScriptParserTest.m +file + + + + +2009-06-30T06:13:13.000000Z +ab543bdd23d646eb7f0bad72bfe32de1 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +26389 + +TDXmlAttribute.m +file + + + + +2009-11-13T07:14:26.000000Z +471d7487fa9420d1a8a096f99a3d2eca +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +860 + +TDXmlEntityRef.h +file + + + + +2009-07-03T19:31:22.000000Z +d77fa2ff7a2b0dc8febe27c093dc4548 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +283 + +TDXmlTokenizer.h +file + + + + +2009-07-03T19:31:24.000000Z +faf31bec1d62b3d43a257d78d0a1637f +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +415 + +TDXmlEntityRef.m +file + + + + +2009-11-13T07:14:26.000000Z +e887c1fba3b8522aea12691967760dc8 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +861 + +TDDigitTest.h +file + + + + +2009-07-03T19:31:26.000000Z +ae18390ea03b47cd889e9791046af4ab +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +304 + +TDXmlTokenizer.m +file + + + + +2009-07-03T19:42:56.000000Z +0548c68530e76e71659b9b2329707c42 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1249 + +SRGSParserTest.h +file + + + + +2009-07-03T19:31:19.000000Z +086682b2b15ace60d726070ee4a60f1f +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +327 + +TDSyntaxHighlighter.h +file + + + + +2009-07-03T19:42:56.000000Z +f159862b35839a7bf5ad3c6e55e4b791 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +766 + +TDDigitTest.m +file + + + + +2009-09-26T05:55:36.000000Z +baefe3dcc0cb55f24645905f34a97aa1 +2009-09-26T19:12:29.746961Z +1403 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1199 + +Tests-Info.plist +file + + + + +2009-07-03T20:35:47.000000Z +f3afee633e814c6e62bbbb24d8f9b171 +2009-07-03T20:39:51.719779Z +1173 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +675 + +TDNSPredicateBuilderTest.h +file + + + + +2009-06-30T06:13:11.000000Z +d50a637c2ecc3c2462c79e41f15dcef4 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +337 + +SRGSParserTest.m +file + + + + +2009-07-12T23:20:48.000000Z +fe8011b0fdd0b0ce84cba5a83b90c869 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +5298 + +TDGenericAssemblerTest.h +file + + + + +2009-07-03T19:31:29.000000Z +7e46bf3272825c70445b50d92c4e7d4c +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +549 + +TDSyntaxHighlighter.m +file + + + + +2009-07-27T05:46:37.000000Z +982c86b655aaa7984e066cecb087732d +2009-07-27T06:00:08.623243Z +1263 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +5574 + +TDNSPredicateBuilderTest.m +file + + + + +2009-06-30T06:13:13.000000Z +a1dd5aab9bcfca9bc53d1fcd241934c2 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +7679 + +TDPatternTest.h +file + + + + +2009-06-30T06:13:10.000000Z +09d53bc2c80fd546f4b8808a4e91ca55 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +323 + +TDGenericAssemblerTest.m +file + + + + +2009-07-03T19:31:29.000000Z +9a202dafb1973ec7a37e7a35e79acc9e +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2136 + +ERBTest.h +file + + + + +2009-07-27T00:55:45.000000Z +687d0bee5481fb427679e3ce8eb0524e +2009-07-27T01:22:37.892748Z +1260 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +399 + +TDRepetitionTest.h +file + + + + +2009-07-03T19:31:29.000000Z +fa666e2c88f5e2ed9196dddfe641f408 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +281 + +TDPatternTest.m +file + + + + +2009-07-03T22:32:10.000000Z +760b64b9fb2b7d9710a4c133c35622d4 +2009-07-03T22:34:56.929029Z +1179 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +6003 + +TDPredicateEvaluatorTest.h +file + + + + +2009-06-30T06:13:11.000000Z +4afd59d8acec27e21a598bcd1d2e6f80 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +406 + +ERBTest.m +file + + + + +2009-08-29T06:09:00.000000Z +102cd88973f3731c728b387ad9ce9cf2 +2009-08-29T06:10:20.621428Z +1361 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1491 + +TDTokenizer+BlobState.h +file + + + + +2009-06-30T06:13:08.000000Z +8584e401bf99714cf58bdf776f4d80b1 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +275 + +TDRepetitionTest.m +file + + + + +2009-11-13T07:14:26.000000Z +9298bff00a6af62f67de3fb1449028ad +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +5566 + +TDPredicateEvaluatorTest.m +file + + + + +2009-09-16T04:29:42.000000Z +d758cff681916f7a583a93c5215cbbe1 +2009-09-16T04:30:31.017239Z +1370 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +10465 + +TDTokenizer+BlobState.m +file + + + + +2009-06-30T06:13:13.000000Z +2fc2b60c289db3b5ffcb2b4310e62f30 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +772 + +TDTrackTest.h +file + + + + +2009-07-03T19:31:28.000000Z +0c8b6ab26ab57631641c6f7af9126c12 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +219 + +TDTrackTest.m +file + + + + +2009-09-17T22:45:56.000000Z +dde3752778bd9b2cfe37b283475fb411 +2009-09-17T22:46:20.790207Z +1382 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +3303 + +XPathParser.h +file + + + + +2009-07-03T19:31:20.000000Z +fafb6a995b117e4b895627b823520983 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3754 + +TDXMLParser.h +file + + + + +2009-06-30T06:13:07.000000Z +45c66e82cca93ba4452401d50e93b8c2 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +219 + +XPathParser.m +file + + + + +2009-08-06T04:01:55.000000Z +a1de989d67997c8ba260440e884edd37 +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +30876 + +TDBlob.h +file + + + + +2009-06-30T06:13:07.000000Z +daa564c42e605e7d6a3c7a1294442ea8 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +265 + +PKRuleNode.h +file + + + + +2009-08-06T04:02:00.000000Z +f359df7dcb42a06d8a2150ee5257ae6c +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +399 + +TDXMLParser.m +file + + + + +2009-06-30T06:13:15.000000Z +874bda7e4245fbc96e52af5d70e5448d +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +204 + +TDBlob.m +file + + + + +2009-06-30T06:13:06.000000Z +fdd1acac7f89f280a5d24ab7fbd4cfff +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +606 + +TDNSPredicateEvaluator.h +file + + + + +2009-07-03T19:42:56.000000Z +92665170c184a4ebe92786bb893ff086 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +616 + +TDParserFactoryTest.h +file + + + + +2009-07-03T19:31:30.000000Z +86b2f9d813c85d1edc17a28839dfcefa +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +437 + +PKRuleNode.m +file + + + + +2009-08-06T04:02:04.000000Z +2ae3d621ca80e6128735bdb0a7ae1e1b +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +834 + +TDDelimitStateTest.h +file + + + + +2009-06-30T06:13:12.000000Z +2856e51c050c626d51c599eab4a597c5 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +321 + +TDParserFactoryTest.m +file + + + + +2009-11-13T07:14:26.000000Z +dee3ccd9bd31a8569f80742c27064708 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +43246 + +TDNSPredicateEvaluator.m +file + + + + +2009-11-13T07:14:26.000000Z +a35eab5be1a276715aae2d265263d04b +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +6270 + +PKTokenNode.h +file + + + + +2009-08-06T04:02:00.000000Z +e32eaa4eaace0be48dc451c2f86b700e +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +425 + +TDParseTreeTest.h +file + + + + +2009-08-17T00:38:47.000000Z +2214b7df31cb49fda613bd1c5d8a4a86 +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +544 + +TDCharacterAssemblyTest.h +file + + + + +2009-07-03T19:31:26.000000Z +ccd79d788278595a9b5465cba2a32892 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +312 + +PKNumberState.h +file + + + + +2009-07-13T03:26:58.000000Z +50beb43f197ef6e29c046eb9b908a40f +2009-07-13T03:32:51.609563Z +1218 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1175 + +TDDelimitStateTest.m +file + + + + +2009-06-30T06:13:12.000000Z +8f60b0f6c1eaefb4edf0a80350ba1a06 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +22429 + +TDXmlEntity.h +file + + + + +2009-07-03T19:31:22.000000Z +7ec9293a5784703899ff3d772e496dec +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +271 + +PKTokenNode.m +file + + + + +2009-08-06T04:02:04.000000Z +c81e1745e228fe99c850eb1f04dd3da2 +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +866 + +TDParseTreeTest.m +file + + + + +2009-09-03T09:44:59.000000Z +528d5063afc7fa787613b053f1cefd81 +2009-08-09T07:09:11.210917Z +1315 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +6176 + +PKNumberState.m +file + + + + +2009-07-13T03:08:53.000000Z +6bd0a4ba6a9136c017995ba3817a3d6e +2009-07-13T03:20:31.678525Z +1217 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3228 + +TDXmlToken.h +file + + + + +2009-07-03T19:42:56.000000Z +28db290808dbd6cc8c03d8501b988ffe +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2870 + +TDCharacterAssemblyTest.m +file + + + + +2009-11-13T07:14:26.000000Z +435820a9e8d9546070830b4a1d529b3f +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1658 + +TDXmlEntity.m +file + + + + +2009-11-13T07:14:26.000000Z +d433a5d36e79c1745b66a3c7c6fc41e0 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +839 + +TDFastJsonParserTest.h +file + + + + +2009-07-03T19:31:24.000000Z +f585d4a89d62e8a844261d0123a68904 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +258 + +TDXmlToken.m +file + + + + +2009-07-03T19:42:56.000000Z +e7ce5f08c2d3753d4adf670e96de062e +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +6165 + +TDFastJsonParserTest.m +file + + + + +2009-07-03T19:31:24.000000Z +719ee766544dc11a6b0f1bad0af86e5c +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +878 + +TDSlashStateTest.h +file + + + + +2009-07-03T19:31:12.000000Z +72dc9b88e54423461e92cb23d6d3a5f7 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +311 + +TDWordStateTest.h +file + + + + +2009-07-03T19:31:26.000000Z +83b28411693b315662eb7d2024406858 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +286 + +TDSignificantWhitespaceState.h +file + + + + +2009-07-03T19:42:56.000000Z +6251bd525f89984968ec53abcf2146c9 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +642 + +TDSlashStateTest.m +file + + + + +2009-07-03T19:31:12.000000Z +6ddc3ccfe9f54ab0c8c0c775122d0b40 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +10130 + +TDSignificantWhitespaceState.m +file + + + + +2009-07-03T19:31:17.000000Z +b6e7c89a0f801eacd94e0f2ba8690542 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1646 + +TDWordStateTest.m +file + + + + +2009-07-03T19:31:26.000000Z +ac15d7d14d38386c61a8a9bcfa1e76b9 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2838 + +PKScientificNumberState.h +file + + + + +2009-07-13T03:08:11.000000Z +b010b09325e0a6d87be48c192f971d4b +2009-07-13T03:20:31.678525Z +1217 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +854 + +TDXmlDocument.h +file + + + + +2009-07-03T19:31:23.000000Z +05b57655d074cf6a6b607aba78e72ad4 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +279 + +TDReaderTest.h +file + + + + +2009-07-03T19:31:27.000000Z +f8b956ca1ad8d38f07b8245c36457f55 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +264 + +PKScientificNumberState.m +file + + + + +2009-07-13T03:12:24.000000Z +ca59be76eed203c886f01609fc121991 +2009-07-13T03:20:31.678525Z +1217 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1989 + +TDXmlDocument.m +file + + + + +2009-11-13T07:14:26.000000Z +6c61875dbfb84506f1805618e9afa7d3 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +853 + +TDReaderTest.m +file + + + + +2009-07-03T19:31:27.000000Z +3b966234eb89657042bbfc0e9a817a1b +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1333 + +TDLowercaseWordTest.h +file + + + + +2009-07-03T19:31:28.000000Z +418e19d6135a35033b817b17823d4e2b +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +243 + +TDLowercaseWordTest.m +file + + + + +2009-07-03T19:31:27.000000Z +8c85ab03002a0f852f45219fd0be6681 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1228 + +TDXmlDecl.h +file + + + + +2009-07-03T19:31:23.000000Z +f77594af484397d5d483f571bd810e11 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +269 + +TDToken+Blob.h +file + + + + +2009-06-30T08:18:50.000000Z +e1262dd321dcacf5ba8c0df6bd747aee +2009-06-30T08:19:25.121159Z +1129 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +262 + +TDScientificNumberStateTest.h +file + + + + +2009-07-13T03:29:09.000000Z +a48641e6b4a2d3d01a08bd7cd0fd85dc +2009-07-13T03:32:51.609563Z +1218 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +336 + +TDParserBlocksTest.h +file + + + + +2009-09-17T21:57:35.000000Z +d2b3ad50f0f4c03a8073a00705ab5f88 +2009-09-17T22:12:38.271967Z +1379 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +289 + +TDXmlSignificantWhitespace.h +file + + + + +2009-07-03T19:31:22.000000Z +7699650f1e76a1285986a3f4301b9e25 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +331 + +TDXmlDecl.m +file + + + + +2009-11-13T07:14:26.000000Z +2a7675b8c8dd56d041597ec444b6d8d2 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +838 + +TDQuoteStateTest.h +file + + + + +2009-07-03T19:31:27.000000Z +03fc05c174c124190fef838a032f0db1 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +290 + +TDToken+Blob.m +file + + + + +2009-06-30T08:18:50.000000Z +5d920a189643a5088030911ce4ee3549 +2009-06-30T08:19:25.121159Z +1129 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +313 + +TDScientificNumberStateTest.m +file + + + + +2009-09-16T05:24:42.000000Z +679a0b3be12a28d04c15fc0f5d12ea53 +2009-09-16T05:35:05.447616Z +1372 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +31145 + +TDParserBlocksTest.m +file + + + + +2009-09-26T03:40:29.000000Z +9d957ce254ad706c5ccbf171714c202e +2009-09-26T03:50:36.795525Z +1400 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2041 + +RelaxParser.h +file + + + + +2009-06-30T06:13:08.000000Z +664a5c37dbdf3a200b311a8feaec61bd +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +245 + +TDXmlNameTest.h +file + + + + +2009-07-03T19:31:21.000000Z +77b539123e5ab66d54ea0320017fda7d +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +226 + +TDXmlSignificantWhitespace.m +file + + + + +2009-11-13T07:14:26.000000Z +ff062f7211e90f9ff82da56d972de9a7 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +945 + +TDQuoteStateTest.m +file + + + + +2009-07-03T19:31:27.000000Z +84ff5d2f3966f0ed0d959abe2bf23788 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2581 + +RelaxParser.m +file + + + + +2009-06-30T06:13:11.000000Z +c0d3411bd025690770b0537d22b6425d +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +16676 + +TDXmlText.h +file + + + + +2009-07-03T19:31:21.000000Z +a8dc1f21bdcfaedd8a6e0cf896f5ae18 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +263 + +TDParserFactoryTest2.h +file + + + + +2009-06-30T06:34:51.000000Z +66946bf761bf41130167c12cbd3dc131 +2009-06-30T06:36:18.475282Z +1118 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +448 + +TDXmlNameTest.m +file + + + + +2009-07-03T19:31:21.000000Z +446b505b44562be0e8dcd3cd190c68b1 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1633 + +TDXmlText.m +file + + + + +2009-11-13T07:14:26.000000Z +5059f622c836021286ad97b16c837744 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +944 + +TDReservedWord.h +file + + + + +2009-07-03T19:31:18.000000Z +cdb2d33524ddd80d048e8190713a3d33 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +300 + +TDParserFactoryTest2.m +file + + + + +2009-08-06T04:01:55.000000Z +5b39e03a01a2e8dcb7745533bf40eb17 +2009-08-02T22:59:20.682429Z +1275 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +20855 + +TDWordOrReservedState.h +file + + + + +2009-07-03T19:31:13.000000Z +be13fbe5e3a2f6db7a277de438382bd2 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +629 + +TDRegularParser.h +file + + + + +2009-07-03T19:31:25.000000Z +4667eb4c2b9687934f9b4b3273337b03 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1235 + +TDBlobState.h +file + + + + +2009-06-30T06:13:07.000000Z +093552caf9b4fc3cdfd0f9113c80e14b +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +234 + +TDReservedWord.m +file + + + + +2009-11-13T07:14:26.000000Z +33533fc49425600b3310c77c163e8bc8 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +846 + +TDWordOrReservedState.m +file + + + + +2009-07-03T19:42:56.000000Z +e797b724e1fe0d5503c0b37d000dcfa4 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +788 + +TDParserFactoryPatternTest.h +file + + + + +2009-06-30T06:34:51.000000Z +cd16e2ccd67fd02611938a65f7b5e164 +2009-06-30T06:36:18.475282Z +1118 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +441 + +TDRegularParser.m +file + + + + +2009-11-13T07:14:26.000000Z +85b83d00fa06a4b9ad7d8f1bb5e719fb +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +9360 + +TDBlobState.m +file + + + + +2009-07-03T19:42:56.000000Z +44ea12dc013d3ac6d36d673549470ae7 +2009-06-30T08:19:25.121159Z +1129 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1001 + +TDParserFactoryPatternTest.m +file + + + + +2009-06-30T06:34:51.000000Z +17de374ccea0cc8b5dab1c9a770083e1 +2009-06-30T06:36:18.475282Z +1118 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +2105 + +TDArithmeticAssembler.h +file + + + + +2009-09-26T03:08:41.000000Z +95a31ebd216abcecd97969a85a570a60 +2009-09-25T23:53:58.853281Z +1399 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +242 + +XMLReader.h +file + + + + +2009-07-03T19:42:56.000000Z +30998420c4287cce7b665ed40462c5a2 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +8430 + +TDXmlTerminal.h +file + + + + +2009-07-03T19:42:56.000000Z +3fe0ef2cb69b3767dd2abe9637247eb0 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +313 + +TDArithmeticAssembler.m +file + + + + +2009-09-26T03:08:41.000000Z +297330071ef00157a26e7cc3db1ce7bf +2009-09-25T23:53:58.853281Z +1399 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1297 + +XMLReader.m +file + + + + +2009-07-03T19:42:56.000000Z +c7b17c21b53cdb7df6e66386d8399ce2 +2009-03-23T17:04:23.554366Z +735 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +10486 + +TDXmlTerminal.m +file + + + + +2009-07-03T19:31:22.000000Z +85419e37f3606f19bce7ec07dca9b8bf +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +310 + +TDMiniCSSAssemblerTest.h +file + + + + +2009-07-03T19:31:30.000000Z +34f7fc1cd5bffcb9333989dcd9a5c063 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +462 + +TDSymbolTest.h +file + + + + +2009-07-03T19:31:28.000000Z +b4236151fca74a1c7c3dcb8f9e77c874 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +273 + +TDMiniCSSAssemblerTest.m +file + + + + +2009-07-03T19:31:30.000000Z +bccf786c6acb333e3d680a2c44dd70ee +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +8971 + +TDSymbolTest.m +file + + + + +2009-07-03T19:31:28.000000Z +321a7a19127503861d8e5e988e712901 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1215 + +TDXmlEndEntity.h +file + + + + +2009-07-03T19:31:23.000000Z +b5347cb75fa3b98b1194cab62cbb7325 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +283 + +TDXmlEndEntity.m +file + + + + +2009-11-13T07:14:26.000000Z +5c1be2469636eac5763a84cf5a1dc55e +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +861 + +XPathAssembler.h +file + + + + +2009-07-03T19:31:20.000000Z +ab4415a3c1f621cb8d46159284dfb1e5 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +374 + +TDXmlTokenizerTest.h +file + + + + +2009-07-03T19:31:24.000000Z +0f298ccac1944a8d1bcaff1f0d5c9bd5 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +283 + +TDLiteralTest.h +file + + + + +2009-07-03T19:31:29.000000Z +4b7af10932f4c5a8a61b856aeec147bf +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +275 + +TDXmlNmtoken.h +file + + + + +2009-07-03T19:31:20.000000Z +21cf1a4df1a2be20df6b05938c8538f4 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +230 + +XPathAssembler.m +file + + + + +2009-08-06T04:01:56.000000Z +5e22aef57355dd4d3e4ba77055122429 +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1067 + +EBNFParser.h +file + + + + +2009-09-16T04:24:50.000000Z +fa2ef0354692dec27f130d1b78ce4a64 +2009-09-16T04:25:37.006705Z +1368 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1879 + +TDXmlTokenizerTest.m +file + + + + +2009-07-03T19:31:24.000000Z +fb3b90c01e4dc0a635744b245a61cebd +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1442 + +TDXmlNmtoken.m +file + + + + +2009-07-03T19:31:20.000000Z +3c5813da1de14017329ec971247379a0 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +414 + +TDLiteralTest.m +file + + + + +2009-07-03T22:05:22.000000Z +fa90bdb119cdcca675c64ce59288e60a +2009-07-03T22:22:49.496142Z +1177 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2244 + +TDXmlName.h +file + + + + +2009-07-03T19:31:21.000000Z +ab5360c9d48c35d4c7e21306cba21b19 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +221 + +EBNFParser.m +file + + + + +2009-11-13T07:14:26.000000Z +64bbcf3e8d8d57b739ec8e9229c151de +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +12648 + +TDXmlName.m +file + + + + +2009-07-03T19:31:21.000000Z +1a0c6457b1b39218538cfd8c500f7254 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +500 + +TDParserFactoryTest3.h +file + + + + +2009-08-06T04:01:56.000000Z +af3a61afd61aadc27d797a11b1a5565e +2009-08-02T06:27:39.526860Z +1266 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +420 + +TDNSPredicateBuilder.h +file + + + + +2009-07-03T19:42:56.000000Z +3a627365f34cce304c349137c71ab5f6 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3279 + +TDXmlNotation.h +file + + + + +2009-07-03T19:31:22.000000Z +4ee37d2d5f7ff05e64424d2c65612716 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +279 + +TDParserFactoryTest3.m +file + + + + +2009-08-06T04:01:56.000000Z +f9e2ee6c195f2f1589ad896f196a0c7b +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +4860 + +TDNSPredicateBuilder.m +file + + + + +2009-11-13T07:14:26.000000Z +542ab0f5c01536736a7d1fe99a9615c1 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +18656 + +TDRegularParserTest.h +file + + + + +2009-07-03T19:31:25.000000Z +144d7f063f4c287ac531e9de4ad4c6ad +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +352 + +TDTokenTest.h +file + + + + +2009-07-03T19:31:27.000000Z +d26afeb45e7502a7940e3271a10cc67f +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +236 + +TDXmlNotation.m +file + + + + +2009-11-13T07:14:26.000000Z +52255e8fed41304c3908443177775a1b +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +853 + +TDXmlComment.h +file + + + + +2009-07-03T19:31:23.000000Z +b3605d1112d850f2e3baac0b9c69f082 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +275 + +TDUppercaseWordTest.h +file + + + + +2009-07-03T19:31:28.000000Z +feb6a458245b98546546ae83ffe78427 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +235 + +TDRegularParserTest.m +file + + + + +2009-11-13T07:14:26.000000Z +f02c8c4dbca9cb25bc378874fdb2004c +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +13351 + +TDTokenTest.m +file + + + + +2009-07-03T19:31:27.000000Z +e348223773fe69458889b61bff4a9e06 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1489 + +TDXmlComment.m +file + + + + +2009-11-13T07:14:26.000000Z +b03a45849ce8295e3ece0f1517970ddc +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +846 + +TDUppercaseWordTest.m +file + + + + +2009-07-03T19:31:28.000000Z +050945e5899585fdd70e5e60b731a84a +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1249 + +TDParserTest.h +file + + + + +2009-07-03T19:31:29.000000Z +ea76cf420d46f291c2b7276f2b22bce5 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +273 + +TDTokenArraySourceTest.h +file + + + + +2009-07-03T19:31:27.000000Z +7e19e396803368a2902f5662e849c768 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +324 + +TDParserTest.m +file + + + + +2009-09-17T19:30:36.000000Z +e6ad2b3c78a48d9dceac3aa49006d8c8 +2009-09-17T22:12:38.271967Z +1379 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4782 + +TDTokenArraySourceTest.m +file + + + + +2009-11-13T07:14:26.000000Z +e6712ed28dd034ac13181dabd4c87ca7 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1476 + +XPathParserGrammarTest.h +file + + + + +2009-06-30T06:13:05.000000Z +9d522d9d9004432f8ae10545fb0cae26 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +352 + +XPathParserGrammarTest.m +file + + + + +2009-08-29T06:08:45.000000Z +a74ff6dbb140d0d93c0206ebafe2b847 +2009-08-29T06:10:20.621428Z +1361 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +9837 + +XPathContext.h +file + + + + +2009-07-03T19:31:20.000000Z +04a4afc62d7703c1c165944438a65203 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +684 + +TDXmlNameState.h +file + + + + +2009-07-03T19:31:21.000000Z +c889bedb1a2769a01d2ba52809c5d96c +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +232 + +TDFastJsonParser.h +file + + + + +2009-07-03T19:31:24.000000Z +3d7457e7330d3dbed06a70d467955c4d +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +392 + +XPathContext.m +file + + + + +2009-07-03T19:31:20.000000Z +5eb5b9a2c025abbf25fa0353dccd4dab +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +618 + +TDXmlNameState.m +file + + + + +2009-07-03T19:31:21.000000Z +9f877f1308ddefb885cff239dd086fb4 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2066 + +TDPlistParserTest.h +file + + + + +2009-07-03T19:31:24.000000Z +ab79893b4ca7efcb2d749f9e490c9dc6 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +340 + +TDFastJsonParser.m +file + + + + +2009-11-13T07:14:26.000000Z +3b635157b15f8a2bc9db3a998860fa5d +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +3802 + +TDTokenizerTest.h +file + + + + +2009-09-17T01:59:11.000000Z +cd4aaf465d59655ee9e975e67908bd8e +2009-09-17T06:13:16.719223Z +1374 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +284 + +TDPlistParserTest.m +file + + + + +2009-09-17T22:35:08.000000Z +fb89622a76377a37a3640f1a40a872e2 +2009-09-17T22:46:20.790207Z +1382 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +13750 + +TDTokenizerTest.m +file + + + + +2009-07-03T19:31:31.000000Z +f6499167b3dd9aea538b2b0cfdc93e81 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +15734 + +TDHtmlSyntaxHighlighter.h +file + + + + +2009-07-03T19:42:56.000000Z +3933998c13f8ebeac05cb66c2089eefd +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1644 + +TDHtmlSyntaxHighlighter.m +file + + + + +2009-11-13T07:14:26.000000Z +978961fdab15faa781801d1e06a281b0 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +21248 + +TDArithmeticParser.h +file + + + + +2009-09-16T05:22:36.000000Z +5effef34f326c175b2a2bc2407a45f94 +2009-09-16T05:35:05.447616Z +1372 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1118 + +TDTokenizerBlocksTest.h +file + + + + +2009-09-17T01:59:26.000000Z +c79054140fbdd7f534af11cca100f1dd +2009-09-17T06:13:16.719223Z +1374 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +296 + +TDArithmeticParser.m +file + + + + +2009-09-16T05:22:44.000000Z +5fa64eb3b89854341cc6e2561e237ab1 +2009-09-16T05:35:05.447616Z +1372 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +6614 + +TDTokenizerBlocksTest.m +file + + + + +2009-09-26T03:40:29.000000Z +a2e7f6a7a3752158bf674ee5a7fcd4c0 +2009-09-26T03:50:36.795525Z +1400 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +740 + +TDSpecificCharTest.h +file + + + + +2009-07-03T19:31:25.000000Z +17e11a0ed2e897eab13f9c65b185fccd +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +317 + +TDJavaScriptParser.h +file + + + + +2009-07-03T19:42:56.000000Z +f1954e123e01347ffda436324f849522 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +15954 + +TDSpecificCharTest.m +file + + + + +2009-09-26T05:55:06.000000Z +f8dc6fdf61e4f62967c5e9ca2a0b44c6 +2009-09-26T19:12:29.746961Z +1403 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1298 + +TDJavaScriptParser.m +file + + + + +2009-07-13T03:30:23.000000Z +a9faf60f13f4082cb58e3aa220d75354 +2009-07-13T03:32:51.609563Z +1218 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +71093 + +PKAST.h +file + + + + +2009-07-12T02:41:15.000000Z +63835387e7736938fbc39e70450e0541 +2009-07-12T02:42:38.222853Z +1212 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +415 + +PKAST.m +file + + + + +2009-07-12T02:48:02.000000Z +5d0ba42d84f9338d83f8db07f89e4813 +2009-07-12T02:42:38.222853Z +1212 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1686 + +TDNCName.h +file + + + + +2009-07-03T19:31:20.000000Z +25287f3be9f9a862cadffc5b6fe922dc +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +378 + +SRGSParser.h +file + + + + +2009-07-03T19:42:56.000000Z +f002acc2a9dec94fd149864f19cc9d25 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3781 + +TDNCName.m +file + + + + +2009-07-03T19:31:20.000000Z +58f93ebd30137558689e40f8525ed2ee +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +524 + +SRGSParser.m +file + + + + +2009-08-06T04:01:55.000000Z +33ce73fbcc6ad51926728b5707db40a1 +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +22158 + +TDSequenceTest.h +file + + + + +2009-07-03T19:31:28.000000Z +fbc3234326f9d0a579cd9c44df49ae17 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +287 + +TDReservedWordTest.h +file + + + + +2009-07-03T19:31:28.000000Z +5e70a5f97bb7c5e6f68a34e29d47c82d +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +233 + +TDSequenceTest.m +file + + + + +2009-11-13T07:14:26.000000Z +776c9a538b97617c228f8853b5851e50 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +6731 + +TDCharTest.h +file + + + + +2009-07-03T19:31:26.000000Z +43eac4a7ea114dd6617f97ff57fb0ff8 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +301 + +TDReservedWordTest.m +file + + + + +2009-07-03T19:31:28.000000Z +80088a99f0ebc9994c8a5ecb6c32bc60 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +955 + +TDCharTest.m +file + + + + +2009-09-26T05:55:45.000000Z +7bd9861340f1feedbbd03dfd67e656c4 +2009-09-26T19:12:29.746961Z +1403 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1225 + +TDPredicateEvaluator.h +file + + + + +2009-07-03T19:42:56.000000Z +1d12f7c42239780f2eafac22455e63c1 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3834 + +TDXmlFragment.h +file + + + + +2009-07-03T19:31:22.000000Z +ebecdfb53ee8eb3f591bb658717872b1 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +277 + +TDNonReservedWord.h +file + + + + +2009-07-03T19:31:17.000000Z +0d4e8ccd56403866f503902f46eb1e17 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +261 + +TDPredicateEvaluator.m +file + + + + +2009-09-16T05:10:03.000000Z +172be784d4601877caae968feb10e264 +2009-09-16T05:10:42.142005Z +1371 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +21739 + +TDXmlFragment.m +file + + + + +2009-11-13T07:14:26.000000Z +6bbcf54bb5bc664801dd5719d679b09b +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +851 + +TDDifferenceTest.h +file + + + + +2009-07-03T18:05:31.000000Z +ff3a97721b0041c259a67e3e54b1d132 +2009-07-03T18:21:46.347810Z +1162 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +346 + +XMLReaderTest.h +file + + + + +2009-07-03T19:31:21.000000Z +cbb518f9547de4bc092f53e08152d961 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +245 + +TDNonReservedWord.m +file + + + + +2009-11-13T07:14:26.000000Z +a1d73198ceb812338cb45c7047dfae6b +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +588 + +PKParseTreeAssembler.h +file + + + + +2009-08-06T04:02:00.000000Z +47d76ad742010dc6d2e4389887965316 +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +363 + +TDDifferenceTest.m +file + + + + +2009-07-03T18:18:30.000000Z +4d073e70fd9eeccc898806e4563878d2 +2009-07-03T18:21:46.347810Z +1162 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3145 + +PKParseTreeAssembler.m +file + + + + +2009-11-13T07:14:26.000000Z +a8f11e99e5049bdbb81a18683830ba7a +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +5143 + +XMLReaderTest.m +file + + + + +2009-07-03T19:31:21.000000Z +b611a80dbbfe08d4cb90e50dac4fa8f5 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +595 + +TDArithmeticParserTest.h +file + + + + +2009-09-16T05:31:33.000000Z +818a17fc44778357bd4176a9506dace0 +2009-09-16T05:35:05.447616Z +1372 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +334 + +TDArithmeticParserTest.m +file + + + + +2009-09-16T05:23:10.000000Z +940611be4e260bd120fd5dbce85b6aec +2009-09-16T05:35:05.447616Z +1372 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +5815 + +TDTokenizerStateTest.h +file + + + + +2009-07-12T22:33:57.000000Z +51bd5e58be8cc9315eb5896020a817e3 +2009-07-12T23:22:41.730758Z +1213 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +291 + +TDTokenAssemblyTest.h +file + + + + +2009-07-03T19:31:28.000000Z +0cd9c68596ce1767e88ee175329bbaf9 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +287 + +TDTokenizerStateTest.m +file + + + + +2009-11-13T07:14:26.000000Z +1d50bedf4eafd033375841bb0908763e +2009-11-06T01:42:40.664388Z +1410 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +4565 + +TDNSPredicateEvaluatorTest.h +file + + + + +2009-06-30T06:13:11.000000Z +425ab12a70361eda2080b44753db6977 +2009-06-30T06:20:20.789257Z +1115 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +447 + +TDTokenAssemblyTest.m +file + + + + +2009-11-13T07:14:26.000000Z +d4fcc9f9df9e6dbdab888d18cf9b93d3 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +7451 + +TDNSPredicateEvaluatorTest.m +file + + + + +2009-11-13T07:14:27.000000Z +a92552c68e72bc340508329d043a7959 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +8094 + +TDWhitespaceStateTest.h +file + + + + +2009-07-03T19:31:27.000000Z +cfdbb1f7f09e2dd4f94d4cb66e23fabf +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +310 + +EBNFParserTest.h +file + + + + +2009-07-03T19:31:25.000000Z +bfdba8092f6180dd3a236360f2f8d390 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +225 + +SAXAssembler.h +file + + + + +2009-08-17T07:54:31.000000Z +b36099df0481fec8c6c9657655d018e9 +2009-08-23T05:03:45.633098Z +1347 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +225 + +TDWhitespaceStateTest.m +file + + + + +2009-07-03T19:31:26.000000Z +be15d6540c7094521e1bfe5e47001fa1 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +9094 + +TDNCNameState.h +file + + + + +2009-07-03T19:31:20.000000Z +4b3cba4507b59ba90ba318e574fe84e7 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +234 + +TDCommentStateTest.h +file + + + + +2009-07-03T19:31:26.000000Z +cb6bb29e297f7b8525a532021064f435 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +339 + +EBNFParserTest.m +file + + + + +2009-07-03T19:31:25.000000Z +cf74c9841f8278a01f82bea8df5d4b2b +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1083 + +TDNegationTest.h +file + + + + +2009-07-03T18:03:21.000000Z +bac0e787ebbde25223f49b889c545a0f +2009-07-03T18:21:46.347810Z +1162 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +323 + +SAXAssembler.m +file + + + + +2009-08-28T04:17:48.000000Z +19f2a4775362554222e7f1611f21fd26 +2009-08-28T04:20:40.336564Z +1354 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +282 + +TDNCNameState.m +file + + + + +2009-07-03T19:31:20.000000Z +f4ca92db26c2578b85eba25b688560d3 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1978 + +TDCommentStateTest.m +file + + + + +2009-11-13T07:14:27.000000Z +0be9b512c35106002bf2f01492f67c2c +2009-11-06T01:42:40.664388Z +1410 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +13284 + +TDNegationTest.m +file + + + + +2009-07-03T18:14:40.000000Z +a38ddac4edbee2651da520dbc26bc3a7 +2009-07-03T18:21:46.347810Z +1162 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1409 + +TDSlashState.h +file + + + + +2009-07-03T19:42:56.000000Z +4f951e496e8e1daaf3f7ea48f1cabf72 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +656 + +TDSignificantWhitespaceStateTest.h +file + + + + +2009-07-03T19:31:17.000000Z +5ad90845509de2c93214fd4e950489dc +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +392 + +TDSlashState.m +file + + + + +2009-07-03T19:42:56.000000Z +d275b1c1fb78c9ab6592d3195117e6ab +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1546 + +TDSignificantWhitespaceStateTest.m +file + + + + +2009-07-03T19:31:12.000000Z +919789bfd61e64435ab5f97f8a44558b +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4759 + +TDJsonParser.h +file + + + + +2009-09-16T04:19:54.000000Z +3b9357a548d01ef00a76d28eaad197dc +2009-09-16T04:21:10.758194Z +1367 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1358 + +TDNumberStateTest.h +file + + + + +2009-07-03T19:31:27.000000Z +f57dad10c394d2a1c49f5058afa10592 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +315 + +TDJsonParser.m +file + + + + +2009-11-13T07:14:27.000000Z +d052138524daebc4bc25ea9515858b8b +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +9187 + +PKParseTree.h +file + + + + +2009-08-06T04:02:00.000000Z +e32c2a87f3dfb7c00590171ae5cde1dd +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +765 + +TDNumberStateTest.m +file + + + + +2009-07-03T19:31:27.000000Z +d8e0315300bfb69148c3b9b5a927ad05 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +17066 + +TDLetterTest.h +file + + + + +2009-07-03T19:31:26.000000Z +8016e4fbe99b60741f1ae96542d48c8d +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +305 + +PKParseTree.m +file + + + + +2009-08-06T04:02:04.000000Z +599bb33ef0d8516b8d32b53257f00ded +2009-08-17T01:06:48.172726Z +1331 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1896 + +TDLetterTest.m +file + + + + +2009-09-26T05:55:30.000000Z +59491f269dd6075b788ed58a23fbf093 +2009-09-26T19:12:29.746961Z +1403 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1213 + +TDSlashStarState.h +file + + + + +2009-07-03T19:31:13.000000Z +26be3db72f553c8abe181b398c7719ab +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +455 + +TDSlashSlashState.h +file + + + + +2009-07-03T19:31:13.000000Z +b10796bb184f44d824d2ce1f03e4bf61 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +443 + +TDSlashStarState.m +file + + + + +2009-07-03T19:31:11.000000Z +268d4030d03e0ed4cd6f541f84aae008 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1727 + +TDSlashSlashState.m +file + + + + +2009-07-03T19:31:11.000000Z +0302df5698dd883e969ce7e972f0d656 +2009-07-03T19:33:03.768692Z +1170 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +1241 + +PKExclusion.h +file + + + + +2009-07-03T18:46:13.000000Z +be4957ba710f46ce7e2bcb70f70fccdf +2009-07-03T18:51:49.968882Z +1166 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +259 + +TDTestScaffold.h +file + + + + +2009-09-17T06:15:07.000000Z +546d3561ffbcc6c7e77f46ac94cacf6d +2009-09-17T06:18:52.723802Z +1375 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +545 + +PKExclusion.m +file + + + + +2009-07-03T19:27:30.000000Z +a3b977932d663bd30c7ce3b998e5aaae +2009-07-03T19:28:44.824677Z +1168 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1643 + +TDTestScaffold.m +file + + + + +2009-09-26T03:40:29.000000Z +0985afb1737f71e6640e0319721c0074 +2009-09-26T03:50:36.795525Z +1400 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +5312 + +TDXmlDoctype.h +file + + + + +2009-07-03T19:31:23.000000Z +e3e6e09b0710d12756f8fafdd7aef261 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +275 + +TDXmlDoctype.m +file + + + + +2009-11-13T07:14:27.000000Z +f9ab685c8393df411c2a1fdd2af16a30 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +846 + +TDXmlProcessingInstruction.h +file + + + + +2009-07-03T19:31:22.000000Z +fdb928042131a1c1d9a2028be1d3a8f1 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +331 + +SAXTest.h +file + + + + +2009-08-17T07:56:03.000000Z +ec3072723d435ee83bd561e649d403b1 +2009-08-23T05:03:45.633098Z +1347 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +360 + +TDXmlProcessingInstruction.m +file + + + + +2009-11-13T07:14:27.000000Z +86d832e63afb86ba53afaca84bcdd302 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +945 + +TDPlistParser.h +file + + + + +2009-09-16T04:17:16.000000Z +25e48391eb619790e8860e9704c5d20f +2009-09-16T04:21:10.758194Z +1367 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +1168 + +SAXTest.m +file + + + + +2009-08-29T06:09:13.000000Z +f1a5432770ad7c3c9aa070cc9be7656d +2009-08-29T06:10:20.621428Z +1361 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +591 + +TDExclusionTest.h +file + + + + +2009-07-03T18:51:08.000000Z +379243a38b311998fdca9c6b13f1ef46 +2009-07-03T04:02:20.986832Z +1153 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +306 + +TDGenericAssembler.h +file + + + + +2009-07-27T04:40:05.000000Z +ef2e9f5e9143d0248c139faf474abf9f +2009-07-27T04:54:34.746113Z +1261 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +716 + +TDPlistParser.m +file + + + + +2009-11-13T07:14:27.000000Z +c72e5f1482f70caddfa9fd09db224606 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +9157 + +TDExclusionTest.m +file + + + + +2009-07-03T18:49:23.000000Z +962961c0bfc6952fe69b65fd2f574155 +2009-07-03T04:02:20.986832Z +1153 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +867 + +TDGenericAssembler.m +file + + + + +2009-11-13T07:14:27.000000Z +dcfc32d7f2b8be60e6207e205d0433e4 +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +5159 + +TDAlternationTest.h +file + + + + +2009-07-03T19:31:29.000000Z +74f99d629dbc7a9ef33dbfd8451c1465 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +293 + +TDXmlEndTag.h +file + + + + +2009-07-03T19:31:23.000000Z +381e060bbf078627d19c5ff8048f7cea +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +271 + +TDRobotCommandTest.h +file + + + + +2009-07-03T19:31:28.000000Z +b0459b610f2fdebeb91a8c1f377ee246 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +233 + +TDAlternationTest.m +file + + + + +2009-07-14T03:29:56.000000Z +254c5e240831086072fccb33c210d463 +2009-07-14T03:32:39.769371Z +1225 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +2535 + +TDJsonParserTest.h +file + + + + +2009-07-03T19:31:24.000000Z +7a18c87249dfd2861886d1b94cfa7107 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +331 + +TDXmlEndTag.m +file + + + + +2009-11-13T07:14:27.000000Z +5d08c90d836effe796a056ac6eb5d83d +2009-10-07T21:46:32.347945Z +1404 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +840 + +TDRobotCommandTest.m +file + + + + +2009-08-06T04:01:56.000000Z +b29759c6fe013de040f65df83508789e +2009-08-03T00:23:08.034904Z +1276 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +4671 + +TDJsonParserTest.m +file + + + + +2009-11-13T07:14:27.000000Z +2052082900ce538058f977a6cad97524 +2009-10-07T23:23:48.841577Z +1405 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +22938 + +TDXmlCdata.h +file + + + + +2009-07-03T19:31:23.000000Z +7e83246098207786b28b7c7d70c10210 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +267 + +TDXmlNmtokenState.h +file + + + + +2009-07-03T19:31:20.000000Z +40cd46893da81bd20c3c29dd6dac77e0 +2009-07-03T19:36:16.806225Z +1171 +todd.ditchendorf +has-props + + + + + + + + + + + + + + + + + + + + +234 + diff --git a/test/.svn/prop-base/TDAlternationTest.h.svn-base b/test/.svn/prop-base/TDAlternationTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDAlternationTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDAlternationTest.m.svn-base b/test/.svn/prop-base/TDAlternationTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDAlternationTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDCharTest.h.svn-base b/test/.svn/prop-base/TDCharTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDCharTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDCharTest.m.svn-base b/test/.svn/prop-base/TDCharTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDCharTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDCharacterAssemblyTest.h.svn-base b/test/.svn/prop-base/TDCharacterAssemblyTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDCharacterAssemblyTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDCharacterAssemblyTest.m.svn-base b/test/.svn/prop-base/TDCharacterAssemblyTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDCharacterAssemblyTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDDigitTest.h.svn-base b/test/.svn/prop-base/TDDigitTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDDigitTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDDigitTest.m.svn-base b/test/.svn/prop-base/TDDigitTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDDigitTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDFastJsonParser.h.svn-base b/test/.svn/prop-base/TDFastJsonParser.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDFastJsonParser.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDFastJsonParser.m.svn-base b/test/.svn/prop-base/TDFastJsonParser.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDFastJsonParser.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDFastJsonParserTest.h.svn-base b/test/.svn/prop-base/TDFastJsonParserTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDFastJsonParserTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDFastJsonParserTest.m.svn-base b/test/.svn/prop-base/TDFastJsonParserTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDFastJsonParserTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDHtmlSyntaxHighlighter.h.svn-base b/test/.svn/prop-base/TDHtmlSyntaxHighlighter.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDHtmlSyntaxHighlighter.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDHtmlSyntaxHighlighter.m.svn-base b/test/.svn/prop-base/TDHtmlSyntaxHighlighter.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDHtmlSyntaxHighlighter.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDJsonParser.h.svn-base b/test/.svn/prop-base/TDJsonParser.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDJsonParser.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDJsonParser.m.svn-base b/test/.svn/prop-base/TDJsonParser.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDJsonParser.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDJsonParserTest.h.svn-base b/test/.svn/prop-base/TDJsonParserTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDJsonParserTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDJsonParserTest.m.svn-base b/test/.svn/prop-base/TDJsonParserTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDJsonParserTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDLetterTest.h.svn-base b/test/.svn/prop-base/TDLetterTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDLetterTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDLetterTest.m.svn-base b/test/.svn/prop-base/TDLetterTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDLetterTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDLiteralTest.h.svn-base b/test/.svn/prop-base/TDLiteralTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDLiteralTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDLiteralTest.m.svn-base b/test/.svn/prop-base/TDLiteralTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDLiteralTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDLowercaseWordTest.h.svn-base b/test/.svn/prop-base/TDLowercaseWordTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDLowercaseWordTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDLowercaseWordTest.m.svn-base b/test/.svn/prop-base/TDLowercaseWordTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDLowercaseWordTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDMiniCSSAssembler.h.svn-base b/test/.svn/prop-base/TDMiniCSSAssembler.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDMiniCSSAssembler.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDMiniCSSAssembler.m.svn-base b/test/.svn/prop-base/TDMiniCSSAssembler.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDMiniCSSAssembler.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDMiniCSSAssemblerTest.h.svn-base b/test/.svn/prop-base/TDMiniCSSAssemblerTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDMiniCSSAssemblerTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDMiniCSSAssemblerTest.m.svn-base b/test/.svn/prop-base/TDMiniCSSAssemblerTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDMiniCSSAssemblerTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDNCName.h.svn-base b/test/.svn/prop-base/TDNCName.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDNCName.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDNCName.m.svn-base b/test/.svn/prop-base/TDNCName.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDNCName.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDNCNameState.h.svn-base b/test/.svn/prop-base/TDNCNameState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDNCNameState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDNCNameState.m.svn-base b/test/.svn/prop-base/TDNCNameState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDNCNameState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDNonReservedWord.h.svn-base b/test/.svn/prop-base/TDNonReservedWord.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDNonReservedWord.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDNonReservedWord.m.svn-base b/test/.svn/prop-base/TDNonReservedWord.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDNonReservedWord.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDNumberStateTest.h.svn-base b/test/.svn/prop-base/TDNumberStateTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDNumberStateTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDNumberStateTest.m.svn-base b/test/.svn/prop-base/TDNumberStateTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDNumberStateTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDParserFactoryTest.h.svn-base b/test/.svn/prop-base/TDParserFactoryTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDParserFactoryTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDParserFactoryTest.m.svn-base b/test/.svn/prop-base/TDParserFactoryTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDParserFactoryTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDParserTest.h.svn-base b/test/.svn/prop-base/TDParserTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDParserTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDParserTest.m.svn-base b/test/.svn/prop-base/TDParserTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDParserTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDQuoteStateTest.h.svn-base b/test/.svn/prop-base/TDQuoteStateTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDQuoteStateTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDQuoteStateTest.m.svn-base b/test/.svn/prop-base/TDQuoteStateTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDQuoteStateTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDReaderTest.h.svn-base b/test/.svn/prop-base/TDReaderTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDReaderTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDReaderTest.m.svn-base b/test/.svn/prop-base/TDReaderTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDReaderTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDRegularParser.h.svn-base b/test/.svn/prop-base/TDRegularParser.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDRegularParser.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDRegularParser.m.svn-base b/test/.svn/prop-base/TDRegularParser.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDRegularParser.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDRegularParserTest.h.svn-base b/test/.svn/prop-base/TDRegularParserTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDRegularParserTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDRegularParserTest.m.svn-base b/test/.svn/prop-base/TDRegularParserTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDRegularParserTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDRepetitionTest.h.svn-base b/test/.svn/prop-base/TDRepetitionTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDRepetitionTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDRepetitionTest.m.svn-base b/test/.svn/prop-base/TDRepetitionTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDRepetitionTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDReservedWord.h.svn-base b/test/.svn/prop-base/TDReservedWord.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDReservedWord.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDReservedWord.m.svn-base b/test/.svn/prop-base/TDReservedWord.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDReservedWord.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDReservedWordTest.h.svn-base b/test/.svn/prop-base/TDReservedWordTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDReservedWordTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDReservedWordTest.m.svn-base b/test/.svn/prop-base/TDReservedWordTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDReservedWordTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDRobotCommandTest.h.svn-base b/test/.svn/prop-base/TDRobotCommandTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDRobotCommandTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDRobotCommandTest.m.svn-base b/test/.svn/prop-base/TDRobotCommandTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDRobotCommandTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSequenceTest.h.svn-base b/test/.svn/prop-base/TDSequenceTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSequenceTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSequenceTest.m.svn-base b/test/.svn/prop-base/TDSequenceTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSequenceTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSignificantWhitespaceState.h.svn-base b/test/.svn/prop-base/TDSignificantWhitespaceState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSignificantWhitespaceState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSignificantWhitespaceState.m.svn-base b/test/.svn/prop-base/TDSignificantWhitespaceState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSignificantWhitespaceState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSignificantWhitespaceStateTest.h.svn-base b/test/.svn/prop-base/TDSignificantWhitespaceStateTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSignificantWhitespaceStateTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSignificantWhitespaceStateTest.m.svn-base b/test/.svn/prop-base/TDSignificantWhitespaceStateTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSignificantWhitespaceStateTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSlashSlashState.h.svn-base b/test/.svn/prop-base/TDSlashSlashState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSlashSlashState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSlashSlashState.m.svn-base b/test/.svn/prop-base/TDSlashSlashState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSlashSlashState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSlashStarState.h.svn-base b/test/.svn/prop-base/TDSlashStarState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSlashStarState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSlashStarState.m.svn-base b/test/.svn/prop-base/TDSlashStarState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSlashStarState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSlashState.h.svn-base b/test/.svn/prop-base/TDSlashState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSlashState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSlashState.m.svn-base b/test/.svn/prop-base/TDSlashState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSlashState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSlashStateTest.h.svn-base b/test/.svn/prop-base/TDSlashStateTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSlashStateTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSlashStateTest.m.svn-base b/test/.svn/prop-base/TDSlashStateTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSlashStateTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSpecificCharTest.h.svn-base b/test/.svn/prop-base/TDSpecificCharTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSpecificCharTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSpecificCharTest.m.svn-base b/test/.svn/prop-base/TDSpecificCharTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSpecificCharTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSymbolStateTest.h.svn-base b/test/.svn/prop-base/TDSymbolStateTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSymbolStateTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSymbolStateTest.m.svn-base b/test/.svn/prop-base/TDSymbolStateTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSymbolStateTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSymbolTest.h.svn-base b/test/.svn/prop-base/TDSymbolTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSymbolTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSymbolTest.m.svn-base b/test/.svn/prop-base/TDSymbolTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSymbolTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSyntaxHighlighter.h.svn-base b/test/.svn/prop-base/TDSyntaxHighlighter.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSyntaxHighlighter.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDSyntaxHighlighter.m.svn-base b/test/.svn/prop-base/TDSyntaxHighlighter.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDSyntaxHighlighter.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTestScaffold.h.svn-base b/test/.svn/prop-base/TDTestScaffold.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTestScaffold.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTestScaffold.m.svn-base b/test/.svn/prop-base/TDTestScaffold.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTestScaffold.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTokenArraySourceTest.h.svn-base b/test/.svn/prop-base/TDTokenArraySourceTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTokenArraySourceTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTokenArraySourceTest.m.svn-base b/test/.svn/prop-base/TDTokenArraySourceTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTokenArraySourceTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTokenAssemblyTest.h.svn-base b/test/.svn/prop-base/TDTokenAssemblyTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTokenAssemblyTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTokenAssemblyTest.m.svn-base b/test/.svn/prop-base/TDTokenAssemblyTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTokenAssemblyTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTokenizerTest.h.svn-base b/test/.svn/prop-base/TDTokenizerTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTokenizerTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTokenizerTest.m.svn-base b/test/.svn/prop-base/TDTokenizerTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTokenizerTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTrackTest.h.svn-base b/test/.svn/prop-base/TDTrackTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTrackTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDTrackTest.m.svn-base b/test/.svn/prop-base/TDTrackTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDTrackTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDUppercaseWordTest.h.svn-base b/test/.svn/prop-base/TDUppercaseWordTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDUppercaseWordTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDUppercaseWordTest.m.svn-base b/test/.svn/prop-base/TDUppercaseWordTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDUppercaseWordTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDWhitespaceStateTest.h.svn-base b/test/.svn/prop-base/TDWhitespaceStateTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDWhitespaceStateTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDWhitespaceStateTest.m.svn-base b/test/.svn/prop-base/TDWhitespaceStateTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDWhitespaceStateTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDWordOrReservedState.h.svn-base b/test/.svn/prop-base/TDWordOrReservedState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDWordOrReservedState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDWordOrReservedState.m.svn-base b/test/.svn/prop-base/TDWordOrReservedState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDWordOrReservedState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDWordStateTest.h.svn-base b/test/.svn/prop-base/TDWordStateTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDWordStateTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDWordStateTest.m.svn-base b/test/.svn/prop-base/TDWordStateTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDWordStateTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlAttribute.h.svn-base b/test/.svn/prop-base/TDXmlAttribute.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlAttribute.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlAttribute.m.svn-base b/test/.svn/prop-base/TDXmlAttribute.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlAttribute.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlCdata.h.svn-base b/test/.svn/prop-base/TDXmlCdata.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlCdata.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlCdata.m.svn-base b/test/.svn/prop-base/TDXmlCdata.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlCdata.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlComment.h.svn-base b/test/.svn/prop-base/TDXmlComment.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlComment.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlComment.m.svn-base b/test/.svn/prop-base/TDXmlComment.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlComment.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlDecl.h.svn-base b/test/.svn/prop-base/TDXmlDecl.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlDecl.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlDecl.m.svn-base b/test/.svn/prop-base/TDXmlDecl.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlDecl.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlDoctype.h.svn-base b/test/.svn/prop-base/TDXmlDoctype.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlDoctype.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlDoctype.m.svn-base b/test/.svn/prop-base/TDXmlDoctype.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlDoctype.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlDocument.h.svn-base b/test/.svn/prop-base/TDXmlDocument.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlDocument.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlDocument.m.svn-base b/test/.svn/prop-base/TDXmlDocument.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlDocument.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlEndEntity.h.svn-base b/test/.svn/prop-base/TDXmlEndEntity.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlEndEntity.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlEndEntity.m.svn-base b/test/.svn/prop-base/TDXmlEndEntity.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlEndEntity.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlEndTag.h.svn-base b/test/.svn/prop-base/TDXmlEndTag.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlEndTag.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlEndTag.m.svn-base b/test/.svn/prop-base/TDXmlEndTag.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlEndTag.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlEntity.h.svn-base b/test/.svn/prop-base/TDXmlEntity.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlEntity.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlEntity.m.svn-base b/test/.svn/prop-base/TDXmlEntity.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlEntity.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlEntityRef.h.svn-base b/test/.svn/prop-base/TDXmlEntityRef.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlEntityRef.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlEntityRef.m.svn-base b/test/.svn/prop-base/TDXmlEntityRef.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlEntityRef.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlFragment.h.svn-base b/test/.svn/prop-base/TDXmlFragment.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlFragment.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlFragment.m.svn-base b/test/.svn/prop-base/TDXmlFragment.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlFragment.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlName.h.svn-base b/test/.svn/prop-base/TDXmlName.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlName.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlName.m.svn-base b/test/.svn/prop-base/TDXmlName.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlName.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNameState.h.svn-base b/test/.svn/prop-base/TDXmlNameState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNameState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNameState.m.svn-base b/test/.svn/prop-base/TDXmlNameState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNameState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNameTest.h.svn-base b/test/.svn/prop-base/TDXmlNameTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNameTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNameTest.m.svn-base b/test/.svn/prop-base/TDXmlNameTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNameTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNmtoken.h.svn-base b/test/.svn/prop-base/TDXmlNmtoken.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNmtoken.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNmtoken.m.svn-base b/test/.svn/prop-base/TDXmlNmtoken.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNmtoken.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNmtokenState.h.svn-base b/test/.svn/prop-base/TDXmlNmtokenState.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNmtokenState.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNmtokenState.m.svn-base b/test/.svn/prop-base/TDXmlNmtokenState.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNmtokenState.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNotation.h.svn-base b/test/.svn/prop-base/TDXmlNotation.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNotation.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlNotation.m.svn-base b/test/.svn/prop-base/TDXmlNotation.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlNotation.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlProcessingInstruction.h.svn-base b/test/.svn/prop-base/TDXmlProcessingInstruction.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlProcessingInstruction.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlProcessingInstruction.m.svn-base b/test/.svn/prop-base/TDXmlProcessingInstruction.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlProcessingInstruction.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlSignificantWhitespace.h.svn-base b/test/.svn/prop-base/TDXmlSignificantWhitespace.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlSignificantWhitespace.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlSignificantWhitespace.m.svn-base b/test/.svn/prop-base/TDXmlSignificantWhitespace.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlSignificantWhitespace.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlStartTag.h.svn-base b/test/.svn/prop-base/TDXmlStartTag.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlStartTag.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlStartTag.m.svn-base b/test/.svn/prop-base/TDXmlStartTag.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlStartTag.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlTerminal.h.svn-base b/test/.svn/prop-base/TDXmlTerminal.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlTerminal.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlTerminal.m.svn-base b/test/.svn/prop-base/TDXmlTerminal.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlTerminal.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlText.h.svn-base b/test/.svn/prop-base/TDXmlText.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlText.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlText.m.svn-base b/test/.svn/prop-base/TDXmlText.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlText.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlToken.h.svn-base b/test/.svn/prop-base/TDXmlToken.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlToken.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlToken.m.svn-base b/test/.svn/prop-base/TDXmlToken.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlToken.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlTokenAssembly.h.svn-base b/test/.svn/prop-base/TDXmlTokenAssembly.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlTokenAssembly.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlTokenAssembly.m.svn-base b/test/.svn/prop-base/TDXmlTokenAssembly.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlTokenAssembly.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlTokenizer.h.svn-base b/test/.svn/prop-base/TDXmlTokenizer.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlTokenizer.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlTokenizer.m.svn-base b/test/.svn/prop-base/TDXmlTokenizer.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlTokenizer.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlTokenizerTest.h.svn-base b/test/.svn/prop-base/TDXmlTokenizerTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlTokenizerTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlTokenizerTest.m.svn-base b/test/.svn/prop-base/TDXmlTokenizerTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlTokenizerTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlWhitespace.h.svn-base b/test/.svn/prop-base/TDXmlWhitespace.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlWhitespace.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/TDXmlWhitespace.m.svn-base b/test/.svn/prop-base/TDXmlWhitespace.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/TDXmlWhitespace.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/XMLReader.h.svn-base b/test/.svn/prop-base/XMLReader.h.svn-base new file mode 100644 index 0000000..8d28d86 --- /dev/null +++ b/test/.svn/prop-base/XMLReader.h.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/XMLReader.m.svn-base b/test/.svn/prop-base/XMLReader.m.svn-base new file mode 100644 index 0000000..8d28d86 --- /dev/null +++ b/test/.svn/prop-base/XMLReader.m.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/XMLReaderTest.h.svn-base b/test/.svn/prop-base/XMLReaderTest.h.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/XMLReaderTest.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/prop-base/XMLReaderTest.m.svn-base b/test/.svn/prop-base/XMLReaderTest.m.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/test/.svn/prop-base/XMLReaderTest.m.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/test/.svn/text-base/EBNFParser.h.svn-base b/test/.svn/text-base/EBNFParser.h.svn-base new file mode 100644 index 0000000..509539c --- /dev/null +++ b/test/.svn/text-base/EBNFParser.h.svn-base @@ -0,0 +1,45 @@ +// +// EBNFParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface EBNFParser : PKRepetition { + PKCollectionParser *statementParser; + PKCollectionParser *exprOrAssignmentParser; + PKCollectionParser *assignmentParser; + PKCollectionParser *declarationParser; + PKCollectionParser *variableParser; + PKCollectionParser *expressionParser; + PKCollectionParser *termParser; + PKCollectionParser *orTermParser; + PKCollectionParser *factorParser; + PKCollectionParser *nextFactorParser; + PKCollectionParser *phraseParser; + PKCollectionParser *phraseStarParser; + PKCollectionParser *phraseQuestionParser; + PKCollectionParser *phrasePlusParser; + PKCollectionParser *atomicValueParser; +} +- (id)parse:(NSString *)s; + +@property (nonatomic, retain) PKCollectionParser *statementParser; +@property (nonatomic, retain) PKCollectionParser *exprOrAssignmentParser; +@property (nonatomic, retain) PKCollectionParser *assignmentParser; +@property (nonatomic, retain) PKCollectionParser *declarationParser; +@property (nonatomic, retain) PKCollectionParser *variableParser; +@property (nonatomic, retain) PKCollectionParser *expressionParser; +@property (nonatomic, retain) PKCollectionParser *termParser; +@property (nonatomic, retain) PKCollectionParser *orTermParser; +@property (nonatomic, retain) PKCollectionParser *factorParser; +@property (nonatomic, retain) PKCollectionParser *nextFactorParser; +@property (nonatomic, retain) PKCollectionParser *phraseParser; +@property (nonatomic, retain) PKCollectionParser *phraseStarParser; +@property (nonatomic, retain) PKCollectionParser *phraseQuestionParser; +@property (nonatomic, retain) PKCollectionParser *phrasePlusParser; +@property (nonatomic, retain) PKCollectionParser *atomicValueParser; +@end diff --git a/test/.svn/text-base/EBNFParser.m.svn-base b/test/.svn/text-base/EBNFParser.m.svn-base new file mode 100644 index 0000000..261e6e5 --- /dev/null +++ b/test/.svn/text-base/EBNFParser.m.svn-base @@ -0,0 +1,427 @@ +// +// EBNFParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "EBNFParser.h" +#import "NSString+ParseKitAdditions.h" + +/* + statement = exprOrAssignment ';' + exprOrAssignment = expression | assigment + assigment = declaration '=' expression + declaration = '$' Word + variable = '$' Word + expression = term orTerm* + term = factor nextFactor* + orTerm = '|' term + factor = phrase | phraseStar | phraseQuestion | phrasePlus + nextFactor = factor + phrase = atomicValue | '(' expression ')' + phraseStar = phrase '*' + phraseQuestion = phrase '?' + phrasePlus = phrase '+' + atomicValue = Word | Number | QuotedString | variable +*/ + +static NSString * const kEBNFEqualsString = @"="; +static NSString * const kEBNFVariablePrefix = @"$"; +static NSString * const kEBNFVariableSuffix = @""; + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface EBNFParser () +- (void)addSymbolString:(NSString *)s toTokenizer:(PKTokenizer *)t; + +- (void)didMatchWord:(PKAssembly *)a; +- (void)didMatchNum:(PKAssembly *)a; +- (void)didMatchQuotedString:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +- (void)didMatchPlus:(PKAssembly *)a; +- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchAssignment:(PKAssembly *)a; +- (void)didMatchVariable:(PKAssembly *)a; +@end + +@implementation EBNFParser + +- (id)init { + if ([super initWithSubparser:self.statementParser]) { + self.tokenizer = [PKTokenizer tokenizer]; + [self addSymbolString:kEBNFEqualsString toTokenizer:self.tokenizer]; + [self addSymbolString:kEBNFVariablePrefix toTokenizer:self.tokenizer]; + [self addSymbolString:kEBNFVariableSuffix toTokenizer:self.tokenizer]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.statementParser = nil; + self.exprOrAssignmentParser = nil; + self.assignmentParser = nil; + self.declarationParser = nil; + self.variableParser = nil; + self.expressionParser = nil; + self.termParser = nil; + self.orTermParser = nil; + self.factorParser = nil; + self.nextFactorParser = nil; + self.phraseParser = nil; + self.phraseStarParser = nil; + self.phraseQuestionParser = nil; + self.phrasePlusParser = nil; + self.atomicValueParser = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + self.tokenizer.string = s; + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:self.tokenizer]; + PKAssembly *result = [self completeMatchFor:a]; + return [result pop]; +} + + +- (void)addSymbolString:(NSString *)s toTokenizer:(PKTokenizer *)t { + if ([s length]) { + NSInteger c = [s characterAtIndex:0]; + [t setTokenizerState:t.symbolState from:c to:c]; + [t.symbolState add:s]; + } +} + + +// statement = exprOrAssignment ';' +- (PKCollectionParser *)statementParser { + if (!statementParser) { + self.statementParser = [PKTrack track]; + [statementParser add:self.exprOrAssignmentParser]; + [statementParser add:[[PKSymbol symbolWithString:@";"] discard]]; + } + return statementParser; +} + + +// exprOrAssignmentParser = expression | assignment +- (PKCollectionParser *)exprOrAssignmentParser { + if (!exprOrAssignmentParser) { + self.exprOrAssignmentParser = [PKAlternation alternation]; + [exprOrAssignmentParser add:self.expressionParser]; + [exprOrAssignmentParser add:self.assignmentParser]; + } + return exprOrAssignmentParser; +} + + +// declaration = variable '=' expression +- (PKCollectionParser *)assignmentParser { + if (!assignmentParser) { + self.assignmentParser = [PKTrack track]; + [assignmentParser add:self.declarationParser]; + [assignmentParser add:[[PKSymbol symbolWithString:kEBNFEqualsString] discard]]; + [assignmentParser add:self.expressionParser]; + [assignmentParser setAssembler:self selector:@selector(didMatchAssignment:)]; + } + return assignmentParser; +} + + +// declaration = '$' Word +- (PKCollectionParser *)declarationParser { + if (!declarationParser) { + self.declarationParser = [PKTrack track]; + [declarationParser add:[[PKSymbol symbolWithString:kEBNFVariablePrefix] discard]]; + [declarationParser add:[PKWord word]]; + if ([kEBNFVariableSuffix length]) { + [declarationParser add:[[PKSymbol symbolWithString:kEBNFVariableSuffix] discard]]; + } + } + return declarationParser; +} + + +// variable = '$' Word +- (PKCollectionParser *)variableParser { + if (!variableParser) { + self.variableParser = [PKTrack track]; + [variableParser add:[[PKSymbol symbolWithString:kEBNFVariablePrefix] discard]]; + [variableParser add:[PKWord word]]; + if ([kEBNFVariableSuffix length]) { + [variableParser add:[[PKSymbol symbolWithString:kEBNFVariableSuffix] discard]]; + } + } + return variableParser; +} + + +// expression = term orTerm* +- (PKCollectionParser *)expressionParser { + if (!expressionParser) { + self.expressionParser = [PKSequence sequence]; + [expressionParser add:self.termParser]; + [expressionParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + } + return expressionParser; +} + + +// term = factor nextFactor* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + [termParser add:self.factorParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.nextFactorParser]]; + } + return termParser; +} + + +// orTerm = '|' term +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKTrack track]; + [orTermParser add:[[PKSymbol symbolWithString:@"|"] discard]]; + [orTermParser add:self.termParser]; + [orTermParser setAssembler:self selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// factor = phrase | phraseStar | phraseQuestion | phrasePlus +- (PKCollectionParser *)factorParser { + if (!factorParser) { + self.factorParser = [PKAlternation alternation]; + [factorParser add:self.phraseParser]; + [factorParser add:self.phraseStarParser]; + [factorParser add:self.phraseQuestionParser]; + [factorParser add:self.phrasePlusParser]; + } + return factorParser; +} + + +// nextFactor = factor +- (PKCollectionParser *)nextFactorParser { + if (!nextFactorParser) { + self.nextFactorParser = [PKAlternation alternation]; + [nextFactorParser add:self.phraseParser]; + [nextFactorParser add:self.phraseStarParser]; + [nextFactorParser add:self.phraseQuestionParser]; + [nextFactorParser add:self.phrasePlusParser]; + [nextFactorParser setAssembler:self selector:@selector(didMatchAnd:)]; + } + return nextFactorParser; +} + + +// phrase = atomicValue | '(' expression ')' +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + PKSequence *s = [PKTrack track]; + [s add:[[PKSymbol symbolWithString:@"("] discard]]; + [s add:self.expressionParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + self.phraseParser = [PKAlternation alternation]; + [phraseParser add:self.atomicValueParser]; + [phraseParser add:s]; + } + return phraseParser; +} + + +// phraseStar = phrase '*' +- (PKCollectionParser *)phraseStarParser { + if (!phraseStarParser) { + self.phraseStarParser = [PKSequence sequence]; + [phraseStarParser add:self.phraseParser]; + [phraseStarParser add:[[PKSymbol symbolWithString:@"*"] discard]]; + [phraseStarParser setAssembler:self selector:@selector(didMatchStar:)]; + } + return phraseStarParser; +} + + +// phraseQuestion = phrase '?' +- (PKCollectionParser *)phraseQuestionParser { + if (!phraseQuestionParser) { + self.phraseQuestionParser = [PKSequence sequence]; + [phraseQuestionParser add:self.phraseParser]; + [phraseQuestionParser add:[[PKSymbol symbolWithString:@"?"] discard]]; + [phraseQuestionParser setAssembler:self selector:@selector(didMatchQuestion:)]; + } + return phraseQuestionParser; +} + + +// phrasePlus = phrase '+' +- (PKCollectionParser *)phrasePlusParser { + if (!phrasePlusParser) { + self.phrasePlusParser = [PKSequence sequence]; + [phrasePlusParser add:self.phraseParser]; + [phrasePlusParser add:[[PKSymbol symbolWithString:@"+"] discard]]; + [phrasePlusParser setAssembler:self selector:@selector(didMatchPlus:)]; + } + return phrasePlusParser; +} + + +// atomicValue = Word | Number | QuotedString | Variable +- (PKCollectionParser *)atomicValueParser { + if (!atomicValueParser) { + self.atomicValueParser = [PKAlternation alternation]; + + PKParser *p = [PKWord word]; + [p setAssembler:self selector:@selector(didMatchWord:)]; + [atomicValueParser add:p]; + + p = [PKNumber number]; + [p setAssembler:self selector:@selector(didMatchNum:)]; + [atomicValueParser add:p]; + + p = [PKQuotedString quotedString]; + [p setAssembler:self selector:@selector(didMatchQuotedString:)]; + [atomicValueParser add:p]; + + p = self.variableParser; + [p setAssembler:self selector:@selector(didMatchVariable:)]; + [atomicValueParser add:p]; + } + return atomicValueParser; +} + + +- (void)didMatchWord:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + [a push:[PKLiteral literalWithString:tok.stringValue]]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + [a push:[PKLiteral literalWithString:tok.stringValue]]; +} + + +- (void)didMatchQuotedString:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + + PKSequence *p = [PKSequence sequence]; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *eof = [PKToken EOFToken]; + while (eof != (tok = [t nextToken])) { + [p add:[PKLiteral literalWithString:tok.stringValue]]; + } + + [a push:p]; +} + + +- (void)didMatchStar:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKRepetition *p = [PKRepetition repetitionWithSubparser:[a pop]]; + [a push:p]; +} + + +- (void)didMatchQuestion:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKAlternation *p = [PKAlternation alternation]; + [p add:[a pop]]; + [p add:[PKEmpty empty]]; + [a push:p]; +} + + +- (void)didMatchPlus:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + PKSequence *p = [PKSequence sequence]; + [p add:top]; + [p add:[PKRepetition repetitionWithSubparser:top]]; + [a push:p]; +} + + +- (void)didMatchAnd:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + PKSequence *p = [PKSequence sequence]; + [p add:[a pop]]; + [p add:top]; + [a push:p]; +} + + +- (void)didMatchOr:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + // NSLog(@"top: %@", top); + // NSLog(@"top class: %@", [top class]); + PKAlternation *p = [PKAlternation alternation]; + [p add:[a pop]]; + [p add:top]; + [a push:p]; +} + + +- (void)didMatchAssignment:(PKAssembly *)a { + NSLog(@"%s", _cmd); + NSLog(@"a: %@", a); + id val = [a pop]; + PKToken *keyTok = [a pop]; + NSMutableDictionary *table = [NSMutableDictionary dictionaryWithDictionary:a.target]; + [table setObject:val forKey:keyTok.stringValue]; + a.target = table; +} + + +- (void)didMatchVariable:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *keyTok = [a pop]; + id val = [a.target objectForKey:keyTok.stringValue]; + if (val) { + [a push:val]; + } +} + +@synthesize statementParser; +@synthesize exprOrAssignmentParser; +@synthesize assignmentParser; +@synthesize declarationParser; +@synthesize variableParser; +@synthesize expressionParser; +@synthesize termParser; +@synthesize orTermParser; +@synthesize factorParser; +@synthesize nextFactorParser; +@synthesize phraseParser; +@synthesize phraseStarParser; +@synthesize phraseQuestionParser; +@synthesize phrasePlusParser; +@synthesize atomicValueParser; +@end \ No newline at end of file diff --git a/test/.svn/text-base/EBNFParserTest.h.svn-base b/test/.svn/text-base/EBNFParserTest.h.svn-base new file mode 100644 index 0000000..e62d42b --- /dev/null +++ b/test/.svn/text-base/EBNFParserTest.h.svn-base @@ -0,0 +1,15 @@ +// +// EBNFParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface EBNFParserTest : SenTestCase { + +} + +@end diff --git a/test/.svn/text-base/EBNFParserTest.m.svn-base b/test/.svn/text-base/EBNFParserTest.m.svn-base new file mode 100644 index 0000000..2563d5c --- /dev/null +++ b/test/.svn/text-base/EBNFParserTest.m.svn-base @@ -0,0 +1,37 @@ +// +// EBNFParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "EBNFParserTest.h" +#import "EBNFParser.h" + +@implementation EBNFParserTest + +- (void)test { + //NSString *s = @"foo (bar|baz)*;"; + NSString *s = @"$baz = bar; ($baz|foo)*;"; + //NSString *s = @"foo;"; + EBNFParser *p = [[[EBNFParser alloc] init] autorelease]; + + // PKAssembly *a = [p bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + // NSLog(@"a: %@", a); + // NSLog(@"a.target: %@", a.target); + + PKParser *res = [p parse:s]; + // NSLog(@"res: %@", res); + // NSLog(@"res: %@", res.string); + // NSLog(@"res.subparsers: %@", res.subparsers); + // NSLog(@"res.subparsers 0: %@", [[res.subparsers objectAtIndex:0] string]); + // NSLog(@"res.subparsers 1: %@", [[res.subparsers objectAtIndex:1] string]); + + s = @"bar foo bar foo"; + PKAssembly *a = [res completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + NSLog(@"\n\na: %@\n\n", a); + +} + +@end diff --git a/test/.svn/text-base/ERBTest.h.svn-base b/test/.svn/text-base/ERBTest.h.svn-base new file mode 100644 index 0000000..a997c20 --- /dev/null +++ b/test/.svn/text-base/ERBTest.h.svn-base @@ -0,0 +1,22 @@ +// +// ERBTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/26/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" + +@interface ERBTest : SenTestCase { + NSString *g; + NSString *s; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; + PKToken *tok; + PKToken *startPrintMarker; +} + +@end diff --git a/test/.svn/text-base/ERBTest.m.svn-base b/test/.svn/text-base/ERBTest.m.svn-base new file mode 100644 index 0000000..cb82089 --- /dev/null +++ b/test/.svn/text-base/ERBTest.m.svn-base @@ -0,0 +1,66 @@ +// +// ERBTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/26/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "ERBTest.h" + +@interface ERBAssembler : NSObject { + +} + +@end + +@implementation ERBAssembler + +- (id)provideValueForKey:(NSString *)k { + return @"hai"; +} + + +- (void)didMatchEndMarker:(PKAssembly *)a { + [a pop]; // '@>' + NSString *k = [a pop]; + [a pop]; // discard '<@=' + [a push:[self provideValueForKey:k]]; +} + + +- (void)didMatchDotWord:(PKAssembly *)a { + PKToken *lastPart = [a pop]; + [a pop]; // '.' + PKToken *firstPart = [a pop]; + + NSString *keyPath = [NSString stringWithFormat:@"%@.%@", + firstPart, lastPart]; + [a push:keyPath]; + // do something with the keyPath +} + +@end + + +@implementation ERBTest + +- (void)setUp { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"erb" ofType:@"grammar"]; + g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + lp = [[PKParserFactory factory] parserFromGrammar:g assembler:[[[ERBAssembler alloc] init] autorelease]]; + t = lp.tokenizer; +// startPrintMarker = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"<@=" floatValue:0]; +} + + +- (void)testFoo { + t.string = @"oh <@= foo.bar @> !"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; +// TDEqualObjects([res description], @"[oh, hai, !]oh/<@=/foo/./bar/@>/!^"); + +} + +@end + diff --git a/test/.svn/text-base/PKAST.h.svn-base b/test/.svn/text-base/PKAST.h.svn-base new file mode 100644 index 0000000..ace9b02 --- /dev/null +++ b/test/.svn/text-base/PKAST.h.svn-base @@ -0,0 +1,27 @@ +// +// PKAST.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKToken; + +@interface PKAST : NSObject { + PKToken *token; + NSMutableArray *children; +} + ++ (id)ASTWithToken:(PKToken *)tok; + +- (id)initWithToken:(PKToken *)tok; + +- (NSInteger)type; + +- (void)addChild:(PKAST *)c; +- (BOOL)isNil; + +@end diff --git a/test/.svn/text-base/PKAST.m.svn-base b/test/.svn/text-base/PKAST.m.svn-base new file mode 100644 index 0000000..2eeb925 --- /dev/null +++ b/test/.svn/text-base/PKAST.m.svn-base @@ -0,0 +1,96 @@ +// +// PKAST.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKAST.h" + +@interface PKAST () +@property (nonatomic, retain) PKToken *token; +@property (nonatomic, retain) NSMutableArray *children; +@end + +@implementation PKAST + ++ (id)ASTWithToken:(PKToken *)tok { + return [[[self alloc] initWithToken:tok] autorelease]; +} + + +- (id)init { + return [self initWithToken:nil]; +} + + +- (id)initWithToken:(PKToken *)tok { + if (self = [super init]) { + self.token = tok; + } + return self; +} + + +- (void)dealloc { + self.token = nil; + self.children = nil; + [super dealloc]; +} + + +- (NSString *)description { + return [token stringValue]; +} + + +- (NSString *)treeDescription { + if (![children count]) { + return [self description]; + } + + NSMutableString *ms = [NSMutableString string]; + + if (![self isNil]) { + [ms appendFormat:@"(%@ ", [self description]]; + } + + NSInteger i = 0; + for (PKAST *child in children) { + if (i++) { + [ms appendFormat:@" %@", child]; + } else { + [ms appendFormat:@"%@", child]; + } + } + + if (![self isNil]) { + [ms appendString:@")"]; + } + + return [[ms copy] autorelease]; +} + + +- (NSInteger)type { + NSAssert2(0, @"%s is an abastract method. Must be overridden in %@", __PRETTY_FUNCTION__, NSStringFromClass([self class])); + return -1; +} + + +- (void)addChild:(PKAST *)c { + if (!children) { + self.children = [NSMutableArray array]; + } + [children addObject:c]; +} + + +- (BOOL)isNil { + return !token; +} + +@synthesize token; +@synthesize children; +@end diff --git a/test/.svn/text-base/PKExclusion.h.svn-base b/test/.svn/text-base/PKExclusion.h.svn-base new file mode 100644 index 0000000..8e47979 --- /dev/null +++ b/test/.svn/text-base/PKExclusion.h.svn-base @@ -0,0 +1,16 @@ +// +// PKExclusion.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface PKExclusion : PKCollectionParser { + +} + ++ (id)exclusion; +@end diff --git a/test/.svn/text-base/PKExclusion.m.svn-base b/test/.svn/text-base/PKExclusion.m.svn-base new file mode 100644 index 0000000..e5b8e2c --- /dev/null +++ b/test/.svn/text-base/PKExclusion.m.svn-base @@ -0,0 +1,76 @@ +// +// PKExclusion.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKExclusion.h" +#import + +@interface NSMutableSet (PKExclusionAdditions) +- (void)exclusiveSetTestingEquality:(NSSet *)s; +@end + +@implementation NSMutableSet (PKExclusionAdditions) + +- (void)exclusiveSetTestingEquality:(NSSet *)s { + for (id a1 in self) { + BOOL found = NO; + for (id a2 in s) { + if ([a1 isEqual:a2 ]) { + found = YES; + break; + } + } + if (found) { + [self removeObject:a1]; + } + } + + for (id a2 in s) { + BOOL found = NO; + for (id a1 in self) { + if ([a2 isEqual:a1]) { + found = YES; + break; + } + } + if (!found) { + [self addObject:a2]; + } + } +} + +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@implementation PKExclusion + ++ (id)exclusion { + return [[[self alloc] init] autorelease]; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSMutableSet *outAssemblies = [NSMutableSet set]; + + NSInteger i = 0; + for (PKParser *p in subparsers) { + if (0 == i++) { + outAssemblies = [[[p matchAndAssemble:inAssemblies] mutableCopy] autorelease]; + } else { + [outAssemblies exclusiveSetTestingEquality:[p allMatchesFor:inAssemblies]]; + } + } + + return outAssemblies; +} + +@end diff --git a/test/.svn/text-base/PKNumberState.h.svn-base b/test/.svn/text-base/PKNumberState.h.svn-base new file mode 100644 index 0000000..734d831 --- /dev/null +++ b/test/.svn/text-base/PKNumberState.h.svn-base @@ -0,0 +1,32 @@ +// +// PKNumberState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class PKNumberState + @brief A number state returns a number from a reader. + @details This state's idea of a number allows an optional, initial minus sign, followed by one or more digits. A decimal point and another string of digits may follow these digits. + If allowsScientificNotation is true (the default) this state allows 'e' or 'E' followed by an (optionally explicityly positive or negative) integer to represent 10 to the indicated power. For example, this state will recognize 1e2 as equaling 100.

+*/ +@interface PKNumberState : PKTokenizerState { + BOOL allowsTrailingDot; + BOOL gotADigit; + BOOL negative; + PKUniChar c; + CGFloat floatValue; +} + +/*! + @property allowsTrailingDot + @brief If true, numbers are allowed to end with a trialing dot, e.g. 42. + @details false by default. +*/ +@property (nonatomic) BOOL allowsTrailingDot; +@end diff --git a/test/.svn/text-base/PKNumberState.m.svn-base b/test/.svn/text-base/PKNumberState.m.svn-base new file mode 100644 index 0000000..055a74d --- /dev/null +++ b/test/.svn/text-base/PKNumberState.m.svn-base @@ -0,0 +1,145 @@ +// +// PKNumberState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface PKNumberState () +- (CGFloat)absorbDigitsFromReader:(PKReader *)r isFraction:(BOOL)fraction; +- (CGFloat)value; +- (void)parseLeftSideFromReader:(PKReader *)r; +- (void)parseRightSideFromReader:(PKReader *)r; +- (void)reset:(PKUniChar)cin; +@end + +@implementation PKNumberState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + [self resetWithReader:r]; + negative = NO; + PKUniChar originalCin = cin; + + if ('-' == cin) { + negative = YES; + cin = [r read]; + [self append:'-']; + } else if ('+' == cin) { + cin = [r read]; + [self append:'+']; + } + + [self reset:cin]; + if ('.' == c) { + [self parseRightSideFromReader:r]; + } else { + [self parseLeftSideFromReader:r]; + [self parseRightSideFromReader:r]; + } + + // erroneous ., +, or - + if (!gotADigit) { + if (negative && PKEOF != c) { // ?? + [r unread]; + } + return [t.symbolState nextTokenFromReader:r startingWith:originalCin tokenizer:t]; + } + + if (PKEOF != c) { + [r unread]; + } + + if (negative) { + floatValue = -floatValue; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:[self bufferedString] floatValue:[self value]]; + tok.offset = offset; + return tok; +} + + +- (CGFloat)value { + return floatValue; +} + + +- (CGFloat)absorbDigitsFromReader:(PKReader *)r isFraction:(BOOL)isFraction { + CGFloat divideBy = 1.0; + CGFloat v = 0.0; + + while (1) { + if (isdigit(c)) { + [self append:c]; + gotADigit = YES; + v = v * 10.0 + (c - '0'); + c = [r read]; + if (isFraction) { + divideBy *= 10.0; + } + } else { + break; + } + } + + if (isFraction) { + v = v / divideBy; + } + + return (CGFloat)v; +} + + +- (void)parseLeftSideFromReader:(PKReader *)r { + floatValue = [self absorbDigitsFromReader:r isFraction:NO]; +} + + +- (void)parseRightSideFromReader:(PKReader *)r { + if ('.' == c) { + PKUniChar n = [r read]; + BOOL nextIsDigit = isdigit(n); + if (PKEOF != n) { + [r unread]; + } + + if (nextIsDigit || allowsTrailingDot) { + [self append:'.']; + if (nextIsDigit) { + c = [r read]; + floatValue += [self absorbDigitsFromReader:r isFraction:YES]; + } + } + } +} + + +- (void)reset:(PKUniChar)cin { + gotADigit = NO; + floatValue = 0.0; + c = cin; +} + +@synthesize allowsTrailingDot; +@end diff --git a/test/.svn/text-base/PKParseTree.h.svn-base b/test/.svn/text-base/PKParseTree.h.svn-base new file mode 100644 index 0000000..57413b9 --- /dev/null +++ b/test/.svn/text-base/PKParseTree.h.svn-base @@ -0,0 +1,31 @@ +// +// PKParseTree.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKRuleNode; +@class PKTokenNode; +@class PKToken; + +@interface PKParseTree : NSObject { + PKParseTree *parent; + NSMutableArray *children; + id userInfo; + BOOL matched; +} ++ (id)parseTree; + +- (PKRuleNode *)addChildRule:(NSString *)name; +- (PKTokenNode *)addChildToken:(PKToken *)tok; +- (void)addChild:(PKParseTree *)tr; + +@property (nonatomic, assign, readonly) PKParseTree *parent; // weak ref +@property (nonatomic, retain, readonly) NSMutableArray *children; +@property (nonatomic, retain) id userInfo; +@property (nonatomic, getter=isMatched) BOOL matched; +@end diff --git a/test/.svn/text-base/PKParseTree.m.svn-base b/test/.svn/text-base/PKParseTree.m.svn-base new file mode 100644 index 0000000..3ce1d99 --- /dev/null +++ b/test/.svn/text-base/PKParseTree.m.svn-base @@ -0,0 +1,90 @@ +// +// PKParseTree.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" + +@interface PKParseTree () +@property (nonatomic, assign, readwrite) PKParseTree *parent; +@property (nonatomic, retain, readwrite) NSMutableArray *children; +@end + +@implementation PKParseTree + ++ (id)parseTree { + return [[[self alloc] init] autorelease]; +} + + +- (void)dealloc { + self.parent = nil; + self.children = nil; + self.userInfo = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKParseTree *t = [[[self class] allocWithZone:zone] init]; + + // assign parent + if (parent) { + t->parent = parent; + + // put new copy in new parent's children array + NSInteger i = [[parent children] indexOfObject:self]; + if (NSNotFound != i) { + [[t->parent children] replaceObjectAtIndex:i withObject:t]; + } + } + + // copy children + if (children) { + t->children = [children mutableCopyWithZone:zone]; + } + return t; +} + + +- (PKRuleNode *)addChildRule:(NSString *)name { + NSParameterAssert([name length]); + PKRuleNode *n = [PKRuleNode ruleNodeWithName:name]; + [self addChild:n]; + return n; +} + + +- (PKTokenNode *)addChildToken:(PKToken *)tok { + NSParameterAssert([[tok stringValue] length]); + PKTokenNode *n = [PKTokenNode tokenNodeWithToken:tok]; + [self addChild:n]; + return n; +} + + +- (void)addChild:(PKParseTree *)tr { + NSParameterAssert(tr); + if (!children) { + self.children = [NSMutableArray array]; + } + tr.parent = self; + [children addObject:tr]; +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", children]; +} + +@synthesize parent; +@synthesize children; +@synthesize userInfo; +@synthesize matched; +@end + diff --git a/test/.svn/text-base/PKParseTreeAssembler.h.svn-base b/test/.svn/text-base/PKParseTreeAssembler.h.svn-base new file mode 100644 index 0000000..5adb2e8 --- /dev/null +++ b/test/.svn/text-base/PKParseTreeAssembler.h.svn-base @@ -0,0 +1,18 @@ +// +// PKParseTreeAssembler.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface PKParseTreeAssembler : NSObject { + NSMutableDictionary *ruleNames; + NSString *preassemblerPrefix; + NSString *assemblerPrefix; + NSString *suffix; +} + +@end diff --git a/test/.svn/text-base/PKParseTreeAssembler.m.svn-base b/test/.svn/text-base/PKParseTreeAssembler.m.svn-base new file mode 100644 index 0000000..15d83d1 --- /dev/null +++ b/test/.svn/text-base/PKParseTreeAssembler.m.svn-base @@ -0,0 +1,175 @@ +// +// PKParseTreeAssembler.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKParseTreeAssembler.h" +#import +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" + +@interface PKParseTreeAssembler () +- (NSString *)ruleNameForSelName:(NSString *)selName withPrefix:(NSString *)pre; +- (void)didMatchRuleNamed:(NSString *)name assembly:(PKAssembly *)a; +- (void)willMatchRuleNamed:(NSString *)name assembly:(PKAssembly *)a; +- (void)didMatchToken:(PKAssembly *)a; +- (PKParseTree *)currentFrom:(PKAssembly *)a; +- (void)removeUnmatchedChildrenFrom:(PKParseTree *)n; + +@property (nonatomic, retain) NSMutableDictionary *ruleNames; +@property (nonatomic, copy) NSString *assemblerPrefix; +@property (nonatomic, copy) NSString *preassemblerPrefix; +@property (nonatomic, copy) NSString *suffix; +@end + +@implementation PKParseTreeAssembler + +- (id)init { + if (self = [super init]) { + self.ruleNames = [NSMutableDictionary dictionary]; + self.preassemblerPrefix = @"willMatch"; + self.assemblerPrefix = @"didMatch"; + self.suffix = @":"; + } + return self; +} + + +- (void)dealloc { + self.ruleNames = nil; + self.preassemblerPrefix = nil; + self.assemblerPrefix = nil; + self.suffix = nil; + [super dealloc]; +} + + +- (BOOL)respondsToSelector:(SEL)sel { + return YES; + if ([super respondsToSelector:sel]) { + return YES; + } else { + NSString *selName = NSStringFromSelector(sel); + if ([selName hasPrefix:assemblerPrefix] && [selName hasSuffix:suffix]) { + return YES; + } + } + return NO; +} + + +- (id)performSelector:(SEL)sel withObject:(id)obj { + NSString *selName = NSStringFromSelector(sel); + + if ([selName hasPrefix:assemblerPrefix] && [selName hasSuffix:suffix]) { + [self didMatchRuleNamed:[self ruleNameForSelName:selName withPrefix:assemblerPrefix] assembly:obj]; + } else if ([selName hasPrefix:preassemblerPrefix] && [selName hasSuffix:suffix]) { + [self willMatchRuleNamed:[self ruleNameForSelName:selName withPrefix:preassemblerPrefix] assembly:obj]; + } else if ([super respondsToSelector:sel]) { + return [super performSelector:sel withObject:obj]; + } else { + NSAssert(0, @""); + } + return nil; +} + + +- (NSString *)ruleNameForSelName:(NSString *)selName withPrefix:(NSString *)prefix { + NSString *ruleName = [ruleNames objectForKey:selName]; + + if (!ruleName) { + NSUInteger prefixLen = [prefix length]; + NSInteger c = ((NSInteger)[selName characterAtIndex:prefixLen]) + 32; // lowercase + NSRange r = NSMakeRange(prefixLen + 1, [selName length] - (prefixLen + [suffix length] + 1 /*:*/)); + ruleName = [NSString stringWithFormat:@"%C%@", c, [selName substringWithRange:r]]; + [ruleNames setObject:ruleName forKey:selName]; + } + + return ruleName; +} + + +- (void)willMatchRuleNamed:(NSString *)name assembly:(PKAssembly *)a { + PKParseTree *current = [self currentFrom:a]; + [self didMatchToken:a]; + current = [current addChildRule:name]; + a.target = current; +} + + +- (void)didMatchRuleNamed:(NSString *)name assembly:(PKAssembly *)a { + PKParseTree *current = [self currentFrom:a]; + + NSArray *origChildren = [[[current children] mutableCopy] autorelease]; + + PKParseTree *oldCurrent = nil; + while ([current isKindOfClass:[PKRuleNode class]] && ![[(id)current name] isEqualToString:name]) { + oldCurrent = [[current retain] autorelease]; + a.target = [current parent]; + current = [self currentFrom:a]; + [self didMatchToken:a]; + } + + if (oldCurrent && ![oldCurrent isMatched]) { + [(id)[current children] addObjectsFromArray:origChildren]; + } + + [self didMatchToken:a]; + current = [self currentFrom:a]; + + [self removeUnmatchedChildrenFrom:current]; + [current setMatched:YES]; + a.target = [current parent]; +} + + +- (void)removeUnmatchedChildrenFrom:(PKParseTree *)n { + NSMutableArray *remove = [NSMutableArray array]; + for (id child in [n children]) { + if (![child isMatched]) { + [remove addObject:child]; + } + } + + for (id child in remove) { + [(id)[n children] removeObject:child]; + } +} + + +- (PKParseTree *)currentFrom:(PKAssembly *)a { + PKParseTree *current = a.target; + if (!current) { + current = [PKParseTree parseTree]; + a.target = current; + } + return current; +} + + +- (void)didMatchToken:(PKAssembly *)a { + PKParseTree *current = [self currentFrom:a]; + if ([current isMatched]) return; + + NSMutableArray *toks = [NSMutableArray arrayWithCapacity:[a.stack count]]; + while (![a isStackEmpty]) { + id tok = [a pop]; + NSAssert([tok isKindOfClass:[PKToken class]], @""); + [toks addObject:tok]; + } + + for (id tok in [toks reverseObjectEnumerator]) { + PKTokenNode *n = [current addChildToken:tok]; + [n setMatched:YES]; + } +} + +@synthesize ruleNames; +@synthesize preassemblerPrefix; +@synthesize assemblerPrefix; +@synthesize suffix; +@end diff --git a/test/.svn/text-base/PKRuleNode.h.svn-base b/test/.svn/text-base/PKRuleNode.h.svn-base new file mode 100644 index 0000000..4988d60 --- /dev/null +++ b/test/.svn/text-base/PKRuleNode.h.svn-base @@ -0,0 +1,21 @@ +// +// PKRuleNode.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKParseTree.h" + +@interface PKRuleNode : PKParseTree { + NSString *name; +} + ++ (id)ruleNodeWithName:(NSString *)s; + +// designated initializer +- (id)initWithName:(NSString *)s; + +@property (nonatomic, copy, readonly) NSString *name; +@end diff --git a/test/.svn/text-base/PKRuleNode.m.svn-base b/test/.svn/text-base/PKRuleNode.m.svn-base new file mode 100644 index 0000000..71571ec --- /dev/null +++ b/test/.svn/text-base/PKRuleNode.m.svn-base @@ -0,0 +1,48 @@ +// +// PKRuleNode.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKRuleNode.h" + +@interface PKRuleNode () +@property (nonatomic, copy, readwrite) NSString *name; +@end + +@implementation PKRuleNode + ++ (id)ruleNodeWithName:(NSString *)s { + return [[[self alloc] initWithName:s] autorelease]; +} + + +- (id)initWithName:(NSString *)s { + if (self = [super init]) { + self.name = s; + } + return self; +} + + +- (void)dealloc { + self.name = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKRuleNode *n = [super copyWithZone:zone]; + n->name = [name copyWithZone:zone]; + return n; +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", name, children]; +} + +@synthesize name; +@end diff --git a/test/.svn/text-base/PKScientificNumberState.h.svn-base b/test/.svn/text-base/PKScientificNumberState.h.svn-base new file mode 100644 index 0000000..214b918 --- /dev/null +++ b/test/.svn/text-base/PKScientificNumberState.h.svn-base @@ -0,0 +1,24 @@ +// +// PKScientificNumberState.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +/*! + @class PKScientificNumberState + @brief A PKScientificNumberState object returns a number from a reader. + @details

This state's idea of a number expands on its superclass, allowing an 'e' followed by an integer to represent 10 to the indicated power. For example, this state will recognize 1e2 as equaling 100.

+

This class exists primarily to show how to introduce a new tokenizing state.

+*/ +@interface PKScientificNumberState : PKNumberState { + BOOL allowsScientificNotation; + CGFloat exp; + BOOL negativeExp; +} + +@property (nonatomic) BOOL allowsScientificNotation; +@end diff --git a/test/.svn/text-base/PKScientificNumberState.m.svn-base b/test/.svn/text-base/PKScientificNumberState.m.svn-base new file mode 100644 index 0000000..fc8ed1b --- /dev/null +++ b/test/.svn/text-base/PKScientificNumberState.m.svn-base @@ -0,0 +1,93 @@ +// +// PKScientificNumberState.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKScientificNumberState.h" +#import +#import + +@interface PKTokenizerState () +- (void)append:(PKUniChar)c; +@end + +@interface PKNumberState () +- (CGFloat)absorbDigitsFromReader:(PKReader *)r isFraction:(BOOL)isFraction; +- (void)parseRightSideFromReader:(PKReader *)r; +- (void)reset:(PKUniChar)cin; +- (CGFloat)value; +@end + +@implementation PKScientificNumberState + +- (id)init { + if (self = [super init]) { + self.allowsScientificNotation = YES; + } + return self; +} + + +- (void)parseRightSideFromReader:(PKReader *)r { + NSParameterAssert(r); + [super parseRightSideFromReader:r]; + if (!allowsScientificNotation) { + return; + } + + if ('e' == c || 'E' == c) { + PKUniChar e = c; + c = [r read]; + + BOOL hasExp = isdigit(c); + negativeExp = ('-' == c); + BOOL positiveExp = ('+' == c); + + if (!hasExp && (negativeExp || positiveExp)) { + c = [r read]; + hasExp = isdigit(c); + } + if (PKEOF != c) { + [r unread]; + } + if (hasExp) { + [self append:e]; + if (negativeExp) { + [self append:'-']; + } else if (positiveExp) { + [self append:'+']; + } + c = [r read]; + exp = [super absorbDigitsFromReader:r isFraction:NO]; + } + } +} + + +- (void)reset:(PKUniChar)cin { + [super reset:cin]; + exp = (CGFloat)0.0; + negativeExp = NO; +} + + +- (CGFloat)value { + CGFloat result = (CGFloat)floatValue; + + NSUInteger i = 0; + for ( ; i < exp; i++) { + if (negativeExp) { + result /= (CGFloat)10.0; + } else { + result *= (CGFloat)10.0; + } + } + + return (CGFloat)result; +} + +@synthesize allowsScientificNotation; +@end diff --git a/test/.svn/text-base/PKTokenNode.h.svn-base b/test/.svn/text-base/PKTokenNode.h.svn-base new file mode 100644 index 0000000..fa8790a --- /dev/null +++ b/test/.svn/text-base/PKTokenNode.h.svn-base @@ -0,0 +1,23 @@ +// +// PKTokenNode.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKParseTree.h" + +@class PKToken; + +@interface PKTokenNode : PKParseTree { + PKToken *token; +} + ++ (id)tokenNodeWithToken:(PKToken *)tok; + +// designated initializer +- (id)initWithToken:(PKToken *)tok; + +@property (nonatomic, retain, readonly) PKToken *token; +@end diff --git a/test/.svn/text-base/PKTokenNode.m.svn-base b/test/.svn/text-base/PKTokenNode.m.svn-base new file mode 100644 index 0000000..98979a5 --- /dev/null +++ b/test/.svn/text-base/PKTokenNode.m.svn-base @@ -0,0 +1,49 @@ +// +// PKTokenNode.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKTokenNode.h" +#import + +@interface PKTokenNode () +@property (nonatomic, retain, readwrite) PKToken *token; +@end + +@implementation PKTokenNode + ++ (id)tokenNodeWithToken:(PKToken *)s { + return [[[self alloc] initWithToken:s] autorelease]; +} + + +- (id)initWithToken:(PKToken *)s { + if (self = [super init]) { + self.token = s; + } + return self; +} + + +- (void)dealloc { + self.token = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKTokenNode *n = [super copyWithZone:zone]; + n->token = [token copyWithZone:zone]; + return n; +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", token]; +} + +@synthesize token; +@end diff --git a/test/.svn/text-base/RelaxParser.h.svn-base b/test/.svn/text-base/RelaxParser.h.svn-base new file mode 100644 index 0000000..5f154c6 --- /dev/null +++ b/test/.svn/text-base/RelaxParser.h.svn-base @@ -0,0 +1,15 @@ +// +// RelaxParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/15/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface RelaxParser : PKSequence { + PKTokenizer *tokenizer; +} + +@end diff --git a/test/.svn/text-base/RelaxParser.m.svn-base b/test/.svn/text-base/RelaxParser.m.svn-base new file mode 100644 index 0000000..48f8a6d --- /dev/null +++ b/test/.svn/text-base/RelaxParser.m.svn-base @@ -0,0 +1,618 @@ +// +// RelaxParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/15/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "RelaxParser.h" + +@implementation RelaxParser + +- (PKTokenizer *)tokenizer { + if (!tokenizer) { + self.tokenizer = [PKTokenizer tokenizer]; + [tokenizer.symbolState add:@"|="]; + [tokenizer.symbolState add:@"&="]; + } + return tokenizer; +} + +// topLevel ::= decl* (pattern | grammarContent*) +- (PKCollectionParser *)topLevelParser { + if (!topLevelParser) { + self.topLevelParser = [PKSequence sequence]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.declParser]; + [topLevelParser add:a]; + + a = [PKAlternation alternation]; + [a add:self.patternParser]; + [a add:[PKRepetition repetitionWithSubparser:self.grammarContentParser]]; + [topLevelParser add:a]; + } + return topLevelParser; +} + +// decl ::= "namespace" identifierOrKeyword "=" namespaceURILiteral +// | "default" "namespace" [identifierOrKeyword] "=" namespaceURILiteral +// | "datatypes" identifierOrKeyword "=" literal +- (PKCollectionParser *)declParser { + if (!declParser) { + self.declParser = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"namespace"]]; + [s add:self.identifierOrKeywordParser]; + [s add:[PKSymbol symbolWithString:@"="]]; + [a add:self.namespaceURILiteralParser]; + [declParser add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"default"]]; + [s add:[PKLiteral literalWithString:@"namespace"]]; + [s add:self.identifierOrKeywordParser]; + [s add:[PKSymbol symbolWithString:@"="]]; + [a add:self.namespaceURILiteralParser]; + [declParser add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"datatypes"]]; + [s add:self.identifierOrKeywordParser]; + [s add:[PKSymbol symbolWithString:@"="]]; + [a add:[PKQuotedString quotedString]]; + [declParser add:s]; + } + return declParser; +} + + +- (PKCollectionParser *)atLeastOneOf:(PKParser *)p { + PKSequence *s = [PKSequence sequence]; + [s add:p]; + [s add:[PKRepetition repetitionWithSubparser:p]]; + return s; +} + +// pattern ::= +// elementPattern +// | attributePattern +// | pattern commaPattern+ +// | pattern andPattern+ +// | pattern orPattern+ +// | patternQuestion +// | patternStar +// | patternPlus +// | listPattern +// | mixedPattern +// | identifier +// | parent +// | emptyKeyword +// | textKeyword +// | [datatypeName] datatypeValue +// | datatypeName ["{" param* "}"] [exceptPattern] +// | "notAllowed" +// | "external" anyURILiteral [inherit] +// | "grammar" "{" grammarContent* "}" +// | "(" pattern ")" +- (PKCollectionParser *)patternParser { + if (!patternParser) { + self.patternParser = [PKAlternation alternation]; + [patternParser add:self.elementPatternParser]; + [patternParser add:self.attributePatternParser]; + [patternParser add:[self atLeastOneOf:self.commaPatternParser]]; + [patternParser add:[self atLeastOneOf:self.andPatternParser]]; + [patternParser add:[self atLeastOneOf:self.orPatternParser]]; + [patternParser add:[self atLeastOneOf:self.patternQuestionParser]]; + [patternParser add:[self atLeastOneOf:self.patternStarParser]]; + [patternParser add:[self atLeastOneOf:self.patternPlusParser]]; + [patternParser add:self.listPatternParser]; + [patternParser add:self.mixedPatternParser]; + [patternParser add:self.identifierParser]; + [patternParser add:self.parentParser]; + [patternParser add:self.emptyKeywordParser]; + [patternParser add:self.textKeywordParser]; + + + + + s = [PKSequence sequence]; + [s add:patternParser]; + + } +} + +// elementPattern := "element" nameClass "{" pattern "}" +- (PKCollectionParser *)elementPatternParser { + if (!elementPatternParser) { + self.elementPatternParser = [PKSequence sequence]; + [elementPatternParser add:[PKLiteral literalWithString:@"element"]]; + [elementPatternParser add:self.nameClass]; + [elementPatternParser add:[PKSymbol symbolWithString:@"{"]]; + [elementPatternParser add:patternParser]; + [elementPatternParser add:[PKSymbol symbolWithString:@"}"]]; + } + return elementPatternParser; +} + + +// attributePattern := "attribute" nameClass "{" pattern "}" +- (PKCollectionParser *)attributePatternParser { + if (!attributePatternParser) { + attributePatternParser = [PKSequence sequence]; + [attributePatternParser add:[PKLiteral literalWithString:@"attribute"]]; + [attributePatternParser add:self.nameClass]; + [attributePatternParser add:[PKSymbol symbolWithString:@"{"]]; + [attributePatternParser add:patternParser]; + [attributePatternParser add:[PKSymbol symbolWithString:@"}"]]; + } + return attributePatternParser; +} + + +// commaPattern := "," pattern +- (PKCollectionParser *)commaPatternParser { + if (!commaPatternParser) { + self.commaPatternParser = [PKSequence sequence]; + [commaPatternParser add:[PKSymbol symbolWithString:@","]]; + [commaPatternParser add:self.patternParser]; + } + return commaPatternParser; +} + + +// andPattern := "&" pattern +- (PKCollectionParser *)andPatternParser { + if (!andPatternParser) { + self.andPatternParser = [PKSequence sequence]; + [andPatternParser add:[PKSymbol symbolWithString:@"&"]]; + [andPatternParser add:self.patternParser]; + } + return andPatternParser; +} + + +// orPattern := "|" pattern +- (PKCollectionParser *)orPatternParser { + if (!orPatternParser) { + self.orPatternParser = [PKSequence sequence]; + [orPatternParser add:[PKSymbol symbolWithString:@"|"]]; + [orPatternParser add:self.patternParser]; + } + return orPatternParser; +} + + +// patternQuestion := pattern "?" +- (PKCollectionParser *)patternQuestionParser { + if (!patternQuestionParser) { + self.patternQuestionParser = [PKSequence sequence]; + [patternQuestionParser add:self.patternParser]; + [patternQuestionParser add:[PKSymbol symbolWithString:@"?"]]; + } + return patternQuestionParser; +} + + +// patternQuestion := pattern "*" +- (PKCollectionParser *)patternStarParser { + if (!patternStarParser) { + self.patternStarParser = [PKSequence sequence]; + [patternStarParser add:self.patternParser]; + [patternStarParser add:[PKSymbol symbolWithString:@"*"]]; + } + return patternStarParser; +} + + +// patternQuestion := pattern "+" +- (PKCollectionParser *)patternPlusParser { + if (!patternPlusParser) { + self.patternPlusParser = [PKSequence sequence]; + [patternPlusParser add:self.patternParser]; + [patternPlusParser add:[PKSymbol symbolWithString:@"+"]]; + } + return patternPlusParser; +} + +// | "list" "{" pattern "}" +- (PKCollectionParser *)listPatternParser { + if (!listPatternParser) { + self.listPatternParser = [PKSequence sequence]; + [listPatternParser add:[PKLiteral literalWithString:@"list"]]; + [listPatternParser add:[PKSymbol symbolWithString:@"{"]]; + [listPatternParser add:patternParser]; + [listPatternParser add:[PKSymbol symbolWithString:@"}"]]; + } + return listPatternParser; +} + +// | "mixed" "{" pattern "}" +- (PKCollectionParser *)mixedPatternParser { + if (!mixedPatternParser) { + self.mixedPatternParser = [PKSequence sequence]; + [mixedPatternParser add:[PKLiteral literalWithString:@"mixed"]]; + [mixedPatternParser add:[PKSymbol symbolWithString:@"{"]]; + [mixedPatternParser add:patternParser]; + [mixedPatternParser add:[PKSymbol symbolWithString:@"}"]]; + } + return mixedPatternParser; +} + +// | "parent" identifier +- (PKCollectionParser *)parentParser { + if (!parentParser) { + self.parentParser = [PKSequence sequence]; + [parentParser add:[PKLiteral literalWithString:@"parent"]]; + [parentParser add:self.identifierParser]; + } + return parentParser; +} + + +// param ::= identifierOrKeyword "=" literal +- (PKCollectionParser *)paramParser { + if (!paramParser) { + self.paramParser = [PKSequence sequence]; + [paramParser add:self.identifierOrKeywordParser]; + [paramParser add:[PKSymbol symbolWithString:@"="]]; + [paramParser add:self.literalParser]; + } + return paramParser; +} + +// exceptPattern ::= "-" pattern +- (PKCollectionParser *)exceptPatternParser { + if (!exceptPattern) { + self.exceptPattern = [PKSequence sequence]; + [exceptPattern add:[PKSymbol symbolWithString:@"-"]]; + [exceptPattern add:self.patternParser]; + } + return exceptPattern; +} + + +// grammarContent ::= start | define | "element" "{" grammarContent* "}" | "include" anyURILiteral [inherit] ["{" includeContent* "}"] +// +// includeContent ::= define | start | elementIncludeContent +- (PKCollectionParser *)includeContentParser { + if (!includeContentParser) { + self.includeContentParser = [PKAlternation alternation]; + [includeContentParser add:self.defineParser]; + [includeContentParser add:self.startParser]; + [includeContentParser add:self.elementIncludeContentParser]; + } + return includeContentParser; +} + +// elementIncludeContent ::= "element" "{" includeContent* "}" +- (PKCollectionParser *)elementIncludeContentParser { + if (!elementIncludeContentParser) { + self.elementIncludeContentParser = [PKSequence sequence]; + [s add:self.elementKeywordParser]; + [s add:[PKSymbol symbolWithString:@"{"]]; + [s add:[PKRepetition repetitionWithSubparser:self.includeContentParser]] + [s add:[PKSymbol symbolWithString:@"}"]]; + + [elementIncludeContentParser add:s]; + } + return elementIncludeContentParser; +} + + +// +// start ::= "start" assignMethod pattern +- (PKCollectionParser *)startParser { + if (!startParser) { + self.startParser = [PKSequence sequence]; + [startParser add:self.startKeywordParser]; + [startParser add:self.assignMethodParser]; + [startParser add:self.patternParser]; + } + return startParser; +} + + +// +// define ::= identifier assignMethod pattern +- (PKCollectionParser *)defineParser { + if (!defineParser) { + self.defineParser = [PKSequence sequence]; + [defineParser add:self.identifierParser]; + [defineParser add:self.assignMethodParser]; + [defineParser add:self.patternParser]; + } + return defineParser; +} + + +// +// assignMethod ::= "=" | "|=" | "&=" +- (PKCollectionParser *)assignMethodParser { + if (!assignMethodParser) { + self.assignMethodParser = [PKAlternation alternation]; + [assignMethodParser add:[PKSymbol symbolWithString:@"="]]; + [assignMethodParser add:[PKSymbol symbolWithString:@"|="]]; + [assignMethodParser add:[PKSymbol symbolWithString:@"&="]]; + } + return assignMethodParser; +} + +// +// nameClass ::= name +// | nsName [exceptNameClass] +// | anyName [exceptNameClass] +// | nameClass "|" nameClass +// | "(" nameClass ")" +// +// name ::= identifierOrKeyword | CName +- (PKCollectionParser *)nameParser { + if (!nameParser) { + self.nameParser = [PKAlternation alternation]; + [nameParser add:self.identifierOrKeywordParser]; + [nameParser add:self.CNameParser]; + } + return nameParser; +} + +// +// exceptNameClass ::= "-" nameClass +- (PKCollectionParser *)exceptNameClassParser { + if (!exceptNameClassParser) { + self.exceptNameClassParser = [PKSequence sequence]; + [nameParser add:[PKSymbol symbolWithString:@"-"]]; + [nameParser add:self.nameClassParser]; + } + return nameParser; +} + +// +// datatypeName ::= CName | "string" | "token" +- (PKCollectionParser *)datatypeNameParser { + if (!datatypeNameParser) { + self.datatypeNameParser = [PKAlternation alternation]; + [datatypeNameParser add:self.CNameParser]; + [datatypeNameParser add:self.stringKeywordParser]; + [datatypeNameParser add:self.tokenKeywordParser]; + } + return datatypeNameParser; +} + + +// +// datatypeValue ::= literal +- (PKCollectionParser *)datatypeValueParser { + if (!datatypeValueParser) { + self.datatypeValueParser = self.literalParser; + } + return datatypeValueParser; +} + + +// +// anyURILiteral ::= literal +- (PKCollectionParser *)anyURILiteralParser { + if (!anyURILiteralParser) { + self.anyURILiteralParser = self.literalParser; + } + return anyURILiteralParser; +} + + +// +// namespaceURILiteral ::= literal | "inherit" +// +// inherit ::= "inherit" "=" identifierOrKeyword +// +// identifierOrKeyword ::= identifier | keyword +// +// identifier ::= (NCName - keyword) | quotedIdentifier +// +// quotedIdentifier ::= "\" NCName +// +// CName ::= NCName ":" NCName +// +// nsName ::= NCName ":*" +// +// anyName ::= "*" +// +// literal ::= literalSegment ("~" literalSegment)+ +// +// literalSegment ::= '"' (Char - ('"' | newline))* '"' +// | "'" (Char - ("'" | newline))* "'" +// | '"""' (['"'] ['"'] (Char - '"'))* '"""' +// | "'''" (["'"] ["'"] (Char - "'"))* "'''" + + +// keyword ::= "attribute" +// | "default" +// | "datatypes" +// | "element" +// | "empty" +// | "external" +// | "grammar" +// | "include" +// | "inherit" +// | "list" +// | "mixed" +// | "namespace" +// | "notAllowed" +// | "parent" +// | "start" +// | "string" +// | "text" +// | "token" +// +- (PKParser *)keywordParser { + if (!keywordParser) { + self.keywordParser = [PKAlternation alternation]; + [keywordParser add:self.attributeKeywordParser]; + [keywordParser add:self.defaultKeywordParser]; + [keywordParser add:self.datatypesKeywordParser]; + [keywordParser add:self.elementKeywordParser]; + [keywordParser add:self.emptyKeywordParser]; + [keywordParser add:self.externalKeywordParser]; + [keywordParser add:self.grammarKeywordParser]; + [keywordParser add:self.includeKeywordParser]; + [keywordParser add:self.inheritKeywordParser]; + [keywordParser add:self.listKeywordParser]; + [keywordParser add:self.mixedKeywordParser]; + [keywordParser add:self.namespaceKeywordParser]; + [keywordParser add:self.notAllowedKeywordParser]; + [keywordParser add:self.parentKeywordParser]; + [keywordParser add:self.startKeywordParser]; + [keywordParser add:self.stringKeywordParser]; + [keywordParser add:self.textParser]; + [keywordParser add:self.tokenKeywordParser]; + } + return keywordParser; +} + + +- (PKParser *)attributeKeywordParser { + if (!attributeKeywordParser) { + self.attributeKeywordParser = [PKLiteral literalWithString:@"attribute"]; + } + return attributeKeywordParser; +} + + +- (PKParser *)defaultKeywordParser { + if (!defaultKeywordParser) { + self.defaultKeywordParser = [PKLiteral literalWithString:@"default"]; + } + return defaultKeywordParser; +} + + +- (PKParser *)datatypesKeywordParser { + if (!datatypesKeywordParser) { + self.datatypesKeywordParser = [PKLiteral literalWithString:@"datatypes"]; + } + return datatypesKeywordParser; +} + + +- (PKParser *)elementKeywordParser { + if (!elementKeywordParser) { + self.elementKeywordParser = [PKLiteral literalWithString:@"element"]; + } + return elementKeywordParser; +} + + +- (PKParser *)emptyKeywordParser { + if (!emptyKeywordParser) { + self.emptyKeywordParser = [PKLiteral literalWithString:@"empty"]; + } + return emptyKeywordParser; +} + + +- (PKParser *)externalKeywordParser { + if (!externalKeywordParser) { + self.externalKeywordParser = [PKLiteral literalWithString:@"external"]; + } + return externalKeywordParser; +} + + +- (PKParser *)grammarKeywordParser { + if (!grammarKeywordParser) { + self.grammarKeywordParser = [PKLiteral literalWithString:@"grammar"]; + } + return grammarKeywordParser; +} + + +- (PKParser *)includeKeywordParser { + if (!includeKeywordParser) { + self.includeKeywordParser = [PKLiteral literalWithString:@"include"]; + } + return includeKeywordParser; +} + + +- (PKParser *)inheritKeywordParser { + if (!inheritKeywordParser) { + self.inheritKeywordParser = [PKLiteral literalWithString:@"inherit"]; + } + return inheritKeywordParser; +} + + +- (PKParser *)listKeywordParser { + if (!listKeywordParser) { + self.listKeywordParser = [PKLiteral literalWithString:@"list"]; + } + return listKeywordParser; +} + + +- (PKParser *)mixedKeywordParser { + if (!mixedKeywordParser) { + self.mixedKeywordParser = [PKLiteral literalWithString:@"mixed"]; + } + return mixedKeywordParser; +} + + +- (PKParser *)namespaceKeywordParser { + if (!namespaceKeywordParser) { + self.namespaceKeywordParser = [PKLiteral literalWithString:@"namespace"]; + } + return namespaceKeywordParser; +} + + +- (PKParser *)notAllowedKeywordParser { + if (!notAllowedKeywordParser) { + self.notAllowedKeywordParser = [PKLiteral literalWithString:@"notAllowed"]; + } + return notAllowedKeywordParser; +} + + +- (PKParser *)parentKeywordParser { + if (!parentKeywordParser) { + self.parentKeywordParser = [PKLiteral literalWithString:@"parent"]; + } + return parentKeywordParser; +} + + +- (PKParser *)startKeywordParser { + if (!startKeywordParser) { + self.startKeywordParser = [PKLiteral literalWithString:@"start"]; + } + return startKeywordParser; +} + + +- (PKParser *)stringKeywordParser { + if (!stringKeywordParser) { + self.stringKeywordParser = [PKLiteral literalWithString:@"string"]; + } + return stringKeywordParser; +} + + +- (PKParser *)textKeywordParser { + if (!textKeywordParser) { + self.textKeywordParser = [PKLiteral literalWithString:@"text"]; + } + return textKeywordParser; +} + + +- (PKParser *)tokenKeywordParser { + if (!tokenKeywordParser) { + self.tokenKeywordParser = [PKLiteral literalWithString:@"token"]; + } + return tokenKeywordParser; +} + +@end diff --git a/test/.svn/text-base/SAXAssembler.h.svn-base b/test/.svn/text-base/SAXAssembler.h.svn-base new file mode 100644 index 0000000..02c4661 --- /dev/null +++ b/test/.svn/text-base/SAXAssembler.h.svn-base @@ -0,0 +1,15 @@ +// +// SAXAssembler.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface SAXAssembler : NSObject { + +} + +@end diff --git a/test/.svn/text-base/SAXAssembler.m.svn-base b/test/.svn/text-base/SAXAssembler.m.svn-base new file mode 100644 index 0000000..199ded3 --- /dev/null +++ b/test/.svn/text-base/SAXAssembler.m.svn-base @@ -0,0 +1,18 @@ +// +// SAXAssembler.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "SAXAssembler.h" +#import + +@implementation SAXAssembler + +- (void)didMatchSTag:(PKAssembly *)a { + +} + +@end diff --git a/test/.svn/text-base/SAXTest.h.svn-base b/test/.svn/text-base/SAXTest.h.svn-base new file mode 100644 index 0000000..3ec3640 --- /dev/null +++ b/test/.svn/text-base/SAXTest.h.svn-base @@ -0,0 +1,21 @@ +// +// SAXTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface SAXTest : SenTestCase { + NSString *s; + NSString *g; + PKParserFactory *factory; + PKTokenAssembly *a; + PKAssembly *res; + PKParser *p; + PKTokenizer *t; +} + +@end diff --git a/test/.svn/text-base/SAXTest.m.svn-base b/test/.svn/text-base/SAXTest.m.svn-base new file mode 100644 index 0000000..1b841a7 --- /dev/null +++ b/test/.svn/text-base/SAXTest.m.svn-base @@ -0,0 +1,27 @@ +// +// SAXTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "SAXTest.h" + +@implementation SAXTest + +- (void)setUp { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xml" ofType:@"grammar"]; + g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + factory = [PKParserFactory factory]; + p = [factory parserFromGrammar:g assembler:self]; + t = p.tokenizer; +} + + +- (void)testSTag { + //PKParser *sTag = [p parserNamed:@"sTag"]; + +} + +@end diff --git a/test/.svn/text-base/SRGSParser.h.svn-base b/test/.svn/text-base/SRGSParser.h.svn-base new file mode 100644 index 0000000..905078b --- /dev/null +++ b/test/.svn/text-base/SRGSParser.h.svn-base @@ -0,0 +1,88 @@ +// +// SRGSParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface SRGSParser : PKSequence { + PKCollectionParser *selfIdentHeader; + PKCollectionParser *ruleName; + PKCollectionParser *tagFormat; + PKCollectionParser *lexiconURI; + PKCollectionParser *weight; + PKCollectionParser *repeat; + PKCollectionParser *probability; + PKCollectionParser *externalRuleRef; + PKCollectionParser *token; + PKCollectionParser *languageAttachment; + PKCollectionParser *tag; + PKCollectionParser *grammar; + PKCollectionParser *declaration; + PKCollectionParser *baseDecl; + PKCollectionParser *languageDecl; + PKCollectionParser *modeDecl; + PKCollectionParser *rootRuleDecl; + PKCollectionParser *tagFormatDecl; + PKCollectionParser *lexiconDecl; + PKCollectionParser *metaDecl; + PKCollectionParser *tagDecl; + PKCollectionParser *ruleDefinition; + PKCollectionParser *scope; + PKCollectionParser *ruleExpansion; + PKCollectionParser *ruleAlternative; + PKCollectionParser *sequenceElement; + PKCollectionParser *subexpansion; + PKCollectionParser *ruleRef; + PKCollectionParser *localRuleRef; + PKCollectionParser *specialRuleRef; + PKCollectionParser *repeatOperator; + + PKCollectionParser *baseURI; + PKCollectionParser *languageCode; + PKCollectionParser *ABNF_URI; + PKCollectionParser *ABNF_URI_with_Media_Type; +} +- (id)parse:(NSString *)s; +- (PKAssembly *)assemblyWithString:(NSString *)s; + +@property (nonatomic, retain) PKCollectionParser *selfIdentHeader; +@property (nonatomic, retain) PKCollectionParser *ruleName; +@property (nonatomic, retain) PKCollectionParser *tagFormat; +@property (nonatomic, retain) PKCollectionParser *lexiconURI; +@property (nonatomic, retain) PKCollectionParser *weight; +@property (nonatomic, retain) PKCollectionParser *repeat; +@property (nonatomic, retain) PKCollectionParser *probability; +@property (nonatomic, retain) PKCollectionParser *externalRuleRef; +@property (nonatomic, retain) PKCollectionParser *token; +@property (nonatomic, retain) PKCollectionParser *languageAttachment; +@property (nonatomic, retain) PKCollectionParser *tag; +@property (nonatomic, retain) PKCollectionParser *grammar; +@property (nonatomic, retain) PKCollectionParser *declaration; +@property (nonatomic, retain) PKCollectionParser *baseDecl; +@property (nonatomic, retain) PKCollectionParser *languageDecl; +@property (nonatomic, retain) PKCollectionParser *modeDecl; +@property (nonatomic, retain) PKCollectionParser *rootRuleDecl; +@property (nonatomic, retain) PKCollectionParser *tagFormatDecl; +@property (nonatomic, retain) PKCollectionParser *lexiconDecl; +@property (nonatomic, retain) PKCollectionParser *metaDecl; +@property (nonatomic, retain) PKCollectionParser *tagDecl; +@property (nonatomic, retain) PKCollectionParser *ruleDefinition; +@property (nonatomic, retain) PKCollectionParser *scope; +@property (nonatomic, retain) PKCollectionParser *ruleExpansion; +@property (nonatomic, retain) PKCollectionParser *ruleAlternative; +@property (nonatomic, retain) PKCollectionParser *sequenceElement; +@property (nonatomic, retain) PKCollectionParser *subexpansion; +@property (nonatomic, retain) PKCollectionParser *ruleRef; +@property (nonatomic, retain) PKCollectionParser *localRuleRef; +@property (nonatomic, retain) PKCollectionParser *specialRuleRef; +@property (nonatomic, retain) PKCollectionParser *repeatOperator; + +@property (nonatomic, retain) PKCollectionParser *baseURI; +@property (nonatomic, retain) PKCollectionParser *languageCode; +@property (nonatomic, retain) PKCollectionParser *ABNF_URI; +@property (nonatomic, retain) PKCollectionParser *ABNF_URI_with_Media_Type; +@end diff --git a/test/.svn/text-base/SRGSParser.m.svn-base b/test/.svn/text-base/SRGSParser.m.svn-base new file mode 100644 index 0000000..a330989 --- /dev/null +++ b/test/.svn/text-base/SRGSParser.m.svn-base @@ -0,0 +1,786 @@ +// +// SRGSParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "SRGSParser.h" +#import "NSString+ParseKitAdditions.h" + +@interface SRGSParser () +- (void)didMatchWord:(PKAssembly *)a; +- (void)didMatchNum:(PKAssembly *)a; +- (void)didMatchQuotedString:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchAssignment:(PKAssembly *)a; +- (void)didMatchVariable:(PKAssembly *)a; +@end + +@implementation SRGSParser + +- (id)init { + if (self = [super init]) { + [self add:self.grammar]; + } + return self; +} + + +- (void)dealloc { + self.selfIdentHeader = nil; + self.ruleName = nil; + self.tagFormat = nil; + self.lexiconURI = nil; + self.weight = nil; + self.repeat = nil; + self.probability = nil; + self.externalRuleRef = nil; + self.token = nil; + self.languageAttachment = nil; + self.tag = nil; + self.grammar = nil; + self.declaration = nil; + self.baseDecl = nil; + self.languageDecl = nil; + self.modeDecl = nil; + self.rootRuleDecl = nil; + self.tagFormatDecl = nil; + self.lexiconDecl = nil; + self.metaDecl = nil; + self.tagDecl = nil; + self.ruleDefinition = nil; + self.scope = nil; + self.ruleExpansion = nil; + self.ruleAlternative = nil; + self.sequenceElement = nil; + self.subexpansion = nil; + self.ruleRef = nil; + self.localRuleRef = nil; + self.specialRuleRef = nil; + self.repeatOperator = nil; + + self.baseURI = nil; + self.languageCode = nil; + self.ABNF_URI = nil; + self.ABNF_URI_with_Media_Type = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + PKAssembly *a = [self assemblyWithString:s]; + a = [self completeMatchFor:a]; + return [a pop]; +} + + +- (PKAssembly *)assemblyWithString:(NSString *)s { + PKTokenizer *t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + [t setTokenizerState:t.symbolState from: '-' to: '-']; + [t setTokenizerState:t.symbolState from: '.' to: '.']; + //[t.wordState setWordChars:YES from:'-' to:'-']; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; + // TDNCNameState *NCNameState = [[[TDNCNameState alloc] init] autorelease]; + return a; +} + + +//selfIdentHeader ::= '#ABNF' #x20 VersionNumber (#x20 CharEncoding)? ';' +//VersionNumber ::= '1.0' +//CharEncoding ::= Nmtoken +- (PKCollectionParser *)selfIdentHeader { + if (!selfIdentHeader) { + self.selfIdentHeader = [PKSequence sequence]; + selfIdentHeader.name = @"selfIdentHeader"; + + [selfIdentHeader add:[PKSymbol symbolWithString:@"#"]]; + [selfIdentHeader add:[PKLiteral literalWithString:@"ABNF"]]; + [selfIdentHeader add:[PKNumber number]]; // VersionNumber + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:[PKWord word]]; // CharEncoding + + [selfIdentHeader add:a]; + [selfIdentHeader add:[PKSymbol symbolWithString:@";"]]; + } + return selfIdentHeader; +} + + +//RuleName ::= '$' ConstrainedName +//ConstrainedName ::= Name - (Char* ('.' | ':' | '-') Char*) +- (PKCollectionParser *)ruleName { + if (!ruleName) { + self.ruleName = [PKSequence sequence]; + [ruleName add:[PKSymbol symbolWithString:@"$"]]; + [ruleName add:[PKWord word]]; // TODO: ConstrainedName + } + return ruleName; +} + +//TagFormat ::= ABNF_URI +- (PKCollectionParser *)tagFormat { + if (!tagFormat) { + self.tagFormat = self.ABNF_URI; + } + return tagFormat; +} + + +//LexiconURI ::= ABNF_URI | ABNF_URI_with_Media_Type +- (PKCollectionParser *)lexiconURI { + if (!lexiconURI) { + self.lexiconURI = [PKAlternation alternation]; + [lexiconURI add:self.ABNF_URI]; + [lexiconURI add:self.ABNF_URI_with_Media_Type]; + } + return lexiconURI; +} + + +//Weight ::= '/' Number '/' +- (PKCollectionParser *)weight { + if (!weight) { + self.weight = [PKSequence sequence]; + [weight add:[PKSymbol symbolWithString:@"/"]]; + [weight add:[PKNumber number]]; + [weight add:[PKSymbol symbolWithString:@"/"]]; + } + return weight; +} + + +//Repeat ::= [0-9]+ ('-' [0-9]*)? +- (PKCollectionParser *)repeat { + if (!repeat) { + self.repeat = [PKSequence sequence]; + [repeat add:[PKNumber number]]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"-"]]; + [s add:[PKNumber number]]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:s]; + + [repeat add:a]; + } + return repeat; +} + + +//Probability ::= '/' Number '/' +- (PKCollectionParser *)probability { + if (!probability) { + self.probability = [PKSequence sequence]; + [probability add:[PKSymbol symbolWithString:@"/"]]; + [probability add:[PKNumber number]]; + [probability add:[PKSymbol symbolWithString:@"/"]]; + } + return probability; +} + + + +//ExternalRuleRef ::= '$' ABNF_URI | '$' ABNF_URI_with_Media_Type +- (PKCollectionParser *)externalRuleRef { + if (!externalRuleRef) { + self.externalRuleRef = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"$"]]; + [s add:self.ABNF_URI]; + [externalRuleRef add:s]; + + s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"$"]]; + [s add:self.ABNF_URI_with_Media_Type]; + [externalRuleRef add:s]; + } + return externalRuleRef; +} + + +//Token ::= Nmtoken | DoubleQuotedCharacters +- (PKCollectionParser *)token { + if (!token) { + self.token = [PKAlternation alternation]; + [token add:[PKWord word]]; + [token add:[PKQuotedString quotedString]]; + } + return token; +} + + +//LanguageAttachment ::= '!' LanguageCode +- (PKCollectionParser *)languageAttachment { + if (!languageAttachment) { + self.languageAttachment = [PKSequence sequence]; + [languageAttachment add:[PKSymbol symbolWithString:@"!"]]; + [languageAttachment add:self.languageCode]; + } + return languageAttachment; +} + + +//Tag ::= '{' [^}]* '}' | '{!{' (Char* - (Char* '}!}' Char*)) '}!}' +- (PKCollectionParser *)tag { + if (!tag) { + self.tag = [PKAlternation alternation]; + + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"{"]]; + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKWord word]]; + [a add:[PKNumber number]]; + [a add:[PKSymbol symbol]]; + [a add:[PKQuotedString quotedString]]; + [s add:[PKRepetition repetitionWithSubparser:a]]; + [s add:[PKSymbol symbolWithString:@"}"]]; + [tag add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"{!{"]]; + a = [PKAlternation alternation]; + [a add:[PKWord word]]; + [a add:[PKNumber number]]; + [a add:[PKSymbol symbol]]; + [a add:[PKQuotedString quotedString]]; + [s add:[PKRepetition repetitionWithSubparser:a]]; + [s add:[PKLiteral literalWithString:@"}!}"]]; + [tag add:s]; + } + return tag; +} + + +#pragma mark - +#pragma mark Grammar + +// grammar ::= selfIdentHeader declaration* ruleDefinition* +- (PKCollectionParser *)grammar { + if (!grammar) { + self.grammar = [PKSequence sequence]; + [grammar add:self.selfIdentHeader]; + [grammar add:[PKRepetition repetitionWithSubparser:self.declaration]]; + [grammar add:[PKRepetition repetitionWithSubparser:self.ruleDefinition]]; + } + return grammar; +} + +// declaration ::= baseDecl | languageDecl | modeDecl | rootRuleDecl | tagFormatDecl | lexiconDecl | metaDecl | tagDecl +- (PKCollectionParser *)declaration { + if (!declaration) { + self.declaration = [PKAlternation alternation]; + [declaration add:self.baseDecl]; + [declaration add:self.languageDecl]; + [declaration add:self.modeDecl]; + [declaration add:self.rootRuleDecl]; + [declaration add:self.tagFormatDecl]; + [declaration add:self.lexiconDecl]; + [declaration add:self.tagDecl]; + } + return declaration; +} + +// baseDecl ::= 'base' BaseURI ';' +- (PKCollectionParser *)baseDecl { + if (!baseDecl) { + self.baseDecl = [PKSequence sequence]; + [baseDecl add:[PKLiteral literalWithString:@"base"]]; + [baseDecl add:self.baseURI]; + [baseDecl add:[PKSymbol symbolWithString:@";"]]; + } + return baseDecl; +} + +// languageDecl ::= 'language' LanguageCode ';' +- (PKCollectionParser *)languageDecl { + if (!languageDecl) { + self.languageDecl = [PKSequence sequence]; + [languageDecl add:[PKLiteral literalWithString:@"language"]]; + [languageDecl add:self.languageCode]; + [languageDecl add:[PKSymbol symbolWithString:@";"]]; + } + return languageDecl; +} + + + +// modeDecl ::= 'mode' 'voice' ';' | 'mode' 'dtmf' ';' +- (PKCollectionParser *)modeDecl { + if (!modeDecl) { + self.modeDecl = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"mode"]]; + [s add:[PKLiteral literalWithString:@"voice"]]; + [s add:[PKSymbol symbolWithString:@";"]]; + [modeDecl add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"mode"]]; + [s add:[PKLiteral literalWithString:@"dtmf"]]; + [s add:[PKSymbol symbolWithString:@";"]]; + [modeDecl add:s]; + } + return modeDecl; +} + + +// rootRuleDecl ::= 'root' RuleName ';' +- (PKCollectionParser *)rootRuleDecl { + if (!rootRuleDecl) { + self.rootRuleDecl = [PKSequence sequence]; + [rootRuleDecl add:[PKLiteral literalWithString:@"root"]]; + [rootRuleDecl add:self.ruleName]; + [rootRuleDecl add:[PKSymbol symbolWithString:@";"]]; + } + return rootRuleDecl; +} + + +// tagFormatDecl ::= 'tag-format' TagFormat ';' +- (PKCollectionParser *)tagFormatDecl { + if (!tagFormatDecl) { + self.tagFormatDecl = [PKSequence sequence]; + [tagFormatDecl add:[PKLiteral literalWithString:@"tag-format"]]; + [tagFormatDecl add:self.tagFormat]; + [tagFormatDecl add:[PKSymbol symbolWithString:@";"]]; + } + return tagFormatDecl; +} + + + +// lexiconDecl ::= 'lexicon' LexiconURI ';' +- (PKCollectionParser *)lexiconDecl { + if (!lexiconDecl) { + self.lexiconDecl = [PKSequence sequence]; + [lexiconDecl add:[PKLiteral literalWithString:@"lexicon"]]; + [lexiconDecl add:self.lexiconURI]; + [lexiconDecl add:[PKSymbol symbolWithString:@";"]]; + } + return lexiconDecl; +} + + +// metaDecl ::= +// 'http-equiv' QuotedCharacters 'is' QuotedCharacters ';' +// | 'meta' QuotedCharacters 'is' QuotedCharacters ';' +- (PKCollectionParser *)metaDecl { + if (!metaDecl) { + self.metaDecl = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"http-equiv"]]; + [s add:[PKQuotedString quotedString]]; + [s add:[PKLiteral literalWithString:@"is"]]; + [s add:[PKQuotedString quotedString]]; + [s add:[PKSymbol symbolWithString:@";"]]; + [metaDecl add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"meta"]]; + [s add:[PKQuotedString quotedString]]; + [s add:[PKLiteral literalWithString:@"is"]]; + [s add:[PKQuotedString quotedString]]; + [s add:[PKSymbol symbolWithString:@";"]]; + [metaDecl add:s]; + } + return metaDecl; +} + + + +// tagDecl ::= Tag ';' +- (PKCollectionParser *)tagDecl { + if (!tagDecl) { + self.tagDecl = [PKSequence sequence]; + [tagDecl add:self.tag]; + [tagDecl add:[PKSymbol symbolWithString:@";"]]; + } + return tagDecl; +} + + +// ruleDefinition ::= scope? RuleName '=' ruleExpansion ';' +- (PKCollectionParser *)ruleDefinition { + if (!ruleDefinition) { + self.ruleDefinition = [PKSequence sequence]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.scope]; + + [ruleDefinition add:a]; + [ruleDefinition add:self.ruleName]; + [ruleDefinition add:[PKSymbol symbolWithString:@"="]]; + [ruleDefinition add:self.ruleExpansion]; + [ruleDefinition add:[PKSymbol symbolWithString:@";"]]; + } + return ruleDefinition; +} + +// scope ::= 'private' | 'public' +- (PKCollectionParser *)scope { + if (!scope) { + self.scope = [PKAlternation alternation]; + [scope add:[PKLiteral literalWithString:@"private"]]; + [scope add:[PKLiteral literalWithString:@"public"]]; + } + return scope; +} + + +// ruleExpansion ::= ruleAlternative ( '|' ruleAlternative )* +- (PKCollectionParser *)ruleExpansion { + if (!ruleExpansion) { + self.ruleExpansion = [PKSequence sequence]; + [ruleExpansion add:self.ruleAlternative]; + + PKSequence *pipeRuleAlternative = [PKSequence sequence]; + [pipeRuleAlternative add:[PKSymbol symbolWithString:@"|"]]; + [pipeRuleAlternative add:self.ruleAlternative]; + [ruleExpansion add:[PKRepetition repetitionWithSubparser:pipeRuleAlternative]]; + } + return ruleExpansion; +} + + +// ruleAlternative ::= Weight? sequenceElement+ +- (PKCollectionParser *)ruleAlternative { + if (!ruleAlternative) { + self.ruleAlternative = [PKSequence sequence]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.weight]; + + [ruleAlternative add:a]; + [ruleAlternative add:self.sequenceElement]; + [ruleAlternative add:[PKRepetition repetitionWithSubparser:self.sequenceElement]]; + } + return ruleAlternative; +} + +// sequenceElement ::= subexpansion | subexpansion repeatOperator + +// me: changing to: +// sequenceElement ::= subexpansion repeatOperator? +- (PKCollectionParser *)sequenceElement { + if (!sequenceElement) { +// self.sequenceElement = [PKAlternation alternation]; +// [sequenceElement add:self.subexpansion]; +// +// PKSequence *s = [PKSequence sequence]; +// [s add:self.subexpansion]; +// [s add:self.repeatOperator]; +// +// [sequenceElement add:s]; + + self.sequenceElement = [PKSequence sequence]; + [sequenceElement add:self.subexpansion]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.repeatOperator]; + + [sequenceElement add:a]; + } + return sequenceElement; +} + +// subexpansion ::= +// Token LanguageAttachment? +// | ruleRef +// | Tag +// | '(' ')' +// | '(' ruleExpansion ')' LanguageAttachment? +// | '[' ruleExpansion ']' LanguageAttachment? +- (PKCollectionParser *)subexpansion { + if (!subexpansion) { + self.subexpansion = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:self.token]; + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.languageAttachment]; + [s add:a]; + [subexpansion add:s]; + + [subexpansion add:self.ruleRef]; + [subexpansion add:self.tag]; + + s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:[PKSymbol symbolWithString:@")"]]; + [subexpansion add:s]; + + s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:self.ruleExpansion]; + [s add:[PKSymbol symbolWithString:@")"]]; + a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.languageAttachment]; + [s add:a]; + [subexpansion add:s]; + + s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"["]]; + [s add:self.ruleExpansion]; + [s add:[PKSymbol symbolWithString:@"]"]]; + a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.languageAttachment]; + [s add:a]; + [subexpansion add:s]; + } + return subexpansion; +} + + +// ruleRef ::= localRuleRef | ExternalRuleRef | specialRuleRef +- (PKCollectionParser *)ruleRef { + if (!ruleRef) { + self.ruleRef = [PKAlternation alternation]; + [ruleRef add:self.localRuleRef]; + [ruleRef add:self.externalRuleRef]; + [ruleRef add:self.specialRuleRef]; + } + return ruleRef; +} + +// localRuleRef ::= RuleName +- (PKCollectionParser *)localRuleRef { + if (!localRuleRef) { + self.localRuleRef = self.ruleName; + } + return localRuleRef; +} + + +// specialRuleRef ::= '$NULL' | '$VOID' | '$GARBAGE' +- (PKCollectionParser *)specialRuleRef { + if (!specialRuleRef) { + self.specialRuleRef = [PKAlternation alternation]; + [specialRuleRef add:[PKLiteral literalWithString:@"$NULL"]]; + [specialRuleRef add:[PKLiteral literalWithString:@"$VOID"]]; + [specialRuleRef add:[PKLiteral literalWithString:@"$GARBAGE"]]; + } + return specialRuleRef; +} + + +// repeatOperator ::='<' Repeat Probability? '>' +- (PKCollectionParser *)repeatOperator { + if (!repeatOperator) { + self.repeatOperator = [PKSequence sequence]; + [repeatOperator add:[PKSymbol symbolWithString:@"<"]]; + [repeatOperator add:self.repeat]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.probability]; + [repeatOperator add:a]; + + [repeatOperator add:[PKSymbol symbolWithString:@">"]]; + } + return repeatOperator; +} + + +//BaseURI ::= ABNF_URI +- (PKCollectionParser *)baseURI { + if (!baseURI) { + self.baseURI = [PKWord word]; + } + return baseURI; +} + + +//LanguageCode ::= Nmtoken +- (PKCollectionParser *)languageCode { + if (!languageCode) { + self.languageCode = [PKSequence sequence]; + [languageCode add:[PKWord word]]; +// [languageCode add:[PKSymbol symbolWithString:@"-"]]; +// [languageCode add:[PKWord word]]; + } + return languageCode; +} + + +- (PKCollectionParser *)ABNF_URI { + if (!ABNF_URI) { + self.ABNF_URI = [PKWord word]; + } + return ABNF_URI; +} + + +- (PKCollectionParser *)ABNF_URI_with_Media_Type { + if (!ABNF_URI_with_Media_Type) { + self.ABNF_URI_with_Media_Type = [PKWord word]; + } + return ABNF_URI_with_Media_Type; +} + + + +#pragma mark - +#pragma mark Assembler Methods + +- (void)didMatchWord:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + [a push:[PKLiteral literalWithString:tok.stringValue]]; +} + + +- (void)didMatchNum:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + [a push:[PKLiteral literalWithString:tok.stringValue]]; +} + + +- (void)didMatchQuotedString:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + + PKSequence *p = [PKSequence sequence]; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *eof = [PKToken EOFToken]; + while (eof != (tok = [t nextToken])) { + [p add:[PKLiteral literalWithString:tok.stringValue]]; + } + + [a push:p]; +} + + +- (void)didMatchStar:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKRepetition *p = [PKRepetition repetitionWithSubparser:[a pop]]; + [a push:p]; +} + + +- (void)didMatchQuestion:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKAlternation *p = [PKAlternation alternation]; + [p add:[a pop]]; + [p add:[PKEmpty empty]]; + [a push:p]; +} + + +- (void)didMatchAnd:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id top = [a pop]; + PKSequence *p = [PKSequence sequence]; + [p add:[a pop]]; + [p add:top]; + [a push:p]; +} + + +- (void)didMatchOr:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id top = [a pop]; +// NSLog(@"top: %@", top); +// NSLog(@"top class: %@", [top class]); + PKAlternation *p = [PKAlternation alternation]; + [p add:[a pop]]; + [p add:top]; + [a push:p]; +} + + +- (void)didMatchAssignment:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id val = [a pop]; + PKToken *keyTok = [a pop]; + + NSMutableDictionary *table = [NSMutableDictionary dictionaryWithDictionary:a.target]; + [table setObject:val forKey:keyTok.stringValue]; + a.target = table; +} + + +- (void)didMatchVariable:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *keyTok = [a pop]; + id val = [a.target objectForKey:keyTok.stringValue]; + +// PKParser *p = nil; +// if (valTok.isWord) { +// p = [PKWord wordWithString:valTok.value]; +// } else if (valTok.isQuotedString) { +// p = [PKQuotedString quotedStringWithString:valTok.value]; +// } else if (valTok.isNumber) { +// p = [PKNum numWithString:valTok.stringValue]; +// } + + [a push:val]; +} + +@synthesize selfIdentHeader; +@synthesize ruleName; +@synthesize tagFormat; +@synthesize lexiconURI; +@synthesize weight; +@synthesize repeat; +@synthesize probability; +@synthesize externalRuleRef; +@synthesize token; +@synthesize languageAttachment; +@synthesize tag; +@synthesize grammar; +@synthesize declaration; +@synthesize baseDecl; +@synthesize languageDecl; +@synthesize modeDecl; +@synthesize rootRuleDecl; +@synthesize tagFormatDecl; +@synthesize lexiconDecl; +@synthesize metaDecl; +@synthesize tagDecl; +@synthesize ruleDefinition; +@synthesize scope; +@synthesize ruleExpansion; +@synthesize ruleAlternative; +@synthesize sequenceElement; +@synthesize subexpansion; +@synthesize ruleRef; +@synthesize localRuleRef; +@synthesize specialRuleRef; +@synthesize repeatOperator; + +@synthesize baseURI; +@synthesize languageCode; +@synthesize ABNF_URI; +@synthesize ABNF_URI_with_Media_Type; +@end \ No newline at end of file diff --git a/test/.svn/text-base/SRGSParserTest.h.svn-base b/test/.svn/text-base/SRGSParserTest.h.svn-base new file mode 100644 index 0000000..f4f3cab --- /dev/null +++ b/test/.svn/text-base/SRGSParserTest.h.svn-base @@ -0,0 +1,20 @@ +// +// SRGSParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +#import "SRGSParser.h" + +@interface SRGSParserTest : SenTestCase { + NSString *s; + SRGSParser *p; + PKAssembly *a; + PKAssembly *result; +} + +@end diff --git a/test/.svn/text-base/SRGSParserTest.m.svn-base b/test/.svn/text-base/SRGSParserTest.m.svn-base new file mode 100644 index 0000000..399d5e1 --- /dev/null +++ b/test/.svn/text-base/SRGSParserTest.m.svn-base @@ -0,0 +1,196 @@ +// +// SRGSParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "SRGSParserTest.h" + +@implementation SRGSParserTest + +- (void)setUp { + p = [[[SRGSParser alloc] init] autorelease]; +} + + +- (void)test { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"example1" ofType:@"srgs"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDNotNil(result); + NSLog(@"\n\n\n result: %@ \n\n\n", result); +// TDEqualObjects(@"[#, ABNF, 1.0, ;]#/ABNF/1.0/;^", [result description]); +} + +- (void)testSelfIdentHeader { + s = @"#ABNF 1.0;"; + a = [p assemblyWithString:s]; + result = [p.selfIdentHeader bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[#, ABNF, 1.0, ;]#/ABNF/1.0/;^", [result description]); + + s = @"#ABNF 1.0 UTF;"; + a = [p assemblyWithString:s]; + result = [p.selfIdentHeader bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[#, ABNF, 1.0, UTF, ;]#/ABNF/1.0/UTF/;^", [result description]); +} + + +- (void)testRuleName { + s = @"$foobar"; + a = [p assemblyWithString:s]; + result = [p.ruleName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[$, foobar]$/foobar^", [result description]); +} + + +- (void)testWeight { + s = @"/4.0/"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [p.weight bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[/, 4.0, /]//4.0//^", [result description]); +} + + +- (void)testProbability { + s = @"/4.0/"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [p.probability bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[/, 4.0, /]//4.0//^", [result description]); +} + + +- (void)testRepeat { + s = @"1 - 4"; + a = [p assemblyWithString:s]; + result = [p.repeat bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[1, -, 4]1/-/4^", [result description]); + + s = @"1-4"; + a = [p assemblyWithString:s]; + result = [p.repeat bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[1, -, 4]1/-/4^", [result description]); +} + + +- (void)testToken { + s = @"foobar"; + a = [p assemblyWithString:s]; + result = [p.token bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foobar]foobar^", [result description]); + + s = @"'foobar'"; + a = [p assemblyWithString:s]; + result = [p.token bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"['foobar']'foobar'^", [result description]); +} + + +- (void)testTag { + s = @"{foobar}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, foobar, }]{/foobar/}^", [result description]); + + s = @"{bar baz}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, bar, baz, }]{/bar/baz/}^", [result description]); + + s = @"{bar 1.2 baz}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, bar, 1.2, baz, }]{/bar/1.2/baz/}^", [result description]); + + s = @"{!{'foobar'}!}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, !, {, 'foobar', }, !, }]{/!/{/'foobar'/}/!/}^", [result description]); + + s = @"{!{'foobar' baz}!}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, !, {, 'foobar', baz, }, !, }]{/!/{/'foobar'/baz/}/!/}^", [result description]); +} + + +- (void)testBaseDecl { + s = @"base url-goes-here;"; + a = [p assemblyWithString:s]; + result = [p.baseDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[base, url-goes-here, ;]base/url-goes-here/;^", [result description]); +} + + +- (void)testLanguageDecl { + s = @"language en-us;"; + a = [p assemblyWithString:s]; + result = [p.languageDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[language, en-us, ;]language/en-us/;^", [result description]); +} + + +- (void)testModeDecl { + s = @"mode voice;"; + a = [p assemblyWithString:s]; + result = [p.modeDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[mode, voice, ;]mode/voice/;^", [result description]); + + s = @"mode dtmf;"; + a = [p assemblyWithString:s]; + result = [p.modeDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[mode, dtmf, ;]mode/dtmf/;^", [result description]); +} + + +- (void)testRootRuleDecl { + s = @"root $foobar;"; + a = [p assemblyWithString:s]; + result = [p.rootRuleDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[root, $, foobar, ;]root/$/foobar/;^", [result description]); +} + + +- (void)testLanguageAttachment { + s = @"!en-us"; + a = [p assemblyWithString:s]; + result = [p.languageAttachment bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[!, en-us]!/en-us^", [result description]); +} + + +- (void)testRepeatOperator { + s = @"<0-2 /0.6/>"; + a = [p assemblyWithString:s]; + result = [p.repeatOperator bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[<, 0, -, 2, /, 0.6, /, >]^", [result description]); +} + + + + +@end diff --git a/test/.svn/text-base/TDAlternationTest.h.svn-base b/test/.svn/text-base/TDAlternationTest.h.svn-base new file mode 100644 index 0000000..430b7e2 --- /dev/null +++ b/test/.svn/text-base/TDAlternationTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKAlternationTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDAlternationTest : SenTestCase { + PKCollectionParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDAlternationTest.m.svn-base b/test/.svn/text-base/TDAlternationTest.m.svn-base new file mode 100644 index 0000000..37d55b7 --- /dev/null +++ b/test/.svn/text-base/TDAlternationTest.m.svn-base @@ -0,0 +1,97 @@ +// +// PKAlternationTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDAlternationTest.h" + +@implementation TDAlternationTest + +- (void)tearDown { + [a release]; +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz { + s = @"foo baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKAlternation alternation]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo]foo^baz/bar", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz1 { + s = @"123 baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKAlternation alternation]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + [p add:[PKNumber number]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^baz/bar", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz2 { + s = @"123 baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + PKParser *w = [PKWord word]; + PKParser *baz = [PKLiteral literalWithString:@"baz"]; + PKParser *n = [PKNumber number]; + p = [PKAlternation alternationWithSubparsers:w, baz, n, nil]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^baz/bar", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz3 { + s = @"123 baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKAlternation alternation]; + [p add:[PKWord word]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKNumber number]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^baz/bar", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz4 { + s = @"123 baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKAlternation alternation]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + [p add:[PKNumber number]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^baz/bar", [result description]); +} + +@end diff --git a/test/.svn/text-base/TDArithmeticAssembler.h.svn-base b/test/.svn/text-base/TDArithmeticAssembler.h.svn-base new file mode 100644 index 0000000..409fd74 --- /dev/null +++ b/test/.svn/text-base/TDArithmeticAssembler.h.svn-base @@ -0,0 +1,15 @@ +// +// TDArithmeticAssembler.h +// ParseKit +// +// Created by Todd Ditchendorf on 9/4/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDArithmeticAssembler : NSObject { + +} + +@end diff --git a/test/.svn/text-base/TDArithmeticAssembler.m.svn-base b/test/.svn/text-base/TDArithmeticAssembler.m.svn-base new file mode 100644 index 0000000..e480791 --- /dev/null +++ b/test/.svn/text-base/TDArithmeticAssembler.m.svn-base @@ -0,0 +1,58 @@ +// +// TDArithmeticAssembler.m +// ParseKit +// +// Created by Todd Ditchendorf on 9/4/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDArithmeticAssembler.h" +#import + +@implementation TDArithmeticAssembler + +- (void)didMatchPlus:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + [a push:[NSNumber numberWithDouble:tok1.floatValue + tok2.floatValue]]; +} + + +- (void)didMatchMinus:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + [a push:[NSNumber numberWithDouble:tok1.floatValue - tok2.floatValue]]; +} + + +- (void)didMatchTimes:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + [a push:[NSNumber numberWithDouble:tok1.floatValue * tok2.floatValue]]; +} + + +- (void)didMatchDivide:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + [a push:[NSNumber numberWithDouble:tok1.floatValue / tok2.floatValue]]; +} + + +- (void)didMatchExp:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + + CGFloat n1 = tok1.floatValue; + CGFloat n2 = tok2.floatValue; + + CGFloat res = n1; + NSUInteger i = 1; + for ( ; i < n2; i++) { + res *= n1; + } + + [a push:[NSNumber numberWithDouble:res]]; +} + +@end diff --git a/test/.svn/text-base/TDArithmeticParser.h.svn-base b/test/.svn/text-base/TDArithmeticParser.h.svn-base new file mode 100644 index 0000000..ec2da0e --- /dev/null +++ b/test/.svn/text-base/TDArithmeticParser.h.svn-base @@ -0,0 +1,33 @@ +// +// PKArithmeticParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDArithmeticParser : PKSequence { + PKCollectionParser *exprParser; + PKCollectionParser *termParser; + PKCollectionParser *plusTermParser; + PKCollectionParser *minusTermParser; + PKCollectionParser *factorParser; + PKCollectionParser *timesFactorParser; + PKCollectionParser *divFactorParser; + PKCollectionParser *exponentFactorParser; + PKCollectionParser *phraseParser; +} +- (double)parse:(NSString *)s; + +@property (retain) PKCollectionParser *exprParser; +@property (retain) PKCollectionParser *termParser; +@property (retain) PKCollectionParser *plusTermParser; +@property (retain) PKCollectionParser *minusTermParser; +@property (retain) PKCollectionParser *factorParser; +@property (retain) PKCollectionParser *timesFactorParser; +@property (retain) PKCollectionParser *divFactorParser; +@property (retain) PKCollectionParser *exponentFactorParser; +@property (retain) PKCollectionParser *phraseParser; +@end diff --git a/test/.svn/text-base/TDArithmeticParser.m.svn-base b/test/.svn/text-base/TDArithmeticParser.m.svn-base new file mode 100644 index 0000000..6a029de --- /dev/null +++ b/test/.svn/text-base/TDArithmeticParser.m.svn-base @@ -0,0 +1,247 @@ +// +// PKArithmeticParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDArithmeticParser.h" + +/* + expr = term (plusTerm | minusTerm)* + term = factor (timesFactor | divFactor)* + plusTerm = '+' term + minusTerm = '-' term + factor = phrase exponentFactor | phrase + timesFactor = '*' factor + divFactor = '/' factor + exponentFactor = '^' factor + phrase = '(' expr ')' | Number +*/ + +@implementation TDArithmeticParser + +- (id)init { + if (self = [super init]) { + [self add:self.exprParser]; + } + return self; +} + + +- (void)dealloc { + self.exprParser = nil; + self.termParser = nil; + self.plusTermParser = nil; + self.minusTermParser = nil; + self.factorParser = nil; + self.timesFactorParser = nil; + self.divFactorParser = nil; + self.exponentFactorParser = nil; + self.phraseParser = nil; + [super dealloc]; +} + + +- (double)parse:(NSString *)s { + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + a = [self completeMatchFor:a]; +// NSLog(@"\n\na: %@\n\n", a); + NSNumber *n = [a pop]; + double f = [n doubleValue]; + return f; +} + + +// expr = term (plusTerm | minusTerm)* +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + [exprParser add:self.termParser]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:self.plusTermParser]; + [a add:self.minusTermParser]; + + [exprParser add:[PKRepetition repetitionWithSubparser:a]]; + } + return exprParser; +} + + +// term = factor (timesFactor | divFactor)* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + [termParser add:self.factorParser]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:self.timesFactorParser]; + [a add:self.divFactorParser]; + + [termParser add:[PKRepetition repetitionWithSubparser:a]]; + } + return termParser; +} + + +// plusTerm = '+' term +- (PKCollectionParser *)plusTermParser { + if (!plusTermParser) { + self.plusTermParser = [PKSequence sequence]; + [plusTermParser add:[[PKSymbol symbolWithString:@"+"] discard]]; + [plusTermParser add:self.termParser]; + [plusTermParser setAssembler:self selector:@selector(didMatchPlus:)]; + } + return plusTermParser; +} + + +// minusTerm = '-' term +- (PKCollectionParser *)minusTermParser { + if (!minusTermParser) { + self.minusTermParser = [PKSequence sequence]; + [minusTermParser add:[[PKSymbol symbolWithString:@"-"] discard]]; + [minusTermParser add:self.termParser]; + [minusTermParser setAssembler:self selector:@selector(didMatchMinus:)]; + } + return minusTermParser; +} + + +// factor = phrase exponentFactor | phrase +- (PKCollectionParser *)factorParser { + if (!factorParser) { + self.factorParser = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:self.phraseParser]; + [s add:self.exponentFactorParser]; + + [factorParser add:s]; + [factorParser add:self.phraseParser]; + } + return factorParser; +} + + +// timesFactor = '*' factor +- (PKCollectionParser *)timesFactorParser { + if (!timesFactorParser) { + self.timesFactorParser = [PKSequence sequence]; + [timesFactorParser add:[[PKSymbol symbolWithString:@"*"] discard]]; + [timesFactorParser add:self.factorParser]; + [timesFactorParser setAssembler:self selector:@selector(didMatchTimes:)]; + } + return timesFactorParser; +} + + +// divFactor = '/' factor +- (PKCollectionParser *)divFactorParser { + if (!divFactorParser) { + self.divFactorParser = [PKSequence sequence]; + [divFactorParser add:[[PKSymbol symbolWithString:@"/"] discard]]; + [divFactorParser add:self.factorParser]; + [divFactorParser setAssembler:self selector:@selector(didMatchDivide:)]; + } + return divFactorParser; +} + + +// exponentFactor = '^' factor +- (PKCollectionParser *)exponentFactorParser { + if (!exponentFactorParser) { + self.exponentFactorParser = [PKSequence sequence]; + [exponentFactorParser add:[[PKSymbol symbolWithString:@"^"] discard]]; + [exponentFactorParser add:self.factorParser]; + [exponentFactorParser setAssembler:self selector:@selector(didMatchExp:)]; + } + return exponentFactorParser; +} + + +// phrase = '(' expr ')' | Number +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + self.phraseParser = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[[PKSymbol symbolWithString:@"("] discard]]; + [s add:self.exprParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + [phraseParser add:s]; + + PKNumber *n = [PKNumber number]; + [n setAssembler:self selector:@selector(didMatchNumber:)]; + [phraseParser add:n]; + } + return phraseParser; +} + + +#pragma mark - +#pragma mark Assembler + +- (void)didMatchNumber:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithDouble:tok.floatValue]]; +} + + +- (void)didMatchPlus:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + [a push:[NSNumber numberWithDouble:[n1 doubleValue] + [n2 doubleValue]]]; +} + + +- (void)didMatchMinus:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + [a push:[NSNumber numberWithDouble:[n1 doubleValue] - [n2 doubleValue]]]; +} + + +- (void)didMatchTimes:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + [a push:[NSNumber numberWithDouble:[n1 doubleValue] * [n2 doubleValue]]]; +} + + +- (void)didMatchDivide:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + [a push:[NSNumber numberWithDouble:[n1 doubleValue] / [n2 doubleValue]]]; +} + + +- (void)didMatchExp:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + + double d1 = [n1 doubleValue]; + double d2 = [n2 doubleValue]; + + double res = d1; + NSUInteger i = 1; + for ( ; i < d2; i++) { + res *= d1; + } + + [a push:[NSNumber numberWithDouble:res]]; +} + +@synthesize exprParser; +@synthesize termParser; +@synthesize plusTermParser; +@synthesize minusTermParser; +@synthesize factorParser; +@synthesize timesFactorParser; +@synthesize divFactorParser; +@synthesize exponentFactorParser; +@synthesize phraseParser; +@end diff --git a/test/.svn/text-base/TDArithmeticParserTest.h.svn-base b/test/.svn/text-base/TDArithmeticParserTest.h.svn-base new file mode 100644 index 0000000..45ae814 --- /dev/null +++ b/test/.svn/text-base/TDArithmeticParserTest.h.svn-base @@ -0,0 +1,18 @@ +// +// PKArithmeticParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "TDArithmeticParser.h" + +@interface TDArithmeticParserTest : SenTestCase { + NSString *s; + TDArithmeticParser *p; + double result; +} + +@end diff --git a/test/.svn/text-base/TDArithmeticParserTest.m.svn-base b/test/.svn/text-base/TDArithmeticParserTest.m.svn-base new file mode 100644 index 0000000..0fbfddb --- /dev/null +++ b/test/.svn/text-base/TDArithmeticParserTest.m.svn-base @@ -0,0 +1,342 @@ +// +// PKArithmeticParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDArithmeticParserTest.h" + +@implementation TDArithmeticParserTest + +- (void)setUp { + p = [TDArithmeticParser parser]; +} + + +- (void)testOne { + s = @"1"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)testFortySeven { + s = @"47"; + result = [p parse:s]; + TDEquals((double)47.0, result); +} + + +- (void)testNegativeZero { + s = @"-0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testNegativeOne { + s = @"-1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testOnePlusOne { + s = @"1 + 1"; + result = [p parse:s]; + TDEquals((double)2.0, result); +} + + +- (void)testOnePlusNegativeOne { + s = @"1 + -1"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testNegativeOnePlusOne { + s = @"-1 + 1"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testOneHundredPlusZero { + s = @"100 + 0"; + result = [p parse:s]; + TDEquals((double)100.0, result); +} + + +- (void)testNegativeOnePlusZero { + s = @"-1 + 0"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testNegativeZeroPlusZero { + s = @"-0 + 0"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testNegativeZeroPlusNegativeZero { + s = @"-0 + -0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testOneMinusOne { + s = @"1 - 1"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testOneMinusNegativeOne { + s = @"1 - -1"; + result = [p parse:s]; + TDEquals((double)2.0, result); +} + + +- (void)testNegativeOneMinusOne { + s = @"-1 - 1"; + result = [p parse:s]; + TDEquals((double)-2.0, result); +} + + +- (void)testOneHundredMinusZero { + s = @"100 - 0"; + result = [p parse:s]; + TDEquals((double)100.0, result); +} + + +- (void)testNegativeOneMinusZero { + s = @"-1 - 0"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testNegativeZeroMinusZero { + s = @"-0 - 0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testNegativeZeroMinusNegativeZero { + s = @"-0 - -0"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testOneTimesOne { + s = @"1 * 1"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)testTwoTimesFour { + s = @"2 * 4"; + result = [p parse:s]; + TDEquals((double)8.0, result); +} + + +- (void)testOneTimesNegativeOne { + s = @"1 * -1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testNegativeOneTimesOne { + s = @"-1 * 1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testOneHundredTimesZero { + s = @"100 * 0"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testNegativeOneTimesZero { + s = @"-1 * 0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testNegativeZeroTimesZero { + s = @"-0 * 0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testNegativeZeroTimesNegativeZero { + s = @"-0 * -0"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testOneDivOne { + s = @"1 / 1"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)testTwoDivFour { + s = @"2 / 4"; + result = [p parse:s]; + TDEquals((double)0.5f, result); +} + + +- (void)testFourDivTwo { + s = @"4 / 2"; + result = [p parse:s]; + TDEquals((double)2.0, result); +} + + +- (void)testOneDivNegativeOne { + s = @"1 / -1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testNegativeOneDivOne { + s = @"-1 / 1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testOneHundredDivZero { + s = @"100 / 0"; + result = [p parse:s]; + TDEquals((double)INFINITY, result); +} + + +- (void)testNegativeOneDivZero { + s = @"-1 / 0"; + result = [p parse:s]; + TDEquals((double)-INFINITY, result); +} + + +- (void)testNegativeZeroDivZero { + s = @"-0 / 0"; + result = [p parse:s]; + TDEquals((double)NAN, result); +} + + +- (void)testNegativeZeroDivNegativeZero { + s = @"-0 / -0"; + result = [p parse:s]; + TDEquals((double)NAN, result); +} + + +- (void)test1Exp1 { + s = @"1 ^ 1"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)test1Exp2 { + s = @"1 ^ 2"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)test9Exp2 { + s = @"9 ^ 2"; + result = [p parse:s]; + TDEquals((double)81.0, result); +} + + +- (void)test9ExpNegative2 { + s = @"9 ^ -2"; + result = [p parse:s]; + TDEquals((double)9.0, result); +} + + +#pragma mark - +#pragma mark Associativity + +- (void)test7minus3minus1 { // minus associativity + s = @"7 - 3 - 1"; + result = [p parse:s]; + TDEquals((double)3.0, (double)result); +} + + +- (void)test9exp2minus81 { // exp associativity + s = @"9^2 - 81"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)test2exp1exp4 { // exp + s = @"2 ^ 1 ^ 4"; + result = [p parse:s]; + TDEquals((double)2.0, result); +} + + +- (void)test100minus5exp2times3 { // exp + s = @"100 - 5^2*3"; + result = [p parse:s]; + TDEquals((double)25.0, result); +} + + +- (void)test100minus25times3 { // precedence + s = @"100 - 25*3"; + result = [p parse:s]; + STAssertEqualsWithAccuracy((double)25.0, result, 1.0, @""); +} + + +- (void)test100minus25times3Parens { // precedence + s = @"(100 - 25)*3"; + result = [p parse:s]; + TDEquals((double)225.0, result); +} + + +- (void)test100minus5exp2times3Parens { // precedence + s = @"(100 - 5^2)*3"; + result = [p parse:s]; + TDEquals((double)225.0, result); +} + +@end diff --git a/test/.svn/text-base/TDBlob.h.svn-base b/test/.svn/text-base/TDBlob.h.svn-base new file mode 100644 index 0000000..efd81fc --- /dev/null +++ b/test/.svn/text-base/TDBlob.h.svn-base @@ -0,0 +1,17 @@ +// +// PKBlob.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDBlob : PKTerminal { + +} ++ (id)blob; + ++ (id)blobWithStartMarker:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDBlob.m.svn-base b/test/.svn/text-base/TDBlob.m.svn-base new file mode 100644 index 0000000..1be3c69 --- /dev/null +++ b/test/.svn/text-base/TDBlob.m.svn-base @@ -0,0 +1,34 @@ +// +// PKBlob.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDBlob.h" +#import +#import "PKToken+Blob.h" + +@implementation TDBlob + ++ (id)blob { + return [self blobWithStartMarker:nil]; +} + + ++ (id)blobWithStartMarker:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + BOOL result = tok.isBlob; + if (self.string) { + result = [tok.stringValue hasPrefix:self.string]; + } + return result; +} + +@end diff --git a/test/.svn/text-base/TDBlobState.h.svn-base b/test/.svn/text-base/TDBlobState.h.svn-base new file mode 100644 index 0000000..d387d5e --- /dev/null +++ b/test/.svn/text-base/TDBlobState.h.svn-base @@ -0,0 +1,15 @@ +// +// PKBlobState.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDBlobState : PKTokenizerState { + +} + +@end diff --git a/test/.svn/text-base/TDBlobState.m.svn-base b/test/.svn/text-base/TDBlobState.m.svn-base new file mode 100644 index 0000000..51dcd49 --- /dev/null +++ b/test/.svn/text-base/TDBlobState.m.svn-base @@ -0,0 +1,45 @@ +// +// PKBlobState.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDBlobState.h" +#import +#import +#import "PKToken+Blob.h" + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation TDBlobState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + PKUniChar c = cin; + do { + [self append:c]; + c = [r read]; + } while (PKEOF != c && !isspace(c)); + + if (PKEOF != c) { + [r unread]; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeBlob stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; +} + +@end diff --git a/test/.svn/text-base/TDCharTest.h.svn-base b/test/.svn/text-base/TDCharTest.h.svn-base new file mode 100644 index 0000000..2c7d7ff --- /dev/null +++ b/test/.svn/text-base/TDCharTest.h.svn-base @@ -0,0 +1,19 @@ +// +// PKCharTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + + +@interface TDCharTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + PKChar *p; + PKAssembly *result; +} + +@end diff --git a/test/.svn/text-base/TDCharTest.m.svn-base b/test/.svn/text-base/TDCharTest.m.svn-base new file mode 100644 index 0000000..0c517f3 --- /dev/null +++ b/test/.svn/text-base/TDCharTest.m.svn-base @@ -0,0 +1,59 @@ +// +// PKCharTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDCharTest.h" + +@interface PKAssembly () +- (BOOL)hasMore; +@end + +@implementation TDCharTest + +- (void)test123 { + s = @"123"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^123", [a description]); + p = [PKChar char]; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[1]1^23", [result description]); + TDTrue([a hasMore]); +} + + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKChar char]; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a]a^bc", [result description]); + TDTrue([a hasMore]); +} + +- (void)testRepetition { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKChar char]; + PKParser *r = [PKRepetition repetitionWithSubparser:p]; + + result = [r bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a, b, c]abc^", [result description]); + TDFalse([result hasMore]); +} + + +@end diff --git a/test/.svn/text-base/TDCharacterAssemblyTest.h.svn-base b/test/.svn/text-base/TDCharacterAssemblyTest.h.svn-base new file mode 100644 index 0000000..6df14e3 --- /dev/null +++ b/test/.svn/text-base/TDCharacterAssemblyTest.h.svn-base @@ -0,0 +1,18 @@ +// +// PKCharacterAssemblyTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + + +@interface TDCharacterAssemblyTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + PKAssembly *result; +} + +@end diff --git a/test/.svn/text-base/TDCharacterAssemblyTest.m.svn-base b/test/.svn/text-base/TDCharacterAssemblyTest.m.svn-base new file mode 100644 index 0000000..692fdbd --- /dev/null +++ b/test/.svn/text-base/TDCharacterAssemblyTest.m.svn-base @@ -0,0 +1,59 @@ +// +// PKCharacterAssemblyTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDCharacterAssemblyTest.h" + +@interface PKAssembly () +- (id)next; +- (BOOL)hasMore; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@property (nonatomic, readonly) NSUInteger objectsRemaining; +@end + +@implementation TDCharacterAssemblyTest + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDNotNil(a); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)0, a.objectsConsumed); + TDEquals((NSUInteger)3, a.objectsRemaining); + TDEquals(YES, [a hasMore]); + + id obj = [a next]; + TDEqualObjects(obj, [NSNumber numberWithInteger:'a']); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)1, a.objectsConsumed); + TDEquals((NSUInteger)2, a.objectsRemaining); + TDEquals(YES, [a hasMore]); + + obj = [a next]; + TDEqualObjects(obj, [NSNumber numberWithInteger:'b']); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)2, a.objectsConsumed); + TDEquals((NSUInteger)1, a.objectsRemaining); + TDEquals(YES, [a hasMore]); + + obj = [a next]; + TDEqualObjects(obj, [NSNumber numberWithInteger:'c']); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)3, a.objectsConsumed); + TDEquals((NSUInteger)0, a.objectsRemaining); + TDEquals(NO, [a hasMore]); + + obj = [a next]; + TDNil(obj); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)3, a.objectsConsumed); + TDEquals((NSUInteger)0, a.objectsRemaining); + TDEquals(NO, [a hasMore]); +} + +@end diff --git a/test/.svn/text-base/TDCommentStateTest.h.svn-base b/test/.svn/text-base/TDCommentStateTest.h.svn-base new file mode 100644 index 0000000..88f45c7 --- /dev/null +++ b/test/.svn/text-base/TDCommentStateTest.h.svn-base @@ -0,0 +1,19 @@ +// +// PKCommentStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDCommentStateTest : SenTestCase { + PKCommentState *commentState; + PKReader *r; + PKTokenizer *t; + NSString *s; + PKToken *tok; +} + +@end diff --git a/test/.svn/text-base/TDCommentStateTest.m.svn-base b/test/.svn/text-base/TDCommentStateTest.m.svn-base new file mode 100644 index 0000000..a2a72d3 --- /dev/null +++ b/test/.svn/text-base/TDCommentStateTest.m.svn-base @@ -0,0 +1,486 @@ +// +// PKCommentStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDCommentStateTest.h" + +@implementation TDCommentStateTest + +- (void)setUp { + r = [[PKReader alloc] init]; + t = [[PKTokenizer alloc] init]; + commentState = t.commentState; +} + + +- (void)tearDown { + [r release]; + [t release]; +} + + +- (void)testSlashSlashFoo { + s = @"// foo"; + r.string = s; + t.string = s; + tok = [commentState nextTokenFromReader:r startingWith:'/' tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(tok.offset, (NSUInteger)-1); + TDEquals([r read], PKEOF); +} + + +- (void)testReportSlashSlashFoo { + s = @"// foo"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.offset, (NSUInteger)0); + TDEqualObjects([t nextToken], [PKToken EOFToken]); +} + + +- (void)testReportSpaceSlashSlashFoo { + s = @" // foo"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"// foo"); + TDEquals(tok.offset, (NSUInteger)1); + TDEqualObjects([t nextToken], [PKToken EOFToken]); +} + + +- (void)testTurnOffSlashSlashFoo { + s = @"// foo"; + r.string = s; + t.string = s; + [commentState removeSingleLineStartMarker:@"//"]; + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"/"); + TDEquals(tok.offset, (NSUInteger)0); + TDEquals([r read], (PKUniChar)'/'); +} + + +- (void)testHashFoo { + s = @"# foo"; + r.string = s; + t.string = s; + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.offset, (NSUInteger)2); + + r.string = s; + t.string = s; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)1); +} + + +- (void)testAddHashFoo { + s = @"# foo"; + t.string = s; + [commentState addSingleLineStartMarker:@"#"]; + [t setTokenizerState:commentState from:'#' to:'#']; + tok = [t nextToken]; + TDEquals(tok, [PKToken EOFToken]); + TDEqualObjects(tok.stringValue, [[PKToken EOFToken] stringValue]); + TDEquals(tok.offset, (NSUInteger)-1); +} + + +- (void)testReportAddHashFoo { + s = @"# foo"; + t.string = s; + commentState.reportsCommentTokens = YES; + [commentState addSingleLineStartMarker:@"#"]; + [t setTokenizerState:commentState from:'#' to:'#']; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testSlashStarFooStarSlash { + s = @"/* foo */"; + t.string = s; + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals([r read], PKEOF); +} + + +- (void)testSlashStarFooStarSlashSpace { + s = @"/* foo */ "; + t.string = s; + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals([r read], PKEOF); +} + + +- (void)testReportSlashStarFooStarSlash { + s = @"/* foo */"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals([t nextToken], [PKToken EOFToken]); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testReportSlashStarFooStarSlashSpace { + s = @"/* foo */ "; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEquals(tok.offset, (NSUInteger)0); + TDEqualObjects(tok.stringValue, @"/* foo */"); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); +} + + +- (void)testReportSlashStarFooStarSlashSpaceA { + s = @"/* foo */ a"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)10); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)9); +} + + +- (void)testReportSlashStarStarFooStarSlashSpaceA { + s = @"/** foo */ a"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/** foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)11); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/** foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)10); +} + + +- (void)testReportSlashStarFooStarStarSlashSpaceA { + s = @"/* foo **/ a"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo **/"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)11); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo **/"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)10); +} + + +- (void)testReportSlashStarFooStarSlashSpaceStarSlash { + s = @"/* foo */ */"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"*"); + TDEquals(tok.offset, (NSUInteger)10); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)9); +} + + +- (void)testTurnOffSlashStarFooStarSlash { + s = @"/* foo */"; + t.string = s; + [commentState removeMultiLineStartMarker:@"/*"]; + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"/"); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testReportSlashStarFooStar { + s = @"/* foo *"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testReportBalancedSlashStarFooStar { + s = @"/* foo *"; + t.string = s; + commentState.reportsCommentTokens = YES; + commentState.balancesEOFTerminatedComments = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo **/"); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testReportBalancedSlashStarFoo { + s = @"/* foo "; + t.string = s; + commentState.reportsCommentTokens = YES; + commentState.balancesEOFTerminatedComments = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testXMLFooStarXMLA { + s = @" a"; + t.string = s; + [commentState addMultiLineStartMarker:@""]; + [t setTokenizerState:commentState from:'<' to:'<']; + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)13); + + t.string = s; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)12); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)13); +} + + +- (void)testReportXMLFooStarXMLA { + s = @" a"; + t.string = s; + commentState.reportsCommentTokens = YES; + [commentState addMultiLineStartMarker:@""]; + [t setTokenizerState:commentState from:'<' to:'<']; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @""); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)13); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @""); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)12); +} + + +- (void)testXXMarker { + s = @"XX foo XX a"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + [commentState addMultiLineStartMarker:@"XX" endMarker:@"XX"]; + [t setTokenizerState:commentState from:'X' to:'X']; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"XX foo XX"); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"XX foo XX"); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); +} + + +- (void)testXXMarkerFalseStartMarkerMatch { + s = @"X foo X a"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + [commentState addMultiLineStartMarker:@"XX" endMarker:@"XX"]; + [t setTokenizerState:commentState from:'X' to:'X']; + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"X"); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"X"); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLuaComments { + s = @"--[comment"; + t.string = s; + + [t setTokenizerState:t.symbolState from:'/' to:'/']; + [t setTokenizerState:t.commentState from:'-' to:'-']; + + [t.commentState addSingleLineStartMarker:@"--"]; + [t.commentState addMultiLineStartMarker:@"--[[" endMarker:@"]]"]; + + t.commentState.reportsCommentTokens = YES; + + PKToken *eof = [PKToken EOFToken]; + + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + + tok = [t nextToken]; + TDEquals(eof, tok); +} + + +- (void)testLuaComments2 { + s = @"--[[[comment]]"; + t.string = s; + + [t setTokenizerState:t.symbolState from:'/' to:'/']; + [t setTokenizerState:t.commentState from:'-' to:'-']; + + [t.commentState addSingleLineStartMarker:@"--"]; + [t.commentState addMultiLineStartMarker:@"--[[" endMarker:@"]]"]; + + t.commentState.reportsCommentTokens = YES; + + PKToken *eof = [PKToken EOFToken]; + + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + + tok = [t nextToken]; + TDEquals(eof, tok); +} + +@end diff --git a/test/.svn/text-base/TDDelimitStateTest.h.svn-base b/test/.svn/text-base/TDDelimitStateTest.h.svn-base new file mode 100644 index 0000000..65c9c5f --- /dev/null +++ b/test/.svn/text-base/TDDelimitStateTest.h.svn-base @@ -0,0 +1,18 @@ +// +// PKDelimitStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/21/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDDelimitStateTest : SenTestCase { + PKDelimitState *delimitState; + PKTokenizer *t; + NSString *s; + PKToken *tok; +} + +@end diff --git a/test/.svn/text-base/TDDelimitStateTest.m.svn-base b/test/.svn/text-base/TDDelimitStateTest.m.svn-base new file mode 100644 index 0000000..bf059e7 --- /dev/null +++ b/test/.svn/text-base/TDDelimitStateTest.m.svn-base @@ -0,0 +1,824 @@ +// +// PKDelimitStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/21/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDDelimitStateTest.h" + +@implementation TDDelimitStateTest + +- (void)setUp { + t = [[PKTokenizer alloc] init]; + delimitState = t.delimitState; +} + + +- (void)tearDown { + [t release]; +} + + +- (void)testLtFooGt { + s = @""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testSlashFooSlash { + s = @"/foo/"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'/' to:'/']; + [delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testSlashFooSlashBar { + s = @"/foo/bar"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'/' to:'/']; + [delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"/foo/"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"bar"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testSlashFooSlashSemi { + s = @"/foo/;"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'/' to:'/']; + [delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"/foo/"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @";"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtFooGtWithFOAllowed { + s = @""; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"fo"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtFooGtWithFAllowed { + s = @""; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"f"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @">"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtFooGtWithFAllowedAndRemove { + s = @""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<" endMarker:@">" allowedCharacterSet:cs]; + [delimitState removeStartMarker:@"<"]; + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @">"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooGt { + s = @"<#foo>"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<#" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooGtWithFOAllowed { + s = @"<#foo>"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"fo"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<#" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooGtWithFAllowed { + s = @"<#foo>"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"f"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<#" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @">"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooGtWithFAllowedAndMultiCharSymbol { + s = @"<#foo>"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"f"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<#" endMarker:@">" allowedCharacterSet:cs]; + + [t.symbolState add:@"<#"]; + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @">"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooHashGt { + s = @"=#foo#="; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'=' to:'=']; + [delimitState addStartMarker:@"=#" endMarker:@"#=" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooHashGtWithFOAllowed { + s = @"=#foo#="; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"fo"]; + + [t setTokenizerState:delimitState from:'=' to:'=']; + [delimitState addStartMarker:@"=#" endMarker:@"#=" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooHashGtWithFAllowed { + s = @"=#foo#="; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"f"]; + + [t setTokenizerState:delimitState from:'=' to:'=']; + [delimitState addStartMarker:@"=#" endMarker:@"#=" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"="); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"="); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollar123Dollar { + s = @"$123$"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$" endMarker:@"$" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarDollar { + s = @"$$123$$"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$$" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHash { + s = @"$$123$#"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHashDecimalDigitAllowed { + s = @"$$123$#"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet decimalDigitCharacterSet]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHashAlphanumericAllowed { + s = @"$$123$#"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet alphanumericCharacterSet]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHashAlphanumericAndWhitespaceAndNewlineAllowed { + s = @"$$123 456\t789\n0$#"; + t.string = s; + NSMutableCharacterSet *cs = [[[NSCharacterSet alphanumericCharacterSet] mutableCopy] autorelease]; + [cs formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]]; + [cs formUnionWithCharacterSet:[NSCharacterSet newlineCharacterSet]]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHashWhitespaceAllowed { + s = @"$$123$#"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet whitespaceCharacterSet]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"123"); + TDEquals(tok.floatValue, (CGFloat)123.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollarDollarHash { + s = @"$$$#"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollarDollar { + s = @"$$$"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollarDollarBalanceEOFStrings { + s = @"$$$"; + t.string = s; + NSCharacterSet *cs = nil; + + delimitState.balancesEOFTerminatedStrings = YES; + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"$$$$#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testPHPPrint { + s = @""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testPHP { + s = @""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testEnvVars { + s = @"${PRODUCT_NAME} or ${EXECUTABLE_NAME}"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ_"]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"${" endMarker:@"}" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"${PRODUCT_NAME}"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"or"); + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"${EXECUTABLE_NAME}"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testCocoaString { + s = @"@\"foo\""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'@' to:'@']; + [delimitState addStartMarker:@"@\"" endMarker:@"\"" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAlphaMarkerXX { + s = @"XXfooXX"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'X' to:'X']; + [delimitState addStartMarker:@"XX" endMarker:@"XX" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAlphaMarkerXXAndXXX { + s = @"XXfooXXX"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'X' to:'X']; + [delimitState addStartMarker:@"XX" endMarker:@"XXX" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAlphaMarkerXXFails { + s = @"XXfooXX"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet whitespaceCharacterSet]; + + [t setTokenizerState:delimitState from:'X' to:'X']; + [delimitState addStartMarker:@"XX" endMarker:@"XX" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAlphaMarkerXXFalseStartMarker { + s = @"XfooXX"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet whitespaceCharacterSet]; + + [t setTokenizerState:delimitState from:'X' to:'X']; + [delimitState addStartMarker:@"XX" endMarker:@"XX" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAtStartMarkerNilEndMarker { + s = @"@foo"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet alphanumericCharacterSet]; + + [t setTokenizerState:delimitState from:'@' to:'@']; + [delimitState addStartMarker:@"@" endMarker:nil allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAtStartMarkerNilEndMarker2 { + s = @"@foo bar @ @baz "; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet alphanumericCharacterSet]; + + [t setTokenizerState:delimitState from:'@' to:'@']; + [delimitState addStartMarker:@"@" endMarker:nil allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"@foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"bar"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"@"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"@baz"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testUnbalancedElementStartTag { + s = @"" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + t.string = s; + delimitState.allowsUnbalancedStrings = YES; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @" + +@class PKTokenizer; +@class PKToken; + +@interface TDFastJsonParser : NSObject { + PKTokenizer *tokenizer; + NSMutableArray *stack; + PKToken *curly; + PKToken *bracket; +} +- (id)parse:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDFastJsonParser.m.svn-base b/test/.svn/text-base/TDFastJsonParser.m.svn-base new file mode 100644 index 0000000..b0023f3 --- /dev/null +++ b/test/.svn/text-base/TDFastJsonParser.m.svn-base @@ -0,0 +1,135 @@ +// +// PKFastJsonParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDFastJsonParser.h" +#import "ParseKit.h" +#import "NSString+ParseKitAdditions.h" + +@interface TDFastJsonParser () +- (void)didMatchDictionary; +- (void)didMatchArray; +- (NSArray *)objectsAbove:(id)fence; + +@property (retain) PKTokenizer *tokenizer; +@property (retain) NSMutableArray *stack; +@property (retain) PKToken *curly; +@property (retain) PKToken *bracket; +@end + +@implementation TDFastJsonParser + +- (id)init { + if (self = [super init]) { + self.tokenizer = [PKTokenizer tokenizer]; + + // configure tokenizer + [tokenizer setTokenizerState:tokenizer.symbolState from: '/' to: '/']; // JSON doesn't have slash slash or slash star comments + [tokenizer setTokenizerState:tokenizer.symbolState from: '\'' to: '\'']; // JSON does not have single quoted strings + + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.0]; + self.bracket = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"[" floatValue:0.0]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.stack = nil; + self.curly = nil; + self.bracket = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + self.stack = [NSMutableArray array]; + + tokenizer.string = s; + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + while ((tok = [tokenizer nextToken]) != eof) { + NSString *sval = tok.stringValue; + + if (tok.isSymbol) { + if ([@"{" isEqualToString:sval]) { + [stack addObject:tok]; + } else if ([@"}" isEqualToString:sval]) { + [self didMatchDictionary]; + } else if ([@"[" isEqualToString:sval]) { + [stack addObject:tok]; + } else if ([@"]" isEqualToString:sval]) { + [self didMatchArray]; + } + } else { + id value = nil; + if (tok.isQuotedString) { + value = [sval stringByTrimmingQuotes]; + } else if (tok.isNumber) { + value = [NSNumber numberWithFloat:tok.floatValue]; + } else { // if (tok.isWord) { + if ([@"null" isEqualToString:sval]) { + value = [NSNull null]; + } else if ([@"true" isEqualToString:sval]) { + value = [NSNumber numberWithBool:YES]; + } else if ([@"false" isEqualToString:sval]) { + value = [NSNumber numberWithBool:NO]; + } + } + [stack addObject:value]; + } + } + + return [stack lastObject]; +} + + +- (void)didMatchDictionary { + NSArray *a = [self objectsAbove:curly]; + NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:[a count]/2.]; + + NSInteger i = [a count] - 1; + for ( ; i >= 0; i--) { + NSString *key = [a objectAtIndex:i--]; + id value = [a objectAtIndex:i]; + [result setObject:value forKey:key]; + } + + [stack addObject:result]; +} + + +- (void)didMatchArray { + NSArray *a = [self objectsAbove:bracket]; + NSMutableArray *result = [NSMutableArray arrayWithCapacity:[a count]]; + for (id obj in [a reverseObjectEnumerator]) { + [result addObject:obj]; + } + [stack addObject:result]; +} + + +- (NSArray *)objectsAbove:(id)fence { + NSMutableArray *result = [NSMutableArray array]; + while (1) { + id obj = [stack lastObject]; + [stack removeLastObject]; + if ([obj isEqual:fence]) { + break; + } + [result addObject:obj]; + } + return result; +} + +@synthesize stack; +@synthesize tokenizer; +@synthesize curly; +@synthesize bracket; +@end diff --git a/test/.svn/text-base/TDFastJsonParserTest.h.svn-base b/test/.svn/text-base/TDFastJsonParserTest.h.svn-base new file mode 100644 index 0000000..29c4d1b --- /dev/null +++ b/test/.svn/text-base/TDFastJsonParserTest.h.svn-base @@ -0,0 +1,16 @@ +// +// PKFastJsonParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "ParseKit.h" + +@interface TDFastJsonParserTest : SenTestCase { + +} + +@end diff --git a/test/.svn/text-base/TDFastJsonParserTest.m.svn-base b/test/.svn/text-base/TDFastJsonParserTest.m.svn-base new file mode 100644 index 0000000..7e75cc9 --- /dev/null +++ b/test/.svn/text-base/TDFastJsonParserTest.m.svn-base @@ -0,0 +1,33 @@ +// +// PKFastJsonParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDFastJsonParserTest.h" +#import "TDFastJsonParser.h" + +@implementation TDFastJsonParserTest + +- (void)testRun { + NSString *s = @"{\"foo\":\"bar\"}"; + TDFastJsonParser *p = [[[TDFastJsonParser alloc] init] autorelease]; + id result = [p parse:s]; + + NSLog(@"result"); + TDNotNil(result); +} + + +- (void)testCrunchBaseJsonParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDFastJsonParser *parser = [[[TDFastJsonParser alloc] init] autorelease]; + [parser parse:s]; + // id res = [parser parse:s]; + //NSLog(@"res %@", res); +} + +@end diff --git a/test/.svn/text-base/TDGenericAssembler.h.svn-base b/test/.svn/text-base/TDGenericAssembler.h.svn-base new file mode 100644 index 0000000..d35f306 --- /dev/null +++ b/test/.svn/text-base/TDGenericAssembler.h.svn-base @@ -0,0 +1,25 @@ +// +// PKGenericAssembler.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/22/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKAssembly; + +@interface TDGenericAssembler : NSObject { + NSMutableDictionary *attributes; + NSMutableDictionary *defaultProperties; + NSMutableDictionary *productionNames; + PKAssembly *currentAssembly; + NSString *prefix; + NSString *suffix; +} +@property (nonatomic, retain) NSMutableDictionary *attributes; +@property (nonatomic, retain) NSMutableDictionary *defaultProperties; +@property (nonatomic, retain) NSMutableDictionary *productionNames; +@property (nonatomic, retain) PKAssembly *currentAssembly; +@end diff --git a/test/.svn/text-base/TDGenericAssembler.m.svn-base b/test/.svn/text-base/TDGenericAssembler.m.svn-base new file mode 100644 index 0000000..e6003ef --- /dev/null +++ b/test/.svn/text-base/TDGenericAssembler.m.svn-base @@ -0,0 +1,169 @@ +// +// PKGenericAssembler.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/22/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDGenericAssembler.h" +#import "NSArray+ParseKitAdditions.h" +#import + +@interface TDGenericAssembler () +- (void)didMatchTerminalNamed:(NSString *)name withAssembly:(PKAssembly *)a; +- (void)appendAttributedStringForObjects:(NSArray *)objs withAttrs:(id)attrs; +- (void)appendAttributedStringForObject:(id)obj withAttrs:(id)attrs; +- (NSMutableArray *)popWhitespaceTokensFrom:(PKAssembly *)a; +- (void)consumeWhitespaceTokens:(NSArray *)whitespaceToks; +- (void)consumeWhitespaceToken:(PKToken *)whitespaceTok; +- (void)consumeWhitespaceFrom:(PKAssembly *)a; + +@property (nonatomic, retain) NSString *prefix; +@property (nonatomic, retain) NSString *suffix; +@end + +@implementation TDGenericAssembler + +- (id)init { + if (self = [super init]) { + self.productionNames = [NSMutableDictionary dictionary]; + self.defaultProperties = [NSDictionary dictionaryWithObjectsAndKeys: + [NSColor blackColor], NSForegroundColorAttributeName, + [NSColor whiteColor], NSBackgroundColorAttributeName, + [NSFont fontWithName:@"Monaco" size:11.0], NSFontAttributeName, + nil]; + self.prefix = @"didMatch"; + self.suffix = @":"; + } + return self; +} + + +- (void)dealloc { + self.attributes = nil; + self.defaultProperties = nil; + self.productionNames = nil; + self.currentAssembly = nil; + self.prefix = nil; + self.suffix = nil; + [super dealloc]; +} + + +- (BOOL)respondsToSelector:(SEL)sel { + return YES; +} + + +- (id)performSelector:(SEL)sel withObject:(id)obj { + NSString *selName = NSStringFromSelector(sel); + + NSString *productionName = [productionNames objectForKey:selName]; + + if (!productionName) { + NSUInteger prefixLen = [prefix length]; + NSInteger c = ((NSInteger)[selName characterAtIndex:prefixLen]) + 32; // lowercase + NSRange r = NSMakeRange(prefixLen + 1, [selName length] - (prefixLen + [suffix length] + 1 /*:*/)); + productionName = [NSString stringWithFormat:@"%C%@", c, [selName substringWithRange:r]]; + [productionNames setObject:productionName forKey:selName]; + } + + [self didMatchTerminalNamed:productionName withAssembly:obj]; + + return nil; +} + + +- (void)didMatchTerminalNamed:(NSString *)name withAssembly:(PKAssembly *)a { + //NSLog(@"%@ : %@", name, a); + self.currentAssembly = a; + NSMutableArray *whitespaceToks = [self popWhitespaceTokensFrom:a]; + + id props = [attributes objectForKey:name]; + if (!props) props = defaultProperties; + + NSMutableArray *toks = nil; + PKToken *tok = nil; + while (tok = [a pop]) { + if (PKTokenTypeWhitespace != tok.tokenType) { + if (!toks) toks = [NSMutableArray array]; + [toks addObject:tok]; + } else { + [self consumeWhitespaceToken:tok]; + break; + } + } + + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:toks withAttrs:props]; + [self consumeWhitespaceTokens:whitespaceToks]; +} + + +- (void)appendAttributedStringForObjects:(NSArray *)objs withAttrs:(id)attrs { + for (id obj in objs) { + [self appendAttributedStringForObject:obj withAttrs:attrs]; + } +} + + +- (void)appendAttributedStringForObject:(id)obj withAttrs:(id)attrs { + NSMutableAttributedString *displayString = currentAssembly.target; + if (!displayString) { + displayString = [[[NSMutableAttributedString alloc] initWithString:@"" attributes:nil] autorelease]; + currentAssembly.target = displayString; + } + + + NSAttributedString *as = [[NSAttributedString alloc] initWithString:[obj stringValue] attributes:attrs]; + [displayString appendAttributedString:as]; + [as release]; +} + + +- (NSMutableArray *)popWhitespaceTokensFrom:(PKAssembly *)a { + NSMutableArray *whitespaceToks = nil; + PKToken *tok = nil; + while (tok = [a pop]) { + if (PKTokenTypeWhitespace == tok.tokenType) { + if (!whitespaceToks) { + whitespaceToks = [NSMutableArray array]; + } + [whitespaceToks addObject:tok]; + } else { + [a push:tok]; + break; + } + } + if (whitespaceToks) { + whitespaceToks = [whitespaceToks reversedMutableArray]; + } + return whitespaceToks; +} + + +- (void)consumeWhitespaceTokens:(NSArray *)whitespaceToks { + [self appendAttributedStringForObjects:whitespaceToks withAttrs:nil]; +} + + +- (void)consumeWhitespaceToken:(PKToken *)whitespaceTok { + [self appendAttributedStringForObject:whitespaceTok withAttrs:nil]; +} + + +- (void)consumeWhitespaceFrom:(PKAssembly *)a { + NSMutableArray *whitespaceToks = [self popWhitespaceTokensFrom:a]; + if (whitespaceToks) { + [self consumeWhitespaceTokens:whitespaceToks]; + } +} + +@synthesize attributes; +@synthesize defaultProperties; +@synthesize productionNames; +@synthesize currentAssembly; +@synthesize prefix; +@synthesize suffix; +@end diff --git a/test/.svn/text-base/TDGenericAssemblerTest.h.svn-base b/test/.svn/text-base/TDGenericAssemblerTest.h.svn-base new file mode 100644 index 0000000..374da85 --- /dev/null +++ b/test/.svn/text-base/TDGenericAssemblerTest.h.svn-base @@ -0,0 +1,25 @@ +// +// PKGenericAssemblerTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" +#import "TDMiniCSSAssembler.h" +#import "TDGenericAssembler.h" + +@interface TDGenericAssemblerTest : SenTestCase { + NSString *path; + NSString *grammarString; + NSString *s; + TDMiniCSSAssembler *cssAssember; + PKParserFactory *factory; + PKParser *cssParser; + PKAssembly *a; + TDGenericAssembler *genericAssember; +} + +@end diff --git a/test/.svn/text-base/TDGenericAssemblerTest.m.svn-base b/test/.svn/text-base/TDGenericAssemblerTest.m.svn-base new file mode 100644 index 0000000..2f574cc --- /dev/null +++ b/test/.svn/text-base/TDGenericAssemblerTest.m.svn-base @@ -0,0 +1,66 @@ +// +// PKGenericAssemblerTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDGenericAssemblerTest.h" + +@implementation TDGenericAssemblerTest + +- (void)setUp { + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + cssAssember = [[TDMiniCSSAssembler alloc] init]; + factory = [PKParserFactory factory]; + cssParser = [factory parserFromGrammar:grammarString assembler:cssAssember]; +} + + +- (void)tearDown { + [cssAssember release]; +} + + +- (void)testColor { + TDNotNil(cssParser); + + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"css"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + a = [PKTokenAssembly assemblyWithString:s]; + a = [cssParser bestMatchFor:a]; + + TDNotNil(cssAssember.attributes); + id props = [cssAssember.attributes objectForKey:@"openCurly"]; + TDNotNil(props); + +// color:red; +// background-color:blue; +// font-family:'Helvetica'; +// font-size:17px; + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Monaco"); + TDEquals((CGFloat)[font pointSize], (CGFloat)11.0); + + NSColor *bgColor = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(bgColor); + STAssertEqualsWithAccuracy([bgColor redComponent], (CGFloat)0.117, 0.001, @""); + STAssertEqualsWithAccuracy([bgColor greenComponent], (CGFloat)0.117, 0.001, @""); + STAssertEqualsWithAccuracy([bgColor blueComponent], (CGFloat)0.141, 0.001, @""); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)0.7, 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)0.14, 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)0.530, 0.001, @""); + +} + + + + +@end diff --git a/test/.svn/text-base/TDHtmlSyntaxHighlighter.h.svn-base b/test/.svn/text-base/TDHtmlSyntaxHighlighter.h.svn-base new file mode 100644 index 0000000..752cba9 --- /dev/null +++ b/test/.svn/text-base/TDHtmlSyntaxHighlighter.h.svn-base @@ -0,0 +1,54 @@ +// +// PKHtmlSyntaxHighlighter.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKTokenizer; +@class PKToken; + +@interface TDHtmlSyntaxHighlighter : NSObject { + BOOL isDarkBG; + BOOL inScript; + PKTokenizer *tokenizer; + NSMutableArray *stack; + PKToken *ltToken; + PKToken *gtToken; + PKToken *startCommentToken; + PKToken *endCommentToken; + PKToken *startCDATAToken; + PKToken *endCDATAToken; + PKToken *startPIToken; + PKToken *endPIToken; + PKToken *startDoctypeToken; + PKToken *fwdSlashToken; + PKToken *eqToken; + PKToken *scriptToken; + PKToken *endScriptToken; + + NSMutableAttributedString *highlightedString; + NSDictionary *tagAttributes; + NSDictionary *textAttributes; + NSDictionary *attrNameAttributes; + NSDictionary *attrValueAttributes; + NSDictionary *eqAttributes; + NSDictionary *commentAttributes; + NSDictionary *piAttributes; +} +- (id)initWithAttributesForDarkBackground:(BOOL)isDark; + +- (NSAttributedString *)attributedStringForString:(NSString *)s; + +@property (nonatomic, retain) NSMutableAttributedString *highlightedString; +@property (nonatomic, retain) NSDictionary *tagAttributes; +@property (nonatomic, retain) NSDictionary *textAttributes; +@property (nonatomic, retain) NSDictionary *attrNameAttributes; +@property (nonatomic, retain) NSDictionary *attrValueAttributes; +@property (nonatomic, retain) NSDictionary *eqAttributes; +@property (nonatomic, retain) NSDictionary *commentAttributes; +@property (nonatomic, retain) NSDictionary *piAttributes; +@end diff --git a/test/.svn/text-base/TDHtmlSyntaxHighlighter.m.svn-base b/test/.svn/text-base/TDHtmlSyntaxHighlighter.m.svn-base new file mode 100644 index 0000000..d2a4693 --- /dev/null +++ b/test/.svn/text-base/TDHtmlSyntaxHighlighter.m.svn-base @@ -0,0 +1,577 @@ +// +// PKHtmlSyntaxHighlighter.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/28/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDHtmlSyntaxHighlighter.h" +#import "NSArray+ParseKitAdditions.h" +#import + +@interface TDHtmlSyntaxHighlighter () +- (void)didMatchTag; +- (void)didMatchText; +- (void)didMatchComment; +- (void)didMatchCDATA; +- (void)didMatchPI; +- (void)didMatchDoctype; +- (void)didMatchScript; +- (id)peek; +- (id)pop; +- (NSArray *)objectsAbove:(id)fence; +- (PKToken *)nextNonWhitespaceTokenFrom:(NSEnumerator *)e; +- (void)consumeWhitespaceOnStack; + +@property (retain) PKTokenizer *tokenizer; +@property (retain) NSMutableArray *stack; +@property (retain) PKToken *ltToken; +@property (retain) PKToken *gtToken; +@property (retain) PKToken *startCommentToken; +@property (retain) PKToken *endCommentToken; +@property (retain) PKToken *startCDATAToken; +@property (retain) PKToken *endCDATAToken; +@property (retain) PKToken *startPIToken; +@property (retain) PKToken *endPIToken; +@property (retain) PKToken *startDoctypeToken; +@property (retain) PKToken *fwdSlashToken; +@property (retain) PKToken *eqToken; +@property (retain) PKToken *scriptToken; +@property (retain) PKToken *endScriptToken; +@end + +@implementation TDHtmlSyntaxHighlighter + +- (id)init { + return [self initWithAttributesForDarkBackground:NO]; +} + + +- (id)initWithAttributesForDarkBackground:(BOOL)isDark { + if (self = [super init]) { + isDarkBG = isDark; + self.tokenizer = [PKTokenizer tokenizer]; + + [tokenizer setTokenizerState:tokenizer.symbolState from:'/' to:'/']; // XML doesn't have slash slash or slash star comments + tokenizer.whitespaceState.reportsWhitespaceTokens = YES; + [tokenizer.wordState setWordChars:YES from:':' to:':']; + + self.ltToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"<" floatValue:0.0]; + self.gtToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@">" floatValue:0.0]; + + self.startCommentToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"" floatValue:0.0]; + [tokenizer.symbolState add:startCommentToken.stringValue]; + [tokenizer.symbolState add:endCommentToken.stringValue]; + + self.startCDATAToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"" floatValue:0.0]; + [tokenizer.symbolState add:startCDATAToken.stringValue]; + [tokenizer.symbolState add:endCDATAToken.stringValue]; + + self.startPIToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"" floatValue:0.0]; + [tokenizer.symbolState add:startPIToken.stringValue]; + [tokenizer.symbolState add:endPIToken.stringValue]; + + self.startDoctypeToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"" floatValue:0.0]; +// [tokenizer.symbolState add:endScriptToken.stringValue]; + + NSFont *monacoFont = [NSFont fontWithName:@"Monaco" size:11.]; + + NSColor *textColor = nil; + NSColor *tagColor = nil; + NSColor *attrNameColor = nil; + NSColor *attrValueColor = nil; + NSColor *eqColor = nil; + NSColor *commentColor = nil; + NSColor *piColor = nil; + + if (isDarkBG) { + textColor = [NSColor whiteColor]; + tagColor = [NSColor colorWithDeviceRed:.70 green:.14 blue:.53 alpha:1.]; + attrNameColor = [NSColor colorWithDeviceRed:.33 green:.45 blue:.48 alpha:1.]; + attrValueColor = [NSColor colorWithDeviceRed:.77 green:.18 blue:.20 alpha:1.]; + eqColor = tagColor; + commentColor = [NSColor colorWithDeviceRed:.24 green:.70 blue:.27 alpha:1.]; + piColor = [NSColor colorWithDeviceRed:.09 green:.62 blue:.74 alpha:1.]; + } else { + textColor = [NSColor blackColor]; + tagColor = [NSColor purpleColor]; + attrNameColor = [NSColor colorWithDeviceRed:0. green:0. blue:.75 alpha:1.]; + attrValueColor = [NSColor colorWithDeviceRed:.75 green:0. blue:0. alpha:1.]; + eqColor = [NSColor darkGrayColor]; + commentColor = [NSColor grayColor]; + piColor = [NSColor colorWithDeviceRed:.09 green:.62 blue:.74 alpha:1.]; + } + + self.textAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + textColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.tagAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + tagColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.attrNameAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + attrNameColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.attrValueAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + attrValueColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.eqAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + eqColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.commentAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + commentColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.piAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + piColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.stack = nil; + self.ltToken = nil; + self.gtToken = nil; + self.startCommentToken = nil; + self.endCommentToken = nil; + self.startCDATAToken = nil; + self.endCDATAToken = nil; + self.startPIToken = nil; + self.endPIToken = nil; + self.startDoctypeToken = nil; + self.fwdSlashToken = nil; + self.eqToken = nil; + self.scriptToken = nil; + self.endScriptToken = nil; + self.highlightedString = nil; + self.textAttributes = nil; + self.tagAttributes = nil; + self.attrNameAttributes = nil; + self.attrValueAttributes = nil; + self.eqAttributes = nil; + self.commentAttributes = nil; + self.piAttributes = nil; + [super dealloc]; +} + + +- (NSAttributedString *)attributedStringForString:(NSString *)s { + self.stack = [NSMutableArray array]; + self.highlightedString = [[[NSMutableAttributedString alloc] init] autorelease]; + + tokenizer.string = s; + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + BOOL inComment = NO; + BOOL inCDATA = NO; + BOOL inPI = NO; + BOOL inDoctype = NO; + + while ((tok = [tokenizer nextToken]) != eof) { + + if (!inComment && !inCDATA && !inPI && !inDoctype && !inScript && tok.isSymbol) { + if ([startCommentToken isEqual:tok]) { + [stack addObject:tok]; + inComment = YES; + } else if ([startCDATAToken isEqual:tok]) { + [stack addObject:tok]; + inCDATA = YES; + } else if ([startPIToken isEqual:tok]) { + [stack addObject:tok]; + inPI = YES; + } else if ([startDoctypeToken isEqual:tok]) { + [stack addObject:tok]; + inDoctype = YES; + } else if ([ltToken isEqual:tok]) { + [self didMatchText]; + [stack addObject:tok]; + } else if ([gtToken isEqual:tok]) { + [stack addObject:tok]; + [self didMatchTag]; + } else { + [stack addObject:tok]; + } + } else if (inComment && [endCommentToken isEqual:tok]) { + inComment = NO; + [stack addObject:tok]; + [self didMatchComment]; + } else if (inCDATA && [endCDATAToken isEqual:tok]) { + inCDATA = NO; + [stack addObject:tok]; + [self didMatchCDATA]; + } else if (inPI && [endPIToken isEqual:tok]) { + inPI = NO; + [stack addObject:tok]; + [self didMatchPI]; + } else if (inDoctype && [gtToken isEqual:tok]) { + inDoctype = NO; + [stack addObject:tok]; + [self didMatchDoctype]; + } else if (inScript && [endScriptToken isEqual:tok]) { + inScript = NO; + [stack addObject:tok]; + [self didMatchScript]; + } else { + [stack addObject:tok]; + } + } + + // handle case where no elements were encountered (plain text basically) + if (![highlightedString length]) { + PKToken *tok = nil; + while (tok = [self pop]) { + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:textAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + NSAttributedString *result = [[highlightedString copy] autorelease]; + self.stack = nil; + self.highlightedString = nil; + tokenizer.string = nil; + return result; +} + + +- (PKToken *)nextNonWhitespaceTokenFrom:(NSEnumerator *)e { + PKToken *tok = [e nextObject]; + while (tok.isWhitespace) { + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + tok = [e nextObject]; + } + return tok; +} + + +- (void)consumeWhitespaceOnStack { + PKToken *tok = [self peek]; + while (tok.isWhitespace) { + tok = [self pop]; + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + tok = [self peek]; + } +} + + +- (void)didMatchComment { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startCommentToken] reversedMutableArray]; + + [self consumeWhitespaceOnStack]; + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:startCommentToken.stringValue attributes:commentAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + NSEnumerator *e = [toks objectEnumerator]; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:endCommentToken]) { + break; + } else { + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:commentAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:commentAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchCDATA { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startCDATAToken] reversedMutableArray]; + + [self consumeWhitespaceOnStack]; + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:startCDATAToken.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + NSEnumerator *e = [toks objectEnumerator]; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:endCDATAToken]) { + break; + } else { + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:textAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchPI { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startPIToken] reversedMutableArray]; + + [self consumeWhitespaceOnStack]; + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:startPIToken.stringValue attributes:piAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + NSEnumerator *e = [toks objectEnumerator]; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:endPIToken]) { + break; + } else { + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:piAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:piAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchDoctype { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startDoctypeToken] reversedMutableArray]; + + [self consumeWhitespaceOnStack]; + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:startDoctypeToken.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + NSEnumerator *e = [toks objectEnumerator]; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:gtToken]) { + break; + } else { + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchScript { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startDoctypeToken] reversedMutableArray]; + + NSEnumerator *e = [toks objectEnumerator]; + NSAttributedString *as = nil; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:endScriptToken]) { + break; + } else { + NSDictionary *attrs = nil; + if ([tok isEqual:scriptToken] || [tok isEqual:ltToken] || [tok isEqual:fwdSlashToken]) { + attrs = tagAttributes; + } else { + attrs = textAttributes; + } + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:attrs] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:endScriptToken.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchStartTag:(NSEnumerator *)e { + while (1) { + // attr name or ns prefix decl "xmlns:foo" or "/" for empty element + PKToken *tok = [self nextNonWhitespaceTokenFrom:e]; + if (!tok) return; + + NSDictionary *attrs = nil; + if ([tok isEqual:eqToken]) { + attrs = eqAttributes; + } else if ([tok isEqual:fwdSlashToken] || [tok isEqual:gtToken]) { + attrs = tagAttributes; + } else if (tok.isQuotedString) { + attrs = attrValueAttributes; + } else { + attrs = attrNameAttributes; + } + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:attrs] autorelease]; + [highlightedString appendAttributedString:as]; + + // "=" + tok = [self nextNonWhitespaceTokenFrom:e]; + if (!tok) return; + + if ([tok isEqual:eqToken]) { + attrs = eqAttributes; + } else if ([tok isEqual:fwdSlashToken] || [tok isEqual:gtToken]) { + attrs = tagAttributes; + } else if (tok.isQuotedString) { + attrs = attrValueAttributes; + } else { + attrs = tagAttributes; + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:attrs] autorelease]; + [highlightedString appendAttributedString:as]; + + // quoted string attr value or ns url value + tok = [self nextNonWhitespaceTokenFrom:e]; + if (!tok) return; + + if ([tok isEqual:fwdSlashToken] || [tok isEqual:gtToken]) { + attrs = tagAttributes; + } else { + attrs = attrValueAttributes; + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:attrs] autorelease]; + [highlightedString appendAttributedString:as]; + } +} + + +- (void)didMatchEndTag:(NSEnumerator *)e { + // consume tagName to ">" + PKToken *tok = nil; + while (tok = [e nextObject]) { + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } +} + + +- (void)didMatchTag { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:nil] reversedMutableArray]; + NSAttributedString *as = nil; + + NSEnumerator *e = [toks objectEnumerator]; + + // append "<" + [self nextNonWhitespaceTokenFrom:e]; // discard + as = [[[NSAttributedString alloc] initWithString:ltToken.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + // consume whitespace to tagName or "/" for end tags or "!" for comments + PKToken *tok = [self nextNonWhitespaceTokenFrom:e]; + + if (tok) { + if ([tok isEqual:scriptToken]) { + inScript = YES; + } else { + inScript = NO; + } + + // consume tagName or "/" or "!" + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + if ([tok isEqual:fwdSlashToken]) { + [self didMatchEndTag:e]; + } else { + [self didMatchStartTag:e]; + } + } +} + + +- (void)didMatchText { + NSArray *a = [self objectsAbove:gtToken]; + for (PKToken *tok in [a reverseObjectEnumerator]) { + NSString *s = tok.stringValue; + if (s) { + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:textAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } +} + + +- (NSArray *)objectsAbove:(id)fence { + NSMutableArray *res = [NSMutableArray array]; + while (1) { + if (![stack count]) { + break; + } + id obj = [self pop]; + if ([obj isEqual:fence]) { + break; + } + [res addObject:obj]; + } + return res; +} + + +- (id)peek { + id obj = nil; + if ([stack count]) { + obj = [stack lastObject]; + } + return obj; +} + + +- (id)pop { + id obj = [self peek]; + if (obj) { + [stack removeLastObject]; + } + return obj; +} + +@synthesize stack; +@synthesize tokenizer; +@synthesize ltToken; +@synthesize gtToken; +@synthesize startCommentToken; +@synthesize endCommentToken; +@synthesize startCDATAToken; +@synthesize endCDATAToken; +@synthesize startPIToken; +@synthesize endPIToken; +@synthesize startDoctypeToken; +@synthesize fwdSlashToken; +@synthesize eqToken; +@synthesize scriptToken; +@synthesize endScriptToken; +@synthesize highlightedString; +@synthesize tagAttributes; +@synthesize textAttributes; +@synthesize attrNameAttributes; +@synthesize attrValueAttributes; +@synthesize eqAttributes; +@synthesize commentAttributes; +@synthesize piAttributes; +@end diff --git a/test/.svn/text-base/TDJavaScriptParser.h.svn-base b/test/.svn/text-base/TDJavaScriptParser.h.svn-base new file mode 100644 index 0000000..e71ef7d --- /dev/null +++ b/test/.svn/text-base/TDJavaScriptParser.h.svn-base @@ -0,0 +1,344 @@ +// +// PKJavaScriptParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 3/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDJavaScriptParser : PKRepetition { + PKCollectionParser *assignmentOpParser; + PKCollectionParser *relationalOpParser; + PKCollectionParser *equalityOpParser; + PKCollectionParser *shiftOpParser; + PKCollectionParser *incrementOpParser; + PKCollectionParser *unaryOpParser; + PKCollectionParser *multiplicativeOpParser; + + PKCollectionParser *programParser; + PKCollectionParser *elementParser; + PKCollectionParser *funcParser; + PKCollectionParser *paramListOptParser; + PKCollectionParser *paramListParser; + PKCollectionParser *commaIdentifierParser; + PKCollectionParser *compoundStmtParser; + PKCollectionParser *stmtsParser; + PKCollectionParser *stmtParser; + PKCollectionParser *ifStmtParser; + PKCollectionParser *ifElseStmtParser; + PKCollectionParser *whileStmtParser; + PKCollectionParser *forParenStmtParser; + PKCollectionParser *forBeginStmtParser; + PKCollectionParser *forInStmtParser; + PKCollectionParser *breakStmtParser; + PKCollectionParser *continueStmtParser; + PKCollectionParser *withStmtParser; + PKCollectionParser *returnStmtParser; + PKCollectionParser *variablesOrExprStmtParser; + PKCollectionParser *conditionParser; + PKCollectionParser *forParenParser; + PKCollectionParser *forBeginParser; + PKCollectionParser *variablesOrExprParser; + PKCollectionParser *varVariablesParser; + PKCollectionParser *variablesParser; + PKCollectionParser *commaVariableParser; + PKCollectionParser *variableParser; + PKCollectionParser *assignmentParser; + PKCollectionParser *exprOptParser; + PKCollectionParser *exprParser; + PKCollectionParser *commaAssignmentExprParser; + PKCollectionParser *assignmentExprParser; + PKCollectionParser *assignmentOpConditionalExprParser; + PKCollectionParser *conditionalExprParser; + PKCollectionParser *ternaryExprParser; + PKCollectionParser *orExprParser; + PKCollectionParser *orAndExprParser; + PKCollectionParser *andExprParser; + PKCollectionParser *andBitwiseOrExprParser; + PKCollectionParser *bitwiseOrExprParser; + PKCollectionParser *pipeBitwiseXorExprParser; + PKCollectionParser *bitwiseXorExprParser; + PKCollectionParser *caretBitwiseAndExprParser; + PKCollectionParser *bitwiseAndExprParser; + PKCollectionParser *ampEqualityExprParser; + PKCollectionParser *equalityExprParser; + PKCollectionParser *equalityOpRelationalExprParser; + PKCollectionParser *relationalExprParser; + PKCollectionParser *relationalOpShiftExprParser; + PKCollectionParser *shiftExprParser; + PKCollectionParser *shiftOpAdditiveExprParser; + PKCollectionParser *additiveExprParser; + PKCollectionParser *plusOrMinusExprParser; + PKCollectionParser *plusExprParser; + PKCollectionParser *minusExprParser; + PKCollectionParser *multiplicativeExprParser; + PKCollectionParser *multiplicativeOpUnaryExprParser; + PKCollectionParser *unaryExprParser; + PKCollectionParser *unaryExpr1Parser; + PKCollectionParser *unaryExpr2Parser; + PKCollectionParser *unaryExpr3Parser; + PKCollectionParser *unaryExpr4Parser; + PKCollectionParser *unaryExpr5Parser; + PKCollectionParser *unaryExpr6Parser; + PKCollectionParser *constructorCallParser; + PKCollectionParser *parenArgListOptParenParser; + PKCollectionParser *memberExprParser; + PKCollectionParser *memberExprExtParser; + PKCollectionParser *dotMemberExprParser; + PKCollectionParser *bracketMemberExprParser; + PKCollectionParser *argListOptParser; + PKCollectionParser *argListParser; + PKCollectionParser *primaryExprParser; + PKCollectionParser *parenExprParenParser; + + PKCollectionParser *funcLiteralParser; + PKCollectionParser *arrayLiteralParser; + PKCollectionParser *objectLiteralParser; + + PKParser *identifierParser; + PKParser *stringParser; + PKParser *numberParser; + + // keywords + PKParser *ifParser; + PKParser *elseParser; + PKParser *whileParser; + PKParser *forParser; + PKParser *inParser; + PKParser *breakParser; + PKParser *continueParser; + PKParser *withParser; + PKParser *returnParser; + PKParser *varParser; + PKParser *deleteParser; + PKParser *newParser; + PKParser *thisParser; + PKParser *falseParser; + PKParser *trueParser; + PKParser *nullParser; + PKParser *undefinedParser; + PKParser *voidParser; + PKParser *typeofParser; + PKParser *instanceofParser; + PKParser *functionParser; + + // multi-char symbols + PKParser *orParser; + PKParser *andParser; + PKParser *neParser; + PKParser *isNotParser; + PKParser *eqParser; + PKParser *isParser; + PKParser *leParser; + PKParser *geParser; + PKParser *plusPlusParser; + PKParser *minusMinusParser; + PKParser *plusEqParser; + PKParser *minusEqParser; + PKParser *timesEqParser; + PKParser *divEqParser; + PKParser *modEqParser; + PKParser *shiftLeftParser; + PKParser *shiftRightParser; + PKParser *shiftRightExtParser; + PKParser *shiftLeftEqParser; + PKParser *shiftRightEqParser; + PKParser *shiftRightExtEqParser; + PKParser *andEqParser; + PKParser *xorEqParser; + PKParser *orEqParser; + + // single char symbols + PKParser *openCurlyParser; + PKParser *closeCurlyParser; + PKParser *openParenParser; + PKParser *closeParenParser; + PKParser *openBracketParser; + PKParser *closeBracketParser; + PKParser *commaParser; + PKParser *dotParser; + PKParser *semiOptParser; + PKParser *semiParser; + PKParser *colonParser; + PKParser *equalsParser; + PKParser *notParser; + PKParser *ltParser; + PKParser *gtParser; + PKParser *ampParser; + PKParser *pipeParser; + PKParser *caretParser; + PKParser *tildeParser; + PKParser *questionParser; + PKParser *plusParser; + PKParser *minusParser; + PKParser *timesParser; + PKParser *divParser; + PKParser *modParser; +} +@property (nonatomic, retain) PKCollectionParser *assignmentOpParser; +@property (nonatomic, retain) PKCollectionParser *relationalOpParser; +@property (nonatomic, retain) PKCollectionParser *equalityOpParser; +@property (nonatomic, retain) PKCollectionParser *shiftOpParser; +@property (nonatomic, retain) PKCollectionParser *incrementOpParser; +@property (nonatomic, retain) PKCollectionParser *unaryOpParser; +@property (nonatomic, retain) PKCollectionParser *multiplicativeOpParser; + +@property (nonatomic, retain) PKCollectionParser *programParser; +@property (nonatomic, retain) PKCollectionParser *elementParser; +@property (nonatomic, retain) PKCollectionParser *funcParser; +@property (nonatomic, retain) PKCollectionParser *paramListOptParser; +@property (nonatomic, retain) PKCollectionParser *paramListParser; +@property (nonatomic, retain) PKCollectionParser *commaIdentifierParser; +@property (nonatomic, retain) PKCollectionParser *compoundStmtParser; +@property (nonatomic, retain) PKCollectionParser *stmtsParser; +@property (nonatomic, retain) PKCollectionParser *stmtParser; +@property (nonatomic, retain) PKCollectionParser *ifStmtParser; +@property (nonatomic, retain) PKCollectionParser *ifElseStmtParser; +@property (nonatomic, retain) PKCollectionParser *whileStmtParser; +@property (nonatomic, retain) PKCollectionParser *forParenStmtParser; +@property (nonatomic, retain) PKCollectionParser *forBeginStmtParser; +@property (nonatomic, retain) PKCollectionParser *forInStmtParser; +@property (nonatomic, retain) PKCollectionParser *breakStmtParser; +@property (nonatomic, retain) PKCollectionParser *continueStmtParser; +@property (nonatomic, retain) PKCollectionParser *withStmtParser; +@property (nonatomic, retain) PKCollectionParser *returnStmtParser; +@property (nonatomic, retain) PKCollectionParser *variablesOrExprStmtParser; +@property (nonatomic, retain) PKCollectionParser *conditionParser; +@property (nonatomic, retain) PKCollectionParser *forParenParser; +@property (nonatomic, retain) PKCollectionParser *forBeginParser; +@property (nonatomic, retain) PKCollectionParser *variablesOrExprParser; +@property (nonatomic, retain) PKCollectionParser *varVariablesParser; +@property (nonatomic, retain) PKCollectionParser *variablesParser; +@property (nonatomic, retain) PKCollectionParser *commaVariableParser; +@property (nonatomic, retain) PKCollectionParser *variableParser; +@property (nonatomic, retain) PKCollectionParser *assignmentParser; +@property (nonatomic, retain) PKCollectionParser *exprOptParser; +@property (nonatomic, retain) PKCollectionParser *exprParser; +@property (nonatomic, retain) PKCollectionParser *commaAssignmentExprParser; +@property (nonatomic, retain) PKCollectionParser *assignmentExprParser; +@property (nonatomic, retain) PKCollectionParser *assignmentOpConditionalExprParser; +@property (nonatomic, retain) PKCollectionParser *conditionalExprParser; +@property (nonatomic, retain) PKCollectionParser *ternaryExprParser; +@property (nonatomic, retain) PKCollectionParser *orExprParser; +@property (nonatomic, retain) PKCollectionParser *orAndExprParser; +@property (nonatomic, retain) PKCollectionParser *andExprParser; +@property (nonatomic, retain) PKCollectionParser *andBitwiseOrExprParser; +@property (nonatomic, retain) PKCollectionParser *bitwiseOrExprParser; +@property (nonatomic, retain) PKCollectionParser *pipeBitwiseXorExprParser; +@property (nonatomic, retain) PKCollectionParser *bitwiseXorExprParser; +@property (nonatomic, retain) PKCollectionParser *caretBitwiseAndExprParser; +@property (nonatomic, retain) PKCollectionParser *bitwiseAndExprParser; +@property (nonatomic, retain) PKCollectionParser *ampEqualityExprParser; +@property (nonatomic, retain) PKCollectionParser *equalityExprParser; +@property (nonatomic, retain) PKCollectionParser *equalityOpRelationalExprParser; +@property (nonatomic, retain) PKCollectionParser *relationalExprParser; +@property (nonatomic, retain) PKCollectionParser *relationalOpShiftExprParser; +@property (nonatomic, retain) PKCollectionParser *shiftExprParser; +@property (nonatomic, retain) PKCollectionParser *shiftOpAdditiveExprParser; +@property (nonatomic, retain) PKCollectionParser *additiveExprParser; +@property (nonatomic, retain) PKCollectionParser *plusOrMinusExprParser; +@property (nonatomic, retain) PKCollectionParser *plusExprParser; +@property (nonatomic, retain) PKCollectionParser *minusExprParser; +@property (nonatomic, retain) PKCollectionParser *multiplicativeExprParser; +@property (nonatomic, retain) PKCollectionParser *multiplicativeOpUnaryExprParser; +@property (nonatomic, retain) PKCollectionParser *unaryExprParser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr1Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr2Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr3Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr4Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr5Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr6Parser; +@property (nonatomic, retain) PKCollectionParser *constructorCallParser; +@property (nonatomic, retain) PKCollectionParser *parenArgListOptParenParser; +@property (nonatomic, retain) PKCollectionParser *memberExprParser; +@property (nonatomic, retain) PKCollectionParser *memberExprExtParser; +@property (nonatomic, retain) PKCollectionParser *dotMemberExprParser; +@property (nonatomic, retain) PKCollectionParser *bracketMemberExprParser; +@property (nonatomic, retain) PKCollectionParser *argListOptParser; +@property (nonatomic, retain) PKCollectionParser *argListParser; +@property (nonatomic, retain) PKCollectionParser *primaryExprParser; +@property (nonatomic, retain) PKCollectionParser *parenExprParenParser; + +@property (nonatomic, retain) PKCollectionParser *funcLiteralParser; +@property (nonatomic, retain) PKCollectionParser *arrayLiteralParser; +@property (nonatomic, retain) PKCollectionParser *objectLiteralParser; + +@property (nonatomic, retain) PKParser *identifierParser; +@property (nonatomic, retain) PKParser *stringParser; +@property (nonatomic, retain) PKParser *numberParser; + +@property (nonatomic, retain) PKParser *ifParser; +@property (nonatomic, retain) PKParser *elseParser; +@property (nonatomic, retain) PKParser *whileParser; +@property (nonatomic, retain) PKParser *forParser; +@property (nonatomic, retain) PKParser *inParser; +@property (nonatomic, retain) PKParser *breakParser; +@property (nonatomic, retain) PKParser *continueParser; +@property (nonatomic, retain) PKParser *withParser; +@property (nonatomic, retain) PKParser *returnParser; +@property (nonatomic, retain) PKParser *varParser; +@property (nonatomic, retain) PKParser *deleteParser; +@property (nonatomic, retain) PKParser *newParser; +@property (nonatomic, retain) PKParser *thisParser; +@property (nonatomic, retain) PKParser *falseParser; +@property (nonatomic, retain) PKParser *trueParser; +@property (nonatomic, retain) PKParser *nullParser; +@property (nonatomic, retain) PKParser *undefinedParser; +@property (nonatomic, retain) PKParser *voidParser; +@property (nonatomic, retain) PKParser *typeofParser; +@property (nonatomic, retain) PKParser *instanceofParser; +@property (nonatomic, retain) PKParser *functionParser; + +@property (nonatomic, retain) PKParser *orParser; +@property (nonatomic, retain) PKParser *andParser; +@property (nonatomic, retain) PKParser *neParser; +@property (nonatomic, retain) PKParser *isNotParser; +@property (nonatomic, retain) PKParser *eqParser; +@property (nonatomic, retain) PKParser *isParser; +@property (nonatomic, retain) PKParser *leParser; +@property (nonatomic, retain) PKParser *geParser; +@property (nonatomic, retain) PKParser *plusPlusParser; +@property (nonatomic, retain) PKParser *minusMinusParser; +@property (nonatomic, retain) PKParser *plusEqParser; +@property (nonatomic, retain) PKParser *minusEqParser; +@property (nonatomic, retain) PKParser *timesEqParser; +@property (nonatomic, retain) PKParser *divEqParser; +@property (nonatomic, retain) PKParser *modEqParser; +@property (nonatomic, retain) PKParser *shiftLeftParser; +@property (nonatomic, retain) PKParser *shiftRightParser; +@property (nonatomic, retain) PKParser *shiftRightExtParser; +@property (nonatomic, retain) PKParser *shiftLeftEqParser; +@property (nonatomic, retain) PKParser *shiftRightEqParser; +@property (nonatomic, retain) PKParser *shiftRightExtEqParser; +@property (nonatomic, retain) PKParser *andEqParser; +@property (nonatomic, retain) PKParser *xorEqParser; +@property (nonatomic, retain) PKParser *orEqParser; + +@property (nonatomic, retain) PKParser *openCurlyParser; +@property (nonatomic, retain) PKParser *closeCurlyParser; +@property (nonatomic, retain) PKParser *openParenParser; +@property (nonatomic, retain) PKParser *closeParenParser; +@property (nonatomic, retain) PKParser *openBracketParser; +@property (nonatomic, retain) PKParser *closeBracketParser; +@property (nonatomic, retain) PKParser *commaParser; +@property (nonatomic, retain) PKParser *dotParser; +@property (nonatomic, retain) PKParser *semiOptParser; +@property (nonatomic, retain) PKParser *semiParser; +@property (nonatomic, retain) PKParser *colonParser; +@property (nonatomic, retain) PKParser *equalsParser; +@property (nonatomic, retain) PKParser *notParser; +@property (nonatomic, retain) PKParser *ltParser; +@property (nonatomic, retain) PKParser *gtParser; +@property (nonatomic, retain) PKParser *ampParser; +@property (nonatomic, retain) PKParser *pipeParser; +@property (nonatomic, retain) PKParser *caretParser; +@property (nonatomic, retain) PKParser *tildeParser; +@property (nonatomic, retain) PKParser *questionParser; +@property (nonatomic, retain) PKParser *plusParser; +@property (nonatomic, retain) PKParser *minusParser; +@property (nonatomic, retain) PKParser *timesParser; +@property (nonatomic, retain) PKParser *divParser; +@property (nonatomic, retain) PKParser *modParser; +@end diff --git a/test/.svn/text-base/TDJavaScriptParser.m.svn-base b/test/.svn/text-base/TDJavaScriptParser.m.svn-base new file mode 100644 index 0000000..f474f8b --- /dev/null +++ b/test/.svn/text-base/TDJavaScriptParser.m.svn-base @@ -0,0 +1,2392 @@ +// +// PKJavaScriptParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 3/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDJavaScriptParser.h" + +@interface PKParser () +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface TDJavaScriptParser () +- (PKAlternation *)zeroOrOne:(PKParser *)p; +- (PKSequence *)oneOrMore:(PKParser *)p; +@end + +@implementation TDJavaScriptParser + +- (id)init { + if (self = [super initWithSubparser:self.elementParser]) { + self.tokenizer = [PKTokenizer tokenizer]; + + // JS supports scientific number notation (exponents like 4E+12 or 2.0e-42) + tokenizer.numberState.allowsScientificNotation = YES; + + // Nums cannot end with '.' (e.g. 32. must be 32.0) + tokenizer.numberState.allowsTrailingDot = NO; + + [tokenizer setTokenizerState:tokenizer.numberState from:'-' to:'-']; + [tokenizer setTokenizerState:tokenizer.numberState from:'.' to:'.']; + [tokenizer setTokenizerState:tokenizer.numberState from:'0' to:'9']; + + // Words can start with '_' + [tokenizer setTokenizerState:tokenizer.wordState from:'_' to:'_']; + + // Words cannot contain '-' + [tokenizer.wordState setWordChars:NO from:'-' to:'-']; + + // Comments + tokenizer.commentState.reportsCommentTokens = YES; + [tokenizer setTokenizerState:tokenizer.commentState from:'/' to:'/']; + + // single-line Comments + [tokenizer.commentState addSingleLineStartMarker:@"//"]; + + // multi-line Comments + [tokenizer.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + [tokenizer.symbolState add:@"||"]; + [tokenizer.symbolState add:@"&&"]; + [tokenizer.symbolState add:@"!="]; + [tokenizer.symbolState add:@"!=="]; + [tokenizer.symbolState add:@"=="]; + [tokenizer.symbolState add:@"==="]; + [tokenizer.symbolState add:@"<="]; + [tokenizer.symbolState add:@">="]; + [tokenizer.symbolState add:@"++"]; + [tokenizer.symbolState add:@"--"]; + [tokenizer.symbolState add:@"+="]; + [tokenizer.symbolState add:@"-="]; + [tokenizer.symbolState add:@"*="]; + [tokenizer.symbolState add:@"/="]; + [tokenizer.symbolState add:@"%="]; + [tokenizer.symbolState add:@"<<"]; + [tokenizer.symbolState add:@">>"]; + [tokenizer.symbolState add:@">>>"]; + [tokenizer.symbolState add:@"<<="]; + [tokenizer.symbolState add:@">>="]; + [tokenizer.symbolState add:@">>>="]; + [tokenizer.symbolState add:@"&="]; + [tokenizer.symbolState add:@"^="]; + } + return self; +} + + +- (void)dealloc { + self.assignmentOpParser = nil; + self.relationalOpParser = nil; + self.equalityOpParser = nil; + self.shiftOpParser = nil; + self.incrementOpParser = nil; + self.unaryOpParser = nil; + self.multiplicativeOpParser = nil; + self.programParser = nil; + self.elementParser = nil; + self.funcParser = nil; + self.paramListOptParser = nil; + self.paramListParser = nil; + self.commaIdentifierParser = nil; + self.compoundStmtParser = nil; + self.stmtsParser = nil; + self.stmtParser = nil; + self.ifStmtParser = nil; + self.ifElseStmtParser = nil; + self.whileStmtParser = nil; + self.forParenStmtParser = nil; + self.forBeginStmtParser = nil; + self.forInStmtParser = nil; + self.breakStmtParser = nil; + self.continueStmtParser = nil; + self.withStmtParser = nil; + self.returnStmtParser = nil; + self.variablesOrExprStmtParser = nil; + self.conditionParser = nil; + self.forParenParser = nil; + self.forBeginParser = nil; + self.variablesOrExprParser = nil; + self.varVariablesParser = nil; + self.variablesParser = nil; + self.commaVariableParser = nil; + self.variableParser = nil; + self.assignmentParser = nil; + self.exprOptParser = nil; + self.exprParser = nil; + self.commaAssignmentExprParser = nil; + self.assignmentExprParser = nil; + self.assignmentOpConditionalExprParser = nil; + self.conditionalExprParser = nil; + self.ternaryExprParser = nil; + self.orExprParser = nil; + self.orAndExprParser = nil; + self.andExprParser = nil; + self.andBitwiseOrExprParser = nil; + self.bitwiseOrExprParser = nil; + self.pipeBitwiseXorExprParser = nil; + self.bitwiseXorExprParser = nil; + self.caretBitwiseAndExprParser = nil; + self.bitwiseAndExprParser = nil; + self.ampEqualityExprParser = nil; + self.equalityExprParser = nil; + self.equalityOpRelationalExprParser = nil; + self.relationalExprParser = nil; + self.relationalOpShiftExprParser = nil; + self.shiftExprParser = nil; + self.shiftOpAdditiveExprParser = nil; + self.additiveExprParser = nil; + self.plusOrMinusExprParser = nil; + self.plusExprParser = nil; + self.minusExprParser = nil; + self.multiplicativeExprParser = nil; + self.multiplicativeOpUnaryExprParser = nil; + self.unaryExprParser = nil; + self.unaryExpr1Parser = nil; + self.unaryExpr2Parser = nil; + self.unaryExpr3Parser = nil; + self.unaryExpr4Parser = nil; + self.unaryExpr5Parser = nil; + self.unaryExpr6Parser = nil; + self.constructorCallParser = nil; + self.parenArgListOptParenParser = nil; + self.memberExprParser = nil; + self.memberExprExtParser = nil; + self.dotMemberExprParser = nil; + self.bracketMemberExprParser = nil; + self.argListOptParser = nil; + self.argListParser = nil; + self.primaryExprParser = nil; + self.parenExprParenParser = nil; + + self.funcLiteralParser = nil; + self.arrayLiteralParser = nil; + self.objectLiteralParser = nil; + + self.identifierParser = nil; + self.stringParser = nil; + self.numberParser = nil; + + self.ifParser = nil; + self.elseParser = nil; + self.whileParser = nil; + self.forParser = nil; + self.inParser = nil; + self.breakParser = nil; + self.continueParser = nil; + self.withParser = nil; + self.returnParser = nil; + self.varParser = nil; + self.deleteParser = nil; + self.newParser = nil; + self.thisParser = nil; + self.falseParser = nil; + self.trueParser = nil; + self.nullParser = nil; + self.undefinedParser = nil; + self.voidParser = nil; + self.typeofParser = nil; + self.instanceofParser = nil; + self.functionParser = nil; + + self.orParser = nil; + self.andParser = nil; + self.neParser = nil; + self.isNotParser = nil; + self.eqParser = nil; + self.isParser = nil; + self.leParser = nil; + self.geParser = nil; + self.plusPlusParser = nil; + self.minusMinusParser = nil; + self.plusEqParser = nil; + self.minusEqParser = nil; + self.timesEqParser = nil; + self.divEqParser = nil; + self.modEqParser = nil; + self.shiftLeftParser = nil; + self.shiftRightParser = nil; + self.shiftRightExtParser = nil; + self.shiftLeftEqParser = nil; + self.shiftRightEqParser = nil; + self.shiftRightExtEqParser = nil; + self.andEqParser = nil; + self.xorEqParser = nil; + self.orEqParser = nil; + + self.openCurlyParser = nil; + self.closeCurlyParser = nil; + self.openParenParser = nil; + self.closeParenParser = nil; + self.openBracketParser = nil; + self.closeBracketParser = nil; + self.commaParser = nil; + self.dotParser = nil; + self.semiOptParser = nil; + self.semiParser = nil; + self.colonParser = nil; + self.equalsParser = nil; + self.notParser = nil; + self.ltParser = nil; + self.gtParser = nil; + self.ampParser = nil; + self.pipeParser = nil; + self.caretParser = nil; + self.tildeParser = nil; + self.questionParser = nil; + self.plusParser = nil; + self.minusParser = nil; + self.timesParser = nil; + self.divParser = nil; + self.modParser = nil; + + [super dealloc]; +} + + +- (PKAlternation *)zeroOrOne:(PKParser *)p { + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:p]; + return a; +} + + +- (PKSequence *)oneOrMore:(PKParser *)p { + PKSequence *s = [PKSequence sequence]; + [s add:p]; + [s add:[PKRepetition repetitionWithSubparser:p]]; + return s; +} + + +// assignmentOperator = equals | plusEq | minusEq | timesEq | divEq | modEq | shiftLeftEq | shiftRightEq | shiftRightExtEq | andEq | xorEq | orEq; +- (PKCollectionParser *)assignmentOpParser { + if (!assignmentOpParser) { + self.assignmentOpParser = [PKAlternation alternation]; + assignmentOpParser.name = @"assignmentOp"; + [assignmentOpParser add:self.equalsParser]; + [assignmentOpParser add:self.plusEqParser]; + [assignmentOpParser add:self.minusEqParser]; + [assignmentOpParser add:self.timesEqParser]; + [assignmentOpParser add:self.divEqParser]; + [assignmentOpParser add:self.modEqParser]; + [assignmentOpParser add:self.shiftLeftEqParser]; + [assignmentOpParser add:self.shiftRightEqParser]; + [assignmentOpParser add:self.shiftRightExtEqParser]; + [assignmentOpParser add:self.andEqParser]; + [assignmentOpParser add:self.orEqParser]; + [assignmentOpParser add:self.xorEqParser]; + } + return assignmentOpParser; +} + + +// relationalOperator = lt | gt | ge | le | instanceof; +- (PKCollectionParser *)relationalOpParser { + if (!relationalOpParser) { + self.relationalOpParser = [PKAlternation alternation]; + relationalOpParser.name = @"relationalOp"; + [relationalOpParser add:self.ltParser]; + [relationalOpParser add:self.gtParser]; + [relationalOpParser add:self.geParser]; + [relationalOpParser add:self.leParser]; + [relationalOpParser add:self.instanceofParser]; + } + return relationalOpParser; +} + + +// equalityOp = eq | ne | is | isnot; +- (PKCollectionParser *)equalityOpParser { + if (!equalityOpParser) { + self.equalityOpParser = [PKAlternation alternation];; + equalityOpParser.name = @"equalityOp"; + [equalityOpParser add:self.eqParser]; + [equalityOpParser add:self.neParser]; + [equalityOpParser add:self.isParser]; + [equalityOpParser add:self.isNotParser]; + } + return equalityOpParser; +} + + +//shiftOp = shiftLeft | shiftRight | shiftRightExt; +- (PKCollectionParser *)shiftOpParser { + if (!shiftOpParser) { + self.shiftOpParser = [PKAlternation alternation]; + shiftOpParser.name = @"shiftOp"; + [shiftOpParser add:self.shiftLeftParser]; + [shiftOpParser add:self.shiftRightParser]; + [shiftOpParser add:self.shiftRightExtParser]; + } + return shiftOpParser; +} + + +//incrementOperator = plusPlus | minusMinus; +- (PKCollectionParser *)incrementOpParser { + if (!incrementOpParser) { + self.incrementOpParser = [PKAlternation alternation]; + incrementOpParser.name = @"incrementOp"; + [incrementOpParser add:self.plusPlusParser]; + [incrementOpParser add:self.minusMinusParser]; + } + return incrementOpParser; +} + + +//unaryOperator = tilde | delete | typeof | void; +- (PKCollectionParser *)unaryOpParser { + if (!unaryOpParser) { + self.unaryOpParser = [PKAlternation alternation]; + unaryOpParser.name = @"unaryOp"; + [unaryOpParser add:self.tildeParser]; + [unaryOpParser add:self.deleteParser]; + [unaryOpParser add:self.typeofParser]; + [unaryOpParser add:self.voidParser]; + } + return unaryOpParser; +} + + +// multiplicativeOperator = times | div | mod; +- (PKCollectionParser *)multiplicativeOpParser { + if (!multiplicativeOpParser) { + self.multiplicativeOpParser = [PKAlternation alternation]; + multiplicativeOpParser.name = @"multiplicativeOperator"; + [multiplicativeOpParser add:self.timesParser]; + [multiplicativeOpParser add:self.divParser]; + [multiplicativeOpParser add:self.modParser]; + } + return multiplicativeOpParser; +} + + + +// Program: +// empty +// Element Program +// +//program = element*; +- (PKCollectionParser *)programParser { + if (!programParser) { + self.programParser = [PKRepetition repetitionWithSubparser:self.elementParser]; + programParser.name = @"program"; + } + return programParser; +} + + +// Element: +// function Identifier ( ParameterListOpt ) CompoundStatement +// Statement +// +//element = func | stmt; +- (PKCollectionParser *)elementParser { + if (!elementParser) { + self.elementParser = [PKAlternation alternation]; + elementParser.name = @"element"; + [elementParser add:self.funcParser]; + [elementParser add:self.stmtParser]; + } + return elementParser; +} + + +//func = function identifier openParen paramListOpt closeParen compoundStmt; +- (PKCollectionParser *)funcParser { + if (!funcParser) { + self.funcParser = [PKSequence sequence]; + funcParser.name = @"func"; + [funcParser add:self.functionParser]; + [funcParser add:self.identifierParser]; + [funcParser add:self.openParenParser]; + [funcParser add:self.paramListOptParser]; + [funcParser add:self.closeParenParser]; + [funcParser add:self.compoundStmtParser]; + } + return funcParser; +} + + +// ParameterListOpt: +// empty +// ParameterList +// +//paramListOpt = Empty | paramList; +- (PKCollectionParser *)paramListOptParser { + if (!paramListOptParser) { + self.paramListOptParser = [PKAlternation alternation]; + paramListOptParser.name = @"paramListOpt"; + [paramListOptParser add:[self zeroOrOne:self.paramListParser]]; + } + return paramListOptParser; +} + + +// ParameterList: +// Identifier +// Identifier , ParameterList +// +//paramList = identifier commaIdentifier*; +- (PKCollectionParser *)paramListParser { + if (!paramListParser) { + self.paramListParser = [PKSequence sequence]; + paramListParser.name = @"paramList"; + [paramListParser add:self.identifierParser]; + [paramListParser add:[PKRepetition repetitionWithSubparser:self.commaIdentifierParser]]; + } + return paramListParser; +} + + +//commaIdentifier = comma identifier; +- (PKCollectionParser *)commaIdentifierParser { + if (!commaIdentifierParser) { + self.commaIdentifierParser = [PKSequence sequence]; + commaIdentifierParser.name = @"commaIdentifier"; + [commaIdentifierParser add:self.commaParser]; + [commaIdentifierParser add:self.identifierParser]; + } + return commaIdentifierParser; +} + + +// CompoundStatement: +// { Statements } +// +//compoundStmt = openCurly stmts closeCurly; +- (PKCollectionParser *)compoundStmtParser { + if (!compoundStmtParser) { + self.compoundStmtParser = [PKSequence sequence]; + compoundStmtParser.name = @"compoundStmt"; + [compoundStmtParser add:self.openCurlyParser]; + [compoundStmtParser add:self.stmtsParser]; + [compoundStmtParser add:self.closeCurlyParser]; + } + return compoundStmtParser; +} + + +// Statements: +// empty +// Statement Statements +// +//stmts = stmt*; +- (PKCollectionParser *)stmtsParser { + if (!stmtsParser) { + self.stmtsParser = [PKRepetition repetitionWithSubparser:self.stmtParser]; + stmtsParser.name = @"stmts"; + } + return stmtsParser; +} + + +// Statement: +// ; +// if Condition Statement +// if Condition Statement else Statement +// while Condition Statement +// ForParen ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin in Expression ) Statement +// break ; +// continue ; +// with ( Expression ) Statement +// return ExpressionOpt ; +// CompoundStatement +// VariablesOrExpression ; +// +//stmt = semi | ifStmt | ifElseStmt | whileStmt | forParenStmt | forBeginStmt | forInStmt | breakStmt | continueStmt | withStmt | returnStmt | compoundStmt | variablesOrExprStmt; +- (PKCollectionParser *)stmtParser { + if (!stmtParser) { + self.stmtParser = [PKAlternation alternation]; + stmtParser.name = @"stmt"; + [stmtParser add:self.semiParser]; + [stmtParser add:self.ifStmtParser]; + [stmtParser add:self.ifElseStmtParser]; + [stmtParser add:self.whileStmtParser]; + [stmtParser add:self.forParenStmtParser]; + [stmtParser add:self.forBeginStmtParser]; + [stmtParser add:self.forInStmtParser]; + [stmtParser add:self.breakStmtParser]; + [stmtParser add:self.continueStmtParser]; + [stmtParser add:self.withStmtParser]; + [stmtParser add:self.returnStmtParser]; + [stmtParser add:self.compoundStmtParser]; + [stmtParser add:self.variablesOrExprStmtParser]; + } + return stmtParser; +} + + +// if Condition Statement +//ifStmt = if condition stmt; +- (PKCollectionParser *)ifStmtParser { + if (!ifStmtParser) { + self.ifStmtParser = [PKSequence sequence]; + ifStmtParser.name = @"ifStmt"; + [ifStmtParser add:self.ifParser]; + [ifStmtParser add:self.conditionParser]; + [ifStmtParser add:self.stmtParser]; + } + return ifStmtParser; +} + + +// if Condition Statement else Statement +//ifElseStmt = if condition stmt else stmt; +- (PKCollectionParser *)ifElseStmtParser { + if (!ifElseStmtParser) { + self.ifElseStmtParser = [PKSequence sequence]; + ifElseStmtParser.name = @"ifElseStmt"; + [ifElseStmtParser add:self.ifParser]; + [ifElseStmtParser add:self.conditionParser]; + [ifElseStmtParser add:self.stmtParser]; + [ifElseStmtParser add:self.elseParser]; + [ifElseStmtParser add:self.stmtParser]; + } + return ifElseStmtParser; +} + + +// while Condition Statement +//whileStmt = while condition stmt; +- (PKCollectionParser *)whileStmtParser { + if (!whileStmtParser) { + self.whileStmtParser = [PKSequence sequence]; + whileStmtParser.name = @"whileStmt"; + [whileStmtParser add:self.whileParser]; + [whileStmtParser add:self.conditionParser]; + [whileStmtParser add:self.stmtParser]; + } + return whileStmtParser; +} + + +// ForParen ; ExpressionOpt ; ExpressionOpt ) Statement +//forParenStmt = forParen semi exprOpt semi exprOpt closeParen stmt; +- (PKCollectionParser *)forParenStmtParser { + if (!forParenStmtParser) { + self.forParenStmtParser = [PKSequence sequence]; + forParenStmtParser.name = @"forParenStmt"; + [forParenStmtParser add:self.forParenParser]; + [forParenStmtParser add:self.semiParser]; + [forParenStmtParser add:self.exprOptParser]; + [forParenStmtParser add:self.semiParser]; + [forParenStmtParser add:self.exprOptParser]; + [forParenStmtParser add:self.closeParenParser]; + [forParenStmtParser add:self.stmtParser]; + } + return forParenStmtParser; +} + + +// ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement +//forBeginStmt = forBegin semi exprOpt semi exprOpt closeParen stmt; +- (PKCollectionParser *)forBeginStmtParser { + if (!forBeginStmtParser) { + self.forBeginStmtParser = [PKSequence sequence]; + forBeginStmtParser.name = @"forBeginStmt"; + [forBeginStmtParser add:self.forBeginParser]; + [forBeginStmtParser add:self.semiParser]; + [forBeginStmtParser add:self.exprOptParser]; + [forBeginStmtParser add:self.semiParser]; + [forBeginStmtParser add:self.exprOptParser]; + [forBeginStmtParser add:self.closeParenParser]; + [forBeginStmtParser add:self.stmtParser]; + } + return forBeginStmtParser; +} + + +// ForBegin in Expression ) Statement +//forInStmt = forBegin in expr closeParen stmt; +- (PKCollectionParser *)forInStmtParser { + if (!forInStmtParser) { + self.forInStmtParser = [PKSequence sequence]; + forInStmtParser.name = @"forInStmt"; + [forInStmtParser add:self.forBeginParser]; + [forInStmtParser add:self.inParser]; + [forInStmtParser add:self.exprParser]; + [forInStmtParser add:self.closeParenParser]; + [forInStmtParser add:self.stmtParser]; + } + return forInStmtParser; +} + + +// break ; +//breakStmt = break semi; +- (PKCollectionParser *)breakStmtParser { + if (!breakStmtParser) { + self.breakStmtParser = [PKSequence sequence]; + breakStmtParser.name = @"breakStmt"; + [breakStmtParser add:self.breakParser]; + [breakStmtParser add:self.semiOptParser]; + } + return breakStmtParser; +} + + +//continueStmt = continue semi; +- (PKCollectionParser *)continueStmtParser { + if (!continueStmtParser) { + self.continueStmtParser = [PKSequence sequence]; + continueStmtParser.name = @"continueStmt"; + [continueStmtParser add:self.continueParser]; + [continueStmtParser add:self.semiOptParser]; + } + return continueStmtParser; +} + + +// with ( Expression ) Statement +//withStmt = with openParen expr closeParen stmt; +- (PKCollectionParser *)withStmtParser { + if (!withStmtParser) { + self.withStmtParser = [PKSequence sequence]; + withStmtParser.name = @"withStmt"; + [withStmtParser add:self.withParser]; + [withStmtParser add:self.openParenParser]; + [withStmtParser add:self.exprParser]; + [withStmtParser add:self.closeParenParser]; + [withStmtParser add:self.stmtParser]; + } + return withStmtParser; +} + + +// return ExpressionOpt ; +//returnStmt = return exprOpt semi; +- (PKCollectionParser *)returnStmtParser { + if (!returnStmtParser) { + self.returnStmtParser = [PKSequence sequence]; + returnStmtParser.name = @"returnStmt"; + [returnStmtParser add:self.returnParser]; + [returnStmtParser add:self.exprOptParser]; + [returnStmtParser add:self.semiOptParser]; + } + return returnStmtParser; +} + + +// VariablesOrExpression ; +//variablesOrExprStmt = variablesOrExpr semi; +- (PKCollectionParser *)variablesOrExprStmtParser { + if (!variablesOrExprStmtParser) { + self.variablesOrExprStmtParser = [PKSequence sequence]; + variablesOrExprStmtParser.name = @"variablesOrExprStmt"; + [variablesOrExprStmtParser add:self.variablesOrExprParser]; + [variablesOrExprStmtParser add:self.semiOptParser]; + } + return variablesOrExprStmtParser; +} + + +// Condition: +// ( Expression ) +// +//condition = openParen expr closeParen; +- (PKCollectionParser *)conditionParser { + if (!conditionParser) { + self.conditionParser = [PKSequence sequence]; + conditionParser.name = @"condition"; + [conditionParser add:self.openParenParser]; + [conditionParser add:self.exprParser]; + [conditionParser add:self.closeParenParser]; + } + return conditionParser; +} + + +// ForParen: +// for ( +// +//forParen = for openParen; +- (PKCollectionParser *)forParenParser { + if (!forParenParser) { + self.forParenParser = [PKSequence sequence]; + forParenParser.name = @"forParen"; + [forParenParser add:self.forParser]; + [forParenParser add:self.openParenParser]; + } + return forParenParser; +} + + +// ForBegin: +// ForParen VariablesOrExpression +// +//forBegin = forParen variablesOrExpr; +- (PKCollectionParser *)forBeginParser { + if (!forBeginParser) { + self.forBeginParser = [PKSequence sequence]; + forBeginParser.name = @"forBegin"; + [forBeginParser add:self.forParenParser]; + [forBeginParser add:self.variablesOrExprParser]; + } + return forBeginParser; +} + + +// VariablesOrExpression: +// var Variables +// Expression +// +//variablesOrExpr = varVariables | expr; +- (PKCollectionParser *)variablesOrExprParser { + if (!variablesOrExprParser) { + self.variablesOrExprParser = [PKAlternation alternation]; + variablesOrExprParser.name = @"variablesOrExpr"; + [variablesOrExprParser add:self.varVariablesParser]; + [variablesOrExprParser add:self.exprParser]; + } + return variablesOrExprParser; +} + + +//varVariables = var variables; +- (PKCollectionParser *)varVariablesParser { + if (!varVariablesParser) { + self.varVariablesParser = [PKSequence sequence]; + varVariablesParser.name = @"varVariables"; + [varVariablesParser add:self.varParser]; + [varVariablesParser add:self.variablesParser]; + } + return varVariablesParser; +} + + +// Variables: +// Variable +// Variable , Variables +// +//variables = variable commaVariable*; +- (PKCollectionParser *)variablesParser { + if (!variablesParser) { + self.variablesParser = [PKSequence sequence]; + variablesParser.name = @"variables"; + [variablesParser add:self.variableParser]; + [variablesParser add:[PKRepetition repetitionWithSubparser:self.commaVariableParser]]; + } + return variablesParser; +} + + +//commaVariable = comma variable; +- (PKCollectionParser *)commaVariableParser { + if (!commaVariableParser) { + self.commaVariableParser = [PKSequence sequence]; + commaVariableParser.name = @"commaVariable"; + [commaVariableParser add:self.commaParser]; + [commaVariableParser add:self.variableParser]; + } + return commaVariableParser; +} + + +// Variable: +// Identifier +// Identifier = AssignmentExpression +// +//variable = identifier assignment?; +- (PKCollectionParser *)variableParser { + if (!variableParser) { + self.variableParser = [PKSequence sequence]; + variableParser.name = @"variableParser"; + [variableParser add:self.identifierParser]; + [variableParser add:[self zeroOrOne:self.assignmentParser]]; + } + return variableParser; +} + + +//assignment = equals assignmentExpr; +- (PKCollectionParser *)assignmentParser { + if (!assignmentParser) { + self.assignmentParser = [PKSequence sequence]; + assignmentParser.name = @"assignment"; + [assignmentParser add:self.equalsParser]; + [assignmentParser add:self.assignmentExprParser]; + } + return assignmentParser; +} + + +// ExpressionOpt: +// empty +// Expression +// +// exprOpt = Empty | expr; +- (PKCollectionParser *)exprOptParser { + if (!exprOptParser) { + self.exprOptParser = [self zeroOrOne:self.exprParser]; + exprOptParser.name = @"exprOpt"; + } + return exprOptParser; +} + + +// Expression: +// AssignmentExpression +// AssignmentExpression , Expression +// +//expr = assignmentExpr commaAssignmentExpr*; +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + exprParser.name = @"exprParser"; + [exprParser add:self.assignmentExprParser]; + [exprParser add:[PKRepetition repetitionWithSubparser:self.commaAssignmentExprParser]]; + } + return exprParser; +} + + +//commaAssignmentExpr = comma assignmentExpr; +- (PKCollectionParser *)commaAssignmentExprParser { + if (!commaAssignmentExprParser) { + self.commaAssignmentExprParser = [PKSequence sequence]; + commaAssignmentExprParser.name = @"commaAssignmentExpr"; + [commaAssignmentExprParser add:self.commaParser]; + [commaAssignmentExprParser add:self.assignmentExprParser]; + } + return commaAssignmentExprParser; +} + + +// AssignmentExpression: +// ConditionalExpression +// ConditionalExpression AssignmentOperator AssignmentExpression +// +// assignmentExpr = conditionalExpr assignmentOpConditionalExpr*; +- (PKCollectionParser *)assignmentExprParser { + if (!assignmentExprParser) { + self.assignmentExprParser = [PKSequence sequence]; + assignmentExprParser.name = @"assignmentExpr"; + [assignmentExprParser add:self.conditionalExprParser]; + [assignmentExprParser add:[PKRepetition repetitionWithSubparser:self.assignmentOpConditionalExprParser]]; + } + return assignmentExprParser; +} + + +// assignmentOpConditionalExpr = assignmentOperator conditionalExpr; +- (PKCollectionParser *)assignmentOpConditionalExprParser { + if (!assignmentOpConditionalExprParser) { + self.assignmentOpConditionalExprParser = [PKSequence sequence]; + assignmentOpConditionalExprParser.name = @"assignmentOpConditionalExpr"; + [assignmentOpConditionalExprParser add:self.assignmentOpParser]; + [assignmentOpConditionalExprParser add:self.conditionalExprParser]; + } + return assignmentOpConditionalExprParser; +} + + +// ConditionalExpression: +// OrExpression +// OrExpression ? AssignmentExpression : AssignmentExpression +// +// conditionalExpr = orExpr ternaryExpr?; +- (PKCollectionParser *)conditionalExprParser { + if (!conditionalExprParser) { + self.conditionalExprParser = [PKSequence sequence]; + conditionalExprParser.name = @"conditionalExpr"; + [conditionalExprParser add:self.orExprParser]; + [conditionalExprParser add:[self zeroOrOne:self.ternaryExprParser]]; + } + return conditionalExprParser; +} + + +// ternaryExpr = question assignmentExpr colon assignmentExpr; +- (PKCollectionParser *)ternaryExprParser { + if (!ternaryExprParser) { + self.ternaryExprParser = [PKSequence sequence]; + ternaryExprParser.name = @"ternaryExpr"; + [ternaryExprParser add:self.questionParser]; + [ternaryExprParser add:self.assignmentExprParser]; + [ternaryExprParser add:self.colonParser]; + [ternaryExprParser add:self.assignmentExprParser]; + } + return ternaryExprParser; +} + + +// OrExpression: +// AndExpression +// AndExpression || OrExpression +// +// orExpr = andExpr orAndExpr*; +- (PKCollectionParser *)orExprParser { + if (!orExprParser) { + self.orExprParser = [PKSequence sequence]; + orExprParser.name = @"orExpr"; + [orExprParser add:self.andExprParser]; + [orExprParser add:[PKRepetition repetitionWithSubparser:self.orAndExprParser]]; + } + return orExprParser; +} + + +// orAndExpr = or andExpr; +- (PKCollectionParser *)orAndExprParser { + if (!orAndExprParser) { + self.orAndExprParser = [PKSequence sequence]; + orAndExprParser.name = @"orAndExpr"; + [orAndExprParser add:self.orParser]; + [orAndExprParser add:self.andExprParser]; + } + return orAndExprParser; +} + + +// AndExpression: +// BitwiseOrExpression +// BitwiseOrExpression && AndExpression +// +// andExpr = bitwiseOrExpr andBitwiseOrExprParser*; +- (PKCollectionParser *)andExprParser { + if (!andExprParser) { + self.andExprParser = [PKSequence sequence]; + andExprParser.name = @"andExpr"; + [andExprParser add:self.bitwiseOrExprParser]; + [andExprParser add:[PKRepetition repetitionWithSubparser:self.andBitwiseOrExprParser]]; + } + return andExprParser; +} + + +// andBitwiseOrExprParser = and bitwiseOrExpr; +- (PKCollectionParser *)andBitwiseOrExprParser { + if (!andBitwiseOrExprParser) { + self.andBitwiseOrExprParser = [PKSequence sequence]; + andBitwiseOrExprParser.name = @"andBitwiseOrExpr"; + [andBitwiseOrExprParser add:self.andParser]; + [andBitwiseOrExprParser add:self.bitwiseOrExprParser]; + } + return andBitwiseOrExprParser; +} + + +// BitwiseOrExpression: +// BitwiseXorExpression +// BitwiseXorExpression | BitwiseOrExpression +// +// bitwiseOrExpr = bitwiseXorExpr pipeBitwiseXorExpr*; +- (PKCollectionParser *)bitwiseOrExprParser { + if (!bitwiseOrExprParser) { + self.bitwiseOrExprParser = [PKSequence sequence]; + bitwiseOrExprParser.name = @"bitwiseOrExpr"; + [bitwiseOrExprParser add:self.bitwiseXorExprParser]; + [bitwiseOrExprParser add:[PKRepetition repetitionWithSubparser:self.pipeBitwiseXorExprParser]]; + } + return bitwiseOrExprParser; +} + + +// pipeBitwiseXorExprParser = pipe bitwiseXorExpr; +- (PKCollectionParser *)pipeBitwiseXorExprParser { + if (!pipeBitwiseXorExprParser) { + self.pipeBitwiseXorExprParser = [PKSequence sequence]; + pipeBitwiseXorExprParser.name = @"pipeBitwiseXorExpr"; + [pipeBitwiseXorExprParser add:self.pipeParser]; + [pipeBitwiseXorExprParser add:self.bitwiseXorExprParser]; + } + return pipeBitwiseXorExprParser; +} + + +// BitwiseXorExpression: +// BitwiseAndExpression +// BitwiseAndExpression ^ BitwiseXorExpression +// +// bitwiseXorExpr = bitwiseAndExpr caretBitwiseAndExpr*; +- (PKCollectionParser *)bitwiseXorExprParser { + if (!bitwiseXorExprParser) { + self.bitwiseXorExprParser = [PKSequence sequence]; + bitwiseXorExprParser.name = @"bitwiseXorExpr"; + [bitwiseXorExprParser add:self.bitwiseAndExprParser]; + [bitwiseXorExprParser add:[PKRepetition repetitionWithSubparser:self.caretBitwiseAndExprParser]]; + } + return bitwiseXorExprParser; +} + + +// caretBitwiseAndExpr = caret bitwiseAndExpr; +- (PKCollectionParser *)caretBitwiseAndExprParser { + if (!caretBitwiseAndExprParser) { + self.caretBitwiseAndExprParser = [PKSequence sequence]; + caretBitwiseAndExprParser.name = @"caretBitwiseAndExpr"; + [caretBitwiseAndExprParser add:self.caretParser]; + [caretBitwiseAndExprParser add:self.bitwiseAndExprParser]; + } + return caretBitwiseAndExprParser; +} + + +// BitwiseAndExpression: +// EqualityExpression +// EqualityExpression & BitwiseAndExpression +// +// bitwiseAndExpr = equalityExpr ampEqualityExpr*; +- (PKCollectionParser *)bitwiseAndExprParser { + if (!bitwiseAndExprParser) { + self.bitwiseAndExprParser = [PKSequence sequence]; + bitwiseAndExprParser.name = @"bitwiseAndExpr"; + [bitwiseAndExprParser add:self.equalityExprParser]; + [bitwiseAndExprParser add:[PKRepetition repetitionWithSubparser:self.ampEqualityExprParser]]; + } + return bitwiseAndExprParser; +} + + +// ampEqualityExpression = amp equalityExpression; +- (PKCollectionParser *)ampEqualityExprParser { + if (!ampEqualityExprParser) { + self.ampEqualityExprParser = [PKSequence sequence]; + ampEqualityExprParser.name = @"ampEqualityExpr"; + [ampEqualityExprParser add:self.ampParser]; + [ampEqualityExprParser add:self.equalityExprParser]; + } + return ampEqualityExprParser; +} + + +// EqualityExpression: +// RelationalExpression +// RelationalExpression EqualityualityOperator EqualityExpression +// +// equalityExpr = relationalExpr equalityOpRelationalExpr*; +- (PKCollectionParser *)equalityExprParser { + if (!equalityExprParser) { + self.equalityExprParser = [PKSequence sequence]; + equalityExprParser.name = @"equalityExpr"; + [equalityExprParser add:self.relationalExprParser]; + [equalityExprParser add:[PKRepetition repetitionWithSubparser:self.equalityOpRelationalExprParser]]; + } + return equalityExprParser; +} + + +// equalityOpRelationalExpr = equalityOp relationalExpr; +- (PKCollectionParser *)equalityOpRelationalExprParser { + if (!equalityOpRelationalExprParser) { + self.equalityOpRelationalExprParser = [PKSequence sequence]; + equalityOpRelationalExprParser.name = @"equalityOpRelationalExpr"; + [equalityOpRelationalExprParser add:self.equalityOpParser]; + [equalityOpRelationalExprParser add:self.relationalExprParser]; + } + return equalityOpRelationalExprParser; +} + + +// RelationalExpression: +// ShiftExpression +// RelationalExpression RelationalationalOperator ShiftExpression +// + +// relationalExpr = shiftExpr relationalOpShiftExpr*; /// TODO ???? +- (PKCollectionParser *)relationalExprParser { + if (!relationalExprParser) { + self.relationalExprParser = [PKSequence sequence]; + relationalExprParser.name = @"relationalExpr"; + [relationalExprParser add:self.shiftExprParser]; + [relationalExprParser add:[PKRepetition repetitionWithSubparser:self.relationalOpShiftExprParser]]; + } + return relationalExprParser; +} + + +// relationalOpShiftExpr = relationalOperator shiftExpr; +- (PKCollectionParser *)relationalOpShiftExprParser { + if (!relationalOpShiftExprParser) { + self.relationalOpShiftExprParser = [PKSequence sequence]; + relationalOpShiftExprParser.name = @"relationalOpShiftExpr"; + [relationalOpShiftExprParser add:self.relationalOpParser]; + [relationalOpShiftExprParser add:self.shiftExprParser]; + } + return relationalOpShiftExprParser; +} + + +// ShiftExpression: +// AdditiveExpression +// AdditiveExpression ShiftOperator ShiftExpression +// +// shiftExpr = additiveExpr shiftOpAdditiveExpr?; +- (PKCollectionParser *)shiftExprParser { + if (!shiftExprParser) { + self.shiftExprParser = [PKSequence sequence]; + shiftExprParser.name = @"shiftExpr"; + [shiftExprParser add:self.additiveExprParser]; + [shiftExprParser add:[PKRepetition repetitionWithSubparser:self.shiftOpAdditiveExprParser]]; + } + return shiftExprParser; +} + + +// shiftOpShiftExpr = shiftOp additiveExpr; +- (PKCollectionParser *)shiftOpAdditiveExprParser { + if (!shiftOpAdditiveExprParser) { + self.shiftOpAdditiveExprParser = [PKSequence sequence]; + shiftOpAdditiveExprParser.name = @"shiftOpShiftExpr"; + [shiftOpAdditiveExprParser add:self.shiftOpParser]; + [shiftOpAdditiveExprParser add:self.additiveExprParser]; + } + return shiftOpAdditiveExprParser; +} + + +// AdditiveExpression: +// MultiplicativeExpression +// MultiplicativeExpression + AdditiveExpression +// MultiplicativeExpression - AdditiveExpression +// +// additiveExpr = multiplicativeExpr plusOrMinusExpr*; +- (PKCollectionParser *)additiveExprParser { + if (!additiveExprParser) { + self.additiveExprParser = [PKSequence sequence]; + additiveExprParser.name = @"additiveExpr"; + [additiveExprParser add:self.multiplicativeExprParser]; + [additiveExprParser add:[PKRepetition repetitionWithSubparser:self.plusOrMinusExprParser]]; + } + return additiveExprParser; +} + + +// plusOrMinusExpr = plusExpr | minusExpr; +- (PKCollectionParser *)plusOrMinusExprParser { + if (!plusOrMinusExprParser) { + self.plusOrMinusExprParser = [PKAlternation alternation]; + plusOrMinusExprParser.name = @"plusOrMinusExpr"; + [plusOrMinusExprParser add:self.plusExprParser]; + [plusOrMinusExprParser add:self.minusExprParser]; + } + return plusOrMinusExprParser; +} + + +// plusExpr = plus multiplicativeExprParser; +- (PKCollectionParser *)plusExprParser { + if (!plusExprParser) { + self.plusExprParser = [PKSequence sequence]; + plusExprParser.name = @"plusExpr"; + [plusExprParser add:self.plusParser]; + [plusExprParser add:self.multiplicativeExprParser]; + } + return plusExprParser; +} + + +// minusExpr = minus multiplicativeExprParser; +- (PKCollectionParser *)minusExprParser { + if (!minusExprParser) { + self.minusExprParser = [PKSequence sequence]; + minusExprParser.name = @"minusExpr"; + [minusExprParser add:self.minusParser]; + [minusExprParser add:self.multiplicativeExprParser]; + } + return minusExprParser; +} + + +// MultiplicativeExpression: +// UnaryExpression +// UnaryExpression MultiplicativeOperator MultiplicativeExpression +// +// multiplicativeExpr = unaryExpr multiplicativeOpUnaryExpr*; +- (PKCollectionParser *)multiplicativeExprParser { + if (!multiplicativeExprParser) { + self.multiplicativeExprParser = [PKSequence sequence]; + multiplicativeExprParser.name = @"multiplicativeExpr"; + [multiplicativeExprParser add:self.unaryExprParser]; + [multiplicativeExprParser add:[PKRepetition repetitionWithSubparser:self.multiplicativeOpUnaryExprParser]]; + } + return multiplicativeExprParser; +} + + +// multiplicativeOpUnaryExpr = multiplicativeOp unaryExpr; +- (PKCollectionParser *)multiplicativeOpUnaryExprParser { + if (!multiplicativeOpUnaryExprParser) { + self.multiplicativeOpUnaryExprParser = [PKSequence sequence]; + multiplicativeOpUnaryExprParser.name = @"multiplicativeOpUnaryExpr"; + [multiplicativeOpUnaryExprParser add:self.multiplicativeOpParser]; + [multiplicativeOpUnaryExprParser add:self.unaryExprParser]; + } + return multiplicativeOpUnaryExprParser; +} + + +// UnaryExpression: +// MemberExpression +// UnaryOperator UnaryExpression +// - UnaryExpression +// IncrementOperator MemberExpression +// MemberExpression IncrementOperator +// new Constructor +// delete MemberExpression +// +// unaryExpr = memberExpr | unaryExpr1 | unaryExpr2 | unaryExpr3 | unaryExpr4 | unaryExpr5 | unaryExpr6; +- (PKCollectionParser *)unaryExprParser { + if (!unaryExprParser) { + self.unaryExprParser = [PKAlternation alternation]; + unaryExprParser.name = @"unaryExpr"; + [unaryExprParser add:self.memberExprParser]; + [unaryExprParser add:self.unaryExpr1Parser]; + [unaryExprParser add:self.unaryExpr2Parser]; + [unaryExprParser add:self.unaryExpr3Parser]; + [unaryExprParser add:self.unaryExpr4Parser]; + [unaryExprParser add:self.unaryExpr5Parser]; + [unaryExprParser add:self.unaryExpr6Parser]; + } + return unaryExprParser; +} + + +// unaryExpr1 = unaryOperator unaryExpr; +- (PKCollectionParser *)unaryExpr1Parser { + if (!unaryExpr1Parser) { + self.unaryExpr1Parser = [PKSequence sequence]; + unaryExpr1Parser.name = @"unaryExpr1"; + [unaryExpr1Parser add:self.unaryOpParser]; + [unaryExpr1Parser add:self.unaryExprParser]; + } + return unaryExpr1Parser; +} + + +// unaryExpr2 = minus unaryExpr; +- (PKCollectionParser *)unaryExpr2Parser { + if (!unaryExpr2Parser) { + self.unaryExpr2Parser = [PKSequence sequence]; + unaryExpr2Parser.name = @"unaryExpr2"; + [unaryExpr2Parser add:self.minusParser]; + [unaryExpr2Parser add:self.unaryExprParser]; + } + return unaryExpr2Parser; +} + + +// unaryExpr3 = incrementOperator memberExpr; +- (PKCollectionParser *)unaryExpr3Parser { + if (!unaryExpr3Parser) { + self.unaryExpr3Parser = [PKSequence sequence]; + unaryExpr3Parser.name = @"unaryExpr3"; + [unaryExpr3Parser add:self.incrementOpParser]; + [unaryExpr3Parser add:self.memberExprParser]; + } + return unaryExpr3Parser; +} + + +// unaryExpr4 = memberExpr incrementOperator; +- (PKCollectionParser *)unaryExpr4Parser { + if (!unaryExpr4Parser) { + self.unaryExpr4Parser = [PKSequence sequence]; + unaryExpr4Parser.name = @"unaryExpr4"; + [unaryExpr4Parser add:self.memberExprParser]; + [unaryExpr4Parser add:self.incrementOpParser]; + } + return unaryExpr4Parser; +} + + +// unaryExpr5 = new constructor; +- (PKCollectionParser *)unaryExpr5Parser { + if (!unaryExpr5Parser) { + self.unaryExpr5Parser = [PKSequence sequence]; + unaryExpr5Parser.name = @"unaryExpr5"; + [unaryExpr5Parser add:self.newParser]; + [unaryExpr5Parser add:self.constructorCallParser]; + } + return unaryExpr5Parser; +} + + +// unaryExpr6 = delete memberExpr; +- (PKCollectionParser *)unaryExpr6Parser { + if (!unaryExpr6Parser) { + self.unaryExpr6Parser = [PKSequence sequence]; + unaryExpr6Parser.name = @"unaryExpr6"; + [unaryExpr6Parser add:self.deleteParser]; + [unaryExpr6Parser add:self.memberExprParser]; + } + return unaryExpr6Parser; +} + + +// ConstructorCall: +// Identifier +// Identifier ( ArgumentListOpt ) +// Identifier . ConstructorCall +// + +// constructorCall = identifier parentArgListOptParent? memberExprExt* +- (PKCollectionParser *)constructorCallParser { + if (!constructorCallParser) { + self.constructorCallParser = [PKSequence sequence]; + constructorCallParser.name = @"constructorCall"; + [constructorCallParser add:self.identifierParser]; + [constructorCallParser add:[self zeroOrOne:self.parenArgListOptParenParser]]; + [constructorCallParser add:[PKRepetition repetitionWithSubparser:self.memberExprExtParser]]; + } + return constructorCallParser; +} + + +// parenArgListParen = openParen argListOpt closeParen; +- (PKCollectionParser *)parenArgListOptParenParser { + if (!parenArgListOptParenParser) { + self.parenArgListOptParenParser = [PKSequence sequence]; + parenArgListOptParenParser.name = @"parenArgListParen"; + [parenArgListOptParenParser add:self.openParenParser]; + [parenArgListOptParenParser add:self.argListOptParser]; + [parenArgListOptParenParser add:self.closeParenParser]; + } + return parenArgListOptParenParser; +} + + +// MemberExpression: +// PrimaryExpression +// PrimaryExpression . MemberExpression +// PrimaryExpression [ Expression ] +// PrimaryExpression ( ArgumentListOpt ) +// +// memberExpr = primaryExpr memberExprExt?; // TODO ?????? +- (PKCollectionParser *)memberExprParser { + if (!memberExprParser) { + self.memberExprParser = [PKSequence sequence]; + memberExprParser.name = @"memberExpr"; + [memberExprParser add:self.primaryExprParser]; + [memberExprParser add:[PKRepetition repetitionWithSubparser:self.memberExprExtParser]]; + } + return memberExprParser; +} + + +// memberExprExt = dotMemberExpr | bracketMemberExpr | parenMemberExpr; +- (PKCollectionParser *)memberExprExtParser { + if (!memberExprExtParser) { + self.memberExprExtParser = [PKAlternation alternation]; + memberExprExtParser.name = @"memberExprExt"; + [memberExprExtParser add:self.dotMemberExprParser]; + [memberExprExtParser add:self.bracketMemberExprParser]; + [memberExprExtParser add:self.parenArgListOptParenParser]; + } + return memberExprExtParser; +} + + +// dotMemberExpr = dot memberExpr; +- (PKCollectionParser *)dotMemberExprParser { + if (!dotMemberExprParser) { + self.dotMemberExprParser = [PKSequence sequence]; + dotMemberExprParser.name = @"dotMemberExpr"; + [dotMemberExprParser add:self.dotParser]; + [dotMemberExprParser add:self.memberExprParser]; + } + return dotMemberExprParser; +} + + +// bracketMemberExpr = openBracket expr closeBracket; +- (PKCollectionParser *)bracketMemberExprParser { + if (!bracketMemberExprParser) { + self.bracketMemberExprParser = [PKSequence sequence]; + bracketMemberExprParser.name = @"bracketMemberExpr"; + [bracketMemberExprParser add:self.openBracketParser]; + [bracketMemberExprParser add:self.exprParser]; + [bracketMemberExprParser add:self.closeBracketParser]; + } + return bracketMemberExprParser; +} + + +// ArgumentListOpt: +// empty +// ArgumentList +// +// argListOpt = argList?; +- (PKCollectionParser *)argListOptParser { + if (!argListOptParser) { + self.argListOptParser = [self zeroOrOne:self.argListParser]; + argListOptParser.name = @"argListOpt"; + } + return argListOptParser; +} + + +// ArgumentList: +// AssignmentExpression +// AssignmentExpression , ArgumentList +// +// argList = assignmentExpr commaAssignmentExpr*; +- (PKCollectionParser *)argListParser { + if (!argListParser) { + self.argListParser = [PKSequence sequence]; + argListParser.name = @"argList"; + [argListParser add:self.assignmentExprParser]; + [argListParser add:[PKRepetition repetitionWithSubparser:self.commaAssignmentExprParser]]; + } + return argListParser; +} + + + // PrimaryExpression: + // ( Expression ) + // funcLiteral + // arrayLiteral + // Identifier + // IntegerLiteral + // FloatingPointLiteral + // StringLiteral + // false + // true + // null + // this +// primaryExpr = parenExprParen | funcLiteral | arrayLiteral | identifier | Number | QuotedString | false | true | null | undefined | this; +- (PKCollectionParser *)primaryExprParser { + if (!primaryExprParser) { + self.primaryExprParser = [PKAlternation alternation]; + primaryExprParser.name = @"primaryExpr"; + [primaryExprParser add:self.parenExprParenParser]; + [primaryExprParser add:self.funcLiteralParser]; + [primaryExprParser add:self.arrayLiteralParser]; + [primaryExprParser add:self.objectLiteralParser]; + [primaryExprParser add:self.identifierParser]; + [primaryExprParser add:self.numberParser]; + [primaryExprParser add:self.stringParser]; + [primaryExprParser add:self.trueParser]; + [primaryExprParser add:self.falseParser]; + [primaryExprParser add:self.nullParser]; + [primaryExprParser add:self.undefinedParser]; // TODO ?? + [primaryExprParser add:self.thisParser]; + } + return primaryExprParser; +} + + + +// parenExprParen = openParen expr closeParen; +- (PKCollectionParser *)parenExprParenParser { + if (!parenExprParenParser) { + self.parenExprParenParser = [PKSequence sequence]; + parenExprParenParser.name = @"parenExprParen"; + [parenExprParenParser add:self.openParenParser]; + [parenExprParenParser add:self.exprParser]; + [parenExprParenParser add:self.closeParenParser]; + } + return parenExprParenParser; +} + + +//funcLiteral = function openParen paramListOpt closeParen compoundStmt; +- (PKCollectionParser *)funcLiteralParser { + if (!funcLiteralParser) { + self.funcLiteralParser = [PKSequence sequence]; + funcLiteralParser.name = @"funcLiteral"; + [funcLiteralParser add:self.functionParser]; + [funcLiteralParser add:self.openParenParser]; + [funcLiteralParser add:self.paramListOptParser]; + [funcLiteralParser add:self.closeParenParser]; + [funcLiteralParser add:self.compoundStmtParser]; + } + return funcLiteralParser; +} + + +//arrayLiteral = '[' arrayContents ']'; +- (PKCollectionParser *)arrayLiteralParser { + if (!arrayLiteralParser) { + self.arrayLiteralParser = [PKTrack track]; + arrayLiteralParser.name = @"arrayLiteralParser"; + + PKSequence *commaPrimaryExpr = [PKSequence sequence]; + [commaPrimaryExpr add:self.commaParser]; + [commaPrimaryExpr add:self.primaryExprParser]; + + PKSequence *arrayContents = [PKSequence sequence]; + [arrayContents add:self.primaryExprParser]; + [arrayContents add:[PKRepetition repetitionWithSubparser:commaPrimaryExpr]]; + + PKAlternation *arrayContentsOpt = [PKAlternation alternation]; + [arrayContentsOpt add:[PKEmpty empty]]; + [arrayContentsOpt add:arrayContents]; + + [arrayLiteralParser add:self.openBracketParser]; + [arrayLiteralParser add:arrayContentsOpt]; + [arrayLiteralParser add:self.closeBracketParser]; + } + return arrayLiteralParser; +} + + +//objectLiteral = '{' objectContentsOpt '}'; +- (PKCollectionParser *)objectLiteralParser { + if (!objectLiteralParser) { + self.objectLiteralParser = [PKSequence sequence]; + objectLiteralParser.name = @"objectLiteralParser"; + + PKSequence *member = [PKSequence sequence]; + [member add:self.identifierParser]; + [member add:self.colonParser]; + [member add:self.primaryExprParser]; + + PKSequence *commaMember = [PKSequence sequence]; + [commaMember add:self.commaParser]; + [commaMember add:member]; + + PKSequence *objectContents = [PKSequence sequence]; + [objectContents add:member]; + [objectContents add:[PKRepetition repetitionWithSubparser:commaMember]]; + + PKAlternation *objectContentsOpt = [PKAlternation alternation]; + [objectContentsOpt add:[PKEmpty empty]]; + [objectContentsOpt add:objectContents]; + + [objectLiteralParser add:self.openCurlyParser]; + [objectLiteralParser add:objectContentsOpt]; + [objectLiteralParser add:self.closeCurlyParser]; + } + return objectLiteralParser; +} + + +// identifier = Word; +- (PKParser *)identifierParser { + if (!identifierParser) { + self.identifierParser = [PKWord word]; + identifierParser.name = @"identifier"; + } + return identifierParser; +} + + +- (PKParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKQuotedString quotedString]; + stringParser.name = @"string"; + } + return stringParser; +} + + +- (PKParser *)numberParser { + if (!numberParser) { + self.numberParser = [PKNumber number]; + numberParser.name = @"number"; + } + return numberParser; +} + + +#pragma mark - +#pragma mark keywords + +- (PKParser *)ifParser { + if (!ifParser) { + self.ifParser = [PKLiteral literalWithString:@"if"]; + ifParser.name = @"if"; + } + return ifParser; +} + + +- (PKParser *)elseParser { + if (!elseParser) { + self.elseParser = [PKLiteral literalWithString:@"else"]; + elseParser.name = @"else"; + } + return elseParser; +} + + +- (PKParser *)whileParser { + if (!whileParser) { + self.whileParser = [PKLiteral literalWithString:@"while"]; + whileParser.name = @"while"; + } + return whileParser; +} + + +- (PKParser *)forParser { + if (!forParser) { + self.forParser = [PKLiteral literalWithString:@"for"]; + forParser.name = @"for"; + } + return forParser; +} + + +- (PKParser *)inParser { + if (!inParser) { + self.inParser = [PKLiteral literalWithString:@"in"]; + inParser.name = @"in"; + } + return inParser; +} + + +- (PKParser *)breakParser { + if (!breakParser) { + self.breakParser = [PKLiteral literalWithString:@"break"]; + breakParser.name = @"break"; + } + return breakParser; +} + + +- (PKParser *)continueParser { + if (!continueParser) { + self.continueParser = [PKLiteral literalWithString:@"continue"]; + continueParser.name = @"continue"; + } + return continueParser; +} + + +- (PKParser *)withParser { + if (!withParser) { + self.withParser = [PKLiteral literalWithString:@"with"]; + withParser.name = @"with"; + } + return withParser; +} + + +- (PKParser *)returnParser { + if (!returnParser) { + self.returnParser = [PKLiteral literalWithString:@"return"]; + returnParser.name = @"return"; + } + return returnParser; +} + + +- (PKParser *)varParser { + if (!varParser) { + self.varParser = [PKLiteral literalWithString:@"var"]; + varParser.name = @"var"; + } + return varParser; +} + + +- (PKParser *)deleteParser { + if (!deleteParser) { + self.deleteParser = [PKLiteral literalWithString:@"delete"]; + deleteParser.name = @"delete"; + } + return deleteParser; +} + + +- (PKParser *)newParser { + if (!newParser) { + self.newParser = [PKLiteral literalWithString:@"new"]; + newParser.name = @"new"; + } + return newParser; +} + + +- (PKParser *)thisParser { + if (!thisParser) { + self.thisParser = [PKLiteral literalWithString:@"this"]; + thisParser.name = @"this"; + } + return thisParser; +} + + +- (PKParser *)falseParser { + if (!falseParser) { + self.falseParser = [PKLiteral literalWithString:@"false"]; + falseParser.name = @"false"; + } + return falseParser; +} + + +- (PKParser *)trueParser { + if (!trueParser) { + self.trueParser = [PKLiteral literalWithString:@"true"]; + trueParser.name = @"true"; + } + return trueParser; +} + + +- (PKParser *)nullParser { + if (!nullParser) { + self.nullParser = [PKLiteral literalWithString:@"null"]; + nullParser.name = @"null"; + } + return nullParser; +} + + +- (PKParser *)undefinedParser { + if (!undefinedParser) { + self.undefinedParser = [PKLiteral literalWithString:@"undefined"]; + undefinedParser.name = @"undefined"; + } + return undefinedParser; +} + + +- (PKParser *)voidParser { + if (!voidParser) { + self.voidParser = [PKLiteral literalWithString:@"void"]; + voidParser.name = @"void"; + } + return voidParser; +} + + +- (PKParser *)typeofParser { + if (!typeofParser) { + self.typeofParser = [PKLiteral literalWithString:@"typeof"]; + typeofParser.name = @"typeof"; + } + return typeofParser; +} + + +- (PKParser *)instanceofParser { + if (!instanceofParser) { + self.instanceofParser = [PKLiteral literalWithString:@"instanceof"]; + instanceofParser.name = @"instanceof"; + } + return instanceofParser; +} + + +- (PKParser *)functionParser { + if (!functionParser) { + self.functionParser = [PKLiteral literalWithString:@"function"]; + functionParser.name = @"function"; + } + return functionParser; +} + + +#pragma mark - +#pragma mark single-char symbols + +- (PKParser *)orParser { + if (!orParser) { + self.orParser = [PKSymbol symbolWithString:@"||"]; + orParser.name = @"or"; + } + return orParser; +} + + +- (PKParser *)andParser { + if (!andParser) { + self.andParser = [PKSymbol symbolWithString:@"&&"]; + andParser.name = @"and"; + } + return andParser; +} + + +- (PKParser *)neParser { + if (!neParser) { + self.neParser = [PKSymbol symbolWithString:@"!="]; + neParser.name = @"ne"; + } + return neParser; +} + + +- (PKParser *)isNotParser { + if (!isNotParser) { + self.isNotParser = [PKSymbol symbolWithString:@"!=="]; + isNotParser.name = @"isNot"; + } + return isNotParser; +} + + +- (PKParser *)eqParser { + if (!eqParser) { + self.eqParser = [PKSymbol symbolWithString:@"=="]; + eqParser.name = @"eq"; + } + return eqParser; +} + + +- (PKParser *)isParser { + if (!isParser) { + self.isParser = [PKSymbol symbolWithString:@"==="]; + isParser.name = @"is"; + } + return isParser; +} + + +- (PKParser *)leParser { + if (!leParser) { + self.leParser = [PKSymbol symbolWithString:@"<="]; + leParser.name = @"le"; + } + return leParser; +} + + +- (PKParser *)geParser { + if (!geParser) { + self.geParser = [PKSymbol symbolWithString:@">="]; + geParser.name = @"ge"; + } + return geParser; +} + + +- (PKParser *)plusPlusParser { + if (!plusPlusParser) { + self.plusPlusParser = [PKSymbol symbolWithString:@"++"]; + plusPlusParser.name = @"plusPlus"; + } + return plusPlusParser; +} + + +- (PKParser *)minusMinusParser { + if (!minusMinusParser) { + self.minusMinusParser = [PKSymbol symbolWithString:@"--"]; + minusMinusParser.name = @"minusMinus"; + } + return minusMinusParser; +} + + +- (PKParser *)plusEqParser { + if (!plusEqParser) { + self.plusEqParser = [PKSymbol symbolWithString:@"+="]; + plusEqParser.name = @"plusEq"; + } + return plusEqParser; +} + + +- (PKParser *)minusEqParser { + if (!minusEqParser) { + self.minusEqParser = [PKSymbol symbolWithString:@"-="]; + minusEqParser.name = @"minusEq"; + } + return minusEqParser; +} + + +- (PKParser *)timesEqParser { + if (!timesEqParser) { + self.timesEqParser = [PKSymbol symbolWithString:@"*="]; + timesEqParser.name = @"timesEq"; + } + return timesEqParser; +} + + +- (PKParser *)divEqParser { + if (!divEqParser) { + self.divEqParser = [PKSymbol symbolWithString:@"/="]; + divEqParser.name = @"divEq"; + } + return divEqParser; +} + + +- (PKParser *)modEqParser { + if (!modEqParser) { + self.modEqParser = [PKSymbol symbolWithString:@"%="]; + modEqParser.name = @"modEq"; + } + return modEqParser; +} + + +- (PKParser *)shiftLeftParser { + if (!shiftLeftParser) { + self.shiftLeftParser = [PKSymbol symbolWithString:@"<<"]; + shiftLeftParser.name = @"shiftLeft"; + } + return shiftLeftParser; +} + + +- (PKParser *)shiftRightParser { + if (!shiftRightParser) { + self.shiftRightParser = [PKSymbol symbolWithString:@">>"]; + shiftRightParser.name = @"shiftRight"; + } + return shiftRightParser; +} + + +- (PKParser *)shiftRightExtParser { + if (!shiftRightExtParser) { + self.shiftRightExtParser = [PKSymbol symbolWithString:@">>>"]; + shiftRightExtParser.name = @"shiftRightExt"; + } + return shiftRightExtParser; +} + + +- (PKParser *)shiftLeftEqParser { + if (!shiftLeftEqParser) { + self.shiftLeftEqParser = [PKSymbol symbolWithString:@"<<="]; + shiftLeftEqParser.name = @"shiftLeftEq"; + } + return shiftLeftEqParser; +} + + +- (PKParser *)shiftRightEqParser { + if (!shiftRightEqParser) { + self.shiftRightEqParser = [PKSymbol symbolWithString:@">>="]; + shiftRightEqParser.name = @"shiftRightEq"; + } + return shiftRightEqParser; +} + + +- (PKParser *)shiftRightExtEqParser { + if (!shiftRightExtEqParser) { + self.shiftRightExtEqParser = [PKSymbol symbolWithString:@">>>="]; + shiftRightExtEqParser.name = @"shiftRightExtEq"; + } + return shiftRightExtEqParser; +} + + +- (PKParser *)andEqParser { + if (!andEqParser) { + self.andEqParser = [PKSymbol symbolWithString:@"&="]; + andEqParser.name = @"andEq"; + } + return andEqParser; +} + + +- (PKParser *)xorEqParser { + if (!xorEqParser) { + self.xorEqParser = [PKSymbol symbolWithString:@"^="]; + xorEqParser.name = @"xorEq"; + } + return xorEqParser; +} + + +- (PKParser *)orEqParser { + if (!orEqParser) { + self.orEqParser = [PKSymbol symbolWithString:@"|="]; + orEqParser.name = @"orEq"; + } + return orEqParser; +} + + +#pragma mark - +#pragma mark single-char symbols + +- (PKParser *)openCurlyParser { + if (!openCurlyParser) { + self.openCurlyParser = [PKSymbol symbolWithString:@"{"]; + openCurlyParser.name = @"openCurly"; + } + return openCurlyParser; +} + + +- (PKParser *)closeCurlyParser { + if (!closeCurlyParser) { + self.closeCurlyParser = [PKSymbol symbolWithString:@"}"]; + closeCurlyParser.name = @"closeCurly"; + } + return closeCurlyParser; +} + + +- (PKParser *)openParenParser { + if (!openParenParser) { + self.openParenParser = [PKSymbol symbolWithString:@"("]; + openParenParser.name = @"openParen"; + } + return openParenParser; +} + + +- (PKParser *)closeParenParser { + if (!closeParenParser) { + self.closeParenParser = [PKSymbol symbolWithString:@")"]; + closeParenParser.name = @"closeParen"; + } + return closeParenParser; +} + + +- (PKParser *)openBracketParser { + if (!openBracketParser) { + self.openBracketParser = [PKSymbol symbolWithString:@"["]; + openBracketParser.name = @"openBracket"; + } + return openBracketParser; +} + + +- (PKParser *)closeBracketParser { + if (!closeBracketParser) { + self.closeBracketParser = [PKSymbol symbolWithString:@"]"]; + closeBracketParser.name = @"closeBracket"; + } + return closeBracketParser; +} + + +- (PKParser *)commaParser { + if (!commaParser) { + self.commaParser = [PKSymbol symbolWithString:@","]; + commaParser.name = @"comma"; + } + return commaParser; +} + + +- (PKParser *)dotParser { + if (!dotParser) { + self.dotParser = [PKSymbol symbolWithString:@"."]; + dotParser.name = @"dot"; + } + return dotParser; +} + + +- (PKParser *)semiOptParser { + if (!semiOptParser) { + self.semiOptParser = [self zeroOrOne:self.semiParser]; + semiOptParser.name = @"semiOpt"; + } + return semiOptParser; +} + + +- (PKParser *)semiParser { + if (!semiParser) { + self.semiParser = [PKSymbol symbolWithString:@";"]; + semiParser.name = @"semi"; + } + return semiParser; +} + + +- (PKParser *)colonParser { + if (!colonParser) { + self.colonParser = [PKSymbol symbolWithString:@":"]; + colonParser.name = @"colon"; + } + return colonParser; +} + + +- (PKParser *)equalsParser { + if (!equalsParser) { + self.equalsParser = [PKSymbol symbolWithString:@"="]; + equalsParser.name = @"equals"; + } + return equalsParser; +} + + +- (PKParser *)notParser { + if (!notParser) { + self.notParser = [PKSymbol symbolWithString:@"!"]; + notParser.name = @"not"; + } + return notParser; +} + + +- (PKParser *)ltParser { + if (!ltParser) { + self.ltParser = [PKSymbol symbolWithString:@"<"]; + ltParser.name = @"lt"; + } + return ltParser; +} + + +- (PKParser *)gtParser { + if (!gtParser) { + self.gtParser = [PKSymbol symbolWithString:@">"]; + gtParser.name = @"gt"; + } + return gtParser; +} + + +- (PKParser *)ampParser { + if (!ampParser) { + self.ampParser = [PKSymbol symbolWithString:@"&"]; + ampParser.name = @"amp"; + } + return ampParser; +} + + +- (PKParser *)pipeParser { + if (!pipeParser) { + self.pipeParser = [PKSymbol symbolWithString:@"|"]; + pipeParser.name = @"pipe"; + } + return pipeParser; +} + + +- (PKParser *)caretParser { + if (!caretParser) { + self.caretParser = [PKSymbol symbolWithString:@"^"]; + caretParser.name = @"caret"; + } + return caretParser; +} + + +- (PKParser *)tildeParser { + if (!tildeParser) { + self.tildeParser = [PKSymbol symbolWithString:@"~"]; + tildeParser.name = @"tilde"; + } + return tildeParser; +} + + +- (PKParser *)questionParser { + if (!questionParser) { + self.questionParser = [PKSymbol symbolWithString:@"?"]; + questionParser.name = @"question"; + } + return questionParser; +} + + +- (PKParser *)plusParser { + if (!plusParser) { + self.plusParser = [PKSymbol symbolWithString:@"+"]; + plusParser.name = @"plus"; + } + return plusParser; +} + + +- (PKParser *)minusParser { + if (!minusParser) { + self.minusParser = [PKSymbol symbolWithString:@"-"]; + minusParser.name = @"minus"; + } + return minusParser; +} + + +- (PKParser *)timesParser { + if (!timesParser) { + self.timesParser = [PKSymbol symbolWithString:@"x"]; + timesParser.name = @"times"; + } + return timesParser; +} + + +- (PKParser *)divParser { + if (!divParser) { + self.divParser = [PKSymbol symbolWithString:@"/"]; + divParser.name = @"div"; + } + return divParser; +} + + +- (PKParser *)modParser { + if (!modParser) { + self.modParser = [PKSymbol symbolWithString:@"%"]; + modParser.name = @"mod"; + } + return modParser; +} + +@synthesize assignmentOpParser; +@synthesize relationalOpParser; +@synthesize equalityOpParser; +@synthesize shiftOpParser; +@synthesize incrementOpParser; +@synthesize unaryOpParser; +@synthesize multiplicativeOpParser; + +@synthesize programParser; +@synthesize elementParser; +@synthesize funcParser; +@synthesize paramListOptParser; +@synthesize paramListParser; +@synthesize commaIdentifierParser; +@synthesize compoundStmtParser; +@synthesize stmtsParser; +@synthesize stmtParser; +@synthesize ifStmtParser; +@synthesize ifElseStmtParser; +@synthesize whileStmtParser; +@synthesize forParenStmtParser; +@synthesize forBeginStmtParser; +@synthesize forInStmtParser; +@synthesize breakStmtParser; +@synthesize continueStmtParser; +@synthesize withStmtParser; +@synthesize returnStmtParser; +@synthesize variablesOrExprStmtParser; +@synthesize conditionParser; +@synthesize forParenParser; +@synthesize forBeginParser; +@synthesize variablesOrExprParser; +@synthesize varVariablesParser; +@synthesize variablesParser; +@synthesize commaVariableParser; +@synthesize variableParser; +@synthesize assignmentParser; +@synthesize exprOptParser; +@synthesize exprParser; +@synthesize commaAssignmentExprParser; +@synthesize assignmentExprParser; +@synthesize assignmentOpConditionalExprParser; +@synthesize conditionalExprParser; +@synthesize ternaryExprParser; +@synthesize orExprParser; +@synthesize orAndExprParser; +@synthesize andExprParser; +@synthesize andBitwiseOrExprParser; +@synthesize bitwiseOrExprParser; +@synthesize pipeBitwiseXorExprParser; +@synthesize bitwiseXorExprParser; +@synthesize caretBitwiseAndExprParser; +@synthesize bitwiseAndExprParser; +@synthesize ampEqualityExprParser; +@synthesize equalityExprParser; +@synthesize equalityOpRelationalExprParser; +@synthesize relationalExprParser; +@synthesize relationalOpShiftExprParser; +@synthesize shiftExprParser; +@synthesize shiftOpAdditiveExprParser; +@synthesize additiveExprParser; +@synthesize plusOrMinusExprParser; +@synthesize plusExprParser; +@synthesize minusExprParser; +@synthesize multiplicativeExprParser; +@synthesize multiplicativeOpUnaryExprParser; +@synthesize unaryExprParser; +@synthesize unaryExpr1Parser; +@synthesize unaryExpr2Parser; +@synthesize unaryExpr3Parser; +@synthesize unaryExpr4Parser; +@synthesize unaryExpr5Parser; +@synthesize unaryExpr6Parser; +@synthesize constructorCallParser; +@synthesize parenArgListOptParenParser; +@synthesize memberExprParser; +@synthesize memberExprExtParser; +@synthesize dotMemberExprParser; +@synthesize bracketMemberExprParser; +@synthesize argListOptParser; +@synthesize argListParser; +@synthesize primaryExprParser; +@synthesize parenExprParenParser; + +@synthesize funcLiteralParser; +@synthesize arrayLiteralParser; +@synthesize objectLiteralParser; + +@synthesize identifierParser; +@synthesize stringParser; +@synthesize numberParser; + +@synthesize ifParser; +@synthesize elseParser; +@synthesize whileParser; +@synthesize forParser; +@synthesize inParser; +@synthesize breakParser; +@synthesize continueParser; +@synthesize withParser; +@synthesize returnParser; +@synthesize varParser; +@synthesize deleteParser; +@synthesize newParser; +@synthesize thisParser; +@synthesize falseParser; +@synthesize trueParser; +@synthesize nullParser; +@synthesize undefinedParser; +@synthesize voidParser; +@synthesize typeofParser; +@synthesize instanceofParser; +@synthesize functionParser; + +@synthesize orParser; +@synthesize andParser; +@synthesize neParser; +@synthesize isNotParser; +@synthesize eqParser; +@synthesize isParser; +@synthesize leParser; +@synthesize geParser; +@synthesize plusPlusParser; +@synthesize minusMinusParser; +@synthesize plusEqParser; +@synthesize minusEqParser; +@synthesize timesEqParser; +@synthesize divEqParser; +@synthesize modEqParser; +@synthesize shiftLeftParser; +@synthesize shiftRightParser; +@synthesize shiftRightExtParser; +@synthesize shiftLeftEqParser; +@synthesize shiftRightEqParser; +@synthesize shiftRightExtEqParser; +@synthesize andEqParser; +@synthesize xorEqParser; +@synthesize orEqParser; + +@synthesize openCurlyParser; +@synthesize closeCurlyParser; +@synthesize openParenParser; +@synthesize closeParenParser; +@synthesize openBracketParser; +@synthesize closeBracketParser; +@synthesize commaParser; +@synthesize dotParser; +@synthesize semiOptParser; +@synthesize semiParser; +@synthesize colonParser; +@synthesize equalsParser; +@synthesize notParser; +@synthesize ltParser; +@synthesize gtParser; +@synthesize ampParser; +@synthesize pipeParser; +@synthesize caretParser; +@synthesize tildeParser; +@synthesize questionParser; +@synthesize plusParser; +@synthesize minusParser; +@synthesize timesParser; +@synthesize divParser; +@synthesize modParser; +@end diff --git a/test/.svn/text-base/TDJavaScriptParserTest.h.svn-base b/test/.svn/text-base/TDJavaScriptParserTest.h.svn-base new file mode 100644 index 0000000..ddc1e22 --- /dev/null +++ b/test/.svn/text-base/TDJavaScriptParserTest.h.svn-base @@ -0,0 +1,19 @@ +// +// PKJavaScriptParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 3/22/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "TDJavaScriptParser.h" + +@interface TDJavaScriptParserTest : SenTestCase { + TDJavaScriptParser *jsp; + NSString *s; + PKTokenAssembly *a; + id res; +} + +@end diff --git a/test/.svn/text-base/TDJavaScriptParserTest.m.svn-base b/test/.svn/text-base/TDJavaScriptParserTest.m.svn-base new file mode 100644 index 0000000..ce6fb73 --- /dev/null +++ b/test/.svn/text-base/TDJavaScriptParserTest.m.svn-base @@ -0,0 +1,742 @@ +// +// PKJavaScriptParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 3/22/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDJavaScriptParserTest.h" + +@implementation TDJavaScriptParserTest + +- (void)setUp { + jsp = [TDJavaScriptParser parser]; +} + + +- (void)tearDown { + +} + + +- (void)testStmtParser { + s = @";"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.stmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[;];^"); + + s = @"{}"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.stmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[{, }]{/}^"); +} + + +- (void)testFunctionParser { + s = @"function"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.functionParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function]function^"); +} + + +- (void)testIdentifierParser { + s = @"foo"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.identifierParser bestMatchFor:a]; + TDEqualObjects([res description], @"[foo]foo^"); +} + + +- (void)testParamListOptParserParser { + s = @"a, b"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.paramListOptParser bestMatchFor:a]; + TDEqualObjects([res description], @"[a, ,, b]a/,/b^"); +} + + +- (void)testCompoundStmtParserParser { + s = @"{}"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.compoundStmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[{, }]{/}^"); +} + + +- (void)testFuncParser { + s = @"function foo(a, b) {}"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.funcParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function, foo, (, a, ,, b, ), {, }]function/foo/(/a/,/b/)/{/}^"); + + s = @"function foo(a, b) { return a + b; }"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.funcParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function, foo, (, a, ,, b, ), {, return, a, +, b, ;, }]function/foo/(/a/,/b/)/{/return/a/+/b/;/}^"); + + s = @"function foo(a, b) { a++; b--; return a + b; }"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.funcParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function, foo, (, a, ,, b, ), {, a, ++, ;, b, --, ;, return, a, +, b, ;, }]function/foo/(/a/,/b/)/{/a/++/;/b/--/;/return/a/+/b/;/}^"); + + s = @"function foo(a, b) { a++; b--; return a + b; }"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.elementParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function, foo, (, a, ,, b, ), {, a, ++, ;, b, --, ;, return, a, +, b, ;, }]function/foo/(/a/,/b/)/{/a/++/;/b/--/;/return/a/+/b/;/}^"); +} + + +- (void)testBitwiseOrExprParser { + s = @"true"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.bitwiseOrExprParser bestMatchFor:a]; + TDEqualObjects([res description], @"[true]true^"); +} + + +- (void)testAndBitwiseOrExprParser { + s = @"&& true"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.andBitwiseOrExprParser bestMatchFor:a]; + TDEqualObjects([res description], @"[&&, true]&&/true^"); +} + + +- (void)testParamListParser { + s = @"baz, bat"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.paramListParser bestMatchFor:a]; + TDEqualObjects([res description], @"[baz, ,, bat]baz/,/bat^"); + + s = @"foo,bar,c_str"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.paramListParser bestMatchFor:a]; + TDEqualObjects([res description], @"[foo, ,, bar, ,, c_str]foo/,/bar/,/c_str^"); + + s = @"_x, __y"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.paramListParser bestMatchFor:a]; + TDEqualObjects([res description], @"[_x, ,, __y]_x/,/__y^"); +} + + +- (void)testCommaIdentifierParser { + s = @", foo"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.commaIdentifierParser bestMatchFor:a]; + TDEqualObjects([res description], @"[,, foo],/foo^"); + + s = @" ,bar"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.commaIdentifierParser bestMatchFor:a]; + TDEqualObjects([res description], @"[,, bar],/bar^"); +} + + +- (void)testBreakStmtParser { + s = @"break;"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.breakStmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[break, ;]break/;^"); +} + + +- (void)testContinueStmtParser { + s = @"continue;"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.continueStmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[continue, ;]continue/;^"); +} + + +- (void)testAssignmentOpParser { + s = @"="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.assignmentOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[=]=^"); + + s = @"*="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.assignmentOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[*=]*=^"); + + s = @"%="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.assignmentOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[%=]%=^"); + + s = @">>>="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.assignmentOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[>>>=]>>>=^"); +} + + +- (void)testRelationalOpParser { + s = @"<="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.relationalOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[<=]<=^"); + + s = @"instanceof"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.relationalOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[instanceof]instanceof^"); +} + + +- (void)testEqualityOpParser { + s = @"=="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.equalityOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[==]==^"); + + s = @"!=="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.equalityOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[!==]!==^"); + + s = @"==="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.equalityOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[===]===^"); +} + + +- (void)testForParenParser { + s = @"for ("; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.forParenParser bestMatchFor:a]; + TDEqualObjects([res description], @"[for, (]for/(^"); + + s = @"for("; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.forParenParser bestMatchFor:a]; + TDEqualObjects([res description], @"[for, (]for/(^"); +} + + +- (void)testExprOptParser { + s = @"true"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.exprOptParser bestMatchFor:a]; + TDEqualObjects([res description], @"[true]true^"); +} + + +- (void)testForBeginParenStmtParser { + s = @"for(1"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.forBeginParser bestMatchFor:a]; + TDEqualObjects([res description], @"[for, (, 1]for/(/1^"); + + s = @";"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.semiParser bestMatchFor:a]; + TDEqualObjects([res description], @"[;];^"); + + s = @"3<2"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.exprOptParser bestMatchFor:a]; + TDEqualObjects([res description], @"[3, <, 2]3/ + +@interface TDJsonParser : PKAlternation { + BOOL shouldAssemble; + PKParser *stringParser; + PKParser *numberParser; + PKParser *nullParser; + PKCollectionParser *booleanParser; + PKCollectionParser *arrayParser; + PKCollectionParser *objectParser; + PKCollectionParser *valueParser; + PKCollectionParser *commaValueParser; + PKCollectionParser *propertyParser; + PKCollectionParser *commaPropertyParser; + + PKToken *curly; + PKToken *bracket; +} + +- (id)initWithIntentToAssemble:(BOOL)shouldAssemble; + +- (id)parse:(NSString *)s; + +@property (nonatomic, retain) PKParser *stringParser; +@property (nonatomic, retain) PKParser *numberParser; +@property (nonatomic, retain) PKParser *nullParser; +@property (nonatomic, retain) PKCollectionParser *booleanParser; +@property (nonatomic, retain) PKCollectionParser *arrayParser; +@property (nonatomic, retain) PKCollectionParser *objectParser; +@property (nonatomic, retain) PKCollectionParser *valueParser; +@property (nonatomic, retain) PKCollectionParser *commaValueParser; +@property (nonatomic, retain) PKCollectionParser *propertyParser; +@property (nonatomic, retain) PKCollectionParser *commaPropertyParser; +@end \ No newline at end of file diff --git a/test/.svn/text-base/TDJsonParser.m.svn-base b/test/.svn/text-base/TDJsonParser.m.svn-base new file mode 100644 index 0000000..dc3ef74 --- /dev/null +++ b/test/.svn/text-base/TDJsonParser.m.svn-base @@ -0,0 +1,316 @@ +// +// PKJsonParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/18/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDJsonParser.h" +#import "ParseKit.h" +#import "NSString+ParseKitAdditions.h" + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface PKCollectionParser () +@property (nonatomic, readwrite, retain) NSMutableArray *subparsers; +@end + +@interface TDJsonParser () +@property (nonatomic, retain) PKToken *curly; +@property (nonatomic, retain) PKToken *bracket; +@end + +@implementation TDJsonParser + +- (id)init { + return [self initWithIntentToAssemble:YES]; +} + + +- (id)initWithIntentToAssemble:(BOOL)yn { + if (self = [super init]) { + shouldAssemble = yn; + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.0]; + self.bracket = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"[" floatValue:0.0]; + + self.tokenizer = [PKTokenizer tokenizer]; + [self.tokenizer setTokenizerState:self.tokenizer.symbolState from: '/' to: '/']; // JSON doesn't have slash slash or slash star comments + [self.tokenizer setTokenizerState:self.tokenizer.symbolState from: '\'' to: '\'']; // JSON does not have single quoted strings + + [self add:self.objectParser]; + [self add:self.arrayParser]; + } + return self; +} + + +- (void)dealloc { + // yikes. this is necessary to prevent a very nasty retain cycle leak. + // to be safe, release the subparsers of all collection parsers (as they may have retain cycles in complex grammars like this one) + // technically i only need to release the valueParser.subparers in this case, but better to be paranoid than to leak. + booleanParser.subparsers = nil; + arrayParser.subparsers = nil; + objectParser.subparsers = nil; + valueParser.subparsers = nil; + commaValueParser.subparsers = nil; + propertyParser.subparsers = nil; + commaPropertyParser.subparsers = nil; + + self.tokenizer = nil; + self.stringParser = nil; + self.numberParser = nil; + self.nullParser = nil; + self.booleanParser = nil; + self.arrayParser = nil; + self.objectParser = nil; + self.valueParser = nil; + self.propertyParser = nil; + self.commaPropertyParser = nil; + self.commaValueParser = nil; + self.curly = nil; + self.bracket = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + self.tokenizer.string = s; + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:self.tokenizer]; + + PKAssembly *result = [self completeMatchFor:a]; + return [result pop]; +} + + +- (PKParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKQuotedString quotedString]; + if (shouldAssemble) { + [stringParser setAssembler:self selector:@selector(didMatchString:)]; + } + } + return stringParser; +} + + +- (PKParser *)numberParser { + if (!numberParser) { + self.numberParser = [PKNumber number]; + if (shouldAssemble) { + [numberParser setAssembler:self selector:@selector(didMatchNumber:)]; + } + } + return numberParser; +} + + +- (PKParser *)nullParser { + if (!nullParser) { + self.nullParser = [[PKLiteral literalWithString:@"null"] discard]; + if (shouldAssemble) { + [nullParser setAssembler:self selector:@selector(didMatchNull:)]; + } + } + return nullParser; +} + + +- (PKCollectionParser *)booleanParser { + if (!booleanParser) { + self.booleanParser = [PKAlternation alternation]; + [booleanParser add:[PKLiteral literalWithString:@"true"]]; + [booleanParser add:[PKLiteral literalWithString:@"false"]]; + if (shouldAssemble) { + [booleanParser setAssembler:self selector:@selector(didMatchBoolean:)]; + } + } + return booleanParser; +} + + +- (PKCollectionParser *)arrayParser { + if (!arrayParser) { + + // array = '[' content ']' + // content = Empty | actualArray + // actualArray = value commaValue* + + PKTrack *actualArray = [PKTrack sequence]; + [actualArray add:self.valueParser]; + [actualArray add:[PKRepetition repetitionWithSubparser:self.commaValueParser]]; + + PKAlternation *content = [PKAlternation alternation]; + [content add:[PKEmpty empty]]; + [content add:actualArray]; + + self.arrayParser = [PKSequence sequence]; + [arrayParser add:[PKSymbol symbolWithString:@"["]]; // serves as fence + [arrayParser add:content]; + [arrayParser add:[[PKSymbol symbolWithString:@"]"] discard]]; + + if (shouldAssemble) { + [arrayParser setAssembler:self selector:@selector(didMatchArray:)]; + } + } + return arrayParser; +} + + +- (PKCollectionParser *)objectParser { + if (!objectParser) { + + // object = '{' content '}' + // content = Empty | actualObject + // actualObject = property commaProperty* + // property = QuotedString ':' value + // commaProperty = ',' property + + PKTrack *actualObject = [PKTrack sequence]; + [actualObject add:self.propertyParser]; + [actualObject add:[PKRepetition repetitionWithSubparser:self.commaPropertyParser]]; + + PKAlternation *content = [PKAlternation alternation]; + [content add:[PKEmpty empty]]; + [content add:actualObject]; + + self.objectParser = [PKSequence sequence]; + [objectParser add:[PKSymbol symbolWithString:@"{"]]; // serves as fence + [objectParser add:content]; + [objectParser add:[[PKSymbol symbolWithString:@"}"] discard]]; + + if (shouldAssemble) { + [objectParser setAssembler:self selector:@selector(didMatchObject:)]; + } + } + return objectParser; +} + + +- (PKCollectionParser *)valueParser { + if (!valueParser) { + self.valueParser = [PKAlternation alternation]; + [valueParser add:self.stringParser]; + [valueParser add:self.numberParser]; + [valueParser add:self.nullParser]; + [valueParser add:self.booleanParser]; + [valueParser add:self.arrayParser]; + [valueParser add:self.objectParser]; + } + return valueParser; +} + + +- (PKCollectionParser *)commaValueParser { + if (!commaValueParser) { + self.commaValueParser = [PKTrack sequence]; + [commaValueParser add:[[PKSymbol symbolWithString:@","] discard]]; + [commaValueParser add:self.valueParser]; + } + return commaValueParser; +} + + +- (PKCollectionParser *)propertyParser { + if (!propertyParser) { + self.propertyParser = [PKSequence sequence]; + [propertyParser add:[PKQuotedString quotedString]]; + [propertyParser add:[[PKSymbol symbolWithString:@":"] discard]]; + [propertyParser add:self.valueParser]; + if (shouldAssemble) { + [propertyParser setAssembler:self selector:@selector(didMatchProperty:)]; + } + } + return propertyParser; +} + + +- (PKCollectionParser *)commaPropertyParser { + if (!commaPropertyParser) { + self.commaPropertyParser = [PKTrack sequence]; + [commaPropertyParser add:[[PKSymbol symbolWithString:@","] discard]]; + [commaPropertyParser add:self.propertyParser]; + } + return commaPropertyParser; +} + + +- (void)didMatchNull:(PKAssembly *)a { + [a push:[NSNull null]]; +} + + +- (void)didMatchNumber:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchString:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[tok.stringValue stringByTrimmingQuotes]]; +} + + +- (void)didMatchBoolean:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithBool:[tok.stringValue isEqualToString:@"true"] ? YES : NO]]; +} + + +- (void)didMatchArray:(PKAssembly *)a { + NSArray *elements = [a objectsAbove:self.bracket]; + NSMutableArray *array = [NSMutableArray arrayWithCapacity:[elements count]]; + + for (id element in [elements reverseObjectEnumerator]) { + if (element) { + [array addObject:element]; + } + } + [a pop]; // pop the [ + [a push:array]; +} + + +- (void)didMatchObject:(PKAssembly *)a { + NSArray *elements = [a objectsAbove:self.curly]; + NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:[elements count] / 2.]; + + NSInteger i = 0; + for ( ; i < [elements count] - 1; i++) { + id value = [elements objectAtIndex:i++]; + NSString *key = [elements objectAtIndex:i]; + if (key && value) { + [d setObject:value forKey:key]; + } + } + + [a pop]; // pop the { + [a push:d]; +} + + +- (void)didMatchProperty:(PKAssembly *)a { + id value = [a pop]; + PKToken *tok = [a pop]; + NSString *key = [tok.stringValue stringByTrimmingQuotes]; + + [a push:key]; + [a push:value]; +} + +@synthesize stringParser; +@synthesize numberParser; +@synthesize nullParser; +@synthesize booleanParser; +@synthesize arrayParser; +@synthesize objectParser; +@synthesize valueParser; +@synthesize commaValueParser; +@synthesize propertyParser; +@synthesize commaPropertyParser; +@synthesize curly; +@synthesize bracket; +@end diff --git a/test/.svn/text-base/TDJsonParserTest.h.svn-base b/test/.svn/text-base/TDJsonParserTest.h.svn-base new file mode 100644 index 0000000..5867a36 --- /dev/null +++ b/test/.svn/text-base/TDJsonParserTest.h.svn-base @@ -0,0 +1,20 @@ +// +// PKJsonParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/17/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@class TDJsonParser; + +@interface TDJsonParserTest : SenTestCase { + TDJsonParser *p; + NSString *s; + PKAssembly *a; + PKAssembly *result; +} + +@end diff --git a/test/.svn/text-base/TDJsonParserTest.m.svn-base b/test/.svn/text-base/TDJsonParserTest.m.svn-base new file mode 100644 index 0000000..ba8bf24 --- /dev/null +++ b/test/.svn/text-base/TDJsonParserTest.m.svn-base @@ -0,0 +1,537 @@ +// +// PKJsonParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/17/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDJsonParserTest.h" +#import "TDJsonParser.h" +#import "TDFastJsonParser.h" + +@implementation TDJsonParserTest + +- (void)setUp { + p = [TDJsonParser parser]; +} + + +- (void)testForAppleBossResultTokenization { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKTokenizer *t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + while (eof != (tok = [t nextToken])) { + //NSLog(@"tok: %@", tok); + } +} + + +- (void)testForAppleBossResult { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + @try { + result = [p parse:s]; + } + @catch (NSException *e) { + //NSLog(@"\n\n\nexception:\n\n %@", [e reason]); + } + + //NSLog(@"result %@", result); +} + + +- (void)testEmptyString { + s = @""; + a = [PKTokenAssembly assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testNum { + s = @"456"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p numberParser] bestMatchFor:a]; + TDNotNil(result); + + TDEqualObjects(@"[456]456^", [result description]); + id obj = [result pop]; + TDNotNil(obj); + TDEqualObjects([NSNumber numberWithFloat:456], obj); + + + s = @"-3.47"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p numberParser] bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[-3.47]-3.47^", [result description]); + obj = [result pop]; + TDNotNil(obj); + TDEqualObjects([NSNumber numberWithFloat:-3.47], obj); +} + + +- (void)testString { + s = @"'foobar'"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p stringParser] bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foobar]'foobar'^", [result description]); + id obj = [result pop]; + TDNotNil(obj); + TDEqualObjects(@"foobar", obj); + + s = @"\"baz boo boo\""; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p stringParser] bestMatchFor:a]; + TDNotNil(result); + + TDEqualObjects(@"[baz boo boo]\"baz boo boo\"^", [result description]); + obj = [result pop]; + TDNotNil(obj); + TDEqualObjects(@"baz boo boo", obj); +} + + +- (void)testBoolean { + s = @"true"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p booleanParser] bestMatchFor:a]; + TDNotNil(result); + + TDEqualObjects(@"[1]true^", [result description]); + id obj = [result pop]; + TDNotNil(obj); + TDEqualObjects([NSNumber numberWithBool:YES], obj); + + s = @"false"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p booleanParser] bestMatchFor:a]; + TDNotNil(result); + + TDEqualObjects(@"[0]false^", [result description]); + obj = [result pop]; + TDNotNil(obj); + TDEqualObjects([NSNumber numberWithBool:NO], obj); +} + + +- (void)testArray { + s = @"[1, 2, 3]"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p arrayParser] bestMatchFor:a]; + + NSLog(@"result: %@", result); + TDNotNil(result); + id obj = [result pop]; + TDEquals((int)3, (int)[obj count]); + TDEqualObjects([NSNumber numberWithInteger:1], [obj objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInteger:2], [obj objectAtIndex:1]); + TDEqualObjects([NSNumber numberWithInteger:3], [obj objectAtIndex:2]); + TDEqualObjects(@"[][/1/,/2/,/3/]^", [result description]); + + s = @"[true, 'garlic jazz!', .888]"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p arrayParser] bestMatchFor:a]; + TDNotNil(result); + + //TDEqualObjects(@"[true, 'garlic jazz!', .888]true/'garlic jazz!'/.888^", [result description]); + obj = [result pop]; + TDEqualObjects([NSNumber numberWithBool:YES], [obj objectAtIndex:0]); + TDEqualObjects(@"garlic jazz!", [obj objectAtIndex:1]); + TDEqualObjects([NSNumber numberWithFloat:.888], [obj objectAtIndex:2]); + + s = @"[1, [2, [3, 4]]]"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p arrayParser] bestMatchFor:a]; + TDNotNil(result); + //NSLog(@"result: %@", [a stack]); + TDEqualObjects([NSNumber numberWithInteger:1], [obj objectAtIndex:0]); +} + + +- (void)testObject { + s = @"{'key': 'value'}"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p objectParser] bestMatchFor:a]; + TDNotNil(result); + + id obj = [result pop]; + TDEqualObjects([obj objectForKey:@"key"], @"value"); + + s = @"{'foo': false, 'bar': true, \"baz\": -9.457}"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p objectParser] bestMatchFor:a]; + TDNotNil(result); + + obj = [result pop]; + TDEqualObjects([obj objectForKey:@"foo"], [NSNumber numberWithBool:NO]); + TDEqualObjects([obj objectForKey:@"bar"], [NSNumber numberWithBool:YES]); + TDEqualObjects([obj objectForKey:@"baz"], [NSNumber numberWithFloat:-9.457]); + + s = @"{'baz': {'foo': [1,2]}}"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p objectParser] bestMatchFor:a]; + TDNotNil(result); + + obj = [result pop]; + NSDictionary *dict = [obj objectForKey:@"baz"]; + TDTrue([dict isKindOfClass:[NSDictionary class]]); + NSArray *arr = [dict objectForKey:@"foo"]; + TDTrue([arr isKindOfClass:[NSArray class]]); + TDEqualObjects([NSNumber numberWithInteger:1], [arr objectAtIndex:0]); + + // TDEqualObjects(@"['baz', 'foo', 1, 2]'baz'/'foo'/1/2^", [result description]); +} + + +- (void)testCrunchBaseJsonParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDJsonParser *parser = [[[TDJsonParser alloc] init] autorelease]; + [parser parse:s]; +// id res = [parser parse:s]; + //NSLog(@"res %@", res); +} + + +- (void)testCrunchBaseJsonParserTokenization { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKTokenizer *t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + while (eof != (tok = [t nextToken])) { + //NSLog(@"tok: %@", tok); + } +} + + +- (void)testCrunchBaseJsonTokenParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDFastJsonParser *parser = [[[TDFastJsonParser alloc] init] autorelease]; + [parser parse:s]; + // id res = [parser parse:s]; + //NSLog(@"res %@", res); +} + + +- (void)testYahoo1 { + s = + @"{" + @"\"name\": \"Yahoo!\"," + @"\"permalink\": \"yahoo\"," + @"\"homepage_url\": \"http://www.yahoo.com\"," + @"\"blog_url\": \"http://yodel.yahoo.com/\"," + @"\"blog_feed_url\": \"http://ycorpblog.com/feed/\"," + @"\"category_code\": \"web\"," + @"\"number_of_employees\": 13600," + @"\"founded_year\": 1994," + @"\"founded_month\": null," + @"\"founded_day\": null," + @"\"deadpooled_year\": null," + @"\"deadpooled_month\": null," + @"\"deadpooled_day\": null," + @"\"deadpooled_url\": null," + @"\"tag_list\": \"search, portal, webmail, photos\"," + @"\"email_address\": \"\"," + @"\"phone_number\": \"(408) 349-3300\"" + @"}"; + result = [p parse:s]; + //NSLog(@"result %@", result); + TDNotNil(result); + id d = result; + TDNotNil(d); + TDTrue([d isKindOfClass:[NSDictionary class]]); + TDEqualObjects([d objectForKey:@"name"], @"Yahoo!"); + TDEqualObjects([d objectForKey:@"permalink"], @"yahoo"); + TDEqualObjects([d objectForKey:@"homepage_url"], @"http://www.yahoo.com"); + TDEqualObjects([d objectForKey:@"blog_url"], @"http://yodel.yahoo.com/"); + TDEqualObjects([d objectForKey:@"blog_feed_url"], @"http://ycorpblog.com/feed/"); + TDEqualObjects([d objectForKey:@"category_code"], @"web"); + TDEqualObjects([d objectForKey:@"number_of_employees"], [NSNumber numberWithInteger:13600]); + TDEqualObjects([d objectForKey:@"founded_year"], [NSNumber numberWithInteger:1994]); + TDEqualObjects([d objectForKey:@"founded_month"], [NSNull null]); + TDEqualObjects([d objectForKey:@"founded_day"], [NSNull null]); + TDEqualObjects([d objectForKey:@"deadpooled_year"], [NSNull null]); + TDEqualObjects([d objectForKey:@"deadpooled_month"], [NSNull null]); + TDEqualObjects([d objectForKey:@"deadpooled_day"], [NSNull null]); + TDEqualObjects([d objectForKey:@"deadpooled_url"], [NSNull null]); + TDEqualObjects([d objectForKey:@"tag_list"], @"search, portal, webmail, photos"); + TDEqualObjects([d objectForKey:@"email_address"], @""); + TDEqualObjects([d objectForKey:@"phone_number"], @"(408) 349-3300"); +} + + +- (void)testYahoo2 { + s = @"{\"image\":" + @" {\"available_sizes\":" + @" [[[150, 37]," + @" \"assets/images/resized/0001/0836/10836v1-max-250x150.png\"]," + @" [[200, 50]," + @" \"assets/images/resized/0001/0836/10836v1-max-250x250.png\"]," + @" [[200, 50]," + @" \"assets/images/resized/0001/0836/10836v1-max-450x450.png\"]]," + @" \"attribution\": null}" + @"}"; + result = [p parse:s]; + //NSLog(@"result %@", result); + + TDNotNil(result); + + id d = result; + TDNotNil(d); + TDTrue([d isKindOfClass:[NSDictionary class]]); + + id image = [d objectForKey:@"image"]; + TDNotNil(image); + TDTrue([image isKindOfClass:[NSDictionary class]]); + + NSArray *sizes = [image objectForKey:@"available_sizes"]; + TDNotNil(sizes); + TDTrue([sizes isKindOfClass:[NSArray class]]); + + TDEquals(3, (int)[sizes count]); + + NSArray *first = [sizes objectAtIndex:0]; + TDNotNil(first); + TDTrue([first isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[first count]); + + NSArray *firstKey = [first objectAtIndex:0]; + TDNotNil(firstKey); + TDTrue([firstKey isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[firstKey count]); + TDEqualObjects([NSNumber numberWithInteger:150], [firstKey objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInteger:37], [firstKey objectAtIndex:1]); + + NSArray *second = [sizes objectAtIndex:1]; + TDNotNil(second); + TDTrue([second isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[second count]); + + NSArray *secondKey = [second objectAtIndex:0]; + TDNotNil(secondKey); + TDTrue([secondKey isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[secondKey count]); + TDEqualObjects([NSNumber numberWithInteger:200], [secondKey objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInteger:50], [secondKey objectAtIndex:1]); + + NSArray *third = [sizes objectAtIndex:2]; + TDNotNil(third); + TDTrue([third isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[third count]); + + NSArray *thirdKey = [third objectAtIndex:0]; + TDNotNil(thirdKey); + TDTrue([thirdKey isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[thirdKey count]); + TDEqualObjects([NSNumber numberWithInteger:200], [thirdKey objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInteger:50], [thirdKey objectAtIndex:1]); + + +// TDEqualObjects([d objectForKey:@"name"], @"Yahoo!"); +} + + +- (void)testYahoo3 { + s = + @"{\"products\":" + @"[" + @"{\"name\": \"Yahoo.com\", \"permalink\": \"yahoo-com\"}," + @"{\"name\": \"Yahoo! Mail\", \"permalink\": \"yahoo-mail\"}," + @"{\"name\": \"Yahoo! Search\", \"permalink\": \"yahoo-search\"}," + @"{\"name\": \"Yahoo! Directory\", \"permalink\": \"yahoo-directory\"}," + @"{\"name\": \"Yahoo! Finance\", \"permalink\": \"yahoo-finance\"}," + @"{\"name\": \"My Yahoo\", \"permalink\": \"my-yahoo\"}," + @"{\"name\": \"Yahoo! News\", \"permalink\": \"yahoo-news\"}," + @"{\"name\": \"Yahoo! Groups\", \"permalink\": \"yahoo-groups\"}," + @"{\"name\": \"Yahoo! Messenger\", \"permalink\": \"yahoo-messenger\"}," + @"{\"name\": \"Yahoo! Games\", \"permalink\": \"yahoo-games\"}," + @"{\"name\": \"Yahoo! People Search\", \"permalink\": \"yahoo-people-search\"}," + @"{\"name\": \"Yahoo! Movies\", \"permalink\": \"yahoo-movies\"}," + @"{\"name\": \"Yahoo! Weather\", \"permalink\": \"yahoo-weather\"}," + @"{\"name\": \"Yahoo! Video\", \"permalink\": \"yahoo-video\"}," + @"{\"name\": \"Yahoo! Music\", \"permalink\": \"yahoo-music\"}," + @"{\"name\": \"Yahoo! Sports\", \"permalink\": \"yahoo-sports\"}," + @"{\"name\": \"Yahoo! Maps\", \"permalink\": \"yahoo-maps\"}," + @"{\"name\": \"Yahoo! Auctions\", \"permalink\": \"yahoo-auctions\"}," + @"{\"name\": \"Yahoo! Widgets\", \"permalink\": \"yahoo-widgets\"}," + @"{\"name\": \"Yahoo! Shopping\", \"permalink\": \"yahoo-shopping\"}," + @"{\"name\": \"Yahoo! Real Estate\", \"permalink\": \"yahoo-real-estate\"}," + @"{\"name\": \"Yahoo! Travel\", \"permalink\": \"yahoo-travel\"}," + @"{\"name\": \"Yahoo! Classifieds\", \"permalink\": \"yahoo-classifieds\"}," + @"{\"name\": \"Yahoo! Answers\", \"permalink\": \"yahoo-answers\"}," + @"{\"name\": \"Yahoo! Mobile\", \"permalink\": \"yahoo-mobile\"}," + @"{\"name\": \"Yahoo! Buzz\", \"permalink\": \"yahoo-buzz\"}," + @"{\"name\": \"Yahoo! Open Search Platform\", \"permalink\": \"yahoo-open-search-platform\"}," + @"{\"name\": \"Fire Eagle\", \"permalink\": \"fireeagle\"}," + @"{\"name\": \"Shine\", \"permalink\": \"shine\"}," + @"{\"name\": \"Yahoo! Shortcuts\", \"permalink\": \"yahoo-shortcuts\"}" + @"]" + @"}"; + result = [p parse:s]; + //NSLog(@"result %@", result); + + TDNotNil(result); + + id d = result; + TDNotNil(d); + TDTrue([d isKindOfClass:[NSDictionary class]]); + + NSArray *products = [d objectForKey:@"products"]; + TDNotNil(products); + TDTrue([products isKindOfClass:[NSArray class]]); +} + + +- (void)testYahoo4 { + s = @"[" + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1" + @"]"; + + p = [[[TDFastJsonParser alloc] init] autorelease]; + result = [p parse:s]; + //NSLog(@"result %@", result); + + TDNotNil(result); + + id d = result; + TDNotNil(d); + TDTrue([d isKindOfClass:[NSArray class]]); + +// NSArray *products = [d objectForKey:@"products"]; +// TDNotNil(products); +// TDTrue([products isKindOfClass:[NSArray class]]); +} +@end diff --git a/test/.svn/text-base/TDLetterTest.h.svn-base b/test/.svn/text-base/TDLetterTest.h.svn-base new file mode 100644 index 0000000..530ef93 --- /dev/null +++ b/test/.svn/text-base/TDLetterTest.h.svn-base @@ -0,0 +1,19 @@ +// +// PKLetterTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + + +@interface TDLetterTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + PKChar *p; + PKAssembly *result; +} + +@end diff --git a/test/.svn/text-base/TDLetterTest.m.svn-base b/test/.svn/text-base/TDLetterTest.m.svn-base new file mode 100644 index 0000000..2075dd5 --- /dev/null +++ b/test/.svn/text-base/TDLetterTest.m.svn-base @@ -0,0 +1,59 @@ +// +// PKLetterTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDLetterTest.h" + +@interface PKAssembly () +- (BOOL)hasMore; +@end + +@implementation TDLetterTest + +- (void)test123 { + s = @"123"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^123", [a description]); + p = [PKLetter letter]; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDNil(result); + TDTrue([a hasMore]); +} + + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKLetter letter]; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a]a^bc", [result description]); + TDTrue([result hasMore]); +} + + +- (void)testRepetition { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKLetter letter]; + PKParser *r = [PKRepetition repetitionWithSubparser:p]; + + result = [r bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a, b, c]abc^", [result description]); + TDFalse([result hasMore]); +} + +@end diff --git a/test/.svn/text-base/TDLiteralTest.h.svn-base b/test/.svn/text-base/TDLiteralTest.h.svn-base new file mode 100644 index 0000000..650053d --- /dev/null +++ b/test/.svn/text-base/TDLiteralTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKLiteralTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDLiteralTest : SenTestCase { + PKParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDLiteralTest.m.svn-base b/test/.svn/text-base/TDLiteralTest.m.svn-base new file mode 100644 index 0000000..e9a6c24 --- /dev/null +++ b/test/.svn/text-base/TDLiteralTest.m.svn-base @@ -0,0 +1,91 @@ +// +// PKLiteralTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDLiteralTest.h" + +@implementation TDLiteralTest + +- (void)tearDown { + [a release]; +} + +- (void)testTrueCompleteMatchForLiteral123 { + s = @"123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + NSLog(@"a: %@", a); + + p = [PKNumber number]; + PKAssembly *result = [p completeMatchFor:a]; + + // -[PKParser completeMatchFor:] + // -[PKParser bestMatchFor:] + // -[PKParser matchAndAssemble:] + // -[PKTerminal allMatchesFor:] + // -[PKTerminal matchOneAssembly:] + // -[PKLiteral qualifies:] + // -[PKParser best:] + + NSLog(@"result: %@", result); + TDNotNil(result); + TDEqualObjects(@"[123]123^", [result description]); +} + + +- (void)testFalseCompleteMatchForLiteral123 { + s = @"1234"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKLiteral literalWithString:@"123"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); + TDEqualObjects(@"[]^1234", [a description]); +} + + +- (void)testTrueCompleteMatchForLiteralFoo { + s = @"Foo"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKLiteral literalWithString:@"Foo"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[Foo]Foo^", [result description]); +} + + +- (void)testFalseCompleteMatchForLiteralFoo { + s = @"Foo"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKLiteral literalWithString:@"foo"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testFalseCompleteMatchForCaseInsensitiveLiteralFoo { + s = @"Fool"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKCaseInsensitiveLiteral literalWithString:@"Foo"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testTrueCompleteMatchForCaseInsensitiveLiteralFoo { + s = @"Foo"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKCaseInsensitiveLiteral literalWithString:@"foo"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[Foo]Foo^", [result description]); +} + +@end diff --git a/test/.svn/text-base/TDLowercaseWordTest.h.svn-base b/test/.svn/text-base/TDLowercaseWordTest.h.svn-base new file mode 100644 index 0000000..ae4ca31 --- /dev/null +++ b/test/.svn/text-base/TDLowercaseWordTest.h.svn-base @@ -0,0 +1,15 @@ +// +// PKLowercaseWordTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDLowercaseWordTest : SenTestCase { + +} +@end + diff --git a/test/.svn/text-base/TDLowercaseWordTest.m.svn-base b/test/.svn/text-base/TDLowercaseWordTest.m.svn-base new file mode 100644 index 0000000..c28182b --- /dev/null +++ b/test/.svn/text-base/TDLowercaseWordTest.m.svn-base @@ -0,0 +1,57 @@ +// +// PKLowercaseWordTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDLowercaseWordTest.h" + +@implementation TDLowercaseWordTest + +- (void)testFoobar { + NSString *s = @"Foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKLowercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)testfoobar { + NSString *s = @"foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKLowercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foobar]foobar^", [result description]); +} + + +- (void)test123 { + NSString *s = @"123"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKLowercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)testPercentFoobar { + NSString *s = @"%Foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKLowercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + +@end diff --git a/test/.svn/text-base/TDMiniCSSAssembler.h.svn-base b/test/.svn/text-base/TDMiniCSSAssembler.h.svn-base new file mode 100644 index 0000000..880c528 --- /dev/null +++ b/test/.svn/text-base/TDMiniCSSAssembler.h.svn-base @@ -0,0 +1,21 @@ +// +// PKMiniCSSAssembler.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/23/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKToken; + +@interface TDMiniCSSAssembler : NSObject { + NSMutableDictionary *attributes; + PKToken *paren; + PKToken *curly; +} +@property (nonatomic, retain) NSMutableDictionary *attributes; +@property (nonatomic, retain) PKToken *paren; +@property (nonatomic, retain) PKToken *curly; +@end diff --git a/test/.svn/text-base/TDMiniCSSAssembler.m.svn-base b/test/.svn/text-base/TDMiniCSSAssembler.m.svn-base new file mode 100644 index 0000000..2ac843b --- /dev/null +++ b/test/.svn/text-base/TDMiniCSSAssembler.m.svn-base @@ -0,0 +1,184 @@ +// +// PKMiniCSSAssembler.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/23/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDMiniCSSAssembler.h" +#import "NSString+ParseKitAdditions.h" +#import + +@interface TDMiniCSSAssembler () +- (void)gatherPropertiesIn:(id)props; +@end + +@implementation TDMiniCSSAssembler + +- (id)init { + if (self = [super init]) { + self.attributes = [NSMutableDictionary dictionary]; + self.paren = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"(" floatValue:0.0]; + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.0]; + } + return self; +} + + +- (void)dealloc { + self.attributes = nil; + self.paren = nil; + self.curly = nil; + [super dealloc]; +} + + +#pragma mark - +#pragma mark Assembler Callbacks + +// @start = ruleset*; +// ruleset = selector '{' decls >'}'; +// selector = LowercaseWord; // forcing selectors to be lowercase words for use in a future syntax-highlight framework where i want that +// decls = Empty | actualDecls; +// actualDecls = decl decl*; +// decl = property >':' expr >';'?; +// property = 'color' | 'background-color' | 'font-family' | 'font-size'; +// expr = pixelValue | rgb | string | constants; +// pixelValue = Number >'px'; +// rgb = >'rgb' '(' Number >',' Number >',' Number >')'; +// string = QuotedString; +// constants = 'bold' | 'normal' | 'italic'; + +- (void)didMatchProperty:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:tok.stringValue]; +} + + +- (void)didMatchString:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[tok.stringValue stringByTrimmingQuotes]]; +} + + +- (void)didMatchConstant:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:tok.stringValue]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchPixelValue:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchRgb:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:paren]; + [a pop]; // discard '(' + CGFloat blue = [(PKToken *)[objs objectAtIndex:0] floatValue]/255.0; + CGFloat green = [(PKToken *)[objs objectAtIndex:1] floatValue]/255.0; + CGFloat red = [(PKToken *)[objs objectAtIndex:2] floatValue]/255.0; + [a push:[NSColor colorWithDeviceRed:red green:green blue:blue alpha:1.0]]; +} + + +- (void)didMatchActualDecls:(PKAssembly *)a { + id d = [NSMutableDictionary dictionary]; + NSArray *objs = [a objectsAbove:curly]; + [a pop]; // discard curly + + NSInteger i = 0; + NSInteger count = [objs count]; + for ( ; i < count - 1; i++) { + id propVal = [objs objectAtIndex:i]; + id propName = [objs objectAtIndex:++i]; + [d setObject:propVal forKey:propName]; + } + + [a push:d]; +} + + +- (void)didMatchRuleset:(PKAssembly *)a { + id props = [a pop]; + [self gatherPropertiesIn:props]; + + for (PKToken *selectorTok in [a objectsAbove:nil]) { + NSString *selector = selectorTok.stringValue; + [attributes setObject:props forKey:selector]; + } +} + + +- (void)gatherPropertiesIn:(id)props { + NSColor *color = [props objectForKey:@"color"]; + if (!color) { + color = [NSColor blackColor]; + } + [props setObject:color forKey:NSForegroundColorAttributeName]; + [props removeObjectForKey:@"color"]; + + color = [props objectForKey:@"background-color"]; + if (!color) { + color = [NSColor whiteColor]; + } + [props setObject:color forKey:NSBackgroundColorAttributeName]; + [props removeObjectForKey:@"background-color"]; + + NSString *fontFamily = [props objectForKey:@"font-family"]; + if (![fontFamily length]) { + fontFamily = @"Monaco"; + } + + CGFloat fontSize = [[props objectForKey:@"font-size"] doubleValue]; + if (fontSize < 9.0) { + fontSize = 9.0; + } + + NSFont *font = [NSFont fontWithName:fontFamily size:fontSize]; + [props setObject:font forKey:NSFontAttributeName]; + [props removeObjectForKey:@"font-family"]; + [props removeObjectForKey:@"font-size"]; +} + +@synthesize attributes; +@synthesize paren; +@synthesize curly; +@end + + +//- (NSUInteger)hexValueFor:(NSString *)inStr { +// NSUInteger i = [[inStr substringWithRange:NSMakeRange(0, 1)] integerValue]; +// i = i *= 16; +// i += [[inStr substringWithRange:NSMakeRange(1, 1)] integerValue]; +// return i; +//} +// +//- (void)didMatchHexcolor:(PKAssembly *)a { +// PKToken *tok = [a pop]; +// NSString *s = tok.stringValue; +// NSColor *color = nil; +// +// if (6 == [s length]) { +// NSString *redStr = [s substringWithRange:NSMakeRange(0, 2)]; +// NSString *greenStr = [s substringWithRange:NSMakeRange(2, 2)]; +// NSString *blueStr = [s substringWithRange:NSMakeRange(4, 2)]; +// +// NSUInteger red = [self hexValueFor:redStr]; +// NSUInteger green = [self hexValueFor:greenStr]; +// NSUInteger blue = [self hexValueFor:blueStr]; +// +// color = [NSColor colorWithDeviceRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1.0]; +// } else { +// color = [NSColor magentaColor]; // signals incorrect value in stylesheet +// } +// [a push:color]; +//} diff --git a/test/.svn/text-base/TDMiniCSSAssemblerTest.h.svn-base b/test/.svn/text-base/TDMiniCSSAssemblerTest.h.svn-base new file mode 100644 index 0000000..8953d05 --- /dev/null +++ b/test/.svn/text-base/TDMiniCSSAssemblerTest.h.svn-base @@ -0,0 +1,23 @@ +// +// PKMiniCSSAssemblerTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" +#import "TDMiniCSSAssembler.h" + +@interface TDMiniCSSAssemblerTest : SenTestCase { + NSString *path; + NSString *grammarString; + NSString *s; + TDMiniCSSAssembler *ass; + PKParserFactory *factory; + PKParser *lp; + PKAssembly *a; +} + +@end diff --git a/test/.svn/text-base/TDMiniCSSAssemblerTest.m.svn-base b/test/.svn/text-base/TDMiniCSSAssemblerTest.m.svn-base new file mode 100644 index 0000000..f166f0d --- /dev/null +++ b/test/.svn/text-base/TDMiniCSSAssemblerTest.m.svn-base @@ -0,0 +1,233 @@ +// +// PKMiniCSSAssemblerTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDMiniCSSAssemblerTest.h" + +@implementation TDMiniCSSAssemblerTest + +- (void)setUp { + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + ass = [[TDMiniCSSAssembler alloc] init]; + factory = [PKParserFactory factory]; + lp = [factory parserFromGrammar:grammarString assembler:ass]; +} + + +- (void)tearDown { + [ass release]; +} + + +- (void)testColor { + TDNotNil(lp); + + s = @"bar { color:rgb(10, 200, 30); }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]bar/{/color/:/rgb/(/10/,/200/,/30/)/;/}^", [a description]); + TDNotNil(ass.attributes); + id props = [ass.attributes objectForKey:@"bar"]; + TDNotNil(props); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); +} + + +- (void)testMultiSelectorColor { + TDNotNil(lp); + + s = @"foo, bar { color:rgb(10, 200, 30); }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]foo/,/bar/{/color/:/rgb/(/10/,/200/,/30/)/;/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"bar"]; + TDNotNil(props); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); + + props = [ass.attributes objectForKey:@"foo"]; + TDNotNil(props); + + color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); +} + + +- (void)testBackgroundColor { + TDNotNil(lp); + + s = @"foo { background-color:rgb(255.0, 0.0, 255.0) }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]foo/{/background-color/:/rgb/(/255.0/,/0.0/,/255.0/)/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"foo"]; + TDNotNil(props); + + NSColor *color = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(255.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(0.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(255.0/255.0), 0.001, @""); +} + + +- (void)testFontSize { + TDNotNil(lp); + + s = @"decl { font-size:12px }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]decl/{/font-size/:/12/px/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"decl"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEquals((CGFloat)[font pointSize], (CGFloat)12.0); + TDEqualObjects([font familyName], @"Monaco"); +} + + +- (void)testSmallFontSize { + TDNotNil(lp); + + s = @"decl { font-size:8px }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]decl/{/font-size/:/8/px/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"decl"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEquals((CGFloat)[font pointSize], (CGFloat)9.0); + TDEqualObjects([font familyName], @"Monaco"); +} + + +- (void)testFont { + TDNotNil(lp); + + s = @"expr { font-size:16px; font-family:'Helvetica' }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]expr/{/font-size/:/16/px/;/font-family/:/'Helvetica'/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"expr"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Helvetica"); + TDEquals((CGFloat)[font pointSize], (CGFloat)16.0); +} + + +- (void)testAll { + TDNotNil(lp); + + s = @"expr { font-size:9.0px; font-family:'Courier'; background-color:rgb(255.0, 0.0, 255.0) ; color:rgb(10, 200, 30);}"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]expr/{/font-size/:/9.0/px/;/font-family/:/'Courier'/;/background-color/:/rgb/(/255.0/,/0.0/,/255.0/)/;/color/:/rgb/(/10/,/200/,/30/)/;/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"expr"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Courier"); + TDEquals((CGFloat)[font pointSize], (CGFloat)9.0); + + NSColor *bgColor = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(bgColor); + STAssertEqualsWithAccuracy([bgColor redComponent], (CGFloat)(255.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor greenComponent], (CGFloat)(0.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor blueComponent], (CGFloat)(255.0/255.0), 0.001, @""); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); +} + + +- (void)testMultiAll { + TDNotNil(lp); + + s = @"expr, decl { font-size:9.0px; font-family:'Courier'; background-color:rgb(255.0, 0.0, 255.0) ; color:rgb(10, 200, 30);}"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]expr/,/decl/{/font-size/:/9.0/px/;/font-family/:/'Courier'/;/background-color/:/rgb/(/255.0/,/0.0/,/255.0/)/;/color/:/rgb/(/10/,/200/,/30/)/;/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"expr"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Courier"); + TDEquals((CGFloat)[font pointSize], (CGFloat)9.0); + + NSColor *bgColor = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(bgColor); + STAssertEqualsWithAccuracy([bgColor redComponent], (CGFloat)(255.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor greenComponent], (CGFloat)(0.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor blueComponent], (CGFloat)(255.0/255.0), 0.001, @""); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); + + props = [ass.attributes objectForKey:@"decl"]; + TDNotNil(props); + + font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Courier"); + TDEquals((CGFloat)[font pointSize], (CGFloat)9.0); + + bgColor = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(bgColor); + STAssertEqualsWithAccuracy([bgColor redComponent], (CGFloat)(255.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor greenComponent], (CGFloat)(0.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor blueComponent], (CGFloat)(255.0/255.0), 0.001, @""); + + color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); +} + +@end diff --git a/test/.svn/text-base/TDNCName.h.svn-base b/test/.svn/text-base/TDNCName.h.svn-base new file mode 100644 index 0000000..9717f88 --- /dev/null +++ b/test/.svn/text-base/TDNCName.h.svn-base @@ -0,0 +1,22 @@ +// +// PKNCName.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKTerminal.h" +#import "PKToken.h" + +extern const NSInteger PKTokenTypeNCName; + +@interface PKToken (NCNameAdditions) +@property (readonly, getter=isNCName) BOOL NCName; +@end + +@interface TDNCName : PKTerminal { + +} ++ (id)NCName; +@end diff --git a/test/.svn/text-base/TDNCName.m.svn-base b/test/.svn/text-base/TDNCName.m.svn-base new file mode 100644 index 0000000..c5a1ad7 --- /dev/null +++ b/test/.svn/text-base/TDNCName.m.svn-base @@ -0,0 +1,33 @@ +// +// PKNCName.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDNCName.h" + +const NSInteger PKTokenTypeNCName = 300; + +@implementation PKToken (NCNameAdditions) + +- (BOOL)isNCName { + return self.tokenType == PKTokenTypeNCName; +} + +@end + +@implementation TDNCName + ++ (id)NCName { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isNCName; +} + +@end diff --git a/test/.svn/text-base/TDNCNameState.h.svn-base b/test/.svn/text-base/TDNCNameState.h.svn-base new file mode 100644 index 0000000..06505e7 --- /dev/null +++ b/test/.svn/text-base/TDNCNameState.h.svn-base @@ -0,0 +1,15 @@ +// +// PKNCNameState.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKTokenizerState.h" + +@interface TDNCNameState : PKTokenizerState { + +} + +@end diff --git a/test/.svn/text-base/TDNCNameState.m.svn-base b/test/.svn/text-base/TDNCNameState.m.svn-base new file mode 100644 index 0000000..149d65a --- /dev/null +++ b/test/.svn/text-base/TDNCNameState.m.svn-base @@ -0,0 +1,79 @@ +// +// PKNCNameState.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDNCNameState.h" +#import "PKTokenizer.h" +#import "PKReader.h" +#import "TDXmlToken.h" + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface TDNCNameState () ++ (BOOL)isNameChar:(PKUniChar)c; ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c; ++ (BOOL)isValidNonStartSymbolChar:(PKUniChar)c; +@end + +// NCName ::= (Letter | '_') (NameChar)* +@implementation TDNCNameState + +//- (BOOL)isWhitespace:(PKUniChar)c { +// return (' ' == c || '\n' == c || '\r' == c || '\t' == c); +//} + + +// NameChar ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender ++ (BOOL)isNameChar:(PKUniChar)c { + if (isalnum(c)) { + return YES; + } else if ([self isValidNonStartSymbolChar:c]) { + return YES; + } + // TODO CombiningChar & Extender + return NO; +} + + ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c { + return ('_' == c); +} + + ++ (BOOL)isValidNonStartSymbolChar:(PKUniChar)c { + return ('_' == c || '.' == c || '-' == c); +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + [self resetWithReader:r]; + + NSInteger c = cin; + do { + [self append:c]; + c = [r read]; + } while ([TDNCNameState isNameChar:c]); + + if (PKEOF != c) { + [r unread]; + } + + if ([[self bufferedString] length] == 1 && [TDNCNameState isValidStartSymbolChar:cin]) { + return [t.symbolState nextTokenFromReader:r startingWith:cin tokenizer:t]; + } else { +// return [[[TDXmlToken alloc] initWithTokenType:TDTT_NAME +// stringValue:[[stringbuf copy] autorelease] +// floatValue:0.0] autorelease]; + return nil; + } +} + +@end diff --git a/test/.svn/text-base/TDNSPredicateBuilder.h.svn-base b/test/.svn/text-base/TDNSPredicateBuilder.h.svn-base new file mode 100644 index 0000000..9b6c010 --- /dev/null +++ b/test/.svn/text-base/TDNSPredicateBuilder.h.svn-base @@ -0,0 +1,76 @@ +// +// PredicateParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/27/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDNSPredicateBuilder : NSObject { + NSString *defaultAttr; + NSString *defaultRelation; + NSString *defaultValue; + PKToken *nonReservedWordFence; + PKCollectionParser *exprParser; + PKCollectionParser *orTermParser; + PKCollectionParser *termParser; + PKCollectionParser *andPrimaryExprParser; + PKCollectionParser *primaryExprParser; + PKCollectionParser *phraseParser; + PKCollectionParser *negatedPredicateParser; + PKCollectionParser *predicateParser; + PKCollectionParser *completePredicateParser; + PKCollectionParser *attrValuePredicateParser; + PKCollectionParser *attrPredicateParser; + PKCollectionParser *valuePredicateParser; + PKCollectionParser *attrParser; + PKCollectionParser *tagParser; + PKCollectionParser *relationParser; + PKCollectionParser *valueParser; + PKCollectionParser *boolParser; + PKParser *trueParser; + PKParser *falseParser; + PKCollectionParser *stringParser; + PKParser *quotedStringParser; + PKCollectionParser *unquotedStringParser; + PKCollectionParser *reservedWordParser; + PKCollectionParser *nonReservedWordParser; + PKPattern *reservedWordPattern; + PKParser *numberParser; + +} +- (NSPredicate *)buildFrom:(NSString *)s; + +@property (nonatomic, copy) NSString *defaultAttr; +@property (nonatomic, copy) NSString *defaultRelation; +@property (nonatomic, copy) NSString *defaultValue; + +@property (nonatomic, retain) PKCollectionParser *exprParser; +@property (nonatomic, retain) PKCollectionParser *orTermParser; +@property (nonatomic, retain) PKCollectionParser *termParser; +@property (nonatomic, retain) PKCollectionParser *andPrimaryExprParser; +@property (nonatomic, retain) PKCollectionParser *primaryExprParser; +@property (nonatomic, retain) PKCollectionParser *phraseParser; +@property (nonatomic, retain) PKCollectionParser *negatedPredicateParser; +@property (nonatomic, retain) PKCollectionParser *predicateParser; +@property (nonatomic, retain) PKCollectionParser *completePredicateParser; +@property (nonatomic, retain) PKCollectionParser *attrValuePredicateParser; +@property (nonatomic, retain) PKCollectionParser *attrPredicateParser; +@property (nonatomic, retain) PKCollectionParser *valuePredicateParser; +@property (nonatomic, retain) PKCollectionParser *attrParser; +@property (nonatomic, retain) PKCollectionParser *tagParser; +@property (nonatomic, retain) PKCollectionParser *relationParser; +@property (nonatomic, retain) PKCollectionParser *valueParser; +@property (nonatomic, retain) PKCollectionParser *boolParser; +@property (nonatomic, retain) PKParser *trueParser; +@property (nonatomic, retain) PKParser *falseParser; +@property (nonatomic, retain) PKCollectionParser *stringParser; +@property (nonatomic, retain) PKParser *quotedStringParser; +@property (nonatomic, retain) PKCollectionParser *unquotedStringParser; +@property (nonatomic, retain) PKCollectionParser *reservedWordParser; +@property (nonatomic, retain) PKCollectionParser *nonReservedWordParser; +@property (nonatomic, retain) PKPattern *reservedWordPattern; +@property (nonatomic, retain) PKParser *numberParser; +@end diff --git a/test/.svn/text-base/TDNSPredicateBuilder.m.svn-base b/test/.svn/text-base/TDNSPredicateBuilder.m.svn-base new file mode 100644 index 0000000..da933ae --- /dev/null +++ b/test/.svn/text-base/TDNSPredicateBuilder.m.svn-base @@ -0,0 +1,587 @@ +// +// PKNSPredicateBuilder.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/27/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDNSPredicateBuilder.h" +#import "NSString+ParseKitAdditions.h" + +// expr = term orTerm*; +// orTerm = 'or' term; +// term = primaryExpr andPrimaryExpr*; +// andPrimaryExpr = 'and' primaryExpr; +// primaryExpr = phrase | '(' expr ')'; +// phrase = predicate | negatedPredicate; +// negatedPredicate = 'not' predicate; +// predicate = completePredicate | attrValuePredicate | attrPredicate | valuePredicate; +// completePredicate = attr relation value; +// attrValuePredicate = attr value; +// attrPredicate = attr; +// valuePredicate = value; +// attr = tag | Word; +// tag = '@' Word; +// value = string | Number | bool; +// string = QuotedString | unquotedString; +// unquotedString = nonReservedWord+; +// bool = 'true' | 'false'; + +@interface TDNSPredicateBuilder () +@property (nonatomic, retain) PKToken *nonReservedWordFence; +@end + +@implementation TDNSPredicateBuilder + +- (id)init { + if (self = [super init]) { + self.defaultAttr = @"content"; + self.defaultRelation = @"="; + self.defaultValue = @""; + self.nonReservedWordFence = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"." floatValue:0.0]; + } + return self; +} + + +- (void)dealloc { + self.defaultAttr = nil; + self.defaultRelation = nil; + self.defaultValue = nil; + self.nonReservedWordFence = nil; + self.exprParser = nil; + self.orTermParser = nil; + self.termParser = nil; + self.andPrimaryExprParser = nil; + self.primaryExprParser = nil; + self.phraseParser = nil; + self.negatedPredicateParser = nil; + self.predicateParser = nil; + self.completePredicateParser = nil; + self.attrValuePredicateParser = nil; + self.attrPredicateParser = nil; + self.valuePredicateParser = nil; + self.attrParser = nil; + self.tagParser = nil; + self.relationParser = nil; + self.valueParser = nil; + self.boolParser = nil; + self.trueParser = nil; + self.falseParser = nil; + self.stringParser = nil; + self.quotedStringParser = nil; + self.unquotedStringParser = nil; + self.reservedWordParser = nil; + self.nonReservedWordParser = nil; + self.reservedWordPattern = nil; + self.numberParser = nil; + [super dealloc]; +} + + +- (NSPredicate *)buildFrom:(NSString *)s; { + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + return [[self.exprParser completeMatchFor:a] pop]; +} + + +// expression = term orTerm* +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + [exprParser add:self.termParser]; + [exprParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + } + return exprParser; +} + + +// orTerm = 'or' term +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKSequence sequence]; + orTermParser.name = @"orTerm"; + [orTermParser add:[[PKCaseInsensitiveLiteral literalWithString:@"or"] discard]]; + [orTermParser add:self.termParser]; + [orTermParser setAssembler:self selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// term = primaryExpr andPrimaryExpr* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + termParser.name = @"term"; + [termParser add:self.primaryExprParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.andPrimaryExprParser]]; + } + return termParser; +} + + +// andPrimaryExpr = 'and' primaryExpr +- (PKCollectionParser *)andPrimaryExprParser { + if (!andPrimaryExprParser) { + self.andPrimaryExprParser = [PKSequence sequence]; + andPrimaryExprParser.name = @"andPrimaryExpr"; + [andPrimaryExprParser add:[[PKCaseInsensitiveLiteral literalWithString:@"and"] discard]]; + [andPrimaryExprParser add:self.primaryExprParser]; + [andPrimaryExprParser setAssembler:self selector:@selector(didMatchAnd:)]; + } + return andPrimaryExprParser; +} + + +// primaryExpr = phrase | '(' expression ')' +- (PKCollectionParser *)primaryExprParser { + if (!primaryExprParser) { + self.primaryExprParser = [PKAlternation alternation]; + primaryExprParser.name = @"primaryExpr"; + [primaryExprParser add:self.phraseParser]; + + PKSequence *s = [PKSequence sequence]; + [s add:[[PKSymbol symbolWithString:@"("] discard]]; + [s add:self.exprParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + [primaryExprParser add:s]; + } + return primaryExprParser; +} + + +// phrase = predicate | negatedPredicate +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + self.phraseParser = [PKAlternation alternation]; + phraseParser.name = @"phrase"; + [phraseParser add:self.predicateParser]; + [phraseParser add:self.negatedPredicateParser]; + } + return phraseParser; +} + + +// negatedPredicate = 'not' predicate +- (PKCollectionParser *)negatedPredicateParser { + if (!negatedPredicateParser) { + self.negatedPredicateParser = [PKSequence sequence]; + negatedPredicateParser.name = @"negatedPredicate"; + [negatedPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"not"] discard]]; + [negatedPredicateParser add:self.predicateParser]; + [negatedPredicateParser setAssembler:self selector:@selector(didMatchNegatedValue:)]; + } + return negatedPredicateParser; +} + + +// predicate = bool | eqPredicate | nePredicate | gtPredicate | gteqPredicate | ltPredicate | lteqPredicate | beginswithPredicate | containsPredicate | endswithPredicate | matchesPredicate +- (PKCollectionParser *)predicateParser { + if (!predicateParser) { + self.predicateParser = [PKAlternation alternation]; + predicateParser.name = @"predicate"; + [predicateParser add:self.completePredicateParser]; + [predicateParser add:self.attrValuePredicateParser]; + [predicateParser add:self.attrPredicateParser]; + [predicateParser add:self.valuePredicateParser]; + [predicateParser setAssembler:self selector:@selector(didMatchPredicate:)]; + } + return predicateParser; +} + + +// completePredicate = attribute relation value +- (PKCollectionParser *)completePredicateParser { + if (!completePredicateParser) { + self.completePredicateParser = [PKSequence sequence]; + completePredicateParser.name = @"completePredicate"; + [completePredicateParser add:self.attrParser]; + [completePredicateParser add:self.relationParser]; + [completePredicateParser add:self.valueParser]; + } + return completePredicateParser; +} + + +// attrValuePredicate = attribute value +- (PKCollectionParser *)attrValuePredicateParser { + if (!attrValuePredicateParser) { + self.attrValuePredicateParser = [PKSequence sequence]; + attrValuePredicateParser.name = @"attrValuePredicate"; + [attrValuePredicateParser add:self.attrParser]; + [attrValuePredicateParser add:self.valueParser]; + [attrValuePredicateParser setAssembler:self selector:@selector(didMatchAttrValuePredicate:)]; + } + return attrValuePredicateParser; +} + + +// attrPredicate = attribute +- (PKCollectionParser *)attrPredicateParser { + if (!attrPredicateParser) { + self.attrPredicateParser = [PKSequence sequence]; + attrPredicateParser.name = @"attrPredicate"; + [attrPredicateParser add:self.attrParser]; + [attrPredicateParser setAssembler:self selector:@selector(didMatchAttrPredicate:)]; + } + return attrPredicateParser; +} + + +// valuePredicate = value +- (PKCollectionParser *)valuePredicateParser { + if (!valuePredicateParser) { + self.valuePredicateParser = [PKSequence sequence]; + valuePredicateParser.name = @"valuePredicate"; + [valuePredicateParser add:self.valueParser]; + [valuePredicateParser setAssembler:self selector:@selector(didMatchValuePredicate:)]; + } + return valuePredicateParser; +} + + +// attr = tag | 'uniqueid' | 'line' | 'type' | 'isgroupheader' | 'level' | 'index' | 'content' | 'parent' | 'project' | 'countofchildren' +- (PKCollectionParser *)attrParser { + if (!attrParser) { + self.attrParser = [PKAlternation alternation]; + attrParser.name = @"attr"; + [attrParser add:self.tagParser]; + [attrParser add:self.nonReservedWordParser]; + [attrParser setAssembler:self selector:@selector(didMatchAttr:)]; + } + return attrParser; +} + + +// relation = '=' | '!=' | '>' | '>=' | '<' | '<=' | 'beginswith' | 'contains' | 'endswith' | 'matches' +- (PKCollectionParser *)relationParser { + if (!relationParser) { + self.relationParser = [PKAlternation alternation]; + relationParser.name = @"relation"; + [relationParser add:[PKSymbol symbolWithString:@"="]]; + [relationParser add:[PKSymbol symbolWithString:@"!="]]; + [relationParser add:[PKSymbol symbolWithString:@">"]]; + [relationParser add:[PKSymbol symbolWithString:@">="]]; + [relationParser add:[PKSymbol symbolWithString:@"<"]]; + [relationParser add:[PKSymbol symbolWithString:@"<="]]; + [relationParser add:[PKCaseInsensitiveLiteral literalWithString:@"beginswith"]]; + [relationParser add:[PKCaseInsensitiveLiteral literalWithString:@"contains"]]; + [relationParser add:[PKCaseInsensitiveLiteral literalWithString:@"endswith"]]; + [relationParser add:[PKCaseInsensitiveLiteral literalWithString:@"matches"]]; + [relationParser setAssembler:self selector:@selector(didMatchRelation:)]; + } + return relationParser; +} + + +// tag = '@' Word +- (PKCollectionParser *)tagParser { + if (!tagParser) { + self.tagParser = [PKSequence sequence]; + tagParser.name = @"tag"; + [tagParser add:[[PKSymbol symbolWithString:@"@"] discard]]; + [tagParser add:[PKWord word]]; + } + return tagParser; +} + + +// value = QuotedString | Number | bool +- (PKCollectionParser *)valueParser { + if (!valueParser) { + self.valueParser = [PKAlternation alternation]; + valueParser.name = @"value"; + [valueParser add:self.stringParser]; + [valueParser add:self.numberParser]; + [valueParser add:self.boolParser]; + } + return valueParser; +} + + +- (PKCollectionParser *)boolParser { + if (!boolParser) { + self.boolParser = [PKAlternation alternation]; + boolParser.name = @"bool"; + [boolParser add:self.trueParser]; + [boolParser add:self.falseParser]; + [boolParser setAssembler:self selector:@selector(didMatchBool:)]; + } + return boolParser; +} + + +- (PKParser *)trueParser { + if (!trueParser) { + self.trueParser = [[PKCaseInsensitiveLiteral literalWithString:@"true"] discard]; + trueParser.name = @"true"; + [trueParser setAssembler:self selector:@selector(didMatchTrue:)]; + } + return trueParser; +} + + +- (PKParser *)falseParser { + if (!falseParser) { + self.falseParser = [[PKCaseInsensitiveLiteral literalWithString:@"false"] discard]; + falseParser.name = @"false"; + [falseParser setAssembler:self selector:@selector(didMatchFalse:)]; + } + return falseParser; +} + + +// string = quotedString | unquotedString +- (PKCollectionParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKAlternation alternation]; + stringParser.name = @"string"; + [stringParser add:self.quotedStringParser]; + [stringParser add:self.unquotedStringParser]; + } + return stringParser; +} + + +// quotedString = QuotedString +- (PKParser *)quotedStringParser { + if (!quotedStringParser) { + self.quotedStringParser = [PKQuotedString quotedString]; + quotedStringParser.name = @"quotedString"; + [quotedStringParser setAssembler:self selector:@selector(didMatchQuotedString:)]; + } + return quotedStringParser; +} + + +// unquotedString = nonReservedWord+ +- (PKCollectionParser *)unquotedStringParser { + if (!unquotedStringParser) { + self.unquotedStringParser = [PKSequence sequence]; + unquotedStringParser.name = @"unquotedString"; + [unquotedStringParser add:self.nonReservedWordParser]; + [unquotedStringParser add:[PKRepetition repetitionWithSubparser:self.nonReservedWordParser]]; + [unquotedStringParser setAssembler:self selector:@selector(didMatchUnquotedString:)]; + } + return unquotedStringParser; +} + + +- (PKCollectionParser *)reservedWordParser { + if (!reservedWordParser) { + self.reservedWordParser = [PKIntersection intersection]; + [reservedWordParser add:[PKWord word]]; + [reservedWordParser add:self.reservedWordPattern]; + reservedWordParser.name = @"reservedWord"; + [reservedWordParser setAssembler:self selector:@selector(didMatchReservedWord:)]; + } + return reservedWordParser; +} + + +// nonReservedWord = Word +- (PKCollectionParser *)nonReservedWordParser { + if (!nonReservedWordParser) { + self.nonReservedWordParser = [PKDifference differenceWithSubparser:[PKWord word] minus:self.reservedWordParser]; + nonReservedWordParser.name = @"nonReservedWord"; + [nonReservedWordParser setAssembler:self selector:@selector(didMatchNonReservedWord:)]; + } + return nonReservedWordParser; +} + + +- (PKPattern *)reservedWordPattern { + if (!reservedWordPattern) { + NSString *s = @"true|false|and|or|not|contains|beginswith|endswith|matches"; + self.reservedWordPattern = [PKPattern patternWithString:s options:PKPatternOptionsIgnoreCase]; + reservedWordPattern.name = @"reservedWordPattern"; + } + return reservedWordPattern; +} + + +- (PKParser *)numberParser { + if (!numberParser) { + self.numberParser = [PKNumber number]; + numberParser.name = @"number"; + [numberParser setAssembler:self selector:@selector(didMatchNumber:)]; + } + return numberParser; +} + + +- (void)didMatchAnd:(PKAssembly *)a { + NSPredicate *p2 = [a pop]; + NSPredicate *p1 = [a pop]; + NSArray *subs = [NSArray arrayWithObjects:p1, p2, nil]; + [a push:[NSCompoundPredicate andPredicateWithSubpredicates:subs]]; +} + + +- (void)didMatchOr:(PKAssembly *)a { + NSPredicate *p2 = [a pop]; + NSPredicate *p1 = [a pop]; + NSArray *subs = [NSArray arrayWithObjects:p1, p2, nil]; + [a push:[NSCompoundPredicate orPredicateWithSubpredicates:subs]]; +} + + +- (void)didMatchPredicate:(PKAssembly *)a { + id value = [a pop]; + id relation = [a pop]; + id attr = [a pop]; + NSString *predicateFormat = [NSString stringWithFormat:@"%@ %@ %%@", attr, relation, nil]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFormat, value, nil]; + [a push:predicate]; +} + + +- (void)didMatchAttrValuePredicate:(PKAssembly *)a { + id value = [a pop]; + id attr = [a pop]; + [a push:attr]; + [a push:defaultRelation]; + [a push:value]; +} + + +- (void)didMatchAttrPredicate:(PKAssembly *)a { + id attr = [a pop]; + [a push:attr]; + [a push:defaultRelation]; + [a push:defaultValue]; +} + + +- (void)didMatchValuePredicate:(PKAssembly *)a { + id value = [a pop]; + [a push:defaultAttr]; + [a push:defaultRelation]; + [a push:value]; +} + + +- (void)didMatchAttr:(PKAssembly *)a { + [a push:[[a pop] stringValue]]; +} + + +- (void)didMatchRelation:(PKAssembly *)a { + [a push:[[a pop] stringValue]]; +} + + +- (void)didMatchNegatedValue:(PKAssembly *)a { + id p = [a pop]; + [a push:[NSCompoundPredicate notPredicateWithSubpredicate:p]]; +} + + +- (void)didMatchBool:(PKAssembly *)a { + NSNumber *b = [a pop]; + [a push:[NSPredicate predicateWithValue:[b boolValue]]]; +} + + +- (void)didMatchTrue:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:YES]]; +} + + +- (void)didMatchFalse:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:NO]]; +} + + +- (void)didMatchQuotedString:(PKAssembly *)a { + [a push:[[[a pop] stringValue] stringByTrimmingQuotes]]; +} + + +- (void)didMatchReservedWord:(PKAssembly *)a { +// PKToken *tok = [a pop]; +// [a push:tok.stringValue]; +} + + +- (void)didMatchNonReservedWord:(PKAssembly *)a { +// id obj = [a pop]; +// [a push:nonReservedWordFence]; +// [a push:obj]; +} + + +- (void)didMatchUnquotedString:(PKAssembly *)a { + NSMutableArray *wordStrings = [NSMutableArray array]; + + while (1) { + NSArray *objs = [a objectsAbove:nonReservedWordFence]; + id next = [a pop]; // is the next obj a fence? + if (![nonReservedWordFence isEqual:next]) { + // if not, put the next token back + if (next) { + [a push:next]; + } + // also put back any toks we didnt mean to pop + for (id obj in [objs reverseObjectEnumerator]) { + [a push:obj]; + } + break; + } + NSAssert(1 == [objs count], @""); + [wordStrings addObject:[objs objectAtIndex:0]]; + } + + NSInteger last = [wordStrings count] - 1; + NSInteger i = 0; + NSMutableString *ms = [NSMutableString string]; + for (NSString *wordString in [wordStrings reverseObjectEnumerator]) { + if (i++ == last) { + [ms appendString:wordString]; + } else { + [ms appendFormat:@"%@ ", wordString]; + } + } + [a push:[[ms copy] autorelease]]; +} + + +- (void)didMatchNumber:(PKAssembly *)a { + NSNumber *n = [NSNumber numberWithFloat:[(PKToken *)[a pop] floatValue]]; + [a push:n]; +} + +@synthesize defaultAttr; +@synthesize defaultRelation; +@synthesize defaultValue; +@synthesize nonReservedWordFence; +@synthesize exprParser; +@synthesize orTermParser; +@synthesize termParser; +@synthesize andPrimaryExprParser; +@synthesize primaryExprParser; +@synthesize phraseParser; +@synthesize negatedPredicateParser; +@synthesize predicateParser; +@synthesize completePredicateParser; +@synthesize attrValuePredicateParser; +@synthesize attrPredicateParser; +@synthesize valuePredicateParser; +@synthesize attrParser; +@synthesize tagParser; +@synthesize relationParser; +@synthesize valueParser; +@synthesize boolParser; +@synthesize trueParser; +@synthesize falseParser; +@synthesize stringParser; +@synthesize quotedStringParser; +@synthesize unquotedStringParser; +@synthesize reservedWordParser; +@synthesize nonReservedWordParser; +@synthesize reservedWordPattern; +@synthesize numberParser; +@end diff --git a/test/.svn/text-base/TDNSPredicateBuilderTest.h.svn-base b/test/.svn/text-base/TDNSPredicateBuilderTest.h.svn-base new file mode 100644 index 0000000..a9fa376 --- /dev/null +++ b/test/.svn/text-base/TDNSPredicateBuilderTest.h.svn-base @@ -0,0 +1,18 @@ +// +// PredicateParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/27/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "TDNSPredicateBuilder.h" + +@interface TDNSPredicateBuilderTest : SenTestCase { + TDNSPredicateBuilder *b; + NSString *s; + PKAssembly *a; +} + +@end diff --git a/test/.svn/text-base/TDNSPredicateBuilderTest.m.svn-base b/test/.svn/text-base/TDNSPredicateBuilderTest.m.svn-base new file mode 100644 index 0000000..8ab1802 --- /dev/null +++ b/test/.svn/text-base/TDNSPredicateBuilderTest.m.svn-base @@ -0,0 +1,213 @@ +// +// PredicateParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/27/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDNSPredicateBuilderTest.h" + +@implementation TDNSPredicateBuilderTest + +- (void)setUp { + b = [[[TDNSPredicateBuilder alloc] init] autorelease]; +} + + +- (void)testEq { + // test numbers + s = @"foo = 1.0"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == 1]foo/=/1.0^", [a description]); + + s = @"foo = -1.0"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == -1]foo/=/-1.0^", [a description]); + + + // test bools + s = @"foo = true"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == TRUEPREDICATE]foo/=/true^", [a description]); + + s = @"foo = false"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == FALSEPREDICATE]foo/=/false^", [a description]); + + + // test strings + s = @"foo = 'bar'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == \"bar\"]foo/=/'bar'^", [a description]); + + s = @"foo = 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == \"baz\"]foo/=/'baz'^", [a description]); +} + + +- (void)testNe { + // test numbers + s = @"foo != 1.0"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != 1]foo/!=/1.0^", [a description]); + + s = @"foo != 1.00"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != 1]foo/!=/1.00^", [a description]); + + + // test bools + s = @"foo != true"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != TRUEPREDICATE]foo/!=/true^", [a description]); + + s = @"foo != false"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != FALSEPREDICATE]foo/!=/false^", [a description]); + + + // test strings + s = @"foo != 'bar'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != \"bar\"]foo/!=/'bar'^", [a description]); + + s = @"foo != 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != \"baz\"]foo/!=/'baz'^", [a description]); +} + + +- (void)testGt { + s = @"foo > 42"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo > 42]foo/>/42^", [a description]); +} + + +- (void)testLt { + s = @"foo < .3"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo < 0.3]foo/= 42"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo >= 42]foo/>=/42^", [a description]); +} + + +- (void)testLteq { + s = @"foo <= .3"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo <= 0.3]foo/<=/.3^", [a description]); +} + + +- (void)testBeginswith { + s = @"foo beginswith 'bar'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo BEGINSWITH \"bar\"]foo/beginswith/'bar'^", [a description]); +} + + +- (void)testContains { + s = @"foo contains 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo CONTAINS \"baz\"]foo/contains/'baz'^", [a description]); +} + + +- (void)testEndswith { + s = @"foo endswith 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo ENDSWITH \"baz\"]foo/endswith/'baz'^", [a description]); +} + + +- (void)testMatches { + s = @"foo matches 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo MATCHES \"baz\"]foo/matches/'baz'^", [a description]); +} + + +- (void)testUnqotedString { +// s = @"foo contains bar"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo CONTAINS \"bar\"]foo/contains/bar^", [a description]); +// +// s = @"foo matches bar baz"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo MATCHES \"bar baz\"]foo/matches/bar/baz^", [a description]); +// +// s = @"foo matches foo bar baz"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo MATCHES \"foo bar baz\"]foo/matches/foo/bar/baz^", [a description]); +// +// s = @"foo matches bar and baz contains bat"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo MATCHES \"bar\" AND baz CONTAINS \"bat\"]foo/matches/bar/and/baz/contains/bat^", [a description]); +// +// s = @"foo matches foo bar and baz contains bat"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo MATCHES \"foo bar\" AND baz CONTAINS \"bat\"]foo/matches/foo/bar/and/baz/contains/bat^", [a description]); +} + + +- (void)testBools { + s = @"true"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[content == TRUEPREDICATE]true^", [a description]); + + s = @"not true"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[NOT content == TRUEPREDICATE]not/true^", [a description]); + + s = @"false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[content == FALSEPREDICATE]false^", [a description]); + + s = @"not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[NOT content == FALSEPREDICATE]not/false^", [a description]); + + s = @"true and false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[content == TRUEPREDICATE AND content == FALSEPREDICATE]true/and/false^", [a description]); + + s = @"not true and false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[(NOT content == TRUEPREDICATE) AND content == FALSEPREDICATE]not/true/and/false^", [a description]); + + s = @"not true and not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[(NOT content == TRUEPREDICATE) AND (NOT content == FALSEPREDICATE)]not/true/and/not/false^", [a description]); + + s = @"true or false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[content == TRUEPREDICATE OR content == FALSEPREDICATE]true/or/false^", [a description]); + + s = @"(true and false) or false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[(content == TRUEPREDICATE AND content == FALSEPREDICATE) OR content == FALSEPREDICATE](/true/and/false/)/or/false^", [a description]); + + s = @"(true and false) or not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[(content == TRUEPREDICATE AND content == FALSEPREDICATE) OR (NOT content == FALSEPREDICATE)](/true/and/false/)/or/not/false^", [a description]); +} + +@end diff --git a/test/.svn/text-base/TDNSPredicateEvaluator.h.svn-base b/test/.svn/text-base/TDNSPredicateEvaluator.h.svn-base new file mode 100644 index 0000000..dc6e3fe --- /dev/null +++ b/test/.svn/text-base/TDNSPredicateEvaluator.h.svn-base @@ -0,0 +1,28 @@ +// +// PKNSPredicateEvaluator.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class TDNSPredicateEvaluator; + +@protocol TDKeyPathResolver +- (id)resolvedValueForKeyPath:(NSString *)s; +@end + +@interface TDNSPredicateEvaluator : NSObject { + id resolver; + PKParser *parser; + PKToken *openCurly; +} +- (id)initWithKeyPathResolver:(id )r; + +- (BOOL)evaluate:(NSString *)s; + +@property (nonatomic, retain) PKParser *parser; +@end diff --git a/test/.svn/text-base/TDNSPredicateEvaluator.m.svn-base b/test/.svn/text-base/TDNSPredicateEvaluator.m.svn-base new file mode 100644 index 0000000..d5af388 --- /dev/null +++ b/test/.svn/text-base/TDNSPredicateEvaluator.m.svn-base @@ -0,0 +1,224 @@ +// +// PKNSPredicateEvaluator.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDNSPredicateEvaluator.h" +#import "PKParserFactory.h" +#import "NSString+ParseKitAdditions.h" +#import "NSArray+ParseKitAdditions.h" + +@interface TDNSPredicateEvaluator () +- (void)didMatchCollectionPredicateAssembly:(PKAssembly *)a ordered:(NSComparisonResult)ordered; + +@property (nonatomic, assign) id resolver; +@property (nonatomic, retain) PKToken *openCurly; +@end + +@implementation TDNSPredicateEvaluator + +- (id)initWithKeyPathResolver:(id )r { + if (self = [super init]) { + self.resolver = r; + + self.openCurly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0]; + + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"nspredicate" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + self.parser = [[PKParserFactory factory] parserFromGrammar:s assembler:self]; + } + return self; +} + + +- (void)dealloc { + resolver = nil; + self.parser = nil; + self.openCurly = nil; + [super dealloc]; +} + + +- (BOOL)evaluate:(NSString *)s { + id result = [parser parse:s]; + return [result boolValue]; +} + + +- (void)didMatchNegatedPredicate:(PKAssembly *)a { + BOOL b = [[a pop] boolValue]; + [a push:[NSNumber numberWithBool:!b]]; +} + + +- (void)didMatchNumComparisonPredicate:(PKAssembly *)a { + CGFloat n2 = [(PKToken *)[a pop] floatValue]; + NSString *op = [[a pop] stringValue]; + CGFloat n1 = [(PKToken *)[a pop] floatValue]; + + BOOL result = NO; + if ([op isEqualToString:@"<"]) { + result = n1 < n2; + } else if ([op isEqualToString:@">"]) { + result = n1 > n2; + } else if ([op isEqualToString:@"="] || [op isEqualToString:@"=="]) { + result = n1 == n2; + } else if ([op isEqualToString:@"<="] || [op isEqualToString:@"=<"]) { + result = n1 <= n2; + } else if ([op isEqualToString:@">="] || [op isEqualToString:@"=>"]) { + result = n1 >= n2; + } else if ([op isEqualToString:@"!="] || [op isEqualToString:@"<>"]) { + result = n1 != n2; + } + + [a push:[NSNumber numberWithBool:result]]; +} + + +- (void)didMatchCollectionLtPredicate:(PKAssembly *)a { + [self didMatchCollectionPredicateAssembly:a ordered:NSOrderedAscending]; +} + + +- (void)didMatchCollectionGtPredicate:(PKAssembly *)a { + [self didMatchCollectionPredicateAssembly:a ordered:NSOrderedDescending]; +} + + +- (void)didMatchCollectionEqPredicate:(PKAssembly *)a { + [self didMatchCollectionPredicateAssembly:a ordered:NSOrderedSame]; +} + + +- (void)didMatchCollectionPredicateAssembly:(PKAssembly *)a ordered:(NSComparisonResult)ordered { + id value = [a pop]; + [a pop]; // discard op + NSArray *array = [a pop]; + NSString *aggOp = [[a pop] stringValue]; + + BOOL isAny = NSOrderedSame == [aggOp caseInsensitiveCompare:@"ANY"]; + BOOL isSome = NSOrderedSame == [aggOp caseInsensitiveCompare:@"SOME"]; + BOOL isNone = NSOrderedSame == [aggOp caseInsensitiveCompare:@"NONE"]; + BOOL isAll = NSOrderedSame == [aggOp caseInsensitiveCompare:@"ALL"]; + + BOOL result = NO; + if (isAny || isSome || isNone) { + for (id obj in array) { + if (ordered == [obj compare:value]) { + result = YES; + break; + } + } + } else if (isAll) { + NSInteger c = 0; + for (id obj in array) { + if (ordered != [obj compare:value]) { + break; + } + c++; + } + result = c == [array count]; + } + + if (isNone) { + result = !result; + } + + [a push:[NSNumber numberWithBool:result]]; +} + + +- (void)didMatchString:(PKAssembly *)a { + NSString *s = [[[a pop] stringValue] stringByTrimmingQuotes]; + [a push:s]; +} + + +- (void)didMatchStringTestPredicate:(PKAssembly *)a { + NSString *s2 = [a pop]; + NSString *op = [[a pop] stringValue]; + NSString *s1 = [a pop]; + + BOOL result = NO; + if (NSOrderedSame == [op caseInsensitiveCompare:@"BEGINSWITH"]) { + result = [s1 hasPrefix:s2]; + } else if (NSOrderedSame == [op caseInsensitiveCompare:@"CONTAINS"]) { + result = (NSNotFound != [s1 rangeOfString:s2].location); + } else if (NSOrderedSame == [op caseInsensitiveCompare:@"ENDSWITH"]) { + result = [s1 hasSuffix:s2]; + } else if (NSOrderedSame == [op caseInsensitiveCompare:@"LIKE"]) { + result = NSOrderedSame == [s1 caseInsensitiveCompare:s2]; // TODO + } else if (NSOrderedSame == [op caseInsensitiveCompare:@"MATCHES"]) { + result = NSOrderedSame == [s1 caseInsensitiveCompare:s2]; // TODO + } + + [a push:[NSNumber numberWithBool:result]]; +} + + +- (void)didMatchAndAndTerm:(PKAssembly *)a { + BOOL b2 = [[a pop] boolValue]; + BOOL b1 = [[a pop] boolValue]; + [a push:[NSNumber numberWithBool:b1 && b2]]; +} + + +- (void)didMatchOrOrTerm:(PKAssembly *)a { + BOOL b2 = [[a pop] boolValue]; + BOOL b1 = [[a pop] boolValue]; + [a push:[NSNumber numberWithBool:b1 || b2]]; +} + + +- (void)didMatchArray:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:openCurly]; + [a pop]; // discard '{' + [a push:[objs reversedArray]]; +} + + +- (void)didMatchCollectionTestPredicate:(PKAssembly *)a { + NSArray *array = [a pop]; + NSAssert([array isKindOfClass:[NSArray class]], @""); + id value = [a pop]; + [a push:[NSNumber numberWithBool:[array containsObject:value]]]; +} + + +- (void)didMatchKeyPath:(PKAssembly *)a { + NSString *keyPath = [[a pop] stringValue]; + [a push:[resolver resolvedValueForKeyPath:keyPath]]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + [a push:[NSNumber numberWithFloat:[(PKToken *)[a pop] floatValue]]]; +} + + +- (void)didMatchTrue:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:YES]]; +} + + +- (void)didMatchFalse:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:NO]]; +} + + +- (void)didMatchTruePredicate:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:YES]]; +} + + +- (void)didMatchFalsePredicate:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:NO]]; +} + +@synthesize resolver; +@synthesize parser; +@synthesize openCurly; +@end diff --git a/test/.svn/text-base/TDNSPredicateEvaluatorTest.h.svn-base b/test/.svn/text-base/TDNSPredicateEvaluatorTest.h.svn-base new file mode 100644 index 0000000..5649760 --- /dev/null +++ b/test/.svn/text-base/TDNSPredicateEvaluatorTest.h.svn-base @@ -0,0 +1,22 @@ +// +// PKNSPredicateEvaluatorTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "TDNSPredicateEvaluator.h" + +@interface TDNSPredicateEvaluatorTest : SenTestCase { + TDNSPredicateEvaluator *eval; + NSString *s; + PKAssembly *a; + PKAssembly *res; + PKTokenizer *t; + + NSMutableDictionary *d; +} + +@end diff --git a/test/.svn/text-base/TDNSPredicateEvaluatorTest.m.svn-base b/test/.svn/text-base/TDNSPredicateEvaluatorTest.m.svn-base new file mode 100644 index 0000000..96bbe6b --- /dev/null +++ b/test/.svn/text-base/TDNSPredicateEvaluatorTest.m.svn-base @@ -0,0 +1,272 @@ +// +// PKNSPredicateEvaluatorTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDNSPredicateEvaluatorTest.h" + +@implementation TDNSPredicateEvaluatorTest + +- (id)resolvedValueForKeyPath:(NSString *)kp { + id result = [d objectForKey:kp]; + if (!result) { + result = [NSNumber numberWithBool:NO]; + } + return result; +} + + +- (void)dealloc { + [eval release]; + [super dealloc]; +} + + +- (void)setUp { + d = [NSMutableDictionary dictionary]; + eval = [[TDNSPredicateEvaluator alloc] initWithKeyPathResolver:self]; + t = eval.parser.tokenizer; +} + + +- (void)testKeyPath { + [d setObject:[NSNumber numberWithBool:YES] forKey:@"foo"]; + [d setObject:[NSNumber numberWithBool:NO] forKey:@"baz"]; + + t.string = @"foo"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[eval.parser parserNamed:@"keyPath"] completeMatchFor:a]; + TDEqualObjects(@"[1]foo^", [res description]); + + t.string = @"bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[eval.parser parserNamed:@"keyPath"] completeMatchFor:a]; + TDEqualObjects(@"[0]bar^", [res description]); + + t.string = @"baz"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[eval.parser parserNamed:@"keyPath"] completeMatchFor:a]; + TDEqualObjects(@"[0]baz^", [res description]); + + t.string = @"foo.bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[eval.parser parserNamed:@"keyPath"] completeMatchFor:a]; + TDEqualObjects(@"[0]foo.bar^", [res description]); +} + + +- (void)testNegatedPredicate { + t.string = @"not 0 < 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]not/0/ 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]1/>/2^", [res description]); + + t.string = @"1 != 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]1/!=/2^", [res description]); + + t.string = @"1 == 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]1/==/2^", [res description]); + + t.string = @"1 = 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]1/=/2^", [res description]); +} + + +- (void)testArray { + t.string = @"{1, 3}"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [[eval.parser parserNamed:@"array"] completeMatchFor:a]; + NSArray *array = [res pop]; + TDEquals((NSUInteger)2, [array count]); + TDEqualObjects([array objectAtIndex:0], [NSNumber numberWithInteger:1]); + TDEqualObjects([array objectAtIndex:1], [NSNumber numberWithInteger:3]); +} + + +- (void)testTrue { + t.string = @"true"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [[eval.parser parserNamed:@"bool"] completeMatchFor:a]; + TDEqualObjects(@"[1]true^", [res description]); +} + + +- (void)testFalse { + t.string = @"false"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [[eval.parser parserNamed:@"bool"] completeMatchFor:a]; + TDEqualObjects(@"[0]false^", [res description]); +} + + +- (void)testTruePredicate { + t.string = @"TRUEPREDICATE"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]TRUEPREDICATE^", [res description]); +} + + +- (void)testFalsePredicate { + t.string = @"FALSEPREDICATE"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]FALSEPREDICATE^", [res description]); +} + + +- (void)testCollectionTest { + t.string = @"1 IN {1}"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]1/IN/{/1/}^", [res description]); +} + + +- (void)testCollectionLtComparison { + t.string = @"ANY {3} < 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]ANY/{/3/}/ 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]ANY/{/3/}/>/4^", [res description]); + + t.string = @"SOME {3} > 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]SOME/{/3/}/>/4^", [res description]); + + t.string = @"NONE {3} > 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]NONE/{/3/}/>/4^", [res description]); + + t.string = @"ALL {3} > 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]ALL/{/3/}/>/4^", [res description]); +} + + +- (void)testOr { + t.string = @"TRUEPREDICATE OR FALSEPREDICATE"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]TRUEPREDICATE/OR/FALSEPREDICATE^", [res description]); +} + + +- (void)testAnd { + t.string = @"TRUEPREDICATE AND FALSEPREDICATE"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]TRUEPREDICATE/AND/FALSEPREDICATE^", [res description]); +} + + +- (void)testCompoundExpr { + t.string = @"(TRUEPREDICATE)"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1](/TRUEPREDICATE/)^", [res description]); +} + +@end diff --git a/test/.svn/text-base/TDNegationTest.h.svn-base b/test/.svn/text-base/TDNegationTest.h.svn-base new file mode 100644 index 0000000..c336c22 --- /dev/null +++ b/test/.svn/text-base/TDNegationTest.h.svn-base @@ -0,0 +1,19 @@ +// +// TDNegationTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDNegationTest : SenTestCase { + PKNegation *n; + PKTokenizer *t; + PKAssembly *a; + PKAssembly *res; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDNegationTest.m.svn-base b/test/.svn/text-base/TDNegationTest.m.svn-base new file mode 100644 index 0000000..7397726 --- /dev/null +++ b/test/.svn/text-base/TDNegationTest.m.svn-base @@ -0,0 +1,60 @@ +// +// TDNegationTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/2/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDNegationTest.h" + +@implementation TDNegationTest + +- (void)testFoo { + n = [PKNegation negationWithSubparser:[PKWord word]]; + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [n bestMatchFor:a]; + TDNil(res); + + s = @"'foo'"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [n bestMatchFor:a]; + TDEqualObjects(@"['foo']'foo'^", [res description]); + + n = [PKNegation negationWithSubparser:[PKLiteral literalWithString:@"foo"]]; + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [n bestMatchFor:a]; + TDNil(res); +} + + +- (void)testParserNamed { + PKWord *w = [PKWord word]; + w.name = @"w"; + n = [PKNegation negationWithSubparser:w]; + + TDEquals(w, [n parserNamed:@"w"]); + + PKCollectionParser *alt = [PKAlternation alternation]; + alt.name = @"alt"; + + PKParser *foo = [PKLiteral literalWithString:@"foo"]; + foo.name = @"foo"; + [alt add:foo]; + + PKParser *bar = [PKLiteral literalWithString:@"bar"]; + bar.name = @"bar"; + [alt add:bar]; + + n = [PKNegation negationWithSubparser:alt]; + + TDEquals(alt, [n parserNamed:@"alt"]); + TDEquals(foo, [n parserNamed:@"foo"]); + TDEquals(bar, [n parserNamed:@"bar"]); +} + +@end diff --git a/test/.svn/text-base/TDNonReservedWord.h.svn-base b/test/.svn/text-base/TDNonReservedWord.h.svn-base new file mode 100644 index 0000000..aa50f32 --- /dev/null +++ b/test/.svn/text-base/TDNonReservedWord.h.svn-base @@ -0,0 +1,16 @@ +// +// PKNonReservedWord.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface TDNonReservedWord : PKWord { + +} + +@end diff --git a/test/.svn/text-base/TDNonReservedWord.m.svn-base b/test/.svn/text-base/TDNonReservedWord.m.svn-base new file mode 100644 index 0000000..1b9c6b8 --- /dev/null +++ b/test/.svn/text-base/TDNonReservedWord.m.svn-base @@ -0,0 +1,29 @@ +// +// PKNonReservedWord.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import + +@interface TDReservedWord () ++ (NSArray *)reservedWords; +@end + +@implementation TDNonReservedWord + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + NSString *s = tok.stringValue; + return [s length] && ![[TDReservedWord reservedWords] containsObject:s]; +} + +@end diff --git a/test/.svn/text-base/TDNumberStateTest.h.svn-base b/test/.svn/text-base/TDNumberStateTest.h.svn-base new file mode 100644 index 0000000..0664fb9 --- /dev/null +++ b/test/.svn/text-base/TDNumberStateTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKNumberStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/29/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDNumberStateTest : SenTestCase { + PKNumberState *numberState; + PKTokenizer *t; + PKReader *r; + NSString *s; +} +@end diff --git a/test/.svn/text-base/TDNumberStateTest.m.svn-base b/test/.svn/text-base/TDNumberStateTest.m.svn-base new file mode 100644 index 0000000..775e758 --- /dev/null +++ b/test/.svn/text-base/TDNumberStateTest.m.svn-base @@ -0,0 +1,662 @@ +// +// PKNumberStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/29/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDNumberStateTest.h" + +@implementation TDNumberStateTest + +- (void)setUp { + t = [[PKTokenizer alloc] init]; + r = [[PKReader alloc] init]; + numberState = t.numberState; +} + + +- (void)tearDown { + [t release]; + [r release]; +} + + +- (void)testSingleDigit { + s = @"3"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)3.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"3", tok.stringValue); +} + + +- (void)testDoubleDigit { + s = @"47"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)47.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"47", tok.stringValue); +} + + +- (void)testTripleDigit { + s = @"654"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)654.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"654", tok.stringValue); +} + + +- (void)testSingleDigitPositive { + s = @"+3"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)3.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+3", tok.stringValue); +} + + +- (void)testDoubleDigitPositive { + s = @"+22"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)22.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)testDoubleDigitPositiveSpace { + s = @"+22 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)22.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)testMultipleDots { + s = @"1.1.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.1", tok.stringValue); + + tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".1", tok.stringValue); +} + + +- (void)testOneDot { + s = @"1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1", tok.stringValue); +} + + +- (void)testCustomOneDot { + s = @"1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.", tok.stringValue); +} + + +- (void)testOneDotZero { + s = @"1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.0", tok.stringValue); +} + + +- (void)testPositiveOneDot { + s = @"+1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1", tok.stringValue); +} + + +- (void)testPositiveOneDotCustom { + s = @"+1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.", tok.stringValue); +} + + +- (void)testPositiveOneDotZero { + s = @"+1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.0", tok.stringValue); +} + + +- (void)testPositiveOneDotZeroSpace { + s = @"+1.0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.0", tok.stringValue); +} + + +- (void)testNegativeOneDot { + s = @"-1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testNegativeOneDotCustom { + s = @"-1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.", tok.stringValue); +} + + +- (void)testNegativeOneDotSpace { + s = @"-1. "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testNegativeOneDotZero { + s = @"-1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.0", tok.stringValue); +} + + +- (void)testNegativeOneDotZeroSpace { + s = @"-1.0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.0", tok.stringValue); +} + + +- (void)testOneDotOne { + s = @"1.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.1", tok.stringValue); +} + + +- (void)testZeroDotOne { + s = @"0.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0.1", tok.stringValue); +} + + +- (void)testDotOne { + s = @".1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".1", tok.stringValue); +} + + +- (void)testDotZero { + s = @".0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); +} + + +- (void)testNegativeDotZero { + s = @"-.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.0", tok.stringValue); +} + + +- (void)testPositiveDotZero { + s = @"+.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+.0", tok.stringValue); +} + + +- (void)testPositiveDotOne { + s = @"+.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+.1", tok.stringValue); +} + + +- (void)testNegativeDotOne { + s = @"-.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1", tok.stringValue); +} + + +- (void)testNegativeDotOneOne { + s = @"-.11"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.11, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.11", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOne { + s = @"-.111"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.111", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZero { + s = @"-.1110"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1110", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZeroZero { + s = @"-.11100"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.11100", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZeroSpace { + s = @"-.1110 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1110", tok.stringValue); +} + + +- (void)testZeroDotThreeSixtyFive { + s = @"0.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0.365", tok.stringValue); +} + + +- (void)testNegativeZeroDotThreeSixtyFive { + s = @"-0.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0.365", tok.stringValue); +} + + +- (void)testNegativeTwentyFourDotThreeSixtyFive { + s = @"-24.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-24.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-24.365", tok.stringValue); +} + + +- (void)testTwentyFourDotThreeSixtyFive { + s = @"24.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)24.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"24.365", tok.stringValue); +} + + +- (void)testZero { + s = @"0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0", tok.stringValue); +} + + +- (void)testNegativeOne { + s = @"-1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testOne { + s = @"1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1", tok.stringValue); +} + + +- (void)testPositiveOne { + s = @"+1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1", tok.stringValue); +} + + +- (void)testPositiveZero { + s = @"+0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+0", tok.stringValue); +} + + +- (void)testPositiveZeroSpace { + s = @"+0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+0", tok.stringValue); +} + + +- (void)testNegativeZero { + s = @"-0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0", tok.stringValue); +} + + +- (void)testNull { + s = @"NULL"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testNil { + s = @"nil"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testEmptyString { + s = @""; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDot { + s = @"."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDotSpace { + s = @". "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDotSpaceOne { + s = @". 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlus { + s = @"+"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlusSpace { + s = @"+ "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlusSpaceOne { + s = @"+ 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinus { + s = @"-"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinusSpace { + s = @"- "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinusSpaceOne { + s = @"- 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testInitSig { + s = @"- (id)init {"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); +} + + +- (void)testInitSig2 { + s = @"-(id)init {"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); +} + + +- (void)testParenStuff { + s = @"-(ab+5)"; + t.string = s; + r.string = s; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); +} + +@end diff --git a/test/.svn/text-base/TDParseTreeTest.h.svn-base b/test/.svn/text-base/TDParseTreeTest.h.svn-base new file mode 100644 index 0000000..9c2d051 --- /dev/null +++ b/test/.svn/text-base/TDParseTreeTest.h.svn-base @@ -0,0 +1,28 @@ +// +// TDParseTreeTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/1/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" +#import "PKParseTreeAssembler.h" + + +@interface TDParseTreeTest : SenTestCase { + PKParserFactory *factory; + PKParseTreeAssembler *as; + NSString *g; + NSString *s; + PKTokenAssembly *a; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; + PKToken *tok; +} + +@end diff --git a/test/.svn/text-base/TDParseTreeTest.m.svn-base b/test/.svn/text-base/TDParseTreeTest.m.svn-base new file mode 100644 index 0000000..f3e3a5e --- /dev/null +++ b/test/.svn/text-base/TDParseTreeTest.m.svn-base @@ -0,0 +1,164 @@ +// +// TDParseTreeTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/1/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDParseTreeTest.h" + +@implementation TDParseTreeTest + +- (void)setUp { + factory = [PKParserFactory factory]; + as = [[[PKParseTreeAssembler alloc] init] autorelease]; +} + + +- (void)testAddExpr { + g = @"@start = expr;" + @"expr = addExpr;" + @"addExpr = atom (('+'|'-') atom)*;" + @"atom = Number;"; + lp = [factory parserFromGrammar:g assembler:as preassembler:as]; + + lp.tokenizer.string = @"1 + 2"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp completeMatchFor:a]; + TDNotNil(res); + TDEqualObjects([res description], @"[]1/+/2^"); + + PKParseTree *tr = res.target; + TDEqualObjects([tr class], [PKParseTree class]); + TDEquals([[tr children] count], (NSUInteger)1); + + PKRuleNode *expr = [[tr children] objectAtIndex:0]; + TDEqualObjects([expr name], @"expr"); + TDEqualObjects([expr class], [PKRuleNode class]); + TDEquals([[expr children] count], (NSUInteger)1); + + PKRuleNode *addExpr = [[expr children] objectAtIndex:0]; + TDEqualObjects([addExpr name], @"addExpr"); + TDEqualObjects([addExpr class], [PKRuleNode class]); + TDEquals([[addExpr children] count], (NSUInteger)3); + + PKRuleNode *atom1 = [[addExpr children] objectAtIndex:0]; + TDEqualObjects([atom1 class], [PKRuleNode class]); + TDEqualObjects([atom1 name], @"atom"); + TDEquals([[atom1 children] count], (NSUInteger)1); + + PKTokenNode *one = [[atom1 children] objectAtIndex:0]; + TDEqualObjects([one class], [PKTokenNode class]); + TDEqualObjects([one token], [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:@"1" floatValue:1.0]); + + PKTokenNode *plus = [[addExpr children] objectAtIndex:1]; + TDEqualObjects([plus class], [PKTokenNode class]); + TDEqualObjects([plus token], [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"+" floatValue:0]); + + PKRuleNode *atom2 = [[addExpr children] objectAtIndex:2]; + TDEqualObjects([atom2 class], [PKRuleNode class]); + TDEqualObjects([atom2 name], @"atom"); + TDEquals([[atom2 children] count], (NSUInteger)1); + + PKTokenNode *two = [[atom2 children] objectAtIndex:0]; + TDEqualObjects([two class], [PKTokenNode class]); + TDEqualObjects([two token], [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:@"2" floatValue:2.0]); +} + + +- (void)testFoo { + g = @"@start = expr;" + @"expr = Word+;"; + lp = [factory parserFromGrammar:g assembler:as preassembler:as]; + + lp.tokenizer.string = @"foo"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp completeMatchFor:a]; + TDNotNil(res); + TDEqualObjects([res description], @"[]foo^"); + + PKParseTree *tr = res.target; + TDEqualObjects([tr class], [PKParseTree class]); + TDEquals([[tr children] count], (NSUInteger)1); + + PKRuleNode *expr = [[tr children] objectAtIndex:0]; + TDEqualObjects([expr name], @"expr"); + TDEqualObjects([expr class], [PKRuleNode class]); + TDEquals([[expr children] count], (NSUInteger)1); + + PKTokenNode *foo = [[expr children] objectAtIndex:0]; + TDEqualObjects([foo class], [PKTokenNode class]); + TDEqualObjects([foo token], [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:@"foo" floatValue:0.0]); +} + + +- (void)testFooBar { + g = @"@start = expr;" + @"expr = Word+;"; + lp = [factory parserFromGrammar:g assembler:as preassembler:as]; + + lp.tokenizer.string = @"foo bar"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp completeMatchFor:a]; + TDNotNil(res); + TDEqualObjects([res description], @"[]foo/bar^"); + + PKParseTree *tr = res.target; + TDEqualObjects([tr class], [PKParseTree class]); + TDEquals([[tr children] count], (NSUInteger)1); + + PKRuleNode *expr = [[tr children] objectAtIndex:0]; + TDEqualObjects([expr name], @"expr"); + TDEqualObjects([expr class], [PKRuleNode class]); + TDEquals([[expr children] count], (NSUInteger)2); + + PKTokenNode *foo = [[expr children] objectAtIndex:0]; + TDEqualObjects([foo class], [PKTokenNode class]); + TDEqualObjects([foo token], [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:@"foo" floatValue:0.0]); + + PKTokenNode *bar = [[expr children] objectAtIndex:1]; + TDEqualObjects([bar class], [PKTokenNode class]); + TDEqualObjects([bar token], [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:@"bar" floatValue:0.0]); +} + + +- (void)testArray { + g = @"@start = array;" + @"array = '[' Number (commaNumber)* ']';" + @"commaNumber = ',' Number;"; + + lp = [factory parserFromGrammar:g assembler:as preassembler:as]; + + lp.tokenizer.string = @"[1,2]"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp completeMatchFor:a]; + TDNotNil(res); + TDEqualObjects([res description], @"[][/1/,/2/]^"); + + PKRuleNode *root = res.target; + PKRuleNode *array = [[root children] objectAtIndex:0]; + + TDEqualObjects([array name], @"array"); + TDEqualObjects([array class], [PKRuleNode class]); + TDEquals([[array children] count], (NSUInteger)4); + + PKTokenNode *open = [[array children] objectAtIndex:0]; + TDEqualObjects([open class], [PKTokenNode class]); + TDEqualObjects([open token], [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"[" floatValue:0.0]); + + PKTokenNode *one = [[array children] objectAtIndex:1]; + TDEqualObjects([one class], [PKTokenNode class]); + TDEqualObjects([one token], [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:@"1" floatValue:1.0]); + + PKRuleNode *commaNumber = [[array children] objectAtIndex:2]; + TDEqualObjects([commaNumber name], @"commaNumber"); + TDEqualObjects([commaNumber class], [PKRuleNode class]); + TDEquals([[commaNumber children] count], (NSUInteger)2); + + PKTokenNode *close = [[array children] objectAtIndex:3]; + TDEqualObjects([close class], [PKTokenNode class]); + TDEqualObjects([close token], [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"]" floatValue:1.0]); +} + +@end diff --git a/test/.svn/text-base/TDParserBlocksTest.h.svn-base b/test/.svn/text-base/TDParserBlocksTest.h.svn-base new file mode 100644 index 0000000..b468aab --- /dev/null +++ b/test/.svn/text-base/TDParserBlocksTest.h.svn-base @@ -0,0 +1,17 @@ +// +// TDParserBlocksTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 9/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDParserBlocksTest : SenTestCase { + PKAssembly *start; + NSString *s; + PKParser *p; +} + +@end diff --git a/test/.svn/text-base/TDParserBlocksTest.m.svn-base b/test/.svn/text-base/TDParserBlocksTest.m.svn-base new file mode 100644 index 0000000..82a7e2d --- /dev/null +++ b/test/.svn/text-base/TDParserBlocksTest.m.svn-base @@ -0,0 +1,84 @@ +// +// TDParserBlocksTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 9/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDParserBlocksTest.h" + +@implementation TDParserBlocksTest + +- (void)setUp { +} + + +- (void)tearDown { +} + + +#ifdef TARGET_OS_SNOW_LEOPARD +- (void)testMath { + s = @"2 4 6 8"; + start = [PKTokenAssembly assemblyWithString:s]; + + PKNumber *n = [PKNumber number]; + p = [PKRepetition repetitionWithSubparser:n]; + + n.assemblerBlock = ^(PKAssembly *a) { + if (![a isStackEmpty]) { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; + } + }; + + p.assemblerBlock = ^(PKAssembly *a) { + NSNumber *total = [a pop]; + if (!total) { + total = [NSNumber numberWithFloat:0]; + } + + while (![a isStackEmpty]) { + NSNumber *n = [a pop]; + total = [NSNumber numberWithFloat:[total floatValue] + [n floatValue]]; + } + + [a push:total]; + }; + + PKAssembly *result = [p completeMatchFor:start]; + TDNotNil(result); + TDEqualObjects(@"[20]2/4/6/8^", [result description]); + TDEquals((double)20.0, [[result pop] doubleValue]); +} + + +- (void)testMath2 { + PKParser *addParser = [PKRepetition repetitionWithSubparser:[PKNumber number]]; + + addParser.assemblerBlock = ^(PKAssembly *a) { + NSArray *toks = [a objectsAbove:nil]; + double total = 0.0; + + for (PKToken *tok in toks) { + total += [tok floatValue]; + } + + [a push:[NSNumber numberWithDouble:total]]; + }; + + s = @"2.5 -5.5 8"; + +// NSNumber *result = [addParser parse:s]; +// NSAssert([result doubleValue] == 5.0, @""); + + start = [PKTokenAssembly assemblyWithString:s]; + PKAssembly *result = [addParser completeMatchFor:start]; + TDNotNil(result); + TDEqualObjects(@"[5]2.5/-5.5/8^", [result description]); + TDEquals(5.0, [(NSNumber *)[result pop] doubleValue]); +} +#endif + +@end diff --git a/test/.svn/text-base/TDParserFactoryPatternTest.h.svn-base b/test/.svn/text-base/TDParserFactoryPatternTest.h.svn-base new file mode 100644 index 0000000..62d6b62 --- /dev/null +++ b/test/.svn/text-base/TDParserFactoryPatternTest.h.svn-base @@ -0,0 +1,22 @@ +// +// PKParserFactoryPatternTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/6/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" + +@interface TDParserFactoryPatternTest : SenTestCase { + NSString *g; + NSString *s; + PKTokenAssembly *a; + PKParserFactory *factory; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; +} + +@end diff --git a/test/.svn/text-base/TDParserFactoryPatternTest.m.svn-base b/test/.svn/text-base/TDParserFactoryPatternTest.m.svn-base new file mode 100644 index 0000000..7914638 --- /dev/null +++ b/test/.svn/text-base/TDParserFactoryPatternTest.m.svn-base @@ -0,0 +1,84 @@ +// +// PKParserFactoryPatternTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/6/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDParserFactoryPatternTest.h" + +@implementation TDParserFactoryPatternTest + +- (void)setUp { + factory = [PKParserFactory factory]; +} + + +- (void)test1 { + g = @"@start = /foo/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + + g = @"@start = /fo+/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + + g = @"@start = /fo+/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + + g = @"@start = /[fo]+/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + + g = @"@start = /\\w+/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)testOptions { + g = @"@start = /foo/i;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"FOO"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[FOO]FOO^", [res description]); + + + g = @"@start = /foo/i;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"FoO"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[FoO]FoO^", [res description]); +} + +@end diff --git a/test/.svn/text-base/TDParserFactoryTest.h.svn-base b/test/.svn/text-base/TDParserFactoryTest.h.svn-base new file mode 100644 index 0000000..1d65617 --- /dev/null +++ b/test/.svn/text-base/TDParserFactoryTest.h.svn-base @@ -0,0 +1,23 @@ +// +// PKParserFactoryTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf All rights reserved. +// + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" + +@interface TDParserFactoryTest : SenTestCase { + NSString *s; + PKTokenAssembly *a; + PKParserFactory *factory; + PKAssembly *res; + + PKSequence *exprSeq; + PKTokenizer *t; + PKParser *lp; // language parser +} + +@end diff --git a/test/.svn/text-base/TDParserFactoryTest.m.svn-base b/test/.svn/text-base/TDParserFactoryTest.m.svn-base new file mode 100644 index 0000000..1c863ae --- /dev/null +++ b/test/.svn/text-base/TDParserFactoryTest.m.svn-base @@ -0,0 +1,1256 @@ +// +// PKParserFactoryTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf All rights reserved. +// + +#import "TDParserFactoryTest.h" +#import + +@interface PKParserFactory () +- (PKTokenizer *)tokenizerForParsingGrammar; +- (PKSequence *)parserFromExpression:(NSString *)s; +@property (retain) PKCollectionParser *exprParser; +@end + +@protocol TDMockAssember +- (void)didMatchFoo:(PKAssembly *)a; +- (void)didMatchBaz:(PKAssembly *)a; +- (void)didMatchStart:(PKAssembly *)a; +- (void)didMatchStart:(PKAssembly *)a; +- (void)didMatch_Start:(PKAssembly *)a; +@end + +@implementation TDParserFactoryTest + +- (void)setUp { + factory = [PKParserFactory factory]; + PKSequence *seq = [PKSequence sequence]; + [seq add:factory.exprParser]; + exprSeq = seq; + t = [factory tokenizerForParsingGrammar]; +} + + +- (void)testJavaScript { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"javascript" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"var foo = 'bar';"; + lp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; +// res = [lp bestMatchFor:a]; +// TDEqualObjects(@"[var, foo, =, 'bar', ;]var/foo/=/bar/;^", [res description]); +} + + +- (void)testCSS2_1 { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"css2_1" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + +// s = @"foo {font-size:12px}"; +// a = [PKTokenAssembly assemblyWithString:s]; +// res = [lp bestMatchFor:a]; +// TDEqualObjects(@"[foo, {, font-family, :, 'helvetica', ;, }]foo/{/font-family/:/'helvetica'/;/}^", [res description]); +} + + +- (void)testCSS { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + PKParser *selectorParser = [lp parserNamed:@"selector"]; + TDNotNil(selectorParser); + TDEqualObjects(selectorParser.name, @"selector"); + TDEqualObjects([selectorParser class], [PKLowercaseWord class]); + + PKParser *declParser = [lp parserNamed:@"decl"]; + TDNotNil(declParser); + TDEqualObjects(declParser.name, @"decl"); + TDEqualObjects([declParser class], [PKSequence class]); + + PKParser *rulesetParser = [lp parserNamed:@"ruleset"]; + TDNotNil(rulesetParser); + TDEqualObjects(rulesetParser, [(PKRepetition *)lp subparser]); + TDEqualObjects(rulesetParser.name, @"ruleset"); + TDEqualObjects([rulesetParser class], [PKSequence class]); + + PKParser *startParser = [lp parserNamed:@"@start"]; + TDNotNil(startParser); + TDEqualObjects(startParser, lp); + TDEqualObjects(startParser.name, @"@start"); + TDEqualObjects([startParser class], [PKRepetition class]); + + s = @"foo {font-family:'helvetica';}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, {, font-family, 'helvetica']foo/{/font-family/:/'helvetica'/;/}^", [res description]); + + s = @"foo {font-family:'helvetica'}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, {, font-family, 'helvetica']foo/{/font-family/:/'helvetica'/}^", [res description]); + + s = @"bar {color:rgb(1, 255, 255); font-size:13px;}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar, {, color, (, 1, 255, 255, font-size, 13]bar/{/color/:/rgb/(/1/,/255/,/255/)/;/font-size/:/13/px/;/}^", [res description]); + + s = @"bar {color:rgb(1, 255, 47.0); font-family:'Helvetica'}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar, {, color, (, 1, 255, 47.0, font-family, 'Helvetica']bar/{/color/:/rgb/(/1/,/255/,/47.0/)/;/font-family/:/'Helvetica'/}^", [res description]); + + s = @"foo {font-family:'Lucida Grande'} bar {color:rgb(1, 255, 255); font-size:9px;}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, {, font-family, 'Lucida Grande', bar, {, color, (, 1, 255, 255, font-size, 9]foo/{/font-family/:/'Lucida Grande'/}/bar/{/color/:/rgb/(/1/,/255/,/255/)/;/font-size/:/9/px/;/}^", [res description]); +} + + +- (void)testJSON { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"{'foo':'bar'}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', :, 'bar', }]{/'foo'/:/'bar'/}^", [res description]); + + s = @"{'foo':{}}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', :, {, }, }]{/'foo'/:/{/}/}^", [res description]); + + s = @"{'foo':{'bar':[]}}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', :, {, 'bar', :, [, ], }, }]{/'foo'/:/{/'bar'/:/[/]/}/}^", [res description]); + + s = @"['foo', true, null]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, 'foo', ,, true, ,, null, ]][/'foo'/,/true/,/null/]^", [res description]); + + s = @"[[]]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, [, ], ]][/[/]/]^", [res description]); + + s = @"[[[1]]]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, [, [, 1, ], ], ]][/[/[/1/]/]/]^", [res description]); +} + + +- (void)testJSONWithDiscards { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json_with_discards" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"{'foo':'bar'}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', 'bar']{/'foo'/:/'bar'/}^", [res description]); + + s = @"{'foo':{}}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', {]{/'foo'/:/{/}/}^", [res description]); + + s = @"{'foo':{'bar':[]}}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', {, 'bar', []{/'foo'/:/{/'bar'/:/[/]/}/}^", [res description]); + + s = @"['foo', true, null]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, 'foo'][/'foo'/,/true/,/null/]^", [res description]); + + s = @"[[]]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, [][/[/]/]^", [res description]); + + s = @"[[[1]]]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, [, [, 1][/[/[/1/]/]/]^", [res description]); +} + + +- (void)testStartLiteral { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = 'bar';"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralNonReserved { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo*; foo = 'bar';"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bar]bar/bar^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralNonReserved2 { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = (foo|baz)*; foo = 'bar'; baz = 'bat'"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + s = @"bar bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bat]bar/bat^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralNonReserved3 { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = (foo|baz)+; foo = 'bar'; baz = 'bat'"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + s = @"bar bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bat]bar/bat^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralNonReserved4 { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = (foo|baz)+; foo = 'bar'; baz = 'bat'"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + s = @"bar bat bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bat, bat]bar/bat/bat^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorDefault { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo = 'bar'; baz = 'bat'"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnAll { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo = 'bar'; baz = 'bat'"; + factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnAll; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnTerminals { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo = 'bar'; baz = 'bat'"; + factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnTerminals; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDNil(lp.assembler); + TDNil(NSStringFromSelector(lp.assemblerSelector)); + + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnExplicit { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo (didMatchFoo:) = 'bar'; baz (didMatchBaz:) = 'bat'"; + factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnExplicit; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDNil(lp.assembler); + TDNil(NSStringFromSelector(lp.assemblerSelector)); + + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnExplicitNone { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo = 'bar'; baz = 'bat'"; + factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnExplicit; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDNil(lp.assembler); + TDNil(NSStringFromSelector(lp.assemblerSelector)); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnExplicitOrTerminal { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = (foo|baz)+; foo (didMatchFoo:) = 'bar'; baz = 'bat'"; + factory.assemblerSettingBehavior = (PKParserFactoryAssemblerSettingBehaviorOnExplicit | PKParserFactoryAssemblerSettingBehaviorOnTerminals); + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDNil(lp.assembler); + TDNil(NSStringFromSelector(lp.assemblerSelector)); + + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + s = @"bar bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bat]bar/bat^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralWithCallback { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start (didMatchStart:) = 'bar';"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDTrue(lp.assembler == mock); + TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatchStart:"); + + [[mock expect] didMatchStart:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testStartRefToLiteral { + s = @" @start = foo; foo = 'bar';"; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); +} + + +- (void)testStartRefToLiteral3 { + s = @" @start = foo|baz; baz = 'bat'; foo = 'bar';"; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); +} + + +- (void)testStartRefToLiteral2 { + s = @"foo = 'bar'; baz = 'bat'; @start = (foo | baz)*;"; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + + s = @"bat bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bat, bat]bat/bat^", [res description]); + + s = @"bat bat bat bat bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bat, bat, bat, bat, bar]bat/bat/bat/bat/bar^", [res description]); +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testStmtTrackException { + s = @"@start ="; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testCallbackTrackException { + s = @"@start ( = 'foo';"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start (foo: = 'foo'"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testSelectorTrackException { + s = @"@start (foo) = 'foo';"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testOrTrackException { + s = @"@start = 'foo'|;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +//- (void)testExprTrackException { +// s = @"@start=(foo;"; +// STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +//} + + +- (void)testIntersectionTrackException { + s = @"@start='foo' &;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testExclusionTrackException { + s = @"@start='foo' -;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testDelimitedStringTrackException { + s = @"@start=DelimitedString('/';"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start=DelimitedString('/', ;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testCardinalityTrackException { + s = @"@start='foo'{;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start='foo'{};"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start='foo'{,};"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start='foo'{m};"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} +#endif + + +- (void)testExprHelloPlus { + s = @"'hello'+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello, hello]hello/hello^", [res description]); +} + + +- (void)testExprHelloStar { + s = @"'hello'*"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKRepetition class]); + + s = @"hello hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello, hello, hello]hello/hello/hello^", [res description]); +} + + +- (void)testExprHelloQuestion { + s = @"'hello'?"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKAlternation class]); + + s = @"hello hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello]hello^hello/hello", [res description]); +} + + +- (void)testExprOhHaiThereQuestion { + s = @"'oh'? 'hai'? 'there'?"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"there"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[there]there^", [res description]); +} + + +- (void)testExprFooBar { + s = @"'foo' 'bar'"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]'foo'/ /'bar'^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + TDEquals((NSUInteger)2, [seq.subparsers count]); + + PKLiteral *c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + c = [seq.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, bar]foo/bar^", [res description]); +} + + +- (void)testExprFooBarBaz { + s = @"'foo' 'bar' 'baz'"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]'foo'/ /'bar'/ /'baz'^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + TDEquals((NSUInteger)3, [seq.subparsers count]); + + PKLiteral *c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + c = [seq.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + c = [seq.subparsers objectAtIndex:2]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"baz", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [res description]); +} + + +- (void)testExprFooOrBar { + s = @"'foo'|'bar'"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]'foo'/|/'bar'^", [res description]); + + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKAlternation class]); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)testExprFooOrBarStar { + s = @"'foo'|'bar'*"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]'foo'/|/'bar'/*^", [res description]); + + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + PKRepetition *rep = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKRepetition class], [rep class]); + c = (PKLiteral *)rep.subparser; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKAlternation class]]); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"foo foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^foo", [res description]); + + s = @"bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar, bar]bar/bar^", [res description]); +} + + +- (void)testExprFooOrBarPlus { + s = @"'foo'|'bar'+"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]'foo'/|/'bar'/+^", [res description]); + + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + PKSequence *seq = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKSequence class], [seq class]); + + c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + PKRepetition *rep = [seq.subparsers objectAtIndex:1]; + TDEqualObjects([PKRepetition class], [rep class]); + c = (PKLiteral *)rep.subparser; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKAlternation class]]); + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"foo foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^foo", [res description]); + + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^bar", [res description]); + + s = @"bar bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar, bar, bar]bar/bar/bar^", [res description]); +} + + +- (void)testExprFooOrBarQuestion { + s = @"'foo'|'bar'?"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]'foo'/|/'bar'/?^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + alt = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKAlternation class], [alt class]); + + PKEmpty *e = [alt.subparsers objectAtIndex:0]; + TDTrue([e isMemberOfClass:[PKEmpty class]]); + + c = (PKLiteral *)[alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKAlternation class]]); + s = @"bar bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^bar/bar", [res description]); + + s = @"foo bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^bar/bar", [res description]); +} + + +- (void)testExprParenFooOrBarParenStar { + s = @"('foo'|'bar')*"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Repetition](/'foo'/|/'bar'/)/*^", [res description]); + PKRepetition *rep = [res pop]; + TDTrue([rep isMemberOfClass:[PKRepetition class]]); + + PKAlternation *alt = (PKAlternation *)rep.subparser; + TDTrue([alt class] == [PKAlternation class]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKRepetition class]); + s = @"foo bar bar foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, bar, bar, foo]foo/bar/bar/foo^", [res description]); +} + + +- (void)testExprParenFooOrBooParenPlus { + s = @"('foo'|'bar')+"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence](/'foo'/|/'bar'/)/+^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + + TDEquals((NSUInteger)2, [seq.subparsers count]); + + PKAlternation *alt = [seq.subparsers objectAtIndex:0]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + PKRepetition *rep = [seq.subparsers objectAtIndex:1]; + TDTrue([rep isMemberOfClass:[PKRepetition class]]); + + alt = (PKAlternation *)rep.subparser; + TDEqualObjects([PKAlternation class], [alt class]); + + c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"foo foo bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, foo, bar, bar]foo/foo/bar/bar^", [res description]); +} + + +- (void)testExprParenFooOrBarParenQuestion { + s = @"('foo'|'bar')?"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation](/'foo'/|/'bar'/)/?^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + + TDEquals((NSUInteger)2, [alt.subparsers count]); + PKEmpty *e = [alt.subparsers objectAtIndex:0]; + TDTrue([PKEmpty class] == [e class]); + + alt = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([alt class], [PKAlternation class]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKAlternation class]); + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^bar", [res description]); + + s = @"bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^bar", [res description]); +} + + +- (void)testExprWord { + s = @"Word"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Word]Word^", [res description]); + PKWord *w = [res pop]; + TDTrue([w isMemberOfClass:[PKWord class]]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKWord class]); + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello]hello^hello", [res description]); +} + + +- (void)testExprWordPlus { + s = @"Word+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello, hello]hello/hello^", [res description]); +} + + +- (void)testExprNum { + s = @"Number"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Number]Number^", [res description]); + PKNumber *w = [res pop]; + TDTrue([w isMemberOfClass:[PKNumber class]]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKNumber class]]); + + s = @"333 444"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[333]333^444", [res description]); + + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDNil(res); +} + + +- (void)testExprNumCardinality { + s = @"Number{2}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]Number/{/2/}^", [res description]); + PKSequence *seq = [res pop]; + TDEqualObjects([seq class], [PKSequence class]); + + TDEquals((NSUInteger)2, [seq.subparsers count]); + PKNumber *n = [seq.subparsers objectAtIndex:0]; + TDEqualObjects([n class], [PKNumber class]); + + n = [seq.subparsers objectAtIndex:1]; + TDEqualObjects([n class], [PKNumber class]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + + s = @"333 444"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[333, 444]333/444^", [res description]); + + s = @"1.1 2.2 3.3"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[1.1, 2.2]1.1/2.2^3.3", [res description]); + + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDNil(res); +} + + +- (void)testExprNumCardinality2 { + s = @"Number{2,3}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]Number/{/2/,/3/}^", [res description]); + PKSequence *seq = [res pop]; + TDEqualObjects([seq class], [PKSequence class]); + + TDEquals((NSUInteger)3, [seq.subparsers count]); + + PKNumber *n = [seq.subparsers objectAtIndex:0]; + TDEqualObjects([n class], [PKNumber class]); + + n = [seq.subparsers objectAtIndex:1]; + TDEqualObjects([n class], [PKNumber class]); + + n = [seq.subparsers objectAtIndex:2]; + TDEqualObjects([n class], [PKAlternation class]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + + s = @"333 444"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[333, 444]333/444^", [res description]); + + s = @"1.1 2.2 3.3"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[1.1, 2.2, 3.3]1.1/2.2/3.3^", [res description]); + + s = @"1.1 2.2 3.3 4"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[1.1, 2.2, 3.3]1.1/2.2/3.3^4", [res description]); + + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDNil(res); +} + + +- (void)testExprNumPlus { + s = @"Number+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + s = @"333 444"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[333, 444]333/444^", [res description]); +} + + +- (void)testExprSymbol { + s = @"Symbol"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Symbol]Symbol^", [res description]); + PKSymbol *w = [res pop]; + TDTrue([w isMemberOfClass:[PKSymbol class]]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSymbol class]]); + + s = @"? #"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[?]?^#", [res description]); + + s = @"hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDNil(res); +} + + +- (void)testExprSymbolPlus { + s = @"Symbol+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + s = @"% *"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[%, *]%/*^", [res description]); +} + + +- (void)testExprQuotedString { + s = @"QuotedString"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[QuotedString]QuotedString^", [res description]); + PKQuotedString *w = [res pop]; + TDTrue([w isMemberOfClass:[PKQuotedString class]]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKQuotedString class]); + s = @"'hello' 'hello'"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"['hello']'hello'^'hello'", [res description]); +} + + +- (void)testExprQuotedStringPlus { + s = @"QuotedString+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + s = @"'hello' 'hello'"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"['hello', 'hello']'hello'/'hello'^", [res description]); +} + + +- (void)testRubyHash { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"rubyhash" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + +// s = @"{\"brand\"=>{\"name\"=>\"something\"," +// @"\"logo\"=>#," +// @"\"summary\"=>\"wee\", \"content\"=>\"woopy doo\"}, \"commit\"=>\"Save\"," +// @"\"authenticity_token\"=>\"43a94d60304a7fb13a4ff61a5960461ce714e92b\"," +// @"\"action\"=>\"create\", \"controller\"=>\"admin/brands\"}"; + + lp.tokenizer.string = @"{'foo'=> {'logo' => # } }"; + + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', =>, {, 'logo', =>, #, }, }]{/'foo'/=>/{/'logo'/=>/#/}/}^", [res description]); +} + + +- (void)testSymbolState { + s = @"@symbolState = 'b'; @start = ('b'|'ar')*;"; + lp = [factory parserFromGrammar:s assembler:nil]; + + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + lp.tokenizer.string = @"bar"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[b, ar]b/ar^", [res description]); + [res pop]; // discar 'ar' + PKToken *tok = [res pop]; + TDEqualObjects([tok class], [PKToken class]); + TDEqualObjects(tok.stringValue, @"b"); + TDTrue(tok.isSymbol); +} + +@end \ No newline at end of file diff --git a/test/.svn/text-base/TDParserFactoryTest2.h.svn-base b/test/.svn/text-base/TDParserFactoryTest2.h.svn-base new file mode 100644 index 0000000..269074c --- /dev/null +++ b/test/.svn/text-base/TDParserFactoryTest2.h.svn-base @@ -0,0 +1,23 @@ +// +// PKParserFactoryTest2.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/31/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" + +@interface TDParserFactoryTest2 : SenTestCase { + NSString *g; + NSString *s; + PKTokenAssembly *a; + PKParserFactory *factory; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; + PKToken *tok; +} + +@end diff --git a/test/.svn/text-base/TDParserFactoryTest2.m.svn-base b/test/.svn/text-base/TDParserFactoryTest2.m.svn-base new file mode 100644 index 0000000..0a3667e --- /dev/null +++ b/test/.svn/text-base/TDParserFactoryTest2.m.svn-base @@ -0,0 +1,704 @@ +// +// PKParserFactoryTest2.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/31/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDParserFactoryTest2.h" + +@implementation TDParserFactoryTest2 + +- (void)setUp { + factory = [PKParserFactory factory]; +} + + +- (void)testOrVsAndPrecendence { + g = @"@start = Word | Number Symbol;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"foo %"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + g = @"@start = Word Number | Symbol;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo 3"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 3]foo/3^", [res description]); + + s = @"%"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[%]%^", [res description]); + + s = @"foo %"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + g = @"@start = Word (Number | Symbol);"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo 3"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 3]foo/3^", [res description]); + + s = @"foo"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + s = @"foo %"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, %]foo/%^", [res description]); +} + + +- (void)test1 { + g = @"@start = (Word | Number)*;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"24.5"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[24.5]24.5^", [res description]); + + s = @"foo bar 2 baz"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, baz]foo/bar/2/baz^", [res description]); + + s = @"foo bar 2 4 baz"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, 4, baz]foo/bar/2/4/baz^", [res description]); +} + + +- (void)test2 { + g = @"@start = (Word | Number)* QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 'bar']foo/'bar'^", [res description]); + + s = @"24.5 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[24.5, 'bar']24.5/'bar'^", [res description]); + + s = @"foo bar 2 baz 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, baz, 'bar']foo/bar/2/baz/'bar'^", [res description]); + + s = @"foo bar 2 4 baz 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, 4, baz, 'bar']foo/bar/2/4/baz/'bar'^", [res description]); +} + + +- (void)test3 { + g = @"@start = (Word | Number)* '$'+ QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, 'bar']foo/$/'bar'^", [res description]); + + s = @"foo $ $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, $, 'bar']foo/$/$/'bar'^", [res description]); + + s = @"24.5 $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[24.5, $, 'bar']24.5/$/'bar'^", [res description]); + + s = @"foo bar 2 baz $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, baz, $, 'bar']foo/bar/2/baz/$/'bar'^", [res description]); + + s = @"foo bar 2 4 baz $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, 4, baz, $, 'bar']foo/bar/2/4/baz/$/'bar'^", [res description]); +} + + +- (void)test4 { + g = @"@start = (Word | Number)* ('$' '%')+ QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, 'bar']foo/$/%/'bar'^", [res description]); + + s = @"foo $ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %, 'bar']foo/$/%/$/%/'bar'^", [res description]); +} + + +- (void)test5 { + g = @"@start = (Word | Number)* ('$' '%')+ QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, 'bar']foo/$/%/'bar'^", [res description]); + + s = @"foo $ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %, 'bar']foo/$/%/$/%/'bar'^", [res description]); + + s = @"foo 33 4 $ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 33, 4, $, %, $, %, 'bar']foo/33/4/$/%/$/%/'bar'^", [res description]); + + s = @"foo 33 bar 4 $ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 33, bar, 4, $, %, $, %, 'bar']foo/33/bar/4/$/%/$/%/'bar'^", [res description]); +} + + +- (void)test6 { + g = @"@start = ((Word | Number)* ('$' '%')+) | QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar']'bar'^", [res description]); + + s = @"foo $ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %]foo/$/%/$/%^", [res description]); +} + + +- (void)test7 { + g = @"@start = ((Word | Number)* ('$' '%')+) | QuotedString+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"'bar' 'foo'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar', 'foo']'bar'/'foo'^", [res description]); + + s = @"foo $ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %]foo/$/%/$/%^", [res description]); + + s = @"$ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[$, %, $, %]$/%/$/%^", [res description]); +} + + +- (void)test8 { + g = @"@start = ((Word | Number)* ('$' '%')+) | QuotedString+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"'bar' 'foo'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar', 'foo']'bar'/'foo'^", [res description]); + + s = @"foo $ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %]foo/$/%/$/%^", [res description]); + + s = @"$ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[$, %, $, %]$/%/$/%^", [res description]); +} + + +- (void)test9 { + g = @"@start = Word | (Number);"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"42"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[42]42^", [res description]); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)test10 { + g = @"@start = Word | (Number QuotedString);"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"42 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[42, 'bar']42/'bar'^", [res description]); +} + + +- (void)test11 { + g = @"@start = ((Word | Number)* | ('$' '%')+) QuotedString+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 'bar']foo/'bar'^", [res description]); + + s = @"$ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[$, %, $, %, 'bar']$/%/$/%/'bar'^", [res description]); +} + + +- (void)test12 { + g = @"@delimitState = '$'; @delimitedString = '$' '%' nil; @start = DelimitedString('$', '%');"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"$foo%"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[$foo%]$foo%^", [res description]); + + + g = @"@delimitState = '$'; @delimitedString = '$' '%' nil; @start = DelimitedString('$', '');"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"$foo%"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[$foo%]$foo%^", [res description]); + + + g = @"@delimitState = '$'; @delimitedString = '$' '%' 'fo'; @start = DelimitedString('$', '%');"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"$foo%"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[$foo%]$foo%^", [res description]); + + + g = @"@delimitState = '$'; @delimitedString = '$' '%' 'f'; @start = DelimitedString('$', '%');"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"$foo%"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testWhitespace { + g = @"@reportsWhitespaceTokens = YES; @start = 'foo' S '+' S 'bar';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo + bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, , +, , bar]foo/ /+/ /bar^", [res description]); + + s = @"foo +bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + g = @"@start = 'foo' S '+' S 'bar';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo + bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + g = @"@reportsWhitespaceTokens = NO; @start = 'foo' S '+' S 'bar';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo + bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + + g = @"@reportsWhitespaceTokens = YES; @start = 'foo' S '+' S 'bar';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo \t \t + bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, \t \t , +, , bar]foo/ \t \t /+/ /bar^", [res description]); +} + + +- (void)testDiscard { + g = @"@start = 'foo'!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]foo^", [res description]); + + g = @"@start = /foo/!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]foo^", [res description]); + + g = @"@delimitState='<'; @delimitedStrings='<%' '%>' nil; @start=DelimitedString('<%', '%>')!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"<% foo %>"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]<% foo %>^", [res description]); +} + + +- (void)testDiscard2 { + g = @"@reportsWhitespaceTokens=YES;@start=S!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @" "; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[] ^", [res description]); + + g = @"@start=Any!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]foo^", [res description]); + + g = @"@start=Word!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]foo^", [res description]); + +} + + +- (void)testComments { + g = + @"@commentState = '/';" + @"@singleLineComments = '//';" + @"@reportsCommentTokens = YES;" + @"@start = Any+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"# // foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[#, // foo]#/// foo^", [res description]); + + tok = [res pop]; + TDTrue(tok.isComment); + +} + + + +- (void)testFallbackState { + g = + @"@commentState = '/';" + @"@commentState.fallbackState = delimitState;" + @"@delimitedString = '/' '/' nil;" + @"@singleLineComments = '//';" + @"@multiLineComments = '/*' '*/';" + @"@start = Any+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"/ %"; + t = lp.tokenizer; + + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, %]//%^", [res description]); + tok = [res pop]; + TDTrue(tok.isSymbol); + + s = @"/ /"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/ /]/ /^", [res description]); + tok = [res pop]; + TDTrue(tok.isDelimitedString); + + s = @"/foo/"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/foo/]/foo/^", [res description]); + tok = [res pop]; + TDTrue(tok.isDelimitedString); + + s = @"# // foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[#]#^", [res description]); + tok = [res pop]; + TDTrue(tok.isSymbol); + +} + + +- (void)testPatternPredicate1 { + g = @"@wordChar = ':'; @start = Word;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"foo:bar"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo:bar]foo:bar^", [res description]); + tok = [res pop]; + TDTrue(tok.isWord); + + g = @"@wordChar = ':'; @start = Word & /[^:]+/;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + tok = [res pop]; + TDTrue(tok.isWord); + + s = @"foo:bar"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testPatternPredicate2 { + g = @"@wordChar = ':'; @start=ncName+; name=Word; ncName=name & /[^:]+/;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + tok = [res pop]; + TDTrue(tok.isWord); + + s = @"foo:bar"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testExclusionFoo { + g = @"@start = ex; ex = Word - 'foo';"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"bar"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[bar]bar^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[wee]wee^", [res description]); +} + + +- (void)testExclusionAlt { + g = @"@start = ex; m = ('foo'|'bar'); ex = Word - m;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[wee]wee^", [res description]); +} + + +- (void)testExclusionAlt2 { + g = @"@start = ex; ex = Word - ('foo'|'bar');"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[wee]wee^", [res description]); +} + + +- (void)testExclusionAlt3 { + g = @"@start = ex; s = 'foo'|'baz'; m = ('foo'|'bar'); ex = s - m;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testExclusionAlt4 { + g = @"@start = ex; m = ('foo'|'bar'); ex = ('foo'|'baz') - m;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testExclusionAlt5 { + g = @"@start = ex; ex = ('foo'|'baz') - ('foo'|'bar');"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + +@end diff --git a/test/.svn/text-base/TDParserFactoryTest3.h.svn-base b/test/.svn/text-base/TDParserFactoryTest3.h.svn-base new file mode 100644 index 0000000..493a9a8 --- /dev/null +++ b/test/.svn/text-base/TDParserFactoryTest3.h.svn-base @@ -0,0 +1,22 @@ +// +// PKParserFactoryTest3.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/27/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDParserFactoryTest3 : SenTestCase { + NSString *g; + NSString *s; + PKTokenAssembly *a; + PKParserFactory *factory; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; + PKToken *tok; +} + +@end diff --git a/test/.svn/text-base/TDParserFactoryTest3.m.svn-base b/test/.svn/text-base/TDParserFactoryTest3.m.svn-base new file mode 100644 index 0000000..dd4e6f8 --- /dev/null +++ b/test/.svn/text-base/TDParserFactoryTest3.m.svn-base @@ -0,0 +1,176 @@ +// +// PKParserFactoryTest3.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/27/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDParserFactoryTest3.h" + +@implementation TDParserFactoryTest3 + +- (void)setUp { + factory = [PKParserFactory factory]; +} + + +- (void)testOrVsAndPrecendence { + g = @" @start ( didMatchFoo: ) = foo;\n" + @" foo = Word & /foo/ | Number! { 1 } ( DelimitedString ( '/' , '/' ) Symbol- '%' ) * /bar/ ;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)testNegation { + g = @"@start = ~'foo';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + s = @"'bar'"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar']'bar'^", [res description]); + + s = @"bar"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[bar]bar^", [res description]); +} + + +- (void)testNegateSymbol { + g = @"@start = ~Symbol;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"1"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]1^", [res description]); + + s = @"'bar'"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar']'bar'^", [res description]); + + s = @"bar"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[bar]bar^", [res description]); + + s = @"$"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + +} + + +- (void)testNegateMore { + g = @"@start = ~Symbol & ~Number;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"1"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + s = @"$"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); +} + + +- (void)testNegateMore2 { + g = @"@start = ~(Symbol|Number);"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"1"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + s = @"$"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); +} + + +- (void)testNcName { + g = @"@wordChars=':' '_'; @wordState='_';" + @"@start = name;" + @"ncName = name & /[^:]+/;" + @"name = Word;"; + // @"nameTest = '*' | ncName ':' '*' | qName;" + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + t.string = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + t.string = @"foo:bar"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo:bar]foo:bar^", [res description]); +} + + +- (void)testFunctionName { + g = + @"@wordState = '_';" + @"@wordChars = '_' '.' '-';" + @"@start = functionName;" + @"functionName = qName - nodeType;" + @"nodeType = 'comment' | 'text' | 'processing-instruction' | 'node';" + @"qName = prefixedName | unprefixedName;" + @"prefixedName = prefix ':' localPart;" + @"unprefixedName = localPart;" + @"localPart = ncName;" + @"prefix = ncName;" + @"ncName = Word;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + t.string = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + t.string = @"foo:bar"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [res description]); + + t.string = @":bar"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"text"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"comment"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"node"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"processing-instruction"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"texts"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[texts]texts^", [res description]); + +} + +@end diff --git a/test/.svn/text-base/TDParserTest.h.svn-base b/test/.svn/text-base/TDParserTest.h.svn-base new file mode 100644 index 0000000..ac4d9ee --- /dev/null +++ b/test/.svn/text-base/TDParserTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDParserTest : SenTestCase { + PKAssembly *a; + NSString *s; + PKParser *p; +} + +@end diff --git a/test/.svn/text-base/TDParserTest.m.svn-base b/test/.svn/text-base/TDParserTest.m.svn-base new file mode 100644 index 0000000..e37188d --- /dev/null +++ b/test/.svn/text-base/TDParserTest.m.svn-base @@ -0,0 +1,177 @@ +// +// PKParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDParserTest.h" + +@implementation TDParserTest + +- (void)setUp { +} + + +- (void)tearDown { +} + + +#pragma mark - + +- (void)testMath { + s = @"2 4 6 8"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKRepetition repetitionWithSubparser:[PKNumber number]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[2, 4, 6, 8]2/4/6/8^", [result description]); +} + + +- (void)testMiniMath { + s = @"4.5 - 5.6 - 222.0"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKSequence *minusNum = [PKSequence sequence]; + [minusNum add:[[PKSymbol symbolWithString:@"-"] discard]]; + [minusNum add:[PKNumber number]]; + + PKSequence *e = [PKSequence sequence]; + [e add:[PKNumber number]]; + [e add:[PKRepetition repetitionWithSubparser:minusNum]]; + + PKAssembly *result = [e completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[4.5, 5.6, 222.0]4.5/-/5.6/-/222.0^", [result description]); +} + + +- (void)testMiniMathWithBrackets { + s = @"[4.5 - 5.6 - 222.0]"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKSequence *minusNum = [PKSequence sequence]; + [minusNum add:[[PKSymbol symbolWithString:@"-"] discard]]; + [minusNum add:[PKNumber number]]; + + PKSequence *e = [PKSequence sequence]; + [e add:[[PKSymbol symbolWithString:@"["] discard]]; + [e add:[PKNumber number]]; + [e add:[PKRepetition repetitionWithSubparser:minusNum]]; + [e add:[[PKSymbol symbolWithString:@"]"] discard]]; + + PKAssembly *result = [e completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[4.5, 5.6, 222.0][/4.5/-/5.6/-/222.0/]^", [result description]); +} + + +- (void)testHotHotSteamingHotCoffee { + PKAlternation *adjective = [PKAlternation alternation]; + [adjective add:[PKLiteral literalWithString:@"hot"]]; + [adjective add:[PKLiteral literalWithString:@"steaming"]]; + + PKRepetition *adjectives = [PKRepetition repetitionWithSubparser:adjective]; + + PKSequence *sentence = [PKSequence sequence]; + [sentence add:adjectives]; + [sentence add:[PKLiteral literalWithString:@"coffee"]]; + + s = @"hot hot steaming hot coffee"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKAssembly *result = [sentence bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[hot, hot, steaming, hot, coffee]hot/hot/steaming/hot/coffee^", [result description]); +} + + +- (void)testList { + PKAssembly *result = nil; + + PKSequence *commaTerm = [PKSequence sequence]; + [commaTerm add:[[PKSymbol symbolWithString:@","] discard]]; + [commaTerm add:[PKWord word]]; + + PKSequence *actualList = [PKSequence sequence]; + [actualList add:[PKWord word]]; + [actualList add:[PKRepetition repetitionWithSubparser:commaTerm]]; + + PKSequence *list = [PKSequence sequence]; + [list add:[[PKSymbol symbolWithString:@"["] discard]]; + [list add:actualList]; + [list add:[[PKSymbol symbolWithString:@"]"] discard]]; + + s = @"[foo, bar, baz]"; + a = [PKTokenAssembly assemblyWithString:s]; + + result = [list bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz][/foo/,/bar/,/baz/]^", [result description]); +} + + +- (void)testJavaScriptStatement { + s = @"123 'boo'"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKAlternation *literals = [PKAlternation alternation]; + [literals add:[PKQuotedString quotedString]]; + [literals add:[PKNumber number]]; + + PKAssembly *result = [literals bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[123]123^'boo'", [result description]); +} + + +- (void)testParserNamed { + + // seq = (foo|bar|seq) foo* w sy; + PKCollectionParser *seq = [PKSequence sequence]; + seq.name = @"seq"; + + PKCollectionParser *alt = [PKAlternation alternation]; + alt.name = @"alt"; + + PKParser *foo = [PKLiteral literalWithString:@"foo"]; + foo.name = @"w"; + [alt add:foo]; + + PKParser *bar = [PKLiteral literalWithString:@"bar"]; + bar.name = @"w"; + [alt add:bar]; + + [alt add:seq]; + + PKRepetition *r = [PKRepetition repetitionWithSubparser:foo]; + + PKWord *w = [PKWord word]; + w.name = @"w"; + + PKSymbol *sy = [PKSymbol symbol]; + sy.name = @"sy"; + + + [seq add:alt]; + [seq add:r]; + [seq add:w]; + [seq add:sy]; + + TDEquals(seq, [seq parserNamed:@"seq"]); + TDEquals(seq, [alt parserNamed:@"seq"]); + + TDEquals(alt, [seq parserNamed:@"alt"]); + TDEquals(w, [seq parserNamed:@"w"]); + TDEquals(sy, [seq parserNamed:@"sy"]); + + TDEquals(foo, [alt parserNamed:@"w"]); + TDEquals(foo, [r parserNamed:@"w"]); +} + +@end diff --git a/test/.svn/text-base/TDPatternTest.h.svn-base b/test/.svn/text-base/TDPatternTest.h.svn-base new file mode 100644 index 0000000..5dea5f3 --- /dev/null +++ b/test/.svn/text-base/TDPatternTest.h.svn-base @@ -0,0 +1,19 @@ +// +// PKPatternTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/31/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDPatternTest : SenTestCase { + PKTokenizer *t; + PKPattern *p; + PKIntersection *inter; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDPatternTest.m.svn-base b/test/.svn/text-base/TDPatternTest.m.svn-base new file mode 100644 index 0000000..4a144a3 --- /dev/null +++ b/test/.svn/text-base/TDPatternTest.m.svn-base @@ -0,0 +1,239 @@ +// +// PKPatternTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/31/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDPatternTest.h" + +@implementation TDPatternTest + +- (void)testFoo { + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"foo"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"foo"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"foo"]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKWord word]]; + + a = [inter completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"foo"]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKSymbol symbol]]; + + a = [inter completeMatchFor:a]; + + TDNil(a); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo+"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo*"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo{1,2}"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo{3,4}"]; + a = [p completeMatchFor:a]; + + TDNil(a); +} + + +- (void)testSlashFooSlash { + s = @"/foo/"; + + t = [PKTokenizer tokenizerWithString:s]; + [t setTokenizerState:t.quoteState from:'/' to:'/']; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + p = [PKPattern patternWithString:@"/foo/" options:PKPatternOptionsNone]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKQuotedString quotedString]]; + + a = [inter completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[/foo/]/foo/^"); + + t = [PKTokenizer tokenizerWithString:s]; + [t setTokenizerState:t.quoteState from:'/' to:'/']; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + p = [PKPattern patternWithString:@"/[^/]+/" options:PKPatternOptionsNone]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKQuotedString quotedString]]; + + a = [inter completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[/foo/]/foo/^"); +} + + +- (void)testAndOrOr { + s = @"and"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[and]and^"); + + s = @"and"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"an|or"]; + a = [p completeMatchFor:a]; + + TDNil(a); + + s = @"or"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"(and)|(or)"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[or]or^"); +} + + +- (void)testNotAnd { + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"[^and]+"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"and"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"[^(and)]"]; + a = [p completeMatchFor:a]; + + TDNil(a); +} + + +- (void)testInvertFoo { + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo+"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + p = [PKNegation negationWithSubparser:p]; + a = [p completeMatchFor:a]; + + TDNil(a); +} + + +- (void)testInvertAndOrNotTrueFalse { + s = @"true"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or|not|true|false"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[true]true^"); + + p = [PKNegation negationWithSubparser:p]; + a = [p completeMatchFor:a]; + + TDNil(a); + + s = @"TRUE"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or|not|true|false" options:PKPatternOptionsIgnoreCase]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[TRUE]TRUE^"); + + p = [PKNegation negationWithSubparser:p]; + a = [p completeMatchFor:a]; + + TDNil(a); + + s = @"NOT"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or|not|true|false" options:PKPatternOptionsIgnoreCase]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKWord word]]; + + a = [inter completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[NOT]NOT^"); + + p = [PKNegation negationWithSubparser:p]; + a = [p completeMatchFor:a]; + + TDNil(a); + + s = @"oR"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or|not|true|false" options:PKPatternOptionsIgnoreCase]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKSymbol symbol]]; + + a = [inter completeMatchFor:a]; + + TDNil(a); +} + +@end diff --git a/test/.svn/text-base/TDPlistParser.h.svn-base b/test/.svn/text-base/TDPlistParser.h.svn-base new file mode 100644 index 0000000..52986da --- /dev/null +++ b/test/.svn/text-base/TDPlistParser.h.svn-base @@ -0,0 +1,35 @@ +// +// PKPlistParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/9/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDPlistParser : PKAlternation { + PKCollectionParser *dictParser; + PKCollectionParser *keyValuePairParser; + PKCollectionParser *arrayParser; + PKCollectionParser *commaValueParser; + PKCollectionParser *keyParser; + PKCollectionParser *valueParser; + PKCollectionParser *stringParser; + PKParser *numParser; + PKParser *nullParser; + PKToken *curly; + PKToken *paren; +} +- (id)parse:(NSString *)s; + +@property (nonatomic, retain) PKCollectionParser *dictParser; +@property (nonatomic, retain) PKCollectionParser *keyValuePairParser; +@property (nonatomic, retain) PKCollectionParser *arrayParser; +@property (nonatomic, retain) PKCollectionParser *commaValueParser; +@property (nonatomic, retain) PKCollectionParser *keyParser; +@property (nonatomic, retain) PKCollectionParser *valueParser; +@property (nonatomic, retain) PKCollectionParser *stringParser; +@property (nonatomic, retain) PKParser *numParser; +@property (nonatomic, retain) PKParser *nullParser; +@end diff --git a/test/.svn/text-base/TDPlistParser.m.svn-base b/test/.svn/text-base/TDPlistParser.m.svn-base new file mode 100644 index 0000000..52fd123 --- /dev/null +++ b/test/.svn/text-base/TDPlistParser.m.svn-base @@ -0,0 +1,316 @@ +// +// PKPlistParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/9/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDPlistParser.h" +#import "NSString+ParseKitAdditions.h" + +//{ +// 0 = 0; +// dictKey = { +// bar = foo; +// }; +// 47 = 0; +// IntegerKey = 1; +// 47.7 = 0; +// = ; +// ArrayKey = ( +// "one one", +// two, +// three +// ); +// "Null Key" = ; +// emptyDictKey = { +// }; +// StringKey = String; +// "1.0" = 1; +// YESKey = 1; +// "NO Key" = 0; +//} + + +// dict = '{' dictContent '}' +// dictContent = keyValuePair* +// keyValuePair = key '=' value ';' +// key = num | string | null +// value = num | string | null | array | dict +// null = '' +// string = Word | QuotedString +// num = Number + +// array = '(' arrayContent ')' +// arrayContent = Empty | actualArray +// actualArray = value commaValue* +// commaValue = ',' value + +static NSString *kTDPlistNullString = @""; + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface PKCollectionParser () +@property (nonatomic, readwrite, retain) NSMutableArray *subparsers; +@end + +@interface TDPlistParser () +@property (nonatomic, retain) PKToken *curly; +@property (nonatomic, retain) PKToken *paren; +@end + +@implementation TDPlistParser + +- (id)init { + self = [super init]; + if (self != nil) { + + self.tokenizer = [PKTokenizer tokenizer]; + // add '' as a multichar symbol + [self.tokenizer.symbolState add:kTDPlistNullString]; + + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.]; + self.paren = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"(" floatValue:0.]; + [self add:[PKEmpty empty]]; + [self add:self.arrayParser]; + [self add:self.dictParser]; + } + return self; +} + + +- (void)dealloc { + // avoid retain cycle leaks by releasing the subparsers of all collection parsers + dictParser.subparsers = nil; + keyValuePairParser.subparsers = nil; + arrayParser.subparsers = nil; + commaValueParser.subparsers = nil; + keyParser.subparsers = nil; + valueParser.subparsers = nil; + stringParser.subparsers = nil; + + self.tokenizer = nil; + self.dictParser = nil; + self.keyValuePairParser = nil; + self.arrayParser = nil; + self.commaValueParser = nil; + self.keyParser = nil; + self.valueParser = nil; + self.stringParser = nil; + self.numParser = nil; + self.nullParser = nil; + self.curly = nil; + self.paren = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:self.tokenizer]; + + // parse + PKAssembly *res = [self completeMatchFor:a]; + + // pop the built result off the assembly's stack and return. + // this will be an array or a dictionary or nil + return [res pop]; +} + + +// dict = '{' dictContent '}' +// dictContent = keyValuePair* +- (PKCollectionParser *)dictParser { + if (!dictParser) { + self.dictParser = [PKTrack track]; + [dictParser add:[PKSymbol symbolWithString:@"{"]]; // dont discard. serves as fence + [dictParser add:[PKRepetition repetitionWithSubparser:self.keyValuePairParser]]; + [dictParser add:[[PKSymbol symbolWithString:@"}"] discard]]; + [dictParser setAssembler:self selector:@selector(didMatchDict:)]; + } + return dictParser; +} + + +// keyValuePair = key '=' value ';' +- (PKCollectionParser *)keyValuePairParser { + if (!keyValuePairParser) { + self.keyValuePairParser = [PKTrack track]; + [keyValuePairParser add:self.keyParser]; + [keyValuePairParser add:[[PKSymbol symbolWithString:@"="] discard]]; + [keyValuePairParser add:self.valueParser]; + [keyValuePairParser add:[[PKSymbol symbolWithString:@";"] discard]]; + } + return keyValuePairParser; +} + + +// array = '(' arrayContent ')' +// arrayContent = Empty | actualArray +// actualArray = value commaValue* +- (PKCollectionParser *)arrayParser { + if (!arrayParser) { + self.arrayParser = [PKTrack track]; + [arrayParser add:[PKSymbol symbolWithString:@"("]]; // dont discard. serves as fence + + PKAlternation *arrayContent = [PKAlternation alternation]; + [arrayContent add:[PKEmpty empty]]; + + PKSequence *actualArray = [PKSequence sequence]; + [actualArray add:self.valueParser]; + [actualArray add:[PKRepetition repetitionWithSubparser:self.commaValueParser]]; + + [arrayContent add:actualArray]; + [arrayParser add:arrayContent]; + [arrayParser add:[[PKSymbol symbolWithString:@")"] discard]]; + [arrayParser setAssembler:self selector:@selector(didMatchArray:)]; + } + return arrayParser; +} + + +// key = num | string | null +- (PKCollectionParser *)keyParser { + if (!keyParser) { + self.keyParser = [PKAlternation alternation]; + [keyParser add:self.numParser]; + [keyParser add:self.stringParser]; + [keyParser add:self.nullParser]; + } + return keyParser; +} + + +// value = num | string | null | array | dict +- (PKCollectionParser *)valueParser { + if (!valueParser) { + self.valueParser = [PKAlternation alternation]; + [valueParser add:self.arrayParser]; + [valueParser add:self.dictParser]; + [valueParser add:self.stringParser]; + [valueParser add:self.numParser]; + [valueParser add:self.nullParser]; + } + return valueParser; +} + + +- (PKCollectionParser *)commaValueParser { + if (!commaValueParser) { + self.commaValueParser = [PKSequence sequence]; + [commaValueParser add:[[PKSymbol symbolWithString:@","] discard]]; + [commaValueParser add:self.valueParser]; + } + return commaValueParser; +} + + +// string = QuotedString | Word +- (PKCollectionParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKAlternation alternation]; + + // we have to remove the quotes from QuotedString string values. so set an assembler method to do that + PKParser *quotedString = [PKQuotedString quotedString]; + [quotedString setAssembler:self selector:@selector(didMatchQuotedString:)]; + [stringParser add:quotedString]; + + // handle non-quoted string values (Words) in a separate assembler method for simplicity. + PKParser *word = [PKWord word]; + [word setAssembler:self selector:@selector(didMatchWord:)]; + [stringParser add:word]; + } + return stringParser; +} + + +- (PKParser *)numParser { + if (!numParser) { + self.numParser = [PKNumber number]; + [numParser setAssembler:self selector:@selector(didMatchNum:)]; + } + return numParser; +} + + +// null = '' +- (PKParser *)nullParser { + if (!nullParser) { + // thus must be a PKSymbol (not a PKLiteral) to match the resulting '' symbol tok + self.nullParser = [PKSymbol symbolWithString:kTDPlistNullString]; + [nullParser setAssembler:self selector:@selector(didMatchNull:)]; + } + return nullParser; +} + + +- (void)didMatchDict:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:self.curly]; + NSInteger count = [objs count]; + NSAssert1(0 == count % 2, @"in -%s, the assembly's stack's count should be a multiple of 2", _cmd); + + NSMutableDictionary *res = [NSMutableDictionary dictionaryWithCapacity:count / 2.]; + if (count) { + NSInteger i = 0; + for ( ; i < [objs count] - 1; i++) { + id value = [objs objectAtIndex:i++]; + id key = [objs objectAtIndex:i]; + [res setObject:value forKey:key]; + } + } + + [a pop]; // discard '{' tok + [a push:[[res copy] autorelease]]; +} + + +- (void)didMatchArray:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:self.paren]; + NSMutableArray *res = [NSMutableArray arrayWithCapacity:[objs count]]; + + for (id obj in [objs reverseObjectEnumerator]) { + [res addObject:obj]; + } + + [a pop]; // discard '(' tok + [a push:[[res copy] autorelease]]; +} + + +- (void)didMatchQuotedString:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[tok.stringValue stringByTrimmingQuotes]]; +} + + +- (void)didMatchWord:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:tok.stringValue]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchNull:(PKAssembly *)a { + [a pop]; // discard '' tok + [a push:[NSNull null]]; +} + +@synthesize dictParser; +@synthesize keyValuePairParser; +@synthesize arrayParser; +@synthesize commaValueParser; +@synthesize keyParser; +@synthesize valueParser; +@synthesize stringParser; +@synthesize numParser; +@synthesize nullParser; +@synthesize curly; +@synthesize paren; +@end diff --git a/test/.svn/text-base/TDPlistParserTest.h.svn-base b/test/.svn/text-base/TDPlistParserTest.h.svn-base new file mode 100644 index 0000000..27a1d4c --- /dev/null +++ b/test/.svn/text-base/TDPlistParserTest.h.svn-base @@ -0,0 +1,19 @@ +// +// PKPlistParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/9/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "TDPlistParser.h" + +@interface TDPlistParserTest : SenTestCase { + TDPlistParser *p; + NSString *s; + PKTokenAssembly *a; + PKAssembly *res; +} + +@end diff --git a/test/.svn/text-base/TDPlistParserTest.m.svn-base b/test/.svn/text-base/TDPlistParserTest.m.svn-base new file mode 100644 index 0000000..ab76797 --- /dev/null +++ b/test/.svn/text-base/TDPlistParserTest.m.svn-base @@ -0,0 +1,465 @@ +// +// PKPlistParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/9/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDPlistParserTest.h" + +@implementation TDPlistParserTest + +- (void)setUp { + p = [[TDPlistParser alloc] init]; +} + + +- (void)tearDown { + [p release]; +} + + +- (void)testARealDict { + s = @" {" + @" ArrayKey = (" + @" one," + @" two," + @" three" + @" );" + @" FloatKey = 1;" + @" IntegerKey = 1;" + @" NOKey = 0;" + @" StringKey = String;" + @" YESKey = 1;" + @" }"; + + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + TDNotNil(res); + + id obj = [res pop]; + TDNotNil(obj); + TDTrue([obj isKindOfClass:[NSDictionary class]]); + TDEquals((NSUInteger)6, [obj count]); + + id arr = [obj objectForKey:@"ArrayKey"]; + TDNotNil(arr); + TDEquals((NSUInteger)3, [arr count]); + + id b = [obj objectForKey:@"YESKey"]; + TDNotNil(b); + TDEqualObjects([NSNumber numberWithInteger:1], b); +} + + +- (void)testARealDict2 { + //NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys: + // [NSNumber numberWithBool:NO], @"NO Key", + // [NSNumber numberWithBool:YES], @"YESKey", + // [NSNumber numberWithInteger:1], @"IntegerKey", + // [NSNumber numberWithFloat:1.0], @"1.0", + // [NSNumber numberWithInteger:0], @"0", + // [NSNumber numberWithInteger:0], [NSNumber numberWithInteger:47], + // [NSNumber numberWithInteger:0], [NSNumber numberWithFloat:47.7], + // @"String", @"StringKey", + // [NSNull null], @"Null Key", + // [NSNull null], [NSNull null], + // [NSDictionary dictionaryWithObject:@"foo" forKey:@"bar"], @"dictKey", + // [NSDictionary dictionary], @"emptyDictKey", + // [NSArray arrayWithObjects:@"one one", @"two", @"three", nil], @"ArrayKey", + // nil]; + //NSLog(@"%@", d); + + s = @"{" + @" 0 = 0;" + @" dictKey = {" + @" bar = foo;" + @" };" + @" 47 = 0;" + @" IntegerKey = 1;" + @" 47.7 = 0;" + @" = ;" + @" ArrayKey = (" + @" \"one one\"," + @" two," + @" three" + @" );" + @" \"Null Key\" = ;" + @" emptyDictKey = {" + @" };" + @" StringKey = String;" + @" \"1.0\" = 1;" + @" YESKey = 1;" + @" \"NO Key\" = 0;" + @"}"; + + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + TDNotNil(res); + + id obj = [res pop]; + TDNotNil(obj); + TDTrue([obj isKindOfClass:[NSDictionary class]]); + TDEquals((NSUInteger)13, [obj count]); + + id arr = [obj objectForKey:@"ArrayKey"]; + TDNotNil(arr); + TDEquals((NSUInteger)3, [arr count]); + + id b = [obj objectForKey:@"YESKey"]; + TDNotNil(b); + TDEqualObjects([NSNumber numberWithInteger:1], b); +} + + +- (void)testDictFooEqBar { + s = @"{foo = bar;}"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchDictionaryAssembly: has already executed. + id obj = [res pop]; // NSDictionary * + TDTrue([obj isKindOfClass:[NSDictionary class]]); + TDEquals((NSUInteger)1, [obj count]); + + TDEqualObjects(@"bar", [obj objectForKey:@"foo"]); +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testDictTrackFooEqBarMisingCurly { + s = @"{foo = bar;"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + STAssertThrowsSpecific([p.dictParser completeMatchFor:a], PKTrackException, @""); +} +#endif + + +- (void)testDictQuoteFooFooQuoteEqBarOneEq2 { + s = @"{\"foo foo\" = bar; 1 = 2.2;}"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchDictionaryAssembly: has already executed. + id obj = [res pop]; // NSDictionary * + TDTrue([obj isKindOfClass:[NSDictionary class]]); + TDEquals((NSUInteger)2, [obj count]); + + TDEqualObjects(@"bar", [obj objectForKey:@"foo foo"]); + TDEqualObjects([NSNumber numberWithFloat:2.2], [obj objectForKey:[NSNumber numberWithInteger:1]]); +} + + +- (void)testKeyValuePairFooEqBar { + s = @"foo = bar;"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.keyValuePairParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchKeyValuePairAssembly: has already executed. + id value = [res pop]; // NSString * + id key = [res pop]; // NSString * + + TDTrue([key isKindOfClass:[NSString class]]); + TDEqualObjects(@"foo", key); + + TDTrue([value isKindOfClass:[NSString class]]); + TDEqualObjects(@"bar", value); +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testKeyValuePairTrackFooEqBarNoSemi { + s = @"foo = bar"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + STAssertThrowsSpecific([p.keyValuePairParser completeMatchFor:a], PKTrackException, @""); +} +#endif + + +- (void)testCommaValueComma1 { + s = @", 1"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.commaValueParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumberAssembly: has already executed. + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEquals((NSInteger)1, [obj integerValue]); +} + + +- (void)testCommaValueCommaFoo { + s = @", Foo"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.commaValueParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchWordAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"Foo", obj); +} + + +- (void)testCommaValueCommaQuoteFooSpaceBarQuote { + s = @", \"Foo Bar\""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.commaValueParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchQuotedStringAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"Foo Bar", obj); +} + + +- (void)testArrayEmptyArray { + s = @"()"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.arrayParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchArrayAssembly: has already executed. + id obj = [res pop]; // NSArray * + TDTrue([obj isKindOfClass:[NSArray class]]); + TDEquals((NSUInteger)0, [obj count]); +} + + +- (void)testArrayNumArray { + s = @"(1, 2, 3)"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.arrayParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchArrayAssembly: has already executed. + id obj = [res pop]; // NSArray * + TDTrue([obj isKindOfClass:[NSArray class]]); + TDEquals((NSUInteger)3, [obj count]); + TDEqualObjects([NSNumber numberWithInt:1], [obj objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInt:2], [obj objectAtIndex:1]); + TDEqualObjects([NSNumber numberWithInt:3], [obj objectAtIndex:2]); +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testArrayTrackNumArrayMissingParen { + s = @"(1, 2, 3"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + STAssertThrowsSpecific([p.arrayParser completeMatchFor:a], PKTrackException, @""); +} + + +- (void)testArrayTrackNumArrayMissingComma { + s = @"(1, 2 3)"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + STAssertThrowsSpecific([p.arrayParser completeMatchFor:a], PKTrackException, @""); +} +#endif + + +- (void)testNullLtNullGt { + s = @""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.nullParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNullAssembly: has already executed. + id obj = [res pop]; // NSNull * + TDTrue([obj isKindOfClass:[NSNull class]]); + TDEqualObjects([NSNull null], obj); +} + + +- (void)testNullQuoteLtNullGtQuote { + s = @"\"\""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.nullParser completeMatchFor:a]; + TDNil(res); +} + + +- (void)testStringQuote1Dot0Quote { + s = @"\"1.0\""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.stringParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchStringAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"1.0", obj); +} + + +- (void)testStringFoo { + s = @"foo"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.stringParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchStringAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"foo", obj); +} + + +- (void)testStringQuoteFooQuote { + s = @"\"foo\""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.stringParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchStringAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"foo", obj); +} + + +- (void)testNum1Dot0 { + s = @"1.0"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. 'floatness' has been lost + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"1", [obj stringValue]); + TDEquals((NSInteger)1, [obj integerValue]); + TDEquals((CGFloat)1.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNumMinus1Dot0 { + s = @"-1.0"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. 'floatness' has been lost + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"-1", [obj stringValue]); + TDEquals((NSInteger)-1, [obj integerValue]); + TDEquals((CGFloat)-1.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNumMinus1 { + s = @"-1"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"-1", [obj stringValue]); + TDEquals((NSInteger)-1, [obj integerValue]); + TDEquals((CGFloat)-1.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNum0 { + s = @"0"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"0", [obj stringValue]); + TDEquals((NSInteger)0, [obj integerValue]); + TDEquals((CGFloat)0.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNum0Dot0 { + s = @"0.0"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. 'floatness' has been lost + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"0", [obj stringValue]); + TDEquals((NSInteger)0, [obj integerValue]); + TDEquals((CGFloat)0.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNumMinus0Dot0 { + s = @"-0.0"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. 'floatness' has been lost + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"-0", [obj stringValue]); + TDEquals((NSInteger)-0, [obj integerValue]); + TDEquals((CGFloat)-0.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNum300 { + s = @"300"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"300", [obj stringValue]); + TDEquals((NSInteger)300, [obj integerValue]); + TDEquals((CGFloat)300.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNumEmptyString { + s = @""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNil(res); +} + +@end diff --git a/test/.svn/text-base/TDPredicateEvaluator.h.svn-base b/test/.svn/text-base/TDPredicateEvaluator.h.svn-base new file mode 100644 index 0000000..d77626b --- /dev/null +++ b/test/.svn/text-base/TDPredicateEvaluator.h.svn-base @@ -0,0 +1,83 @@ +// +// PKPredicateEvaluator.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/28/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@protocol TDPredicateEvaluatorDelegate +- (id)valueForAttributeKey:(NSString *)key; +- (CGFloat)floatForAttributeKey:(NSString *)key; +- (BOOL)boolForAttributeKey:(NSString *)key; +@end + +@interface TDPredicateEvaluator : NSObject { + id delegate; + PKCollectionParser *exprParser; + PKCollectionParser *orTermParser; + PKCollectionParser *termParser; + PKCollectionParser *andPrimaryExprParser; + PKCollectionParser *primaryExprParser; + PKCollectionParser *phraseParser; + PKCollectionParser *negatedPredicateParser; + PKCollectionParser *predicateParser; + PKCollectionParser *attrParser; + PKCollectionParser *tagParser; + PKCollectionParser *eqStringPredicateParser; + PKCollectionParser *eqNumberPredicateParser; + PKCollectionParser *eqBoolPredicateParser; + PKCollectionParser *neStringPredicateParser; + PKCollectionParser *neNumberPredicateParser; + PKCollectionParser *neBoolPredicateParser; + PKCollectionParser *gtPredicateParser; + PKCollectionParser *gteqPredicateParser; + PKCollectionParser *ltPredicateParser; + PKCollectionParser *lteqPredicateParser; + PKCollectionParser *beginswithPredicateParser; + PKCollectionParser *containsPredicateParser; + PKCollectionParser *endswithPredicateParser; + PKCollectionParser *matchesPredicateParser; + PKCollectionParser *valueParser; + PKCollectionParser *boolParser; + PKParser *trueParser; + PKParser *falseParser; + PKParser *stringParser; + PKParser *numberParser; +} +- (id)initWithDelegate:(id )d; +- (BOOL)evaluate:(NSString *)s; + +@property (nonatomic, retain) PKCollectionParser *exprParser; +@property (nonatomic, retain) PKCollectionParser *orTermParser; +@property (nonatomic, retain) PKCollectionParser *termParser; +@property (nonatomic, retain) PKCollectionParser *andPrimaryExprParser; +@property (nonatomic, retain) PKCollectionParser *primaryExprParser; +@property (nonatomic, retain) PKCollectionParser *phraseParser; +@property (nonatomic, retain) PKCollectionParser *negatedPredicateParser; +@property (nonatomic, retain) PKCollectionParser *predicateParser; +@property (nonatomic, retain) PKCollectionParser *attrParser; +@property (nonatomic, retain) PKCollectionParser *tagParser; +@property (nonatomic, retain) PKCollectionParser *eqStringPredicateParser; +@property (nonatomic, retain) PKCollectionParser *eqNumberPredicateParser; +@property (nonatomic, retain) PKCollectionParser *eqBoolPredicateParser; +@property (nonatomic, retain) PKCollectionParser *neStringPredicateParser; +@property (nonatomic, retain) PKCollectionParser *neNumberPredicateParser; +@property (nonatomic, retain) PKCollectionParser *neBoolPredicateParser; +@property (nonatomic, retain) PKCollectionParser *gtPredicateParser; +@property (nonatomic, retain) PKCollectionParser *gteqPredicateParser; +@property (nonatomic, retain) PKCollectionParser *ltPredicateParser; +@property (nonatomic, retain) PKCollectionParser *lteqPredicateParser; +@property (nonatomic, retain) PKCollectionParser *beginswithPredicateParser; +@property (nonatomic, retain) PKCollectionParser *containsPredicateParser; +@property (nonatomic, retain) PKCollectionParser *endswithPredicateParser; +@property (nonatomic, retain) PKCollectionParser *matchesPredicateParser; +@property (nonatomic, retain) PKCollectionParser *valueParser; +@property (nonatomic, retain) PKCollectionParser *boolParser; +@property (nonatomic, retain) PKParser *trueParser; +@property (nonatomic, retain) PKParser *falseParser; +@property (nonatomic, retain) PKParser *stringParser; +@property (nonatomic, retain) PKParser *numberParser; +@end diff --git a/test/.svn/text-base/TDPredicateEvaluator.m.svn-base b/test/.svn/text-base/TDPredicateEvaluator.m.svn-base new file mode 100644 index 0000000..531bbe9 --- /dev/null +++ b/test/.svn/text-base/TDPredicateEvaluator.m.svn-base @@ -0,0 +1,656 @@ +// +// PKPredicateEvaluator.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/28/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDPredicateEvaluator.h" +#import "NSString+ParseKitAdditions.h" + +// expr = term orTerm* +// orTerm = 'or' term +// term = primaryExpr andPrimaryExpr* +// andPrimaryExpr = 'and' primaryExpr +// primaryExpr = phrase | '(' expression ')' +// phrase = predicate | negatedPredicate +// negatedPredicate = 'not' predicate +// predicate = bool | eqPredicate | nePredicate | gtPredicate | gteqPredicate | ltPredicate | lteqPredicate | beginswithPredicate | containsPredicate | endswithPredicate | matchesPredicate +// eqPredicate = attr '=' value +// nePredicate = attr '!=' value +// gtPredicate = attr '>' value +// gteqPredicate = attr '>=' value +// ltPredicate = attr '<' value +// lteqPredicate = attr '<=' value +// beginswithPredicate = attr 'beginswith' value +// containsPredicate = attr 'contains' value +// endswithPredicate = attr 'endswith' value +// matchesPredicate = attr 'matches' value + +// attr = tag | Word +// tag = '@' Word +// value = QuotedString | Number | bool +// bool = 'true' | 'false' + +@implementation TDPredicateEvaluator + +- (id)initWithDelegate:(id )d { + if (self = [super init]) { + delegate = d; + } + return self; +} + + +- (void)dealloc { + delegate = nil; + self.exprParser = nil; + self.orTermParser = nil; + self.termParser = nil; + self.andPrimaryExprParser = nil; + self.primaryExprParser = nil; + self.negatedPredicateParser = nil; + self.predicateParser = nil; + self.phraseParser = nil; + self.attrParser = nil; + self.tagParser = nil; + self.eqStringPredicateParser = nil; + self.eqNumberPredicateParser = nil; + self.eqBoolPredicateParser = nil; + self.neStringPredicateParser = nil; + self.neNumberPredicateParser = nil; + self.neBoolPredicateParser = nil; + self.gtPredicateParser = nil; + self.gteqPredicateParser = nil; + self.ltPredicateParser = nil; + self.lteqPredicateParser = nil; + self.beginswithPredicateParser = nil; + self.containsPredicateParser = nil; + self.endswithPredicateParser = nil; + self.matchesPredicateParser = nil; + self.valueParser = nil; + self.boolParser = nil; + self.trueParser = nil; + self.falseParser = nil; + self.stringParser = nil; + self.numberParser = nil; + [super dealloc]; +} + + +- (BOOL)evaluate:(NSString *)s { + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + return [[[self.exprParser completeMatchFor:a] pop] boolValue]; +} + + +// expression = term orTerm* +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + [exprParser add:self.termParser]; + [exprParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + } + return exprParser; +} + + +// orTerm = 'or' term +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKSequence sequence]; + [orTermParser add:[[PKCaseInsensitiveLiteral literalWithString:@"or"] discard]]; + [orTermParser add:self.termParser]; + [orTermParser setAssembler:self selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// term = primaryExpr andPrimaryExpr* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + [termParser add:self.primaryExprParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.andPrimaryExprParser]]; + } + return termParser; +} + + +// andPrimaryExpr = 'and' primaryExpr +- (PKCollectionParser *)andPrimaryExprParser { + if (!andPrimaryExprParser) { + self.andPrimaryExprParser = [PKSequence sequence]; + [andPrimaryExprParser add:[[PKCaseInsensitiveLiteral literalWithString:@"and"] discard]]; + [andPrimaryExprParser add:self.primaryExprParser]; + [andPrimaryExprParser setAssembler:self selector:@selector(didMatchAnd:)]; + } + return andPrimaryExprParser; +} + + +// primaryExpr = phrase | '(' expression ')' +- (PKCollectionParser *)primaryExprParser { + if (!primaryExprParser) { + self.primaryExprParser = [PKAlternation alternation]; + [primaryExprParser add:self.phraseParser]; + + PKSequence *s = [PKSequence sequence]; + [s add:[[PKSymbol symbolWithString:@"("] discard]]; + [s add:self.exprParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + [primaryExprParser add:s]; + } + return primaryExprParser; +} + + +// phrase = predicate | negatedPredicate +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + self.phraseParser = [PKAlternation alternation]; + [phraseParser add:self.predicateParser]; + [phraseParser add:self.negatedPredicateParser]; + } + return phraseParser; +} + + +// negatedPredicate = 'not' predicate +- (PKCollectionParser *)negatedPredicateParser { + if (!negatedPredicateParser) { + self.negatedPredicateParser = [PKSequence sequence]; + [negatedPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"not"] discard]]; + [negatedPredicateParser add:self.predicateParser]; + [negatedPredicateParser setAssembler:self selector:@selector(didMatchNegatedValue:)]; + } + return negatedPredicateParser; +} + + +// predicate = bool | eqPredicate | nePredicate | gtPredicate | gteqPredicate | ltPredicate | lteqPredicate | beginswithPredicate | containsPredicate | endswithPredicate | matchesPredicate +- (PKCollectionParser *)predicateParser { + if (!predicateParser) { + self.predicateParser = [PKAlternation alternation]; + [predicateParser add:self.boolParser]; + [predicateParser add:self.eqStringPredicateParser]; + [predicateParser add:self.eqNumberPredicateParser]; + [predicateParser add:self.eqBoolPredicateParser]; + [predicateParser add:self.neStringPredicateParser]; + [predicateParser add:self.neNumberPredicateParser]; + [predicateParser add:self.neBoolPredicateParser]; + [predicateParser add:self.gtPredicateParser]; + [predicateParser add:self.gteqPredicateParser]; + [predicateParser add:self.ltPredicateParser]; + [predicateParser add:self.lteqPredicateParser]; + [predicateParser add:self.beginswithPredicateParser]; + [predicateParser add:self.containsPredicateParser]; + [predicateParser add:self.endswithPredicateParser]; + [predicateParser add:self.matchesPredicateParser]; + } + return predicateParser; +} + + +// attr = tag | Word +- (PKCollectionParser *)attrParser { + if (!attrParser) { + self.attrParser = [PKAlternation alternation]; + [attrParser add:self.tagParser]; + [attrParser add:[PKWord word]]; + [attrParser setAssembler:self selector:@selector(didMatchAttr:)]; + } + return attrParser; +} + + +// tag = '@' Word +- (PKCollectionParser *)tagParser { + if (!tagParser) { + self.tagParser = [PKSequence sequence]; + [tagParser add:[[PKSymbol symbolWithString:@"@"] discard]]; + [tagParser add:[PKWord word]]; + } + return tagParser; +} + + +// eqPredicate = attr '=' value +- (PKCollectionParser *)eqStringPredicateParser { + if (!eqStringPredicateParser) { + self.eqStringPredicateParser = [PKSequence sequence]; + [eqStringPredicateParser add:self.attrParser]; + [eqStringPredicateParser add:[[PKSymbol symbolWithString:@"="] discard]]; + [eqStringPredicateParser add:self.stringParser]; + [eqStringPredicateParser setAssembler:self selector:@selector(didMatchEqStringPredicate:)]; + } + return eqStringPredicateParser; +} + + +- (PKCollectionParser *)eqNumberPredicateParser { + if (!eqNumberPredicateParser) { + self.eqNumberPredicateParser = [PKSequence sequence]; + [eqNumberPredicateParser add:self.attrParser]; + [eqNumberPredicateParser add:[[PKSymbol symbolWithString:@"="] discard]]; + [eqNumberPredicateParser add:self.numberParser]; + [eqNumberPredicateParser setAssembler:self selector:@selector(didMatchEqNumberPredicate:)]; + } + return eqNumberPredicateParser; +} + + +- (PKCollectionParser *)eqBoolPredicateParser { + if (!eqBoolPredicateParser) { + self.eqBoolPredicateParser = [PKSequence sequence]; + [eqBoolPredicateParser add:self.attrParser]; + [eqBoolPredicateParser add:[[PKSymbol symbolWithString:@"="] discard]]; + [eqBoolPredicateParser add:self.boolParser]; + [eqBoolPredicateParser setAssembler:self selector:@selector(didMatchEqBoolPredicate:)]; + } + return eqBoolPredicateParser; +} + + +// nePredicate = attr '!=' value +- (PKCollectionParser *)neStringPredicateParser { + if (!neStringPredicateParser) { + self.neStringPredicateParser = [PKSequence sequence]; + [neStringPredicateParser add:self.attrParser]; + [neStringPredicateParser add:[[PKSymbol symbolWithString:@"!="] discard]]; + [neStringPredicateParser add:self.stringParser]; + [neStringPredicateParser setAssembler:self selector:@selector(didMatchNeStringPredicate:)]; + } + return neStringPredicateParser; +} + + +- (PKCollectionParser *)neNumberPredicateParser { + if (!neNumberPredicateParser) { + self.neNumberPredicateParser = [PKSequence sequence]; + [neNumberPredicateParser add:self.attrParser]; + [neNumberPredicateParser add:[[PKSymbol symbolWithString:@"!="] discard]]; + [neNumberPredicateParser add:self.numberParser]; + [neNumberPredicateParser setAssembler:self selector:@selector(didMatchNeNumberPredicate:)]; + } + return neNumberPredicateParser; +} + + +- (PKCollectionParser *)neBoolPredicateParser { + if (!neBoolPredicateParser) { + self.neBoolPredicateParser = [PKSequence sequence]; + [neBoolPredicateParser add:self.attrParser]; + [neBoolPredicateParser add:[[PKSymbol symbolWithString:@"!="] discard]]; + [neBoolPredicateParser add:self.boolParser]; + [neBoolPredicateParser setAssembler:self selector:@selector(didMatchNeBoolPredicate:)]; + } + return neBoolPredicateParser; +} + + +// gtPredicate = attr '>' value +- (PKCollectionParser *)gtPredicateParser { + if (!gtPredicateParser) { + self.gtPredicateParser = [PKSequence sequence]; + [gtPredicateParser add:self.attrParser]; + [gtPredicateParser add:[[PKSymbol symbolWithString:@">"] discard]]; + [gtPredicateParser add:self.valueParser]; + [gtPredicateParser setAssembler:self selector:@selector(didMatchGtPredicate:)]; + } + return gtPredicateParser; +} + + +// gteqPredicate = attr '>=' value +- (PKCollectionParser *)gteqPredicateParser { + if (!gteqPredicateParser) { + self.gteqPredicateParser = [PKSequence sequence]; + [gteqPredicateParser add:self.attrParser]; + [gteqPredicateParser add:[[PKSymbol symbolWithString:@">="] discard]]; + [gteqPredicateParser add:self.valueParser]; + [gteqPredicateParser setAssembler:self selector:@selector(didMatchGteqPredicate:)]; + } + return gteqPredicateParser; +} + + +// ltPredicate = attr '<' value +- (PKCollectionParser *)ltPredicateParser { + if (!ltPredicateParser) { + self.ltPredicateParser = [PKSequence sequence]; + [ltPredicateParser add:self.attrParser]; + [ltPredicateParser add:[[PKSymbol symbolWithString:@"<"] discard]]; + [ltPredicateParser add:self.valueParser]; + [ltPredicateParser setAssembler:self selector:@selector(didMatchLtPredicate:)]; + } + return ltPredicateParser; +} + + +// lteqPredicate = attr '<=' value +- (PKCollectionParser *)lteqPredicateParser { + if (!lteqPredicateParser) { + self.lteqPredicateParser = [PKSequence sequence]; + [lteqPredicateParser add:self.attrParser]; + [lteqPredicateParser add:[[PKSymbol symbolWithString:@"<="] discard]]; + [lteqPredicateParser add:self.valueParser]; + [lteqPredicateParser setAssembler:self selector:@selector(didMatchLteqPredicate:)]; + } + return lteqPredicateParser; +} + + +// beginswithPredicate = attr 'beginswith' value +- (PKCollectionParser *)beginswithPredicateParser { + if (!beginswithPredicateParser) { + self.beginswithPredicateParser = [PKSequence sequence]; + [beginswithPredicateParser add:self.attrParser]; + [beginswithPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"beginswith"] discard]]; + [beginswithPredicateParser add:self.valueParser]; + [beginswithPredicateParser setAssembler:self selector:@selector(didMatchBeginswithPredicate:)]; + } + return beginswithPredicateParser; +} + + +// containsPredicate = attr 'contains' value +- (PKCollectionParser *)containsPredicateParser { + if (!containsPredicateParser) { + self.containsPredicateParser = [PKSequence sequence]; + [containsPredicateParser add:self.attrParser]; + [containsPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"contains"] discard]]; + [containsPredicateParser add:self.valueParser]; + [containsPredicateParser setAssembler:self selector:@selector(didMatchContainsPredicate:)]; + } + return containsPredicateParser; +} + + +// endswithPredicate = attr 'endswith' value +- (PKCollectionParser *)endswithPredicateParser { + if (!endswithPredicateParser) { + self.endswithPredicateParser = [PKSequence sequence]; + [endswithPredicateParser add:self.attrParser]; + [endswithPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"endswith"] discard]]; + [endswithPredicateParser add:self.valueParser]; + [endswithPredicateParser setAssembler:self selector:@selector(didMatchEndswithPredicate:)]; + } + return endswithPredicateParser; +} + + +// matchesPredicate = attr 'matches' value +- (PKCollectionParser *)matchesPredicateParser { + if (!matchesPredicateParser) { + self.matchesPredicateParser = [PKSequence sequence]; + [matchesPredicateParser add:self.attrParser]; + [matchesPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"matches"] discard]]; + [matchesPredicateParser add:self.valueParser]; + [matchesPredicateParser setAssembler:self selector:@selector(didMatchMatchesPredicate:)]; + } + return matchesPredicateParser; +} + + +// value = QuotedString | Number | bool +- (PKCollectionParser *)valueParser { + if (!valueParser) { + self.valueParser = [PKAlternation alternation]; + [valueParser add:self.stringParser]; + [valueParser add:self.numberParser]; + [valueParser add:self.boolParser]; + } + return valueParser; +} + + +- (PKCollectionParser *)boolParser { + if (!boolParser) { + self.boolParser = [PKAlternation alternation]; + [boolParser add:self.trueParser]; + [boolParser add:self.falseParser]; + [boolParser setAssembler:self selector:@selector(didMatchBool:)]; + } + return boolParser; +} + + +- (PKParser *)trueParser { + if (!trueParser) { + self.trueParser = [[PKCaseInsensitiveLiteral literalWithString:@"true"] discard]; + [trueParser setAssembler:self selector:@selector(didMatchTrue:)]; + } + return trueParser; +} + + +- (PKParser *)falseParser { + if (!falseParser) { + self.falseParser = [[PKCaseInsensitiveLiteral literalWithString:@"false"] discard]; + [falseParser setAssembler:self selector:@selector(didMatchFalse:)]; + } + return falseParser; +} + + +- (PKParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKQuotedString quotedString]; + [stringParser setAssembler:self selector:@selector(didMatchString:)]; + } + return stringParser; +} + + +- (PKParser *)numberParser { + if (!numberParser) { + self.numberParser = [PKNumber number]; + [numberParser setAssembler:self selector:@selector(didMatchNumber:)]; + } + return numberParser; +} + + +- (void)didMatchAnd:(PKAssembly *)a { + NSNumber *b2 = [a pop]; + NSNumber *b1 = [a pop]; + BOOL yn = ([b1 boolValue] && [b2 boolValue]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchOr:(PKAssembly *)a { + NSNumber *b2 = [a pop]; + NSNumber *b1 = [a pop]; + BOOL yn = ([b1 boolValue] || [b2 boolValue]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchEqStringPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [[delegate valueForAttributeKey:attrKey] isEqual:value]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchEqNumberPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [value isEqualToNumber:[delegate valueForAttributeKey:attrKey]]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchEqBoolPredicate:(PKAssembly *)a { + NSNumber *b = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = ([delegate boolForAttributeKey:attrKey] == [b boolValue]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchNeStringPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + + BOOL yn = ![[delegate valueForAttributeKey:attrKey] isEqual:value]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchNeNumberPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = ![value isEqualToNumber:[delegate valueForAttributeKey:attrKey]]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchNeBoolPredicate:(PKAssembly *)a { + NSNumber *b = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = ([delegate boolForAttributeKey:attrKey] != [b boolValue]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchGtPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = (NSOrderedDescending == [[delegate valueForAttributeKey:attrKey] compare:value]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchGteqPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = (NSOrderedAscending != [[delegate valueForAttributeKey:attrKey] compare:value]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchLtPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = (NSOrderedAscending == [[delegate valueForAttributeKey:attrKey] compare:value]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchLteqPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = (NSOrderedDescending != [[delegate valueForAttributeKey:attrKey] compare:value]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchBeginswithPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [[delegate valueForAttributeKey:attrKey] hasPrefix:value]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchContainsPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + NSRange r = [[delegate valueForAttributeKey:attrKey] rangeOfString:value]; + BOOL yn = (NSNotFound != r.location); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchEndswithPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [[delegate valueForAttributeKey:attrKey] hasSuffix:value]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchMatchesPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [[delegate valueForAttributeKey:attrKey] isEqual:value]; // TODO should this be a regex match? + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchAttr:(PKAssembly *)a { + [a push:[[a pop] stringValue]]; +} + + +- (void)didMatchNegatedValue:(PKAssembly *)a { + NSNumber *b = [a pop]; + [a push:[NSNumber numberWithBool:![b boolValue]]]; +} + + +- (void)didMatchBool:(PKAssembly *)a { + NSNumber *b = [a pop]; + [a push:[NSNumber numberWithBool:[b boolValue]]]; +} + + +- (void)didMatchTrue:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:YES]]; +} + + +- (void)didMatchFalse:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:NO]]; +} + + +- (void)didMatchString:(PKAssembly *)a { + NSString *s = [[[a pop] stringValue] stringByTrimmingQuotes]; + [a push:s]; +} + + +- (void)didMatchNumber:(PKAssembly *)a { + NSNumber *b = [NSNumber numberWithFloat:[(PKToken *)[a pop] floatValue]]; + [a push:b]; +} + +@synthesize exprParser; +@synthesize orTermParser; +@synthesize termParser; +@synthesize andPrimaryExprParser; +@synthesize primaryExprParser; +@synthesize phraseParser; +@synthesize negatedPredicateParser; +@synthesize predicateParser; +@synthesize attrParser; +@synthesize tagParser; +@synthesize eqStringPredicateParser; +@synthesize eqNumberPredicateParser; +@synthesize eqBoolPredicateParser; +@synthesize neStringPredicateParser; +@synthesize neNumberPredicateParser; +@synthesize neBoolPredicateParser; +@synthesize gtPredicateParser; +@synthesize gteqPredicateParser; +@synthesize ltPredicateParser; +@synthesize lteqPredicateParser; +@synthesize beginswithPredicateParser; +@synthesize containsPredicateParser; +@synthesize endswithPredicateParser; +@synthesize matchesPredicateParser; +@synthesize valueParser; +@synthesize boolParser; +@synthesize trueParser; +@synthesize falseParser; +@synthesize stringParser; +@synthesize numberParser; +@end diff --git a/test/.svn/text-base/TDPredicateEvaluatorTest.h.svn-base b/test/.svn/text-base/TDPredicateEvaluatorTest.h.svn-base new file mode 100644 index 0000000..ba46841 --- /dev/null +++ b/test/.svn/text-base/TDPredicateEvaluatorTest.h.svn-base @@ -0,0 +1,20 @@ +// +// PKPredicateEvaluatorTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 5/28/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "TDPredicateEvaluator.h" + +@interface TDPredicateEvaluatorTest : SenTestCase { + TDPredicateEvaluator *p; + NSString *s; + PKAssembly *a; + + NSMutableDictionary *d; +} + +@end diff --git a/test/.svn/text-base/TDPredicateEvaluatorTest.m.svn-base b/test/.svn/text-base/TDPredicateEvaluatorTest.m.svn-base new file mode 100644 index 0000000..dfe1375 --- /dev/null +++ b/test/.svn/text-base/TDPredicateEvaluatorTest.m.svn-base @@ -0,0 +1,303 @@ +// +// PKPredicateEvaluatorTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 5/28/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDPredicateEvaluatorTest.h" + +@implementation TDPredicateEvaluatorTest + +- (id)valueForAttributeKey:(NSString *)key { + return [d objectForKey:key]; +} + + +- (CGFloat)floatForAttributeKey:(NSString *)key { + return [(NSNumber *)[d objectForKey:key] floatValue]; +} + + +- (BOOL)boolForAttributeKey:(NSString *)key { + return [[d objectForKey:key] boolValue]; +} + + +- (void)setUp { + d = [NSMutableDictionary dictionary]; + p = [[[TDPredicateEvaluator alloc] initWithDelegate:self] autorelease]; +} + + +- (void)testEq { + // test numbers + [d setValue:[NSNumber numberWithFloat:1.0] forKey:@"foo"]; + s = @"foo = 1.0"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/=/1.0^", [a description]); + + s = @"foo = -1.0"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/=/-1.0^", [a description]); + + + // test bools + [d setValue:[NSNumber numberWithBool:YES] forKey:@"foo"]; + s = @"foo = true"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/=/true^", [a description]); + + s = @"foo = false"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/=/false^", [a description]); + + [d setValue:[NSNumber numberWithBool:NO] forKey:@"foo"]; + s = @"foo = true"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/=/true^", [a description]); + + s = @"foo = false"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/=/false^", [a description]); + + + // test strings + [d setValue:@"bar" forKey:@"foo"]; + s = @"foo = 'bar'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/=/'bar'^", [a description]); + + s = @"foo = 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/=/'baz'^", [a description]); +} + + +- (void)testNe { + // test numbers + [d setValue:[NSNumber numberWithFloat:1.0] forKey:@"foo"]; + s = @"foo != 1.0"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/!=/1.0^", [a description]); + + s = @"foo != -1.0"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/!=/-1.0^", [a description]); + + + // test bools + [d setValue:[NSNumber numberWithBool:YES] forKey:@"foo"]; + s = @"foo != true"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/!=/true^", [a description]); + + s = @"foo != false"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/!=/false^", [a description]); + + [d setValue:[NSNumber numberWithBool:NO] forKey:@"foo"]; + s = @"foo != true"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/!=/true^", [a description]); + + s = @"foo != false"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/!=/false^", [a description]); + + + // test strings + [d setValue:@"bar" forKey:@"foo"]; + s = @"foo != 'bar'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/!=/'bar'^", [a description]); + + s = @"foo != 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/!=/'baz'^", [a description]); +} + + +- (void)testGt { + [d setValue:[NSNumber numberWithInteger:41] forKey:@"foo"]; + s = @"foo > 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/>/42^", [a description]); + + [d setValue:[NSNumber numberWithInteger:43] forKey:@"foo"]; + s = @"foo > 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/>/42^", [a description]); + + [d setValue:[NSNumber numberWithFloat:1.2] forKey:@"foo"]; + s = @"foo > 1.2"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/>/1.2^", [a description]); + + [d setValue:[NSNumber numberWithFloat:1.2001] forKey:@"foo"]; + s = @"foo > 1.2"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/>/1.2^", [a description]); +} + + +- (void)testLt { + [d setValue:[NSNumber numberWithInteger:41] forKey:@"foo"]; + s = @"foo < .3"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/= 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/>=/42^", [a description]); + + [d setValue:[NSNumber numberWithFloat:41.99] forKey:@"foo"]; + s = @"foo >= 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/>=/42^", [a description]); + + [d setValue:[NSNumber numberWithInteger:42] forKey:@"foo"]; + s = @"foo >= 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/>=/42^", [a description]); +} + + +- (void)testLteq { + [d setValue:[NSNumber numberWithInteger:41] forKey:@"foo"]; + s = @"foo <= .3"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/<=/.3^", [a description]); + + [d setValue:[NSNumber numberWithFloat:.3] forKey:@"foo"]; + s = @"foo <= .3"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/<=/.3^", [a description]); + + [d setValue:[NSNumber numberWithFloat:.3111] forKey:@"foo"]; + s = @"foo <= .3"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/<=/.3^", [a description]); +} + + +- (void)testBeginswith { + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo beginswith 'foo'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/beginswith/'foo'^", [a description]); + + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo beginswith 'bar'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/beginswith/'bar'^", [a description]); +} + + +- (void)testContains { + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo contains 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/contains/'baz'^", [a description]); + + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo contains 'bat'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/contains/'bat'^", [a description]); +} + + +- (void)testEndswith { + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo endswith 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/endswith/'baz'^", [a description]); + + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo endswith 'bat'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/endswith/'bat'^", [a description]); +} + + +- (void)testMatches { + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo matches 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/matches/'baz'^", [a description]); +} + + +- (void)testBools { + s = @"true"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[1]true^", [a description]); + + s = @"not true"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]not/true^", [a description]); + + s = @"false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]false^", [a description]); + + s = @"not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[1]not/false^", [a description]); + + s = @"true and false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]true/and/false^", [a description]); + + s = @"not true and false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]not/true/and/false^", [a description]); + + s = @"not true and not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]not/true/and/not/false^", [a description]); + + s = @"true or false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[1]true/or/false^", [a description]); + + s = @"(true and false) or false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0](/true/and/false/)/or/false^", [a description]); + + s = @"(true and false) or not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[1](/true/and/false/)/or/not/false^", [a description]); +} + +@end diff --git a/test/.svn/text-base/TDQuoteStateTest.h.svn-base b/test/.svn/text-base/TDQuoteStateTest.h.svn-base new file mode 100644 index 0000000..117ae2f --- /dev/null +++ b/test/.svn/text-base/TDQuoteStateTest.h.svn-base @@ -0,0 +1,17 @@ +// +// QuoteStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/21/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + + +@interface TDQuoteStateTest : SenTestCase { + PKQuoteState *quoteState; + PKReader *r; + NSString *s; +} +@end diff --git a/test/.svn/text-base/TDQuoteStateTest.m.svn-base b/test/.svn/text-base/TDQuoteStateTest.m.svn-base new file mode 100644 index 0000000..801a3ab --- /dev/null +++ b/test/.svn/text-base/TDQuoteStateTest.m.svn-base @@ -0,0 +1,104 @@ +// +// PKQuoteStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/21/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDQuoteStateTest.h" + + +@implementation TDQuoteStateTest + +- (void)setUp { + quoteState = [[PKQuoteState alloc] init]; + r = [[PKReader alloc] init]; +} + + +- (void)tearDown { + [quoteState release]; + [r release]; +} + + +- (void)testQuotedString { + s = @"'stuff'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + +} + + +- (void)testQuotedStringEOFTerminated { + s = @"'stuff"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); +} + + +- (void)testQuotedStringRepairEOFTerminated { + s = @"'stuff"; + r.string = s; + quoteState.balancesEOFTerminatedQuotes = YES; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"'stuff'", tok.stringValue); +} + + +- (void)testQuotedStringPlus { + s = @"'a quote here' more"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"'a quote here'", tok.stringValue); +} + + +- (void)test14CharQuotedString { + s = @"'123456789abcef'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + + +- (void)test15CharQuotedString { + s = @"'123456789abcefg'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + + +- (void)test16CharQuotedString { + s = @"'123456789abcefgh'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + + +- (void)test31CharQuotedString { + s = @"'123456789abcefgh123456789abcefg'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + + +- (void)test32CharQuotedString { + s = @"'123456789abcefgh123456789abcefgh'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + +@end diff --git a/test/.svn/text-base/TDReaderTest.h.svn-base b/test/.svn/text-base/TDReaderTest.h.svn-base new file mode 100644 index 0000000..fc9c2ac --- /dev/null +++ b/test/.svn/text-base/TDReaderTest.h.svn-base @@ -0,0 +1,16 @@ +// +// PKReaderTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/21/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDReaderTest : SenTestCase { + PKReader *reader; + NSString *string; +} + +@end diff --git a/test/.svn/text-base/TDReaderTest.m.svn-base b/test/.svn/text-base/TDReaderTest.m.svn-base new file mode 100644 index 0000000..6a8c88c --- /dev/null +++ b/test/.svn/text-base/TDReaderTest.m.svn-base @@ -0,0 +1,78 @@ +// +// PKReaderTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/21/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDReaderTest.h" + + +@implementation TDReaderTest + +- (void)setUp { + string = @"abcdefghijklmnopqrstuvwxyz"; + [string retain]; + reader = [[PKReader alloc] initWithString:string]; +} + + +- (void)tearDown { + [string release]; + [reader release]; +} + + +#pragma mark - + +- (void)testReadCharsMatch { + TDNotNil(reader); + NSInteger len = [string length]; + PKUniChar c; + NSInteger i = 0; + for ( ; i < len; i++) { + c = [string characterAtIndex:i]; + TDEquals(c, [reader read]); + } +} + + +- (void)testReadTooFar { + NSInteger len = [string length]; + NSInteger i = 0; + for ( ; i < len; i++) { + [reader read]; + } + TDEquals(PKEOF, [reader read]); +} + + +- (void)testUnread { + [reader read]; + [reader unread]; + PKUniChar a = 'a'; + TDEquals(a, [reader read]); + + [reader read]; + [reader read]; + [reader unread]; + PKUniChar c = 'c'; + TDEquals(c, [reader read]); +} + + +- (void)testUnreadTooFar { + [reader unread]; + PKUniChar a = 'a'; + TDEquals(a, [reader read]); + + [reader unread]; + [reader unread]; + [reader unread]; + [reader unread]; + PKUniChar a2 = 'a'; + TDEquals(a2, [reader read]); +} + +@end diff --git a/test/.svn/text-base/TDRegularParser.h.svn-base b/test/.svn/text-base/TDRegularParser.h.svn-base new file mode 100644 index 0000000..a4ea92b --- /dev/null +++ b/test/.svn/text-base/TDRegularParser.h.svn-base @@ -0,0 +1,35 @@ +// +// PKRegularParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDRegularParser : PKSequence { + PKCollectionParser *expressionParser; + PKCollectionParser *termParser; + PKCollectionParser *orTermParser; + PKCollectionParser *factorParser; + PKCollectionParser *nextFactorParser; + PKCollectionParser *phraseParser; + PKCollectionParser *phraseStarParser; + PKCollectionParser *phrasePlusParser; + PKCollectionParser *phraseQuestionParser; + PKCollectionParser *letterOrDigitParser; +} ++ (id)parserFromGrammar:(NSString *)s; + +@property (retain) PKCollectionParser *expressionParser; +@property (retain) PKCollectionParser *termParser; +@property (retain) PKCollectionParser *orTermParser; +@property (retain) PKCollectionParser *factorParser; +@property (retain) PKCollectionParser *nextFactorParser; +@property (retain) PKCollectionParser *phraseParser; +@property (retain) PKCollectionParser *phraseStarParser; +@property (retain) PKCollectionParser *phrasePlusParser; +@property (retain) PKCollectionParser *phraseQuestionParser; +@property (retain) PKCollectionParser *letterOrDigitParser; +@end diff --git a/test/.svn/text-base/TDRegularParser.m.svn-base b/test/.svn/text-base/TDRegularParser.m.svn-base new file mode 100644 index 0000000..a7c1fa4 --- /dev/null +++ b/test/.svn/text-base/TDRegularParser.m.svn-base @@ -0,0 +1,315 @@ +// +// PKRegularParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDRegularParser.h" + +@interface TDRegularParser () +- (void)didMatchChar:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchPlus:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +//- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchExpression:(PKAssembly *)a; +@end + +@implementation TDRegularParser + +- (id)init { + if (self = [super init]) { + [self add:self.expressionParser]; + } + return self; +} + + +- (void)dealloc { + self.expressionParser = nil; + self.termParser = nil; + self.orTermParser = nil; + self.factorParser = nil; + self.nextFactorParser = nil; + self.phraseParser = nil; + self.phraseStarParser = nil; + self.phrasePlusParser = nil; + self.phraseQuestionParser = nil; + self.letterOrDigitParser = nil; + [super dealloc]; +} + + ++ (id)parserFromGrammar:(NSString *)s { + TDRegularParser *p = [TDRegularParser parser]; + PKAssembly *a = [PKCharacterAssembly assemblyWithString:s]; + a = [p completeMatchFor:a]; + return [a pop]; +} + + +// expression = term orTerm* +// term = factor nextFactor* +// orTerm = '|' term +// factor = phrase | phraseStar | phrasePlus | phraseQuestion +// nextFactor = factor +// phrase = letterOrDigit | '(' expression ')' +// phraseStar = phrase '*' +// phraseStar = phrase '+' +// phraseStar = phrase '?' +// letterOrDigit = Letter | Digit + + +// expression = term orTerm* +- (PKCollectionParser *)expressionParser { + if (!expressionParser) { + self.expressionParser = [PKSequence sequence]; + expressionParser.name = @"expression"; + [expressionParser add:self.termParser]; + [expressionParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + [expressionParser setAssembler:self selector:@selector(didMatchExpression:)]; + } + return expressionParser; +} + + +// term = factor nextFactor* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + termParser.name = @"term"; + [termParser add:self.factorParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.nextFactorParser]]; + } + return termParser; +} + + +// orTerm = '|' term +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKSequence sequence]; + orTermParser.name = @"orTerm"; + [orTermParser add:[[PKSpecificChar specificCharWithChar:'|'] discard]]; + [orTermParser add:self.termParser]; + [orTermParser setAssembler:self selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// factor = phrase | phraseStar | phrasePlus | phraseQuestion +- (PKCollectionParser *)factorParser { + if (!factorParser) { + self.factorParser = [PKAlternation alternation]; + factorParser.name = @"factor"; + [factorParser add:self.phraseParser]; + [factorParser add:self.phraseStarParser]; + [factorParser add:self.phrasePlusParser]; + [factorParser add:self.phraseQuestionParser]; + } + return factorParser; +} + + +// nextFactor = factor +- (PKCollectionParser *)nextFactorParser { + if (!nextFactorParser) { + self.nextFactorParser = [PKAlternation alternation]; + nextFactorParser.name = @"nextFactor"; + [nextFactorParser add:self.phraseParser]; + [nextFactorParser add:self.phraseStarParser]; + [nextFactorParser add:self.phrasePlusParser]; + [nextFactorParser add:self.phraseQuestionParser]; +// [nextFactorParser setAssembler:self selector:@selector(didMatchAnd:)]; + } + return nextFactorParser; +} + + +// phrase = letterOrDigit | '(' expression ')' +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + PKSequence *s = [PKSequence sequence]; + [s add:[[PKSpecificChar specificCharWithChar:'('] discard]]; + [s add:self.expressionParser]; + [s add:[[PKSpecificChar specificCharWithChar:')'] discard]]; + + self.phraseParser = [PKAlternation alternation]; + phraseParser.name = @"phrase"; + [phraseParser add:self.letterOrDigitParser]; + [phraseParser add:s]; + } + return phraseParser; +} + + +// phraseStar = phrase '*' +- (PKCollectionParser *)phraseStarParser { + if (!phraseStarParser) { + self.phraseStarParser = [PKSequence sequence]; + phraseStarParser.name = @"phraseStar"; + [phraseStarParser add:self.phraseParser]; + [phraseStarParser add:[[PKSpecificChar specificCharWithChar:'*'] discard]]; + [phraseStarParser setAssembler:self selector:@selector(didMatchStar:)]; + } + return phraseStarParser; +} + + +// phrasePlus = phrase '+' +- (PKCollectionParser *)phrasePlusParser { + if (!phrasePlusParser) { + self.phrasePlusParser = [PKSequence sequence]; + phrasePlusParser.name = @"phrasePlus"; + [phrasePlusParser add:self.phraseParser]; + [phrasePlusParser add:[[PKSpecificChar specificCharWithChar:'+'] discard]]; + [phrasePlusParser setAssembler:self selector:@selector(didMatchPlus:)]; + } + return phrasePlusParser; +} + + +// phrasePlus = phrase '?' +- (PKCollectionParser *)phraseQuestionParser { + if (!phraseQuestionParser) { + self.phraseQuestionParser = [PKSequence sequence]; + phraseQuestionParser.name = @"phraseQuestion"; + [phraseQuestionParser add:self.phraseParser]; + [phraseQuestionParser add:[[PKSpecificChar specificCharWithChar:'?'] discard]]; + [phraseQuestionParser setAssembler:self selector:@selector(didMatchQuestion:)]; + } + return phraseQuestionParser; +} + + +// letterOrDigit = Letter | Digit +- (PKCollectionParser *)letterOrDigitParser { + if (!letterOrDigitParser) { + self.letterOrDigitParser = [PKAlternation alternation]; + letterOrDigitParser.name = @"letterOrDigit"; + [letterOrDigitParser add:[PKLetter letter]]; + [letterOrDigitParser add:[PKDigit digit]]; + [letterOrDigitParser setAssembler:self selector:@selector(didMatchChar:)]; + } + return letterOrDigitParser; +} + + +- (void)didMatchChar:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id obj = [a pop]; + NSAssert([obj isKindOfClass:[NSNumber class]], @""); + NSInteger c = [obj integerValue]; + [a push:[PKSpecificChar specificCharWithChar:c]]; +} + + +- (void)didMatchStar:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + NSAssert([top isKindOfClass:[PKParser class]], @""); + PKRepetition *rep = [PKRepetition repetitionWithSubparser:top]; + [a push:rep]; +} + + +- (void)didMatchPlus:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + NSAssert([top isKindOfClass:[PKParser class]], @""); + PKSequence *seq = [PKSequence sequence]; + [seq add:top]; + [seq add:[PKRepetition repetitionWithSubparser:top]]; + [a push:seq]; +} + + +- (void)didMatchQuestion:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + NSAssert([top isKindOfClass:[PKParser class]], @""); + PKAlternation *alt = [PKAlternation alternation]; + [alt add:[PKEmpty empty]]; + [alt add:top]; + [a push:alt]; +} + + +//- (void)didMatchAnd:(PKAssembly *)a { +//// NSLog(@"%s", _cmd); +//// NSLog(@"a: %@", a); +// id second = [a pop]; +// id first = [a pop]; +// NSAssert([first isKindOfClass:[PKParser class]], @""); +// NSAssert([second isKindOfClass:[PKParser class]], @""); +// PKSequence *p = [PKSequence sequence]; +// [p add:first]; +// [p add:second]; +// [a push:p]; +//} + + +- (void)didMatchExpression:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + + NSAssert(![a isStackEmpty], @""); + + id obj = nil; + NSMutableArray *objs = [NSMutableArray array]; + while (![a isStackEmpty]) { + obj = [a pop]; + [objs addObject:obj]; + NSAssert([obj isKindOfClass:[PKParser class]], @""); + } + + if ([objs count] > 1) { + PKSequence *seq = [PKSequence sequence]; + for (id obj in [objs reverseObjectEnumerator]) { + [seq add:obj]; + } + [a push:seq]; + } else { + NSAssert((NSUInteger)1 == [objs count], @""); + PKParser *p = [objs objectAtIndex:0]; + [a push:p]; + } +} + + +- (void)didMatchOr:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id second = [a pop]; + id first = [a pop]; +// NSLog(@"first: %@", first); +// NSLog(@"second: %@", second); + NSAssert(first, @""); + NSAssert(second, @""); + NSAssert([first isKindOfClass:[PKParser class]], @""); + NSAssert([second isKindOfClass:[PKParser class]], @""); + PKAlternation *p = [PKAlternation alternation]; + [p add:first]; + [p add:second]; + [a push:p]; +} + +@synthesize expressionParser; +@synthesize termParser; +@synthesize orTermParser; +@synthesize factorParser; +@synthesize nextFactorParser; +@synthesize phraseParser; +@synthesize phraseStarParser; +@synthesize phrasePlusParser; +@synthesize phraseQuestionParser; +@synthesize letterOrDigitParser; +@end diff --git a/test/.svn/text-base/TDRegularParserTest.h.svn-base b/test/.svn/text-base/TDRegularParserTest.h.svn-base new file mode 100644 index 0000000..89638f3 --- /dev/null +++ b/test/.svn/text-base/TDRegularParserTest.h.svn-base @@ -0,0 +1,19 @@ +// +// PKRegularParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "TDRegularParser.h" + +@interface TDRegularParserTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + TDRegularParser *p; + PKAssembly *res; +} + +@end diff --git a/test/.svn/text-base/TDRegularParserTest.m.svn-base b/test/.svn/text-base/TDRegularParserTest.m.svn-base new file mode 100644 index 0000000..6e608b0 --- /dev/null +++ b/test/.svn/text-base/TDRegularParserTest.m.svn-base @@ -0,0 +1,401 @@ +// +// PKRegularParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDRegularParserTest.h" + +@implementation TDRegularParserTest + +- (void)setUp { + p = [TDRegularParser parser]; +} + + +- (void)testAabPlus { + s = @"aab+"; + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"aabbbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, a, b, b, b, b]aabbbb^", [res description]); +} + + +- (void)testAabStar { + s = @"aab*"; + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"aabbbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, a, b, b, b, b]aabbbb^", [res description]); +} + + +- (void)testAabQuestion { + s = @"aab?"; + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"aabbbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, a, b]aab^bbb", [res description]); +} + + +- (void)testAb { + s = @"ab"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]ab^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + TDEquals((NSUInteger)2, [seq.subparsers count]); + + PKSpecificChar *c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + c = [seq.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"ab"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, b]ab^", [res description]); +} + + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]abc^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + TDEquals((NSUInteger)3, [seq.subparsers count]); + + PKSpecificChar *c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + c = [seq.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + c = [seq.subparsers objectAtIndex:2]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"c", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, b, c]abc^", [res description]); +} + + +- (void)testAOrB { + s = @"a|b"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]a|b^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"b"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b]b^", [res description]); +} + + +- (void)test4Or7 { + s = @"4|7"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]4|7^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"4", c.string); + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"7", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"4"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[4]4^", [res description]); +} + + +- (void)testAOrBStar { + s = @"a|b*"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]a|b*^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + PKRepetition *rep = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKRepetition class], [rep class]); + c = (PKSpecificChar *)rep.subparser; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"bbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b, b, b]bbb^", [res description]); +} + + +- (void)testAOrBPlus { + s = @"a|b+"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]a|b+^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + PKSequence *seq = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKSequence class], [seq class]); + + c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + PKRepetition *rep = [seq.subparsers objectAtIndex:1]; + TDEqualObjects([PKRepetition class], [rep class]); + c = (PKSpecificChar *)rep.subparser; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"bbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b, b, b]bbb^", [res description]); + + s = @"abbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a]a^bbb", [res description]); +} + + +- (void)testAOrBQuestion { + s = @"a|b?"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]a|b?^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + alt = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKAlternation class], [alt class]); + + PKEmpty *e = [alt.subparsers objectAtIndex:0]; + TDTrue([e isMemberOfClass:[PKEmpty class]]); + + c = (PKSpecificChar *)[alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"bbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b]b^bb", [res description]); + + s = @"abbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a]a^bbb", [res description]); +} + + +- (void)testParenAOrBParenStar { + s = @"(a|b)*"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Repetition](a|b)*^", [res description]); + PKRepetition *rep = [res pop]; + TDTrue([rep isMemberOfClass:[PKRepetition class]]); + + PKAlternation *alt = (PKAlternation *)rep.subparser; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKRepetition class]]); + s = @"bbbaaa"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b, b, b, a, a, a]bbbaaa^", [res description]); +} + + +- (void)testParenAOrBParenPlus { + s = @"(a|b)+"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence](a|b)+^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + + TDEquals((NSUInteger)2, [seq.subparsers count]); + + PKAlternation *alt = [seq.subparsers objectAtIndex:0]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + PKRepetition *rep = [seq.subparsers objectAtIndex:1]; + TDTrue([rep isMemberOfClass:[PKRepetition class]]); + + alt = (PKAlternation *)rep.subparser; + TDEqualObjects([PKAlternation class], [alt class]); + + c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"bbbaaa"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b, b, b, a, a, a]bbbaaa^", [res description]); +} + + +- (void)testParenAOrBParenQuestion { + s = @"(a|b)?"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation](a|b)?^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + + TDEquals((NSUInteger)2, [alt.subparsers count]); + PKEmpty *e = [alt.subparsers objectAtIndex:0]; + TDTrue([PKEmpty class] == [e class]); + + alt = [alt.subparsers objectAtIndex:1]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"bbbaaa"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b]b^bbaaa", [res description]); +} + +@end diff --git a/test/.svn/text-base/TDRepetitionTest.h.svn-base b/test/.svn/text-base/TDRepetitionTest.h.svn-base new file mode 100644 index 0000000..1cf4e54 --- /dev/null +++ b/test/.svn/text-base/TDRepetitionTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKRepetitionTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDRepetitionTest : SenTestCase { + PKParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDRepetitionTest.m.svn-base b/test/.svn/text-base/TDRepetitionTest.m.svn-base new file mode 100644 index 0000000..c97c2cd --- /dev/null +++ b/test/.svn/text-base/TDRepetitionTest.m.svn-base @@ -0,0 +1,222 @@ +// +// PKRepetitionTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDRepetitionTest.h" + +@interface PKParser () +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@implementation TDRepetitionTest + +- (void)setUp { +} + + +- (void)tearDown { + [a release]; + [p release]; +} + + +#pragma mark - + +- (void)testWordRepetitionAllMatchesForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + NSLog(@"all: %@", all); + + TDNotNil(all); + NSUInteger c = [all count]; + TDEquals((NSUInteger)4, c); +} + + +- (void)testWordRepetitionBestMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + + PKAssembly *result = [p bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testWordRepetitionBestMatchForFooSpaceBarSpace123 { + s = @"foo bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, bar]foo/bar^123", [result description]); +} + + +- (void)testWordRepetitionAllMatchesForFooSpaceBarSpace123 { + s = @"foo bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + NSLog(@"all: %@", all); + + TDNotNil(all); + NSUInteger c = [all count]; + TDEquals((NSUInteger)3, c); +} + + +- (void)testWordRepetitionAllMatchesFooSpace123SpaceBaz { + s = @"foo 123 baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + NSLog(@"all: %@", all); + + TDNotNil(all); + NSUInteger c = [all count]; + TDEquals((NSUInteger)2, c); +} + + +- (void)testNumRepetitionAllMatchesForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + NSLog(@"all: %@", all); + + TDNotNil(all); + NSUInteger c = [all count]; + TDEquals((NSUInteger)1, c); +} + + +- (void)testWordRepetitionCompleteMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testWordRepetitionCompleteMatchForFooSpaceBarSpace123 { + s = @"foo bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testWordRepetitionCompleteMatchFor456SpaceBarSpace123 { + s = @"456 bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testNumRepetitionCompleteMatchFor456SpaceBarSpace123 { + s = @"456 bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testNumRepetitionAllMatchesFor123Space456SpaceBaz { + s = @"123 456 baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + + TDNotNil(all); + NSInteger c = [all count]; + TDEquals((NSUInteger)3, (NSUInteger)c); +} + + +- (void)testNumRepetitionBestMatchFor123Space456SpaceBaz { + s = @"123 456 baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123, 456]123/456^baz", [result description]); +} + + +- (void)testNumRepetitionCompleteMatchFor123 { + s = @"123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^", [result description]); +} + + +- (void)testWordRepetitionCompleteMatchFor123 { + s = @"123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)testWordRepetitionBestMatchForFoo { + s = @"foo"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo]foo^", [result description]); +} + +@end diff --git a/test/.svn/text-base/TDReservedWord.h.svn-base b/test/.svn/text-base/TDReservedWord.h.svn-base new file mode 100644 index 0000000..a2028c2 --- /dev/null +++ b/test/.svn/text-base/TDReservedWord.h.svn-base @@ -0,0 +1,17 @@ +// +// PKReservedWord.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface TDReservedWord : PKWord { + +} + ++ (void)setReservedWords:(NSArray *)inWords; +@end diff --git a/test/.svn/text-base/TDReservedWord.m.svn-base b/test/.svn/text-base/TDReservedWord.m.svn-base new file mode 100644 index 0000000..417fa09 --- /dev/null +++ b/test/.svn/text-base/TDReservedWord.m.svn-base @@ -0,0 +1,43 @@ +// +// PKReservedWord.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +static NSArray *sTDReservedWords = nil; + +@interface TDReservedWord () ++ (NSArray *)reservedWords; +@end + +@implementation TDReservedWord + ++ (NSArray *)reservedWords { + return [[sTDReservedWords retain] autorelease]; +} + + ++ (void)setReservedWords:(NSArray *)inWords { + if (inWords != sTDReservedWords) { + [sTDReservedWords autorelease]; + sTDReservedWords = [inWords copy]; + } +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + NSString *s = tok.stringValue; + return [s length] && [[TDReservedWord reservedWords] containsObject:s]; +} + +@end diff --git a/test/.svn/text-base/TDReservedWordTest.h.svn-base b/test/.svn/text-base/TDReservedWordTest.h.svn-base new file mode 100644 index 0000000..6f08d3f --- /dev/null +++ b/test/.svn/text-base/TDReservedWordTest.h.svn-base @@ -0,0 +1,15 @@ +// +// PKReservedWordTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDReservedWordTest : SenTestCase { + +} + +@end diff --git a/test/.svn/text-base/TDReservedWordTest.m.svn-base b/test/.svn/text-base/TDReservedWordTest.m.svn-base new file mode 100644 index 0000000..b5c7767 --- /dev/null +++ b/test/.svn/text-base/TDReservedWordTest.m.svn-base @@ -0,0 +1,41 @@ +// +// PKReservedWordTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDReservedWordTest.h" +#import "ParseKit.h" + +@implementation TDReservedWordTest + +- (void)testFoobar { + NSString *s = @"Foobar"; + [TDReservedWord setReservedWords:[NSArray arrayWithObject:@"Foobar"]]; + + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [TDReservedWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[Foobar]Foobar^", [result description]); +// TDNil(result); +} + + +- (void)testfoobar { + NSString *s = @"foobar"; + [TDReservedWord setReservedWords:[NSArray arrayWithObject:@"Foobar"]]; + + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [TDReservedWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + +@end diff --git a/test/.svn/text-base/TDRobotCommandTest.h.svn-base b/test/.svn/text-base/TDRobotCommandTest.h.svn-base new file mode 100644 index 0000000..897ed44 --- /dev/null +++ b/test/.svn/text-base/TDRobotCommandTest.h.svn-base @@ -0,0 +1,15 @@ +// +// PKRobotCommandTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDRobotCommandTest : SenTestCase { + +} + +@end diff --git a/test/.svn/text-base/TDRobotCommandTest.m.svn-base b/test/.svn/text-base/TDRobotCommandTest.m.svn-base new file mode 100644 index 0000000..0b2936e --- /dev/null +++ b/test/.svn/text-base/TDRobotCommandTest.m.svn-base @@ -0,0 +1,177 @@ +// +// PKRobotCommandTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDRobotCommandTest.h" + +@interface RobotCommand : NSObject { + NSString *location; +} +@property (copy) NSString *location; +@end + +@implementation RobotCommand + +- (void)dealloc { + self.location = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + RobotCommand *c = [[RobotCommand allocWithZone:zone] init]; + c->location = [location copy]; + return c; +} + +@synthesize location; +@end + +@interface RobotPickCommand : RobotCommand {} +@end +@implementation RobotPickCommand +- (NSString *)description { return [NSString stringWithFormat:@"pick %@", self.location]; } +@end + +@interface RobotPlaceCommand : RobotCommand {} +@end +@implementation RobotPlaceCommand +- (NSString *)description { return [NSString stringWithFormat:@"place %@", self.location]; } +@end + +@interface RobotScanCommand : RobotCommand {} +@end +@implementation RobotScanCommand +- (NSString *)description { return [NSString stringWithFormat:@"scan %@", self.location]; } +@end + +@implementation TDRobotCommandTest + +// e = command* +// command = pickCommand | placeCommand | scanCommand +// pickCommand = "pick" "carrier" "from" location +// placeCommand = "place" "carrier" "at" location +// scanCommand = "scan" location +// location = Word + +- (PKParser *)location { + return [PKWord word]; +} + + +- (PKParser *)pickCommand { + PKSequence *s = [PKSequence sequence]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"pick"] discard]]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"carrier"] discard]]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"from"] discard]]; + [s add:[self location]]; + [s setAssembler:self selector:@selector(didMatchPickCommand:)]; + return s; +} + + +- (PKParser *)placeCommand { + PKSequence *s = [PKSequence sequence]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"place"] discard]]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"carrier"] discard]]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"at"] discard]]; + [s add:[self location]]; + [s setAssembler:self selector:@selector(didMatchPlaceCommand:)]; + return s; +} + + +- (PKParser *)scanCommand { + PKSequence *s = [PKSequence sequence]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"scan"] discard]]; + [s add:[self location]]; + [s setAssembler:self selector:@selector(didMatchScanCommand:)]; + return s; +} + + +- (PKParser *)command { + PKAlternation *a = [PKAlternation alternation]; + [a add:[self pickCommand]]; + [a add:[self placeCommand]]; + [a add:[self scanCommand]]; + return a; +} + + +- (void)testPick { + NSString *s1 = @"pick carrier from LINE_IN"; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithString:s1]; + PKParser *p = [self command]; + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[]pick/carrier/from/LINE_IN^", [result description]); + + id target = result.target; + TDNotNil(target); + TDEqualObjects(@"pick LINE_IN", [target description]); +} + + +- (void)testPlace { + NSString *s2 = @"place carrier at LINE_OUT"; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithString:s2]; + PKParser *p = [self command]; + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[]place/carrier/at/LINE_OUT^", [result description]); + + id target = result.target; + TDNotNil(target); + TDEqualObjects(@"place LINE_OUT", [target description]); +} + + +- (void)testScan { + NSString *s3 = @"scan DB101_OUT"; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithString:s3]; + PKParser *p = [self command]; + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[]scan/DB101_OUT^", [result description]); + + id target = result.target; + TDNotNil(target); + TDEqualObjects(@"scan DB101_OUT", [target description]); +} + + +- (void)didMatchPickCommand:(PKAssembly *)a { + RobotPickCommand *c = [[[RobotPickCommand alloc] init] autorelease]; + PKToken *location = [a pop]; + c.location = location.stringValue; + a.target = c; +} + + +- (void)didMatchPlaceCommand:(PKAssembly *)a { + RobotPlaceCommand *c = [[[RobotPlaceCommand alloc] init] autorelease]; + PKToken *location = [a pop]; + c.location = location.stringValue; + a.target = c; +} + + +- (void)didMatchScanCommand:(PKAssembly *)a { + RobotScanCommand *c = [[[RobotScanCommand alloc] init] autorelease]; + PKToken *location = [a pop]; + c.location = location.stringValue; + a.target = c; +} + +@end diff --git a/test/.svn/text-base/TDScientificNumberStateTest.h.svn-base b/test/.svn/text-base/TDScientificNumberStateTest.h.svn-base new file mode 100644 index 0000000..30e9988 --- /dev/null +++ b/test/.svn/text-base/TDScientificNumberStateTest.h.svn-base @@ -0,0 +1,18 @@ +// +// PKScientificNumberStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDScientificNumberStateTest : SenTestCase { + PKNumberState *numberState; + PKTokenizer *t; + PKReader *r; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDScientificNumberStateTest.m.svn-base b/test/.svn/text-base/TDScientificNumberStateTest.m.svn-base new file mode 100644 index 0000000..e611e55 --- /dev/null +++ b/test/.svn/text-base/TDScientificNumberStateTest.m.svn-base @@ -0,0 +1,1223 @@ +// +// PKScientificNumberStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/25/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDScientificNumberStateTest.h" +#import "TDArithmeticParser.h" + +@implementation TDScientificNumberStateTest + +- (void)setUp { + t = [[PKTokenizer alloc] init]; + r = [[PKReader alloc] init]; + numberState = t.numberState; + numberState.allowsScientificNotation = YES; + [t setTokenizerState:numberState from:'0' to:'9']; + [t setTokenizerState:numberState from:'.' to:'.']; + [t setTokenizerState:numberState from:'-' to:'-']; +// NSLog(@"\n\n\n\n\n %f \n\n\n\n\n", 020); +} + + +- (void)tearDown { + [numberState release]; + [r release]; +} + + +//- (void)testScientificNumberStringArithmetic { +// t.string = @"1e2 + 1e1 + 1e0 + 1e-1 + 1e-2 + 1e-3"; +// TDArithmeticParser *p = [[[TDArithmeticParser alloc] init] autorelease]; +// PKAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; +// PKAssembly *res = [p bestMatchFor:a]; +// PKToken *tok = [res pop]; +// TDEquals((CGFloat)111.111, tok.floatValue); +//} + + +- (void)testSingleDigit { + s = @"3"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)3.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"3", tok.stringValue); +} + + +- (void)testDoubleDigit { + s = @"47"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)47.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"47", tok.stringValue); +} + + +- (void)testTripleDigit { + s = @"654"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)654.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"654", tok.stringValue); +} + + +- (void)testSingleDigitPositive { + s = @"+3"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)3.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+3", tok.stringValue); +} + + +- (void)testDoubleDigitPositive { + s = @"+22"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)22.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)testDoubleDigitPositiveSpace { + s = @"+22 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)22.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)testMultipleDots { + s = @"1.1.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.1", tok.stringValue); + + tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".1", tok.stringValue); +} + + +- (void)testOneDot { + s = @"1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1", tok.stringValue); +} + + +- (void)testCustomOneDot1 { + s = @"1."; + t.string = s; + numberState.allowsTrailingDot = YES; + numberState.allowsScientificNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.", tok.stringValue); +} + + +- (void)testCustomOneDot2 { + s = @"1."; + t.string = s; + numberState.allowsTrailingDot = YES; + numberState.allowsScientificNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.", tok.stringValue); +} + + +- (void)testOneDotZero { + s = @"1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.0", tok.stringValue); +} + + +- (void)testPositiveOneDot { + s = @"+1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1", tok.stringValue); +} + + +- (void)testPositiveOneDotCustom { + s = @"+1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.", tok.stringValue); +} + + +- (void)testPositiveOneDotZero { + s = @"+1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.0", tok.stringValue); +} + + +- (void)testPositiveOneDotZeroSpace { + s = @"+1.0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.0", tok.stringValue); +} + + +- (void)testNegativeOneDot { + s = @"-1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testNegativeOneDotCustom { + s = @"-1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.", tok.stringValue); +} + + +- (void)testNegativeOneDotSpace { + s = @"-1. "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testNegativeOneDotZero { + s = @"-1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.0", tok.stringValue); +} + + +- (void)testNegativeOneDotZeroSpace { + s = @"-1.0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.0", tok.stringValue); +} + + +- (void)testOneDotOne { + s = @"1.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.1", tok.stringValue); +} + + +- (void)testZeroDotOne { + s = @"0.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0.1", tok.stringValue); +} + + +- (void)testDotOne { + s = @".1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".1", tok.stringValue); +} + + +- (void)testDotZero { + s = @".0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); +} + + +- (void)testNegativeDotZero { + s = @"-.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.0", tok.stringValue); +} + + +- (void)testPositiveDotZero { + s = @"+.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+.0", tok.stringValue); +} + + +- (void)testPositiveDotOne { + s = @"+.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+.1", tok.stringValue); +} + + +- (void)testNegativeDotOne { + s = @"-.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1", tok.stringValue); +} + + +- (void)testNegativeDotOneOne { + s = @"-.11"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.11, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.11", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOne { + s = @"-.111"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.111", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZero { + s = @"-.1110"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1110", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZeroZero { + s = @"-.11100"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.11100", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZeroSpace { + s = @"-.1110 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1110", tok.stringValue); +} + + +- (void)testZeroDotThreeSixtyFive { + s = @"0.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0.365", tok.stringValue); +} + + +- (void)testNegativeZeroDotThreeSixtyFive { + s = @"-0.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0.365", tok.stringValue); +} + + +- (void)testNegativeTwentyFourDotThreeSixtyFive { + s = @"-24.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-24.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-24.365", tok.stringValue); +} + + +- (void)testTwentyFourDotThreeSixtyFive { + s = @"24.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)24.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"24.365", tok.stringValue); +} + + +- (void)testZero { + s = @"0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0", tok.stringValue); +} + + +- (void)testNegativeOne { + s = @"-1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testOne { + s = @"1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1", tok.stringValue); +} + + +- (void)testPositiveOne { + s = @"+1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1", tok.stringValue); +} + + +- (void)testPositiveZero { + s = @"+0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+0", tok.stringValue); +} + + +- (void)testPositiveZeroSpace { + s = @"+0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+0", tok.stringValue); +} + + +- (void)testNegativeZero { + s = @"-0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0", tok.stringValue); +} + + +- (void)testNull { + s = @"NULL"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testNil { + s = @"nil"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testEmptyString { + s = @""; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDot { + s = @"."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDotSpace { + s = @". "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDotSpaceOne { + s = @". 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlus { + s = @"+"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlusSpace { + s = @"+ "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlusSpaceOne { + s = @"+ 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinus { + s = @"-"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinusSpace { + s = @"- "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinusSpaceOne { + s = @"- 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testInitSig { + s = @"- (id)init {"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(@"-", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); +} + + +#pragma mark - + +- (void)test1e1 { + s = @"1e1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)10.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)test1e2 { + s = @"1e2"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)100.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)test2dot0e2 { + s = @"2.0e2"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); +} + + +- (void)test2dot0E2 { + s = @"2.0E2"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); +} + + +- (void)test2e2 { + s = @"2e2"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); +} + + +- (void)test2eNegative2Tok { + s = @"2e-2"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.02, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2e2Tok { + s = @"2e2"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2e2fooTok { + s = @"2e2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2e2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2eNegative2fooTok { + s = @"2e-2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.02, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2e-2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2ePositive2fooTok { + s = @"2e+2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2e+2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2dot0ePositive2fooTok { + s = @"2.0e+2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2.0e+2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2dot0eNegative2fooTok { + s = @"2.0e-2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.02, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2.0e-2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testNotAllowsScientificNotation2dot0e2 { + s = @"2.0e2"; + t.string = s; + r.string = s; + numberState.allowsScientificNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2.0", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"e2", tok.stringValue); +} + + +- (void)testNotAllowsScientificNotation2dot0E2 { + s = @"2.0E2"; + t.string = s; + r.string = s; + numberState.allowsScientificNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2.0", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"E2", tok.stringValue); +} + + +- (void)testNotAllowsScientificNotation2e2 { + s = @"2e2"; + t.string = s; + r.string = s; + numberState.allowsScientificNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"e2", tok.stringValue); +} + + +- (void)testOctal { + s = @"020"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testOctal2 { + s = @"020"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testMinusOctal { + s = @"-020"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)-16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-020", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testMinusOctal2 { + s = @"-020"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)-16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-020", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testOctalDecimal { + s = @"020.0"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testOctalDecimal2 { + s = @"020.0"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testOctalDecimalNO { + s = @"020.0"; + t.string = s; + numberState.allowsOctalNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)20.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020.0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHex { + s = @"0x20"; + t.string = s; + numberState.allowsOctalNotation = NO; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)32.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x20", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHex2 { + s = @"0x20"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)32.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x20", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testNotHex { + s = @"0x"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isWord); + TDEqualObjects(@"x", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexAlpha { + s = @"0xA"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)10.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0xA", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); + + s = @"0xa"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + tok = [t nextToken]; + TDEquals((CGFloat)10.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0xa", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); + + s = @"0xB7"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + tok = [t nextToken]; + TDEquals((CGFloat)183.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0xB7", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); + + s = @"0x8EE"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + tok = [t nextToken]; + TDEquals((CGFloat)2286.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x8EE", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testMinusHex { + s = @"-0x20"; + t.string = s; + numberState.allowsHexadecimalNotation = NO; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)-32.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0x20", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testMinusHex2 { + s = @"-0x20"; + t.string = s; + numberState.allowsHexadecimalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)-32.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0x20", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexDecimal { + s = @"0x30.0"; + t.string = s; + numberState.allowsOctalNotation = NO; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)48.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x30", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexDecimal2 { + s = @"0x40.0"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)64.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x40", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexDecimal3 { + s = @"00x30.0"; + t.string = s; + numberState.allowsOctalNotation = NO; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"00", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"x30", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexDecimal4 { + s = @"00x30.0"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"00", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"x30", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + +@end diff --git a/test/.svn/text-base/TDSequenceTest.h.svn-base b/test/.svn/text-base/TDSequenceTest.h.svn-base new file mode 100644 index 0000000..adaca13 --- /dev/null +++ b/test/.svn/text-base/TDSequenceTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKSequenceTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDSequenceTest : SenTestCase { + PKCollectionParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDSequenceTest.m.svn-base b/test/.svn/text-base/TDSequenceTest.m.svn-base new file mode 100644 index 0000000..3c83301 --- /dev/null +++ b/test/.svn/text-base/TDSequenceTest.m.svn-base @@ -0,0 +1,251 @@ +// +// PKSequenceTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDSequenceTest.h" + +@interface PKParser () +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@implementation TDSequenceTest + +- (void)tearDown { +} + +- (void)testDiscard { + s = @"foo -"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo]foo/-^", [result description]); +} + + +- (void)testDiscard2 { + s = @"foo foo -"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, foo]foo/foo/-^", [result description]); +} + + +- (void)testDiscard3 { + s = @"foo - foo"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, foo]foo/-/foo^", [result description]); +} + + +- (void)testDiscard1 { + s = @"- foo"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo]-/foo^", [result description]); +} + + +- (void)testDiscard4 { + s = @"- foo -"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo]-/foo/-^", [result description]); +} + + +- (void)testDiscard5 { + s = @"- foo + foo"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"+"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, foo]-/foo/+/foo^", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz1 { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *foo = [PKLiteral literalWithString:@"foo"]; + PKParser *bar = [PKLiteral literalWithString:@"bar"]; + PKParser *baz = [PKLiteral literalWithString:@"baz"]; + p = [PKSequence sequenceWithSubparsers:foo, baz, bar, nil]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNil(result); +} + + +- (void)testFalseLiteralBestMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testTrueLiteralCompleteMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testTrueLiteralCompleteMatchForFooSpaceBarSpaceBaz1 { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKWord word]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testFalseLiteralCompleteMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testFalseLiteralCompleteMatchForFooSpaceBarSpaceBaz1 { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKNumber number]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testTrueLiteralAllMatchsForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); +} + + +- (void)testFalseLiteralAllMatchsForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"123"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + NSSet *result = [p allMatchesFor:[NSSet setWithObject:a]]; + + TDNotNil(result); + NSUInteger c = [result count]; + TDEquals((NSUInteger)0, c); +} + +@end diff --git a/test/.svn/text-base/TDSignificantWhitespaceState.h.svn-base b/test/.svn/text-base/TDSignificantWhitespaceState.h.svn-base new file mode 100644 index 0000000..dff96d2 --- /dev/null +++ b/test/.svn/text-base/TDSignificantWhitespaceState.h.svn-base @@ -0,0 +1,24 @@ +// +// PKSignificantWhitespaceState.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import + +// NOTE: this class is not currently in use or included in the Framework. It is an example of how to add a new token type + +static const NSInteger PKTokenTypeWhitespace = 5; + +@interface PKToken (TDSignificantWhitespaceStateAdditions) +@property (nonatomic, readonly, getter=isWhitespace) BOOL whitespace; +@end + +@interface TDSignificantWhitespaceState : PKWhitespaceState { + +} +@end diff --git a/test/.svn/text-base/TDSignificantWhitespaceState.m.svn-base b/test/.svn/text-base/TDSignificantWhitespaceState.m.svn-base new file mode 100644 index 0000000..231db96 --- /dev/null +++ b/test/.svn/text-base/TDSignificantWhitespaceState.m.svn-base @@ -0,0 +1,69 @@ +// +// PKSignificantWhitespaceState.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation PKToken (TDSignificantWhitespaceStateAdditions) + +- (BOOL)isWhitespace { + return self.tokenType == PKTokenTypeWhitespace; +} + + +- (NSString *)debugDescription { + NSString *typeString = nil; + if (self.isNumber) { + typeString = @"Number"; + } else if (self.isQuotedString) { + typeString = @"Quoted String"; + } else if (self.isSymbol) { + typeString = @"Symbol"; + } else if (self.isWord) { + typeString = @"Word"; + } else if (self.isWhitespace) { + typeString = @"Whitespace"; + } + return [NSString stringWithFormat:@"<%@ %C%@%C>", typeString, 0x00ab, self.value, 0x00bb]; +} + +@end + +@implementation TDSignificantWhitespaceState + +- (void)dealloc { + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + c = cin; + while ([self isWhitespaceChar:c]) { + [self append:c]; + c = [r read]; + } + if (c != -1) { + [r unread]; + } + + return [PKToken tokenWithTokenType:PKTokenTypeWhitespace stringValue:[self bufferedString] floatValue:0.0]; +} + +@end diff --git a/test/.svn/text-base/TDSignificantWhitespaceStateTest.h.svn-base b/test/.svn/text-base/TDSignificantWhitespaceStateTest.h.svn-base new file mode 100644 index 0000000..20699b5 --- /dev/null +++ b/test/.svn/text-base/TDSignificantWhitespaceStateTest.h.svn-base @@ -0,0 +1,18 @@ +// +// PKSignificantWhitespaceStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@interface TDSignificantWhitespaceStateTest : SenTestCase { + TDSignificantWhitespaceState *whitespaceState; + PKReader *r; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDSignificantWhitespaceStateTest.m.svn-base b/test/.svn/text-base/TDSignificantWhitespaceStateTest.m.svn-base new file mode 100644 index 0000000..a5efeed --- /dev/null +++ b/test/.svn/text-base/TDSignificantWhitespaceStateTest.m.svn-base @@ -0,0 +1,164 @@ +// +// PKSignificantWhitespaceStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDSignificantWhitespaceStateTest.h" + + +@implementation TDSignificantWhitespaceStateTest + +- (void)setUp { + whitespaceState = [[TDSignificantWhitespaceState alloc] init]; +} + + +- (void)tearDown { + [whitespaceState release]; + [r release]; +} + + +- (void)testSpace { + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testTwoSpaces { + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testEmptyString { + s = @""; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testTab { + s = @"\t"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testNewLine { + s = @"\n"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testCarriageReturn { + s = @"\r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testSpaceCarriageReturn { + s = @" \r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testSpaceTabNewLineSpace { + s = @" \t\n "; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testSpaceA { + s = @" a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@" ", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + +- (void)testSpaceASpace { + s = @" a "; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@" ", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +- (void)testTabA { + s = @"\ta"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@"\t", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +- (void)testNewLineA { + s = @"\na"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@"\n", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +- (void)testCarriageReturnA { + s = @"\ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@"\r", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +- (void)testNewLineSpaceCarriageReturnA { + s = @"\n \ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@"\n \r", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +@end diff --git a/test/.svn/text-base/TDSlashSlashState.h.svn-base b/test/.svn/text-base/TDSlashSlashState.h.svn-base new file mode 100644 index 0000000..a090d15 --- /dev/null +++ b/test/.svn/text-base/TDSlashSlashState.h.svn-base @@ -0,0 +1,20 @@ +// +// PKSlashSlashState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class TDSlashSlashState + @brief A slash slash state ignores everything up to an end-of-line and returns the tokenizer's next token. +*/ +@interface TDSlashSlashState : PKTokenizerState { + +} + +@end diff --git a/test/.svn/text-base/TDSlashSlashState.m.svn-base b/test/.svn/text-base/TDSlashSlashState.m.svn-base new file mode 100644 index 0000000..5483cfe --- /dev/null +++ b/test/.svn/text-base/TDSlashSlashState.m.svn-base @@ -0,0 +1,53 @@ +// +// PKSlashSlashState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation TDSlashSlashState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + BOOL reportTokens = t.slashState.reportsCommentTokens; + if (reportTokens) { + [self resetWithReader:r]; + [self append:'/']; + } + + NSInteger c = cin; + + while ('\n' != c && '\r' != c && -1 != c) { + if (reportTokens) { + [self append:c]; + } + c = [r read]; + } + if (-1 != c) { + [r unread]; + } + + if (reportTokens) { + return [PKToken tokenWithTokenType:PKTokenTypeComment stringValue:[self bufferedString] floatValue:0.0]; + } else { + return [t nextToken]; + } +} + +@end diff --git a/test/.svn/text-base/TDSlashStarState.h.svn-base b/test/.svn/text-base/TDSlashStarState.h.svn-base new file mode 100644 index 0000000..1a94b9b --- /dev/null +++ b/test/.svn/text-base/TDSlashStarState.h.svn-base @@ -0,0 +1,20 @@ +// +// PKSlashStarState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class TDSlashStarState + @brief A slash star state ignores everything up to a closing star and slash, and then returns the tokenizer's next token. +*/ +@interface TDSlashStarState : PKTokenizerState { + +} + +@end diff --git a/test/.svn/text-base/TDSlashStarState.m.svn-base b/test/.svn/text-base/TDSlashStarState.m.svn-base new file mode 100644 index 0000000..07114b8 --- /dev/null +++ b/test/.svn/text-base/TDSlashStarState.m.svn-base @@ -0,0 +1,72 @@ +// +// PKSlashStarState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation TDSlashStarState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + BOOL reportTokens = t.slashState.reportsCommentTokens; + if (reportTokens) { + [self resetWithReader:r]; + [self append:'/']; + } + + NSInteger c = cin; + while (-1 != c) { + if (reportTokens) { + [self append:c]; + } + c = [r read]; + + if ('*' == c) { + NSInteger peek = [r read]; + if ('/' == peek) { + if (reportTokens) { + [self append:c]; + [self append:peek]; + } + c = [r read]; + break; + } else if ('*' == peek) { + [r unread]; + } else { + if (reportTokens) { + [self append:c]; + } + c = peek; + } + } + } + + if (-1 != c) { + [r unread]; + } + + if (reportTokens) { + return [PKToken tokenWithTokenType:PKTokenTypeComment stringValue:[self bufferedString] floatValue:0.0]; + } else { + return [t nextToken]; + } +} + +@end diff --git a/test/.svn/text-base/TDSlashState.h.svn-base b/test/.svn/text-base/TDSlashState.h.svn-base new file mode 100644 index 0000000..fc8146e --- /dev/null +++ b/test/.svn/text-base/TDSlashState.h.svn-base @@ -0,0 +1,27 @@ +// +// PKSlashState.h +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +@class TDSlashSlashState; +@class TDSlashStarState; + +/*! + @class TDSlashState + @brief This state will either delegate to a comment-handling state, or return a PKSymbol token with just a slash in it. +*/ +@interface TDSlashState : PKTokenizerState { + TDSlashSlashState *slashSlashState; + TDSlashStarState *slashStarState; + BOOL reportsCommentTokens; +} + + +@property (nonatomic) BOOL reportsCommentTokens; +@end diff --git a/test/.svn/text-base/TDSlashState.m.svn-base b/test/.svn/text-base/TDSlashState.m.svn-base new file mode 100644 index 0000000..728d706 --- /dev/null +++ b/test/.svn/text-base/TDSlashState.m.svn-base @@ -0,0 +1,59 @@ +// +// PKSlashState.m +// ParseKit +// +// Created by Todd Ditchendorf on 1/20/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +@interface TDSlashState () +@property (nonatomic, retain) TDSlashSlashState *slashSlashState; +@property (nonatomic, retain) TDSlashStarState *slashStarState; +@end + +@implementation TDSlashState + +- (id)init { + if (self = [super init]) { + self.slashSlashState = [[[TDSlashSlashState alloc] init] autorelease]; + self.slashStarState = [[[TDSlashStarState alloc] init] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.slashSlashState = nil; + self.slashStarState = nil; + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + NSInteger c = [r read]; + if ('/' == c) { + return [slashSlashState nextTokenFromReader:r startingWith:c tokenizer:t]; + } else if ('*' == c) { + return [slashStarState nextTokenFromReader:r startingWith:c tokenizer:t]; + } else { + if (-1 != c) { + [r unread]; + } + return [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"/" floatValue:0.0]; + } +} + +@synthesize slashSlashState; +@synthesize slashStarState; +@synthesize reportsCommentTokens; +@end diff --git a/test/.svn/text-base/TDSlashStateTest.h.svn-base b/test/.svn/text-base/TDSlashStateTest.h.svn-base new file mode 100644 index 0000000..1184eab --- /dev/null +++ b/test/.svn/text-base/TDSlashStateTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKSlashStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDSlashStateTest : SenTestCase { + TDSlashState *slashState; + PKReader *r; + PKTokenizer *t; + NSString *s; +} +@end diff --git a/test/.svn/text-base/TDSlashStateTest.m.svn-base b/test/.svn/text-base/TDSlashStateTest.m.svn-base new file mode 100644 index 0000000..d707f2e --- /dev/null +++ b/test/.svn/text-base/TDSlashStateTest.m.svn-base @@ -0,0 +1,390 @@ +// +// PKSlashStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDSlashStateTest.h" + +@implementation TDSlashStateTest + +- (void)setUp { + r = [[PKReader alloc] init]; + t = [[PKTokenizer alloc] init]; + slashState = t.slashState; +} + + +- (void)tearDown { + [r release]; + [t release]; +} + + +- (void)testSpace { + s = @" "; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlash { + s = @"/"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlash { + s = @"/"; + r.string = s; + t.string = s; + + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashSlash { + s = @"//"; + r.string = s; + t.string = s; + + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, s); + TDTrue(tok.isComment); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashSlashFoo { + s = @"// foo"; + r.string = s; + t.string = s; + + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, s); + TDTrue(tok.isComment); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashAbc { + s = @"/abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testReportSlashAbc { + s = @"/abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSlashSpaceAbc { + s = @"/ abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testReportSlashSpaceAbc { + s = @"/ abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testSlashSlashAbc { + s = @"//abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashSlashAbc { + s = @"//abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashSlashSpaceAbc { + s = @"// abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashSlashSpaceAbc { + s = @"// abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcStarSlash { + s = @"/*abc*/"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcStarSlash { + s = @"/*abc*/"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcStarStar { + s = @"/*abc**"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAStarStarSpaceA { + s = @"/*a**/ a"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/*a**/"); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testReportSlashStarAbcStarStarSpaceA { + s = @"/*abc**/ a"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/*abc**/"); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testReportSlashStarStarSlash { + s = @"/**/"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarStarStarSlash { + s = @"/***/"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarStarSlashSpace { + s = @"/**/ "; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/**/"); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testReportSlashStarAbcStarSpaceStarSpaceA { + s = @"/*abc* */ a"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/*abc* */"); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testSlashStarAbc { + s = @"/*abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbc { + s = @"/*abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcStar { + s = @"/*abc*"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcStarSpace { + s = @"/*abc* "; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcStarSpace { + s = @"/*abc* "; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcSlash { + s = @"/*abc/"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcSlashSpace { + s = @"/*abc/ "; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcSlashSpace { + s = @"/*abc/ "; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcNewline { + s = @"/*abc\n"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcNewline { + s = @"/*abc\n"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + +@end diff --git a/test/.svn/text-base/TDSpecificCharTest.h.svn-base b/test/.svn/text-base/TDSpecificCharTest.h.svn-base new file mode 100644 index 0000000..648d20c --- /dev/null +++ b/test/.svn/text-base/TDSpecificCharTest.h.svn-base @@ -0,0 +1,19 @@ +// +// PKSpecificCharTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + + +@interface TDSpecificCharTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + PKChar *p; + PKAssembly *result; +} + +@end diff --git a/test/.svn/text-base/TDSpecificCharTest.m.svn-base b/test/.svn/text-base/TDSpecificCharTest.m.svn-base new file mode 100644 index 0000000..5ffe718 --- /dev/null +++ b/test/.svn/text-base/TDSpecificCharTest.m.svn-base @@ -0,0 +1,59 @@ +// +// PKSpecificCharTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/15/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDSpecificCharTest.h" + +@interface PKAssembly () +- (BOOL)hasMore; +@end + +@implementation TDSpecificCharTest + +- (void)test123 { + s = @"123"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^123", [a description]); + p = [PKSpecificChar specificCharWithChar:'1']; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[1]1^23", [result description]); + TDTrue([a hasMore]); +} + + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKSpecificChar specificCharWithChar:'1']; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDNil(result); + TDTrue([a hasMore]); +} + + +- (void)testRepetition { + s = @"aaa"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^aaa", [a description]); + p = [PKSpecificChar specificCharWithChar:'a']; + PKParser *r = [PKRepetition repetitionWithSubparser:p]; + + result = [r bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a, a, a]aaa^", [result description]); + TDFalse([result hasMore]); +} + +@end diff --git a/test/.svn/text-base/TDSymbolStateTest.h.svn-base b/test/.svn/text-base/TDSymbolStateTest.h.svn-base new file mode 100644 index 0000000..c529b8f --- /dev/null +++ b/test/.svn/text-base/TDSymbolStateTest.h.svn-base @@ -0,0 +1,16 @@ +// +// PKSymbolStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/12/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDSymbolStateTest : SenTestCase { + PKSymbolState *symbolState; + PKReader *r; + NSString *s; +} +@end diff --git a/test/.svn/text-base/TDSymbolStateTest.m.svn-base b/test/.svn/text-base/TDSymbolStateTest.m.svn-base new file mode 100644 index 0000000..9202d6d --- /dev/null +++ b/test/.svn/text-base/TDSymbolStateTest.m.svn-base @@ -0,0 +1,572 @@ +// +// PKSymbolStateTestok.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/12/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDSymbolStateTest.h" + +@implementation TDSymbolStateTest + +- (void)setUp { + symbolState = [[PKSymbolState alloc] init]; +} + + +- (void)tearDown { + [symbolState release]; + [r release]; +} + + +- (void)testDot { + s = @"."; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testDotA { + s = @".a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testDotSpace { + s = @". "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testDotDot { + s = @".."; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)'.', [r read]); +} + + + +- (void)testAddDotDot { + s = @".."; + [symbolState add:s]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"..", tok.stringValue); + TDEqualObjects(@"..", tok.value); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testAddDotDotSpace { + s = @".. "; + [symbolState add:@".."]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"..", tok.stringValue); + TDEqualObjects(@"..", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testAddColonEqual { + s = @":="; + [symbolState add:s]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@":=", tok.stringValue); + TDEqualObjects(@":=", tok.value); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testAddColonEqualSpace { + s = @":= "; + [symbolState add:@":="]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@":=", tok.stringValue); + TDEqualObjects(@":=", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testAddGtEqualLtSpace { + s = @">=< "; + [symbolState add:@">=<"]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testAddGtEqualLt { + s = @">=<"; + [symbolState add:s]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTokenzierAddGtEqualLt { + s = @">=<"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:s]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtSpaceFoo { + s = @">=< foo"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@">=<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@"foo", tok.stringValue); + TDEqualObjects(@"foo", tok.value); + TDTrue(tok.isWord); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtFoo { + s = @">==<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@"foo", tok.stringValue); + TDEqualObjects(@"foo", tok.value); + TDTrue(tok.isWord); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtDot { + s = @">=<."; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@">=<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtSpaceDot { + s = @">=< ."; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@">=<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtSpaceDotSpace { + s = @">=< . "; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@">=<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddLtBangDashDashSpaceDotSpace { + s = @""; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"-->"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"-->", tok.stringValue); + TDEqualObjects(@"-->", tok.value); + + tok = [t nextToken]; + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDashGtSpaceDot { + s = @"--> ."; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"-->"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"-->", tok.stringValue); + TDEqualObjects(@"-->", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDashGtSpaceDotSpace { + s = @"--> . "; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"-->"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"-->", tok.stringValue); + TDEqualObjects(@"-->", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDash { + s = @"--"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"--"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"--", tok.stringValue); + TDEqualObjects(@"--", tok.value); + + tok = [t nextToken]; + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDashSpaceDot { + s = @"-- ."; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"--"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"--", tok.stringValue); + TDEqualObjects(@"--", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDashSpaceDotSpace { + s = @"-- . "; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"--"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"--", tok.stringValue); + TDEqualObjects(@"--", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualButNotEqual { + s = @"="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualButNotEqualEqual { + s = @"=="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualCompareEqualEqualEqualEqual { + s = @"===="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"===", tok.stringValue); + TDEqualObjects(@"===", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualCompareEqualEqualEqualEqualEqual { + s = @"====="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"===", tok.stringValue); + TDEqualObjects(@"===", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualCompareEqualEqualEqualEqualEqualSpaceEqual { + s = @"===== ="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"===", tok.stringValue); + TDEqualObjects(@"===", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualEqual { + s = @"===="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualColonEqualButNotEqualColon { + s = @"=:"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"=:="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@":", tok.stringValue); + TDEqualObjects(@":", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierRemoveEqualEqual { + s = @"=="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState remove:@"=="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierRemoveEqualEqualAddEqualEqual { + s = @"===="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState remove:@"=="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + [t.symbolState add:@"=="]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualColonEqualAndThenEqualColonEqualColon { + s = @"=:=:"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"=:="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=:=", tok.stringValue); + TDEqualObjects(@"=:=", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@":", tok.stringValue); + TDEqualObjects(@":", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTrickyCase { + s = @"+++\n+++-\n+++-+"; + + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"+++"]; + [t.symbolState add:@"+++-+"]; + + PKToken *eof = [PKToken EOFToken]; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+++"); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+++"); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+++-+"); + + tok = [t nextToken]; + TDEquals(eof, tok); +} + +@end diff --git a/test/.svn/text-base/TDSymbolTest.h.svn-base b/test/.svn/text-base/TDSymbolTest.h.svn-base new file mode 100644 index 0000000..a7c277b --- /dev/null +++ b/test/.svn/text-base/TDSymbolTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKSymbolTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDSymbolTest : SenTestCase { + PKParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDSymbolTest.m.svn-base b/test/.svn/text-base/TDSymbolTest.m.svn-base new file mode 100644 index 0000000..2f2e258 --- /dev/null +++ b/test/.svn/text-base/TDSymbolTest.m.svn-base @@ -0,0 +1,66 @@ +// +// PKSymbolTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDSymbolTest.h" + + +@implementation TDSymbolTest + +- (void)tearDown { +} + + +- (void)testDash { + s = @"-"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSymbol symbolWithString:s]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[-]-^", [result description]); +} + + +- (void)testFalseDash { + s = @"-"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSymbol symbolWithString:@"+"]; + + PKAssembly *result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testTrueDash { + s = @"-"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSymbol symbol]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[-]-^", [result description]); +} + + +- (void)testDiscardDash { + s = @"-"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [[PKSymbol symbolWithString:s] discard]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[]-^", [result description]); +} +@end diff --git a/test/.svn/text-base/TDSyntaxHighlighter.h.svn-base b/test/.svn/text-base/TDSyntaxHighlighter.h.svn-base new file mode 100644 index 0000000..05eda08 --- /dev/null +++ b/test/.svn/text-base/TDSyntaxHighlighter.h.svn-base @@ -0,0 +1,29 @@ +// +// PKSyntaxHighlighter.h +// HTTPClient +// +// Created by Todd Ditchendorf on 12/26/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class PKParser; +@class PKTokenizer; +@class PKParserFactory; +@class TDMiniCSSAssembler; +@class TDGenericAssembler; + +@interface TDSyntaxHighlighter : NSObject { + PKParserFactory *parserFactory; + PKParser *miniCSSParser; + TDMiniCSSAssembler *miniCSSAssembler; + TDGenericAssembler *genericAssembler; + BOOL cacheParsers; + NSMutableDictionary *parserCache; + NSMutableDictionary *tokenizerCache; +} +- (NSAttributedString *)highlightedStringForString:(NSString *)s ofGrammar:(NSString *)grammarName; + +@property (nonatomic) BOOL cacheParsers; // default is NO +@end diff --git a/test/.svn/text-base/TDSyntaxHighlighter.m.svn-base b/test/.svn/text-base/TDSyntaxHighlighter.m.svn-base new file mode 100644 index 0000000..4557ec8 --- /dev/null +++ b/test/.svn/text-base/TDSyntaxHighlighter.m.svn-base @@ -0,0 +1,168 @@ +// +// PKSyntaxHighlighter.m +// HTTPClient +// +// Created by Todd Ditchendorf on 12/26/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDSyntaxHighlighter.h" +#import +#import "PKParserFactory.h" +#import "TDMiniCSSAssembler.h" +#import "TDGenericAssembler.h" + +@interface TDSyntaxHighlighter () +- (NSMutableDictionary *)attributesForGrammarNamed:(NSString *)grammarName; +- (PKParser *)parserForGrammarNamed:(NSString *)grammarName; + +// all of the ivars for these properties are lazy loaded in the getters. +// thats so that if an application has syntax highlighting turned off, this class will +// consume much less memory/fewer resources. +@property (nonatomic, retain) PKParserFactory *parserFactory; +@property (nonatomic, retain) PKParser *miniCSSParser; +@property (nonatomic, retain) TDMiniCSSAssembler *miniCSSAssembler; +@property (nonatomic, retain) TDGenericAssembler *genericAssembler; +@property (nonatomic, retain) NSMutableDictionary *parserCache; +@property (nonatomic, retain) NSMutableDictionary *tokenizerCache; +@end + +@implementation TDSyntaxHighlighter + +- (id)init { + if (self = [super init]) { + + } + return self; +} + + +- (void)dealloc { + PKReleaseSubparserTree(miniCSSParser); + for (PKParser *p in parserCache) { + PKReleaseSubparserTree(p); + } + + self.parserFactory = nil; + self.miniCSSParser = nil; + self.miniCSSAssembler = nil; + self.genericAssembler = nil; + self.parserCache = nil; + self.tokenizerCache = nil; + [super dealloc]; +} + + +- (PKParserFactory *)parserFactory { + if (!parserFactory) { + self.parserFactory = [PKParserFactory factory]; + } + return parserFactory; +} + + +- (TDMiniCSSAssembler *)miniCSSAssembler { + if (!miniCSSAssembler) { + self.miniCSSAssembler = [[[TDMiniCSSAssembler alloc] init] autorelease]; + } + return miniCSSAssembler; +} + + +- (PKParser *)miniCSSParser { + if (!miniCSSParser) { + // create mini-css parser + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + NSString *grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + self.miniCSSParser = [self.parserFactory parserFromGrammar:grammarString assembler:self.miniCSSAssembler]; + } + return miniCSSParser; +} + + +- (TDGenericAssembler *)genericAssembler { + if (!genericAssembler) { + self.genericAssembler = [[[TDGenericAssembler alloc] init] autorelease]; + } + return genericAssembler; +} + + +- (NSMutableDictionary *)parserCache { + if (!parserCache) { + self.parserCache = [NSMutableDictionary dictionary]; + } + return parserCache; +} + + +- (NSMutableDictionary *)attributesForGrammarNamed:(NSString *)grammarName { + // parse CSS + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:grammarName ofType:@"css"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + [self.miniCSSParser bestMatchFor:a]; // produce dict of attributes from the CSS + return self.miniCSSAssembler.attributes; +} + + +- (PKParser *)parserForGrammarNamed:(NSString *)grammarName { + // create parser or the grammar requested or fetch parser from cache + PKParser *parser = nil; + if (cacheParsers) { + parser = [self.parserCache objectForKey:grammarName]; + } + + if (!parser) { + // get attributes from css && give to the generic assembler + parserFactory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnAll; + self.genericAssembler.attributes = [self attributesForGrammarNamed:grammarName]; + + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:grammarName ofType:@"grammar"]; + NSString *grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + // generate a parser for the requested grammar + parserFactory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnTerminals; + parser = [self.parserFactory parserFromGrammar:grammarString assembler:self.genericAssembler]; + + if (cacheParsers) { + [self.parserCache setObject:parser forKey:grammarName]; + [self.tokenizerCache setObject:parser.tokenizer forKey:grammarName]; + } + } + + return parser; +} + + +- (NSAttributedString *)highlightedStringForString:(NSString *)s ofGrammar:(NSString *)grammarName { + // create or fetch the parser & tokenizer for this grammar + PKParser *parser = [self parserForGrammarNamed:grammarName]; + + // parse the string. take care to preseve the whitespace and comments in the string + parser.tokenizer.string = s; + parser.tokenizer.whitespaceState.reportsWhitespaceTokens = YES; + parser.tokenizer.commentState.reportsCommentTokens = YES; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:parser.tokenizer]; + a.preservesWhitespaceTokens = YES; + + PKAssembly *resultAssembly = [parser completeMatchFor:a]; // finally, parse the input. stores attributed string in resultAssembly.target + + if (!cacheParsers) { + PKReleaseSubparserTree(parser); + } + + id result = [[resultAssembly.target copy] autorelease]; + return result; +} + +@synthesize parserFactory; +@synthesize miniCSSParser; +@synthesize miniCSSAssembler; +@synthesize genericAssembler; +@synthesize cacheParsers; +@synthesize parserCache; +@synthesize tokenizerCache; +@end diff --git a/test/.svn/text-base/TDTestScaffold.h.svn-base b/test/.svn/text-base/TDTestScaffold.h.svn-base new file mode 100644 index 0000000..d107ccf --- /dev/null +++ b/test/.svn/text-base/TDTestScaffold.h.svn-base @@ -0,0 +1,18 @@ +// +// PKTestScaffold.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import +#import + +#define TDTrue(e) STAssertTrue((e), @"") +#define TDFalse(e) STAssertFalse((e), @"") +#define TDNil(e) STAssertNil((e), @"") +#define TDNotNil(e) STAssertNotNil((e), @"") +#define TDEquals(e1, e2) STAssertEquals((e1), (e2), @"") +#define TDEqualObjects(e1, e2) STAssertEqualObjects((e1), (e2), @"") diff --git a/test/.svn/text-base/TDTestScaffold.m.svn-base b/test/.svn/text-base/TDTestScaffold.m.svn-base new file mode 100644 index 0000000..f6c701d --- /dev/null +++ b/test/.svn/text-base/TDTestScaffold.m.svn-base @@ -0,0 +1,153 @@ +// +// PKTestScaffold.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +#define RUN_ALL_TEST_CASES 1 +#define SOLO_TEST_CASE @"TDParserBlocksTest" + +@interface SenTestSuite (TDAdditions) +- (void)addSuitesForClassNames:(NSArray *)classNames; +@end + +SenTestSuite *TDSoloTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Solo Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObject:SOLO_TEST_CASE]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +SenTestSuite *TDTokensTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Tokens Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDReaderTest", + @"TDTokenizerTest", + @"TDTokenizerTest", + @"TDNumberStateTest", + @"TDQuoteStateTest", + @"TDWhitespaceStateTest", + @"TDWordStateTest", + @"TDSlashStateTest", + @"TDSymbolStateTest", + @"TDCommentStateTest", + @"TDDelimitStateTest", + @"TDTokenizerStateTest", +#ifdef TARGET_OS_SNOW_LEOPARD + @"TDTokenizerBlocksTest", + @"TDParserBlocksTest", +#endif + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +SenTestSuite *TDCharsTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Chars Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDCharacterAssemblyTest", + @"TDDigitTest", + @"TDCharTest", + @"TDLetterTest", + @"TDSpecificCharTest", + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +SenTestSuite *TDParseTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Parse Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDParserTest", + @"TDTokenAssemblyTest", + @"TDLiteralTest", + @"TDPatternTest", + @"TDRepetitionTest", + @"TDSequenceTest", + @"TDAlternationTest", + @"TDSymbolTest", + @"TDRobotCommandTest", + @"TDXmlParserTest", + @"TDJsonParserTest", + @"TDFastJsonParserTest", + @"TDRegularParserTest", + @"SRGSParserTest", + @"EBNFParserTest", + @"TDPlistParserTest", + @"TDXmlNameTest", + @"XPathParserTest", + @"XMLReaderTest", + @"TDXmlTokenizerTest", + @"TDArithmeticParserTest", + @"TDScientificNumberStateTest", + @"TDTokenArraySourceTest", + @"TDDifferenceTest", + @"TDNegationTest", + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +SenTestSuite *TDParserFactoryTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"ParserFactory Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDParserFactoryTest", + @"TDParserFactoryTest2", + @"TDParserFactoryPatternTest", + @"TDMiniCSSAssemblerTest", + @"TDPredicateEvaluatorTest", + @"TDNSPredicateEvaluatorTest", + @"TDNSPredicateBuilderTest", + @"TDJavaScriptParserTest", + @"TDXMLParserTest", + @"XPathParserGrammarTest", + @"ERBTest", + @"TDParseTreeTest", + @"SAXTest", + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +@implementation SenTestSuite (TDAdditions) + ++ (id)testSuiteForBundlePath:(NSString *)path { + SenTestSuite *suite = nil; + +#if RUN_ALL_TEST_CASES + suite = [self defaultTestSuite]; +#else + suite = [self testSuiteWithName:@"My Tests"]; + // [suite addTest:TDCharsTestSuite()]; + // [suite addTest:TDTokensTestSuite()]; + // [suite addTest:TDParseTestSuite()]; + // [suite addTest:TDParserFactoryTestSuite()]; + [suite addTest:TDSoloTestSuite()]; +#endif + + return suite; +} + + +- (void)addSuitesForClassNames:(NSArray *)classNames { + for (NSString *className in classNames) { + SenTestSuite *suite = [SenTestSuite testSuiteForTestCaseWithName:className]; + [self addTest:suite]; + } +} + +@end \ No newline at end of file diff --git a/test/.svn/text-base/TDToken+Blob.h.svn-base b/test/.svn/text-base/TDToken+Blob.h.svn-base new file mode 100644 index 0000000..5e2a09a --- /dev/null +++ b/test/.svn/text-base/TDToken+Blob.h.svn-base @@ -0,0 +1,16 @@ +// +// PKToken+Blob.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +extern const NSInteger PKTokenTypeBlob; + +@interface PKToken (Blob) +- (BOOL)isBlob; +@end + diff --git a/test/.svn/text-base/TDToken+Blob.m.svn-base b/test/.svn/text-base/TDToken+Blob.m.svn-base new file mode 100644 index 0000000..dea88e7 --- /dev/null +++ b/test/.svn/text-base/TDToken+Blob.m.svn-base @@ -0,0 +1,20 @@ +// +// PKToken+Blob.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKToken+Blob.h" + +const NSInteger PKTokenTypeBlob = 200; + +@implementation PKToken (Blob) + +- (BOOL)isBlob { + return PKTokenTypeBlob == self.tokenType; +} + +@end + diff --git a/test/.svn/text-base/TDTokenArraySourceTest.h.svn-base b/test/.svn/text-base/TDTokenArraySourceTest.h.svn-base new file mode 100644 index 0000000..c0bf6b7 --- /dev/null +++ b/test/.svn/text-base/TDTokenArraySourceTest.h.svn-base @@ -0,0 +1,18 @@ +// +// PKTokenArraySourceTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDTokenArraySourceTest : SenTestCase { + PKTokenizer *t; + NSString *d; + NSString *s; + PKTokenArraySource *tas; +} + +@end diff --git a/test/.svn/text-base/TDTokenArraySourceTest.m.svn-base b/test/.svn/text-base/TDTokenArraySourceTest.m.svn-base new file mode 100644 index 0000000..b299c33 --- /dev/null +++ b/test/.svn/text-base/TDTokenArraySourceTest.m.svn-base @@ -0,0 +1,51 @@ +// +// PKTokenArraySourceTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTokenArraySourceTest.h" + +@implementation TDTokenArraySourceTest + +- (void)setUp { +} + + +- (void)testFoo { + d = @";"; + s = @"I came; I saw; I left in peace.;"; + t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + tas = [[[PKTokenArraySource alloc] initWithTokenizer:t delimiter:d] autorelease]; + + TDTrue([tas hasMore]); + NSArray *a = [tas nextTokenArray]; + TDNotNil(a); + TDEquals((NSUInteger)2, [a count]); + TDEqualObjects(@"I", [[a objectAtIndex:0] stringValue]); + TDEqualObjects(@"came", [[a objectAtIndex:1] stringValue]); + + TDTrue([tas hasMore]); + a = [tas nextTokenArray]; + TDNotNil(a); + TDEquals((NSUInteger)2, [a count]); + TDEqualObjects(@"I", [[a objectAtIndex:0] stringValue]); + TDEqualObjects(@"saw", [[a objectAtIndex:1] stringValue]); + + TDTrue([tas hasMore]); + a = [tas nextTokenArray]; + TDNotNil(a); + TDEquals((NSUInteger)5, [a count]); + TDEqualObjects(@"I", [[a objectAtIndex:0] stringValue]); + TDEqualObjects(@"left", [[a objectAtIndex:1] stringValue]); + TDEqualObjects(@"in", [[a objectAtIndex:2] stringValue]); + TDEqualObjects(@"peace", [[a objectAtIndex:3] stringValue]); + TDEqualObjects(@".", [[a objectAtIndex:4] stringValue]); + + TDFalse([tas hasMore]); + a = [tas nextTokenArray]; + TDNil(a); +} +@end diff --git a/test/.svn/text-base/TDTokenAssemblyTest.h.svn-base b/test/.svn/text-base/TDTokenAssemblyTest.h.svn-base new file mode 100644 index 0000000..3b279a6 --- /dev/null +++ b/test/.svn/text-base/TDTokenAssemblyTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKTokenAssemblyTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDTokenAssemblyTest : SenTestCase { + PKAssembly *a; + NSString *s; + PKParser *p; +} + +@end diff --git a/test/.svn/text-base/TDTokenAssemblyTest.m.svn-base b/test/.svn/text-base/TDTokenAssemblyTest.m.svn-base new file mode 100644 index 0000000..c228447 --- /dev/null +++ b/test/.svn/text-base/TDTokenAssemblyTest.m.svn-base @@ -0,0 +1,292 @@ +// +// PKTokenAssemblyTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTokenAssemblyTest.h" + +@interface PKAssembly () +- (id)next; +- (BOOL)hasMore; +@property (nonatomic, readonly) NSUInteger length; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@property (nonatomic, readonly) NSUInteger objectsRemaining; +@end + +@implementation TDTokenAssemblyTest + +- (void)setUp { +} + + +- (void)tearDown { + [p release]; +} + + +#pragma mark - + +- (void)testWordOhSpaceHaiExclamation { + s = @"oh hai!"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)3, [a length]); + + TDEquals((NSUInteger)0, a.objectsConsumed); + TDEquals((NSUInteger)3, a.objectsRemaining); + TDEqualObjects(@"[]^oh/hai/!", [a description]); + TDTrue([a hasMore]); + TDEqualObjects(@"oh", [[a next] stringValue]); + + TDEquals((NSUInteger)1, a.objectsConsumed); + TDEquals((NSUInteger)2, a.objectsRemaining); + TDEqualObjects(@"[]oh^hai/!", [a description]); + TDTrue([a hasMore]); + TDEqualObjects(@"hai", [[a next] stringValue]); + + TDEquals((NSUInteger)2, a.objectsConsumed); + TDEquals((NSUInteger)1, a.objectsRemaining); + TDEqualObjects(@"[]oh/hai^!", [a description]); + TDTrue([a hasMore]); + TDEqualObjects(@"!", [[a next] stringValue]); + + TDEquals((NSUInteger)3, a.objectsConsumed); + TDEquals((NSUInteger)0, a.objectsRemaining); + TDEqualObjects(@"[]oh/hai/!^", [a description]); + TDFalse([a hasMore]); + TDNil([[a next] stringValue]); + + TDEquals((NSUInteger)3, a.objectsConsumed); + TDEquals((NSUInteger)0, a.objectsRemaining); + TDEqualObjects(@"[]oh/hai/!^", [a description]); + TDFalse([a hasMore]); + TDNil([[a next] stringValue]); + + TDEquals((NSUInteger)3, [a length]); +} + + +- (void)testBestMatchForWordFoobar { + s = @"foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^foobar", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[foobar]foobar^", [result description]); + TDFalse(result == a); + + + result = [p bestMatchFor:result]; + TDNil(result); +} + + +- (void)testCompleteMatchForWordFoobar { + s = @"foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^foobar", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDEqualObjects(@"[foobar]foobar^", [result description]); + TDFalse(result == a); +} + + +- (void)testBestMatchForWordFooSpaceBar { + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^foo/bar", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^bar", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForWordFooSpaceBar { + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^foo/bar", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testBestMatchForNumFoobar { + s = @"foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^foobar", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testCompleteMatchForNumFoobar { + s = @"foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^foobar", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testBestMatchForWord123 { + s = @"123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^123", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testCompleteMatchForWord123 { + s = @"123"; + a = [PKTokenAssembly assemblyWithString:s]; + + + p = [[PKWord alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^123", [a description]); +} + + +- (void)testBestMatchForNum123 { + s = @"123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^123", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[123]123^", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForNum123 { + s = @"123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^123", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[123]123^", [result description]); + TDFalse(result == a); +} + + +- (void)testBestMatchForNum123Space456 { + s = @"123 456"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^123/456", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[123]123^456", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForNum123Space456 { + s = @"123 456"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^123/456", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testBestMatchForWordFoobarSpace123 { + s = @"foobar 123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^foobar/123", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[foobar]foobar^123", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForWordFoobarSpace123 { + s = @"foobar 123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^foobar/123", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testBestMatchForNum123Space456Foobar { + s = @"123 456 foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)3, [a length]); + TDEqualObjects(@"[]^123/456/foobar", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[123]123^456/foobar", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForNum123Space456Foobar { + s = @"123 456 foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)3, [a length]); + TDEqualObjects(@"[]^123/456/foobar", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + +@end + diff --git a/test/.svn/text-base/TDTokenTest.h.svn-base b/test/.svn/text-base/TDTokenTest.h.svn-base new file mode 100644 index 0000000..16e42af --- /dev/null +++ b/test/.svn/text-base/TDTokenTest.h.svn-base @@ -0,0 +1,15 @@ +// +// PKTokenTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/8/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDTokenTest : SenTestCase { + PKToken *eof; +} + +@end diff --git a/test/.svn/text-base/TDTokenTest.m.svn-base b/test/.svn/text-base/TDTokenTest.m.svn-base new file mode 100644 index 0000000..d3c7215 --- /dev/null +++ b/test/.svn/text-base/TDTokenTest.m.svn-base @@ -0,0 +1,88 @@ +// +// PKTokenTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/8/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTokenTest.h" + +@implementation TDTokenTest + +- (void)setUp { + eof = [PKToken EOFToken]; +} + + +- (void)testEOFTokenReleaseOnce1 { + TDNotNil(eof); + [eof release]; +} + + +- (void)testEOFTokenReleaseOnce2 { + TDNotNil(eof); + [eof release]; +} + + +- (void)testEOFTokenReleaseTwice1 { + TDNotNil(eof); + [eof release]; + TDNotNil(eof); + [eof release]; +} + + +- (void)testEOFTokenReleaseTwice2 { + TDNotNil(eof); + [eof release]; + TDNotNil(eof); + [eof release]; +} + + +- (void)testEOFTokenAutoreleaseOnce1 { + TDNotNil(eof); + [eof autorelease]; +} + + +- (void)testEOFTokenAutoreleaseOnce2 { + TDNotNil(eof); + [eof autorelease]; +} + + +- (void)testEOFTokenAutoreleaseTwice1 { + TDNotNil(eof); + [eof autorelease]; + TDNotNil(eof); + [eof autorelease]; +} + + +- (void)testEOFTokenAutoreleaseTwice2 { + TDNotNil(eof); + [eof autorelease]; + TDNotNil(eof); + [eof autorelease]; +} + + +- (void)testEOFTokenRetainCount { + TDTrue([eof retainCount] >= 17035104); + // NO IDEA WHY THIS WONT PASS + //TDEquals(UINT_MAX, [eof retainCount]); /*17035104 4294967295*/ +// TDEqualObjects([NSNumber numberWithUnsignedInt:4294967295], [NSNumber numberWithUnsignedInt:[eof retainCount]]); +} + + +- (void)testCopyIdentity { + id copy = [eof copy]; + TDTrue(copy == eof); + [copy release]; // appease clang sa +} + +@end diff --git a/test/.svn/text-base/TDTokenizer+BlobState.h.svn-base b/test/.svn/text-base/TDTokenizer+BlobState.h.svn-base new file mode 100644 index 0000000..fa2d019 --- /dev/null +++ b/test/.svn/text-base/TDTokenizer+BlobState.h.svn-base @@ -0,0 +1,15 @@ +// +// PKTokenizer+BlobState.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class TDBlobState; + +@interface PKTokenizer (BlobState) +- (TDBlobState *)blobState; +@end diff --git a/test/.svn/text-base/TDTokenizer+BlobState.m.svn-base b/test/.svn/text-base/TDTokenizer+BlobState.m.svn-base new file mode 100644 index 0000000..f880358 --- /dev/null +++ b/test/.svn/text-base/TDTokenizer+BlobState.m.svn-base @@ -0,0 +1,36 @@ +// +// PKTokenizer+BlobState.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKTokenizer+BlobState.h" +#import "TDBlobState.h" + +static NSMutableDictionary *sBlobCache = nil; + +@implementation PKTokenizer (BlobState) + +- (TDBlobState *)blobState { + TDBlobState *bs = nil; + + @synchronized (self) { + if (!sBlobCache) { + sBlobCache = [[NSMutableDictionary alloc] init]; + } + + NSString *key = [NSString stringWithFormat:@"%p", self]; + bs = [sBlobCache objectForKey:key]; + + if (!bs) { + bs = [[[TDBlobState alloc] init] autorelease]; + [sBlobCache setObject:bs forKey:key]; + } + } + + return bs; +} + +@end diff --git a/test/.svn/text-base/TDTokenizerBlocksTest.h.svn-base b/test/.svn/text-base/TDTokenizerBlocksTest.h.svn-base new file mode 100644 index 0000000..6c16a46 --- /dev/null +++ b/test/.svn/text-base/TDTokenizerBlocksTest.h.svn-base @@ -0,0 +1,18 @@ +// +// TDTokenizerBlocksTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 9/16/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@class PKTokenizer; + +@interface TDTokenizerBlocksTest : SenTestCase { + PKTokenizer *t; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDTokenizerBlocksTest.m.svn-base b/test/.svn/text-base/TDTokenizerBlocksTest.m.svn-base new file mode 100644 index 0000000..32e8529 --- /dev/null +++ b/test/.svn/text-base/TDTokenizerBlocksTest.m.svn-base @@ -0,0 +1,38 @@ +// +// TDTokenizerBlocksTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 9/16/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTokenizerBlocksTest.h" + +@implementation TDTokenizerBlocksTest + +- (void)setUp { +} + + +- (void)tearDown { +} + + +#ifdef TARGET_OS_SNOW_LEOPARD +- (void)testBlastOff { + s = @"\"It's 123 blast-off!\", she said, // watch out!\n" + @"and <= 3 'ticks' later /* wince */, it's blast-off!"; + t = [PKTokenizer tokenizerWithString:s]; + + NSLog(@"\n\n starting!!! \n\n"); + + [t enumerateTokensUsingBlock:^(PKToken *tok, BOOL *stop) { + NSLog(@"(%@)", tok.stringValue); + }]; + + + NSLog(@"\n\n done!!! \n\n"); +} +#endif + +@end diff --git a/test/.svn/text-base/TDTokenizerStateTest.h.svn-base b/test/.svn/text-base/TDTokenizerStateTest.h.svn-base new file mode 100644 index 0000000..cee1004 --- /dev/null +++ b/test/.svn/text-base/TDTokenizerStateTest.h.svn-base @@ -0,0 +1,17 @@ +// +// TDTokenizerStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/12/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDTokenizerStateTest : SenTestCase { + PKTokenizer *t; + NSString *s; + PKToken *tok; +} + +@end diff --git a/test/.svn/text-base/TDTokenizerStateTest.m.svn-base b/test/.svn/text-base/TDTokenizerStateTest.m.svn-base new file mode 100644 index 0000000..9616dea --- /dev/null +++ b/test/.svn/text-base/TDTokenizerStateTest.m.svn-base @@ -0,0 +1,172 @@ +// +// TDTokenizerStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/12/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTokenizerStateTest.h" + +@implementation TDTokenizerStateTest + +- (void)setUp { + t = [[PKTokenizer alloc] init]; +} + + +- (void)tearDown { + [t release]; +} + + +- (void)testFallbackStateCast { + [t setTokenizerState:t.symbolState from:'c' to:'c']; + [t.symbolState setFallbackState:t.wordState from:'c' to:'c']; + [t.symbolState add:@"cast"]; + + t.string = @"foo cast cat"; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"cast", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"c", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"at", tok.stringValue); + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testFallbackStateCastAs { + [t setTokenizerState:t.symbolState from:'c' to:'c']; + [t.symbolState setFallbackState:t.wordState from:'c' to:'c']; + [t.symbolState add:@"cast as"]; + + t.string = @"foo cast as cat"; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"cast as", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"c", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"at", tok.stringValue); + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testTrickyFwdSlash { + [t.delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:nil]; + + [t setTokenizerState:t.commentState from:'#' to:'#']; + [t setTokenizerState:t.commentState from:'/' to:'/']; + + [t.commentState addSingleLineStartMarker:@"##"]; + [t.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + t.commentState.fallbackState = t.symbolState; + [t.commentState setFallbackState:t.delimitState from:'/' to:'/']; + + t.string = @"foo /bar/ /*## */ # baz ## ja"; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(@"/bar/", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"#", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"baz", tok.stringValue); + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testTrickyFwdSlash2 { + [t.delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:nil]; + + [t setTokenizerState:t.commentState from:'#' to:'#']; + [t setTokenizerState:t.commentState from:'/' to:'/']; + + [t.commentState addSingleLineStartMarker:@"##"]; + [t.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + t.commentState.fallbackState = t.symbolState; + [t.commentState setFallbackState:t.delimitState from:'/' to:'/']; + + t.string = @"## ja"; + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testTrickyFwdSlash3 { + [t.delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:nil]; + + [t setTokenizerState:t.commentState from:'#' to:'#']; + [t setTokenizerState:t.commentState from:'/' to:'/']; + + [t.commentState addSingleLineStartMarker:@"##"]; + [t.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + t.commentState.fallbackState = t.delimitState; + [t.commentState setFallbackState:t.symbolState from:'#' to:'#']; + + t.string = @"foo /bar/ /*## */ # baz ## ja"; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(@"/bar/", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"#", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"baz", tok.stringValue); + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + +@end diff --git a/test/.svn/text-base/TDTokenizerTest.h.svn-base b/test/.svn/text-base/TDTokenizerTest.h.svn-base new file mode 100644 index 0000000..e6bc1ba --- /dev/null +++ b/test/.svn/text-base/TDTokenizerTest.h.svn-base @@ -0,0 +1,18 @@ +// +// PKTokenizerTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@class PKTokenizer; + +@interface TDTokenizerTest : SenTestCase { + PKTokenizer *t; + NSString *s; +} + +@end diff --git a/test/.svn/text-base/TDTokenizerTest.m.svn-base b/test/.svn/text-base/TDTokenizerTest.m.svn-base new file mode 100644 index 0000000..ed1d1cb --- /dev/null +++ b/test/.svn/text-base/TDTokenizerTest.m.svn-base @@ -0,0 +1,621 @@ +// +// PKTokenizerTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 7/11/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTokenizerTest.h" +#import "ParseKit.h" + +@implementation TDTokenizerTest + +- (void)setUp { +} + + +- (void)tearDown { +} + + +- (void)testBlastOff { + s = @"\"It's 123 blast-off!\", she said, // watch out!\n" + @"and <= 3 'ticks' later /* wince */, it's blast-off!"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + //NSLog(@"\n\n starting!!! \n\n"); + while ((tok = [t nextToken]) != eof) { + //NSLog(@"(%@)", tok.stringValue); + } + //NSLog(@"\n\n done!!! \n\n"); + +} + +- (void)testStuff { + s = @"2 != 47. Blast-off!! 'Woo-hoo!'"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + while ((tok = [t nextToken]) != eof) { + //NSLog(@"(%@) (%.1f) : %@", tok.stringValue, tok.floatValue, [tok debugDescription]); + } +} + + +- (void)testStuff2 { + s = @"2 != 47. Blast-off!! 'Woo-hoo!'"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"2"); + TDEqualObjects(tok.value, [NSNumber numberWithFloat:2.0]); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"!="); + TDEqualObjects(tok.value, @"!="); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"47"); + TDEqualObjects(tok.value, [NSNumber numberWithFloat:47.0]); + TDEquals(tok.offset, (NSUInteger)5); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEqualObjects(tok.value, @"."); + TDEquals(tok.offset, (NSUInteger)7); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"Blast-off"); + TDEqualObjects(tok.value, @"Blast-off"); + TDEquals(tok.offset, (NSUInteger)9); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"!"); + TDEqualObjects(tok.value, @"!"); + TDEquals(tok.offset, (NSUInteger)18); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"!"); + TDEqualObjects(tok.value, @"!"); + TDEquals(tok.offset, (NSUInteger)19); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isQuotedString); + TDEqualObjects(tok.stringValue, @"'Woo-hoo!'"); + TDEqualObjects(tok.value, @"'Woo-hoo!'"); + TDEquals(tok.offset, (NSUInteger)21); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok == eof); + TDEquals(tok.offset, (NSUInteger)PKEOF); +} + + +- (void)testFortySevenDot { + s = @"47."; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"47"); + TDEqualObjects(tok.value, [NSNumber numberWithFloat:47.0]); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEqualObjects(tok.value, @"."); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok == eof); + TDEquals(tok.offset, (NSUInteger)PKEOF); +} + + +- (void)testFortySevenDotSpaceFoo { + s = @"47. foo"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"47"); + TDEqualObjects(tok.value, [NSNumber numberWithFloat:47.0]); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEqualObjects(tok.value, @"."); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEqualObjects(tok.value, @"foo"); + TDEquals(tok.offset, (NSUInteger)4); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok == eof); + TDEquals(tok.offset, (NSUInteger)PKEOF); +} + + +- (void)testDotOne { + s = @" .999"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + STAssertEqualsWithAccuracy((CGFloat)0.999, tok.floatValue, 0.01, @""); + TDTrue(tok.isNumber); + TDEquals(tok.offset, (NSUInteger)3); + +// if ([PKToken EOFToken] == token) break; + +} + + +- (void)testSpaceDotSpace { + s = @" . "; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)1); + + // if ([PKToken EOFToken] == token) break; + +} + + +- (void)testInitSig { + s = @"- (id)init {"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@"-", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(@"(", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)2); +} + + +- (void)testInitSig2 { + s = @"-(id)init {"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@"-", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(@"(", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)1); +} + + +- (void)testMinusSpaceTwo { + s = @"- 2"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@"-", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(@"2", tok.stringValue); + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEquals(tok.offset, (NSUInteger)2); +} + + +- (void)testMinusPlusTwo { + s = @"+2"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@"+", tok.stringValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2", tok.stringValue); + TDEquals(tok.offset, (NSUInteger)1); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testMinusPlusTwoCustom { + s = @"+2"; + t = [PKTokenizer tokenizerWithString:s]; + [t setTokenizerState:t.numberState from:'+' to:'+']; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+2", tok.stringValue); + TDEquals(tok.offset, (NSUInteger)0); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testSimpleAPIUsage { + s = @". , () 12.33333 .:= .456\n\n>=< 'boooo'fasa this should /* not*/ appear \r /*but */this should >==<"]; + + NSMutableArray *toks = [NSMutableArray array]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *token = nil; + while (token = [t nextToken]) { + if (eof == token) break; + + [toks addObject:token]; + + } + + //NSLog(@"\n\n\n\ntoks: %@\n\n\n\n", toks); +} + + +- (void)testKatakana1 { + s = @"ア"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = [t nextToken]; + + TDNotNil(tok); + TDTrue(tok.isWord); + TDEqualObjects(s, tok.stringValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(eof, tok); +} + + +- (void)testKatakana2 { + s = @"アア"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = [t nextToken]; + + TDNotNil(tok); + TDTrue(tok.isWord); + TDEqualObjects(s, tok.stringValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(eof, tok); +} + + +- (void)testKatakana3 { + s = @"アェ"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = [t nextToken]; + + TDNotNil(tok); + TDTrue(tok.isWord); + TDEqualObjects(s, tok.stringValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(eof, tok); +} + + +- (void)testParenStuff { + s = @"-(ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)4); + + tok = [t nextToken]; + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"5"); + TDEquals((CGFloat)5.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)5); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @")"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)6); +} + + +- (void)testParenStuff2 { + s = @"- (ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)3); +} + + +- (void)testParenStuff3 { + s = @"+(ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)4); + + tok = [t nextToken]; + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"5"); + TDEquals((CGFloat)5.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)5); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @")"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)6); +} + + +- (void)testParenStuff4 { + s = @"+ (ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)3); +} + + +- (void)testParenStuff5 { + s = @".(ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)4); + + tok = [t nextToken]; + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"5"); + TDEquals((CGFloat)5.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)5); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @")"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)6); +} + + +- (void)testParenStuff6 { + s = @". (ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)3); +} + + +- (void)testParenStuff7 { + s = @"-(ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + + NSMutableString *final = [NSMutableString string]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + while ((tok = [t nextToken]) != eof) { + [final appendString:[tok stringValue]]; + } + + TDNotNil(tok); + TDEqualObjects(final, s); + TDEqualObjects(eof, [t nextToken]); +} + +@end diff --git a/test/.svn/text-base/TDTrackTest.h.svn-base b/test/.svn/text-base/TDTrackTest.h.svn-base new file mode 100644 index 0000000..a27d572 --- /dev/null +++ b/test/.svn/text-base/TDTrackTest.h.svn-base @@ -0,0 +1,15 @@ +// +// PKTrackTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDTrackTest : SenTestCase { + +} + +@end diff --git a/test/.svn/text-base/TDTrackTest.m.svn-base b/test/.svn/text-base/TDTrackTest.m.svn-base new file mode 100644 index 0000000..66dfeed --- /dev/null +++ b/test/.svn/text-base/TDTrackTest.m.svn-base @@ -0,0 +1,112 @@ +// +// PKTrackTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTrackTest.h" +#import "ParseKit.h" + + +@implementation TDTrackTest + +// list = '(' contents ')' +// contents = empty | actualList +// actualList = Word (',' Word)* + + +- (PKParser *)listParser { + PKTrack *commaWord = [PKTrack track]; + [commaWord add:[[PKSymbol symbolWithString:@","] discard]]; + [commaWord add:[PKWord word]]; + + PKSequence *actualList = [PKSequence sequence]; + [actualList add:[PKWord word]]; + [actualList add:[PKRepetition repetitionWithSubparser:commaWord]]; + + PKAlternation *contents = [PKAlternation alternation]; + [contents add:[PKEmpty empty]]; + [contents add:actualList]; + + PKTrack *list = [PKTrack track]; + [list add:[[PKSymbol symbolWithString:@"("] discard]]; + [list add:contents]; + [list add:[[PKSymbol symbolWithString:@")"] discard]]; + + return list; +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testTrack { + + PKParser *list = [self listParser]; + + NSArray *test = [NSArray arrayWithObjects: + @"()", + @"(pilfer)", + @"(pilfer, pinch)", + @"(pilfer, pinch, purloin)", + @"(pilfer, pinch,, purloin)", + @"(", + @"(pilfer", + @"(pilfer, ", + @"(, pinch, purloin)", + @"pilfer, pinch", + nil]; + + for (NSString *s in test) { + //NSLog(@"\n----testing: %@", s); + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + @try { + PKAssembly *result = [list completeMatchFor:a]; + if (!result) { + //NSLog(@"[list completeMatchFor:] returns nil"); + } else { + //NSString *stack = [[[list completeMatchFor:a] stack] description]; + //NSLog(@"OK stack is: %@", stack); + } + } @catch (PKTrackException *e) { + //NSLog(@"\n\n%@\n\n", [e reason]); + } + } + +} + + +- (void)testMissingParen { + PKParser *open = [PKSymbol symbolWithString:@"("]; + PKParser *close = [PKSymbol symbolWithString:@")"]; + PKTrack *track = [PKTrack trackWithSubparsers:open, close, nil]; + + PKAssembly *a = [PKTokenAssembly assemblyWithString:@"("]; + STAssertThrowsSpecificNamed([track completeMatchFor:a], PKTrackException, PKTrackExceptionName, @""); + + @try { + [track completeMatchFor:a]; + STAssertTrue(0, @"Should not be reached"); + } @catch (PKTrackException *e) { + TDEqualObjects([e class], [PKTrackException class]); + TDEqualObjects([e name], PKTrackExceptionName); + + NSDictionary *userInfo = e.userInfo; + TDNotNil(userInfo); + + NSString *after = [userInfo objectForKey:@"after"]; + NSString *expected = [userInfo objectForKey:@"expected"]; + NSString *found = [userInfo objectForKey:@"found"]; + + TDNotNil(after); + TDNotNil(expected); + TDNotNil(found); + + TDEqualObjects(after, @"("); + TDEqualObjects(expected, @"Symbol )"); + TDEqualObjects(found, @"-nothing-"); + } +} +#endif + +@end diff --git a/test/.svn/text-base/TDUppercaseWordTest.h.svn-base b/test/.svn/text-base/TDUppercaseWordTest.h.svn-base new file mode 100644 index 0000000..46c6a3c --- /dev/null +++ b/test/.svn/text-base/TDUppercaseWordTest.h.svn-base @@ -0,0 +1,15 @@ +// +// PKUppercaseWordTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDUppercaseWordTest : SenTestCase { + +} + +@end diff --git a/test/.svn/text-base/TDUppercaseWordTest.m.svn-base b/test/.svn/text-base/TDUppercaseWordTest.m.svn-base new file mode 100644 index 0000000..58d2009 --- /dev/null +++ b/test/.svn/text-base/TDUppercaseWordTest.m.svn-base @@ -0,0 +1,58 @@ +// +// PKUppercaseWordTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/13/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDUppercaseWordTest.h" +#import "ParseKit.h" + +@implementation TDUppercaseWordTest + +- (void)testFoobar { + NSString *s = @"Foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKUppercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[Foobar]Foobar^", [result description]); +} + + +- (void)testfoobar { + NSString *s = @"foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKUppercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)test123 { + NSString *s = @"123"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKUppercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)testPercentFoobar { + NSString *s = @"%Foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKUppercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + +@end diff --git a/test/.svn/text-base/TDWhitespaceStateTest.h.svn-base b/test/.svn/text-base/TDWhitespaceStateTest.h.svn-base new file mode 100644 index 0000000..210c614 --- /dev/null +++ b/test/.svn/text-base/TDWhitespaceStateTest.h.svn-base @@ -0,0 +1,16 @@ +// +// PKWhitespaceStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDWhitespaceStateTest : SenTestCase { + PKWhitespaceState *whitespaceState; + PKReader *r; + NSString *s; +} +@end diff --git a/test/.svn/text-base/TDWhitespaceStateTest.m.svn-base b/test/.svn/text-base/TDWhitespaceStateTest.m.svn-base new file mode 100644 index 0000000..a751dc8 --- /dev/null +++ b/test/.svn/text-base/TDWhitespaceStateTest.m.svn-base @@ -0,0 +1,324 @@ +// +// PKWhitespaceStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDWhitespaceStateTest.h" + + +@implementation TDWhitespaceStateTest + +- (void)setUp { + whitespaceState = [[PKWhitespaceState alloc] init]; +} + + +- (void)tearDown { + [whitespaceState release]; + [r release]; +} + + +- (void)testSpace { + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTwoSpaces { + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testNil { + s = nil; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testNull { + s = NULL; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testEmptyString { + s = @""; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTab { + s = @"\t"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testNewLine { + s = @"\n"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testCarriageReturn { + s = @"\r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSpaceCarriageReturn { + s = @" \r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSpaceTabNewLineSpace { + s = @" \t\n "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSpaceA { + s = @" a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + +- (void)testSpaceASpace { + s = @" a "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testTabA { + s = @"\ta"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testNewLineA { + s = @"\na"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testCarriageReturnA { + s = @"\ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testNewLineSpaceCarriageReturnA { + s = @"\n \ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +#pragma mark - +#pragma mark Significant + +- (void)testSignificantSpace { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantTwoSpaces { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantEmptyString { + whitespaceState.reportsWhitespaceTokens = YES; + s = @""; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantTab { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\t"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantNewLine { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\n"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantCarriageReturn { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantSpaceCarriageReturn { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" \r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantSpaceTabNewLineSpace { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" \t\n "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantSpaceA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@" ", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantSpaceASpace { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" a "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@" ", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantTabA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\ta"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@"\t", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantNewLineA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\na"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@"\n", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantCarriageReturnA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@"\r", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantNewLineSpaceCarriageReturnA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\n \ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@"\n \r", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + +@end \ No newline at end of file diff --git a/test/.svn/text-base/TDWordOrReservedState.h.svn-base b/test/.svn/text-base/TDWordOrReservedState.h.svn-base new file mode 100644 index 0000000..9545ff0 --- /dev/null +++ b/test/.svn/text-base/TDWordOrReservedState.h.svn-base @@ -0,0 +1,25 @@ +// +// PKWordOrReservedState.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +#import + +/*! + @class TDWordOrReservedState + @brief Override PKWordState to return known reserved words as tokens of type TDTT_RESERVED. +*/ +@interface TDWordOrReservedState : PKWordState { + NSMutableSet *reservedWords; +} + +/*! + @brief Adds the specified string as a known reserved word. + @param s reserved word to add +*/ +- (void)addReservedWord:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDWordOrReservedState.m.svn-base b/test/.svn/text-base/TDWordOrReservedState.m.svn-base new file mode 100644 index 0000000..e61c42b --- /dev/null +++ b/test/.svn/text-base/TDWordOrReservedState.m.svn-base @@ -0,0 +1,42 @@ +// +// PKWordOrReservedState.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/14/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDWordOrReservedState () +@property (nonatomic, retain) NSMutableSet *reservedWords; +@end + +@implementation TDWordOrReservedState + +- (id)init { + if (self = [super init]) { + self.reservedWords = [NSMutableSet set]; + } + return self; +} + + +- (void)dealloc { + self.reservedWords = nil; + [super dealloc]; +} + + +- (void)addReservedWord:(NSString *)s { + [reservedWords addObject:s]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + return nil; +} + +@synthesize reservedWords; +@end diff --git a/test/.svn/text-base/TDWordStateTest.h.svn-base b/test/.svn/text-base/TDWordStateTest.h.svn-base new file mode 100644 index 0000000..8a31c15 --- /dev/null +++ b/test/.svn/text-base/TDWordStateTest.h.svn-base @@ -0,0 +1,16 @@ +// +// PKWordStateTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDWordStateTest : SenTestCase { + PKWordState *wordState; + PKReader *r; + NSString *s; +} +@end diff --git a/test/.svn/text-base/TDWordStateTest.m.svn-base b/test/.svn/text-base/TDWordStateTest.m.svn-base new file mode 100644 index 0000000..274c1e8 --- /dev/null +++ b/test/.svn/text-base/TDWordStateTest.m.svn-base @@ -0,0 +1,112 @@ +// +// PKWordStateTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDWordStateTest.h" + + +@implementation TDWordStateTest + +- (void)setUp { + wordState = [[PKWordState alloc] init]; +} + + +- (void)tearDown { + [wordState release]; + [r release]; +} + + +- (void)testA { + s = @"a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"a", tok.stringValue); + TDEqualObjects(@"a", tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testASpace { + s = @"a "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"a", tok.stringValue); + TDEqualObjects(@"a", tok.value); + TDTrue(tok.isWord); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testAb { + s = @"ab"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testAbc { + s = @"abc"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testItApostropheS { + s = @"it's"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTwentyDashFive { + s = @"twenty-five"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTwentyUnderscoreFive { + s = @"twenty_five"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testNumber1 { + s = @"number1"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + +@end diff --git a/test/.svn/text-base/TDXMLParser.h.svn-base b/test/.svn/text-base/TDXMLParser.h.svn-base new file mode 100644 index 0000000..d7e944e --- /dev/null +++ b/test/.svn/text-base/TDXMLParser.h.svn-base @@ -0,0 +1,15 @@ +// +// PKXMLParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/19/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface TDXMLParser : NSObject { + +} + +@end diff --git a/test/.svn/text-base/TDXMLParser.m.svn-base b/test/.svn/text-base/TDXMLParser.m.svn-base new file mode 100644 index 0000000..f72a6ce --- /dev/null +++ b/test/.svn/text-base/TDXMLParser.m.svn-base @@ -0,0 +1,15 @@ +// +// PKXMLParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/19/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXMLParser.h" + +@implementation TDXMLParser + + + +@end diff --git a/test/.svn/text-base/TDXMLParserTest.h.svn-base b/test/.svn/text-base/TDXMLParserTest.h.svn-base new file mode 100644 index 0000000..41d88d6 --- /dev/null +++ b/test/.svn/text-base/TDXMLParserTest.h.svn-base @@ -0,0 +1,21 @@ +// +// PKXMLParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/19/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface TDXMLParserTest : SenTestCase { + NSString *s; + NSString *g; + PKParserFactory *factory; + PKTokenAssembly *a; + PKAssembly *res; + PKParser *p; + PKTokenizer *t; +} + +@end diff --git a/test/.svn/text-base/TDXMLParserTest.m.svn-base b/test/.svn/text-base/TDXMLParserTest.m.svn-base new file mode 100644 index 0000000..605667a --- /dev/null +++ b/test/.svn/text-base/TDXMLParserTest.m.svn-base @@ -0,0 +1,423 @@ +// +// PKXMLParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/19/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXMLParserTest.h" + +@implementation TDXMLParserTest + +- (void)setUp { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xml" ofType:@"grammar"]; + g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + factory = [PKParserFactory factory]; + p = [factory parserFromGrammar:g assembler:self]; + t = p.tokenizer; +} + + +- (void)testSTag { + PKParser *sTag = [p parserNamed:@"sTag"]; + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, , >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, \t, >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, \n , >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, , bar, =, 'baz', >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, , bar, =, 'baz', , baz, =, 'bat', >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, , bar, =, 'baz', , baz, =, \t, 'bat', >]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDEqualObjects(@"[<, foo, />]^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, ]/^", [res description]); + + t.string = @" "; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, , ]/ /^", [res description]); + + t.string = @"&bar;"; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &, bar, ;, ]/&/bar/;/^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#, 20, ;, ]/&#/20/;/^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, ]/&#x/FF20/;/^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , ]/&#x/FF20/;/ /^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, , ]//^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , ]/&#x/FF20/;//^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , , ]/&#x/FF20/;/ //^", [res description]); +} + + +- (void)testSmallSTagGrammar { + g = @"@delimitState='<';@reportsWhitespaceTokens=YES;@start=sTag;sTag='<' name (S attribute)* S? '>';name=/[^-:\\.]\\w+/;attribute=name eq attValue;eq=S? '=' S?;attValue=QuotedString;"; + PKParser *sTag = [factory parserFromGrammar:g assembler:nil]; + t = sTag.tokenizer; + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [sTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, >]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [sTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, , >]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [sTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, \n, >]^", [res description]); + + t.string = @"< foo>"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [sTag bestMatchFor:a]; + TDNil(res); +} + + +- (void)testSmallETagGrammar { + g = @"@symbols = '&#' '&#x' '' '' nil; @delimitedString='' nil; @delimitedString='' nil;" + @"@reportsWhitespaceTokens = YES;" + @"@start = eTag;" + @"eTag='';" + @"name=/[^-:\\.]\\w+/;"; + + PKParser *eTag = [factory parserFromGrammar:g assembler:nil]; + t = eTag.tokenizer; + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eTag bestMatchFor:a]; + TDEqualObjects(@"[]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eTag bestMatchFor:a]; + TDEqualObjects(@"[]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eTag bestMatchFor:a]; + TDNil(res); + + t.string = @"< /foo>"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eTag bestMatchFor:a]; + TDNil(res); +} + + +- (void)testETag { + t.string = @""; + res = [[p parserNamed:@"eTag"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); +} + + +- (void)test1 { + t.string = @""; + res = [[p parserNamed:@"element"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, ]/^", [res description]); + + t.string = @""; + res = [[p parserNamed:@"emptyElemTag"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, />]^", [res description]); +} + + +- (void)testSmallEmptyElemTagGrammar { + g = @"@delimitState='<';@symbols='/>';@reportsWhitespaceTokens=YES;@start=emptyElemTag;emptyElemTag='<' name (S attribute)* S? '/>';name=/[^-:\\.]\\w+/;attribute=name eq attValue;eq=S? '=' S?;attValue=QuotedString;"; + PKParser *emptyElemTag = [factory parserFromGrammar:g assembler:nil]; + t = emptyElemTag.tokenizer; + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [emptyElemTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, />]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [emptyElemTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, , />]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [emptyElemTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, , bar, =, 'baz', />]^", [res description]); +} + + +- (void)testSmallCharDataGrammar { + g = @"@symbols = '&#' '&#x' '' '' nil '' nil '' nil;" + @"@reportsWhitespaceTokens = YES;" + @"@start = charData+;" + @"charData = /[^<\\&]+/ - (/[^\\]]*\\]\\]>[^<\\&]*/);"; + + PKParser *charData = [factory parserFromGrammar:g assembler:nil]; + t = charData.tokenizer; + + t.string = @" "; + res = [charData bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[ ] ^", [res description]); + + t.string = @"foo % 1"; + res = [charData bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, , %, , 1]foo/ /%/ /1^", [res description]); + + t.string = @"foo & 1"; + res = [charData bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, ]foo/ ^&/ /1", [res description]); +} + + +- (void)testSmallElementGrammar { + g = @"@symbols = '&#' '&#x' '' '' nil '' nil '' nil;" + @"@reportsWhitespaceTokens = YES;" + @"@start = element;" + @"element = emptyElemTag | sTag content eTag;" + @"eTag = '';" + @"sTag = '<' name (S attribute)* S? '>';" + @"emptyElemTag = '<' name (S attribute)* S? '/>';" + //@"content = Empty | (element | reference | cdSect | pi | comment | charData)+;" + @"content = Empty | (element | reference | cdSect | charData)+;" + @"name = /[^-:\\.]\\w+/;" + @"attribute = name eq attValue;" + @"eq=S? '=' S?;" + @"attValue = QuotedString;" + @"charData = /[^<\\&]+/ - (/[^\\]]*\\]\\]>[^<\\&]*/);" + @"reference = entityRef | charRef;" + @"entityRef = '&' name ';';" + @"charRef = '&#' /[0-9]+/ ';' | '&#x' /[0-9a-fA-F]+/ ';';" + @"cdSect = DelimitedString('');" + ; + + PKParser *element = [factory parserFromGrammar:g assembler:nil]; + t = element.tokenizer; + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [element bestMatchFor:a]; + TDEqualObjects(@"[<, foo, />]^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, ]/^", [res description]); + + t.string = @" "; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, , ]/ /^", [res description]); + + t.string = @"&bar;"; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &, bar, ;, ]/&/bar/;/^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#, 20, ;, ]/&#/20/;/^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, ]/&#x/FF20/;/^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , ]/&#x/FF20/;/ /^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, , ]//^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , ]/&#x/FF20/;//^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , , ]/&#x/FF20/;/ //^", [res description]); +} + + +// [1] +- (void)testDocument { + // xmlDecl = ''; + t.string = @""; + res = [[p parserNamed:@"document"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[, <, foo, >, ]//^", [res description]); + + // xmlDecl = ''; + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[, <, foo, >, ]//^", [res description]); + + // xmlDecl = ''; + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"xml"]; + t.string = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + NSDate *d = [NSDate date]; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + NSLog(@"time: %d", [d timeIntervalSinceNow]); + TDNotNil(res); + TDTrue([[res description] hasSuffix:@"^"]); +} + + +// [2] +- (void)test { + +} + + +// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) +// charData = /[^<\&]+/ - (/[^\]]*\]\]>[^<\&]*/); +- (void)testCharData { + t.string = @"foo"; + res = [[p parserNamed:@"charData"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + t.string = @"fo' +// comment = DelimitedString(''); +- (void)testComment { + t.string = @""; + res = [[p parserNamed:@"comment"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + + +} + + +// [16] PI ::= '' Char*)))? '?>' +// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) +// pi = '/* '?>'; +// piTarget = name - /xml/i; + +- (void)testPI { + NSString *gram = + @"@reportsWhitespaceTokens=YES;" + @"@symbols='';" + @"@symbolState = '<';" + @"name=/[^-:\\.]\\w+/;" + @"piTarget = name - /xml/i;" + @"@wordState = ':' '.' '-' '_';" + @"@wordChars = ':' '.' '-' '_';" + @"pi = '/* '?>';" + @"@start = pi;"; + PKParser *pi = [[PKParserFactory factory] parserFromGrammar:gram assembler:nil]; + pi.tokenizer.string = @""; + res = [pi bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:pi.tokenizer]]; + TDEqualObjects(@"[]^", [res description]); + + t.string = @""; + res = [[p parserNamed:@"pi"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + + t.string = @""; + res = [[p parserNamed:@"pi"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + +} + + +// [23] XMLDecl ::= '' +// xmlDecl = ''; +- (void)testXmlDecl { +// versionNum = /(['"])1\.[0-9]\1/; +// versionInfo = S 'version' eq versionNum; + + t.string = @" version='1.0'"; + res = [[p parserNamed:@"versionInfo"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[ , version, =, '1.0'] /version/=/'1.0'^", [res description]); + + // encodingDecl = S 'encoding' eq QuotedString; # TODO + t.string = @" encoding='UTF-8'"; + res = [[p parserNamed:@"encodingDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[ , encoding, =, 'UTF-8'] /encoding/=/'UTF-8'^", [res description]); + + // sdDecl = S 'standalone' eq QuotedString; # /(["'])(yes|no)\1/; # TODO + t.string = @" standalone='no'"; + res = [[p parserNamed:@"sdDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[ , standalone, =, 'no'] /standalone/=/'no'^", [res description]); + + t.string = @"'; + t.string = @""; + res = [[p parserNamed:@"xmlDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + + // xmlDecl = ''; + t.string = @""; + res = [[p parserNamed:@"xmlDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + + // xmlDecl = ''; + t.string = @""; + res = [[p parserNamed:@"xmlDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + +} + + +@end diff --git a/test/.svn/text-base/TDXmlAttribute.h.svn-base b/test/.svn/text-base/TDXmlAttribute.h.svn-base new file mode 100644 index 0000000..a598664 --- /dev/null +++ b/test/.svn/text-base/TDXmlAttribute.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlAttribute.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlAttribute : TDXmlTerminal { + +} ++ (id)attribute; ++ (id)attributeWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlAttribute.m.svn-base b/test/.svn/text-base/TDXmlAttribute.m.svn-base new file mode 100644 index 0000000..428e380 --- /dev/null +++ b/test/.svn/text-base/TDXmlAttribute.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlAttribute.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlAttribute.h" +#import "TDXmlToken.h" + +@implementation TDXmlAttribute + ++ (id)attribute { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)attributeWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_ATTRIBUTE stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isAttribute; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlCdata.h.svn-base b/test/.svn/text-base/TDXmlCdata.h.svn-base new file mode 100644 index 0000000..2989542 --- /dev/null +++ b/test/.svn/text-base/TDXmlCdata.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlCdata.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlCdata : TDXmlTerminal { + +} ++ (id)cdata; ++ (id)cdataWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlCdata.m.svn-base b/test/.svn/text-base/TDXmlCdata.m.svn-base new file mode 100644 index 0000000..28d784c --- /dev/null +++ b/test/.svn/text-base/TDXmlCdata.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlCdata.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlCdata.h" +#import "TDXmlToken.h" + +@implementation TDXmlCdata + ++ (id)cdata { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)cdataWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_CDATA stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isCdata; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlComment.h.svn-base b/test/.svn/text-base/TDXmlComment.h.svn-base new file mode 100644 index 0000000..3333e09 --- /dev/null +++ b/test/.svn/text-base/TDXmlComment.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlComment.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlComment : TDXmlTerminal { + +} ++ (id)comment; ++ (id)commentWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlComment.m.svn-base b/test/.svn/text-base/TDXmlComment.m.svn-base new file mode 100644 index 0000000..4f71ab0 --- /dev/null +++ b/test/.svn/text-base/TDXmlComment.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlComment.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlComment.h" +#import "TDXmlToken.h" + +@implementation TDXmlComment + ++ (id)comment { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)commentWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_COMMENT stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isComment; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlDecl.h.svn-base b/test/.svn/text-base/TDXmlDecl.h.svn-base new file mode 100644 index 0000000..af2e19b --- /dev/null +++ b/test/.svn/text-base/TDXmlDecl.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlDecl.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlDecl : TDXmlTerminal { + +} ++ (id)xmlDecl; ++ (id)xmlDeclWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlDecl.m.svn-base b/test/.svn/text-base/TDXmlDecl.m.svn-base new file mode 100644 index 0000000..ac3655e --- /dev/null +++ b/test/.svn/text-base/TDXmlDecl.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlDecl.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlDecl.h" +#import "TDXmlToken.h" + +@implementation TDXmlDecl + ++ (id)xmlDecl { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)xmlDeclWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_XML_DECL stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isXmlDecl; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlDoctype.h.svn-base b/test/.svn/text-base/TDXmlDoctype.h.svn-base new file mode 100644 index 0000000..16692f8 --- /dev/null +++ b/test/.svn/text-base/TDXmlDoctype.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlDoctype.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlDoctype : TDXmlTerminal { + +} ++ (id)doctype; ++ (id)doctypeWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlDoctype.m.svn-base b/test/.svn/text-base/TDXmlDoctype.m.svn-base new file mode 100644 index 0000000..953e554 --- /dev/null +++ b/test/.svn/text-base/TDXmlDoctype.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlDoctype.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlDoctype.h" +#import "TDXmlToken.h" + +@implementation TDXmlDoctype + ++ (id)doctype { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)doctypeWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_DOCTYPE stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isDoctype; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlDocument.h.svn-base b/test/.svn/text-base/TDXmlDocument.h.svn-base new file mode 100644 index 0000000..9563da3 --- /dev/null +++ b/test/.svn/text-base/TDXmlDocument.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlDocument.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlDocument : TDXmlTerminal { + +} ++ (id)document; ++ (id)documentWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlDocument.m.svn-base b/test/.svn/text-base/TDXmlDocument.m.svn-base new file mode 100644 index 0000000..8b1d356 --- /dev/null +++ b/test/.svn/text-base/TDXmlDocument.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlDocument.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlDocument.h" +#import "TDXmlToken.h" + +@implementation TDXmlDocument + ++ (id)document { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)documentWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_DOCUMENT stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isDocument; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlEndEntity.h.svn-base b/test/.svn/text-base/TDXmlEndEntity.h.svn-base new file mode 100644 index 0000000..71362ac --- /dev/null +++ b/test/.svn/text-base/TDXmlEndEntity.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlEndEntity.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlEndEntity : TDXmlTerminal { + +} ++ (id)endEntity; ++ (id)endEntityWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlEndEntity.m.svn-base b/test/.svn/text-base/TDXmlEndEntity.m.svn-base new file mode 100644 index 0000000..aa49d32 --- /dev/null +++ b/test/.svn/text-base/TDXmlEndEntity.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlEndEntity.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlEndEntity.h" +#import "TDXmlToken.h" + +@implementation TDXmlEndEntity + ++ (id)endEntity { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)endEntityWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_END_ENTITY stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isEndEntity; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlEndTag.h.svn-base b/test/.svn/text-base/TDXmlEndTag.h.svn-base new file mode 100644 index 0000000..d48c90d --- /dev/null +++ b/test/.svn/text-base/TDXmlEndTag.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlEndTag.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlEndTag : TDXmlTerminal { + +} ++ (id)endTag; ++ (id)endTagWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlEndTag.m.svn-base b/test/.svn/text-base/TDXmlEndTag.m.svn-base new file mode 100644 index 0000000..436816b --- /dev/null +++ b/test/.svn/text-base/TDXmlEndTag.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlEndTag.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlEndTag.h" +#import "TDXmlToken.h" + +@implementation TDXmlEndTag + ++ (id)endTag { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)endTagWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_END_TAG stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isEndTag; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlEntity.h.svn-base b/test/.svn/text-base/TDXmlEntity.h.svn-base new file mode 100644 index 0000000..ea52efc --- /dev/null +++ b/test/.svn/text-base/TDXmlEntity.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlEntity.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlEntity : TDXmlTerminal { + +} ++ (id)entity; ++ (id)entityWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlEntity.m.svn-base b/test/.svn/text-base/TDXmlEntity.m.svn-base new file mode 100644 index 0000000..823e358 --- /dev/null +++ b/test/.svn/text-base/TDXmlEntity.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlEntity.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlEntity.h" +#import "TDXmlToken.h" + +@implementation TDXmlEntity + ++ (id)entity { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)entityWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_ENTITY stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isEntity; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlEntityRef.h.svn-base b/test/.svn/text-base/TDXmlEntityRef.h.svn-base new file mode 100644 index 0000000..b69bbba --- /dev/null +++ b/test/.svn/text-base/TDXmlEntityRef.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlEntityRef.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlEntityRef : TDXmlTerminal { + +} ++ (id)entityRef; ++ (id)entityRefWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlEntityRef.m.svn-base b/test/.svn/text-base/TDXmlEntityRef.m.svn-base new file mode 100644 index 0000000..f601ed5 --- /dev/null +++ b/test/.svn/text-base/TDXmlEntityRef.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlEntityRef.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlEntityRef.h" +#import "TDXmlToken.h" + +@implementation TDXmlEntityRef + ++ (id)entityRef { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)entityRefWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_ENTITY_REF stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isEntityRef; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlFragment.h.svn-base b/test/.svn/text-base/TDXmlFragment.h.svn-base new file mode 100644 index 0000000..0598d41 --- /dev/null +++ b/test/.svn/text-base/TDXmlFragment.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlFragment.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlFragment : TDXmlTerminal { + +} ++ (id)doctype; ++ (id)doctypeWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlFragment.m.svn-base b/test/.svn/text-base/TDXmlFragment.m.svn-base new file mode 100644 index 0000000..bddcd58 --- /dev/null +++ b/test/.svn/text-base/TDXmlFragment.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlFragment.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlFragment.h" +#import "TDXmlToken.h" + +@implementation TDXmlFragment + ++ (id)doctype { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)doctypeWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_FRAGMENT stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isFragment; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlName.h.svn-base b/test/.svn/text-base/TDXmlName.h.svn-base new file mode 100644 index 0000000..1d9d007 --- /dev/null +++ b/test/.svn/text-base/TDXmlName.h.svn-base @@ -0,0 +1,15 @@ +// +// PKXmlName.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKTerminal.h" + +@interface TDXmlName : PKTerminal { + +} ++ (id)name; +@end diff --git a/test/.svn/text-base/TDXmlName.m.svn-base b/test/.svn/text-base/TDXmlName.m.svn-base new file mode 100644 index 0000000..8a33fd2 --- /dev/null +++ b/test/.svn/text-base/TDXmlName.m.svn-base @@ -0,0 +1,33 @@ +// +// PKXmlName.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlName.h" +#import "PKToken.h" + +@implementation TDXmlName + ++ (id)name { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + //NSString *s = tok.stringValue; + if (YES) { + + } + + return YES; +} + +@end diff --git a/test/.svn/text-base/TDXmlNameState.h.svn-base b/test/.svn/text-base/TDXmlNameState.h.svn-base new file mode 100644 index 0000000..92c5ff2 --- /dev/null +++ b/test/.svn/text-base/TDXmlNameState.h.svn-base @@ -0,0 +1,15 @@ +// +// PKXmlNameState.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKTokenizerState.h" + +@interface TDXmlNameState : PKTokenizerState { + +} + +@end diff --git a/test/.svn/text-base/TDXmlNameState.m.svn-base b/test/.svn/text-base/TDXmlNameState.m.svn-base new file mode 100644 index 0000000..f3fe3ef --- /dev/null +++ b/test/.svn/text-base/TDXmlNameState.m.svn-base @@ -0,0 +1,81 @@ +// +// PKXmlNameState.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlNameState.h" +#import "PKTokenizer.h" +#import "PKReader.h" +#import "TDXmlToken.h" + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface TDXmlNameState () ++ (BOOL)isNameChar:(PKUniChar)c; ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c; ++ (BOOL)isValidNonStartSymbolChar:(PKUniChar)c; +@end + +//Name ::= (Letter | '_' | ':') (NameChar)* +@implementation TDXmlNameState + +//- (BOOL)isWhitespace:(PKUniChar)c { +// return (' ' == c || '\n' == c || '\r' == c || '\t' == c); +//} + + +// NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender ++ (BOOL)isNameChar:(PKUniChar)c { + if (isalpha(c)) { + return YES; + } else if (isdigit(c)) { + return YES; + } else if ([[self class] isValidNonStartSymbolChar:c]) { + return YES; + } + // TODO CombiningChar & Extender + return NO; +} + + ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c { + return ('_' == c || ':' == c); +} + + ++ (BOOL)isValidNonStartSymbolChar:(PKUniChar)c { + return ('_' == c || '.' == c || '-' == c || ':' == c); +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + [self resetWithReader:r]; + + NSInteger c = cin; + do { + [self append:c]; + c = [r read]; + } while ([[self class] isNameChar:c]); + + if (PKEOF != c) { + [r unread]; + } + + if ([[self bufferedString] length] == 1 && [[self class] isValidStartSymbolChar:cin]) { + return [t.symbolState nextTokenFromReader:r startingWith:cin tokenizer:t]; + } else { +// return [[[TDXmlToken alloc] initWithTokenType:TDTT_NAME +// stringValue:[[stringbuf copy] autorelease] +// floatValue:0.0] autorelease]; + return nil; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlNameTest.h.svn-base b/test/.svn/text-base/TDXmlNameTest.h.svn-base new file mode 100644 index 0000000..9401b9d --- /dev/null +++ b/test/.svn/text-base/TDXmlNameTest.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlNameTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +// + +@interface TDXmlNameTest : SenTestCase { + +} + +@end diff --git a/test/.svn/text-base/TDXmlNameTest.m.svn-base b/test/.svn/text-base/TDXmlNameTest.m.svn-base new file mode 100644 index 0000000..7daca57 --- /dev/null +++ b/test/.svn/text-base/TDXmlNameTest.m.svn-base @@ -0,0 +1,62 @@ +// +// PKXmlNameTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlNameTest.h" +#import "TDXmlNameState.h" +#import "TDXmlNmtokenState.h" +#import "TDXmlToken.h" + +@implementation TDXmlNameTest +// +//- (void)test { +// NSString *s = @"_foob?ar _foobar 2baz"; +// PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; +// +// //Name ::= (Letter | '_' | ':') (NameChar)* +// TDXmlNameState *nameState = [[[TDXmlNameState alloc] init] autorelease]; +// +// [t setTokenizerState:nameState from: '_' to: '_']; +// [t setTokenizerState:nameState from: ':' to: ':']; +// [t setTokenizerState:nameState from: 'a' to: 'z']; +// [t setTokenizerState:nameState from: 'A' to: 'Z']; +// [t setTokenizerState:nameState from:0xc0 to:0xff]; +// +// TDXmlNmtokenState *nmtokenState = [[[TDXmlNmtokenState alloc] init] autorelease]; +// [t setTokenizerState:nmtokenState from: '0' to: '9']; +// +// TDXmlToken *tok = nil; +// +// // _foob +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isName); +// +// // '?' +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isSymbol); +// +// // ar +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isName); +// +// // _foobar +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isName); +// +// // 2baz +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isNmtoken); +// NSLog(@"tok: %@", tok); +// +//} + +@end diff --git a/test/.svn/text-base/TDXmlNmtoken.h.svn-base b/test/.svn/text-base/TDXmlNmtoken.h.svn-base new file mode 100644 index 0000000..aa67c83 --- /dev/null +++ b/test/.svn/text-base/TDXmlNmtoken.h.svn-base @@ -0,0 +1,15 @@ +// +// PKXmlNmtoken.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKTerminal.h" + +@interface TDXmlNmtoken : PKTerminal { + +} ++ (id)nmtoken; +@end diff --git a/test/.svn/text-base/TDXmlNmtoken.m.svn-base b/test/.svn/text-base/TDXmlNmtoken.m.svn-base new file mode 100644 index 0000000..50cf4b1 --- /dev/null +++ b/test/.svn/text-base/TDXmlNmtoken.m.svn-base @@ -0,0 +1,24 @@ +// +// PKXmlNmtoken.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlNmtoken.h" +#import "TDXmlToken.h" + +@implementation TDXmlNmtoken + ++ (id)nmtoken { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +//- (BOOL)qualifies:(id)obj { +// TDXmlToken *tok = (TDXmlToken *)obj; +// return tok.isNmtoken; +//} + +@end diff --git a/test/.svn/text-base/TDXmlNmtokenState.h.svn-base b/test/.svn/text-base/TDXmlNmtokenState.h.svn-base new file mode 100644 index 0000000..2e57bb8 --- /dev/null +++ b/test/.svn/text-base/TDXmlNmtokenState.h.svn-base @@ -0,0 +1,15 @@ +// +// PKXmlNmtokenState.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlNameState.h" + +@interface TDXmlNmtokenState : TDXmlNameState { + +} + +@end diff --git a/test/.svn/text-base/TDXmlNmtokenState.m.svn-base b/test/.svn/text-base/TDXmlNmtokenState.m.svn-base new file mode 100644 index 0000000..7e7eb26 --- /dev/null +++ b/test/.svn/text-base/TDXmlNmtokenState.m.svn-base @@ -0,0 +1,59 @@ +// +// PKXmlNmtokenState.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlNmtokenState.h" +#import "PKTokenizer.h" +#import "PKReader.h" +#import "TDXmlToken.h" + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface TDXmlNameState () ++ (BOOL)isNameChar:(PKUniChar)c; ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c; +@end + +// NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender +@implementation TDXmlNmtokenState + ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c { + return ('_' == c || ':' == c || '-' == c || '.' == c); +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + [self resetWithReader:r]; + + NSInteger c = cin; + do { + [self append:c]; + c = [r read]; + } while ([[self class] isNameChar:c]); + + if (PKEOF != c) { + [r unread]; + } + + NSString *s = [self bufferedString]; + if ([s length] == 1 && [[self class] isValidStartSymbolChar:cin]) { + return [t.symbolState nextTokenFromReader:r startingWith:cin tokenizer:t]; + } else if ([s length] == 1 && isdigit(cin)) { + return [t.numberState nextTokenFromReader:r startingWith:cin tokenizer:t]; + } else { + return nil; +// return [[[TDXmlToken alloc] initWithTokenType:TDTT_NMTOKEN +// stringValue:[[stringbuf copy] autorelease] +// floatValue:0.0] autorelease]; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlNotation.h.svn-base b/test/.svn/text-base/TDXmlNotation.h.svn-base new file mode 100644 index 0000000..6b9c0dc --- /dev/null +++ b/test/.svn/text-base/TDXmlNotation.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlNotation.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlNotation : TDXmlTerminal { + +} ++ (id)notation; ++ (id)notationWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlNotation.m.svn-base b/test/.svn/text-base/TDXmlNotation.m.svn-base new file mode 100644 index 0000000..40e4b53 --- /dev/null +++ b/test/.svn/text-base/TDXmlNotation.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlNotation.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlNotation.h" +#import "TDXmlToken.h" + +@implementation TDXmlNotation + ++ (id)notation { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)notationWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_NOTATION stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isNotation; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlProcessingInstruction.h.svn-base b/test/.svn/text-base/TDXmlProcessingInstruction.h.svn-base new file mode 100644 index 0000000..ba6f73a --- /dev/null +++ b/test/.svn/text-base/TDXmlProcessingInstruction.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlProcessingInstruction.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlProcessingInstruction : TDXmlTerminal { + +} ++ (id)processingInstruction; ++ (id)processingInstructionWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlProcessingInstruction.m.svn-base b/test/.svn/text-base/TDXmlProcessingInstruction.m.svn-base new file mode 100644 index 0000000..fcc6e9e --- /dev/null +++ b/test/.svn/text-base/TDXmlProcessingInstruction.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlProcessingInstruction.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlProcessingInstruction.h" +#import "TDXmlToken.h" + +@implementation TDXmlProcessingInstruction + ++ (id)processingInstruction { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)processingInstructionWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_PROCESSING_INSTRUCTION stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isProcessingInstruction; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlSignificantWhitespace.h.svn-base b/test/.svn/text-base/TDXmlSignificantWhitespace.h.svn-base new file mode 100644 index 0000000..99af28c --- /dev/null +++ b/test/.svn/text-base/TDXmlSignificantWhitespace.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlSignificantWhitespace.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlSignificantWhitespace : TDXmlTerminal { + +} ++ (id)significantWhitespace; ++ (id)significantWhitespaceWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlSignificantWhitespace.m.svn-base b/test/.svn/text-base/TDXmlSignificantWhitespace.m.svn-base new file mode 100644 index 0000000..e1b4273 --- /dev/null +++ b/test/.svn/text-base/TDXmlSignificantWhitespace.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlSignificantWhitespace.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlSignificantWhitespace.h" +#import "TDXmlToken.h" + +@implementation TDXmlSignificantWhitespace + ++ (id)significantWhitespace { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)significantWhitespaceWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_SIGNIFICANT_WHITESPACE stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isSignificantWhitespace; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlStartTag.h.svn-base b/test/.svn/text-base/TDXmlStartTag.h.svn-base new file mode 100644 index 0000000..96a9e85 --- /dev/null +++ b/test/.svn/text-base/TDXmlStartTag.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlStartTag.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlStartTag : TDXmlTerminal { + +} ++ (id)startTag; ++ (id)startTagWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlStartTag.m.svn-base b/test/.svn/text-base/TDXmlStartTag.m.svn-base new file mode 100644 index 0000000..a2e67f8 --- /dev/null +++ b/test/.svn/text-base/TDXmlStartTag.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlStartTag.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlStartTag.h" +#import "TDXmlToken.h" + +@implementation TDXmlStartTag + ++ (id)startTag { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)startTagWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_START_TAG stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isStartTag; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlTerminal.h.svn-base b/test/.svn/text-base/TDXmlTerminal.h.svn-base new file mode 100644 index 0000000..05f5186 --- /dev/null +++ b/test/.svn/text-base/TDXmlTerminal.h.svn-base @@ -0,0 +1,17 @@ +// +// PKXmlTerminal.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class TDXmlToken; + +@interface TDXmlTerminal : PKTerminal { + TDXmlToken *tok; +} +@property (nonatomic, retain) TDXmlToken *tok; +@end diff --git a/test/.svn/text-base/TDXmlTerminal.m.svn-base b/test/.svn/text-base/TDXmlTerminal.m.svn-base new file mode 100644 index 0000000..4ae615c --- /dev/null +++ b/test/.svn/text-base/TDXmlTerminal.m.svn-base @@ -0,0 +1,20 @@ +// +// PKXmlTerminal.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" +#import "TDXmlToken.h" + +@implementation TDXmlTerminal + +- (void)dealloc { + self.tok = nil; + [super dealloc]; +} + +@synthesize tok; +@end diff --git a/test/.svn/text-base/TDXmlText.h.svn-base b/test/.svn/text-base/TDXmlText.h.svn-base new file mode 100644 index 0000000..c404139 --- /dev/null +++ b/test/.svn/text-base/TDXmlText.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlText.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlText : TDXmlTerminal { + +} ++ (id)text; ++ (id)textWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlText.m.svn-base b/test/.svn/text-base/TDXmlText.m.svn-base new file mode 100644 index 0000000..8975b40 --- /dev/null +++ b/test/.svn/text-base/TDXmlText.m.svn-base @@ -0,0 +1,51 @@ +// +// PKXmlText.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlText.h" +#import "TDXmlToken.h" + +@implementation TDXmlText + ++ (id)text { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)textWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + NSLog(@"%s", _cmd); + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_TEXT stringValue:s]; + NSLog(@"tok : %@", tok); + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + NSLog(@"%s obj: %@ isText: %d", _cmd, obj, other.isText); + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isText; + } +} + +@end diff --git a/test/.svn/text-base/TDXmlToken.h.svn-base b/test/.svn/text-base/TDXmlToken.h.svn-base new file mode 100644 index 0000000..5117523 --- /dev/null +++ b/test/.svn/text-base/TDXmlToken.h.svn-base @@ -0,0 +1,89 @@ +// +// PKXmlToken.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +typedef enum { + TDTT_XML_NONE = 0, + TDTT_XML_START_TAG = 1, + TDTT_XML_ATTRIBUTE = 2, + TDTT_XML_TEXT = 3, + TDTT_XML_CDATA = 4, + TDTT_XML_ENTITY_REF = 5, + TDTT_XML_ENTITY = 6, + TDTT_XML_PROCESSING_INSTRUCTION = 7, + TDTT_XML_COMMENT = 8, + TDTT_XML_DOCUMENT = 9, + TDTT_XML_DOCTYPE = 10, + TDTT_XML_FRAGMENT = 11, + TDTT_XML_NOTATION = 12, + TDTT_XML_WHITESPACE = 13, + TDTT_XML_SIGNIFICANT_WHITESPACE = 14, + TDTT_XML_END_TAG = 15, + TDTT_XML_END_ENTITY = 16, + TDTT_XML_XML_DECL = 17, + TDTT_XML_EOF = 18 +} TDXmlTokenType; + +@interface TDXmlToken : NSObject { + NSString *stringValue; + TDXmlTokenType tokenType; + + BOOL none; + BOOL startTag; + BOOL attribute; + BOOL text; + BOOL cdata; + BOOL entityRef; + BOOL entity; + BOOL processingInstruction; + BOOL comment; + BOOL document; + BOOL doctype; + BOOL fragment; + BOOL notation; + BOOL whitespace; + BOOL significantWhitespace; + BOOL endTag; + BOOL endEntity; + BOOL xmlDecl; + + id value; +} ++ (TDXmlToken *)EOFToken; ++ (id)tokenWithTokenType:(TDXmlTokenType)t stringValue:(NSString *)s; + +// designated initializer +- (id)initWithTokenType:(TDXmlTokenType)t stringValue:(NSString *)s; + +- (BOOL)isEqualIgnoringCase:(id)obj; + +- (NSString *)debugDescription; + +@property (nonatomic, readonly, getter=isNone) BOOL none; +@property (nonatomic, readonly, getter=isStartTag) BOOL startTag; +@property (nonatomic, readonly, getter=isAttribute) BOOL attribute; +@property (nonatomic, readonly, getter=isText) BOOL text; +@property (nonatomic, readonly, getter=isCdata) BOOL cdata; +@property (nonatomic, readonly, getter=isEntityRef) BOOL entityRef; +@property (nonatomic, readonly, getter=isEntity) BOOL entity; +@property (nonatomic, readonly, getter=isProcessingInstruction) BOOL processingInstruction; +@property (nonatomic, readonly, getter=isComment) BOOL comment; +@property (nonatomic, readonly, getter=isDocument) BOOL document; +@property (nonatomic, readonly, getter=isDoctype) BOOL doctype; +@property (nonatomic, readonly, getter=isFragment) BOOL fragment; +@property (nonatomic, readonly, getter=isNotation) BOOL notation; +@property (nonatomic, readonly, getter=isWhitespace) BOOL whitespace; +@property (nonatomic, readonly, getter=isSignificantWhitespace) BOOL significantWhitespace; +@property (nonatomic, readonly, getter=isEndTag) BOOL endTag; +@property (nonatomic, readonly, getter=isEndEntity) BOOL endEntity; +@property (nonatomic, readonly, getter=isXmlDecl) BOOL xmlDecl; +@property (nonatomic, readonly, copy) NSString *stringValue; +@property (nonatomic, readonly) TDXmlTokenType tokenType; +@property (nonatomic, readonly, copy) id value; +@end diff --git a/test/.svn/text-base/TDXmlToken.m.svn-base b/test/.svn/text-base/TDXmlToken.m.svn-base new file mode 100644 index 0000000..777d1be --- /dev/null +++ b/test/.svn/text-base/TDXmlToken.m.svn-base @@ -0,0 +1,203 @@ +// +// PKXmlToken.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlToken.h" + +@interface TDXmlTokenEOF : TDXmlToken {} +@end + +@implementation TDXmlTokenEOF +- (NSString *)description { + return [NSString stringWithFormat:@"", self]; +} +@end + +@interface TDXmlToken () +@property (nonatomic, readwrite, getter=isNone) BOOL none; +@property (nonatomic, readwrite, getter=isStartTag) BOOL startTag; +@property (nonatomic, readwrite, getter=isAttribute) BOOL attribute; +@property (nonatomic, readwrite, getter=isText) BOOL text; +@property (nonatomic, readwrite, getter=isCdata) BOOL cdata; +@property (nonatomic, readwrite, getter=isEntityRef) BOOL entityRef; +@property (nonatomic, readwrite, getter=isEntity) BOOL entity; +@property (nonatomic, readwrite, getter=isProcessingInstruction) BOOL processingInstruction; +@property (nonatomic, readwrite, getter=isComment) BOOL comment; +@property (nonatomic, readwrite, getter=isDocument) BOOL document; +@property (nonatomic, readwrite, getter=isDoctype) BOOL doctype; +@property (nonatomic, readwrite, getter=isFragment) BOOL fragment; +@property (nonatomic, readwrite, getter=isNotation) BOOL notation; +@property (nonatomic, readwrite, getter=isWhitespace) BOOL whitespace; +@property (nonatomic, readwrite, getter=isSignificantWhitespace) BOOL significantWhitespace; +@property (nonatomic, readwrite, getter=isEndTag) BOOL endTag; +@property (nonatomic, readwrite, getter=isEndEntity) BOOL endEntity; +@property (nonatomic, readwrite, getter=isXmlDecl) BOOL xmlDecl; +@property (nonatomic, readwrite, copy) NSString *stringValue; +@property (nonatomic, readwrite) TDXmlTokenType tokenType; +@property (nonatomic, readwrite, copy) id value; +@end + +@implementation TDXmlToken + ++ (TDXmlToken *)EOFToken { + static TDXmlToken *EOFToken = nil; + @synchronized (self) { + if (!EOFToken) { + EOFToken = [[TDXmlTokenEOF alloc] initWithTokenType:TDTT_XML_EOF stringValue:nil]; + } + } + return EOFToken; +} + + ++ (id)tokenWithTokenType:(TDXmlTokenType)t stringValue:(NSString *)s { + return [[[self alloc] initWithTokenType:t stringValue:s] autorelease]; +} + + +#pragma mark - + +// designated initializer +- (id)initWithTokenType:(TDXmlTokenType)t stringValue:(NSString *)s { + if (self = [super init]) { + self.tokenType = t; + self.stringValue = s; + + self.none = (TDTT_XML_NONE == t); + self.startTag = (TDTT_XML_START_TAG == t); + self.attribute = (TDTT_XML_ATTRIBUTE == t); + self.text = (TDTT_XML_TEXT == t); + self.cdata = (TDTT_XML_CDATA == t); + self.entityRef = (TDTT_XML_ENTITY_REF == t); + self.entity = (TDTT_XML_ENTITY == t); + self.processingInstruction = (TDTT_XML_PROCESSING_INSTRUCTION == t); + self.comment = (TDTT_XML_COMMENT == t); + self.document = (TDTT_XML_DOCUMENT == t); + self.doctype = (TDTT_XML_DOCTYPE == t); + self.fragment = (TDTT_XML_FRAGMENT == t); + self.notation = (TDTT_XML_NOTATION == t); + self.whitespace = (TDTT_XML_WHITESPACE == t); + self.significantWhitespace = (TDTT_XML_SIGNIFICANT_WHITESPACE == t); + self.endTag = (TDTT_XML_END_TAG == t); + self.endEntity = (TDTT_XML_END_ENTITY == t); + self.xmlDecl = (TDTT_XML_XML_DECL == t); + + self.value = stringValue; + } + return self; +} + + +- (void)dealloc { + self.stringValue = nil; + self.value = nil; + [super dealloc]; +} + + +- (NSUInteger)hash { + return [stringValue hash]; +} + + +- (BOOL)isEqual:(id)rhv { + if (![rhv isMemberOfClass:[TDXmlToken class]]) { + return NO; + } + + TDXmlToken *that = (TDXmlToken *)rhv; + if (tokenType != that.tokenType) { + return NO; + } + + return [stringValue isEqualToString:that.stringValue]; +} + + +- (BOOL)isEqualIgnoringCase:(id)rhv { + if (![rhv isMemberOfClass:[TDXmlToken class]]) { + return NO; + } + + TDXmlToken *that = (TDXmlToken *)rhv; + if (tokenType != that.tokenType) { + return NO; + } + + return [stringValue.lowercaseString isEqualToString:that.stringValue.lowercaseString]; +} + + +- (NSString *)debugDescription { + NSString *typeString = nil; + if (self.isNone) { + typeString = @"None"; + } else if (self.isStartTag) { + typeString = @"Start Tag"; + } else if (self.isAttribute) { + typeString = @"Attribute"; + } else if (self.isText) { + typeString = @"Text"; + } else if (self.isCdata) { + typeString = @"CData"; + } else if (self.isEntityRef) { + typeString = @"Entity Reference"; + } else if (self.isEntity) { + typeString = @"Entity"; + } else if (self.isProcessingInstruction) { + typeString = @"Processing Instruction"; + } else if (self.isComment) { + typeString = @"Comment"; + } else if (self.isDocument) { + typeString = @"Document"; + } else if (self.isDoctype) { + typeString = @"Doctype"; + } else if (self.isFragment) { + typeString = @"Fragment"; + } else if (self.isNotation) { + typeString = @"Notation"; + } else if (self.isWhitespace) { + typeString = @"Whitespace"; + } else if (self.isSignificantWhitespace) { + typeString = @"Significant Whitespace"; + } else if (self.isEndTag) { + typeString = @"End Tag"; + } else if (self.isEndEntity) { + typeString = @"End Entity"; + } else if (self.isXmlDecl) { + typeString = @"XML Declaration"; + } + return [NSString stringWithFormat:@"<%@ %C%@%C>", typeString, 0x00ab, self.value, 0x00bb]; +} + + +- (NSString *)description { + return [self debugDescription]; +} + +@synthesize none; +@synthesize startTag; +@synthesize attribute; +@synthesize text; +@synthesize cdata; +@synthesize entityRef; +@synthesize entity; +@synthesize processingInstruction; +@synthesize comment; +@synthesize document; +@synthesize doctype; +@synthesize fragment; +@synthesize notation; +@synthesize whitespace; +@synthesize significantWhitespace; +@synthesize endTag; +@synthesize endEntity; +@synthesize xmlDecl; +@synthesize stringValue; +@synthesize tokenType; +@synthesize value; +@end diff --git a/test/.svn/text-base/TDXmlTokenAssembly.h.svn-base b/test/.svn/text-base/TDXmlTokenAssembly.h.svn-base new file mode 100644 index 0000000..57533e1 --- /dev/null +++ b/test/.svn/text-base/TDXmlTokenAssembly.h.svn-base @@ -0,0 +1,18 @@ +// +// PKXmlTokenAssembly.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/21/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class TDXmlTokenizer; + +@interface TDXmlTokenAssembly : PKAssembly { + TDXmlTokenizer *tokenizer; + NSMutableArray *tokens; +} +@property (nonatomic, retain) TDXmlTokenizer *tokenizer; +@end diff --git a/test/.svn/text-base/TDXmlTokenAssembly.m.svn-base b/test/.svn/text-base/TDXmlTokenAssembly.m.svn-base new file mode 100644 index 0000000..380d0c2 --- /dev/null +++ b/test/.svn/text-base/TDXmlTokenAssembly.m.svn-base @@ -0,0 +1,150 @@ +// +// PKXmlTokenAssembly.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/21/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTokenAssembly.h" +#import "TDXmlTokenizer.h" +#import "TDXmlToken.h" + +@interface TDXmlTokenAssembly () +- (void)tokenize; + +@property (nonatomic, retain) NSMutableArray *tokens; +@end + +@implementation TDXmlTokenAssembly + +- (id)init { + return nil; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tokenizer = [[[TDXmlTokenizer alloc] initWithContentsOfFile:s] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.tokens = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + TDXmlTokenAssembly *a = (TDXmlTokenAssembly *)[super copyWithZone:zone]; + a->tokens = [self.tokens mutableCopy]; + return a; +} + + +- (NSMutableArray *)tokens { + if (!tokens) { + [self tokenize]; + } + return [[tokens retain] autorelease]; +} + + +- (void)setTokens:(NSMutableArray *)inArray { + if (inArray != tokens) { + [tokens autorelease]; + tokens = [inArray retain]; + } +} + + +- (void)tokenize { + self.tokens = [NSMutableArray array]; + + TDXmlToken *eof = [TDXmlToken EOFToken]; + TDXmlToken *tok = nil; + while ((tok = [tokenizer nextToken]) != eof) { + [tokens addObject:tok]; + } +} + + +- (id)peek { + if (index >= [self.tokens count]) { + return nil; + } + id tok = [self.tokens objectAtIndex:index]; + + return tok; +} + + +- (id)next { + id tok = [self peek]; + if (tok) { + index++; + } + return tok; +} + + +- (BOOL)hasMore { + return (index < [self.tokens count]); +} + + +- (NSUInteger)length { + return [self.tokens count]; +} + + +- (NSUInteger)consumedObjectCount { + return index; +} + + +- (NSUInteger)remainingObjectCount { + return ([self.tokens count] - index); +} + + +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter { + NSMutableString *s = [NSMutableString string]; + + NSInteger i = 0; + NSInteger len = self.consumedObjectCount; + + for ( ; i < len; i++) { + TDXmlToken *tok = [self.tokens objectAtIndex:i]; + [s appendString:tok.stringValue]; + if (i != len - 1) { + [s appendString:delimiter]; + } + } + + return [[s copy] autorelease]; +} + + +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter { + NSMutableString *s = [NSMutableString string]; + + NSInteger i = self.consumedObjectCount; + NSInteger len = [self length]; + + for ( ; i < len; i++) { + TDXmlToken *tok = [self.tokens objectAtIndex:i]; + [s appendString:tok.stringValue]; + if (i != len - 1) { + [s appendString:delimiter]; + } + } + return [[s copy] autorelease]; +} + +@synthesize tokenizer; +@end diff --git a/test/.svn/text-base/TDXmlTokenizer.h.svn-base b/test/.svn/text-base/TDXmlTokenizer.h.svn-base new file mode 100644 index 0000000..6a55b83 --- /dev/null +++ b/test/.svn/text-base/TDXmlTokenizer.h.svn-base @@ -0,0 +1,21 @@ +// +// PKXmlTokenizer.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class TDXmlToken; +@class XMLReader; + +@interface TDXmlTokenizer : NSObject { + XMLReader *reader; +} ++ (id)tokenizerWithContentsOfFile:(NSString *)path; + +- (id)initWithContentsOfFile:(NSString *)path; +- (TDXmlToken *)nextToken; +@end diff --git a/test/.svn/text-base/TDXmlTokenizer.m.svn-base b/test/.svn/text-base/TDXmlTokenizer.m.svn-base new file mode 100644 index 0000000..118bdec --- /dev/null +++ b/test/.svn/text-base/TDXmlTokenizer.m.svn-base @@ -0,0 +1,63 @@ +// +// PKXmlTokenizer.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTokenizer.h" +#import "XMLReader.h" +#import "TDXmlToken.h" + +@interface TDXmlTokenizer () +@property (nonatomic, retain) XMLReader *reader; +@end + +@implementation TDXmlTokenizer + ++ (id)tokenizerWithContentsOfFile:(NSString *)path { + return [[[self alloc] initWithContentsOfFile:path] autorelease]; +} + + +- (id)init { + return nil; +} + + +- (id)initWithContentsOfFile:(NSString *)path { + if (self = [super init]) { + self.reader = [[[XMLReader alloc] initWithContentsOfFile:path] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.reader = nil; + [super dealloc]; +} + + +- (TDXmlToken *)nextToken { + TDXmlToken *tok = nil; + NSInteger ret = -1; + NSInteger nodeType = -1; + + do { + ret = [reader read]; + nodeType = reader.nodeType; + } while (nodeType == TDTT_XML_SIGNIFICANT_WHITESPACE || nodeType == TDTT_XML_WHITESPACE); + + if (ret <= 0) { + tok = [TDXmlToken EOFToken]; + } else { + tok = [TDXmlToken tokenWithTokenType:reader.nodeType stringValue:reader.name]; + } + + return tok; +} + +@synthesize reader; +@end diff --git a/test/.svn/text-base/TDXmlTokenizerTest.h.svn-base b/test/.svn/text-base/TDXmlTokenizerTest.h.svn-base new file mode 100644 index 0000000..e41411b --- /dev/null +++ b/test/.svn/text-base/TDXmlTokenizerTest.h.svn-base @@ -0,0 +1,17 @@ +// +// PKXmlTokenizerTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/21/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "TDXmlTokenizer.h" +#import "TDXmlToken.h" + +@interface TDXmlTokenizerTest : SenTestCase { + +} + +@end diff --git a/test/.svn/text-base/TDXmlTokenizerTest.m.svn-base b/test/.svn/text-base/TDXmlTokenizerTest.m.svn-base new file mode 100644 index 0000000..eac0d6b --- /dev/null +++ b/test/.svn/text-base/TDXmlTokenizerTest.m.svn-base @@ -0,0 +1,51 @@ +// +// PKXmlTokenizerTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/21/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTokenizerTest.h" +#import "TDXmlDecl.h" +#import "TDXmlStartTag.h" +#import "TDXmlEndTag.h" +#import "TDXmlText.h" +#import "TDXmlSignificantWhitespace.h" +#import "TDXmlTokenAssembly.h" + + +@implementation TDXmlTokenizerTest + +- (void)testFoo { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"xml"]; + + TDXmlTokenizer *t = [TDXmlTokenizer tokenizerWithContentsOfFile:path]; + NSLog(@"\n\n %@\n\n", t); + + TDXmlToken *eof = [TDXmlToken EOFToken]; + TDXmlToken *tok = nil; + + while ((tok = [t nextToken]) != eof) { + //NSLog(@" %@", [tok debugDescription]); + } +} + + +- (void)testAppleBoss { + PKSequence *s = [PKSequence sequence]; + s.name = @"parent sequence"; + [s add:[TDXmlStartTag startTagWithString:@"result"]]; + [s add:[TDXmlStartTag startTagWithString:@"url"]]; + [s add:[TDXmlText text]]; + [s add:[TDXmlEndTag endTagWithString:@"url"]]; + [s add:[TDXmlEndTag endTagWithString:@"result"]]; + + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"small-xml-file" ofType:@"xml"]; + TDXmlTokenAssembly *a = [TDXmlTokenAssembly assemblyWithString:path]; + + PKAssembly *result = [s bestMatchFor:a]; + NSLog(@"\n\n\n result: %@ \n\n\n", result); +} + +@end diff --git a/test/.svn/text-base/TDXmlWhitespace.h.svn-base b/test/.svn/text-base/TDXmlWhitespace.h.svn-base new file mode 100644 index 0000000..4e92513 --- /dev/null +++ b/test/.svn/text-base/TDXmlWhitespace.h.svn-base @@ -0,0 +1,16 @@ +// +// PKXmlWhitespace.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlTerminal.h" + +@interface TDXmlWhitespace : TDXmlTerminal { + +} ++ (id)whitespace; ++ (id)whitespaceWithString:(NSString *)s; +@end diff --git a/test/.svn/text-base/TDXmlWhitespace.m.svn-base b/test/.svn/text-base/TDXmlWhitespace.m.svn-base new file mode 100644 index 0000000..85b40ed --- /dev/null +++ b/test/.svn/text-base/TDXmlWhitespace.m.svn-base @@ -0,0 +1,48 @@ +// +// PKXmlWhitespace.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/20/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDXmlWhitespace.h" +#import "TDXmlToken.h" + +@implementation TDXmlWhitespace + ++ (id)whitespace { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)whitespaceWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_WHITESPACE stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isWhitespace; + } +} + +@end diff --git a/test/.svn/text-base/Tests-Info.plist.svn-base b/test/.svn/text-base/Tests-Info.plist.svn-base new file mode 100644 index 0000000..2e46062 --- /dev/null +++ b/test/.svn/text-base/Tests-Info.plist.svn-base @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.Tests + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSPrincipalClass + TDTestScaffold + + diff --git a/test/.svn/text-base/XMLReader.h.svn-base b/test/.svn/text-base/XMLReader.h.svn-base new file mode 100644 index 0000000..19cf8dd --- /dev/null +++ b/test/.svn/text-base/XMLReader.h.svn-base @@ -0,0 +1,245 @@ +// +// XMLReader.h +// XMLReader +// +// Created by Todd Ditchendorf on 6/5/06. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import +//#import +#import + +/** + * XMLReaderMode: + * + * Internal state values for the reader. + */ +typedef enum { + XMLReaderReadStateInitial = 0, + XMLReaderReadStateInteractive = 1, + XMLReaderReadStateError = 2, + XMLReaderReadStateEOF = 3, + XMLReaderReadStateClosed = 4, + XMLReaderReadStateReading = 5 +} XMLReaderReadState; + +/** + * xmlParserProperties: + * + * Some common options to use with xmlTextReaderSetParserProp, but it + * is better to use xmlParserOption and the xmlReaderNewxxx and + * xmlReaderForxxx APIs now. + * +typedef enum { + XML_PARSER_LOADDTD = 1, + XML_PARSER_DEFAULTATTRS = 2, + XML_PARSER_VALIDATE = 3, + XML_PARSER_SUBST_ENTITIES = 4 +} xmlParserProperties; +*/ + +/** + * xmlParserSeverities: + * + * How severe an error callback is when the per-reader error callback API + * is used. + */ +typedef enum { + XMLReaderSeverityValidityWarning = 1, + XMLReaderSeverityValidityError = 2, + XMLReaderSeverityWarning = 3, + XMLReaderSeverityError = 4 +} XMLReaderSeverity; + +/** + * XMLReaderNodeType: + * + * Predefined constants for the different types of nodes. + */ +typedef enum { + XMLReaderNodeTypeNone = 0, + XMLReaderNodeTypeElement = 1, + XMLReaderNodeTypeAttribute = 2, + XMLReaderNodeTypeText = 3, + XMLReaderNodeTypeCDATA = 4, + XMLReaderNodeTypeEntityReference = 5, + XMLReaderNodeTypeEntity = 6, + XMLReaderNodeTypeProcessingInstruction = 7, + XMLReaderNodeTypeComment = 8, + XMLReaderNodeTypeDocument = 9, + XMLReaderNodeTypeDocumentType = 10, + XMLReaderNodeTypeDocumentFragment = 11, + XMLReaderNodeTypeNotation = 12, + XMLReaderNodeTypeWhitespace = 13, + XMLReaderNodeTypeSignificantWhitespace = 14, + XMLReaderNodeTypeEndElement = 15, + XMLReaderNodeTypeEndEntity = 16, + XMLReaderNodeTypeXmlDeclaration = 17 +} XMLReaderNodeType; + + +@interface NSObject (XMLReaderErrorHandler) +- (void)validityWarning:(NSString *)msg lineNumber:(NSInteger)n; +- (void)validityError:(NSString *)msg lineNumber:(NSInteger)n; +- (void)warning:(NSString *)msg lineNumber:(NSInteger)n; +- (void)error:(NSString *)msg lineNumber:(NSInteger)n; +- (void)fatalError:(NSString *)msg lineNumber:(NSInteger)n; +@end + +@interface XMLReader : NSObject { + xmlTextReaderPtr _reader; + xmlRelaxNGPtr _schema; + NSString *path; + id errorHandler; + NSString *relaxNGSchemaPath; +} + ++ (id)parserWithContentsOfFile:(NSString *)newPath; +//+ (id)parserWithXMLString:(NSString *)XMLString; + +- (id)initWithContentsOfFile:(NSString *)path; +//- (id)initWithXMLString:(NSString *)XMLString; + +// Gets the number of attributes on the current node. +@property (nonatomic, readonly) NSInteger attributeCount; +//- (NSInteger)attributeCount; + +// Gets the base Uniform Resource Identifier (URI) of the current node. +@property (nonatomic, readonly, copy) NSString *baseURI; +//- (NSString *)baseURI; + +// Gets a value indicating whether this reader can parse and resolve entities. +//@property (nonatomic, readonly) BOOL canResolveEntity; +//- (BOOL)canResolveEntity; + +// Gets the depth of the current node in the XML document. +@property (nonatomic, readonly) NSInteger depth; +//- (NSInteger)depth; + +// Gets a value indicating whether the XMLReader.ReadState is ReadState.EndOfFile, signifying the reader is positioned at the end of the stream. +@property (nonatomic, readonly) BOOL isEOF; +//- (BOOL)isEOF; + +// Gets a value indicating whether the current node has any attributes. +@property (nonatomic, readonly) BOOL hasAttributes; +//- (BOOL)hasAttributes; + +// Gets a value indicating whether the current node can have an associated text value. +@property (nonatomic, readonly) BOOL hasValue; +//- (BOOL)hasValue; + +// Gets a value indicating whether the current node is an attribute that was generated from the default value defined in the DTD or schema. +@property (nonatomic, readonly) BOOL isDefault; +//- (BOOL)isDefault; + +// Gets a value indicating whether the current node is an empty element (for example, ). +@property (nonatomic, readonly) BOOL isEmptyElement; +//- (BOOL)isEmptyElement; + +// Gets the local name of the current node. +@property (nonatomic, readonly, copy) NSString *localName; +//- (NSString *)localName; + +// Gets the qualified name of the current node. +@property (nonatomic, readonly, copy) NSString *name; +//- (NSString *)name; + +// Gets the namespace URI associated with the node on which the reader is positioned. +@property (nonatomic, readonly, copy) NSString *namespaceURI; +//- (NSString *)namespaceURI; + +// Gets the name table used by the current instance to store and look up element and attribute names, prefixes, and namespaces. +//- (XmlNameTable)NameTable; + +// Gets the type of the current node. +@property (nonatomic, readonly) XMLReaderNodeType nodeType; +//- (XMLReaderNodeType)nodeType; + +// Gets the namespace prefix associated with the current node. +@property (nonatomic, readonly, copy) NSString *prefix; +//- (NSString *)prefix; + +// Gets the quotation mark character used to enclose the value of an attribute. +@property (nonatomic, readonly) char quoteChar; +//- (char)quoteChar; + +// Gets the read state of the reader. +@property (nonatomic, readonly) XMLReaderReadState readState; +//- (XMLReaderReadState)readState; + +// Gets the text value of the current node. +@property (nonatomic, readonly, copy) NSString *value; +//- (NSString *)value; + +// Gets the current xml:lang scope. +@property (nonatomic, readonly, copy) NSString *XMLLang; +//- (NSString *)XMLLang; + +// Gets the current xml:space scope. +//- (XMLSpace)XMLSpace; + +// Changes the XMLReader.ReadState to XMLReaderReadState.Closed. +- (void)close; + +// Returns the value of the attribute with the specified index relative to the containing element. +- (NSString *)attributeAtIndex:(NSInteger)index; + +// Returns the value of the attribute with the specified qualified name. +- (NSString *)attributeWithQName:(NSString *)qName; + +// Returns the value of the attribute with the specified local name and namespace URI. +- (NSString *)attributeWithLocalName:(NSString *)localName namespaceURI:(NSString *)nsURI; + +// Determines whether the specified string is a valid XML name. ++ (BOOL)isName:(NSString *)str; + +// Determines whether the specified string is a valid XML name token (Nmtoken). ++ (BOOL)isNameToken:(NSString *)str; + +// Resolves a namespace prefix in the scope of the current element. +- (NSString *)lookupNamespace:(NSString *)prefix; + +// Moves the position of the current instance to the attribute with the specified index relative to the containing element. +- (void)moveToAttributeAtIndex:(NSInteger)index; + +// Moves the position of the current instance to the attribute with the specified qualified name. +- (BOOL)moveToAttributeWithQName:(NSString *)qName; + +// Moves the position of the current instance to the attribute with the specified local name and namespace URI. +- (BOOL)moveToAttributeWithLocalName:(NSString *)localName namespaceURI:(NSString *)nsURI; + +// Moves the position of the current instance to the node that contains the current Attribute node. +- (BOOL)moveToElement; + +// Moves the position of the current instance to the first attribute associated with the current node. +- (BOOL)moveToFirstAttribute; + +// Moves the position of the current instance to the next attribute associated with the current node. +- (BOOL)moveToNextAttribute; + +// Moves the position of the current instance to the next node in the stream, exposing its properties. +- (BOOL)read; + +// Parses an attribute value into one or more Text, EntityReference, and EndEntity nodes. +- (BOOL)readAttributeValue; + +// Reads the contents of a text-only element. +- (NSString *)readElementString; + +// Reads the contents of the current node, including child nodes and markup. +- (NSString *)readInnerXML; + +// Reads the current node and its contents, including child nodes and markup. +- (NSString *)readOuterXML; + +// Reads the contents of an element or text node as a string. +- (NSString *)readString; + +// Skips over the current element and moves the position of the current instance to the next node in the stream. +- (void)skip; + +@property (nonatomic, copy) NSString *relaxNGSchemaPath; +@property (nonatomic, readonly) BOOL isValid; +@property (nonatomic, retain) id errorHandler; +@end diff --git a/test/.svn/text-base/XMLReader.m.svn-base b/test/.svn/text-base/XMLReader.m.svn-base new file mode 100644 index 0000000..2ae9812 --- /dev/null +++ b/test/.svn/text-base/XMLReader.m.svn-base @@ -0,0 +1,425 @@ + +#import "XMLReader.h" +//#import +#import + +@interface NSString (libxml2Support) ++ (id)stringWithXmlChar:(xmlChar *)xc; +- (xmlChar *)xmlChar; +@end + +@implementation NSString (libxml2Support) + ++ (id)stringWithXmlChar:(xmlChar *)xc { + if (!xc) { + return nil; + } + return [NSString stringWithUTF8String:(char *)xc]; +} + + +- (xmlChar *)xmlChar { + return (unsigned char *)[self UTF8String]; +} + +@end + + +@interface XMLReader () +@property (nonatomic, copy) NSString *path; +@end + + +@implementation XMLReader + +// don't know what this handles. can't get it to fire +static void readerErr(XMLReader *self, const char *msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator) { + NSString *str = [NSString stringWithUTF8String:msg]; + int line = xmlTextReaderLocatorLineNumber(locator); + NSLog(@"some kinda error! %s, severity: %i, line: %i", msg, severity, line); + + switch (severity) { + case XMLReaderSeverityValidityWarning: + [self.errorHandler validityWarning:str lineNumber:line]; + break; + case XMLReaderSeverityValidityError: + [self.errorHandler validityError:str lineNumber:line]; + break; + case XMLReaderSeverityWarning: + [self.errorHandler warning:str lineNumber:line]; + break; + case XMLReaderSeverityError: + [self.errorHandler error:str lineNumber:line]; + break; + } + +} + + +// handles well-formedness errors in instance document +// and handles validity errors in instance doc +static void structErr(XMLReader *self, xmlErrorPtr error) { + const char *msg = error->message; + int line = error->line; + int level = error->level; + + NSLog(@"Instance doc well-formedness or validity error, level: %i", level); + NSLog(@"message: = %s", msg); + NSLog(@"line: = %i", line); + + NSString *str = [NSString stringWithUTF8String:msg]; + + switch (level) { + case XML_ERR_WARNING: + [self.errorHandler warning:str lineNumber:line]; + break; + case XML_ERR_ERROR: + [self.errorHandler error:str lineNumber:line]; + break; + case XML_ERR_FATAL: + [self.errorHandler fatalError:str lineNumber:line]; + break; + } +} + + ++ (id)parserWithContentsOfFile:(NSString *)path { + return [[[XMLReader alloc] initWithContentsOfFile:path] autorelease]; +} + +/* ++ (id)parserWithXMLString:(NSString *)XMLString { + return [[[self alloc] initWithXMLString:XMLStirng] autorelease]; +} +*/ + +- (id)initWithContentsOfFile:(NSString *)newPath { + if (self = [super init]) { + self.path = newPath; + + _reader = xmlNewTextReaderFilename([path UTF8String]); + xmlTextReaderSetParserProp(_reader, XML_PARSE_RECOVER, 1); + xmlTextReaderSetParserProp(_reader, XML_PARSE_XINCLUDE, 1); + xmlTextReaderSetErrorHandler(_reader, (xmlTextReaderErrorFunc)readerErr, (void *)self); + xmlTextReaderSetStructuredErrorHandler(_reader, (xmlStructuredErrorFunc)structErr, (void *)self); + } + return self; +} + + +- (void)dealloc { + self.path = nil; + self.errorHandler = nil; + self.relaxNGSchemaPath = nil; + if (_reader) { + xmlFreeTextReader(_reader); + } + if (_schema) { + xmlRelaxNGFree(_schema); + } + [super dealloc]; +} + + +#pragma mark - +#pragma mark Properties + +- (NSInteger)attributeCount { + return xmlTextReaderAttributeCount(_reader); +} + + +- (NSString *)baseURI { + return [NSString stringWithXmlChar:xmlTextReaderBaseUri(_reader)]; +} + + +//- (BOOL)canResolveEntity { +// return YES; +//} + + +- (NSInteger)depth { + return xmlTextReaderDepth(_reader); +} + + +- (BOOL)isEOF { + return XMLReaderReadStateEOF == [self readState]; +} + + +- (BOOL)hasAttributes { + return xmlTextReaderHasAttributes(_reader); +} + + +- (BOOL)hasValue { + return xmlTextReaderHasValue(_reader); +} + + +- (BOOL)isDefault { + return xmlTextReaderIsDefault(_reader); +} + + +- (BOOL)isEmptyElement { + return xmlTextReaderIsEmptyElement(_reader); +} + + +- (NSString *)localName { + xmlChar *c = xmlTextReaderLocalName(_reader); + if (c) { + return [NSString stringWithXmlChar:c]; + } + return nil; +} + + +- (NSString *)name { + xmlChar *c = xmlTextReaderName(_reader); + if (c) { + return [NSString stringWithXmlChar:c]; + } + return nil; +} + + +- (NSString *)namespaceURI { + xmlChar *c = xmlTextReaderNamespaceUri(_reader); + if (c) { + return [NSString stringWithXmlChar:c]; + } + return nil; +} + + +#pragma mark - +#pragma mark Methods + +- (XMLReaderNodeType)nodeType { + return xmlTextReaderNodeType(_reader); +} + + +- (NSString *)prefix { + return [NSString stringWithXmlChar:xmlTextReaderPrefix(_reader)]; +} + + +- (char)quoteChar { + return xmlTextReaderQuoteChar(_reader); +} + + +- (XMLReaderReadState)readState { + return xmlTextReaderReadState(_reader); +} + + +- (NSString *)value { + return [NSString stringWithXmlChar:xmlTextReaderValue(_reader)]; +} + + +- (NSString *)XMLLang { + return [NSString stringWithXmlChar:xmlTextReaderXmlLang(_reader)]; +} + + +- (void)close { + xmlTextReaderClose(_reader); +} + + +- (NSString *)attributeAtIndex:(NSInteger)index { + return [NSString stringWithXmlChar:xmlTextReaderGetAttributeNo(_reader, index)]; +} + + +- (NSString *)attributeWithQName:(NSString *)qName { + return [NSString stringWithXmlChar:xmlTextReaderGetAttribute(_reader, [qName xmlChar])]; +} + + +- (NSString *)attributeWithLocalName:(NSString *)localName namespaceURI:(NSString *)nsURI { + return [NSString stringWithXmlChar:xmlTextReaderGetAttributeNs(_reader, [localName xmlChar], [nsURI xmlChar])]; +} + + ++ (BOOL)isName:(NSString *)str { + return YES; +} + + ++ (BOOL)isNameToken:(NSString *)str { + return YES; +} + + +- (NSString *)lookupNamespace:(NSString *)prefix { + return [NSString stringWithXmlChar:xmlTextReaderLookupNamespace(_reader, [prefix xmlChar])]; +} + + +- (void)moveToAttributeAtIndex:(NSInteger)index { + xmlTextReaderMoveToAttributeNo(_reader, index); +} + + +- (BOOL)moveToAttributeWithQName:(NSString *)qName { + return xmlTextReaderMoveToAttribute(_reader, [qName xmlChar]); +} + + +- (BOOL)moveToAttributeWithLocalName:(NSString *)localName namespaceURI:(NSString *)nsURI { + return xmlTextReaderMoveToAttributeNs(_reader, [localName xmlChar], [nsURI xmlChar]); +} + + +- (BOOL)moveToElement { + return xmlTextReaderMoveToElement(_reader); +} + + +- (BOOL)moveToFirstAttribute { + return xmlTextReaderMoveToFirstAttribute(_reader); +} + + +- (BOOL)moveToNextAttribute { + return xmlTextReaderMoveToNextAttribute(_reader); +} + + +- (BOOL)read { + return xmlTextReaderRead(_reader); +} + + +- (BOOL)readAttributeValue { + return xmlTextReaderReadAttributeValue(_reader); +} + + +- (NSString *)readElementString { + return [NSString stringWithXmlChar:xmlTextReaderReadString(_reader)]; +} + + +- (NSString *)readInnerXML { + return [NSString stringWithXmlChar:xmlTextReaderReadInnerXml(_reader)]; +} + + +- (NSString *)readOuterXML { + return [NSString stringWithXmlChar:xmlTextReaderReadOuterXml(_reader)]; +} + + +- (NSString *)readString { + return [NSString stringWithXmlChar:xmlTextReaderReadString(_reader)]; +} + + +- (void)skip { + xmlTextReaderNextSibling(_reader); +} + + +// handles warnings encountered while parsing RNG schema +static void rngWarn(XMLReader *self, const char *msg, ...) { + va_list ap; + va_start(ap, msg); + + NSMutableString *str = [NSMutableString stringWithFormat:[NSString stringWithUTF8String:msg], ap]; + NSLog(@"RELAX NG warn: %s", msg); + va_end(ap); + + [str replaceOccurrencesOfString:@"<" + withString:@"<" + options:0 + range:NSMakeRange(0, [str length])]; + + str = [NSString stringWithFormat:@"Warning while parsing RELAX NG schema: %s",msg]; + [self.errorHandler validityWarning:str lineNumber:-1]; +} + + +// handles errors encountered while parsing RNG schema +static void rngErr(XMLReader *self, const char *msg, ...) { + va_list ap; + va_start(ap, msg); + + NSMutableString *str = [NSMutableString stringWithFormat:[NSString stringWithUTF8String:msg], ap]; + NSLog(@"RELAX NG err %@",str); + va_end(ap); + + [str replaceOccurrencesOfString:@"<" + withString:@"<" + options:0 + range:NSMakeRange(0, [str length])]; + + str = [NSString stringWithFormat:@"Error while parsing RELAX NG schema:
%@
",str]; + [self.errorHandler validityError:str lineNumber:-1]; + +} + + +- (NSString *)relaxNGSchemaPath { + return [[relaxNGSchemaPath retain] autorelease]; +} + + +- (void)setRelaxNGSchemaPath:(NSString *)newPath { + if (relaxNGSchemaPath != newPath) { + [relaxNGSchemaPath autorelease]; + relaxNGSchemaPath = [newPath retain]; + + const char *schemafurl = [relaxNGSchemaPath UTF8String]; + + // RELAX NG Parser Context + xmlRelaxNGParserCtxtPtr ctxt = xmlRelaxNGNewParserCtxt(schemafurl); + xmlRelaxNGSetParserErrors(ctxt, + (xmlRelaxNGValidityErrorFunc)rngErr, + (xmlRelaxNGValidityWarningFunc)rngWarn, + (void *)self); + // xmlRelaxNGSetParserStructuredErrors(ctxt, (xmlStructuredErrorFunc)structErr, NULL); + + if (_schema) { + xmlRelaxNGFree(_schema); + _schema = NULL; + } + + NSLog(@"gonna parse schema"); + _schema = xmlRelaxNGParse(ctxt); + NSLog(@"did parse schema"); + xmlRelaxNGFreeParserCtxt(ctxt); + + if (_reader) { + xmlFreeTextReader(_reader); + } + _reader = xmlNewTextReaderFilename([path UTF8String]); + xmlTextReaderSetParserProp(_reader, XML_PARSE_RECOVER, 1); + xmlTextReaderSetParserProp(_reader, XML_PARSE_XINCLUDE, 1); + + xmlTextReaderRelaxNGSetSchema(_reader, _schema); + + xmlTextReaderSetErrorHandler(_reader, (xmlTextReaderErrorFunc)readerErr, (void *)self); + + xmlTextReaderSetStructuredErrorHandler(_reader, (xmlStructuredErrorFunc)structErr, (void *)self); + } + +} + + +- (BOOL)isValid { + return xmlTextReaderIsValid(_reader); +} + +@synthesize path; +@synthesize errorHandler; +@synthesize relaxNGSchemaPath; +@end diff --git a/test/.svn/text-base/XMLReaderTest.h.svn-base b/test/.svn/text-base/XMLReaderTest.h.svn-base new file mode 100644 index 0000000..ee45ee4 --- /dev/null +++ b/test/.svn/text-base/XMLReaderTest.h.svn-base @@ -0,0 +1,16 @@ +// +// XMLReaderTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/18/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" +#import "XMLReader.h" + +@interface XMLReaderTest : SenTestCase { + +} + +@end diff --git a/test/.svn/text-base/XMLReaderTest.m.svn-base b/test/.svn/text-base/XMLReaderTest.m.svn-base new file mode 100644 index 0000000..c2986bb --- /dev/null +++ b/test/.svn/text-base/XMLReaderTest.m.svn-base @@ -0,0 +1,27 @@ +// +// XMLReaderTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/18/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "XMLReaderTest.h" + +@implementation XMLReaderTest + +- (void)test { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"xml"]; + + NSLog(@"\n\npath: %@\n\n", path); + + XMLReader *p = [XMLReader parserWithContentsOfFile:path]; + NSInteger ret = [p read]; + while (ret == 1) { + //NSLog(@"nodeType: %d, name: %@", p.nodeType, p.name); + ret = [p read]; + + } +} + +@end diff --git a/test/.svn/text-base/XPathAssembler.h.svn-base b/test/.svn/text-base/XPathAssembler.h.svn-base new file mode 100644 index 0000000..09080d4 --- /dev/null +++ b/test/.svn/text-base/XPathAssembler.h.svn-base @@ -0,0 +1,19 @@ +// +// XPathAssembler.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/17/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class XPathContext; +@class PKReader; + +@interface XPathAssembler : NSObject { + XPathContext *context; +} +- (void)resetWithReader:(PKReader *)r; +@property (retain) XPathContext *context; +@end diff --git a/test/.svn/text-base/XPathAssembler.m.svn-base b/test/.svn/text-base/XPathAssembler.m.svn-base new file mode 100644 index 0000000..6246aaf --- /dev/null +++ b/test/.svn/text-base/XPathAssembler.m.svn-base @@ -0,0 +1,59 @@ +// +// XPathAssembler.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/17/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "XPathAssembler.h" +#import +#import "XPathContext.h" + +@implementation XPathAssembler + +- (id)init { + if (self = [super init]) { + self.context = [[[XPathContext alloc] init] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.context = nil; + [super dealloc]; +} + + +- (void)resetWithReader:(PKReader *)r { + [context resetWithCurrentNode:nil]; +} + + +- (void)didMatchAxisSpecifier:(PKAssembly *)a { + //NSLog(@"\n\n %s\n\n %@ \n\n", _cmd, a); + + //PKToken *tok = [a pop]; + +} + + +- (void)didMatchNodeTest:(PKAssembly *)a { + //NSLog(@"\n\n %s\n\n %@ \n\n", _cmd, a); +} + + +- (void)didMatchPredicate:(PKAssembly *)a { + //NSLog(@"\n\n %s\n\n %@ \n\n", _cmd, a); +} + +// [4] Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep +- (void)didMatchStep:(PKAssembly *)a { + //NSLog(@"\n\n %s\n\n %@ \n\n", _cmd, a); +} + + + +@synthesize context; +@end diff --git a/test/.svn/text-base/XPathContext.h.svn-base b/test/.svn/text-base/XPathContext.h.svn-base new file mode 100644 index 0000000..78ef26f --- /dev/null +++ b/test/.svn/text-base/XPathContext.h.svn-base @@ -0,0 +1,29 @@ +// +// XPathContext.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/17/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@interface XPathContext : NSObject { + // static context + NSString *baseURIString; + NSMutableDictionary *namespaces; + NSMutableDictionary *variables; + NSMutableDictionary *functions; + + // dynamic context + NSXMLNode *currentNode; + NSXMLNode *contextNode; + NSArray *contextNodeSet; + + // +} +- (void)resetWithCurrentNode:(NSXMLNode *)n; +@property (retain) NSXMLNode *currentNode; +@property (retain) NSXMLNode *contextNode; +@property (retain) NSArray *contextNodeSet; +@end diff --git a/test/.svn/text-base/XPathContext.m.svn-base b/test/.svn/text-base/XPathContext.m.svn-base new file mode 100644 index 0000000..2e4daee --- /dev/null +++ b/test/.svn/text-base/XPathContext.m.svn-base @@ -0,0 +1,37 @@ +// +// XPathContext.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/17/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "XPathContext.h" + +@implementation XPathContext + +- (id)init { + if (self = [super init]) { + } + return self; +} + + +- (void)resetWithCurrentNode:(NSXMLNode *)n { + self.currentNode = n; + self.contextNode = nil; + self.contextNodeSet = nil; +} + + +- (void)dealloc { + self.currentNode = nil; + self.contextNode = nil; + self.contextNodeSet = nil; + [super dealloc]; +} + +@synthesize currentNode; +@synthesize contextNode; +@synthesize contextNodeSet; +@end diff --git a/test/.svn/text-base/XPathParser.h.svn-base b/test/.svn/text-base/XPathParser.h.svn-base new file mode 100644 index 0000000..5ec6458 --- /dev/null +++ b/test/.svn/text-base/XPathParser.h.svn-base @@ -0,0 +1,96 @@ +// +// XPathParser.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class XPathAssembler; +@class PKAssembly; + +@interface XPathParser : PKSequence { + XPathAssembler *xpathAssembler; + PKCollectionParser *locationPath; + PKCollectionParser *absoluteLocationPath; + PKCollectionParser *relativeLocationPath; + PKCollectionParser *step; + PKCollectionParser *axisSpecifier; + PKCollectionParser *axisName; + PKCollectionParser *nodeTest; + PKCollectionParser *predicate; + PKCollectionParser *predicateExpr; + PKCollectionParser *abbreviatedAbsoluteLocationPath; + PKCollectionParser *abbreviatedRelativeLocationPath; + PKCollectionParser *abbreviatedStep; + PKCollectionParser *abbreviatedAxisSpecifier; + PKCollectionParser *expr; + PKCollectionParser *primaryExpr; + PKCollectionParser *functionCall; + PKCollectionParser *argument; + PKCollectionParser *unionExpr; + PKCollectionParser *pathExpr; + PKCollectionParser *filterExpr; + PKCollectionParser *orExpr; + PKCollectionParser *andExpr; + PKCollectionParser *equalityExpr; + PKCollectionParser *relationalExpr; + PKCollectionParser *additiveExpr; + PKCollectionParser *multiplicativeExpr; + PKCollectionParser *unaryExpr; + PKCollectionParser *exprToken; + PKParser *literal; + PKParser *number; + PKCollectionParser *operator; + PKCollectionParser *operatorName; + PKParser *multiplyOperator; + PKParser *functionName; + PKCollectionParser *variableReference; + PKCollectionParser *nameTest; + PKCollectionParser *nodeType; + PKCollectionParser *QName; +} +- (id)parse:(NSString *)s; +- (PKAssembly *)assemblyWithString:(NSString *)s; + +@property (retain) PKCollectionParser *locationPath; +@property (retain) PKCollectionParser *absoluteLocationPath; +@property (retain) PKCollectionParser *relativeLocationPath; +@property (retain) PKCollectionParser *step; +@property (retain) PKCollectionParser *axisSpecifier; +@property (retain) PKCollectionParser *axisName; +@property (retain) PKCollectionParser *nodeTest; +@property (retain) PKCollectionParser *predicate; +@property (retain) PKCollectionParser *predicateExpr; +@property (retain) PKCollectionParser *abbreviatedAbsoluteLocationPath; +@property (retain) PKCollectionParser *abbreviatedRelativeLocationPath; +@property (retain) PKCollectionParser *abbreviatedStep; +@property (retain) PKCollectionParser *abbreviatedAxisSpecifier; +@property (retain) PKCollectionParser *expr; +@property (retain) PKCollectionParser *primaryExpr; +@property (retain) PKCollectionParser *functionCall; +@property (retain) PKCollectionParser *argument; +@property (retain) PKCollectionParser *unionExpr; +@property (retain) PKCollectionParser *pathExpr; +@property (retain) PKCollectionParser *filterExpr; +@property (retain) PKCollectionParser *orExpr; +@property (retain) PKCollectionParser *andExpr; +@property (retain) PKCollectionParser *equalityExpr; +@property (retain) PKCollectionParser *relationalExpr; +@property (retain) PKCollectionParser *additiveExpr; +@property (retain) PKCollectionParser *multiplicativeExpr; +@property (retain) PKCollectionParser *unaryExpr; +@property (retain) PKCollectionParser *exprToken; +@property (retain) PKParser *literal; +@property (retain) PKParser *number; +@property (retain) PKCollectionParser *operator; +@property (retain) PKCollectionParser *operatorName; +@property (retain) PKParser *multiplyOperator; +@property (retain) PKParser *functionName; +@property (retain) PKCollectionParser *variableReference; +@property (retain) PKCollectionParser *nameTest; +@property (retain) PKCollectionParser *nodeType; +@property (retain) PKCollectionParser *QName; +@end diff --git a/test/.svn/text-base/XPathParser.m.svn-base b/test/.svn/text-base/XPathParser.m.svn-base new file mode 100644 index 0000000..2ab9f05 --- /dev/null +++ b/test/.svn/text-base/XPathParser.m.svn-base @@ -0,0 +1,973 @@ +// +// XPathParser.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "XPathParser.h" +//#import "TDNCName.h" + +#import "TDNCNameState.h" +#import "XPathAssembler.h" + +@interface XPathParser () +@property (retain) XPathAssembler *xpathAssembler; +@end + +@implementation XPathParser + +- (id)init { + if (self = [super init]) { + self.xpathAssembler = [[[XPathAssembler alloc] init] autorelease]; + [self add:self.locationPath]; + } + return self; +} + + +- (void)dealloc { + self.xpathAssembler = nil; + self.locationPath = nil; + self.absoluteLocationPath = nil; + self.relativeLocationPath = nil; + self.step = nil; + self.axisSpecifier = nil; + self.axisName = nil; + self.nodeTest = nil; + self.predicate = nil; + self.predicateExpr = nil; + self.abbreviatedAbsoluteLocationPath = nil; + self.abbreviatedRelativeLocationPath = nil; + self.abbreviatedStep = nil; + self.abbreviatedAxisSpecifier = nil; + self.expr = nil; + self.primaryExpr = nil; + self.functionCall = nil; + self.argument = nil; + self.unionExpr = nil; + self.pathExpr = nil; + self.filterExpr = nil; + self.orExpr = nil; + self.andExpr = nil; + self.equalityExpr = nil; + self.relationalExpr = nil; + self.additiveExpr = nil; + self.multiplicativeExpr = nil; + self.unaryExpr = nil; + self.exprToken = nil; + self.literal = nil; + self.number = nil; + self.operator = nil; + self.operatorName = nil; + self.multiplyOperator = nil; + self.functionName = nil; + self.variableReference = nil; + self.nameTest = nil; + self.nodeType = nil; + self.QName = nil; + [super dealloc]; +} + + +- (PKAssembly *)assemblyWithString:(NSString *)s { + PKTokenizer *t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + [t.symbolState add:@"::"]; + [t.symbolState add:@"!="]; + [t.symbolState add:@"<="]; + [t.symbolState add:@">="]; + [t.symbolState add:@".."]; + [t.symbolState add:@"//"]; + [t setTokenizerState:t.wordState from: '_' to: '_']; +// [t setTokenizerState:NCNameState from: 'a' to: 'z']; +// [t setTokenizerState:NCNameState from: 'A' to: 'Z']; +// [t setTokenizerState:NCNameState from:0xc0 to:0xff]; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; +// TDNCNameState *NCNameState = [[[TDNCNameState alloc] init] autorelease]; + + return a; +} + + +- (id)parse:(NSString *)s { + [xpathAssembler resetWithReader:nil]; + PKAssembly *a = [self assemblyWithString:s]; + id result = [self completeMatchFor:a]; + return result; +} + + +// [1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath +- (PKCollectionParser *)locationPath { + //NSLog(@"%s", _cmd); + if (!locationPath) { + self.locationPath = [PKAlternation alternation]; + locationPath.name = @"locationPath"; + + [locationPath add:self.relativeLocationPath]; + [locationPath add:self.absoluteLocationPath]; + } + return locationPath; +} + + +//[2] AbsoluteLocationPath ::= '/' RelativeLocationPath? | AbbreviatedAbsoluteLocationPath +- (PKCollectionParser *)absoluteLocationPath { + //NSLog(@"%s", _cmd); + if (!absoluteLocationPath) { + self.absoluteLocationPath = [PKAlternation alternation]; + absoluteLocationPath.name = @"absoluteLocationPath"; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.relativeLocationPath]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"/"]]; + [s add:a]; + + [absoluteLocationPath add:s]; + [absoluteLocationPath add:self.abbreviatedAbsoluteLocationPath]; + } + return absoluteLocationPath; +} + +#pragma mark - +#pragma mark left recursion + +//[3] RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | AbbreviatedRelativeLocationPath + +// avoiding left recursion by changing to this +//[3] RelativeLocationPath ::= Step SlashStep* | AbbreviatedRelativeLocationPath + +- (PKCollectionParser *)relativeLocationPath { + //NSLog(@"%s", _cmd); + if (!relativeLocationPath) { + self.relativeLocationPath = [PKAlternation alternation]; + relativeLocationPath.name = @"relativeLocationPath"; + + PKSequence *s = [PKSequence sequence]; + [s add:self.step]; + + PKSequence *slashStep = [PKSequence sequence]; + [slashStep add:[PKSymbol symbolWithString:@"/"]]; + [slashStep add:self.step]; + [s add:[PKRepetition repetitionWithSubparser:slashStep]]; + + [relativeLocationPath add:s]; + // TODO this is causing and infinite loop! +// [relativeLocationPath add:self.abbreviatedRelativeLocationPath]; + } + return relativeLocationPath; +} + + +// [4] Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep +- (PKCollectionParser *)step { + NSLog(@"%s", _cmd); + if (!step) { + self.step = [PKAlternation alternation]; + step.name = @"step"; + + PKSequence *s = [PKSequence sequence]; + [s add:self.axisSpecifier]; + [s add:self.nodeTest]; + [s add:[PKRepetition repetitionWithSubparser:self.predicate]]; + + [step add:s]; + [step add:self.abbreviatedStep]; + + [step setAssembler:xpathAssembler selector:@selector(didMatchStep:)]; + } + return step; +} + + +// [5] AxisSpecifier ::= AxisName '::' | AbbreviatedAxisSpecifier +- (PKCollectionParser *)axisSpecifier { + //NSLog(@"%s", _cmd); + if (!axisSpecifier) { + self.axisSpecifier = [PKAlternation alternation]; + axisSpecifier.name = @"axisSpecifier"; + + PKSequence *s = [PKSequence sequence]; + [s add:self.axisName]; + [s add:[PKSymbol symbolWithString:@"::"]]; + + [axisSpecifier add:s]; + [axisSpecifier add:self.abbreviatedAxisSpecifier]; + [axisSpecifier setAssembler:xpathAssembler selector:@selector(didMatchAxisSpecifier:)]; + } + return axisSpecifier; +} + + +// [6] AxisName ::= 'ancestor' | 'ancestor-or-self' | 'attribute' | 'child' | 'descendant' | 'descendant-or-self' +// | 'following' | 'following-sibling' | 'namespace' | 'parent' | 'preceding' | 'preceding-sibling' | 'self' +- (PKCollectionParser *)axisName { + //NSLog(@"%s", _cmd); + if (!axisName) { + self.axisName = [PKAlternation alternation]; + axisName.name = @"axisName"; + [axisName add:[PKLiteral literalWithString:@"ancestor"]]; + [axisName add:[PKLiteral literalWithString:@"ancestor-or-self"]]; + [axisName add:[PKLiteral literalWithString:@"attribute"]]; + [axisName add:[PKLiteral literalWithString:@"child"]]; + [axisName add:[PKLiteral literalWithString:@"descendant"]]; + [axisName add:[PKLiteral literalWithString:@"descendant-or-self"]]; + [axisName add:[PKLiteral literalWithString:@"following"]]; + [axisName add:[PKLiteral literalWithString:@"following-sibling"]]; + [axisName add:[PKLiteral literalWithString:@"preceeding"]]; + [axisName add:[PKLiteral literalWithString:@"preceeding-sibling"]]; + [axisName add:[PKLiteral literalWithString:@"namespace"]]; + [axisName add:[PKLiteral literalWithString:@"parent"]]; + [axisName add:[PKLiteral literalWithString:@"self"]]; + } + return axisName; +} + + +// [7] NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' +- (PKCollectionParser *)nodeTest { + //NSLog(@"%s", _cmd); + if (!nodeTest) { + self.nodeTest = [PKAlternation alternation]; + nodeTest.name = @"nodeTest"; + [nodeTest add:self.nameTest]; + + PKSequence *s = [PKSequence sequence]; + [s add:self.nodeType]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:[PKSymbol symbolWithString:@")"]]; + [nodeTest add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"processing-instruction"]]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:self.literal]; + [s add:[PKSymbol symbolWithString:@")"]]; + [nodeTest add:s]; + } + return nodeTest; +} + + +// [8] Predicate ::= '[' PredicateExpr ']' +- (PKCollectionParser *)predicate { + //NSLog(@"%s", _cmd); + if (!predicate) { + self.predicate = [PKSequence sequence]; + predicate.name = @"predicate"; + [predicate add:[PKSymbol symbolWithString:@"["]]; + [predicate add:self.predicateExpr]; + [predicate add:[PKSymbol symbolWithString:@"]"]]; + } + return predicate; +} + + +// [9] PredicateExpr ::= Expr +- (PKCollectionParser *)predicateExpr { + //NSLog(@"%s", _cmd); + if (!predicateExpr) { + self.predicateExpr = self.expr; + predicateExpr.name = @"predicateExpr"; + } + return predicateExpr; +} + + +// [10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath +- (PKCollectionParser *)abbreviatedAbsoluteLocationPath { + //NSLog(@"%s", _cmd); + if (!abbreviatedAbsoluteLocationPath) { + self.abbreviatedAbsoluteLocationPath = [PKSequence sequence]; + abbreviatedAbsoluteLocationPath.name = @"abbreviatedAbsoluteLocationPath"; + [abbreviatedAbsoluteLocationPath add:[PKSymbol symbolWithString:@"//"]]; + [abbreviatedAbsoluteLocationPath add:self.relativeLocationPath]; + } + return abbreviatedAbsoluteLocationPath; +} + + +// [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step +- (PKCollectionParser *)abbreviatedRelativeLocationPath { + //NSLog(@"%s", _cmd); + if (!abbreviatedRelativeLocationPath) { + self.abbreviatedRelativeLocationPath = [PKSequence sequence]; + abbreviatedRelativeLocationPath.name = @"abbreviatedRelativeLocationPath"; + [abbreviatedRelativeLocationPath add:self.relativeLocationPath]; + [abbreviatedRelativeLocationPath add:[PKSymbol symbolWithString:@"//"]]; + [abbreviatedRelativeLocationPath add:self.step]; + } + return abbreviatedRelativeLocationPath; +} + + +// [12] AbbreviatedStep ::= '.' | '..' +- (PKCollectionParser *)abbreviatedStep { + //NSLog(@"%s", _cmd); + if (!abbreviatedStep) { + self.abbreviatedStep = [PKAlternation alternation]; + abbreviatedStep.name = @"abbreviatedStep"; + [abbreviatedStep add:[PKSymbol symbolWithString:@"."]]; + [abbreviatedStep add:[PKSymbol symbolWithString:@".."]]; + } + return abbreviatedStep; +} + + +// [13] AbbreviatedAxisSpecifier ::= '@'? +- (PKCollectionParser *)abbreviatedAxisSpecifier { + //NSLog(@"%s", _cmd); + if (!abbreviatedAxisSpecifier) { + self.abbreviatedAxisSpecifier = [PKAlternation alternation]; + abbreviatedAxisSpecifier.name = @"abbreviatedAxisSpecifier"; + [abbreviatedAxisSpecifier add:[PKEmpty empty]]; + [abbreviatedAxisSpecifier add:[PKSymbol symbolWithString:@"@"]]; + } + return abbreviatedAxisSpecifier; +} + + +// [14] Expr ::= OrExpr +- (PKCollectionParser *)expr { + //NSLog(@"%s", _cmd); + if (!expr) { + self.expr = self.orExpr; + expr.name = @"expr"; + } + return expr; +} + + +// [15] PrimaryExpr ::= VariableReference +// | '(' Expr ')' +// | Literal +// | Number +// | FunctionCall +- (PKCollectionParser *)primaryExpr { + //NSLog(@"%s", _cmd); + if (!primaryExpr) { + self.primaryExpr = [PKAlternation alternation]; + primaryExpr.name = @"primaryExpr"; + [primaryExpr add:self.variableReference]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:self.expr]; + [s add:[PKSymbol symbolWithString:@")"]]; + [primaryExpr add:s]; + + [primaryExpr add:self.literal]; + [primaryExpr add:self.number]; + [primaryExpr add:self.functionCall]; + } + return primaryExpr; +} + + +// [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' + +// commaArg ::= ',' Argument +// [16] FunctionCall ::= FunctionName '(' ( Argument commaArg* )? ')' +- (PKCollectionParser *)functionCall { + //NSLog(@"%s", _cmd); + if (!functionCall) { + self.functionCall = [PKSequence sequence]; + functionCall.name = @"functionCall"; + [functionCall add:self.functionName]; + [functionCall add:[PKSymbol symbolWithString:@"("]]; + + PKSequence *commaArg = [PKSequence sequence]; + [commaArg add:[PKSymbol symbolWithString:@","]]; + [commaArg add:self.argument]; + + PKSequence *args = [PKSequence sequence]; + [args add:self.argument]; + [args add:[PKRepetition repetitionWithSubparser:commaArg]]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:args]; + + [functionCall add:a]; + [functionCall add:[PKSymbol symbolWithString:@")"]]; + } + return functionCall; +} + + +// [17] Argument ::= Expr +- (PKCollectionParser *)argument { + //NSLog(@"%s", _cmd); + if (!argument) { + self.argument = self.expr; + argument.name = @"argument"; + } + return argument; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [18] UnionExpr ::= PathExpr | UnionExpr '|' PathExpr + +// pipePathExpr :: = | PathExpr +// [18] UnionExpr ::= PathExpr PipePathExpr* +- (PKCollectionParser *)unionExpr { + //NSLog(@"%s", _cmd); + if (!unionExpr) { + self.unionExpr = [PKSequence sequence]; + unionExpr.name = @"unionExpr"; + + PKSequence *pipePathExpr = [PKSequence sequence]; + [pipePathExpr add:[PKSymbol symbolWithString:@"|"]]; + [pipePathExpr add:self.pathExpr]; + + [unionExpr add:self.pathExpr]; + [unionExpr add:[PKRepetition repetitionWithSubparser:pipePathExpr]]; + } + return unionExpr; +} + + +//[19] PathExpr ::= LocationPath +// | FilterExpr +// | FilterExpr '/' RelativeLocationPath +// | FilterExpr '//' RelativeLocationPath +- (PKCollectionParser *)pathExpr { + //NSLog(@"%s", _cmd); + if (!pathExpr) { + self.pathExpr = [PKAlternation alternation]; + pathExpr.name = @"pathExpr"; + [pathExpr add:self.locationPath]; + [pathExpr add:self.filterExpr]; + + PKSequence *s = [PKSequence sequence]; + [s add:self.filterExpr]; + [s add:[PKSymbol symbolWithString:@"/"]]; + [s add:self.relativeLocationPath]; + [pathExpr add:s]; + + s = [PKSequence sequence]; + [s add:self.filterExpr]; + [s add:[PKSymbol symbolWithString:@"//"]]; + [s add:self.relativeLocationPath]; + [pathExpr add:s]; + } + return pathExpr; +} + + +#pragma mark - +#pragma mark Left Recursion???????????? + +// [20] FilterExpr ::= PrimaryExpr | FilterExpr Predicate + + +// [20] FilterExpr ::= PrimaryExpr Predicate? +- (PKCollectionParser *)filterExpr { + //NSLog(@"%s", _cmd); + if (!filterExpr) { + self.filterExpr = [PKSequence sequence]; + filterExpr.name = @"filterExpr"; + [filterExpr add:self.primaryExpr]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.predicate]; + [filterExpr add:a]; + } + return filterExpr; +} + + +#pragma mark - +#pragma mark Left Recursion +// [21] OrExpr ::= AndExpr | OrExpr 'or' AndExpr + +// orAndExpr ::= 'or' AndExpr +// me: AndExpr orAndExpr* +- (PKCollectionParser *)orExpr { + //NSLog(@"%s", _cmd); + if (!orExpr) { + self.orExpr = [PKSequence sequence]; + orExpr.name = @"orExpr"; + + [orExpr add:self.andExpr]; + + PKSequence *orAndExpr = [PKSequence sequence]; + [orAndExpr add:[PKLiteral literalWithString:@"or"]]; + [orAndExpr add:self.andExpr]; + + [orExpr add:[PKRepetition repetitionWithSubparser:orAndExpr]]; + } + return orExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [22] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr + + +// andEqualityExpr +// EqualityExpr andEqualityExpr + +- (PKCollectionParser *)andExpr { + //NSLog(@"%s", _cmd); + if (!andExpr) { + self.andExpr = [PKSequence sequence]; + andExpr.name = @"andExpr"; + [andExpr add:self.equalityExpr]; + + PKSequence *andEqualityExpr = [PKSequence sequence]; + [andEqualityExpr add:[PKLiteral literalWithString:@"and"]]; + [andEqualityExpr add:self.equalityExpr]; + + [andExpr add:[PKRepetition repetitionWithSubparser:andEqualityExpr]]; + } + return andExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [23] EqualityExpr ::= RelationalExpr +// | EqualityExpr '=' RelationalExpr +// | EqualityExpr '!=' RelationalExpr + +// RelationalExpr (equalsRelationalExpr | notEqualsRelationalExpr)? + +- (PKCollectionParser *)equalityExpr { + //NSLog(@"%s", _cmd); + if (!equalityExpr) { + self.equalityExpr = [PKSequence sequence]; + equalityExpr.name = @"equalityExpr"; + [equalityExpr add:self.relationalExpr]; + + PKSequence *equalsRelationalExpr = [PKSequence sequence]; + [equalsRelationalExpr add:[PKSymbol symbolWithString:@"="]]; + [equalsRelationalExpr add:self.relationalExpr]; + + PKSequence *notEqualsRelationalExpr = [PKSequence sequence]; + [notEqualsRelationalExpr add:[PKSymbol symbolWithString:@"!="]]; + [notEqualsRelationalExpr add:self.relationalExpr]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:equalsRelationalExpr]; + [a add:notEqualsRelationalExpr]; + + PKAlternation *a1 = [PKAlternation alternation]; + [a1 add:[PKEmpty empty]]; + [a1 add:a]; + + [equalityExpr add:a1]; + } + return equalityExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [24] RelationalExpr ::= AdditiveExpr +// | RelationalExpr '<' AdditiveExpr +// | RelationalExpr '>' AdditiveExpr +// | RelationalExpr '<=' AdditiveExpr +// | RelationalExpr '>=' AdditiveExpr + +// RelationalExpr = AdditiveExpr (ltAdditiveExpr | gtAdditiveExpr | lteAdditiveExpr | gteAdditiveExpr)? +- (PKCollectionParser *)relationalExpr { + //NSLog(@"%s", _cmd); + if (!relationalExpr) { + + self.relationalExpr = [PKSequence sequence]; + relationalExpr.name = @"relationalExpr"; + [relationalExpr add:self.additiveExpr]; + + PKAlternation *a = [PKAlternation alternation]; + + PKSequence *ltAdditiveExpr = [PKSequence sequence]; + [ltAdditiveExpr add:[PKSymbol symbolWithString:@"<"]]; + [a add:ltAdditiveExpr]; + + PKSequence *gtAdditiveExpr = [PKSequence sequence]; + [gtAdditiveExpr add:[PKSymbol symbolWithString:@">"]]; + [a add:gtAdditiveExpr]; + + PKSequence *lteAdditiveExpr = [PKSequence sequence]; + [lteAdditiveExpr add:[PKSymbol symbolWithString:@"<="]]; + [a add:lteAdditiveExpr]; + + PKSequence *gteAdditiveExpr = [PKSequence sequence]; + [gteAdditiveExpr add:[PKSymbol symbolWithString:@">="]]; + [a add:gteAdditiveExpr]; + + PKAlternation *a1 = [PKAlternation alternation]; + [a1 add:[PKEmpty empty]]; + [a1 add:a]; + + [relationalExpr add:a1]; + } + return relationalExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [25] AdditiveExpr ::= MultiplicativeExpr +// | AdditiveExpr '+' MultiplicativeExpr +// | AdditiveExpr '-' MultiplicativeExpr + +// AdditiveExpr ::= MultiplicativeExpr (plusMultiplicativeExpr | minusMultiplicativeExpr)? +- (PKCollectionParser *)additiveExpr { + //NSLog(@"%s", _cmd); + if (!additiveExpr) { + self.additiveExpr = [PKSequence sequence]; + additiveExpr.name = @"additiveExpr"; + [additiveExpr add:self.multiplicativeExpr]; + + PKAlternation *a = [PKAlternation alternation]; + + PKSequence *plusMultiplicativeExpr = [PKSequence sequence]; + [plusMultiplicativeExpr add:[PKSymbol symbolWithString:@"+"]]; + [plusMultiplicativeExpr add:self.multiplicativeExpr]; + [a add:plusMultiplicativeExpr]; + + PKSequence *minusMultiplicativeExpr = [PKSequence sequence]; + [minusMultiplicativeExpr add:[PKSymbol symbolWithString:@"-"]]; + [minusMultiplicativeExpr add:self.multiplicativeExpr]; + [a add:minusMultiplicativeExpr]; + + PKAlternation *a1 = [PKAlternation alternation]; + [a1 add:[PKEmpty empty]]; + [a1 add:a]; + + [additiveExpr add:a1]; + } + return additiveExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [26] MultiplicativeExpr ::= UnaryExpr +// | MultiplicativeExpr MultiplyOperator UnaryExpr +// | MultiplicativeExpr 'div' UnaryExpr +// | MultiplicativeExpr 'mod' UnaryExpr + +// MultiplicativeExpr :: = UnaryExpr (multiplyUnaryExpr | divUnaryExpr | modUnaryExpr)? +- (PKCollectionParser *)multiplicativeExpr { + //NSLog(@"%s", _cmd); + if (!multiplicativeExpr) { + self.multiplicativeExpr = [PKSequence sequence]; + multiplicativeExpr.name = @"multiplicativeExpr"; + [multiplicativeExpr add:self.unaryExpr]; + + PKAlternation *a = [PKAlternation alternation]; + + PKSequence *multiplyUnaryExpr = [PKSequence sequence]; + [multiplyUnaryExpr add:self.multiplyOperator]; + [multiplyUnaryExpr add:self.unaryExpr]; + [a add:multiplyUnaryExpr]; + + PKSequence *divUnaryExpr = [PKSequence sequence]; + [divUnaryExpr add:[PKLiteral literalWithString:@"div"]]; + [divUnaryExpr add:self.unaryExpr]; + [a add:divUnaryExpr]; + + PKSequence *modUnaryExpr = [PKSequence sequence]; + [modUnaryExpr add:[PKLiteral literalWithString:@"mod"]]; + [modUnaryExpr add:self.unaryExpr]; + [a add:modUnaryExpr]; + + PKAlternation *a1 = [PKAlternation alternation]; + [a1 add:[PKEmpty empty]]; + [a1 add:a]; + + [multiplicativeExpr add:a1]; + } + return multiplicativeExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [27] UnaryExpr ::= UnionExpr | '-' UnaryExpr + +// UnaryExpr ::= '-'? UnionExpr +- (PKCollectionParser *)unaryExpr { + //NSLog(@"%s", _cmd); + if (!unaryExpr) { + self.unaryExpr = [PKSequence sequence]; + unaryExpr.name = @"unaryExpr"; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:[PKSymbol symbolWithString:@"-"]]; + + [unaryExpr add:a]; + [unaryExpr add:self.unionExpr]; + + // self.unaryExpr = [PKAlternation alternation]; +// [unaryExpr add:self.unionExpr]; +// +// PKSequence *s = [PKSequence sequence]; +// [s add:[PKSymbol symbolWithString:@"-"]]; +// [s add:unaryExpr]; +// [unionExpr add:s]; + } + return unaryExpr; +} + + +// [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' +// | NameTest +// | NodeType +// | Operator +// | FunctionName +// | AxisName +// | Literal +// | Number +// | VariableReference +- (PKCollectionParser *)exprToken { + //NSLog(@"%s", _cmd); + if (!exprToken) { + self.exprToken = [PKAlternation alternation]; + exprToken.name = @"exprToken"; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKSymbol symbolWithString:@"("]]; + [a add:[PKSymbol symbolWithString:@")"]]; + [a add:[PKSymbol symbolWithString:@"["]]; + [a add:[PKSymbol symbolWithString:@"]"]]; + [a add:[PKSymbol symbolWithString:@"."]]; + [a add:[PKSymbol symbolWithString:@".."]]; + [a add:[PKSymbol symbolWithString:@"@"]]; + [a add:[PKSymbol symbolWithString:@","]]; + [a add:[PKSymbol symbolWithString:@"::"]]; + [exprToken add:a]; + + [exprToken add:self.nameTest]; + [exprToken add:self.nodeType]; + [exprToken add:self.operator]; + [exprToken add:self.functionName]; + [exprToken add:self.axisName]; + [exprToken add:self.literal]; + [exprToken add:self.number]; + [exprToken add:self.variableReference]; + } + return exprToken; +} + + +- (PKParser *)literal { + //NSLog(@"%s", _cmd); + if (!literal) { + self.literal = [PKQuotedString quotedString]; + literal.name = @"literal"; + } + return literal; +} + + +- (PKParser *)number { + //NSLog(@"%s", _cmd); + if (!number) { + self.number = [PKNumber number]; + number.name = @"number"; + } + return number; +} + + +// [32] Operator ::= OperatorName +// | MultiplyOperator +// | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' +- (PKCollectionParser *)operator { + //NSLog(@"%s", _cmd); + if (!operator) { + self.operator = [PKAlternation alternation]; + operator.name = @"operator"; + [operator add:self.operatorName]; + [operator add:self.multiplyOperator]; + [operator add:[PKSymbol symbolWithString: @"/"]]; + [operator add:[PKSymbol symbolWithString:@"//"]]; + [operator add:[PKSymbol symbolWithString: @"|"]]; + [operator add:[PKSymbol symbolWithString: @"+"]]; + [operator add:[PKSymbol symbolWithString: @"-"]]; + [operator add:[PKSymbol symbolWithString: @"="]]; + [operator add:[PKSymbol symbolWithString:@"!="]]; + [operator add:[PKSymbol symbolWithString: @"<"]]; + [operator add:[PKSymbol symbolWithString:@"<="]]; + [operator add:[PKSymbol symbolWithString: @">"]]; + [operator add:[PKSymbol symbolWithString:@">="]]; + } + return operator; +} + + +// [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div' +- (PKCollectionParser *)operatorName { + //NSLog(@"%s", _cmd); + if (!operatorName) { + self.operatorName = [PKAlternation alternation]; + operatorName.name = @"operatorName"; + [operatorName add:[PKLiteral literalWithString:@"and"]]; + [operatorName add:[PKLiteral literalWithString: @"or"]]; + [operatorName add:[PKLiteral literalWithString:@"mod"]]; + [operatorName add:[PKLiteral literalWithString:@"div"]]; + } + return operatorName; +} + + +// [34] MultiplyOperator ::= '*' +- (PKParser *)multiplyOperator { + //NSLog(@"%s", _cmd); + if (!multiplyOperator) { + self.multiplyOperator = [PKSymbol symbolWithString:@"*"]; + multiplyOperator.name = @"multiplyOperator"; + } + return multiplyOperator; +} + + +//[7] QName ::= PrefixedName| UnprefixedName +//[8] PrefixedName ::= Prefix ':' LocalPart +//[9] UnprefixedName ::= LocalPart +//[10] Prefix ::= NCName +//[11] LocalPart ::= NCName +- (PKCollectionParser *)QName { + //NSLog(@"%s", _cmd); + if (!QName) { + self.QName = [PKAlternation alternation]; + QName.name = @"QName"; + + PKParser *prefix = [PKWord word]; + PKParser *localPart = [PKWord word]; + PKParser *unprefixedName = localPart; + + PKSequence *prefixedName = [PKSequence sequence]; + [prefixedName add:prefix]; + [prefixedName add:[PKSymbol symbolWithString:@":"]]; + [prefixedName add:localPart]; + + [QName add:prefixedName]; + [QName add:unprefixedName]; + } + return QName; +} + + +// [35] FunctionName ::= QName - NodeType +- (PKParser *)functionName { + //NSLog(@"%s", _cmd); + if (!functionName) { + self.functionName = self.QName; // TODO QName - NodeType + functionName.name = @"functionName"; + } + return functionName; +} + + +// [36] VariableReference ::= '$' QName +- (PKCollectionParser *)variableReference { + //NSLog(@"%s", _cmd); + if (!variableReference) { + self.variableReference = [PKSequence sequence]; + variableReference.name = @"variableReference"; + [variableReference add:[PKSymbol symbolWithString:@"$"]]; + [variableReference add:self.QName]; + } + return variableReference; +} + + +// [37] NameTest ::= '*' | NCName ':' '*' | QName +- (PKCollectionParser *)nameTest { + //NSLog(@"%s", _cmd); + if (!nameTest) { + self.nameTest = [PKAlternation alternation]; + nameTest.name = @"nameTest"; + [nameTest add:[PKSymbol symbolWithString:@"*"]]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKWord word]]; + [s add:[PKSymbol symbolWithString:@":"]]; + [s add:[PKSymbol symbolWithString:@"*"]]; + [nameTest add:s]; + + [nameTest add:self.QName]; + } + return nameTest; +} + + +// [38] NodeType ::= 'comment' +// | 'text' +// | 'processing-instruction' +// | 'node' +- (PKCollectionParser *)nodeType { + //NSLog(@"%s", _cmd); + if (!nodeType) { + self.nodeType = [PKAlternation alternation]; + nodeType.name = @"nodeType"; + [nodeType add:[PKLiteral literalWithString:@"comment"]]; + [nodeType add:[PKLiteral literalWithString:@"text"]]; + [nodeType add:[PKLiteral literalWithString:@"processing-instruction"]]; + [nodeType add:[PKLiteral literalWithString:@"node"]]; + } + return nodeType; +} + +@synthesize xpathAssembler; +@synthesize locationPath; +@synthesize absoluteLocationPath; +@synthesize relativeLocationPath; +@synthesize step; +@synthesize axisSpecifier; +@synthesize axisName; +@synthesize nodeTest; +@synthesize predicate; +@synthesize predicateExpr; +@synthesize abbreviatedAbsoluteLocationPath; +@synthesize abbreviatedRelativeLocationPath; +@synthesize abbreviatedStep; +@synthesize abbreviatedAxisSpecifier; +@synthesize expr; +@synthesize primaryExpr; +@synthesize functionCall; +@synthesize argument; +@synthesize unionExpr; +@synthesize pathExpr; +@synthesize filterExpr; +@synthesize orExpr; +@synthesize andExpr; +@synthesize equalityExpr; +@synthesize relationalExpr; +@synthesize additiveExpr; +@synthesize multiplicativeExpr; +@synthesize unaryExpr; +@synthesize exprToken; +@synthesize literal; +@synthesize number; +@synthesize operator; +@synthesize operatorName; +@synthesize multiplyOperator; +@synthesize functionName; +@synthesize variableReference; +@synthesize nameTest; +@synthesize nodeType; +@synthesize QName; +@end diff --git a/test/.svn/text-base/XPathParserGrammarTest.h.svn-base b/test/.svn/text-base/XPathParserGrammarTest.h.svn-base new file mode 100644 index 0000000..3a5c6a2 --- /dev/null +++ b/test/.svn/text-base/XPathParserGrammarTest.h.svn-base @@ -0,0 +1,20 @@ +// +// XPathParserGrammarTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/28/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +@interface XPathParserGrammarTest : SenTestCase { + NSString *s; + PKParser *p; + PKTokenizer *t; + PKAssembly *a; + PKAssembly *res; + PKToken *tok; +} + +@end diff --git a/test/.svn/text-base/XPathParserGrammarTest.m.svn-base b/test/.svn/text-base/XPathParserGrammarTest.m.svn-base new file mode 100644 index 0000000..e59443f --- /dev/null +++ b/test/.svn/text-base/XPathParserGrammarTest.m.svn-base @@ -0,0 +1,286 @@ +// +// XPathParserGrammarTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/28/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "XPathParserGrammarTest.h" + +@implementation XPathParserGrammarTest + +- (void)setUp { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xpath1_0" ofType:@"grammar"]; + NSString *g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + p = [[PKParserFactory factory] parserFromGrammar:g assembler:nil]; + t = p.tokenizer; +} + + +- (void)testFoo { + t.string = @"foo"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNotNil(res); + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)test { + t.string = @"child::foo"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + // NSLog(@"\n\n res: %@ \n\n", res); + //TDEqualObjects(@"[/, foo]//foo^", [res description]); + + + t.string = @"/foo"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; +// NSLog(@"\n\n res: %@ \n\n", res); + TDEqualObjects(@"[/, foo]//foo^", [res description]); + + t.string = @"/foo/bar"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar]//foo///bar^", [res description]); + + t.string = @"/foo/bar/baz"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, /, baz]//foo///bar///baz^", [res description]); + + t.string = @"/foo/bar[baz]"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, [, baz, ]]//foo///bar/[/baz/]^", [res description]); + + t.string = @"/foo/bar[@baz]"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, [, @, baz, ]]//foo///bar/[/@/baz/]^", [res description]); + + t.string = @"/foo/bar[@baz='foo']"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, [, @, baz, =, 'foo', ]]//foo///bar/[/@/baz/=/'foo'/]^", [res description]); + + t.string = @"/foo/bar[baz]/foo"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, [, baz, ], /, foo]//foo///bar/[/baz/]///foo^", [res description]); + + // not supported + t.string = @"//foo"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + NSLog(@"\n\n res: %@ \n\n", res); + TDEqualObjects(@"[//, foo]///foo^", [res description]); +} + + +- (void)testAxisName { + t.string = @"child"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"axisName"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[child]child^", [res description]); + + t.string = @"preceding-sibling"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"axisName"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[preceding-sibling]preceding-sibling^", [res description]); +} + + +- (void)testAxisSpecifier { + t.string = @"child::"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"axisSpecifier"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[child, ::]child/::^", [res description]); + t.string = @"preceding-sibling::"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"axisSpecifier"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[preceding-sibling, ::]preceding-sibling/::^", [res description]); +} + + +- (void)testQName { + t.string = @"foo:bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"qName"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [res description]); + + t.string = @"foo:bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + //TDAssertThrowsSpecificNamed([p.QName bestMatchFor:a], [NSException class], @"PKTrackException"); +} + + +- (void)testNameTest { + t.string = @"foo:bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [res description]); + + t.string = @"*"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[*]*^", [res description]); + + t.string = @"foo:*"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, :, *]foo/:/*^", [res description]); + + t.string = @"*:bar"; // NOT ALLOWED + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[*]*^:/bar", [res description]); + + t.string = @"foo"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo]foo^", [res description]); + + t.string = @"foo:bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + //TDAssertThrowsSpecificNamed([p.nameTest bestMatchFor:a], [NSException class], @"PKTrackException"); +} + + +- (void)testNodeType { + t.string = @"comment"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeType"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[comment]comment^", [res description]); + + t.string = @"node"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeType"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[node]node^", [res description]); + +} + + +- (void)testNodeTest { + t.string = @"comment()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[comment, (, )]comment/(/)^", [res description]); + + t.string = @"processing-instruction()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[processing-instruction, (, )]processing-instruction/(/)^", [res description]); + + t.string = @"processing-instruction('baz')"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[processing-instruction, (, 'baz', )]processing-instruction/(/'baz'/)^", [res description]); + + t.string = @"node()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[node, (, )]node/(/)^", [res description]); + + t.string = @"text()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[text, (, )]text/(/)^", [res description]); + + t.string = @"*"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[*]*^", [res description]); + + t.string = @"foo:*"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, :, *]foo/:/*^", [res description]); + + t.string = @"bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[bar]bar^", [res description]); +} + + +- (void)testVariableReference { + t.string = @"$foo"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + p = [p parserNamed:@"pathExpr"]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[$, foo]$/foo^", [res description]); + + t.string = @"$bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + p = [p parserNamed:@"pathExpr"]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[$, bar]$/bar^", [res description]); +} + + +- (void)testFunctionCall { + t.string = @"foo()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, )]foo/(/)^", [res description]); + + t.string = @"foo('bar')"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, 'bar', )]foo/(/'bar'/)^", [res description]); + + t.string = @"foo('bar', 'baz')"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, 'bar', ,, 'baz', )]foo/(/'bar'/,/'baz'/)^", [res description]); + + t.string = @"foo('bar', 1)"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, 'bar', ,, 1, )]foo/(/'bar'/,/1/)^", [res description]); +} + +- (void)testOrExpr { + t.string = @"foo or bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"orExpr"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, or, bar]foo/or/bar^", [res description]); +} + + +- (void)testAndExpr { + t.string = @"foo() and bar()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"andExpr"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, ), and, bar, (, )]foo/(/)/and/bar/(/)^", [res description]); + + t.string = @"foo and bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"andExpr"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, and, bar]foo/and/bar^", [res description]); +} + +@end diff --git a/test/.svn/text-base/XPathParserTest.h.svn-base b/test/.svn/text-base/XPathParserTest.h.svn-base new file mode 100644 index 0000000..a1686f5 --- /dev/null +++ b/test/.svn/text-base/XPathParserTest.h.svn-base @@ -0,0 +1,20 @@ +// +// XPathParserTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +#import "XPathParser.h" + +@interface XPathParserTest : SenTestCase { + NSString *s; + XPathParser *p; + PKAssembly *a; + PKAssembly *result; +} + +@end diff --git a/test/.svn/text-base/XPathParserTest.m.svn-base b/test/.svn/text-base/XPathParserTest.m.svn-base new file mode 100644 index 0000000..0333ce4 --- /dev/null +++ b/test/.svn/text-base/XPathParserTest.m.svn-base @@ -0,0 +1,303 @@ +// +// XPathParserTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 8/16/08. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "XPathParserTest.h" +#import "TDNCName.h" + +@implementation XPathParserTest + +- (void)setUp { + p = [[[XPathParser alloc] init] autorelease]; +} + +- (void)test { + s = @"child::foo"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; +// NSLog(@"\n\n result: %@ \n\n", result); + //TDEqualObjects(@"[/, foo]//foo^", [result description]); + + + s = @"/foo"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + NSLog(@"\n\n result: %@ \n\n", result); + TDEqualObjects(@"[/, foo]//foo^", [result description]); + + s = @"/foo/bar"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar]//foo///bar^", [result description]); + + s = @"/foo/bar/baz"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, /, baz]//foo///bar///baz^", [result description]); + + s = @"/foo/bar[baz]"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, [, baz, ]]//foo///bar/[/baz/]^", [result description]); + + s = @"/foo/bar[@baz]"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, [, @, baz, ]]//foo///bar/[/@/baz/]^", [result description]); + + s = @"/foo/bar[@baz='foo']"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, [, @, baz, =, 'foo', ]]//foo///bar/[/@/baz/=/'foo'/]^", [result description]); + + s = @"/foo/bar[baz]/foo"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, [, baz, ], /, foo]//foo///bar/[/baz/]///foo^", [result description]); + + // not supported +// s = @"//foo"; +// a = [p assemblyWithString:s]; +// result = [p bestMatchFor:a]; +// NSLog(@"\n\n result: %@ \n\n", result); +// TDEqualObjects(@"[//, foo]///foo^", [result description]); +} + + +- (void)testAxisName { + s = @"child"; + a = [p assemblyWithString:s]; + NSLog(@"\n\n a: %@ \n\n", a); + result = [p.axisName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[child]child^", [result description]); + + s = @"preceeding-sibling"; + a = [p assemblyWithString:s]; + result = [p.axisName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[preceeding-sibling]preceeding-sibling^", [result description]); +} + + +- (void)testAxisSpecifier { + s = @"child::"; + a = [p assemblyWithString:s]; + result = [p.axisSpecifier bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[child, ::]child/::^", [result description]); + s = @"preceeding-sibling::"; + a = [p assemblyWithString:s]; + result = [p.axisSpecifier bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[preceeding-sibling, ::]preceeding-sibling/::^", [result description]); +} + + +- (void)testOperatorName { + s = @"and"; + a = [p assemblyWithString:s]; + result = [p.operatorName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[and]and^", [result description]); + + s = @"or"; + a = [p assemblyWithString:s]; + result = [p.operatorName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[or]or^", [result description]); +} + + +- (void)testQName { + s = @"foo:bar"; + a = [p assemblyWithString:s]; + result = [p.QName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [result description]); + + s = @"foo:bar"; + a = [p assemblyWithString:s]; + //TDAssertThrowsSpecificNamed([p.QName bestMatchFor:a], [NSException class], @"PKTrackException"); +} + + +- (void)testNameTest { + s = @"foo:bar"; + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [result description]); + + s = @"*"; + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[*]*^", [result description]); + + s = @"foo:*"; + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, :, *]foo/:/*^", [result description]); + + s = @"*:bar"; // NOT ALLOWED + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[*]*^:/bar", [result description]); + + s = @"foo"; + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo]foo^", [result description]); + + s = @"foo:bar"; + a = [p assemblyWithString:s]; + //TDAssertThrowsSpecificNamed([p.nameTest bestMatchFor:a], [NSException class], @"PKTrackException"); +} + + +- (void)testNodeType { + s = @"comment"; + a = [p assemblyWithString:s]; + result = [p.nodeType bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[comment]comment^", [result description]); + + s = @"node"; + a = [p assemblyWithString:s]; + result = [p.nodeType bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[node]node^", [result description]); + +} + + +- (void)testNodeTest { + s = @"comment()"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[comment, (, )]comment/(/)^", [result description]); + + s = @"processing-instruction()"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[processing-instruction, (, )]processing-instruction/(/)^", [result description]); + + s = @"processing-instruction('baz')"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[processing-instruction, (, 'baz', )]processing-instruction/(/'baz'/)^", [result description]); + + s = @"node()"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[node, (, )]node/(/)^", [result description]); + + s = @"text()"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[text, (, )]text/(/)^", [result description]); + + s = @"*"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[*]*^", [result description]); + + s = @"foo:*"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, :, *]foo/:/*^", [result description]); + + s = @"bar"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[bar]bar^", [result description]); +} + + +- (void)testVariableReference { + s = @"$foo"; + a = [p assemblyWithString:s]; + result = [p.variableReference bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[$, foo]$/foo^", [result description]); + + s = @"$bar"; + a = [p assemblyWithString:s]; + result = [p.variableReference bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[$, bar]$/bar^", [result description]); + + s = @"$foo:bar"; + a = [p assemblyWithString:s]; + result = [p.variableReference bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[$, foo, :, bar]$/foo/:/bar^", [result description]); +} + + +- (void)testFunctionCall { + s = @"foo()"; + a = [p assemblyWithString:s]; + result = [p.functionCall bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, )]foo/(/)^", [result description]); + + s = @"foo('bar')"; + a = [p assemblyWithString:s]; + result = [p.functionCall bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, 'bar', )]foo/(/'bar'/)^", [result description]); + + s = @"foo('bar', 'baz')"; + a = [p assemblyWithString:s]; + result = [p.functionCall bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, 'bar', ,, 'baz', )]foo/(/'bar'/,/'baz'/)^", [result description]); + + s = @"foo('bar', 1)"; + a = [p assemblyWithString:s]; + result = [p.functionCall bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, 'bar', ,, 1, )]foo/(/'bar'/,/1/)^", [result description]); +} + +- (void)testOrExpr { + s = @"foo or bar"; + a = [p assemblyWithString:s]; + result = [p.orExpr bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, or, bar]foo/or/bar^", [result description]); +} + + +- (void)testAndExpr { + s = @"foo() and bar()"; + a = [p assemblyWithString:s]; + result = [p.andExpr bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, ), and, bar, (, )]foo/(/)/and/bar/(/)^", [result description]); + + s = @"foo and bar"; + a = [p assemblyWithString:s]; + result = [p.andExpr bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, and, bar]foo/and/bar^", [result description]); +} + +@end diff --git a/test/.svn/tmp/tempfile.2.tmp b/test/.svn/tmp/tempfile.2.tmp new file mode 100644 index 0000000..be16b06 --- /dev/null +++ b/test/.svn/tmp/tempfile.2.tmp @@ -0,0 +1,2392 @@ +// +// TDJavaScriptParser.m +// TDParseKit +// +// Created by Todd Ditchendorf on 3/17/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "TDJavaScriptParser.h" + +@interface TDParser () +- (void)setTokenizer:(TDTokenizer *)t; +@end + +@interface TDJavaScriptParser () +- (TDAlternation *)zeroOrOne:(TDParser *)p; +- (TDAlternation *)oneOrMore:(TDParser *)p; +@end + +@implementation TDJavaScriptParser + +- (id)init { + if (self = [super initWithSubparser:self.elementParser]) { + self.tokenizer = [TDTokenizer tokenizer]; + + // JS supports scientific number notation (exponents like 4E+12 or 2.0e-42) + tokenizer.numberState = [[[TDScientificNumberState alloc] init] autorelease]; + + // Nums cannot end with '.' (e.g. 32. must be 32.0) + tokenizer.numberState.allowsTrailingDot = NO; + + [tokenizer setTokenizerState:tokenizer.numberState from:'-' to:'-']; + [tokenizer setTokenizerState:tokenizer.numberState from:'.' to:'.']; + [tokenizer setTokenizerState:tokenizer.numberState from:'0' to:'9']; + + // Words can start with '_' + [tokenizer setTokenizerState:tokenizer.wordState from:'_' to:'_']; + + // Words cannot contain '-' + [tokenizer.wordState setWordChars:NO from:'-' to:'-']; + + // Comments + tokenizer.commentState.reportsCommentTokens = YES; + [tokenizer setTokenizerState:tokenizer.commentState from:'/' to:'/']; + + // single-line Comments + [tokenizer.commentState addSingleLineStartMarker:@"//"]; + + // multi-line Comments + [tokenizer.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + [tokenizer.symbolState add:@"||"]; + [tokenizer.symbolState add:@"&&"]; + [tokenizer.symbolState add:@"!="]; + [tokenizer.symbolState add:@"!=="]; + [tokenizer.symbolState add:@"=="]; + [tokenizer.symbolState add:@"==="]; + [tokenizer.symbolState add:@"<="]; + [tokenizer.symbolState add:@">="]; + [tokenizer.symbolState add:@"++"]; + [tokenizer.symbolState add:@"--"]; + [tokenizer.symbolState add:@"+="]; + [tokenizer.symbolState add:@"-="]; + [tokenizer.symbolState add:@"*="]; + [tokenizer.symbolState add:@"/="]; + [tokenizer.symbolState add:@"%="]; + [tokenizer.symbolState add:@"<<"]; + [tokenizer.symbolState add:@">>"]; + [tokenizer.symbolState add:@">>>"]; + [tokenizer.symbolState add:@"<<="]; + [tokenizer.symbolState add:@">>="]; + [tokenizer.symbolState add:@">>>="]; + [tokenizer.symbolState add:@"&="]; + [tokenizer.symbolState add:@"^="]; + } + return self; +} + + +- (void)dealloc { + self.assignmentOpParser = nil; + self.relationalOpParser = nil; + self.equalityOpParser = nil; + self.shiftOpParser = nil; + self.incrementOpParser = nil; + self.unaryOpParser = nil; + self.multiplicativeOpParser = nil; + self.programParser = nil; + self.elementParser = nil; + self.funcParser = nil; + self.paramListOptParser = nil; + self.paramListParser = nil; + self.commaIdentifierParser = nil; + self.compoundStmtParser = nil; + self.stmtsParser = nil; + self.stmtParser = nil; + self.ifStmtParser = nil; + self.ifElseStmtParser = nil; + self.whileStmtParser = nil; + self.forParenStmtParser = nil; + self.forBeginStmtParser = nil; + self.forInStmtParser = nil; + self.breakStmtParser = nil; + self.continueStmtParser = nil; + self.withStmtParser = nil; + self.returnStmtParser = nil; + self.variablesOrExprStmtParser = nil; + self.conditionParser = nil; + self.forParenParser = nil; + self.forBeginParser = nil; + self.variablesOrExprParser = nil; + self.varVariablesParser = nil; + self.variablesParser = nil; + self.commaVariableParser = nil; + self.variableParser = nil; + self.assignmentParser = nil; + self.exprOptParser = nil; + self.exprParser = nil; + self.commaAssignmentExprParser = nil; + self.assignmentExprParser = nil; + self.assignmentOpConditionalExprParser = nil; + self.conditionalExprParser = nil; + self.ternaryExprParser = nil; + self.orExprParser = nil; + self.orAndExprParser = nil; + self.andExprParser = nil; + self.andBitwiseOrExprParser = nil; + self.bitwiseOrExprParser = nil; + self.pipeBitwiseXorExprParser = nil; + self.bitwiseXorExprParser = nil; + self.caretBitwiseAndExprParser = nil; + self.bitwiseAndExprParser = nil; + self.ampEqualityExprParser = nil; + self.equalityExprParser = nil; + self.equalityOpRelationalExprParser = nil; + self.relationalExprParser = nil; + self.relationalOpShiftExprParser = nil; + self.shiftExprParser = nil; + self.shiftOpAdditiveExprParser = nil; + self.additiveExprParser = nil; + self.plusOrMinusExprParser = nil; + self.plusExprParser = nil; + self.minusExprParser = nil; + self.multiplicativeExprParser = nil; + self.multiplicativeOpUnaryExprParser = nil; + self.unaryExprParser = nil; + self.unaryExpr1Parser = nil; + self.unaryExpr2Parser = nil; + self.unaryExpr3Parser = nil; + self.unaryExpr4Parser = nil; + self.unaryExpr5Parser = nil; + self.unaryExpr6Parser = nil; + self.constructorCallParser = nil; + self.parenArgListOptParenParser = nil; + self.memberExprParser = nil; + self.memberExprExtParser = nil; + self.dotMemberExprParser = nil; + self.bracketMemberExprParser = nil; + self.argListOptParser = nil; + self.argListParser = nil; + self.primaryExprParser = nil; + self.parenExprParenParser = nil; + + self.funcLiteralParser = nil; + self.arrayLiteralParser = nil; + self.objectLiteralParser = nil; + + self.identifierParser = nil; + self.stringParser = nil; + self.numberParser = nil; + + self.ifParser = nil; + self.elseParser = nil; + self.whileParser = nil; + self.forParser = nil; + self.inParser = nil; + self.breakParser = nil; + self.continueParser = nil; + self.withParser = nil; + self.returnParser = nil; + self.varParser = nil; + self.deleteParser = nil; + self.newParser = nil; + self.thisParser = nil; + self.falseParser = nil; + self.trueParser = nil; + self.nullParser = nil; + self.undefinedParser = nil; + self.voidParser = nil; + self.typeofParser = nil; + self.instanceofParser = nil; + self.functionParser = nil; + + self.orParser = nil; + self.andParser = nil; + self.neParser = nil; + self.isNotParser = nil; + self.eqParser = nil; + self.isParser = nil; + self.leParser = nil; + self.geParser = nil; + self.plusPlusParser = nil; + self.minusMinusParser = nil; + self.plusEqParser = nil; + self.minusEqParser = nil; + self.timesEqParser = nil; + self.divEqParser = nil; + self.modEqParser = nil; + self.shiftLeftParser = nil; + self.shiftRightParser = nil; + self.shiftRightExtParser = nil; + self.shiftLeftEqParser = nil; + self.shiftRightEqParser = nil; + self.shiftRightExtEqParser = nil; + self.andEqParser = nil; + self.xorEqParser = nil; + self.orEqParser = nil; + + self.openCurlyParser = nil; + self.closeCurlyParser = nil; + self.openParenParser = nil; + self.closeParenParser = nil; + self.openBracketParser = nil; + self.closeBracketParser = nil; + self.commaParser = nil; + self.dotParser = nil; + self.semiOptParser = nil; + self.semiParser = nil; + self.colonParser = nil; + self.equalsParser = nil; + self.notParser = nil; + self.ltParser = nil; + self.gtParser = nil; + self.ampParser = nil; + self.pipeParser = nil; + self.caretParser = nil; + self.tildeParser = nil; + self.questionParser = nil; + self.plusParser = nil; + self.minusParser = nil; + self.timesParser = nil; + self.divParser = nil; + self.modParser = nil; + + [super dealloc]; +} + + +- (TDAlternation *)zeroOrOne:(TDParser *)p { + TDAlternation *a = [TDAlternation alternation]; + [a add:[TDEmpty empty]]; + [a add:p]; + return a; +} + + +- (TDAlternation *)oneOrMore:(TDParser *)p { + TDAlternation *s = [TDSequence sequence]; + [s add:p]; + [s add:[TDRepetition repetitionWithSubparser:p]]; + return s; +} + + +// assignmentOperator = equals | plusEq | minusEq | timesEq | divEq | modEq | shiftLeftEq | shiftRightEq | shiftRightExtEq | andEq | xorEq | orEq; +- (TDCollectionParser *)assignmentOpParser { + if (!assignmentOpParser) { + self.assignmentOpParser = [TDAlternation alternation]; + assignmentOpParser.name = @"assignmentOperator"; + [assignmentOpParser add:self.equalsParser]; + [assignmentOpParser add:self.plusEqParser]; + [assignmentOpParser add:self.minusEqParser]; + [assignmentOpParser add:self.timesEqParser]; + [assignmentOpParser add:self.divEqParser]; + [assignmentOpParser add:self.modEqParser]; + [assignmentOpParser add:self.shiftLeftEqParser]; + [assignmentOpParser add:self.shiftRightEqParser]; + [assignmentOpParser add:self.shiftRightExtEqParser]; + [assignmentOpParser add:self.andEqParser]; + [assignmentOpParser add:self.orEqParser]; + [assignmentOpParser add:self.xorEqParser]; + } + return assignmentOpParser; +} + + +// relationalOperator = lt | gt | ge | le | instanceof; +- (TDCollectionParser *)relationalOpParser { + if (!relationalOpParser) { + self.relationalOpParser = [TDAlternation alternation]; + relationalOpParser.name = @"relationalOperator"; + [relationalOpParser add:self.ltParser]; + [relationalOpParser add:self.gtParser]; + [relationalOpParser add:self.geParser]; + [relationalOpParser add:self.leParser]; + [relationalOpParser add:self.instanceofParser]; + } + return relationalOpParser; +} + + +// equalityOp = eq | ne | is | isnot; +- (TDCollectionParser *)equalityOpParser { + if (!equalityOpParser) { + self.equalityOpParser = [TDAlternation alternation];; + equalityOpParser.name = @"equalityOp"; + [equalityOpParser add:self.eqParser]; + [equalityOpParser add:self.neParser]; + [equalityOpParser add:self.isParser]; + [equalityOpParser add:self.isNotParser]; + } + return equalityOpParser; +} + + +//shiftOp = shiftLeft | shiftRight | shiftRightExt; +- (TDCollectionParser *)shiftOpParser { + if (!shiftOpParser) { + self.shiftOpParser = [TDAlternation alternation]; + shiftOpParser.name = @"shiftOp"; + [shiftOpParser add:self.shiftLeftParser]; + [shiftOpParser add:self.shiftRightParser]; + [shiftOpParser add:self.shiftRightExtParser]; + } + return shiftOpParser; +} + + +//incrementOperator = plusPlus | minusMinus; +- (TDCollectionParser *)incrementOpParser { + if (!incrementOpParser) { + self.incrementOpParser = [TDAlternation alternation]; + incrementOpParser.name = @"incrementOp"; + [incrementOpParser add:self.plusPlusParser]; + [incrementOpParser add:self.minusMinusParser]; + } + return incrementOpParser; +} + + +//unaryOperator = tilde | delete | typeof | void; +- (TDCollectionParser *)unaryOpParser { + if (!unaryOpParser) { + self.unaryOpParser = [TDAlternation alternation]; + unaryOpParser.name = @"unaryOp"; + [unaryOpParser add:self.tildeParser]; + [unaryOpParser add:self.deleteParser]; + [unaryOpParser add:self.typeofParser]; + [unaryOpParser add:self.voidParser]; + } + return unaryOpParser; +} + + +// multiplicativeOperator = times | div | mod; +- (TDCollectionParser *)multiplicativeOpParser { + if (!multiplicativeOpParser) { + self.multiplicativeOpParser = [TDAlternation alternation]; + multiplicativeOpParser.name = @"multiplicativeOperator"; + [multiplicativeOpParser add:self.timesParser]; + [multiplicativeOpParser add:self.divParser]; + [multiplicativeOpParser add:self.modParser]; + } + return multiplicativeOpParser; +} + + + +// Program: +// empty +// Element Program +// +//program = element*; +- (TDCollectionParser *)programParser { + if (!programParser) { + self.programParser = [TDRepetition repetitionWithSubparser:self.elementParser]; + programParser.name = @"program"; + } + return programParser; +} + + +// Element: +// function Identifier ( ParameterListOpt ) CompoundStatement +// Statement +// +//element = func | stmt; +- (TDCollectionParser *)elementParser { + if (!elementParser) { + self.elementParser = [TDAlternation alternation]; + elementParser.name = @"element"; + [elementParser add:self.funcParser]; + [elementParser add:self.stmtParser]; + } + return elementParser; +} + + +//func = function identifier openParen paramListOpt closeParen compoundStmt; +- (TDCollectionParser *)funcParser { + if (!funcParser) { + self.funcParser = [TDSequence sequence]; + funcParser.name = @"func"; + [funcParser add:self.functionParser]; + [funcParser add:self.identifierParser]; + [funcParser add:self.openParenParser]; + [funcParser add:self.paramListOptParser]; + [funcParser add:self.closeParenParser]; + [funcParser add:self.compoundStmtParser]; + } + return funcParser; +} + + +// ParameterListOpt: +// empty +// ParameterList +// +//paramListOpt = Empty | paramList; +- (TDCollectionParser *)paramListOptParser { + if (!paramListOptParser) { + self.paramListOptParser = [TDAlternation alternation]; + paramListOptParser.name = @"paramListOpt"; + [paramListOptParser add:[self zeroOrOne:self.paramListParser]]; + } + return paramListOptParser; +} + + +// ParameterList: +// Identifier +// Identifier , ParameterList +// +//paramList = identifier commaIdentifier*; +- (TDCollectionParser *)paramListParser { + if (!paramListParser) { + self.paramListParser = [TDSequence sequence]; + paramListParser.name = @"paramList"; + [paramListParser add:self.identifierParser]; + [paramListParser add:[TDRepetition repetitionWithSubparser:self.commaIdentifierParser]]; + } + return paramListParser; +} + + +//commaIdentifier = comma identifier; +- (TDCollectionParser *)commaIdentifierParser { + if (!commaIdentifierParser) { + self.commaIdentifierParser = [TDSequence sequence]; + commaIdentifierParser.name = @"commaIdentifier"; + [commaIdentifierParser add:self.commaParser]; + [commaIdentifierParser add:self.identifierParser]; + } + return commaIdentifierParser; +} + + +// CompoundStatement: +// { Statements } +// +//compoundStmt = openCurly stmts closeCurly; +- (TDCollectionParser *)compoundStmtParser { + if (!compoundStmtParser) { + self.compoundStmtParser = [TDSequence sequence]; + compoundStmtParser.name = @"compoundStmt"; + [compoundStmtParser add:self.openCurlyParser]; + [compoundStmtParser add:self.stmtsParser]; + [compoundStmtParser add:self.closeCurlyParser]; + } + return compoundStmtParser; +} + + +// Statements: +// empty +// Statement Statements +// +//stmts = stmt*; +- (TDCollectionParser *)stmtsParser { + if (!stmtsParser) { + self.stmtsParser = [TDRepetition repetitionWithSubparser:self.stmtParser]; + stmtsParser.name = @"stmts"; + } + return stmtsParser; +} + + +// Statement: +// ; +// if Condition Statement +// if Condition Statement else Statement +// while Condition Statement +// ForParen ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin in Expression ) Statement +// break ; +// continue ; +// with ( Expression ) Statement +// return ExpressionOpt ; +// CompoundStatement +// VariablesOrExpression ; +// +//stmt = semi | ifStmt | ifElseStmt | whileStmt | forParenStmt | forBeginStmt | forInStmt | breakStmt | continueStmt | withStmt | returnStmt | compoundStmt | variablesOrExprStmt; +- (TDCollectionParser *)stmtParser { + if (!stmtParser) { + self.stmtParser = [TDAlternation alternation]; + stmtParser.name = @"stmt"; + [stmtParser add:self.semiParser]; + [stmtParser add:self.ifStmtParser]; + [stmtParser add:self.ifElseStmtParser]; + [stmtParser add:self.whileStmtParser]; + [stmtParser add:self.forParenStmtParser]; + [stmtParser add:self.forBeginStmtParser]; + [stmtParser add:self.forInStmtParser]; + [stmtParser add:self.breakStmtParser]; + [stmtParser add:self.continueStmtParser]; + [stmtParser add:self.withStmtParser]; + [stmtParser add:self.returnStmtParser]; + [stmtParser add:self.compoundStmtParser]; + [stmtParser add:self.variablesOrExprStmtParser]; + } + return stmtParser; +} + + +// if Condition Statement +//ifStmt = if condition stmt; +- (TDCollectionParser *)ifStmtParser { + if (!ifStmtParser) { + self.ifStmtParser = [TDSequence sequence]; + ifStmtParser.name = @"ifStmt"; + [ifStmtParser add:self.ifParser]; + [ifStmtParser add:self.conditionParser]; + [ifStmtParser add:self.stmtParser]; + } + return ifStmtParser; +} + + +// if Condition Statement else Statement +//ifElseStmt = if condition stmt else stmt; +- (TDCollectionParser *)ifElseStmtParser { + if (!ifElseStmtParser) { + self.ifElseStmtParser = [TDSequence sequence]; + ifElseStmtParser.name = @"ifElseStmt"; + [ifElseStmtParser add:self.ifParser]; + [ifElseStmtParser add:self.conditionParser]; + [ifElseStmtParser add:self.stmtParser]; + [ifElseStmtParser add:self.elseParser]; + [ifElseStmtParser add:self.stmtParser]; + } + return ifElseStmtParser; +} + + +// while Condition Statement +//whileStmt = while condition stmt; +- (TDCollectionParser *)whileStmtParser { + if (!whileStmtParser) { + self.whileStmtParser = [TDSequence sequence]; + whileStmtParser.name = @"whileStmt"; + [whileStmtParser add:self.whileParser]; + [whileStmtParser add:self.conditionParser]; + [whileStmtParser add:self.stmtParser]; + } + return whileStmtParser; +} + + +// ForParen ; ExpressionOpt ; ExpressionOpt ) Statement +//forParenStmt = forParen semi exprOpt semi exprOpt closeParen stmt; +- (TDCollectionParser *)forParenStmtParser { + if (!forParenStmtParser) { + self.forParenStmtParser = [TDSequence sequence]; + forParenStmtParser.name = @"forParenStmt"; + [forParenStmtParser add:self.forParenParser]; + [forParenStmtParser add:self.semiParser]; + [forParenStmtParser add:self.exprOptParser]; + [forParenStmtParser add:self.semiParser]; + [forParenStmtParser add:self.exprOptParser]; + [forParenStmtParser add:self.closeParenParser]; + [forParenStmtParser add:self.stmtParser]; + } + return forParenStmtParser; +} + + +// ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement +//forBeginStmt = forBegin semi exprOpt semi exprOpt closeParen stmt; +- (TDCollectionParser *)forBeginStmtParser { + if (!forBeginStmtParser) { + self.forBeginStmtParser = [TDSequence sequence]; + forBeginStmtParser.name = @"forBeginStmt"; + [forBeginStmtParser add:self.forBeginParser]; + [forBeginStmtParser add:self.semiParser]; + [forBeginStmtParser add:self.exprOptParser]; + [forBeginStmtParser add:self.semiParser]; + [forBeginStmtParser add:self.exprOptParser]; + [forBeginStmtParser add:self.closeParenParser]; + [forBeginStmtParser add:self.stmtParser]; + } + return forBeginStmtParser; +} + + +// ForBegin in Expression ) Statement +//forInStmt = forBegin in expr closeParen stmt; +- (TDCollectionParser *)forInStmtParser { + if (!forInStmtParser) { + self.forInStmtParser = [TDSequence sequence]; + forInStmtParser.name = @"forInStmt"; + [forInStmtParser add:self.forBeginParser]; + [forInStmtParser add:self.inParser]; + [forInStmtParser add:self.exprParser]; + [forInStmtParser add:self.closeParenParser]; + [forInStmtParser add:self.stmtParser]; + } + return forInStmtParser; +} + + +// break ; +//breakStmt = break semi; +- (TDCollectionParser *)breakStmtParser { + if (!breakStmtParser) { + self.breakStmtParser = [TDSequence sequence]; + breakStmtParser.name = @"breakStmt"; + [breakStmtParser add:self.breakParser]; + [breakStmtParser add:self.semiOptParser]; + } + return breakStmtParser; +} + + +//continueStmt = continue semi; +- (TDCollectionParser *)continueStmtParser { + if (!continueStmtParser) { + self.continueStmtParser = [TDSequence sequence]; + continueStmtParser.name = @"continueStmt"; + [continueStmtParser add:self.continueParser]; + [continueStmtParser add:self.semiOptParser]; + } + return continueStmtParser; +} + + +// with ( Expression ) Statement +//withStmt = with openParen expr closeParen stmt; +- (TDCollectionParser *)withStmtParser { + if (!withStmtParser) { + self.withStmtParser = [TDSequence sequence]; + withStmtParser.name = @"withStmt"; + [withStmtParser add:self.withParser]; + [withStmtParser add:self.openParenParser]; + [withStmtParser add:self.exprParser]; + [withStmtParser add:self.closeParenParser]; + [withStmtParser add:self.stmtParser]; + } + return withStmtParser; +} + + +// return ExpressionOpt ; +//returnStmt = return exprOpt semi; +- (TDCollectionParser *)returnStmtParser { + if (!returnStmtParser) { + self.returnStmtParser = [TDSequence sequence]; + returnStmtParser.name = @"returnStmt"; + [returnStmtParser add:self.returnParser]; + [returnStmtParser add:self.exprOptParser]; + [returnStmtParser add:self.semiOptParser]; + } + return returnStmtParser; +} + + +// VariablesOrExpression ; +//variablesOrExprStmt = variablesOrExpr semi; +- (TDCollectionParser *)variablesOrExprStmtParser { + if (!variablesOrExprStmtParser) { + self.variablesOrExprStmtParser = [TDSequence sequence]; + variablesOrExprStmtParser.name = @"variablesOrExprStmt"; + [variablesOrExprStmtParser add:self.variablesOrExprParser]; + [variablesOrExprStmtParser add:self.semiOptParser]; + } + return variablesOrExprStmtParser; +} + + +// Condition: +// ( Expression ) +// +//condition = openParen expr closeParen; +- (TDCollectionParser *)conditionParser { + if (!conditionParser) { + self.conditionParser = [TDSequence sequence]; + conditionParser.name = @"condition"; + [conditionParser add:self.openParenParser]; + [conditionParser add:self.exprParser]; + [conditionParser add:self.closeParenParser]; + } + return conditionParser; +} + + +// ForParen: +// for ( +// +//forParen = for openParen; +- (TDCollectionParser *)forParenParser { + if (!forParenParser) { + self.forParenParser = [TDSequence sequence]; + forParenParser.name = @"forParen"; + [forParenParser add:self.forParser]; + [forParenParser add:self.openParenParser]; + } + return forParenParser; +} + + +// ForBegin: +// ForParen VariablesOrExpression +// +//forBegin = forParen variablesOrExpr; +- (TDCollectionParser *)forBeginParser { + if (!forBeginParser) { + self.forBeginParser = [TDSequence sequence]; + forBeginParser.name = @"forBegin"; + [forBeginParser add:self.forParenParser]; + [forBeginParser add:self.variablesOrExprParser]; + } + return forBeginParser; +} + + +// VariablesOrExpression: +// var Variables +// Expression +// +//variablesOrExpr = varVariables | expr; +- (TDCollectionParser *)variablesOrExprParser { + if (!variablesOrExprParser) { + self.variablesOrExprParser = [TDAlternation alternation]; + variablesOrExprParser.name = @"variablesOrExpr"; + [variablesOrExprParser add:self.varVariablesParser]; + [variablesOrExprParser add:self.exprParser]; + } + return variablesOrExprParser; +} + + +//varVariables = var variables; +- (TDCollectionParser *)varVariablesParser { + if (!varVariablesParser) { + self.varVariablesParser = [TDSequence sequence]; + varVariablesParser.name = @"varVariables"; + [varVariablesParser add:self.varParser]; + [varVariablesParser add:self.variablesParser]; + } + return varVariablesParser; +} + + +// Variables: +// Variable +// Variable , Variables +// +//variables = variable commaVariable*; +- (TDCollectionParser *)variablesParser { + if (!variablesParser) { + self.variablesParser = [TDSequence sequence]; + variablesParser.name = @"variables"; + [variablesParser add:self.variableParser]; + [variablesParser add:[TDRepetition repetitionWithSubparser:self.commaVariableParser]]; + } + return variablesParser; +} + + +//commaVariable = comma variable; +- (TDCollectionParser *)commaVariableParser { + if (!commaVariableParser) { + self.commaVariableParser = [TDSequence sequence]; + commaVariableParser.name = @"commaVariable"; + [commaVariableParser add:self.commaParser]; + [commaVariableParser add:self.variableParser]; + } + return commaVariableParser; +} + + +// Variable: +// Identifier +// Identifier = AssignmentExpression +// +//variable = identifier assignment?; +- (TDCollectionParser *)variableParser { + if (!variableParser) { + self.variableParser = [TDSequence sequence]; + variableParser.name = @"variableParser"; + [variableParser add:self.identifierParser]; + [variableParser add:[self zeroOrOne:self.assignmentParser]]; + } + return variableParser; +} + + +//assignment = equals assignmentExpr; +- (TDCollectionParser *)assignmentParser { + if (!assignmentParser) { + self.assignmentParser = [TDSequence sequence]; + assignmentParser.name = @"assignment"; + [assignmentParser add:self.equalsParser]; + [assignmentParser add:self.assignmentExprParser]; + } + return assignmentParser; +} + + +// ExpressionOpt: +// empty +// Expression +// +// exprOpt = Empty | expr; +- (TDCollectionParser *)exprOptParser { + if (!exprOptParser) { + self.exprOptParser = [self zeroOrOne:self.exprParser]; + exprOptParser.name = @"exprOpt"; + } + return exprOptParser; +} + + +// Expression: +// AssignmentExpression +// AssignmentExpression , Expression +// +//expr = assignmentExpr commaAssignmentExpr*; +- (TDCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [TDSequence sequence]; + exprParser.name = @"exprParser"; + [exprParser add:self.assignmentExprParser]; + [exprParser add:[TDRepetition repetitionWithSubparser:self.commaAssignmentExprParser]]; + } + return exprParser; +} + + +//commaAssignmentExpr = comma assignmentExpr; +- (TDCollectionParser *)commaAssignmentExprParser { + if (!commaAssignmentExprParser) { + self.commaAssignmentExprParser = [TDSequence sequence]; + commaAssignmentExprParser.name = @"commaAssignmentExpr"; + [commaAssignmentExprParser add:self.commaParser]; + [commaAssignmentExprParser add:self.assignmentExprParser]; + } + return commaAssignmentExprParser; +} + + +// AssignmentExpression: +// ConditionalExpression +// ConditionalExpression AssignmentOperator AssignmentExpression +// +// assignmentExpr = conditionalExpr assignmentOpConditionalExpr*; +- (TDCollectionParser *)assignmentExprParser { + if (!assignmentExprParser) { + self.assignmentExprParser = [TDSequence sequence]; + assignmentExprParser.name = @"assignmentExpr"; + [assignmentExprParser add:self.conditionalExprParser]; + [assignmentExprParser add:[TDRepetition repetitionWithSubparser:self.assignmentOpConditionalExprParser]]; + } + return assignmentExprParser; +} + + +// assignmentOpConditionalExpr = assignmentOperator conditionalExpr; +- (TDCollectionParser *)assignmentOpConditionalExprParser { + if (!assignmentOpConditionalExprParser) { + self.assignmentOpConditionalExprParser = [TDSequence sequence]; + assignmentOpConditionalExprParser.name = @"assignmentOpConditionalExpr"; + [assignmentOpConditionalExprParser add:self.assignmentOpParser]; + [assignmentOpConditionalExprParser add:self.conditionalExprParser]; + } + return assignmentOpConditionalExprParser; +} + + +// ConditionalExpression: +// OrExpression +// OrExpression ? AssignmentExpression : AssignmentExpression +// +// conditionalExpr = orExpr ternaryExpr?; +- (TDCollectionParser *)conditionalExprParser { + if (!conditionalExprParser) { + self.conditionalExprParser = [TDSequence sequence]; + conditionalExprParser.name = @"conditionalExpr"; + [conditionalExprParser add:self.orExprParser]; + [conditionalExprParser add:[self zeroOrOne:self.ternaryExprParser]]; + } + return conditionalExprParser; +} + + +// ternaryExpr = question assignmentExpr colon assignmentExpr; +- (TDCollectionParser *)ternaryExprParser { + if (!ternaryExprParser) { + self.ternaryExprParser = [TDSequence sequence]; + ternaryExprParser.name = @"ternaryExpr"; + [ternaryExprParser add:self.questionParser]; + [ternaryExprParser add:self.assignmentExprParser]; + [ternaryExprParser add:self.colonParser]; + [ternaryExprParser add:self.assignmentExprParser]; + } + return ternaryExprParser; +} + + +// OrExpression: +// AndExpression +// AndExpression || OrExpression +// +// orExpr = andExpr orAndExpr*; +- (TDCollectionParser *)orExprParser { + if (!orExprParser) { + self.orExprParser = [TDSequence sequence]; + orExprParser.name = @"orExpr"; + [orExprParser add:self.andExprParser]; + [orExprParser add:[TDRepetition repetitionWithSubparser:self.orAndExprParser]]; + } + return orExprParser; +} + + +// orAndExpr = or andExpr; +- (TDCollectionParser *)orAndExprParser { + if (!orAndExprParser) { + self.orAndExprParser = [TDSequence sequence]; + orAndExprParser.name = @"orAndExpr"; + [orAndExprParser add:self.orParser]; + [orAndExprParser add:self.andExprParser]; + } + return orAndExprParser; +} + + +// AndExpression: +// BitwiseOrExpression +// BitwiseOrExpression && AndExpression +// +// andExpr = bitwiseOrExpr andBitwiseOrExprParser*; +- (TDCollectionParser *)andExprParser { + if (!andExprParser) { + self.andExprParser = [TDSequence sequence]; + andExprParser.name = @"andExpr"; + [andExprParser add:self.bitwiseOrExprParser]; + [andExprParser add:[TDRepetition repetitionWithSubparser:self.andBitwiseOrExprParser]]; + } + return andExprParser; +} + + +// andBitwiseOrExprParser = and bitwiseOrExpr; +- (TDCollectionParser *)andBitwiseOrExprParser { + if (!andBitwiseOrExprParser) { + self.andBitwiseOrExprParser = [TDSequence sequence]; + andBitwiseOrExprParser.name = @"andBitwiseOrExpr"; + [andBitwiseOrExprParser add:self.andParser]; + [andBitwiseOrExprParser add:self.bitwiseOrExprParser]; + } + return andBitwiseOrExprParser; +} + + +// BitwiseOrExpression: +// BitwiseXorExpression +// BitwiseXorExpression | BitwiseOrExpression +// +// bitwiseOrExpr = bitwiseXorExpr pipeBitwiseXorExpr*; +- (TDCollectionParser *)bitwiseOrExprParser { + if (!bitwiseOrExprParser) { + self.bitwiseOrExprParser = [TDSequence sequence]; + bitwiseOrExprParser.name = @"bitwiseOrExpr"; + [bitwiseOrExprParser add:self.bitwiseXorExprParser]; + [bitwiseOrExprParser add:[TDRepetition repetitionWithSubparser:self.pipeBitwiseXorExprParser]]; + } + return bitwiseOrExprParser; +} + + +// pipeBitwiseXorExprParser = pipe bitwiseXorExpr; +- (TDCollectionParser *)pipeBitwiseXorExprParser { + if (!pipeBitwiseXorExprParser) { + self.pipeBitwiseXorExprParser = [TDSequence sequence]; + pipeBitwiseXorExprParser.name = @"pipeBitwiseXorExpr"; + [pipeBitwiseXorExprParser add:self.pipeParser]; + [pipeBitwiseXorExprParser add:self.bitwiseXorExprParser]; + } + return pipeBitwiseXorExprParser; +} + + +// BitwiseXorExpression: +// BitwiseAndExpression +// BitwiseAndExpression ^ BitwiseXorExpression +// +// bitwiseXorExpr = bitwiseAndExpr caretBitwiseAndExpr*; +- (TDCollectionParser *)bitwiseXorExprParser { + if (!bitwiseXorExprParser) { + self.bitwiseXorExprParser = [TDSequence sequence]; + bitwiseXorExprParser.name = @"bitwiseXorExpr"; + [bitwiseXorExprParser add:self.bitwiseAndExprParser]; + [bitwiseXorExprParser add:[TDRepetition repetitionWithSubparser:self.caretBitwiseAndExprParser]]; + } + return bitwiseXorExprParser; +} + + +// caretBitwiseAndExpr = caret bitwiseAndExpr; +- (TDCollectionParser *)caretBitwiseAndExprParser { + if (!caretBitwiseAndExprParser) { + self.caretBitwiseAndExprParser = [TDSequence sequence]; + caretBitwiseAndExprParser.name = @"caretBitwiseAndExpr"; + [caretBitwiseAndExprParser add:self.caretParser]; + [caretBitwiseAndExprParser add:self.bitwiseAndExprParser]; + } + return caretBitwiseAndExprParser; +} + + +// BitwiseAndExpression: +// EqualityExpression +// EqualityExpression & BitwiseAndExpression +// +// bitwiseAndExpr = equalityExpr ampEqualityExpr*; +- (TDCollectionParser *)bitwiseAndExprParser { + if (!bitwiseAndExprParser) { + self.bitwiseAndExprParser = [TDSequence sequence]; + bitwiseAndExprParser.name = @"bitwiseAndExpr"; + [bitwiseAndExprParser add:self.equalityExprParser]; + [bitwiseAndExprParser add:[TDRepetition repetitionWithSubparser:self.ampEqualityExprParser]]; + } + return bitwiseAndExprParser; +} + + +// ampEqualityExpression = amp equalityExpression; +- (TDCollectionParser *)ampEqualityExprParser { + if (!ampEqualityExprParser) { + self.ampEqualityExprParser = [TDSequence sequence]; + ampEqualityExprParser.name = @"ampEqualityExpr"; + [ampEqualityExprParser add:self.ampParser]; + [ampEqualityExprParser add:self.equalityExprParser]; + } + return ampEqualityExprParser; +} + + +// EqualityExpression: +// RelationalExpression +// RelationalExpression EqualityualityOperator EqualityExpression +// +// equalityExpr = relationalExpr equalityOpRelationalExpr*; +- (TDCollectionParser *)equalityExprParser { + if (!equalityExprParser) { + self.equalityExprParser = [TDSequence sequence]; + equalityExprParser.name = @"equalityExpr"; + [equalityExprParser add:self.relationalExprParser]; + [equalityExprParser add:[TDRepetition repetitionWithSubparser:self.equalityOpRelationalExprParser]]; + } + return equalityExprParser; +} + + +// equalityOpRelationalExpr = equalityOp relationalExpr; +- (TDCollectionParser *)equalityOpRelationalExprParser { + if (!equalityOpRelationalExprParser) { + self.equalityOpRelationalExprParser = [TDSequence sequence]; + equalityOpRelationalExprParser.name = @"equalityOpRelationalExpr"; + [equalityOpRelationalExprParser add:self.equalityOpParser]; + [equalityOpRelationalExprParser add:self.relationalExprParser]; + } + return equalityOpRelationalExprParser; +} + + +// RelationalExpression: +// ShiftExpression +// RelationalExpression RelationalationalOperator ShiftExpression +// + +// relationalExpr = shiftExpr relationalOpShiftExpr*; /// TODO ???? +- (TDCollectionParser *)relationalExprParser { + if (!relationalExprParser) { + self.relationalExprParser = [TDSequence sequence]; + relationalExprParser.name = @"relationalExpr"; + [relationalExprParser add:self.shiftExprParser]; + [relationalExprParser add:[TDRepetition repetitionWithSubparser:self.relationalOpShiftExprParser]]; + } + return relationalExprParser; +} + + +// relationalOpShiftExpr = relationalOperator shiftExpr; +- (TDCollectionParser *)relationalOpShiftExprParser { + if (!relationalOpShiftExprParser) { + self.relationalOpShiftExprParser = [TDSequence sequence]; + relationalOpShiftExprParser.name = @"relationalOpShiftExpr"; + [relationalOpShiftExprParser add:self.relationalOpParser]; + [relationalOpShiftExprParser add:self.shiftExprParser]; + } + return relationalOpShiftExprParser; +} + + +// ShiftExpression: +// AdditiveExpression +// AdditiveExpression ShiftOperator ShiftExpression +// +// shiftExpr = additiveExpr shiftOpAdditiveExpr?; +- (TDCollectionParser *)shiftExprParser { + if (!shiftExprParser) { + self.shiftExprParser = [TDSequence sequence]; + shiftExprParser.name = @"shiftExpr"; + [shiftExprParser add:self.additiveExprParser]; + [shiftExprParser add:[TDRepetition repetitionWithSubparser:self.shiftOpAdditiveExprParser]]; + } + return shiftExprParser; +} + + +// shiftOpShiftExpr = shiftOp additiveExpr; +- (TDCollectionParser *)shiftOpAdditiveExprParser { + if (!shiftOpAdditiveExprParser) { + self.shiftOpAdditiveExprParser = [TDSequence sequence]; + shiftOpAdditiveExprParser.name = @"shiftOpShiftExpr"; + [shiftOpAdditiveExprParser add:self.shiftOpParser]; + [shiftOpAdditiveExprParser add:self.additiveExprParser]; + } + return shiftOpAdditiveExprParser; +} + + +// AdditiveExpression: +// MultiplicativeExpression +// MultiplicativeExpression + AdditiveExpression +// MultiplicativeExpression - AdditiveExpression +// +// additiveExpr = multiplicativeExpr plusOrMinusExpr*; +- (TDCollectionParser *)additiveExprParser { + if (!additiveExprParser) { + self.additiveExprParser = [TDSequence sequence]; + additiveExprParser.name = @"additiveExpr"; + [additiveExprParser add:self.multiplicativeExprParser]; + [additiveExprParser add:[TDRepetition repetitionWithSubparser:self.plusOrMinusExprParser]]; + } + return additiveExprParser; +} + + +// plusOrMinusExpr = plusExpr | minusExpr; +- (TDCollectionParser *)plusOrMinusExprParser { + if (!plusOrMinusExprParser) { + self.plusOrMinusExprParser = [TDAlternation alternation]; + plusOrMinusExprParser.name = @"plusOrMinusExpr"; + [plusOrMinusExprParser add:self.plusExprParser]; + [plusOrMinusExprParser add:self.minusExprParser]; + } + return plusOrMinusExprParser; +} + + +// plusExpr = plus multiplicativeExprParser; +- (TDCollectionParser *)plusExprParser { + if (!plusExprParser) { + self.plusExprParser = [TDSequence sequence]; + plusExprParser.name = @"plusExpr"; + [plusExprParser add:self.plusParser]; + [plusExprParser add:self.multiplicativeExprParser]; + } + return plusExprParser; +} + + +// minusExpr = minus multiplicativeExprParser; +- (TDCollectionParser *)minusExprParser { + if (!minusExprParser) { + self.minusExprParser = [TDSequence sequence]; + minusExprParser.name = @"minusExpr"; + [minusExprParser add:self.minusParser]; + [minusExprParser add:self.multiplicativeExprParser]; + } + return minusExprParser; +} + + +// MultiplicativeExpression: +// UnaryExpression +// UnaryExpression MultiplicativeOperator MultiplicativeExpression +// +// multiplicativeExpr = unaryExpr multiplicativeOpUnaryExpr*; +- (TDCollectionParser *)multiplicativeExprParser { + if (!multiplicativeExprParser) { + self.multiplicativeExprParser = [TDSequence sequence]; + multiplicativeExprParser.name = @"multiplicativeExpr"; + [multiplicativeExprParser add:self.unaryExprParser]; + [multiplicativeExprParser add:[TDRepetition repetitionWithSubparser:self.multiplicativeOpUnaryExprParser]]; + } + return multiplicativeExprParser; +} + + +// multiplicativeOpUnaryExpr = multiplicativeOp unaryExpr; +- (TDCollectionParser *)multiplicativeOpUnaryExprParser { + if (!multiplicativeOpUnaryExprParser) { + self.multiplicativeOpUnaryExprParser = [TDSequence sequence]; + multiplicativeOpUnaryExprParser.name = @"multiplicativeOpUnaryExpr"; + [multiplicativeOpUnaryExprParser add:self.multiplicativeOpParser]; + [multiplicativeOpUnaryExprParser add:self.unaryExprParser]; + } + return multiplicativeOpUnaryExprParser; +} + + +// UnaryExpression: +// MemberExpression +// UnaryOperator UnaryExpression +// - UnaryExpression +// IncrementOperator MemberExpression +// MemberExpression IncrementOperator +// new Constructor +// delete MemberExpression +// +// unaryExpr = memberExpr | unaryExpr1 | unaryExpr2 | unaryExpr3 | unaryExpr4 | unaryExpr5 | unaryExpr6; +- (TDCollectionParser *)unaryExprParser { + if (!unaryExprParser) { + self.unaryExprParser = [TDAlternation alternation]; + unaryExprParser.name = @"unaryExpr"; + [unaryExprParser add:self.memberExprParser]; + [unaryExprParser add:self.unaryExpr1Parser]; + [unaryExprParser add:self.unaryExpr2Parser]; + [unaryExprParser add:self.unaryExpr3Parser]; + [unaryExprParser add:self.unaryExpr4Parser]; + [unaryExprParser add:self.unaryExpr5Parser]; + [unaryExprParser add:self.unaryExpr6Parser]; + } + return unaryExprParser; +} + + +// unaryExpr1 = unaryOperator unaryExpr; +- (TDCollectionParser *)unaryExpr1Parser { + if (!unaryExpr1Parser) { + self.unaryExpr1Parser = [TDSequence sequence]; + unaryExpr1Parser.name = @"unaryExpr1"; + [unaryExpr1Parser add:self.unaryOpParser]; + [unaryExpr1Parser add:self.unaryExprParser]; + } + return unaryExpr1Parser; +} + + +// unaryExpr2 = minus unaryExpr; +- (TDCollectionParser *)unaryExpr2Parser { + if (!unaryExpr2Parser) { + self.unaryExpr2Parser = [TDSequence sequence]; + unaryExpr2Parser.name = @"unaryExpr2"; + [unaryExpr2Parser add:self.minusParser]; + [unaryExpr2Parser add:self.unaryExprParser]; + } + return unaryExpr2Parser; +} + + +// unaryExpr3 = incrementOperator memberExpr; +- (TDCollectionParser *)unaryExpr3Parser { + if (!unaryExpr3Parser) { + self.unaryExpr3Parser = [TDSequence sequence]; + unaryExpr3Parser.name = @"unaryExpr3"; + [unaryExpr3Parser add:self.incrementOpParser]; + [unaryExpr3Parser add:self.memberExprParser]; + } + return unaryExpr3Parser; +} + + +// unaryExpr4 = memberExpr incrementOperator; +- (TDCollectionParser *)unaryExpr4Parser { + if (!unaryExpr4Parser) { + self.unaryExpr4Parser = [TDSequence sequence]; + unaryExpr4Parser.name = @"unaryExpr4"; + [unaryExpr4Parser add:self.memberExprParser]; + [unaryExpr4Parser add:self.incrementOpParser]; + } + return unaryExpr4Parser; +} + + +// unaryExpr5 = new constructor; +- (TDCollectionParser *)unaryExpr5Parser { + if (!unaryExpr5Parser) { + self.unaryExpr5Parser = [TDSequence sequence]; + unaryExpr5Parser.name = @"unaryExpr5"; + [unaryExpr5Parser add:self.newParser]; + [unaryExpr5Parser add:self.constructorCallParser]; + } + return unaryExpr5Parser; +} + + +// unaryExpr6 = delete memberExpr; +- (TDCollectionParser *)unaryExpr6Parser { + if (!unaryExpr6Parser) { + self.unaryExpr6Parser = [TDSequence sequence]; + unaryExpr6Parser.name = @"unaryExpr6"; + [unaryExpr6Parser add:self.deleteParser]; + [unaryExpr6Parser add:self.memberExprParser]; + } + return unaryExpr6Parser; +} + + +// ConstructorCall: +// Identifier +// Identifier ( ArgumentListOpt ) +// Identifier . ConstructorCall +// + +// constructorCall = identifier parentArgListOptParent? memberExprExt* +- (TDCollectionParser *)constructorCallParser { + if (!constructorCallParser) { + self.constructorCallParser = [TDSequence sequence]; + constructorCallParser.name = @"constructorCall"; + [constructorCallParser add:self.identifierParser]; + [constructorCallParser add:[self zeroOrOne:self.parenArgListOptParenParser]]; + [constructorCallParser add:[TDRepetition repetitionWithSubparser:self.memberExprExtParser]]; + } + return constructorCallParser; +} + + +// parenArgListParen = openParen argListOpt closeParen; +- (TDCollectionParser *)parenArgListOptParenParser { + if (!parenArgListOptParenParser) { + self.parenArgListOptParenParser = [TDSequence sequence]; + parenArgListOptParenParser.name = @"parenArgListParen"; + [parenArgListOptParenParser add:self.openParenParser]; + [parenArgListOptParenParser add:self.argListOptParser]; + [parenArgListOptParenParser add:self.closeParenParser]; + } + return parenArgListOptParenParser; +} + + +// MemberExpression: +// PrimaryExpression +// PrimaryExpression . MemberExpression +// PrimaryExpression [ Expression ] +// PrimaryExpression ( ArgumentListOpt ) +// +// memberExpr = primaryExpr memberExprExt?; // TODO ?????? +- (TDCollectionParser *)memberExprParser { + if (!memberExprParser) { + self.memberExprParser = [TDSequence sequence]; + memberExprParser.name = @"memberExpr"; + [memberExprParser add:self.primaryExprParser]; + [memberExprParser add:[TDRepetition repetitionWithSubparser:self.memberExprExtParser]]; + } + return memberExprParser; +} + + +// memberExprExt = dotMemberExpr | bracketMemberExpr | parenMemberExpr; +- (TDCollectionParser *)memberExprExtParser { + if (!memberExprExtParser) { + self.memberExprExtParser = [TDAlternation alternation]; + memberExprExtParser.name = @"memberExprExt"; + [memberExprExtParser add:self.dotMemberExprParser]; + [memberExprExtParser add:self.bracketMemberExprParser]; + [memberExprExtParser add:self.parenArgListOptParenParser]; + } + return memberExprExtParser; +} + + +// dotMemberExpr = dot memberExpr; +- (TDCollectionParser *)dotMemberExprParser { + if (!dotMemberExprParser) { + self.dotMemberExprParser = [TDSequence sequence]; + dotMemberExprParser.name = @"dotMemberExpr"; + [dotMemberExprParser add:self.dotParser]; + [dotMemberExprParser add:self.memberExprParser]; + } + return dotMemberExprParser; +} + + +// bracketMemberExpr = openBracket expr closeBracket; +- (TDCollectionParser *)bracketMemberExprParser { + if (!bracketMemberExprParser) { + self.bracketMemberExprParser = [TDSequence sequence]; + bracketMemberExprParser.name = @"bracketMemberExpr"; + [bracketMemberExprParser add:self.openBracketParser]; + [bracketMemberExprParser add:self.exprParser]; + [bracketMemberExprParser add:self.closeBracketParser]; + } + return bracketMemberExprParser; +} + + +// ArgumentListOpt: +// empty +// ArgumentList +// +// argListOpt = argList?; +- (TDCollectionParser *)argListOptParser { + if (!argListOptParser) { + self.argListOptParser = [self zeroOrOne:self.argListParser]; + argListOptParser.name = @"argListOpt"; + } + return argListOptParser; +} + + +// ArgumentList: +// AssignmentExpression +// AssignmentExpression , ArgumentList +// +// argList = assignmentExpr commaAssignmentExpr*; +- (TDCollectionParser *)argListParser { + if (!argListParser) { + self.argListParser = [TDSequence sequence]; + argListParser.name = @"argList"; + [argListParser add:self.assignmentExprParser]; + [argListParser add:[TDRepetition repetitionWithSubparser:self.commaAssignmentExprParser]]; + } + return argListParser; +} + + + // PrimaryExpression: + // ( Expression ) + // funcLiteral + // arrayLiteral + // Identifier + // IntegerLiteral + // FloatingPointLiteral + // StringLiteral + // false + // true + // null + // this +// primaryExpr = parenExprParen | funcLiteral | arrayLiteral | identifier | Num | QuotedString | false | true | null | undefined | this; +- (TDCollectionParser *)primaryExprParser { + if (!primaryExprParser) { + self.primaryExprParser = [TDAlternation alternation]; + primaryExprParser.name = @"primaryExpr"; + [primaryExprParser add:self.parenExprParenParser]; + [primaryExprParser add:self.funcLiteralParser]; + [primaryExprParser add:self.arrayLiteralParser]; + [primaryExprParser add:self.objectLiteralParser]; + [primaryExprParser add:self.identifierParser]; + [primaryExprParser add:self.numberParser]; + [primaryExprParser add:self.stringParser]; + [primaryExprParser add:self.trueParser]; + [primaryExprParser add:self.falseParser]; + [primaryExprParser add:self.nullParser]; + [primaryExprParser add:self.undefinedParser]; // TODO ?? + [primaryExprParser add:self.thisParser]; + } + return primaryExprParser; +} + + + +// parenExprParen = openParen expr closeParen; +- (TDCollectionParser *)parenExprParenParser { + if (!parenExprParenParser) { + self.parenExprParenParser = [TDSequence sequence]; + parenExprParenParser.name = @"parenExprParen"; + [parenExprParenParser add:self.openParenParser]; + [parenExprParenParser add:self.exprParser]; + [parenExprParenParser add:self.closeParenParser]; + } + return parenExprParenParser; +} + + +//funcLiteral = function openParen paramListOpt closeParen compoundStmt; +- (TDCollectionParser *)funcLiteralParser { + if (!funcLiteralParser) { + self.funcLiteralParser = [TDSequence sequence]; + funcLiteralParser.name = @"funcLiteral"; + [funcLiteralParser add:self.functionParser]; + [funcLiteralParser add:self.openParenParser]; + [funcLiteralParser add:self.paramListOptParser]; + [funcLiteralParser add:self.closeParenParser]; + [funcLiteralParser add:self.compoundStmtParser]; + } + return funcLiteralParser; +} + + +//arrayLiteral = '[' arrayContents ']'; +- (TDCollectionParser *)arrayLiteralParser { + if (!arrayLiteralParser) { + self.arrayLiteralParser = [TDTrack track]; + arrayLiteralParser.name = @"arrayLiteralParser"; + + TDSequence *commaPrimaryExpr = [TDSequence sequence]; + [commaPrimaryExpr add:self.commaParser]; + [commaPrimaryExpr add:self.primaryExprParser]; + + TDSequence *arrayContents = [TDSequence sequence]; + [arrayContents add:self.primaryExprParser]; + [arrayContents add:[TDRepetition repetitionWithSubparser:commaPrimaryExpr]]; + + TDAlternation *arrayContentsOpt = [TDAlternation alternation]; + [arrayContentsOpt add:[TDEmpty empty]]; + [arrayContentsOpt add:arrayContents]; + + [arrayLiteralParser add:self.openBracketParser]; + [arrayLiteralParser add:arrayContentsOpt]; + [arrayLiteralParser add:self.closeBracketParser]; + } + return arrayLiteralParser; +} + + +//objectLiteral = '{' objectContentsOpt '}'; +- (TDCollectionParser *)objectLiteralParser { + if (!objectLiteralParser) { + self.objectLiteralParser = [TDSequence sequence]; + objectLiteralParser.name = @"objectLiteralParser"; + + TDSequence *member = [TDSequence sequence]; + [member add:self.identifierParser]; + [member add:self.colonParser]; + [member add:self.primaryExprParser]; + + TDSequence *commaMember = [TDSequence sequence]; + [commaMember add:self.commaParser]; + [commaMember add:member]; + + TDSequence *objectContents = [TDSequence sequence]; + [objectContents add:member]; + [objectContents add:[TDRepetition repetitionWithSubparser:commaMember]]; + + TDAlternation *objectContentsOpt = [TDAlternation alternation]; + [objectContentsOpt add:[TDEmpty empty]]; + [objectContentsOpt add:objectContents]; + + [objectLiteralParser add:self.openCurlyParser]; + [objectLiteralParser add:objectContentsOpt]; + [objectLiteralParser add:self.closeCurlyParser]; + } + return objectLiteralParser; +} + + +// identifier = Word; +- (TDParser *)identifierParser { + if (!identifierParser) { + self.identifierParser = [TDWord word]; + identifierParser.name = @"identifier"; + } + return identifierParser; +} + + +- (TDParser *)stringParser { + if (!stringParser) { + self.stringParser = [TDQuotedString quotedString]; + stringParser.name = @"string"; + } + return stringParser; +} + + +- (TDParser *)numberParser { + if (!numberParser) { + self.numberParser = [TDNum num]; + numberParser.name = @"number"; + } + return numberParser; +} + + +#pragma mark - +#pragma mark keywords + +- (TDParser *)ifParser { + if (!ifParser) { + self.ifParser = [TDLiteral literalWithString:@"if"]; + ifParser.name = @"if"; + } + return ifParser; +} + + +- (TDParser *)elseParser { + if (!elseParser) { + self.elseParser = [TDLiteral literalWithString:@"else"]; + elseParser.name = @"else"; + } + return elseParser; +} + + +- (TDParser *)whileParser { + if (!whileParser) { + self.whileParser = [TDLiteral literalWithString:@"while"]; + whileParser.name = @"while"; + } + return whileParser; +} + + +- (TDParser *)forParser { + if (!forParser) { + self.forParser = [TDLiteral literalWithString:@"for"]; + forParser.name = @"for"; + } + return forParser; +} + + +- (TDParser *)inParser { + if (!inParser) { + self.inParser = [TDLiteral literalWithString:@"in"]; + inParser.name = @"in"; + } + return inParser; +} + + +- (TDParser *)breakParser { + if (!breakParser) { + self.breakParser = [TDLiteral literalWithString:@"break"]; + breakParser.name = @"break"; + } + return breakParser; +} + + +- (TDParser *)continueParser { + if (!continueParser) { + self.continueParser = [TDLiteral literalWithString:@"continue"]; + continueParser.name = @"continue"; + } + return continueParser; +} + + +- (TDParser *)withParser { + if (!withParser) { + self.withParser = [TDLiteral literalWithString:@"with"]; + withParser.name = @"with"; + } + return withParser; +} + + +- (TDParser *)returnParser { + if (!returnParser) { + self.returnParser = [TDLiteral literalWithString:@"return"]; + returnParser.name = @"return"; + } + return returnParser; +} + + +- (TDParser *)varParser { + if (!varParser) { + self.varParser = [TDLiteral literalWithString:@"var"]; + varParser.name = @"var"; + } + return varParser; +} + + +- (TDParser *)deleteParser { + if (!deleteParser) { + self.deleteParser = [TDLiteral literalWithString:@"delete"]; + deleteParser.name = @"delete"; + } + return deleteParser; +} + + +- (TDParser *)newParser { + if (!newParser) { + self.newParser = [TDLiteral literalWithString:@"new"]; + newParser.name = @"new"; + } + return newParser; +} + + +- (TDParser *)thisParser { + if (!thisParser) { + self.thisParser = [TDLiteral literalWithString:@"this"]; + thisParser.name = @"this"; + } + return thisParser; +} + + +- (TDParser *)falseParser { + if (!falseParser) { + self.falseParser = [TDLiteral literalWithString:@"false"]; + falseParser.name = @"false"; + } + return falseParser; +} + + +- (TDParser *)trueParser { + if (!trueParser) { + self.trueParser = [TDLiteral literalWithString:@"true"]; + trueParser.name = @"true"; + } + return trueParser; +} + + +- (TDParser *)nullParser { + if (!nullParser) { + self.nullParser = [TDLiteral literalWithString:@"null"]; + nullParser.name = @"null"; + } + return nullParser; +} + + +- (TDParser *)undefinedParser { + if (!undefinedParser) { + self.undefinedParser = [TDLiteral literalWithString:@"undefined"]; + undefinedParser.name = @"undefined"; + } + return undefinedParser; +} + + +- (TDParser *)voidParser { + if (!voidParser) { + self.voidParser = [TDLiteral literalWithString:@"void"]; + voidParser.name = @"void"; + } + return voidParser; +} + + +- (TDParser *)typeofParser { + if (!typeofParser) { + self.typeofParser = [TDLiteral literalWithString:@"typeof"]; + typeofParser.name = @"typeof"; + } + return typeofParser; +} + + +- (TDParser *)instanceofParser { + if (!instanceofParser) { + self.instanceofParser = [TDLiteral literalWithString:@"instanceof"]; + instanceofParser.name = @"instanceof"; + } + return instanceofParser; +} + + +- (TDParser *)functionParser { + if (!functionParser) { + self.functionParser = [TDLiteral literalWithString:@"function"]; + functionParser.name = @"function"; + } + return functionParser; +} + + +#pragma mark - +#pragma mark single-char symbols + +- (TDParser *)orParser { + if (!orParser) { + self.orParser = [TDSymbol symbolWithString:@"||"]; + orParser.name = @"or"; + } + return orParser; +} + + +- (TDParser *)andParser { + if (!andParser) { + self.andParser = [TDSymbol symbolWithString:@"&&"]; + andParser.name = @"and"; + } + return andParser; +} + + +- (TDParser *)neParser { + if (!neParser) { + self.neParser = [TDSymbol symbolWithString:@"!="]; + neParser.name = @"ne"; + } + return neParser; +} + + +- (TDParser *)isNotParser { + if (!isNotParser) { + self.isNotParser = [TDSymbol symbolWithString:@"!=="]; + isNotParser.name = @"isNot"; + } + return isNotParser; +} + + +- (TDParser *)eqParser { + if (!eqParser) { + self.eqParser = [TDSymbol symbolWithString:@"=="]; + eqParser.name = @"eq"; + } + return eqParser; +} + + +- (TDParser *)isParser { + if (!isParser) { + self.isParser = [TDSymbol symbolWithString:@"==="]; + isParser.name = @"is"; + } + return isParser; +} + + +- (TDParser *)leParser { + if (!leParser) { + self.leParser = [TDSymbol symbolWithString:@"<="]; + leParser.name = @"le"; + } + return leParser; +} + + +- (TDParser *)geParser { + if (!geParser) { + self.geParser = [TDSymbol symbolWithString:@">="]; + geParser.name = @"ge"; + } + return geParser; +} + + +- (TDParser *)plusPlusParser { + if (!plusPlusParser) { + self.plusPlusParser = [TDSymbol symbolWithString:@"++"]; + plusPlusParser.name = @"plusPlus"; + } + return plusPlusParser; +} + + +- (TDParser *)minusMinusParser { + if (!minusMinusParser) { + self.minusMinusParser = [TDSymbol symbolWithString:@"--"]; + minusMinusParser.name = @"minusMinus"; + } + return minusMinusParser; +} + + +- (TDParser *)plusEqParser { + if (!plusEqParser) { + self.plusEqParser = [TDSymbol symbolWithString:@"+="]; + plusEqParser.name = @"plusEq"; + } + return plusEqParser; +} + + +- (TDParser *)minusEqParser { + if (!minusEqParser) { + self.minusEqParser = [TDSymbol symbolWithString:@"-="]; + minusEqParser.name = @"minusEq"; + } + return minusEqParser; +} + + +- (TDParser *)timesEqParser { + if (!timesEqParser) { + self.timesEqParser = [TDSymbol symbolWithString:@"*="]; + timesEqParser.name = @"timesEq"; + } + return timesEqParser; +} + + +- (TDParser *)divEqParser { + if (!divEqParser) { + self.divEqParser = [TDSymbol symbolWithString:@"/="]; + divEqParser.name = @"divEq"; + } + return divEqParser; +} + + +- (TDParser *)modEqParser { + if (!modEqParser) { + self.modEqParser = [TDSymbol symbolWithString:@"%="]; + modEqParser.name = @"modEq"; + } + return modEqParser; +} + + +- (TDParser *)shiftLeftParser { + if (!shiftLeftParser) { + self.shiftLeftParser = [TDSymbol symbolWithString:@"<<"]; + shiftLeftParser.name = @"shiftLeft"; + } + return shiftLeftParser; +} + + +- (TDParser *)shiftRightParser { + if (!shiftRightParser) { + self.shiftRightParser = [TDSymbol symbolWithString:@">>"]; + shiftRightParser.name = @"shiftRight"; + } + return shiftRightParser; +} + + +- (TDParser *)shiftRightExtParser { + if (!shiftRightExtParser) { + self.shiftRightExtParser = [TDSymbol symbolWithString:@">>>"]; + shiftRightExtParser.name = @"shiftRightExt"; + } + return shiftRightExtParser; +} + + +- (TDParser *)shiftLeftEqParser { + if (!shiftLeftEqParser) { + self.shiftLeftEqParser = [TDSymbol symbolWithString:@"<<="]; + shiftLeftEqParser.name = @"shiftLeftEq"; + } + return shiftLeftEqParser; +} + + +- (TDParser *)shiftRightEqParser { + if (!shiftRightEqParser) { + self.shiftRightEqParser = [TDSymbol symbolWithString:@">>="]; + shiftRightEqParser.name = @"shiftRightEq"; + } + return shiftRightEqParser; +} + + +- (TDParser *)shiftRightExtEqParser { + if (!shiftRightExtEqParser) { + self.shiftRightExtEqParser = [TDSymbol symbolWithString:@">>>="]; + shiftRightExtEqParser.name = @"shiftRightExtEq"; + } + return shiftRightExtEqParser; +} + + +- (TDParser *)andEqParser { + if (!andEqParser) { + self.andEqParser = [TDSymbol symbolWithString:@"&="]; + andEqParser.name = @"andEq"; + } + return andEqParser; +} + + +- (TDParser *)xorEqParser { + if (!xorEqParser) { + self.xorEqParser = [TDSymbol symbolWithString:@"^="]; + xorEqParser.name = @"xorEq"; + } + return xorEqParser; +} + + +- (TDParser *)orEqParser { + if (!orEqParser) { + self.orEqParser = [TDSymbol symbolWithString:@"|="]; + orEqParser.name = @"orEq"; + } + return orEqParser; +} + + +#pragma mark - +#pragma mark single-char symbols + +- (TDParser *)openCurlyParser { + if (!openCurlyParser) { + self.openCurlyParser = [TDSymbol symbolWithString:@"{"]; + openCurlyParser.name = @"openCurly"; + } + return openCurlyParser; +} + + +- (TDParser *)closeCurlyParser { + if (!closeCurlyParser) { + self.closeCurlyParser = [TDSymbol symbolWithString:@"}"]; + closeCurlyParser.name = @"closeCurly"; + } + return closeCurlyParser; +} + + +- (TDParser *)openParenParser { + if (!openParenParser) { + self.openParenParser = [TDSymbol symbolWithString:@"("]; + openParenParser.name = @"openParen"; + } + return openParenParser; +} + + +- (TDParser *)closeParenParser { + if (!closeParenParser) { + self.closeParenParser = [TDSymbol symbolWithString:@")"]; + closeParenParser.name = @"closeParen"; + } + return closeParenParser; +} + + +- (TDParser *)openBracketParser { + if (!openBracketParser) { + self.openBracketParser = [TDSymbol symbolWithString:@"["]; + openBracketParser.name = @"openBracket"; + } + return openBracketParser; +} + + +- (TDParser *)closeBracketParser { + if (!closeBracketParser) { + self.closeBracketParser = [TDSymbol symbolWithString:@"]"]; + closeBracketParser.name = @"closeBracket"; + } + return closeBracketParser; +} + + +- (TDParser *)commaParser { + if (!commaParser) { + self.commaParser = [TDSymbol symbolWithString:@","]; + commaParser.name = @"comma"; + } + return commaParser; +} + + +- (TDParser *)dotParser { + if (!dotParser) { + self.dotParser = [TDSymbol symbolWithString:@"."]; + dotParser.name = @"dot"; + } + return dotParser; +} + + +- (TDParser *)semiOptParser { + if (!semiOptParser) { + self.semiOptParser = [self zeroOrOne:self.semiParser]; + semiOptParser.name = @"semiOpt"; + } + return semiOptParser; +} + + +- (TDParser *)semiParser { + if (!semiParser) { + self.semiParser = [TDSymbol symbolWithString:@";"]; + semiParser.name = @"semi"; + } + return semiParser; +} + + +- (TDParser *)colonParser { + if (!colonParser) { + self.colonParser = [TDSymbol symbolWithString:@":"]; + colonParser.name = @"colon"; + } + return colonParser; +} + + +- (TDParser *)equalsParser { + if (!equalsParser) { + self.equalsParser = [TDSymbol symbolWithString:@"="]; + equalsParser.name = @"equals"; + } + return equalsParser; +} + + +- (TDParser *)notParser { + if (!notParser) { + self.notParser = [TDSymbol symbolWithString:@"!"]; + notParser.name = @"not"; + } + return notParser; +} + + +- (TDParser *)ltParser { + if (!ltParser) { + self.ltParser = [TDSymbol symbolWithString:@"<"]; + ltParser.name = @"lt"; + } + return ltParser; +} + + +- (TDParser *)gtParser { + if (!gtParser) { + self.gtParser = [TDSymbol symbolWithString:@">"]; + gtParser.name = @"gt"; + } + return gtParser; +} + + +- (TDParser *)ampParser { + if (!ampParser) { + self.ampParser = [TDSymbol symbolWithString:@"&"]; + ampParser.name = @"amp"; + } + return ampParser; +} + + +- (TDParser *)pipeParser { + if (!pipeParser) { + self.pipeParser = [TDSymbol symbolWithString:@"|"]; + pipeParser.name = @"pipe"; + } + return pipeParser; +} + + +- (TDParser *)caretParser { + if (!caretParser) { + self.caretParser = [TDSymbol symbolWithString:@"^"]; + caretParser.name = @"caret"; + } + return caretParser; +} + + +- (TDParser *)tildeParser { + if (!tildeParser) { + self.tildeParser = [TDSymbol symbolWithString:@"~"]; + tildeParser.name = @"tilde"; + } + return tildeParser; +} + + +- (TDParser *)questionParser { + if (!questionParser) { + self.questionParser = [TDSymbol symbolWithString:@"?"]; + questionParser.name = @"question"; + } + return questionParser; +} + + +- (TDParser *)plusParser { + if (!plusParser) { + self.plusParser = [TDSymbol symbolWithString:@"+"]; + plusParser.name = @"plus"; + } + return plusParser; +} + + +- (TDParser *)minusParser { + if (!minusParser) { + self.minusParser = [TDSymbol symbolWithString:@"-"]; + minusParser.name = @"minus"; + } + return minusParser; +} + + +- (TDParser *)timesParser { + if (!timesParser) { + self.timesParser = [TDSymbol symbolWithString:@"x"]; + timesParser.name = @"times"; + } + return timesParser; +} + + +- (TDParser *)divParser { + if (!divParser) { + self.divParser = [TDSymbol symbolWithString:@"/"]; + divParser.name = @"div"; + } + return divParser; +} + + +- (TDParser *)modParser { + if (!modParser) { + self.modParser = [TDSymbol symbolWithString:@"%"]; + modParser.name = @"mod"; + } + return modParser; +} + +@synthesize assignmentOpParser; +@synthesize relationalOpParser; +@synthesize equalityOpParser; +@synthesize shiftOpParser; +@synthesize incrementOpParser; +@synthesize unaryOpParser; +@synthesize multiplicativeOpParser; + +@synthesize programParser; +@synthesize elementParser; +@synthesize funcParser; +@synthesize paramListOptParser; +@synthesize paramListParser; +@synthesize commaIdentifierParser; +@synthesize compoundStmtParser; +@synthesize stmtsParser; +@synthesize stmtParser; +@synthesize ifStmtParser; +@synthesize ifElseStmtParser; +@synthesize whileStmtParser; +@synthesize forParenStmtParser; +@synthesize forBeginStmtParser; +@synthesize forInStmtParser; +@synthesize breakStmtParser; +@synthesize continueStmtParser; +@synthesize withStmtParser; +@synthesize returnStmtParser; +@synthesize variablesOrExprStmtParser; +@synthesize conditionParser; +@synthesize forParenParser; +@synthesize forBeginParser; +@synthesize variablesOrExprParser; +@synthesize varVariablesParser; +@synthesize variablesParser; +@synthesize commaVariableParser; +@synthesize variableParser; +@synthesize assignmentParser; +@synthesize exprOptParser; +@synthesize exprParser; +@synthesize commaAssignmentExprParser; +@synthesize assignmentExprParser; +@synthesize assignmentOpConditionalExprParser; +@synthesize conditionalExprParser; +@synthesize ternaryExprParser; +@synthesize orExprParser; +@synthesize orAndExprParser; +@synthesize andExprParser; +@synthesize andBitwiseOrExprParser; +@synthesize bitwiseOrExprParser; +@synthesize pipeBitwiseXorExprParser; +@synthesize bitwiseXorExprParser; +@synthesize caretBitwiseAndExprParser; +@synthesize bitwiseAndExprParser; +@synthesize ampEqualityExprParser; +@synthesize equalityExprParser; +@synthesize equalityOpRelationalExprParser; +@synthesize relationalExprParser; +@synthesize relationalOpShiftExprParser; +@synthesize shiftExprParser; +@synthesize shiftOpAdditiveExprParser; +@synthesize additiveExprParser; +@synthesize plusOrMinusExprParser; +@synthesize plusExprParser; +@synthesize minusExprParser; +@synthesize multiplicativeExprParser; +@synthesize multiplicativeOpUnaryExprParser; +@synthesize unaryExprParser; +@synthesize unaryExpr1Parser; +@synthesize unaryExpr2Parser; +@synthesize unaryExpr3Parser; +@synthesize unaryExpr4Parser; +@synthesize unaryExpr5Parser; +@synthesize unaryExpr6Parser; +@synthesize constructorCallParser; +@synthesize parenArgListOptParenParser; +@synthesize memberExprParser; +@synthesize memberExprExtParser; +@synthesize dotMemberExprParser; +@synthesize bracketMemberExprParser; +@synthesize argListOptParser; +@synthesize argListParser; +@synthesize primaryExprParser; +@synthesize parenExprParenParser; + +@synthesize funcLiteralParser; +@synthesize arrayLiteralParser; +@synthesize objectLiteralParser; + +@synthesize identifierParser; +@synthesize stringParser; +@synthesize numberParser; + +@synthesize ifParser; +@synthesize elseParser; +@synthesize whileParser; +@synthesize forParser; +@synthesize inParser; +@synthesize breakParser; +@synthesize continueParser; +@synthesize withParser; +@synthesize returnParser; +@synthesize varParser; +@synthesize deleteParser; +@synthesize newParser; +@synthesize thisParser; +@synthesize falseParser; +@synthesize trueParser; +@synthesize nullParser; +@synthesize undefinedParser; +@synthesize voidParser; +@synthesize typeofParser; +@synthesize instanceofParser; +@synthesize functionParser; + +@synthesize orParser; +@synthesize andParser; +@synthesize neParser; +@synthesize isNotParser; +@synthesize eqParser; +@synthesize isParser; +@synthesize leParser; +@synthesize geParser; +@synthesize plusPlusParser; +@synthesize minusMinusParser; +@synthesize plusEqParser; +@synthesize minusEqParser; +@synthesize timesEqParser; +@synthesize divEqParser; +@synthesize modEqParser; +@synthesize shiftLeftParser; +@synthesize shiftRightParser; +@synthesize shiftRightExtParser; +@synthesize shiftLeftEqParser; +@synthesize shiftRightEqParser; +@synthesize shiftRightExtEqParser; +@synthesize andEqParser; +@synthesize xorEqParser; +@synthesize orEqParser; + +@synthesize openCurlyParser; +@synthesize closeCurlyParser; +@synthesize openParenParser; +@synthesize closeParenParser; +@synthesize openBracketParser; +@synthesize closeBracketParser; +@synthesize commaParser; +@synthesize dotParser; +@synthesize semiOptParser; +@synthesize semiParser; +@synthesize colonParser; +@synthesize equalsParser; +@synthesize notParser; +@synthesize ltParser; +@synthesize gtParser; +@synthesize ampParser; +@synthesize pipeParser; +@synthesize caretParser; +@synthesize tildeParser; +@synthesize questionParser; +@synthesize plusParser; +@synthesize minusParser; +@synthesize timesParser; +@synthesize divParser; +@synthesize modParser; +@end diff --git a/test/.svn/tmp/tempfile.3.tmp b/test/.svn/tmp/tempfile.3.tmp new file mode 100644 index 0000000..d16fef1 --- /dev/null +++ b/test/.svn/tmp/tempfile.3.tmp @@ -0,0 +1,1183 @@ +// +// TDParserFactory.m +// TDParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2008 Todd Ditchendorf All rights reserved. +// + +#import "TDParserFactory.h" +#import +#import "NSString+TDParseKitAdditions.h" +#import "NSArray+TDParseKitAdditions.h" + +@interface TDParser (TDParserFactoryAdditionsFriend) +- (void)setTokenizer:(TDTokenizer *)t; +@end + +@interface TDCollectionParser () +@property (nonatomic, readwrite, retain) NSMutableArray *subparsers; +@end + +@interface TDRepetition () +@property (nonatomic, readwrite, retain) TDParser *subparser; +@end + +void TDReleaseSubparserTree(TDParser *p) { + if ([p isKindOfClass:[TDCollectionParser class]]) { + TDCollectionParser *c = (TDCollectionParser *)p; + NSArray *subs = c.subparsers; + if (subs) { + [subs retain]; + c.subparsers = nil; + for (TDParser *s in subs) { + TDReleaseSubparserTree(s); + } + [subs release]; + } + } else if ([p isMemberOfClass:[TDRepetition class]]) { + TDRepetition *r = (TDRepetition *)p; + TDParser *sub = r.subparser; + if (sub) { + [sub retain]; + r.subparser = nil; + TDReleaseSubparserTree(sub); + [sub release]; + } + } +} + +@interface TDParserFactory () +- (id)parserTokensTableFromParsingStatementsInString:(NSString *)s; +- (void)gatherParserClassNamesFromTokens; +- (NSString *)parserClassNameFromTokenArray:(NSArray *)toks; + +- (TDTokenizer *)tokenizerFromGrammarSettings; +- (BOOL)boolForTokenForKey:(NSString *)key; +- (void)setTokenizerState:(TDTokenizerState *)state onTokenizer:(TDTokenizer *)t forTokensForKey:(NSString *)key; + +- (id)expandParser:(TDParser *)p fromTokenArray:(NSArray *)toks; +- (TDParser *)expandedParserForName:(NSString *)parserName; +- (void)setAssemblerForParser:(TDParser *)p; +- (NSString *)defaultAssemblerSelectorNameForParserName:(NSString *)parserName; + +// this is only for unit tests? can it go away? +- (TDSequence *)parserFromExpression:(NSString *)s; + +- (TDAlternation *)zeroOrOne:(TDParser *)p; +- (TDSequence *)oneOrMore:(TDParser *)p; + +- (void)workOnStatementAssembly:(TDAssembly *)a; +- (NSString *)defaultAssemblerSelectorNameForParserName:(NSString *)parserName; +- (void)workOnCallbackAssembly:(TDAssembly *)a; +- (void)workOnExpressionAssembly:(TDAssembly *)a; +- (void)workOnLiteralAssembly:(TDAssembly *)a; +- (void)workOnVariableAssembly:(TDAssembly *)a; +- (void)workOnConstantAssembly:(TDAssembly *)a; +- (void)workOnNumAssembly:(TDAssembly *)a; +- (void)workOnStarAssembly:(TDAssembly *)a; +- (void)workOnPlusAssembly:(TDAssembly *)a; +- (void)workOnQuestionAssembly:(TDAssembly *)a; +- (void)workOnPhraseCardinalityAssembly:(TDAssembly *)a; +- (void)workOnCardinalityAssembly:(TDAssembly *)a; +- (void)workOnOrAssembly:(TDAssembly *)a; + +@property (nonatomic, assign) id assembler; +@property (nonatomic, retain) NSMutableDictionary *parserTokensTable; +@property (nonatomic, retain) NSMutableDictionary *parserClassTable; +@property (nonatomic, retain) NSMutableDictionary *selectorTable; +@property (nonatomic, retain) TDToken *equals; +@property (nonatomic, retain) TDToken *curly; +@property (nonatomic, retain) TDToken *paren; +@property (nonatomic, retain) TDToken *caret; +@property (nonatomic, retain) TDCollectionParser *statementParser; +@property (nonatomic, retain) TDCollectionParser *declarationParser; +@property (nonatomic, retain) TDCollectionParser *callbackParser; +@property (nonatomic, retain) TDCollectionParser *selectorParser; +@property (nonatomic, retain) TDCollectionParser *expressionParser; +@property (nonatomic, retain) TDCollectionParser *termParser; +@property (nonatomic, retain) TDCollectionParser *orTermParser; +@property (nonatomic, retain) TDCollectionParser *factorParser; +@property (nonatomic, retain) TDCollectionParser *nextFactorParser; +@property (nonatomic, retain) TDCollectionParser *phraseParser; +@property (nonatomic, retain) TDCollectionParser *phraseStarParser; +@property (nonatomic, retain) TDCollectionParser *phrasePlusParser; +@property (nonatomic, retain) TDCollectionParser *phraseQuestionParser; +@property (nonatomic, retain) TDCollectionParser *phraseCardinalityParser; +@property (nonatomic, retain) TDCollectionParser *cardinalityParser; +@property (nonatomic, retain) TDCollectionParser *atomicValueParser; +@property (nonatomic, retain) TDCollectionParser *discardParser; +@property (nonatomic, retain) TDParser *patternParser; +@property (nonatomic, retain) TDParser *literalParser; +@property (nonatomic, retain) TDParser *variableParser; +@property (nonatomic, retain) TDParser *constantParser; +@property (nonatomic, retain) TDCollectionParser *delimitedStringParser; +@end + +@implementation TDParserFactory + ++ (id)factory { + return [[[TDParserFactory alloc] init] autorelease]; +} + + +- (id)init { + if (self = [super init]) { + self.equals = [TDToken tokenWithTokenType:TDTokenTypeSymbol stringValue:@"=" floatValue:0.0]; + self.curly = [TDToken tokenWithTokenType:TDTokenTypeSymbol stringValue:@"{" floatValue:0.0]; + self.paren = [TDToken tokenWithTokenType:TDTokenTypeSymbol stringValue:@"(" floatValue:0.0]; + self.caret = [TDToken tokenWithTokenType:TDTokenTypeSymbol stringValue:@"^" floatValue:0.0]; + self.assemblerSettingBehavior = TDParserFactoryAssemblerSettingBehaviorOnAll; + } + return self; +} + + +- (void)dealloc { + assembler = nil; // appease clang static analyzer + + TDReleaseSubparserTree(statementParser); + TDReleaseSubparserTree(expressionParser); + + self.parserTokensTable = nil; + self.parserClassTable = nil; + self.selectorTable = nil; + self.equals = nil; + self.curly = nil; + self.paren = nil; + self.caret = nil; + self.statementParser = nil; + self.declarationParser = nil; + self.callbackParser = nil; + self.selectorParser = nil; + self.expressionParser = nil; + self.termParser = nil; + self.orTermParser = nil; + self.factorParser = nil; + self.nextFactorParser = nil; + self.phraseParser = nil; + self.phraseStarParser = nil; + self.phrasePlusParser = nil; + self.phraseQuestionParser = nil; + self.phraseCardinalityParser = nil; + self.cardinalityParser = nil; + self.atomicValueParser = nil; + self.patternParser = nil; + self.discardParser = nil; + self.literalParser = nil; + self.variableParser = nil; + self.constantParser = nil; + self.delimitedStringParser = nil; + [super dealloc]; +} + + +- (TDParser *)parserFromGrammar:(NSString *)s assembler:(id)a { + self.assembler = a; + self.selectorTable = [NSMutableDictionary dictionary]; + self.parserClassTable = [NSMutableDictionary dictionary]; + self.parserTokensTable = [self parserTokensTableFromParsingStatementsInString:s]; + + TDTokenizer *t = [self tokenizerFromGrammarSettings]; + + [self gatherParserClassNamesFromTokens]; + + TDParser *start = [self expandedParserForName:@"@start"]; + + assembler = nil; + self.selectorTable = nil; + self.parserClassTable = nil; + self.parserTokensTable = nil; + + if (start && [start isKindOfClass:[TDParser class]]) { + start.tokenizer = t; + return start; + } else { + [NSException raise:@"GrammarException" format:@"The provided language grammar was invalid"]; + return nil; + } +} + + +- (id)parserTokensTableFromParsingStatementsInString:(NSString *)s { + TDTokenizer *t = [TDTokenizer tokenizerWithString:s]; + + // customize tokenizer to find tokenizer customization directives + [t setTokenizerState:t.wordState from:'@' to:'@']; + + // customize tokenizer for Pattern regexes + [t setTokenizerState:t.delimitState from:'/' to:'/']; + [t.delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:[[NSCharacterSet whitespaceCharacterSet] invertedSet]]; + + // customize tokenizer for comments + [t setTokenizerState:t.commentState from:'#' to:'#']; + [t setTokenizerState:t.commentState from:'"' to:'"']; + [t.commentState removeSingleLineStartMarker:@"//"]; + [t.commentState removeMultiLineStartMarker:@"/*"]; + [t.commentState addSingleLineStartMarker:@"#"]; + [t.commentState addMultiLineStartMarker:@"\"\"\"" endMarker:@"\"\"\""]; + + TDTokenArraySource *src = [[TDTokenArraySource alloc] initWithTokenizer:t delimiter:@";"]; + id target = [NSMutableDictionary dictionary]; // setup the variable lookup table + + while ([src hasMore]) { + NSArray *toks = [src nextTokenArray]; + TDAssembly *a = [TDTokenAssembly assemblyWithTokenArray:toks]; + a.target = target; + a = [self.statementParser completeMatchFor:a]; + target = a.target; + } + + [src release]; + + return target; +} + + +- (void)gatherParserClassNamesFromTokens { + isGatheringClasses = YES; + // discover the actual parser class types + for (NSString *parserName in parserTokensTable) { + NSString *className = [self parserClassNameFromTokenArray:[parserTokensTable objectForKey:parserName]]; + NSAssert(className.length, @""); + [parserClassTable setObject:className forKey:parserName]; + } + isGatheringClasses = NO; +} + + +- (NSString *)parserClassNameFromTokenArray:(NSArray *)toks { + TDAssembly *a = [TDTokenAssembly assemblyWithTokenArray:toks]; + a.target = parserTokensTable; + a = [self.expressionParser completeMatchFor:a]; + TDParser *res = [a pop]; + a.target = nil; + return [res className]; +} + + +- (TDTokenizer *)tokenizerFromGrammarSettings { + TDTokenizer *t = [TDTokenizer tokenizer]; + [t.commentState removeSingleLineStartMarker:@"//"]; + [t.commentState removeMultiLineStartMarker:@"/*"]; + + t.whitespaceState.reportsWhitespaceTokens = [self boolForTokenForKey:@"@reportsWhitespaceTokens"]; + t.commentState.reportsCommentTokens = [self boolForTokenForKey:@"@reportsCommentTokens"]; + t.commentState.balancesEOFTerminatedComments = [self boolForTokenForKey:@"balancesEOFTerminatedComments"]; + t.quoteState.balancesEOFTerminatedQuotes = [self boolForTokenForKey:@"@balancesEOFTerminatedQuotes"]; + t.delimitState.balancesEOFTerminatedStrings = [self boolForTokenForKey:@"@balancesEOFTerminatedStrings"]; + t.numberState.allowsTrailingDot = [self boolForTokenForKey:@"@allowsTrailingDot"]; + + [self setTokenizerState:t.wordState onTokenizer:t forTokensForKey:@"@wordState"]; + [parserTokensTable removeObjectForKey:@"@wordState"]; + [self setTokenizerState:t.numberState onTokenizer:t forTokensForKey:@"@numberState"]; + [parserTokensTable removeObjectForKey:@"@numberState"]; + [self setTokenizerState:t.quoteState onTokenizer:t forTokensForKey:@"@quoteState"]; + [parserTokensTable removeObjectForKey:@"@quoteState"]; + [self setTokenizerState:t.delimitState onTokenizer:t forTokensForKey:@"@delimitState"]; + [parserTokensTable removeObjectForKey:@"@delimitState"]; + [self setTokenizerState:t.symbolState onTokenizer:t forTokensForKey:@"@symbolState"]; + [parserTokensTable removeObjectForKey:@"@symbolState"]; + [self setTokenizerState:t.commentState onTokenizer:t forTokensForKey:@"@commentState"]; + [parserTokensTable removeObjectForKey:@"@commentState"]; + [self setTokenizerState:t.whitespaceState onTokenizer:t forTokensForKey:@"@whitespaceState"]; + [parserTokensTable removeObjectForKey:@"@shitespaceState"]; + + NSArray *toks = nil; + + // muli-char symbols + toks = [parserTokensTable objectForKey:@"@symbols"]; + for (TDToken *tok in toks) { + if (tok.isQuotedString) { + [t.symbolState add:[tok.stringValue stringByTrimmingQuotes]]; + } + } + [parserTokensTable removeObjectForKey:@"@symbols"]; + + + // wordChars + toks = [parserTokensTable objectForKey:@"@wordChars"]; + for (TDToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + if (s.length) { + NSInteger c = [s characterAtIndex:0]; + [t.wordState setWordChars:YES from:c to:c]; + } + } + } + [parserTokensTable removeObjectForKey:@"@wordChars"]; + + // whitespaceChars + toks = [parserTokensTable objectForKey:@"@whitespaceChars"]; + for (TDToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + if (s.length) { + NSInteger c = [s characterAtIndex:0]; + [t.whitespaceState setWhitespaceChars:YES from:c to:c]; + } + } + } + [parserTokensTable removeObjectForKey:@"whitespaceChars"]; + + // single-line comments + toks = [parserTokensTable objectForKey:@"@singleLineComments"]; + for (TDToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + [t.commentState addSingleLineStartMarker:s]; + [t.symbolState add:s]; + } + } + [parserTokensTable removeObjectForKey:@"singleLineComments"]; + + // multi-line comments + toks = [parserTokensTable objectForKey:@"@multiLineComments"]; + if (toks.count > 1) { + NSInteger i = 0; + for ( ; i < toks.count - 1; i++) { + TDToken *startTok = [toks objectAtIndex:i]; + TDToken *endTok = [toks objectAtIndex:++i]; + if (startTok.isQuotedString && endTok.isQuotedString) { + NSString *start = [startTok.stringValue stringByTrimmingQuotes]; + NSString *end = [endTok.stringValue stringByTrimmingQuotes]; + [t.commentState addMultiLineStartMarker:start endMarker:end]; + [t.symbolState add:start]; + [t.symbolState add:end]; + } + } + } + [parserTokensTable removeObjectForKey:@"multiLineComments"]; + + // delimited strings + toks = [parserTokensTable objectForKey:@"@delimitedStrings"]; + NSAssert(0 == toks.count % 3, @"@delimitedStrings must be specified as quoted strings in multiples of 3"); + if (toks.count > 1) { + NSInteger i = 0; + for ( ; i < toks.count - 2; i++) { + TDToken *startTok = [toks objectAtIndex:i]; + TDToken *endTok = [toks objectAtIndex:++i]; + TDToken *charSetTok = [toks objectAtIndex:++i]; + if (startTok.isQuotedString && endTok.isQuotedString) { + NSString *start = [startTok.stringValue stringByTrimmingQuotes]; + NSString *end = [endTok.stringValue stringByTrimmingQuotes]; + NSCharacterSet *charSet = nil; + if (charSetTok.isQuotedString) { + charSet = [NSCharacterSet characterSetWithCharactersInString:[charSetTok.stringValue stringByTrimmingQuotes]]; + } + [t.delimitState addStartMarker:start endMarker:end allowedCharacterSet:charSet]; + } + } + } + [parserTokensTable removeObjectForKey:@"@delimitedStrings"]; + + return t; +} + + +- (BOOL)boolForTokenForKey:(NSString *)key { + BOOL result = NO; + NSArray *toks = [parserTokensTable objectForKey:key]; + if (toks.count) { + TDToken *tok = [toks objectAtIndex:0]; + if (tok.isWord && [tok.stringValue isEqualToString:@"YES"]) { + result = YES; + } + } + return result; +} + + +- (void)setTokenizerState:(TDTokenizerState *)state onTokenizer:(TDTokenizer *)t forTokensForKey:(NSString *)key { + NSArray *toks = [parserTokensTable objectForKey:key]; + for (TDToken *tok in toks) { + if (tok.isQuotedString) { + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + if (1 == s.length) { + NSInteger c = [s characterAtIndex:0]; + [t setTokenizerState:state from:c to:c]; + } + } + } +} + + +- (TDParser *)expandedParserForName:(NSString *)parserName { + id obj = [parserTokensTable objectForKey:parserName]; + if ([obj isKindOfClass:[TDParser class]]) { + return obj; + } else { + // prevent infinite loops by creating a parser of the correct type first, and putting it in the table + NSString *className = [parserClassTable objectForKey:parserName]; + + TDParser *p = [[NSClassFromString(className) alloc] init]; + [parserTokensTable setObject:p forKey:parserName]; + [p release]; + + p = [self expandParser:p fromTokenArray:obj]; + p.name = parserName; + + [self setAssemblerForParser:p]; + + [parserTokensTable setObject:p forKey:parserName]; + return p; + } +} + + +- (void)setAssemblerForParser:(TDParser *)p { + NSString *parserName = p.name; + NSString *selName = [selectorTable objectForKey:parserName]; + + BOOL setOnAll = (assemblerSettingBehavior & TDParserFactoryAssemblerSettingBehaviorOnAll); + + if (setOnAll) { + // continue + } else { + BOOL setOnExplicit = (assemblerSettingBehavior & TDParserFactoryAssemblerSettingBehaviorOnExplicit); + if (setOnExplicit && selName) { + // continue + } else { + BOOL isTerminal = [p isKindOfClass:[TDTerminal class]]; + if (!isTerminal && !setOnExplicit) return; + + BOOL setOnTerminals = (assemblerSettingBehavior & TDParserFactoryAssemblerSettingBehaviorOnTerminals); + if (setOnTerminals && isTerminal) { + // continue + } else { + return; + } + } + } + + if (!selName) { + selName = [self defaultAssemblerSelectorNameForParserName:parserName]; + } + + SEL sel = NSSelectorFromString(selName); + if (assembler && [assembler respondsToSelector:sel]) { + [p setAssembler:assembler selector:sel]; + } +} + + +- (id)expandParser:(TDParser *)p fromTokenArray:(NSArray *)toks { + TDAssembly *a = [TDTokenAssembly assemblyWithTokenArray:toks]; + a.target = parserTokensTable; + a = [self.expressionParser completeMatchFor:a]; + TDParser *res = [a pop]; + if ([p isKindOfClass:[TDCollectionParser class]]) { + TDCollectionParser *cp = (TDCollectionParser *)p; + [cp add:res]; + return cp; + } else { + return res; + } +} + + +// this is just a utility for unit-testing +- (TDSequence *)parserFromExpression:(NSString *)s { + TDTokenizer *t = [TDTokenizer tokenizerWithString:s]; + TDAssembly *a = [TDTokenAssembly assemblyWithTokenizer:t]; + a.target = [NSMutableDictionary dictionary]; // setup the variable lookup table + a = [self.expressionParser completeMatchFor:a]; + return [a pop]; +} + + +- (TDAlternation *)zeroOrOne:(TDParser *)p { + TDAlternation *a = [TDAlternation alternation]; + [a add:[TDEmpty empty]]; + [a add:p]; + return a; +} + + +- (TDSequence *)oneOrMore:(TDParser *)p { + TDSequence *s = [TDSequence sequence]; + [s add:p]; + [s add:[TDRepetition repetitionWithSubparser:p]]; + return s; +} + + +// @start = statement* +// satement = declaration '=' expression +// declaration = Word callback? +// callback = '(' selector ')' +// selector = Word ':' +// expression = term orTerm* +// term = factor nextFactor* +// orTerm = '|' term +// factor = phrase | phraseStar | phrasePlus | phraseQuestion | phraseCardinality +// nextFactor = factor +// phrase = atomicValue | '(' expression ')' +// phraseStar = phrase '*' +// phrasePlus = phrase '+' +// phraseQuestion = phrase '?' +// phraseCardinality = phrase cardinality +// cardinality = '{' Num '}' +// atomicValue = discard? (literal | variable | constant | pattern | delimitedString) +// discard = '^' +// literal = QuotedString +// variable = LowercaseWord +// constant = UppercaseWord +// pattern = DelimitedString('/', '/') + + +// satement = declaration '=' expression +- (TDCollectionParser *)statementParser { + if (!statementParser) { + self.statementParser = [TDTrack track]; + statementParser.name = @"statement"; + [statementParser add:self.declarationParser]; + [statementParser add:[TDSymbol symbolWithString:@"="]]; + + // accept any tokens in the parser expr the first time around. just gather tokens for later + [statementParser add:[self oneOrMore:[TDAny any]]]; + [statementParser setAssembler:self selector:@selector(workOnStatementAssembly:)]; + } + return statementParser; +} + + +// declaration = productionName callback? +- (TDCollectionParser *)declarationParser { + if (!declarationParser) { + self.declarationParser = [TDTrack track]; + declarationParser.name = @"declaration"; + [declarationParser add:[TDWord word]]; + [declarationParser add:[self zeroOrOne:self.callbackParser]]; + } + return declarationParser; +} + + +// callback = '(' selector ')' +- (TDCollectionParser *)callbackParser { + if (!callbackParser) { + self.callbackParser = [TDTrack track]; + callbackParser.name = @"callback"; + [callbackParser add:[[TDSymbol symbolWithString:@"("] discard]]; + [callbackParser add:self.selectorParser]; + [callbackParser add:[[TDSymbol symbolWithString:@")"] discard]]; + [callbackParser setAssembler:self selector:@selector(workOnCallbackAssembly:)]; + } + return callbackParser; +} + + +// selector = Word ':' +- (TDCollectionParser *)selectorParser { + if (!selectorParser) { + self.selectorParser = [TDTrack track]; + selectorParser.name = @"selector"; + [selectorParser add:[TDLowercaseWord word]]; + [selectorParser add:[[TDSymbol symbolWithString:@":"] discard]]; + } + return selectorParser; +} + + +// expression = term orTerm* +- (TDCollectionParser *)expressionParser { + if (!expressionParser) { + self.expressionParser = [TDSequence sequence]; + expressionParser.name = @"expression"; + [expressionParser add:self.termParser]; + [expressionParser add:[TDRepetition repetitionWithSubparser:self.orTermParser]]; + [expressionParser setAssembler:self selector:@selector(workOnExpressionAssembly:)]; + } + return expressionParser; +} + + +// term = factor nextFactor* +- (TDCollectionParser *)termParser { + if (!termParser) { + self.termParser = [TDSequence sequence]; + termParser.name = @"term"; + [termParser add:self.factorParser]; + [termParser add:[TDRepetition repetitionWithSubparser:self.nextFactorParser]]; + [termParser setAssembler:self selector:@selector(workOnAndAssembly:)]; + } + return termParser; +} + + +// orTerm = '|' term +- (TDCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [TDTrack track]; + orTermParser.name = @"orTerm"; + [orTermParser add:[TDSymbol symbolWithString:@"|"]]; // preserve as fence + [orTermParser add:self.termParser]; + [orTermParser setAssembler:self selector:@selector(workOnOrAssembly:)]; + } + return orTermParser; +} + + +// factor = phrase | phraseStar | phrasePlus | phraseQuestion | phraseCardinality +- (TDCollectionParser *)factorParser { + if (!factorParser) { + self.factorParser = [TDAlternation alternation]; + factorParser.name = @"factor"; + [factorParser add:self.phraseParser]; + [factorParser add:self.phraseStarParser]; + [factorParser add:self.phrasePlusParser]; + [factorParser add:self.phraseQuestionParser]; + [factorParser add:self.phraseCardinalityParser]; + } + return factorParser; +} + + +// nextFactor = factor +- (TDCollectionParser *)nextFactorParser { + if (!nextFactorParser) { + self.nextFactorParser = [TDAlternation alternation]; + nextFactorParser.name = @"nextFactor"; + [nextFactorParser add:self.phraseParser]; + [nextFactorParser add:self.phraseStarParser]; + [nextFactorParser add:self.phrasePlusParser]; + [nextFactorParser add:self.phraseQuestionParser]; + [nextFactorParser add:self.phraseCardinalityParser]; + } + return nextFactorParser; +} + + +// phrase = atomicValue | '(' expression ')' +- (TDCollectionParser *)phraseParser { + if (!phraseParser) { + self.phraseParser = [TDAlternation alternation]; + phraseParser.name = @"phrase"; + [phraseParser add:self.atomicValueParser]; + + TDSequence *s = [TDSequence sequence]; + [s add:[TDSymbol symbolWithString:@"("]]; + [s add:self.expressionParser]; + [s add:[[TDSymbol symbolWithString:@")"] discard]]; + + [phraseParser add:s]; + } + return phraseParser; +} + + +// phraseStar = phrase '*' +- (TDCollectionParser *)phraseStarParser { + if (!phraseStarParser) { + self.phraseStarParser = [TDSequence sequence]; + phraseStarParser.name = @"phraseStar"; + [phraseStarParser add:self.phraseParser]; + [phraseStarParser add:[[TDSymbol symbolWithString:@"*"] discard]]; + [phraseStarParser setAssembler:self selector:@selector(workOnStarAssembly:)]; + } + return phraseStarParser; +} + + +// phrasePlus = phrase '+' +- (TDCollectionParser *)phrasePlusParser { + if (!phrasePlusParser) { + self.phrasePlusParser = [TDSequence sequence]; + phrasePlusParser.name = @"phrasePlus"; + [phrasePlusParser add:self.phraseParser]; + [phrasePlusParser add:[[TDSymbol symbolWithString:@"+"] discard]]; + [phrasePlusParser setAssembler:self selector:@selector(workOnPlusAssembly:)]; + } + return phrasePlusParser; +} + + +// phraseQuestion = phrase '?' +- (TDCollectionParser *)phraseQuestionParser { + if (!phraseQuestionParser) { + self.phraseQuestionParser = [TDSequence sequence]; + phraseQuestionParser.name = @"phraseQuestion"; + [phraseQuestionParser add:self.phraseParser]; + [phraseQuestionParser add:[[TDSymbol symbolWithString:@"?"] discard]]; + [phraseQuestionParser setAssembler:self selector:@selector(workOnQuestionAssembly:)]; + } + return phraseQuestionParser; +} + + +// phraseCardinality = phrase cardinality +- (TDCollectionParser *)phraseCardinalityParser { + if (!phraseCardinalityParser) { + self.phraseCardinalityParser = [TDSequence sequence]; + phraseCardinalityParser.name = @"phraseCardinality"; + [phraseCardinalityParser add:self.phraseParser]; + [phraseCardinalityParser add:self.cardinalityParser]; + [phraseCardinalityParser setAssembler:self selector:@selector(workOnPhraseCardinalityAssembly:)]; + } + return phraseCardinalityParser; +} + + +// cardinality = '{' Num '}' +- (TDCollectionParser *)cardinalityParser { + if (!cardinalityParser) { + self.cardinalityParser = [TDTrack track]; + cardinalityParser.name = @"cardinality"; + + TDTrack *commaNum = [TDTrack track]; + [commaNum add:[[TDSymbol symbolWithString:@","] discard]]; + [commaNum add:[TDNum num]]; + + [cardinalityParser add:[TDSymbol symbolWithString:@"{"]]; // serves as fence. dont discard + [cardinalityParser add:[TDNum num]]; + [cardinalityParser add:[self zeroOrOne:commaNum]]; + [cardinalityParser add:[[TDSymbol symbolWithString:@"}"] discard]]; + [cardinalityParser setAssembler:self selector:@selector(workOnCardinalityAssembly:)]; + } + return cardinalityParser; +} + + +// atomicValue = (pattern | literal | variable | constant | delimitedString) discard? +- (TDCollectionParser *)atomicValueParser { + if (!atomicValueParser) { + self.atomicValueParser = [TDSequence sequence]; + atomicValueParser.name = @"atomicValue"; + + [atomicValueParser add:[self zeroOrOne:self.discardParser]]; + + TDAlternation *a = [TDAlternation alternation]; + [a add:self.patternParser]; + [a add:self.literalParser]; + [a add:self.variableParser]; + [a add:self.constantParser]; + [a add:self.delimitedStringParser]; + [atomicValueParser add:a]; + } + return atomicValueParser; +} + + +// discard = '^' +- (TDCollectionParser *)discardParser { + if (!discardParser) { + self.discardParser = [TDTrack track]; + discardParser.name = @"discardParser"; + [discardParser add:[TDSymbol symbolWithString:@"^"]]; // preserve + } + return discardParser; +} + + +// pattern = DelimitedString('/', '/'); +- (TDParser *)patternParser { + if (!patternParser) { + patternParser.name = @"pattern"; + self.patternParser = [TDDelimitedString delimitedStringWithStartMarker:@"/" endMarker:@"/"]; + [patternParser setAssembler:self selector:@selector(workOnPatternAssembly:)]; + } + return patternParser; +} + + +// literal = QuotedString +- (TDParser *)literalParser { + if (!literalParser) { + self.literalParser = [TDQuotedString quotedString]; + [literalParser setAssembler:self selector:@selector(workOnLiteralAssembly:)]; + } + return literalParser; +} + + +// variable = LowercaseWord +- (TDParser *)variableParser { + if (!variableParser) { + self.variableParser = [TDLowercaseWord word]; + variableParser.name = @"variable"; + [variableParser setAssembler:self selector:@selector(workOnVariableAssembly:)]; + } + return variableParser; +} + + +// constant = UppercaseWord +- (TDParser *)constantParser { + if (!constantParser) { + self.constantParser = [TDUppercaseWord word]; + constantParser.name = @"constant"; + [constantParser setAssembler:self selector:@selector(workOnConstantAssembly:)]; + } + return constantParser; +} + + +// delimitedString = 'DelimitedString' '(' QuotedString (',' QuotedString)? ')' +- (TDCollectionParser *)delimitedStringParser { + if (!delimitedStringParser) { + self.delimitedStringParser = [TDTrack track]; + delimitedStringParser.name = @"delimitedString"; + + TDSequence *secondArg = [TDTrack track]; + [secondArg add:[[TDSymbol symbolWithString:@","] discard]]; + [secondArg add:[TDQuotedString quotedString]]; // endMarker + + [delimitedStringParser add:[[TDLiteral literalWithString:@"DelimitedString"] discard]]; + [delimitedStringParser add:[TDSymbol symbolWithString:@"("]]; // preserve as fence + [delimitedStringParser add:[TDQuotedString quotedString]]; // startMarker + [delimitedStringParser add:[self zeroOrOne:secondArg]]; + [delimitedStringParser add:[[TDSymbol symbolWithString:@")"] discard]]; + + [delimitedStringParser setAssembler:self selector:@selector(workOnDelimitedStringAssembly:)]; + } + return delimitedStringParser; +} + + +- (BOOL)shouldDiscard:(TDAssembly *)a { + if (![a isStackEmpty]) { + id obj = [a pop]; + if ([obj isEqual:caret]) { + return YES; + } else { + [a push:obj]; + } + } + return NO; +} + + +- (void)workOnStatementAssembly:(TDAssembly *)a { + NSArray *toks = [[a objectsAbove:equals] reversedArray]; + [a pop]; // discard '=' tok + + NSString *parserName = nil; + NSString *selName = nil; + id obj = [a pop]; + if ([obj isKindOfClass:[NSString class]]) { // a callback was provided + selName = obj; + parserName = [[a pop] stringValue]; + } else { + parserName = [obj stringValue]; + } + + if (selName) { + NSAssert(selName.length, @""); + [selectorTable setObject:selName forKey:parserName]; + } + NSMutableDictionary *d = a.target; + NSAssert(toks.count, @""); + [d setObject:toks forKey:parserName]; +} + + +- (NSString *)defaultAssemblerSelectorNameForParserName:(NSString *)parserName { + NSString *prefix = nil; + if ([parserName hasPrefix:@"@"]) { + parserName = [parserName substringFromIndex:1]; + prefix = @"workOn_"; + } else { + prefix = @"workOn"; + } + NSString *s = [NSString stringWithFormat:@"%@%@", [[parserName substringToIndex:1] uppercaseString], [parserName substringFromIndex:1]]; + return [NSString stringWithFormat:@"%@%@Assembly:", prefix, s]; +} + + +- (void)workOnCallbackAssembly:(TDAssembly *)a { + TDToken *selNameTok = [a pop]; + NSString *selName = [NSString stringWithFormat:@"%@:", selNameTok.stringValue]; + [a push:selName]; +} + + +- (void)workOnExpressionAssembly:(TDAssembly *)a { + NSArray *objs = [a objectsAbove:paren]; + NSAssert(objs.count, @""); + + [a pop]; // pop '(' + if (objs.count > 1) { + TDSequence *seq = [TDSequence sequence]; + for (id obj in [objs reverseObjectEnumerator]) { + [seq add:obj]; + } + [a push:seq]; + } else if (objs.count) { + [a push:[objs objectAtIndex:0]]; + } +} + + +- (void)workOnPatternAssembly:(TDAssembly *)a { + TDToken *tok = [a pop]; + NSAssert(tok.isDelimitedString, @""); + + NSString *s = tok.stringValue; + NSAssert(s.length > 2, @""); + + NSAssert([s hasPrefix:@"/"], @""); + NSAssert([s hasSuffix:@"/"], @""); + + NSString *re = [s stringByTrimmingQuotes]; + + TDPatternOptions opts = TDPatternOptionsNone; +// if (NSNotFound != [optsString rangeOfString:@"i"].location) { +// opts |= TDPatternOptionsIgnoreCase; +// } +// if (NSNotFound != [optsString rangeOfString:@"m"].location) { +// opts |= TDPatternOptionsMultiline; +// } +// if (NSNotFound != [optsString rangeOfString:@"x"].location) { +// opts |= TDPatternOptionsComments; +// } +// if (NSNotFound != [optsString rangeOfString:@"s"].location) { +// opts |= TDPatternOptionsDotAll; +// } +// if (NSNotFound != [optsString rangeOfString:@"w"].location) { +// opts |= TDPatternOptionsUnicodeWordBoundaries; +// } + + TDTerminal *t = [TDPattern patternWithString:re options:opts tokenType:TDTokenTypeAny]; + + if ([self shouldDiscard:a]) { + [t discard]; + } + + [a push:t]; +} + + +- (void)workOnLiteralAssembly:(TDAssembly *)a { + TDToken *tok = [a pop]; + + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + TDTerminal *t = [TDCaseInsensitiveLiteral literalWithString:s]; + + if ([self shouldDiscard:a]) { + [t discard]; + } + + [a push:t]; +} + + +- (void)workOnVariableAssembly:(TDAssembly *)a { + TDToken *tok = [a pop]; + NSString *parserName = tok.stringValue; + TDParser *p = nil; + if (isGatheringClasses) { + // lookup the actual possible parser. + // if its not there, or still a token array, just spoof it with a sequence + NSMutableDictionary *d = a.target; + p = [d objectForKey:parserName]; + if (![p isKindOfClass:[TDParser parser]]) { + p = [TDSequence sequence]; + } + } else { + if ([parserTokensTable objectForKey:parserName]) { + p = [self expandedParserForName:parserName]; + } + } + [a push:p]; +} + + +- (void)workOnConstantAssembly:(TDAssembly *)a { + TDToken *tok = [a pop]; + NSString *s = tok.stringValue; + id p = nil; + if ([s isEqualToString:@"Word"]) { + p = [TDWord word]; + } else if ([s isEqualToString:@"LowercaseWord"]) { + p = [TDLowercaseWord word]; + } else if ([s isEqualToString:@"UppercaseWord"]) { + p = [TDUppercaseWord word]; + } else if ([s isEqualToString:@"Num"]) { + p = [TDNum num]; + } else if ([s isEqualToString:@"S"]) { + p = [TDWhitespace whitespace]; + } else if ([s isEqualToString:@"QuotedString"]) { + p = [TDQuotedString quotedString]; + } else if ([s isEqualToString:@"Symbol"]) { + p = [TDSymbol symbol]; + } else if ([s isEqualToString:@"Comment"]) { + p = [TDComment comment]; + } else if ([s isEqualToString:@"Any"]) { + p = [TDAny any]; + } else if ([s isEqualToString:@"Empty"]) { + p = [TDEmpty empty]; + } else if ([s isEqualToString:@"Pattern"]) { + p = tok; + } else if ([s isEqualToString:@"DelimitedString"]) { + p = tok; + } else if ([s isEqualToString:@"YES"] || [s isEqualToString:@"NO"]) { + p = tok; + } else { + [NSException raise:@"Grammar Exception" format: + @"User Grammar referenced a constant parser name (uppercase word) which is not supported: %@. Must be one of: Word, LowercaseWord, UppercaseWord, QuotedString, Num, Symbol, Empty.", s]; + } + + if ([p isKindOfClass:[TDTerminal class]] && [self shouldDiscard:a]) { + TDTerminal *t = (TDTerminal *)p; + [t discard]; + } + + [a push:p]; +} + + +- (void)workOnDelimitedStringAssembly:(TDAssembly *)a { + NSArray *toks = [a objectsAbove:paren]; + [a pop]; // discard '(' fence + + NSAssert(toks.count > 0 && toks.count < 3, @""); + NSString *start = [[[toks lastObject] stringValue] stringByTrimmingQuotes]; + NSString *end = nil; + if (toks.count > 1) { + end = [[[toks objectAtIndex:0] stringValue] stringByTrimmingQuotes]; + } + + TDTerminal *t = [TDDelimitedString delimitedStringWithStartMarker:start endMarker:end]; + + if ([self shouldDiscard:a]) { + [t discard]; + } + + [a push:t]; +} + + +- (void)workOnNumAssembly:(TDAssembly *)a { + TDToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)workOnStarAssembly:(TDAssembly *)a { + id top = [a pop]; + TDRepetition *rep = [TDRepetition repetitionWithSubparser:top]; + [a push:rep]; +} + + +- (void)workOnPlusAssembly:(TDAssembly *)a { + id top = [a pop]; + [a push:[self oneOrMore:top]]; +} + + +- (void)workOnQuestionAssembly:(TDAssembly *)a { + id top = [a pop]; + [a push:[self zeroOrOne:top]]; +} + + +- (void)workOnPhraseCardinalityAssembly:(TDAssembly *)a { + NSRange r = [[a pop] rangeValue]; + TDParser *p = [a pop]; + TDSequence *s = [TDSequence sequence]; + + NSInteger start = r.location; + NSInteger end = r.length; + + NSInteger i = 0; + for ( ; i < start; i++) { + [s add:p]; + } + + for ( ; i < end; i++) { + [s add:[self zeroOrOne:p]]; + } + + [a push:s]; +} + + +- (void)workOnCardinalityAssembly:(TDAssembly *)a { + NSArray *toks = [a objectsAbove:self.curly]; + [a pop]; // discard '{' tok + + NSAssert(toks.count > 0, @""); + + CGFloat start = [[toks lastObject] floatValue]; + CGFloat end = start; + if (toks.count > 1) { + end = [[toks objectAtIndex:0] floatValue]; + } + + NSAssert(start <= end, @""); + + NSRange r = NSMakeRange(start, end); + [a push:[NSValue valueWithRange:r]]; +} + + +- (void)workOnOrAssembly:(TDAssembly *)a { + id second = [a pop]; + [a pop]; // pop '|' + id first = [a pop]; + TDAlternation *p = [TDAlternation alternation]; + [p add:first]; + [p add:second]; + [a push:p]; +} + + +- (void)workOnAndAssembly:(TDAssembly *)a { + NSMutableArray *parsers = [NSMutableArray array]; + while (![a isStackEmpty]) { + id obj = [a pop]; + if ([obj isKindOfClass:[TDParser class]]) { + [parsers addObject:obj]; + } else { + [a push:obj]; + break; + } + } + + if (parsers.count > 1) { + TDSequence *seq = [TDSequence sequence]; + for (TDParser *p in [parsers reverseObjectEnumerator]) { + [seq add:p]; + } + + [a push:seq]; + } else if (1 == parsers.count) { + [a push:[parsers objectAtIndex:0]]; + } +} + +@synthesize assembler; +@synthesize parserTokensTable; +@synthesize parserClassTable; +@synthesize selectorTable; +@synthesize equals; +@synthesize curly; +@synthesize paren; +@synthesize caret; +@synthesize statementParser; +@synthesize declarationParser; +@synthesize callbackParser; +@synthesize selectorParser; +@synthesize expressionParser; +@synthesize termParser; +@synthesize orTermParser; +@synthesize factorParser; +@synthesize nextFactorParser; +@synthesize phraseParser; +@synthesize phraseStarParser; +@synthesize phrasePlusParser; +@synthesize phraseQuestionParser; +@synthesize phraseCardinalityParser; +@synthesize cardinalityParser; +@synthesize atomicValueParser; +@synthesize discardParser; +@synthesize patternParser; +@synthesize literalParser; +@synthesize variableParser; +@synthesize constantParser; +@synthesize delimitedStringParser; +@synthesize assemblerSettingBehavior; +@end diff --git a/test/.svn/tmp/tempfile.tmp b/test/.svn/tmp/tempfile.tmp new file mode 100644 index 0000000..393dccc --- /dev/null +++ b/test/.svn/tmp/tempfile.tmp @@ -0,0 +1,130 @@ +// +// TDTestScaffold.m +// TDParseKit +// +// Created by Todd Ditchendorf on 7/13/08. +// Copyright 2008 Todd Ditchendorf. All rights reserved. +// + +#import "TDTestScaffold.h" + +#define RUN_ALL_TEST_CASES 1 +#define SOLO_TEST_CASE @"TDPlistParserTest" + +@interface SenTestSuite (TDAdditions) +- (void)addSuitesForClassNames:(NSArray *)classNames; +@end + +@implementation SenTestSuite (TDAdditions) + +- (void)addSuitesForClassNames:(NSArray *)classNames { + for (NSString *className in classNames) { + SenTestSuite *suite = [SenTestSuite testSuiteForTestCaseWithName:className]; + [self addTest:suite]; + } +} + +@end + +@implementation TDTestScaffold + ++ (void)load { + [self poseAsClass:[SenTestSuite class]]; +} + + ++ (SenTestSuite *)soloTestSuite { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Solo Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObject:SOLO_TEST_CASE]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + + ++ (SenTestSuite *)tokensTestSuite { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Tokens Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDReaderTest", + @"TDTokenizerTest", + @"TDTokenizerTest", + @"TDNumberStateTest", + @"TDQuoteStateTest", + @"TDWhitespaceStateTest", + @"TDWordStateTest", + @"TDSlashStateTest", + @"TDSymbolStateTest", + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + + ++ (SenTestSuite *)charsTestSuite { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Chars Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDCharacterAssemblyTest", + @"TDDigitTest", + @"TDCharTest", + @"TDLetterTest", + @"TDSpecificCharTest", + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + + ++ (SenTestSuite *)parseTestSuite { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Parse Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDParserTest", + @"TDTokenAssemblyTest", + @"TDLiteralTest", + @"TDRepetitionTest", + @"TDSequenceTest", + @"TDAlternationTest", + @"TDSymbolTest", + @"TDRobotCommandTest", + @"TDXmlParserTest", + @"TDJsonParserTest", + @"TDFastJsonParserTest", + @"TDRegularParserTest", + @"SRGSParserTest", + @"EBNFParserTest", + @"TDPlistParserTest", + @"TDXmlNameTest", + @"XPathParserTest", + @"XMLReaderTest", + @"TDXmlTokenizerTest", + @"TDArithmeticParserTest", + @"TDScientificNumberStateTest", + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + + ++ (id)testSuiteForBundlePath:(NSString *) bundlePath { + SenTestSuite *suite = nil; + +#if RUN_ALL_TEST_CASES + suite = [super defaultTestSuite]; +#else + suite = [SenTestSuite testSuiteWithName:@"My Tests"]; +// [suite addTest:[self charsTestSuite]]; +// [suite addTest:[self tokensTestSuite]]; +// [suite addTest:[self parseTestSuite]]; + [suite addTest:[self soloTestSuite]]; +#endif + + return suite; +} + +@end \ No newline at end of file diff --git a/test/EBNFParser.h b/test/EBNFParser.h new file mode 100644 index 0000000..1ae1dba --- /dev/null +++ b/test/EBNFParser.h @@ -0,0 +1,51 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface EBNFParser : PKRepetition { + PKCollectionParser *statementParser; + PKCollectionParser *exprOrAssignmentParser; + PKCollectionParser *assignmentParser; + PKCollectionParser *declarationParser; + PKCollectionParser *variableParser; + PKCollectionParser *expressionParser; + PKCollectionParser *termParser; + PKCollectionParser *orTermParser; + PKCollectionParser *factorParser; + PKCollectionParser *nextFactorParser; + PKCollectionParser *phraseParser; + PKCollectionParser *phraseStarParser; + PKCollectionParser *phraseQuestionParser; + PKCollectionParser *phrasePlusParser; + PKCollectionParser *atomicValueParser; +} +- (id)parse:(NSString *)s; + +@property (nonatomic, retain) PKCollectionParser *statementParser; +@property (nonatomic, retain) PKCollectionParser *exprOrAssignmentParser; +@property (nonatomic, retain) PKCollectionParser *assignmentParser; +@property (nonatomic, retain) PKCollectionParser *declarationParser; +@property (nonatomic, retain) PKCollectionParser *variableParser; +@property (nonatomic, retain) PKCollectionParser *expressionParser; +@property (nonatomic, retain) PKCollectionParser *termParser; +@property (nonatomic, retain) PKCollectionParser *orTermParser; +@property (nonatomic, retain) PKCollectionParser *factorParser; +@property (nonatomic, retain) PKCollectionParser *nextFactorParser; +@property (nonatomic, retain) PKCollectionParser *phraseParser; +@property (nonatomic, retain) PKCollectionParser *phraseStarParser; +@property (nonatomic, retain) PKCollectionParser *phraseQuestionParser; +@property (nonatomic, retain) PKCollectionParser *phrasePlusParser; +@property (nonatomic, retain) PKCollectionParser *atomicValueParser; +@end diff --git a/test/EBNFParser.m b/test/EBNFParser.m new file mode 100644 index 0000000..c5d8e91 --- /dev/null +++ b/test/EBNFParser.m @@ -0,0 +1,433 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "EBNFParser.h" +#import "NSString+ParseKitAdditions.h" + +/* + statement = exprOrAssignment ';' + exprOrAssignment = expression | assigment + assigment = declaration '=' expression + declaration = '$' Word + variable = '$' Word + expression = term orTerm* + term = factor nextFactor* + orTerm = '|' term + factor = phrase | phraseStar | phraseQuestion | phrasePlus + nextFactor = factor + phrase = atomicValue | '(' expression ')' + phraseStar = phrase '*' + phraseQuestion = phrase '?' + phrasePlus = phrase '+' + atomicValue = Word | Number | QuotedString | variable +*/ + +static NSString * const kEBNFEqualsString = @"="; +static NSString * const kEBNFVariablePrefix = @"$"; +static NSString * const kEBNFVariableSuffix = @""; + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface EBNFParser () +- (void)addSymbolString:(NSString *)s toTokenizer:(PKTokenizer *)t; + +- (void)didMatchWord:(PKAssembly *)a; +- (void)didMatchNum:(PKAssembly *)a; +- (void)didMatchQuotedString:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +- (void)didMatchPlus:(PKAssembly *)a; +- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchAssignment:(PKAssembly *)a; +- (void)didMatchVariable:(PKAssembly *)a; +@end + +@implementation EBNFParser + +- (id)init { + if ([super initWithSubparser:self.statementParser]) { + self.tokenizer = [PKTokenizer tokenizer]; + [self addSymbolString:kEBNFEqualsString toTokenizer:self.tokenizer]; + [self addSymbolString:kEBNFVariablePrefix toTokenizer:self.tokenizer]; + [self addSymbolString:kEBNFVariableSuffix toTokenizer:self.tokenizer]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.statementParser = nil; + self.exprOrAssignmentParser = nil; + self.assignmentParser = nil; + self.declarationParser = nil; + self.variableParser = nil; + self.expressionParser = nil; + self.termParser = nil; + self.orTermParser = nil; + self.factorParser = nil; + self.nextFactorParser = nil; + self.phraseParser = nil; + self.phraseStarParser = nil; + self.phraseQuestionParser = nil; + self.phrasePlusParser = nil; + self.atomicValueParser = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + self.tokenizer.string = s; + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:self.tokenizer]; + PKAssembly *result = [self completeMatchFor:a]; + return [result pop]; +} + + +- (void)addSymbolString:(NSString *)s toTokenizer:(PKTokenizer *)t { + if ([s length]) { + NSInteger c = [s characterAtIndex:0]; + [t setTokenizerState:t.symbolState from:c to:c]; + [t.symbolState add:s]; + } +} + + +// statement = exprOrAssignment ';' +- (PKCollectionParser *)statementParser { + if (!statementParser) { + self.statementParser = [PKTrack track]; + [statementParser add:self.exprOrAssignmentParser]; + [statementParser add:[[PKSymbol symbolWithString:@";"] discard]]; + } + return statementParser; +} + + +// exprOrAssignmentParser = expression | assignment +- (PKCollectionParser *)exprOrAssignmentParser { + if (!exprOrAssignmentParser) { + self.exprOrAssignmentParser = [PKAlternation alternation]; + [exprOrAssignmentParser add:self.expressionParser]; + [exprOrAssignmentParser add:self.assignmentParser]; + } + return exprOrAssignmentParser; +} + + +// declaration = variable '=' expression +- (PKCollectionParser *)assignmentParser { + if (!assignmentParser) { + self.assignmentParser = [PKTrack track]; + [assignmentParser add:self.declarationParser]; + [assignmentParser add:[[PKSymbol symbolWithString:kEBNFEqualsString] discard]]; + [assignmentParser add:self.expressionParser]; + [assignmentParser setAssembler:self selector:@selector(didMatchAssignment:)]; + } + return assignmentParser; +} + + +// declaration = '$' Word +- (PKCollectionParser *)declarationParser { + if (!declarationParser) { + self.declarationParser = [PKTrack track]; + [declarationParser add:[[PKSymbol symbolWithString:kEBNFVariablePrefix] discard]]; + [declarationParser add:[PKWord word]]; + if ([kEBNFVariableSuffix length]) { + [declarationParser add:[[PKSymbol symbolWithString:kEBNFVariableSuffix] discard]]; + } + } + return declarationParser; +} + + +// variable = '$' Word +- (PKCollectionParser *)variableParser { + if (!variableParser) { + self.variableParser = [PKTrack track]; + [variableParser add:[[PKSymbol symbolWithString:kEBNFVariablePrefix] discard]]; + [variableParser add:[PKWord word]]; + if ([kEBNFVariableSuffix length]) { + [variableParser add:[[PKSymbol symbolWithString:kEBNFVariableSuffix] discard]]; + } + } + return variableParser; +} + + +// expression = term orTerm* +- (PKCollectionParser *)expressionParser { + if (!expressionParser) { + self.expressionParser = [PKSequence sequence]; + [expressionParser add:self.termParser]; + [expressionParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + } + return expressionParser; +} + + +// term = factor nextFactor* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + [termParser add:self.factorParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.nextFactorParser]]; + } + return termParser; +} + + +// orTerm = '|' term +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKTrack track]; + [orTermParser add:[[PKSymbol symbolWithString:@"|"] discard]]; + [orTermParser add:self.termParser]; + [orTermParser setAssembler:self selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// factor = phrase | phraseStar | phraseQuestion | phrasePlus +- (PKCollectionParser *)factorParser { + if (!factorParser) { + self.factorParser = [PKAlternation alternation]; + [factorParser add:self.phraseParser]; + [factorParser add:self.phraseStarParser]; + [factorParser add:self.phraseQuestionParser]; + [factorParser add:self.phrasePlusParser]; + } + return factorParser; +} + + +// nextFactor = factor +- (PKCollectionParser *)nextFactorParser { + if (!nextFactorParser) { + self.nextFactorParser = [PKAlternation alternation]; + [nextFactorParser add:self.phraseParser]; + [nextFactorParser add:self.phraseStarParser]; + [nextFactorParser add:self.phraseQuestionParser]; + [nextFactorParser add:self.phrasePlusParser]; + [nextFactorParser setAssembler:self selector:@selector(didMatchAnd:)]; + } + return nextFactorParser; +} + + +// phrase = atomicValue | '(' expression ')' +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + PKSequence *s = [PKTrack track]; + [s add:[[PKSymbol symbolWithString:@"("] discard]]; + [s add:self.expressionParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + self.phraseParser = [PKAlternation alternation]; + [phraseParser add:self.atomicValueParser]; + [phraseParser add:s]; + } + return phraseParser; +} + + +// phraseStar = phrase '*' +- (PKCollectionParser *)phraseStarParser { + if (!phraseStarParser) { + self.phraseStarParser = [PKSequence sequence]; + [phraseStarParser add:self.phraseParser]; + [phraseStarParser add:[[PKSymbol symbolWithString:@"*"] discard]]; + [phraseStarParser setAssembler:self selector:@selector(didMatchStar:)]; + } + return phraseStarParser; +} + + +// phraseQuestion = phrase '?' +- (PKCollectionParser *)phraseQuestionParser { + if (!phraseQuestionParser) { + self.phraseQuestionParser = [PKSequence sequence]; + [phraseQuestionParser add:self.phraseParser]; + [phraseQuestionParser add:[[PKSymbol symbolWithString:@"?"] discard]]; + [phraseQuestionParser setAssembler:self selector:@selector(didMatchQuestion:)]; + } + return phraseQuestionParser; +} + + +// phrasePlus = phrase '+' +- (PKCollectionParser *)phrasePlusParser { + if (!phrasePlusParser) { + self.phrasePlusParser = [PKSequence sequence]; + [phrasePlusParser add:self.phraseParser]; + [phrasePlusParser add:[[PKSymbol symbolWithString:@"+"] discard]]; + [phrasePlusParser setAssembler:self selector:@selector(didMatchPlus:)]; + } + return phrasePlusParser; +} + + +// atomicValue = Word | Number | QuotedString | Variable +- (PKCollectionParser *)atomicValueParser { + if (!atomicValueParser) { + self.atomicValueParser = [PKAlternation alternation]; + + PKParser *p = [PKWord word]; + [p setAssembler:self selector:@selector(didMatchWord:)]; + [atomicValueParser add:p]; + + p = [PKNumber number]; + [p setAssembler:self selector:@selector(didMatchNum:)]; + [atomicValueParser add:p]; + + p = [PKQuotedString quotedString]; + [p setAssembler:self selector:@selector(didMatchQuotedString:)]; + [atomicValueParser add:p]; + + p = self.variableParser; + [p setAssembler:self selector:@selector(didMatchVariable:)]; + [atomicValueParser add:p]; + } + return atomicValueParser; +} + + +- (void)didMatchWord:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + [a push:[PKLiteral literalWithString:tok.stringValue]]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + [a push:[PKLiteral literalWithString:tok.stringValue]]; +} + + +- (void)didMatchQuotedString:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + + PKSequence *p = [PKSequence sequence]; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *eof = [PKToken EOFToken]; + while (eof != (tok = [t nextToken])) { + [p add:[PKLiteral literalWithString:tok.stringValue]]; + } + + [a push:p]; +} + + +- (void)didMatchStar:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKRepetition *p = [PKRepetition repetitionWithSubparser:[a pop]]; + [a push:p]; +} + + +- (void)didMatchQuestion:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + PKAlternation *p = [PKAlternation alternation]; + [p add:[a pop]]; + [p add:[PKEmpty empty]]; + [a push:p]; +} + + +- (void)didMatchPlus:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + PKSequence *p = [PKSequence sequence]; + [p add:top]; + [p add:[PKRepetition repetitionWithSubparser:top]]; + [a push:p]; +} + + +- (void)didMatchAnd:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + PKSequence *p = [PKSequence sequence]; + [p add:[a pop]]; + [p add:top]; + [a push:p]; +} + + +- (void)didMatchOr:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + // NSLog(@"top: %@", top); + // NSLog(@"top class: %@", [top class]); + PKAlternation *p = [PKAlternation alternation]; + [p add:[a pop]]; + [p add:top]; + [a push:p]; +} + + +- (void)didMatchAssignment:(PKAssembly *)a { + NSLog(@"%s", _cmd); + NSLog(@"a: %@", a); + id val = [a pop]; + PKToken *keyTok = [a pop]; + NSMutableDictionary *table = [NSMutableDictionary dictionaryWithDictionary:a.target]; + [table setObject:val forKey:keyTok.stringValue]; + a.target = table; +} + + +- (void)didMatchVariable:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *keyTok = [a pop]; + id val = [a.target objectForKey:keyTok.stringValue]; + if (val) { + [a push:val]; + } +} + +@synthesize statementParser; +@synthesize exprOrAssignmentParser; +@synthesize assignmentParser; +@synthesize declarationParser; +@synthesize variableParser; +@synthesize expressionParser; +@synthesize termParser; +@synthesize orTermParser; +@synthesize factorParser; +@synthesize nextFactorParser; +@synthesize phraseParser; +@synthesize phraseStarParser; +@synthesize phraseQuestionParser; +@synthesize phrasePlusParser; +@synthesize atomicValueParser; +@end \ No newline at end of file diff --git a/test/EBNFParserTest.h b/test/EBNFParserTest.h new file mode 100644 index 0000000..6d6ec54 --- /dev/null +++ b/test/EBNFParserTest.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface EBNFParserTest : SenTestCase { + +} + +@end diff --git a/test/EBNFParserTest.m b/test/EBNFParserTest.m new file mode 100644 index 0000000..17160c6 --- /dev/null +++ b/test/EBNFParserTest.m @@ -0,0 +1,43 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "EBNFParserTest.h" +#import "EBNFParser.h" + +@implementation EBNFParserTest + +- (void)test { + //NSString *s = @"foo (bar|baz)*;"; + NSString *s = @"$baz = bar; ($baz|foo)*;"; + //NSString *s = @"foo;"; + EBNFParser *p = [[[EBNFParser alloc] init] autorelease]; + + // PKAssembly *a = [p bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + // NSLog(@"a: %@", a); + // NSLog(@"a.target: %@", a.target); + + PKParser *res = [p parse:s]; + // NSLog(@"res: %@", res); + // NSLog(@"res: %@", res.string); + // NSLog(@"res.subparsers: %@", res.subparsers); + // NSLog(@"res.subparsers 0: %@", [[res.subparsers objectAtIndex:0] string]); + // NSLog(@"res.subparsers 1: %@", [[res.subparsers objectAtIndex:1] string]); + + s = @"bar foo bar foo"; + PKAssembly *a = [res completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + NSLog(@"\n\na: %@\n\n", a); + +} + +@end diff --git a/test/ERBTest.h b/test/ERBTest.h new file mode 100644 index 0000000..4e750c9 --- /dev/null +++ b/test/ERBTest.h @@ -0,0 +1,28 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" + +@interface ERBTest : SenTestCase { + NSString *g; + NSString *s; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; + PKToken *tok; + PKToken *startPrintMarker; +} + +@end diff --git a/test/ERBTest.m b/test/ERBTest.m new file mode 100644 index 0000000..7b4b1e7 --- /dev/null +++ b/test/ERBTest.m @@ -0,0 +1,72 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "ERBTest.h" + +@interface ERBAssembler : NSObject { + +} + +@end + +@implementation ERBAssembler + +- (id)provideValueForKey:(NSString *)k { + return @"hai"; +} + + +- (void)didMatchEndMarker:(PKAssembly *)a { + [a pop]; // '@>' + NSString *k = [a pop]; + [a pop]; // discard '<@=' + [a push:[self provideValueForKey:k]]; +} + + +- (void)didMatchDotWord:(PKAssembly *)a { + PKToken *lastPart = [a pop]; + [a pop]; // '.' + PKToken *firstPart = [a pop]; + + NSString *keyPath = [NSString stringWithFormat:@"%@.%@", + firstPart, lastPart]; + [a push:keyPath]; + // do something with the keyPath +} + +@end + + +@implementation ERBTest + +- (void)setUp { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"erb" ofType:@"grammar"]; + g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + lp = [[PKParserFactory factory] parserFromGrammar:g assembler:[[[ERBAssembler alloc] init] autorelease]]; + t = lp.tokenizer; +// startPrintMarker = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"<@=" floatValue:0]; +} + + +- (void)testFoo { + t.string = @"oh <@= foo.bar @> !"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; +// TDEqualObjects([res description], @"[oh, hai, !]oh/<@=/foo/./bar/@>/!^"); + +} + +@end + diff --git a/test/PKAST.h b/test/PKAST.h new file mode 100644 index 0000000..1690bf1 --- /dev/null +++ b/test/PKAST.h @@ -0,0 +1,33 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKToken; + +@interface PKAST : NSObject { + PKToken *token; + NSMutableArray *children; +} + ++ (id)ASTWithToken:(PKToken *)tok; + +- (id)initWithToken:(PKToken *)tok; + +- (NSInteger)type; + +- (void)addChild:(PKAST *)c; +- (BOOL)isNil; + +@end diff --git a/test/PKAST.m b/test/PKAST.m new file mode 100644 index 0000000..f12946f --- /dev/null +++ b/test/PKAST.m @@ -0,0 +1,102 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKAST.h" + +@interface PKAST () +@property (nonatomic, retain) PKToken *token; +@property (nonatomic, retain) NSMutableArray *children; +@end + +@implementation PKAST + ++ (id)ASTWithToken:(PKToken *)tok { + return [[[self alloc] initWithToken:tok] autorelease]; +} + + +- (id)init { + return [self initWithToken:nil]; +} + + +- (id)initWithToken:(PKToken *)tok { + if (self = [super init]) { + self.token = tok; + } + return self; +} + + +- (void)dealloc { + self.token = nil; + self.children = nil; + [super dealloc]; +} + + +- (NSString *)description { + return [token stringValue]; +} + + +- (NSString *)treeDescription { + if (![children count]) { + return [self description]; + } + + NSMutableString *ms = [NSMutableString string]; + + if (![self isNil]) { + [ms appendFormat:@"(%@ ", [self description]]; + } + + NSInteger i = 0; + for (PKAST *child in children) { + if (i++) { + [ms appendFormat:@" %@", child]; + } else { + [ms appendFormat:@"%@", child]; + } + } + + if (![self isNil]) { + [ms appendString:@")"]; + } + + return [[ms copy] autorelease]; +} + + +- (NSInteger)type { + NSAssert2(0, @"%s is an abastract method. Must be overridden in %@", __PRETTY_FUNCTION__, NSStringFromClass([self class])); + return -1; +} + + +- (void)addChild:(PKAST *)c { + if (!children) { + self.children = [NSMutableArray array]; + } + [children addObject:c]; +} + + +- (BOOL)isNil { + return !token; +} + +@synthesize token; +@synthesize children; +@end diff --git a/test/PKExclusion.h b/test/PKExclusion.h new file mode 100644 index 0000000..f7ef9b2 --- /dev/null +++ b/test/PKExclusion.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface PKExclusion : PKCollectionParser { + +} + ++ (id)exclusion; +@end diff --git a/test/PKExclusion.m b/test/PKExclusion.m new file mode 100644 index 0000000..9dec1e0 --- /dev/null +++ b/test/PKExclusion.m @@ -0,0 +1,82 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKExclusion.h" +#import + +@interface NSMutableSet (PKExclusionAdditions) +- (void)exclusiveSetTestingEquality:(NSSet *)s; +@end + +@implementation NSMutableSet (PKExclusionAdditions) + +- (void)exclusiveSetTestingEquality:(NSSet *)s { + for (id a1 in self) { + BOOL found = NO; + for (id a2 in s) { + if ([a1 isEqual:a2 ]) { + found = YES; + break; + } + } + if (found) { + [self removeObject:a1]; + } + } + + for (id a2 in s) { + BOOL found = NO; + for (id a1 in self) { + if ([a2 isEqual:a1]) { + found = YES; + break; + } + } + if (!found) { + [self addObject:a2]; + } + } +} + +@end + +@interface PKParser () +- (NSSet *)matchAndAssemble:(NSSet *)inAssemblies; +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@implementation PKExclusion + ++ (id)exclusion { + return [[[self alloc] init] autorelease]; +} + + +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies { + NSParameterAssert(inAssemblies); + NSMutableSet *outAssemblies = [NSMutableSet set]; + + NSInteger i = 0; + for (PKParser *p in subparsers) { + if (0 == i++) { + outAssemblies = [[[p matchAndAssemble:inAssemblies] mutableCopy] autorelease]; + } else { + [outAssemblies exclusiveSetTestingEquality:[p allMatchesFor:inAssemblies]]; + } + } + + return outAssemblies; +} + +@end diff --git a/test/PKNumberState.h b/test/PKNumberState.h new file mode 100644 index 0000000..84b0a22 --- /dev/null +++ b/test/PKNumberState.h @@ -0,0 +1,38 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class PKNumberState + @brief A number state returns a number from a reader. + @details This state's idea of a number allows an optional, initial minus sign, followed by one or more digits. A decimal point and another string of digits may follow these digits. + If allowsScientificNotation is true (the default) this state allows 'e' or 'E' followed by an (optionally explicityly positive or negative) integer to represent 10 to the indicated power. For example, this state will recognize 1e2 as equaling 100.

+*/ +@interface PKNumberState : PKTokenizerState { + BOOL allowsTrailingDot; + BOOL gotADigit; + BOOL negative; + PKUniChar c; + CGFloat floatValue; +} + +/*! + @property allowsTrailingDot + @brief If true, numbers are allowed to end with a trialing dot, e.g. 42. + @details false by default. +*/ +@property (nonatomic) BOOL allowsTrailingDot; +@end diff --git a/test/PKNumberState.m b/test/PKNumberState.m new file mode 100644 index 0000000..71921e3 --- /dev/null +++ b/test/PKNumberState.m @@ -0,0 +1,151 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import +#import + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface PKNumberState () +- (CGFloat)absorbDigitsFromReader:(PKReader *)r isFraction:(BOOL)fraction; +- (CGFloat)value; +- (void)parseLeftSideFromReader:(PKReader *)r; +- (void)parseRightSideFromReader:(PKReader *)r; +- (void)reset:(PKUniChar)cin; +@end + +@implementation PKNumberState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + [self resetWithReader:r]; + negative = NO; + PKUniChar originalCin = cin; + + if ('-' == cin) { + negative = YES; + cin = [r read]; + [self append:'-']; + } else if ('+' == cin) { + cin = [r read]; + [self append:'+']; + } + + [self reset:cin]; + if ('.' == c) { + [self parseRightSideFromReader:r]; + } else { + [self parseLeftSideFromReader:r]; + [self parseRightSideFromReader:r]; + } + + // erroneous ., +, or - + if (!gotADigit) { + if (negative && PKEOF != c) { // ?? + [r unread]; + } + return [t.symbolState nextTokenFromReader:r startingWith:originalCin tokenizer:t]; + } + + if (PKEOF != c) { + [r unread]; + } + + if (negative) { + floatValue = -floatValue; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:[self bufferedString] floatValue:[self value]]; + tok.offset = offset; + return tok; +} + + +- (CGFloat)value { + return floatValue; +} + + +- (CGFloat)absorbDigitsFromReader:(PKReader *)r isFraction:(BOOL)isFraction { + CGFloat divideBy = 1.0; + CGFloat v = 0.0; + + while (1) { + if (isdigit(c)) { + [self append:c]; + gotADigit = YES; + v = v * 10.0 + (c - '0'); + c = [r read]; + if (isFraction) { + divideBy *= 10.0; + } + } else { + break; + } + } + + if (isFraction) { + v = v / divideBy; + } + + return (CGFloat)v; +} + + +- (void)parseLeftSideFromReader:(PKReader *)r { + floatValue = [self absorbDigitsFromReader:r isFraction:NO]; +} + + +- (void)parseRightSideFromReader:(PKReader *)r { + if ('.' == c) { + PKUniChar n = [r read]; + BOOL nextIsDigit = isdigit(n); + if (PKEOF != n) { + [r unread]; + } + + if (nextIsDigit || allowsTrailingDot) { + [self append:'.']; + if (nextIsDigit) { + c = [r read]; + floatValue += [self absorbDigitsFromReader:r isFraction:YES]; + } + } + } +} + + +- (void)reset:(PKUniChar)cin { + gotADigit = NO; + floatValue = 0.0; + c = cin; +} + +@synthesize allowsTrailingDot; +@end diff --git a/test/PKParseTree.h b/test/PKParseTree.h new file mode 100644 index 0000000..2a5b0e1 --- /dev/null +++ b/test/PKParseTree.h @@ -0,0 +1,37 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKRuleNode; +@class PKTokenNode; +@class PKToken; + +@interface PKParseTree : NSObject { + PKParseTree *parent; + NSMutableArray *children; + id userInfo; + BOOL matched; +} ++ (id)parseTree; + +- (PKRuleNode *)addChildRule:(NSString *)name; +- (PKTokenNode *)addChildToken:(PKToken *)tok; +- (void)addChild:(PKParseTree *)tr; + +@property (nonatomic, assign, readonly) PKParseTree *parent; // weak ref +@property (nonatomic, retain, readonly) NSMutableArray *children; +@property (nonatomic, retain) id userInfo; +@property (nonatomic, getter=isMatched) BOOL matched; +@end diff --git a/test/PKParseTree.m b/test/PKParseTree.m new file mode 100644 index 0000000..79d527f --- /dev/null +++ b/test/PKParseTree.m @@ -0,0 +1,96 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" + +@interface PKParseTree () +@property (nonatomic, assign, readwrite) PKParseTree *parent; +@property (nonatomic, retain, readwrite) NSMutableArray *children; +@end + +@implementation PKParseTree + ++ (id)parseTree { + return [[[self alloc] init] autorelease]; +} + + +- (void)dealloc { + self.parent = nil; + self.children = nil; + self.userInfo = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKParseTree *t = [[[self class] allocWithZone:zone] init]; + + // assign parent + if (parent) { + t->parent = parent; + + // put new copy in new parent's children array + NSInteger i = [[parent children] indexOfObject:self]; + if (NSNotFound != i) { + [[t->parent children] replaceObjectAtIndex:i withObject:t]; + } + } + + // copy children + if (children) { + t->children = [children mutableCopyWithZone:zone]; + } + return t; +} + + +- (PKRuleNode *)addChildRule:(NSString *)name { + NSParameterAssert([name length]); + PKRuleNode *n = [PKRuleNode ruleNodeWithName:name]; + [self addChild:n]; + return n; +} + + +- (PKTokenNode *)addChildToken:(PKToken *)tok { + NSParameterAssert([[tok stringValue] length]); + PKTokenNode *n = [PKTokenNode tokenNodeWithToken:tok]; + [self addChild:n]; + return n; +} + + +- (void)addChild:(PKParseTree *)tr { + NSParameterAssert(tr); + if (!children) { + self.children = [NSMutableArray array]; + } + tr.parent = self; + [children addObject:tr]; +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", children]; +} + +@synthesize parent; +@synthesize children; +@synthesize userInfo; +@synthesize matched; +@end + diff --git a/test/PKParseTreeAssembler.h b/test/PKParseTreeAssembler.h new file mode 100644 index 0000000..15dde9b --- /dev/null +++ b/test/PKParseTreeAssembler.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface PKParseTreeAssembler : NSObject { + NSMutableDictionary *ruleNames; + NSString *preassemblerPrefix; + NSString *assemblerPrefix; + NSString *suffix; +} + +@end diff --git a/test/PKParseTreeAssembler.m b/test/PKParseTreeAssembler.m new file mode 100644 index 0000000..0802853 --- /dev/null +++ b/test/PKParseTreeAssembler.m @@ -0,0 +1,181 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKParseTreeAssembler.h" +#import +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" + +@interface PKParseTreeAssembler () +- (NSString *)ruleNameForSelName:(NSString *)selName withPrefix:(NSString *)pre; +- (void)didMatchRuleNamed:(NSString *)name assembly:(PKAssembly *)a; +- (void)willMatchRuleNamed:(NSString *)name assembly:(PKAssembly *)a; +- (void)didMatchToken:(PKAssembly *)a; +- (PKParseTree *)currentFrom:(PKAssembly *)a; +- (void)removeUnmatchedChildrenFrom:(PKParseTree *)n; + +@property (nonatomic, retain) NSMutableDictionary *ruleNames; +@property (nonatomic, copy) NSString *assemblerPrefix; +@property (nonatomic, copy) NSString *preassemblerPrefix; +@property (nonatomic, copy) NSString *suffix; +@end + +@implementation PKParseTreeAssembler + +- (id)init { + if (self = [super init]) { + self.ruleNames = [NSMutableDictionary dictionary]; + self.preassemblerPrefix = @"willMatch"; + self.assemblerPrefix = @"didMatch"; + self.suffix = @":"; + } + return self; +} + + +- (void)dealloc { + self.ruleNames = nil; + self.preassemblerPrefix = nil; + self.assemblerPrefix = nil; + self.suffix = nil; + [super dealloc]; +} + + +- (BOOL)respondsToSelector:(SEL)sel { + return YES; + if ([super respondsToSelector:sel]) { + return YES; + } else { + NSString *selName = NSStringFromSelector(sel); + if ([selName hasPrefix:assemblerPrefix] && [selName hasSuffix:suffix]) { + return YES; + } + } + return NO; +} + + +- (id)performSelector:(SEL)sel withObject:(id)obj { + NSString *selName = NSStringFromSelector(sel); + + if ([selName hasPrefix:assemblerPrefix] && [selName hasSuffix:suffix]) { + [self didMatchRuleNamed:[self ruleNameForSelName:selName withPrefix:assemblerPrefix] assembly:obj]; + } else if ([selName hasPrefix:preassemblerPrefix] && [selName hasSuffix:suffix]) { + [self willMatchRuleNamed:[self ruleNameForSelName:selName withPrefix:preassemblerPrefix] assembly:obj]; + } else if ([super respondsToSelector:sel]) { + return [super performSelector:sel withObject:obj]; + } else { + NSAssert(0, @""); + } + return nil; +} + + +- (NSString *)ruleNameForSelName:(NSString *)selName withPrefix:(NSString *)prefix { + NSString *ruleName = [ruleNames objectForKey:selName]; + + if (!ruleName) { + NSUInteger prefixLen = [prefix length]; + NSInteger c = ((NSInteger)[selName characterAtIndex:prefixLen]) + 32; // lowercase + NSRange r = NSMakeRange(prefixLen + 1, [selName length] - (prefixLen + [suffix length] + 1 /*:*/)); + ruleName = [NSString stringWithFormat:@"%C%@", c, [selName substringWithRange:r]]; + [ruleNames setObject:ruleName forKey:selName]; + } + + return ruleName; +} + + +- (void)willMatchRuleNamed:(NSString *)name assembly:(PKAssembly *)a { + PKParseTree *current = [self currentFrom:a]; + [self didMatchToken:a]; + current = [current addChildRule:name]; + a.target = current; +} + + +- (void)didMatchRuleNamed:(NSString *)name assembly:(PKAssembly *)a { + PKParseTree *current = [self currentFrom:a]; + + NSArray *origChildren = [[[current children] mutableCopy] autorelease]; + + PKParseTree *oldCurrent = nil; + while ([current isKindOfClass:[PKRuleNode class]] && ![[(id)current name] isEqualToString:name]) { + oldCurrent = [[current retain] autorelease]; + a.target = [current parent]; + current = [self currentFrom:a]; + [self didMatchToken:a]; + } + + if (oldCurrent && ![oldCurrent isMatched]) { + [(id)[current children] addObjectsFromArray:origChildren]; + } + + [self didMatchToken:a]; + current = [self currentFrom:a]; + + [self removeUnmatchedChildrenFrom:current]; + [current setMatched:YES]; + a.target = [current parent]; +} + + +- (void)removeUnmatchedChildrenFrom:(PKParseTree *)n { + NSMutableArray *remove = [NSMutableArray array]; + for (id child in [n children]) { + if (![child isMatched]) { + [remove addObject:child]; + } + } + + for (id child in remove) { + [(id)[n children] removeObject:child]; + } +} + + +- (PKParseTree *)currentFrom:(PKAssembly *)a { + PKParseTree *current = a.target; + if (!current) { + current = [PKParseTree parseTree]; + a.target = current; + } + return current; +} + + +- (void)didMatchToken:(PKAssembly *)a { + PKParseTree *current = [self currentFrom:a]; + if ([current isMatched]) return; + + NSMutableArray *toks = [NSMutableArray arrayWithCapacity:[a.stack count]]; + while (![a isStackEmpty]) { + id tok = [a pop]; + NSAssert([tok isKindOfClass:[PKToken class]], @""); + [toks addObject:tok]; + } + + for (id tok in [toks reverseObjectEnumerator]) { + PKTokenNode *n = [current addChildToken:tok]; + [n setMatched:YES]; + } +} + +@synthesize ruleNames; +@synthesize preassemblerPrefix; +@synthesize assemblerPrefix; +@synthesize suffix; +@end diff --git a/test/PKRuleNode.h b/test/PKRuleNode.h new file mode 100644 index 0000000..ec9d51f --- /dev/null +++ b/test/PKRuleNode.h @@ -0,0 +1,27 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKParseTree.h" + +@interface PKRuleNode : PKParseTree { + NSString *name; +} + ++ (id)ruleNodeWithName:(NSString *)s; + +// designated initializer +- (id)initWithName:(NSString *)s; + +@property (nonatomic, copy, readonly) NSString *name; +@end diff --git a/test/PKRuleNode.m b/test/PKRuleNode.m new file mode 100644 index 0000000..c748ac2 --- /dev/null +++ b/test/PKRuleNode.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKRuleNode.h" + +@interface PKRuleNode () +@property (nonatomic, copy, readwrite) NSString *name; +@end + +@implementation PKRuleNode + ++ (id)ruleNodeWithName:(NSString *)s { + return [[[self alloc] initWithName:s] autorelease]; +} + + +- (id)initWithName:(NSString *)s { + if (self = [super init]) { + self.name = s; + } + return self; +} + + +- (void)dealloc { + self.name = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKRuleNode *n = [super copyWithZone:zone]; + n->name = [name copyWithZone:zone]; + return n; +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", name, children]; +} + +@synthesize name; +@end diff --git a/test/PKScientificNumberState.h b/test/PKScientificNumberState.h new file mode 100644 index 0000000..90c0a65 --- /dev/null +++ b/test/PKScientificNumberState.h @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/*! + @class PKScientificNumberState + @brief A PKScientificNumberState object returns a number from a reader. + @details

This state's idea of a number expands on its superclass, allowing an 'e' followed by an integer to represent 10 to the indicated power. For example, this state will recognize 1e2 as equaling 100.

+

This class exists primarily to show how to introduce a new tokenizing state.

+*/ +@interface PKScientificNumberState : PKNumberState { + BOOL allowsScientificNotation; + CGFloat exp; + BOOL negativeExp; +} + +@property (nonatomic) BOOL allowsScientificNotation; +@end diff --git a/test/PKScientificNumberState.m b/test/PKScientificNumberState.m new file mode 100644 index 0000000..e29421d --- /dev/null +++ b/test/PKScientificNumberState.m @@ -0,0 +1,99 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKScientificNumberState.h" +#import +#import + +@interface PKTokenizerState () +- (void)append:(PKUniChar)c; +@end + +@interface PKNumberState () +- (CGFloat)absorbDigitsFromReader:(PKReader *)r isFraction:(BOOL)isFraction; +- (void)parseRightSideFromReader:(PKReader *)r; +- (void)reset:(PKUniChar)cin; +- (CGFloat)value; +@end + +@implementation PKScientificNumberState + +- (id)init { + if (self = [super init]) { + self.allowsScientificNotation = YES; + } + return self; +} + + +- (void)parseRightSideFromReader:(PKReader *)r { + NSParameterAssert(r); + [super parseRightSideFromReader:r]; + if (!allowsScientificNotation) { + return; + } + + if ('e' == c || 'E' == c) { + PKUniChar e = c; + c = [r read]; + + BOOL hasExp = isdigit(c); + negativeExp = ('-' == c); + BOOL positiveExp = ('+' == c); + + if (!hasExp && (negativeExp || positiveExp)) { + c = [r read]; + hasExp = isdigit(c); + } + if (PKEOF != c) { + [r unread]; + } + if (hasExp) { + [self append:e]; + if (negativeExp) { + [self append:'-']; + } else if (positiveExp) { + [self append:'+']; + } + c = [r read]; + exp = [super absorbDigitsFromReader:r isFraction:NO]; + } + } +} + + +- (void)reset:(PKUniChar)cin { + [super reset:cin]; + exp = (CGFloat)0.0; + negativeExp = NO; +} + + +- (CGFloat)value { + CGFloat result = (CGFloat)floatValue; + + NSUInteger i = 0; + for ( ; i < exp; i++) { + if (negativeExp) { + result /= (CGFloat)10.0; + } else { + result *= (CGFloat)10.0; + } + } + + return (CGFloat)result; +} + +@synthesize allowsScientificNotation; +@end diff --git a/test/PKTokenNode.h b/test/PKTokenNode.h new file mode 100644 index 0000000..25be566 --- /dev/null +++ b/test/PKTokenNode.h @@ -0,0 +1,29 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKParseTree.h" + +@class PKToken; + +@interface PKTokenNode : PKParseTree { + PKToken *token; +} + ++ (id)tokenNodeWithToken:(PKToken *)tok; + +// designated initializer +- (id)initWithToken:(PKToken *)tok; + +@property (nonatomic, retain, readonly) PKToken *token; +@end diff --git a/test/PKTokenNode.m b/test/PKTokenNode.m new file mode 100644 index 0000000..4d7f081 --- /dev/null +++ b/test/PKTokenNode.m @@ -0,0 +1,55 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKTokenNode.h" +#import + +@interface PKTokenNode () +@property (nonatomic, retain, readwrite) PKToken *token; +@end + +@implementation PKTokenNode + ++ (id)tokenNodeWithToken:(PKToken *)s { + return [[[self alloc] initWithToken:s] autorelease]; +} + + +- (id)initWithToken:(PKToken *)s { + if (self = [super init]) { + self.token = s; + } + return self; +} + + +- (void)dealloc { + self.token = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + PKTokenNode *n = [super copyWithZone:zone]; + n->token = [token copyWithZone:zone]; + return n; +} + + +- (NSString *)description { + return [NSString stringWithFormat:@"", token]; +} + +@synthesize token; +@end diff --git a/test/RelaxParser.h b/test/RelaxParser.h new file mode 100644 index 0000000..723f66a --- /dev/null +++ b/test/RelaxParser.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface RelaxParser : PKSequence { + PKTokenizer *tokenizer; +} + +@end diff --git a/test/RelaxParser.m b/test/RelaxParser.m new file mode 100644 index 0000000..4cc0b57 --- /dev/null +++ b/test/RelaxParser.m @@ -0,0 +1,624 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "RelaxParser.h" + +@implementation RelaxParser + +- (PKTokenizer *)tokenizer { + if (!tokenizer) { + self.tokenizer = [PKTokenizer tokenizer]; + [tokenizer.symbolState add:@"|="]; + [tokenizer.symbolState add:@"&="]; + } + return tokenizer; +} + +// topLevel ::= decl* (pattern | grammarContent*) +- (PKCollectionParser *)topLevelParser { + if (!topLevelParser) { + self.topLevelParser = [PKSequence sequence]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.declParser]; + [topLevelParser add:a]; + + a = [PKAlternation alternation]; + [a add:self.patternParser]; + [a add:[PKRepetition repetitionWithSubparser:self.grammarContentParser]]; + [topLevelParser add:a]; + } + return topLevelParser; +} + +// decl ::= "namespace" identifierOrKeyword "=" namespaceURILiteral +// | "default" "namespace" [identifierOrKeyword] "=" namespaceURILiteral +// | "datatypes" identifierOrKeyword "=" literal +- (PKCollectionParser *)declParser { + if (!declParser) { + self.declParser = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"namespace"]]; + [s add:self.identifierOrKeywordParser]; + [s add:[PKSymbol symbolWithString:@"="]]; + [a add:self.namespaceURILiteralParser]; + [declParser add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"default"]]; + [s add:[PKLiteral literalWithString:@"namespace"]]; + [s add:self.identifierOrKeywordParser]; + [s add:[PKSymbol symbolWithString:@"="]]; + [a add:self.namespaceURILiteralParser]; + [declParser add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"datatypes"]]; + [s add:self.identifierOrKeywordParser]; + [s add:[PKSymbol symbolWithString:@"="]]; + [a add:[PKQuotedString quotedString]]; + [declParser add:s]; + } + return declParser; +} + + +- (PKCollectionParser *)atLeastOneOf:(PKParser *)p { + PKSequence *s = [PKSequence sequence]; + [s add:p]; + [s add:[PKRepetition repetitionWithSubparser:p]]; + return s; +} + +// pattern ::= +// elementPattern +// | attributePattern +// | pattern commaPattern+ +// | pattern andPattern+ +// | pattern orPattern+ +// | patternQuestion +// | patternStar +// | patternPlus +// | listPattern +// | mixedPattern +// | identifier +// | parent +// | emptyKeyword +// | textKeyword +// | [datatypeName] datatypeValue +// | datatypeName ["{" param* "}"] [exceptPattern] +// | "notAllowed" +// | "external" anyURILiteral [inherit] +// | "grammar" "{" grammarContent* "}" +// | "(" pattern ")" +- (PKCollectionParser *)patternParser { + if (!patternParser) { + self.patternParser = [PKAlternation alternation]; + [patternParser add:self.elementPatternParser]; + [patternParser add:self.attributePatternParser]; + [patternParser add:[self atLeastOneOf:self.commaPatternParser]]; + [patternParser add:[self atLeastOneOf:self.andPatternParser]]; + [patternParser add:[self atLeastOneOf:self.orPatternParser]]; + [patternParser add:[self atLeastOneOf:self.patternQuestionParser]]; + [patternParser add:[self atLeastOneOf:self.patternStarParser]]; + [patternParser add:[self atLeastOneOf:self.patternPlusParser]]; + [patternParser add:self.listPatternParser]; + [patternParser add:self.mixedPatternParser]; + [patternParser add:self.identifierParser]; + [patternParser add:self.parentParser]; + [patternParser add:self.emptyKeywordParser]; + [patternParser add:self.textKeywordParser]; + + + + + s = [PKSequence sequence]; + [s add:patternParser]; + + } +} + +// elementPattern := "element" nameClass "{" pattern "}" +- (PKCollectionParser *)elementPatternParser { + if (!elementPatternParser) { + self.elementPatternParser = [PKSequence sequence]; + [elementPatternParser add:[PKLiteral literalWithString:@"element"]]; + [elementPatternParser add:self.nameClass]; + [elementPatternParser add:[PKSymbol symbolWithString:@"{"]]; + [elementPatternParser add:patternParser]; + [elementPatternParser add:[PKSymbol symbolWithString:@"}"]]; + } + return elementPatternParser; +} + + +// attributePattern := "attribute" nameClass "{" pattern "}" +- (PKCollectionParser *)attributePatternParser { + if (!attributePatternParser) { + attributePatternParser = [PKSequence sequence]; + [attributePatternParser add:[PKLiteral literalWithString:@"attribute"]]; + [attributePatternParser add:self.nameClass]; + [attributePatternParser add:[PKSymbol symbolWithString:@"{"]]; + [attributePatternParser add:patternParser]; + [attributePatternParser add:[PKSymbol symbolWithString:@"}"]]; + } + return attributePatternParser; +} + + +// commaPattern := "," pattern +- (PKCollectionParser *)commaPatternParser { + if (!commaPatternParser) { + self.commaPatternParser = [PKSequence sequence]; + [commaPatternParser add:[PKSymbol symbolWithString:@","]]; + [commaPatternParser add:self.patternParser]; + } + return commaPatternParser; +} + + +// andPattern := "&" pattern +- (PKCollectionParser *)andPatternParser { + if (!andPatternParser) { + self.andPatternParser = [PKSequence sequence]; + [andPatternParser add:[PKSymbol symbolWithString:@"&"]]; + [andPatternParser add:self.patternParser]; + } + return andPatternParser; +} + + +// orPattern := "|" pattern +- (PKCollectionParser *)orPatternParser { + if (!orPatternParser) { + self.orPatternParser = [PKSequence sequence]; + [orPatternParser add:[PKSymbol symbolWithString:@"|"]]; + [orPatternParser add:self.patternParser]; + } + return orPatternParser; +} + + +// patternQuestion := pattern "?" +- (PKCollectionParser *)patternQuestionParser { + if (!patternQuestionParser) { + self.patternQuestionParser = [PKSequence sequence]; + [patternQuestionParser add:self.patternParser]; + [patternQuestionParser add:[PKSymbol symbolWithString:@"?"]]; + } + return patternQuestionParser; +} + + +// patternQuestion := pattern "*" +- (PKCollectionParser *)patternStarParser { + if (!patternStarParser) { + self.patternStarParser = [PKSequence sequence]; + [patternStarParser add:self.patternParser]; + [patternStarParser add:[PKSymbol symbolWithString:@"*"]]; + } + return patternStarParser; +} + + +// patternQuestion := pattern "+" +- (PKCollectionParser *)patternPlusParser { + if (!patternPlusParser) { + self.patternPlusParser = [PKSequence sequence]; + [patternPlusParser add:self.patternParser]; + [patternPlusParser add:[PKSymbol symbolWithString:@"+"]]; + } + return patternPlusParser; +} + +// | "list" "{" pattern "}" +- (PKCollectionParser *)listPatternParser { + if (!listPatternParser) { + self.listPatternParser = [PKSequence sequence]; + [listPatternParser add:[PKLiteral literalWithString:@"list"]]; + [listPatternParser add:[PKSymbol symbolWithString:@"{"]]; + [listPatternParser add:patternParser]; + [listPatternParser add:[PKSymbol symbolWithString:@"}"]]; + } + return listPatternParser; +} + +// | "mixed" "{" pattern "}" +- (PKCollectionParser *)mixedPatternParser { + if (!mixedPatternParser) { + self.mixedPatternParser = [PKSequence sequence]; + [mixedPatternParser add:[PKLiteral literalWithString:@"mixed"]]; + [mixedPatternParser add:[PKSymbol symbolWithString:@"{"]]; + [mixedPatternParser add:patternParser]; + [mixedPatternParser add:[PKSymbol symbolWithString:@"}"]]; + } + return mixedPatternParser; +} + +// | "parent" identifier +- (PKCollectionParser *)parentParser { + if (!parentParser) { + self.parentParser = [PKSequence sequence]; + [parentParser add:[PKLiteral literalWithString:@"parent"]]; + [parentParser add:self.identifierParser]; + } + return parentParser; +} + + +// param ::= identifierOrKeyword "=" literal +- (PKCollectionParser *)paramParser { + if (!paramParser) { + self.paramParser = [PKSequence sequence]; + [paramParser add:self.identifierOrKeywordParser]; + [paramParser add:[PKSymbol symbolWithString:@"="]]; + [paramParser add:self.literalParser]; + } + return paramParser; +} + +// exceptPattern ::= "-" pattern +- (PKCollectionParser *)exceptPatternParser { + if (!exceptPattern) { + self.exceptPattern = [PKSequence sequence]; + [exceptPattern add:[PKSymbol symbolWithString:@"-"]]; + [exceptPattern add:self.patternParser]; + } + return exceptPattern; +} + + +// grammarContent ::= start | define | "element" "{" grammarContent* "}" | "include" anyURILiteral [inherit] ["{" includeContent* "}"] +// +// includeContent ::= define | start | elementIncludeContent +- (PKCollectionParser *)includeContentParser { + if (!includeContentParser) { + self.includeContentParser = [PKAlternation alternation]; + [includeContentParser add:self.defineParser]; + [includeContentParser add:self.startParser]; + [includeContentParser add:self.elementIncludeContentParser]; + } + return includeContentParser; +} + +// elementIncludeContent ::= "element" "{" includeContent* "}" +- (PKCollectionParser *)elementIncludeContentParser { + if (!elementIncludeContentParser) { + self.elementIncludeContentParser = [PKSequence sequence]; + [s add:self.elementKeywordParser]; + [s add:[PKSymbol symbolWithString:@"{"]]; + [s add:[PKRepetition repetitionWithSubparser:self.includeContentParser]] + [s add:[PKSymbol symbolWithString:@"}"]]; + + [elementIncludeContentParser add:s]; + } + return elementIncludeContentParser; +} + + +// +// start ::= "start" assignMethod pattern +- (PKCollectionParser *)startParser { + if (!startParser) { + self.startParser = [PKSequence sequence]; + [startParser add:self.startKeywordParser]; + [startParser add:self.assignMethodParser]; + [startParser add:self.patternParser]; + } + return startParser; +} + + +// +// define ::= identifier assignMethod pattern +- (PKCollectionParser *)defineParser { + if (!defineParser) { + self.defineParser = [PKSequence sequence]; + [defineParser add:self.identifierParser]; + [defineParser add:self.assignMethodParser]; + [defineParser add:self.patternParser]; + } + return defineParser; +} + + +// +// assignMethod ::= "=" | "|=" | "&=" +- (PKCollectionParser *)assignMethodParser { + if (!assignMethodParser) { + self.assignMethodParser = [PKAlternation alternation]; + [assignMethodParser add:[PKSymbol symbolWithString:@"="]]; + [assignMethodParser add:[PKSymbol symbolWithString:@"|="]]; + [assignMethodParser add:[PKSymbol symbolWithString:@"&="]]; + } + return assignMethodParser; +} + +// +// nameClass ::= name +// | nsName [exceptNameClass] +// | anyName [exceptNameClass] +// | nameClass "|" nameClass +// | "(" nameClass ")" +// +// name ::= identifierOrKeyword | CName +- (PKCollectionParser *)nameParser { + if (!nameParser) { + self.nameParser = [PKAlternation alternation]; + [nameParser add:self.identifierOrKeywordParser]; + [nameParser add:self.CNameParser]; + } + return nameParser; +} + +// +// exceptNameClass ::= "-" nameClass +- (PKCollectionParser *)exceptNameClassParser { + if (!exceptNameClassParser) { + self.exceptNameClassParser = [PKSequence sequence]; + [nameParser add:[PKSymbol symbolWithString:@"-"]]; + [nameParser add:self.nameClassParser]; + } + return nameParser; +} + +// +// datatypeName ::= CName | "string" | "token" +- (PKCollectionParser *)datatypeNameParser { + if (!datatypeNameParser) { + self.datatypeNameParser = [PKAlternation alternation]; + [datatypeNameParser add:self.CNameParser]; + [datatypeNameParser add:self.stringKeywordParser]; + [datatypeNameParser add:self.tokenKeywordParser]; + } + return datatypeNameParser; +} + + +// +// datatypeValue ::= literal +- (PKCollectionParser *)datatypeValueParser { + if (!datatypeValueParser) { + self.datatypeValueParser = self.literalParser; + } + return datatypeValueParser; +} + + +// +// anyURILiteral ::= literal +- (PKCollectionParser *)anyURILiteralParser { + if (!anyURILiteralParser) { + self.anyURILiteralParser = self.literalParser; + } + return anyURILiteralParser; +} + + +// +// namespaceURILiteral ::= literal | "inherit" +// +// inherit ::= "inherit" "=" identifierOrKeyword +// +// identifierOrKeyword ::= identifier | keyword +// +// identifier ::= (NCName - keyword) | quotedIdentifier +// +// quotedIdentifier ::= "\" NCName +// +// CName ::= NCName ":" NCName +// +// nsName ::= NCName ":*" +// +// anyName ::= "*" +// +// literal ::= literalSegment ("~" literalSegment)+ +// +// literalSegment ::= '"' (Char - ('"' | newline))* '"' +// | "'" (Char - ("'" | newline))* "'" +// | '"""' (['"'] ['"'] (Char - '"'))* '"""' +// | "'''" (["'"] ["'"] (Char - "'"))* "'''" + + +// keyword ::= "attribute" +// | "default" +// | "datatypes" +// | "element" +// | "empty" +// | "external" +// | "grammar" +// | "include" +// | "inherit" +// | "list" +// | "mixed" +// | "namespace" +// | "notAllowed" +// | "parent" +// | "start" +// | "string" +// | "text" +// | "token" +// +- (PKParser *)keywordParser { + if (!keywordParser) { + self.keywordParser = [PKAlternation alternation]; + [keywordParser add:self.attributeKeywordParser]; + [keywordParser add:self.defaultKeywordParser]; + [keywordParser add:self.datatypesKeywordParser]; + [keywordParser add:self.elementKeywordParser]; + [keywordParser add:self.emptyKeywordParser]; + [keywordParser add:self.externalKeywordParser]; + [keywordParser add:self.grammarKeywordParser]; + [keywordParser add:self.includeKeywordParser]; + [keywordParser add:self.inheritKeywordParser]; + [keywordParser add:self.listKeywordParser]; + [keywordParser add:self.mixedKeywordParser]; + [keywordParser add:self.namespaceKeywordParser]; + [keywordParser add:self.notAllowedKeywordParser]; + [keywordParser add:self.parentKeywordParser]; + [keywordParser add:self.startKeywordParser]; + [keywordParser add:self.stringKeywordParser]; + [keywordParser add:self.textParser]; + [keywordParser add:self.tokenKeywordParser]; + } + return keywordParser; +} + + +- (PKParser *)attributeKeywordParser { + if (!attributeKeywordParser) { + self.attributeKeywordParser = [PKLiteral literalWithString:@"attribute"]; + } + return attributeKeywordParser; +} + + +- (PKParser *)defaultKeywordParser { + if (!defaultKeywordParser) { + self.defaultKeywordParser = [PKLiteral literalWithString:@"default"]; + } + return defaultKeywordParser; +} + + +- (PKParser *)datatypesKeywordParser { + if (!datatypesKeywordParser) { + self.datatypesKeywordParser = [PKLiteral literalWithString:@"datatypes"]; + } + return datatypesKeywordParser; +} + + +- (PKParser *)elementKeywordParser { + if (!elementKeywordParser) { + self.elementKeywordParser = [PKLiteral literalWithString:@"element"]; + } + return elementKeywordParser; +} + + +- (PKParser *)emptyKeywordParser { + if (!emptyKeywordParser) { + self.emptyKeywordParser = [PKLiteral literalWithString:@"empty"]; + } + return emptyKeywordParser; +} + + +- (PKParser *)externalKeywordParser { + if (!externalKeywordParser) { + self.externalKeywordParser = [PKLiteral literalWithString:@"external"]; + } + return externalKeywordParser; +} + + +- (PKParser *)grammarKeywordParser { + if (!grammarKeywordParser) { + self.grammarKeywordParser = [PKLiteral literalWithString:@"grammar"]; + } + return grammarKeywordParser; +} + + +- (PKParser *)includeKeywordParser { + if (!includeKeywordParser) { + self.includeKeywordParser = [PKLiteral literalWithString:@"include"]; + } + return includeKeywordParser; +} + + +- (PKParser *)inheritKeywordParser { + if (!inheritKeywordParser) { + self.inheritKeywordParser = [PKLiteral literalWithString:@"inherit"]; + } + return inheritKeywordParser; +} + + +- (PKParser *)listKeywordParser { + if (!listKeywordParser) { + self.listKeywordParser = [PKLiteral literalWithString:@"list"]; + } + return listKeywordParser; +} + + +- (PKParser *)mixedKeywordParser { + if (!mixedKeywordParser) { + self.mixedKeywordParser = [PKLiteral literalWithString:@"mixed"]; + } + return mixedKeywordParser; +} + + +- (PKParser *)namespaceKeywordParser { + if (!namespaceKeywordParser) { + self.namespaceKeywordParser = [PKLiteral literalWithString:@"namespace"]; + } + return namespaceKeywordParser; +} + + +- (PKParser *)notAllowedKeywordParser { + if (!notAllowedKeywordParser) { + self.notAllowedKeywordParser = [PKLiteral literalWithString:@"notAllowed"]; + } + return notAllowedKeywordParser; +} + + +- (PKParser *)parentKeywordParser { + if (!parentKeywordParser) { + self.parentKeywordParser = [PKLiteral literalWithString:@"parent"]; + } + return parentKeywordParser; +} + + +- (PKParser *)startKeywordParser { + if (!startKeywordParser) { + self.startKeywordParser = [PKLiteral literalWithString:@"start"]; + } + return startKeywordParser; +} + + +- (PKParser *)stringKeywordParser { + if (!stringKeywordParser) { + self.stringKeywordParser = [PKLiteral literalWithString:@"string"]; + } + return stringKeywordParser; +} + + +- (PKParser *)textKeywordParser { + if (!textKeywordParser) { + self.textKeywordParser = [PKLiteral literalWithString:@"text"]; + } + return textKeywordParser; +} + + +- (PKParser *)tokenKeywordParser { + if (!tokenKeywordParser) { + self.tokenKeywordParser = [PKLiteral literalWithString:@"token"]; + } + return tokenKeywordParser; +} + +@end diff --git a/test/SAXAssembler.h b/test/SAXAssembler.h new file mode 100644 index 0000000..b3f185a --- /dev/null +++ b/test/SAXAssembler.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface SAXAssembler : NSObject { + +} + +@end diff --git a/test/SAXAssembler.m b/test/SAXAssembler.m new file mode 100644 index 0000000..3d24354 --- /dev/null +++ b/test/SAXAssembler.m @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "SAXAssembler.h" +#import + +@implementation SAXAssembler + +- (void)didMatchSTag:(PKAssembly *)a { + +} + +@end diff --git a/test/SAXTest.h b/test/SAXTest.h new file mode 100644 index 0000000..a27b07a --- /dev/null +++ b/test/SAXTest.h @@ -0,0 +1,27 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface SAXTest : SenTestCase { + NSString *s; + NSString *g; + PKParserFactory *factory; + PKTokenAssembly *a; + PKAssembly *res; + PKParser *p; + PKTokenizer *t; +} + +@end diff --git a/test/SAXTest.m b/test/SAXTest.m new file mode 100644 index 0000000..58c20a8 --- /dev/null +++ b/test/SAXTest.m @@ -0,0 +1,33 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "SAXTest.h" + +@implementation SAXTest + +- (void)setUp { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xml" ofType:@"grammar"]; + g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + factory = [PKParserFactory factory]; + p = [factory parserFromGrammar:g assembler:self]; + t = p.tokenizer; +} + + +- (void)testSTag { + //PKParser *sTag = [p parserNamed:@"sTag"]; + +} + +@end diff --git a/test/SRGSParser.h b/test/SRGSParser.h new file mode 100644 index 0000000..9770e0e --- /dev/null +++ b/test/SRGSParser.h @@ -0,0 +1,94 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface SRGSParser : PKSequence { + PKCollectionParser *selfIdentHeader; + PKCollectionParser *ruleName; + PKCollectionParser *tagFormat; + PKCollectionParser *lexiconURI; + PKCollectionParser *weight; + PKCollectionParser *repeat; + PKCollectionParser *probability; + PKCollectionParser *externalRuleRef; + PKCollectionParser *token; + PKCollectionParser *languageAttachment; + PKCollectionParser *tag; + PKCollectionParser *grammar; + PKCollectionParser *declaration; + PKCollectionParser *baseDecl; + PKCollectionParser *languageDecl; + PKCollectionParser *modeDecl; + PKCollectionParser *rootRuleDecl; + PKCollectionParser *tagFormatDecl; + PKCollectionParser *lexiconDecl; + PKCollectionParser *metaDecl; + PKCollectionParser *tagDecl; + PKCollectionParser *ruleDefinition; + PKCollectionParser *scope; + PKCollectionParser *ruleExpansion; + PKCollectionParser *ruleAlternative; + PKCollectionParser *sequenceElement; + PKCollectionParser *subexpansion; + PKCollectionParser *ruleRef; + PKCollectionParser *localRuleRef; + PKCollectionParser *specialRuleRef; + PKCollectionParser *repeatOperator; + + PKCollectionParser *baseURI; + PKCollectionParser *languageCode; + PKCollectionParser *ABNF_URI; + PKCollectionParser *ABNF_URI_with_Media_Type; +} +- (id)parse:(NSString *)s; +- (PKAssembly *)assemblyWithString:(NSString *)s; + +@property (nonatomic, retain) PKCollectionParser *selfIdentHeader; +@property (nonatomic, retain) PKCollectionParser *ruleName; +@property (nonatomic, retain) PKCollectionParser *tagFormat; +@property (nonatomic, retain) PKCollectionParser *lexiconURI; +@property (nonatomic, retain) PKCollectionParser *weight; +@property (nonatomic, retain) PKCollectionParser *repeat; +@property (nonatomic, retain) PKCollectionParser *probability; +@property (nonatomic, retain) PKCollectionParser *externalRuleRef; +@property (nonatomic, retain) PKCollectionParser *token; +@property (nonatomic, retain) PKCollectionParser *languageAttachment; +@property (nonatomic, retain) PKCollectionParser *tag; +@property (nonatomic, retain) PKCollectionParser *grammar; +@property (nonatomic, retain) PKCollectionParser *declaration; +@property (nonatomic, retain) PKCollectionParser *baseDecl; +@property (nonatomic, retain) PKCollectionParser *languageDecl; +@property (nonatomic, retain) PKCollectionParser *modeDecl; +@property (nonatomic, retain) PKCollectionParser *rootRuleDecl; +@property (nonatomic, retain) PKCollectionParser *tagFormatDecl; +@property (nonatomic, retain) PKCollectionParser *lexiconDecl; +@property (nonatomic, retain) PKCollectionParser *metaDecl; +@property (nonatomic, retain) PKCollectionParser *tagDecl; +@property (nonatomic, retain) PKCollectionParser *ruleDefinition; +@property (nonatomic, retain) PKCollectionParser *scope; +@property (nonatomic, retain) PKCollectionParser *ruleExpansion; +@property (nonatomic, retain) PKCollectionParser *ruleAlternative; +@property (nonatomic, retain) PKCollectionParser *sequenceElement; +@property (nonatomic, retain) PKCollectionParser *subexpansion; +@property (nonatomic, retain) PKCollectionParser *ruleRef; +@property (nonatomic, retain) PKCollectionParser *localRuleRef; +@property (nonatomic, retain) PKCollectionParser *specialRuleRef; +@property (nonatomic, retain) PKCollectionParser *repeatOperator; + +@property (nonatomic, retain) PKCollectionParser *baseURI; +@property (nonatomic, retain) PKCollectionParser *languageCode; +@property (nonatomic, retain) PKCollectionParser *ABNF_URI; +@property (nonatomic, retain) PKCollectionParser *ABNF_URI_with_Media_Type; +@end diff --git a/test/SRGSParser.m b/test/SRGSParser.m new file mode 100644 index 0000000..0e36d23 --- /dev/null +++ b/test/SRGSParser.m @@ -0,0 +1,792 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "SRGSParser.h" +#import "NSString+ParseKitAdditions.h" + +@interface SRGSParser () +- (void)didMatchWord:(PKAssembly *)a; +- (void)didMatchNum:(PKAssembly *)a; +- (void)didMatchQuotedString:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchAssignment:(PKAssembly *)a; +- (void)didMatchVariable:(PKAssembly *)a; +@end + +@implementation SRGSParser + +- (id)init { + if (self = [super init]) { + [self add:self.grammar]; + } + return self; +} + + +- (void)dealloc { + self.selfIdentHeader = nil; + self.ruleName = nil; + self.tagFormat = nil; + self.lexiconURI = nil; + self.weight = nil; + self.repeat = nil; + self.probability = nil; + self.externalRuleRef = nil; + self.token = nil; + self.languageAttachment = nil; + self.tag = nil; + self.grammar = nil; + self.declaration = nil; + self.baseDecl = nil; + self.languageDecl = nil; + self.modeDecl = nil; + self.rootRuleDecl = nil; + self.tagFormatDecl = nil; + self.lexiconDecl = nil; + self.metaDecl = nil; + self.tagDecl = nil; + self.ruleDefinition = nil; + self.scope = nil; + self.ruleExpansion = nil; + self.ruleAlternative = nil; + self.sequenceElement = nil; + self.subexpansion = nil; + self.ruleRef = nil; + self.localRuleRef = nil; + self.specialRuleRef = nil; + self.repeatOperator = nil; + + self.baseURI = nil; + self.languageCode = nil; + self.ABNF_URI = nil; + self.ABNF_URI_with_Media_Type = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + PKAssembly *a = [self assemblyWithString:s]; + a = [self completeMatchFor:a]; + return [a pop]; +} + + +- (PKAssembly *)assemblyWithString:(NSString *)s { + PKTokenizer *t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + [t setTokenizerState:t.symbolState from: '-' to: '-']; + [t setTokenizerState:t.symbolState from: '.' to: '.']; + //[t.wordState setWordChars:YES from:'-' to:'-']; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; + // TDNCNameState *NCNameState = [[[TDNCNameState alloc] init] autorelease]; + return a; +} + + +//selfIdentHeader ::= '#ABNF' #x20 VersionNumber (#x20 CharEncoding)? ';' +//VersionNumber ::= '1.0' +//CharEncoding ::= Nmtoken +- (PKCollectionParser *)selfIdentHeader { + if (!selfIdentHeader) { + self.selfIdentHeader = [PKSequence sequence]; + selfIdentHeader.name = @"selfIdentHeader"; + + [selfIdentHeader add:[PKSymbol symbolWithString:@"#"]]; + [selfIdentHeader add:[PKLiteral literalWithString:@"ABNF"]]; + [selfIdentHeader add:[PKNumber number]]; // VersionNumber + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:[PKWord word]]; // CharEncoding + + [selfIdentHeader add:a]; + [selfIdentHeader add:[PKSymbol symbolWithString:@";"]]; + } + return selfIdentHeader; +} + + +//RuleName ::= '$' ConstrainedName +//ConstrainedName ::= Name - (Char* ('.' | ':' | '-') Char*) +- (PKCollectionParser *)ruleName { + if (!ruleName) { + self.ruleName = [PKSequence sequence]; + [ruleName add:[PKSymbol symbolWithString:@"$"]]; + [ruleName add:[PKWord word]]; // TODO: ConstrainedName + } + return ruleName; +} + +//TagFormat ::= ABNF_URI +- (PKCollectionParser *)tagFormat { + if (!tagFormat) { + self.tagFormat = self.ABNF_URI; + } + return tagFormat; +} + + +//LexiconURI ::= ABNF_URI | ABNF_URI_with_Media_Type +- (PKCollectionParser *)lexiconURI { + if (!lexiconURI) { + self.lexiconURI = [PKAlternation alternation]; + [lexiconURI add:self.ABNF_URI]; + [lexiconURI add:self.ABNF_URI_with_Media_Type]; + } + return lexiconURI; +} + + +//Weight ::= '/' Number '/' +- (PKCollectionParser *)weight { + if (!weight) { + self.weight = [PKSequence sequence]; + [weight add:[PKSymbol symbolWithString:@"/"]]; + [weight add:[PKNumber number]]; + [weight add:[PKSymbol symbolWithString:@"/"]]; + } + return weight; +} + + +//Repeat ::= [0-9]+ ('-' [0-9]*)? +- (PKCollectionParser *)repeat { + if (!repeat) { + self.repeat = [PKSequence sequence]; + [repeat add:[PKNumber number]]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"-"]]; + [s add:[PKNumber number]]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:s]; + + [repeat add:a]; + } + return repeat; +} + + +//Probability ::= '/' Number '/' +- (PKCollectionParser *)probability { + if (!probability) { + self.probability = [PKSequence sequence]; + [probability add:[PKSymbol symbolWithString:@"/"]]; + [probability add:[PKNumber number]]; + [probability add:[PKSymbol symbolWithString:@"/"]]; + } + return probability; +} + + + +//ExternalRuleRef ::= '$' ABNF_URI | '$' ABNF_URI_with_Media_Type +- (PKCollectionParser *)externalRuleRef { + if (!externalRuleRef) { + self.externalRuleRef = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"$"]]; + [s add:self.ABNF_URI]; + [externalRuleRef add:s]; + + s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"$"]]; + [s add:self.ABNF_URI_with_Media_Type]; + [externalRuleRef add:s]; + } + return externalRuleRef; +} + + +//Token ::= Nmtoken | DoubleQuotedCharacters +- (PKCollectionParser *)token { + if (!token) { + self.token = [PKAlternation alternation]; + [token add:[PKWord word]]; + [token add:[PKQuotedString quotedString]]; + } + return token; +} + + +//LanguageAttachment ::= '!' LanguageCode +- (PKCollectionParser *)languageAttachment { + if (!languageAttachment) { + self.languageAttachment = [PKSequence sequence]; + [languageAttachment add:[PKSymbol symbolWithString:@"!"]]; + [languageAttachment add:self.languageCode]; + } + return languageAttachment; +} + + +//Tag ::= '{' [^}]* '}' | '{!{' (Char* - (Char* '}!}' Char*)) '}!}' +- (PKCollectionParser *)tag { + if (!tag) { + self.tag = [PKAlternation alternation]; + + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"{"]]; + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKWord word]]; + [a add:[PKNumber number]]; + [a add:[PKSymbol symbol]]; + [a add:[PKQuotedString quotedString]]; + [s add:[PKRepetition repetitionWithSubparser:a]]; + [s add:[PKSymbol symbolWithString:@"}"]]; + [tag add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"{!{"]]; + a = [PKAlternation alternation]; + [a add:[PKWord word]]; + [a add:[PKNumber number]]; + [a add:[PKSymbol symbol]]; + [a add:[PKQuotedString quotedString]]; + [s add:[PKRepetition repetitionWithSubparser:a]]; + [s add:[PKLiteral literalWithString:@"}!}"]]; + [tag add:s]; + } + return tag; +} + + +#pragma mark - +#pragma mark Grammar + +// grammar ::= selfIdentHeader declaration* ruleDefinition* +- (PKCollectionParser *)grammar { + if (!grammar) { + self.grammar = [PKSequence sequence]; + [grammar add:self.selfIdentHeader]; + [grammar add:[PKRepetition repetitionWithSubparser:self.declaration]]; + [grammar add:[PKRepetition repetitionWithSubparser:self.ruleDefinition]]; + } + return grammar; +} + +// declaration ::= baseDecl | languageDecl | modeDecl | rootRuleDecl | tagFormatDecl | lexiconDecl | metaDecl | tagDecl +- (PKCollectionParser *)declaration { + if (!declaration) { + self.declaration = [PKAlternation alternation]; + [declaration add:self.baseDecl]; + [declaration add:self.languageDecl]; + [declaration add:self.modeDecl]; + [declaration add:self.rootRuleDecl]; + [declaration add:self.tagFormatDecl]; + [declaration add:self.lexiconDecl]; + [declaration add:self.tagDecl]; + } + return declaration; +} + +// baseDecl ::= 'base' BaseURI ';' +- (PKCollectionParser *)baseDecl { + if (!baseDecl) { + self.baseDecl = [PKSequence sequence]; + [baseDecl add:[PKLiteral literalWithString:@"base"]]; + [baseDecl add:self.baseURI]; + [baseDecl add:[PKSymbol symbolWithString:@";"]]; + } + return baseDecl; +} + +// languageDecl ::= 'language' LanguageCode ';' +- (PKCollectionParser *)languageDecl { + if (!languageDecl) { + self.languageDecl = [PKSequence sequence]; + [languageDecl add:[PKLiteral literalWithString:@"language"]]; + [languageDecl add:self.languageCode]; + [languageDecl add:[PKSymbol symbolWithString:@";"]]; + } + return languageDecl; +} + + + +// modeDecl ::= 'mode' 'voice' ';' | 'mode' 'dtmf' ';' +- (PKCollectionParser *)modeDecl { + if (!modeDecl) { + self.modeDecl = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"mode"]]; + [s add:[PKLiteral literalWithString:@"voice"]]; + [s add:[PKSymbol symbolWithString:@";"]]; + [modeDecl add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"mode"]]; + [s add:[PKLiteral literalWithString:@"dtmf"]]; + [s add:[PKSymbol symbolWithString:@";"]]; + [modeDecl add:s]; + } + return modeDecl; +} + + +// rootRuleDecl ::= 'root' RuleName ';' +- (PKCollectionParser *)rootRuleDecl { + if (!rootRuleDecl) { + self.rootRuleDecl = [PKSequence sequence]; + [rootRuleDecl add:[PKLiteral literalWithString:@"root"]]; + [rootRuleDecl add:self.ruleName]; + [rootRuleDecl add:[PKSymbol symbolWithString:@";"]]; + } + return rootRuleDecl; +} + + +// tagFormatDecl ::= 'tag-format' TagFormat ';' +- (PKCollectionParser *)tagFormatDecl { + if (!tagFormatDecl) { + self.tagFormatDecl = [PKSequence sequence]; + [tagFormatDecl add:[PKLiteral literalWithString:@"tag-format"]]; + [tagFormatDecl add:self.tagFormat]; + [tagFormatDecl add:[PKSymbol symbolWithString:@";"]]; + } + return tagFormatDecl; +} + + + +// lexiconDecl ::= 'lexicon' LexiconURI ';' +- (PKCollectionParser *)lexiconDecl { + if (!lexiconDecl) { + self.lexiconDecl = [PKSequence sequence]; + [lexiconDecl add:[PKLiteral literalWithString:@"lexicon"]]; + [lexiconDecl add:self.lexiconURI]; + [lexiconDecl add:[PKSymbol symbolWithString:@";"]]; + } + return lexiconDecl; +} + + +// metaDecl ::= +// 'http-equiv' QuotedCharacters 'is' QuotedCharacters ';' +// | 'meta' QuotedCharacters 'is' QuotedCharacters ';' +- (PKCollectionParser *)metaDecl { + if (!metaDecl) { + self.metaDecl = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"http-equiv"]]; + [s add:[PKQuotedString quotedString]]; + [s add:[PKLiteral literalWithString:@"is"]]; + [s add:[PKQuotedString quotedString]]; + [s add:[PKSymbol symbolWithString:@";"]]; + [metaDecl add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"meta"]]; + [s add:[PKQuotedString quotedString]]; + [s add:[PKLiteral literalWithString:@"is"]]; + [s add:[PKQuotedString quotedString]]; + [s add:[PKSymbol symbolWithString:@";"]]; + [metaDecl add:s]; + } + return metaDecl; +} + + + +// tagDecl ::= Tag ';' +- (PKCollectionParser *)tagDecl { + if (!tagDecl) { + self.tagDecl = [PKSequence sequence]; + [tagDecl add:self.tag]; + [tagDecl add:[PKSymbol symbolWithString:@";"]]; + } + return tagDecl; +} + + +// ruleDefinition ::= scope? RuleName '=' ruleExpansion ';' +- (PKCollectionParser *)ruleDefinition { + if (!ruleDefinition) { + self.ruleDefinition = [PKSequence sequence]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.scope]; + + [ruleDefinition add:a]; + [ruleDefinition add:self.ruleName]; + [ruleDefinition add:[PKSymbol symbolWithString:@"="]]; + [ruleDefinition add:self.ruleExpansion]; + [ruleDefinition add:[PKSymbol symbolWithString:@";"]]; + } + return ruleDefinition; +} + +// scope ::= 'private' | 'public' +- (PKCollectionParser *)scope { + if (!scope) { + self.scope = [PKAlternation alternation]; + [scope add:[PKLiteral literalWithString:@"private"]]; + [scope add:[PKLiteral literalWithString:@"public"]]; + } + return scope; +} + + +// ruleExpansion ::= ruleAlternative ( '|' ruleAlternative )* +- (PKCollectionParser *)ruleExpansion { + if (!ruleExpansion) { + self.ruleExpansion = [PKSequence sequence]; + [ruleExpansion add:self.ruleAlternative]; + + PKSequence *pipeRuleAlternative = [PKSequence sequence]; + [pipeRuleAlternative add:[PKSymbol symbolWithString:@"|"]]; + [pipeRuleAlternative add:self.ruleAlternative]; + [ruleExpansion add:[PKRepetition repetitionWithSubparser:pipeRuleAlternative]]; + } + return ruleExpansion; +} + + +// ruleAlternative ::= Weight? sequenceElement+ +- (PKCollectionParser *)ruleAlternative { + if (!ruleAlternative) { + self.ruleAlternative = [PKSequence sequence]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.weight]; + + [ruleAlternative add:a]; + [ruleAlternative add:self.sequenceElement]; + [ruleAlternative add:[PKRepetition repetitionWithSubparser:self.sequenceElement]]; + } + return ruleAlternative; +} + +// sequenceElement ::= subexpansion | subexpansion repeatOperator + +// me: changing to: +// sequenceElement ::= subexpansion repeatOperator? +- (PKCollectionParser *)sequenceElement { + if (!sequenceElement) { +// self.sequenceElement = [PKAlternation alternation]; +// [sequenceElement add:self.subexpansion]; +// +// PKSequence *s = [PKSequence sequence]; +// [s add:self.subexpansion]; +// [s add:self.repeatOperator]; +// +// [sequenceElement add:s]; + + self.sequenceElement = [PKSequence sequence]; + [sequenceElement add:self.subexpansion]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.repeatOperator]; + + [sequenceElement add:a]; + } + return sequenceElement; +} + +// subexpansion ::= +// Token LanguageAttachment? +// | ruleRef +// | Tag +// | '(' ')' +// | '(' ruleExpansion ')' LanguageAttachment? +// | '[' ruleExpansion ']' LanguageAttachment? +- (PKCollectionParser *)subexpansion { + if (!subexpansion) { + self.subexpansion = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:self.token]; + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.languageAttachment]; + [s add:a]; + [subexpansion add:s]; + + [subexpansion add:self.ruleRef]; + [subexpansion add:self.tag]; + + s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:[PKSymbol symbolWithString:@")"]]; + [subexpansion add:s]; + + s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:self.ruleExpansion]; + [s add:[PKSymbol symbolWithString:@")"]]; + a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.languageAttachment]; + [s add:a]; + [subexpansion add:s]; + + s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"["]]; + [s add:self.ruleExpansion]; + [s add:[PKSymbol symbolWithString:@"]"]]; + a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.languageAttachment]; + [s add:a]; + [subexpansion add:s]; + } + return subexpansion; +} + + +// ruleRef ::= localRuleRef | ExternalRuleRef | specialRuleRef +- (PKCollectionParser *)ruleRef { + if (!ruleRef) { + self.ruleRef = [PKAlternation alternation]; + [ruleRef add:self.localRuleRef]; + [ruleRef add:self.externalRuleRef]; + [ruleRef add:self.specialRuleRef]; + } + return ruleRef; +} + +// localRuleRef ::= RuleName +- (PKCollectionParser *)localRuleRef { + if (!localRuleRef) { + self.localRuleRef = self.ruleName; + } + return localRuleRef; +} + + +// specialRuleRef ::= '$NULL' | '$VOID' | '$GARBAGE' +- (PKCollectionParser *)specialRuleRef { + if (!specialRuleRef) { + self.specialRuleRef = [PKAlternation alternation]; + [specialRuleRef add:[PKLiteral literalWithString:@"$NULL"]]; + [specialRuleRef add:[PKLiteral literalWithString:@"$VOID"]]; + [specialRuleRef add:[PKLiteral literalWithString:@"$GARBAGE"]]; + } + return specialRuleRef; +} + + +// repeatOperator ::='<' Repeat Probability? '>' +- (PKCollectionParser *)repeatOperator { + if (!repeatOperator) { + self.repeatOperator = [PKSequence sequence]; + [repeatOperator add:[PKSymbol symbolWithString:@"<"]]; + [repeatOperator add:self.repeat]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.probability]; + [repeatOperator add:a]; + + [repeatOperator add:[PKSymbol symbolWithString:@">"]]; + } + return repeatOperator; +} + + +//BaseURI ::= ABNF_URI +- (PKCollectionParser *)baseURI { + if (!baseURI) { + self.baseURI = [PKWord word]; + } + return baseURI; +} + + +//LanguageCode ::= Nmtoken +- (PKCollectionParser *)languageCode { + if (!languageCode) { + self.languageCode = [PKSequence sequence]; + [languageCode add:[PKWord word]]; +// [languageCode add:[PKSymbol symbolWithString:@"-"]]; +// [languageCode add:[PKWord word]]; + } + return languageCode; +} + + +- (PKCollectionParser *)ABNF_URI { + if (!ABNF_URI) { + self.ABNF_URI = [PKWord word]; + } + return ABNF_URI; +} + + +- (PKCollectionParser *)ABNF_URI_with_Media_Type { + if (!ABNF_URI_with_Media_Type) { + self.ABNF_URI_with_Media_Type = [PKWord word]; + } + return ABNF_URI_with_Media_Type; +} + + + +#pragma mark - +#pragma mark Assembler Methods + +- (void)didMatchWord:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + [a push:[PKLiteral literalWithString:tok.stringValue]]; +} + + +- (void)didMatchNum:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + [a push:[PKLiteral literalWithString:tok.stringValue]]; +} + + +- (void)didMatchQuotedString:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *tok = [a pop]; + NSString *s = [tok.stringValue stringByTrimmingQuotes]; + + PKSequence *p = [PKSequence sequence]; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *eof = [PKToken EOFToken]; + while (eof != (tok = [t nextToken])) { + [p add:[PKLiteral literalWithString:tok.stringValue]]; + } + + [a push:p]; +} + + +- (void)didMatchStar:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKRepetition *p = [PKRepetition repetitionWithSubparser:[a pop]]; + [a push:p]; +} + + +- (void)didMatchQuestion:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKAlternation *p = [PKAlternation alternation]; + [p add:[a pop]]; + [p add:[PKEmpty empty]]; + [a push:p]; +} + + +- (void)didMatchAnd:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id top = [a pop]; + PKSequence *p = [PKSequence sequence]; + [p add:[a pop]]; + [p add:top]; + [a push:p]; +} + + +- (void)didMatchOr:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id top = [a pop]; +// NSLog(@"top: %@", top); +// NSLog(@"top class: %@", [top class]); + PKAlternation *p = [PKAlternation alternation]; + [p add:[a pop]]; + [p add:top]; + [a push:p]; +} + + +- (void)didMatchAssignment:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id val = [a pop]; + PKToken *keyTok = [a pop]; + + NSMutableDictionary *table = [NSMutableDictionary dictionaryWithDictionary:a.target]; + [table setObject:val forKey:keyTok.stringValue]; + a.target = table; +} + + +- (void)didMatchVariable:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + PKToken *keyTok = [a pop]; + id val = [a.target objectForKey:keyTok.stringValue]; + +// PKParser *p = nil; +// if (valTok.isWord) { +// p = [PKWord wordWithString:valTok.value]; +// } else if (valTok.isQuotedString) { +// p = [PKQuotedString quotedStringWithString:valTok.value]; +// } else if (valTok.isNumber) { +// p = [PKNum numWithString:valTok.stringValue]; +// } + + [a push:val]; +} + +@synthesize selfIdentHeader; +@synthesize ruleName; +@synthesize tagFormat; +@synthesize lexiconURI; +@synthesize weight; +@synthesize repeat; +@synthesize probability; +@synthesize externalRuleRef; +@synthesize token; +@synthesize languageAttachment; +@synthesize tag; +@synthesize grammar; +@synthesize declaration; +@synthesize baseDecl; +@synthesize languageDecl; +@synthesize modeDecl; +@synthesize rootRuleDecl; +@synthesize tagFormatDecl; +@synthesize lexiconDecl; +@synthesize metaDecl; +@synthesize tagDecl; +@synthesize ruleDefinition; +@synthesize scope; +@synthesize ruleExpansion; +@synthesize ruleAlternative; +@synthesize sequenceElement; +@synthesize subexpansion; +@synthesize ruleRef; +@synthesize localRuleRef; +@synthesize specialRuleRef; +@synthesize repeatOperator; + +@synthesize baseURI; +@synthesize languageCode; +@synthesize ABNF_URI; +@synthesize ABNF_URI_with_Media_Type; +@end \ No newline at end of file diff --git a/test/SRGSParserTest.h b/test/SRGSParserTest.h new file mode 100644 index 0000000..3908fb3 --- /dev/null +++ b/test/SRGSParserTest.h @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +#import "SRGSParser.h" + +@interface SRGSParserTest : SenTestCase { + NSString *s; + SRGSParser *p; + PKAssembly *a; + PKAssembly *result; +} + +@end diff --git a/test/SRGSParserTest.m b/test/SRGSParserTest.m new file mode 100644 index 0000000..482ab06 --- /dev/null +++ b/test/SRGSParserTest.m @@ -0,0 +1,202 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "SRGSParserTest.h" + +@implementation SRGSParserTest + +- (void)setUp { + p = [[[SRGSParser alloc] init] autorelease]; +} + + +- (void)test { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"example1" ofType:@"srgs"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDNotNil(result); + NSLog(@"\n\n\n result: %@ \n\n\n", result); +// TDEqualObjects(@"[#, ABNF, 1.0, ;]#/ABNF/1.0/;^", [result description]); +} + +- (void)testSelfIdentHeader { + s = @"#ABNF 1.0;"; + a = [p assemblyWithString:s]; + result = [p.selfIdentHeader bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[#, ABNF, 1.0, ;]#/ABNF/1.0/;^", [result description]); + + s = @"#ABNF 1.0 UTF;"; + a = [p assemblyWithString:s]; + result = [p.selfIdentHeader bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[#, ABNF, 1.0, UTF, ;]#/ABNF/1.0/UTF/;^", [result description]); +} + + +- (void)testRuleName { + s = @"$foobar"; + a = [p assemblyWithString:s]; + result = [p.ruleName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[$, foobar]$/foobar^", [result description]); +} + + +- (void)testWeight { + s = @"/4.0/"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [p.weight bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[/, 4.0, /]//4.0//^", [result description]); +} + + +- (void)testProbability { + s = @"/4.0/"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [p.probability bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[/, 4.0, /]//4.0//^", [result description]); +} + + +- (void)testRepeat { + s = @"1 - 4"; + a = [p assemblyWithString:s]; + result = [p.repeat bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[1, -, 4]1/-/4^", [result description]); + + s = @"1-4"; + a = [p assemblyWithString:s]; + result = [p.repeat bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[1, -, 4]1/-/4^", [result description]); +} + + +- (void)testToken { + s = @"foobar"; + a = [p assemblyWithString:s]; + result = [p.token bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foobar]foobar^", [result description]); + + s = @"'foobar'"; + a = [p assemblyWithString:s]; + result = [p.token bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"['foobar']'foobar'^", [result description]); +} + + +- (void)testTag { + s = @"{foobar}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, foobar, }]{/foobar/}^", [result description]); + + s = @"{bar baz}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, bar, baz, }]{/bar/baz/}^", [result description]); + + s = @"{bar 1.2 baz}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, bar, 1.2, baz, }]{/bar/1.2/baz/}^", [result description]); + + s = @"{!{'foobar'}!}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, !, {, 'foobar', }, !, }]{/!/{/'foobar'/}/!/}^", [result description]); + + s = @"{!{'foobar' baz}!}"; + a = [p assemblyWithString:s]; + result = [p.tag bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[{, !, {, 'foobar', baz, }, !, }]{/!/{/'foobar'/baz/}/!/}^", [result description]); +} + + +- (void)testBaseDecl { + s = @"base url-goes-here;"; + a = [p assemblyWithString:s]; + result = [p.baseDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[base, url-goes-here, ;]base/url-goes-here/;^", [result description]); +} + + +- (void)testLanguageDecl { + s = @"language en-us;"; + a = [p assemblyWithString:s]; + result = [p.languageDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[language, en-us, ;]language/en-us/;^", [result description]); +} + + +- (void)testModeDecl { + s = @"mode voice;"; + a = [p assemblyWithString:s]; + result = [p.modeDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[mode, voice, ;]mode/voice/;^", [result description]); + + s = @"mode dtmf;"; + a = [p assemblyWithString:s]; + result = [p.modeDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[mode, dtmf, ;]mode/dtmf/;^", [result description]); +} + + +- (void)testRootRuleDecl { + s = @"root $foobar;"; + a = [p assemblyWithString:s]; + result = [p.rootRuleDecl bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[root, $, foobar, ;]root/$/foobar/;^", [result description]); +} + + +- (void)testLanguageAttachment { + s = @"!en-us"; + a = [p assemblyWithString:s]; + result = [p.languageAttachment bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[!, en-us]!/en-us^", [result description]); +} + + +- (void)testRepeatOperator { + s = @"<0-2 /0.6/>"; + a = [p assemblyWithString:s]; + result = [p.repeatOperator bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[<, 0, -, 2, /, 0.6, /, >]^", [result description]); +} + + + + +@end diff --git a/test/TDAlternationTest.h b/test/TDAlternationTest.h new file mode 100644 index 0000000..02de3e0 --- /dev/null +++ b/test/TDAlternationTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDAlternationTest : SenTestCase { + PKCollectionParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/TDAlternationTest.m b/test/TDAlternationTest.m new file mode 100644 index 0000000..1a1a303 --- /dev/null +++ b/test/TDAlternationTest.m @@ -0,0 +1,103 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDAlternationTest.h" + +@implementation TDAlternationTest + +- (void)tearDown { + [a release]; +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz { + s = @"foo baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKAlternation alternation]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo]foo^baz/bar", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz1 { + s = @"123 baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKAlternation alternation]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + [p add:[PKNumber number]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^baz/bar", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz2 { + s = @"123 baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + PKParser *w = [PKWord word]; + PKParser *baz = [PKLiteral literalWithString:@"baz"]; + PKParser *n = [PKNumber number]; + p = [PKAlternation alternationWithSubparsers:w, baz, n, nil]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^baz/bar", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz3 { + s = @"123 baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKAlternation alternation]; + [p add:[PKWord word]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKNumber number]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^baz/bar", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz4 { + s = @"123 baz bar"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKAlternation alternation]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + [p add:[PKNumber number]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^baz/bar", [result description]); +} + +@end diff --git a/test/TDArithmeticAssembler.h b/test/TDArithmeticAssembler.h new file mode 100644 index 0000000..4cac6d5 --- /dev/null +++ b/test/TDArithmeticAssembler.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDArithmeticAssembler : NSObject { + +} + +@end diff --git a/test/TDArithmeticAssembler.m b/test/TDArithmeticAssembler.m new file mode 100644 index 0000000..330a304 --- /dev/null +++ b/test/TDArithmeticAssembler.m @@ -0,0 +1,64 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDArithmeticAssembler.h" +#import + +@implementation TDArithmeticAssembler + +- (void)didMatchPlus:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + [a push:[NSNumber numberWithDouble:tok1.floatValue + tok2.floatValue]]; +} + + +- (void)didMatchMinus:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + [a push:[NSNumber numberWithDouble:tok1.floatValue - tok2.floatValue]]; +} + + +- (void)didMatchTimes:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + [a push:[NSNumber numberWithDouble:tok1.floatValue * tok2.floatValue]]; +} + + +- (void)didMatchDivide:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + [a push:[NSNumber numberWithDouble:tok1.floatValue / tok2.floatValue]]; +} + + +- (void)didMatchExp:(PKAssembly *)a { + PKToken *tok2 = [a pop]; + PKToken *tok1 = [a pop]; + + CGFloat n1 = tok1.floatValue; + CGFloat n2 = tok2.floatValue; + + CGFloat res = n1; + NSUInteger i = 1; + for ( ; i < n2; i++) { + res *= n1; + } + + [a push:[NSNumber numberWithDouble:res]]; +} + +@end diff --git a/test/TDArithmeticParser.h b/test/TDArithmeticParser.h new file mode 100644 index 0000000..54ff67a --- /dev/null +++ b/test/TDArithmeticParser.h @@ -0,0 +1,39 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDArithmeticParser : PKSequence { + PKCollectionParser *exprParser; + PKCollectionParser *termParser; + PKCollectionParser *plusTermParser; + PKCollectionParser *minusTermParser; + PKCollectionParser *factorParser; + PKCollectionParser *timesFactorParser; + PKCollectionParser *divFactorParser; + PKCollectionParser *exponentFactorParser; + PKCollectionParser *phraseParser; +} +- (double)parse:(NSString *)s; + +@property (retain) PKCollectionParser *exprParser; +@property (retain) PKCollectionParser *termParser; +@property (retain) PKCollectionParser *plusTermParser; +@property (retain) PKCollectionParser *minusTermParser; +@property (retain) PKCollectionParser *factorParser; +@property (retain) PKCollectionParser *timesFactorParser; +@property (retain) PKCollectionParser *divFactorParser; +@property (retain) PKCollectionParser *exponentFactorParser; +@property (retain) PKCollectionParser *phraseParser; +@end diff --git a/test/TDArithmeticParser.m b/test/TDArithmeticParser.m new file mode 100644 index 0000000..6fb8240 --- /dev/null +++ b/test/TDArithmeticParser.m @@ -0,0 +1,253 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDArithmeticParser.h" + +/* + expr = term (plusTerm | minusTerm)* + term = factor (timesFactor | divFactor)* + plusTerm = '+' term + minusTerm = '-' term + factor = phrase exponentFactor | phrase + timesFactor = '*' factor + divFactor = '/' factor + exponentFactor = '^' factor + phrase = '(' expr ')' | Number +*/ + +@implementation TDArithmeticParser + +- (id)init { + if (self = [super init]) { + [self add:self.exprParser]; + } + return self; +} + + +- (void)dealloc { + self.exprParser = nil; + self.termParser = nil; + self.plusTermParser = nil; + self.minusTermParser = nil; + self.factorParser = nil; + self.timesFactorParser = nil; + self.divFactorParser = nil; + self.exponentFactorParser = nil; + self.phraseParser = nil; + [super dealloc]; +} + + +- (double)parse:(NSString *)s { + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + a = [self completeMatchFor:a]; +// NSLog(@"\n\na: %@\n\n", a); + NSNumber *n = [a pop]; + double f = [n doubleValue]; + return f; +} + + +// expr = term (plusTerm | minusTerm)* +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + [exprParser add:self.termParser]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:self.plusTermParser]; + [a add:self.minusTermParser]; + + [exprParser add:[PKRepetition repetitionWithSubparser:a]]; + } + return exprParser; +} + + +// term = factor (timesFactor | divFactor)* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + [termParser add:self.factorParser]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:self.timesFactorParser]; + [a add:self.divFactorParser]; + + [termParser add:[PKRepetition repetitionWithSubparser:a]]; + } + return termParser; +} + + +// plusTerm = '+' term +- (PKCollectionParser *)plusTermParser { + if (!plusTermParser) { + self.plusTermParser = [PKSequence sequence]; + [plusTermParser add:[[PKSymbol symbolWithString:@"+"] discard]]; + [plusTermParser add:self.termParser]; + [plusTermParser setAssembler:self selector:@selector(didMatchPlus:)]; + } + return plusTermParser; +} + + +// minusTerm = '-' term +- (PKCollectionParser *)minusTermParser { + if (!minusTermParser) { + self.minusTermParser = [PKSequence sequence]; + [minusTermParser add:[[PKSymbol symbolWithString:@"-"] discard]]; + [minusTermParser add:self.termParser]; + [minusTermParser setAssembler:self selector:@selector(didMatchMinus:)]; + } + return minusTermParser; +} + + +// factor = phrase exponentFactor | phrase +- (PKCollectionParser *)factorParser { + if (!factorParser) { + self.factorParser = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:self.phraseParser]; + [s add:self.exponentFactorParser]; + + [factorParser add:s]; + [factorParser add:self.phraseParser]; + } + return factorParser; +} + + +// timesFactor = '*' factor +- (PKCollectionParser *)timesFactorParser { + if (!timesFactorParser) { + self.timesFactorParser = [PKSequence sequence]; + [timesFactorParser add:[[PKSymbol symbolWithString:@"*"] discard]]; + [timesFactorParser add:self.factorParser]; + [timesFactorParser setAssembler:self selector:@selector(didMatchTimes:)]; + } + return timesFactorParser; +} + + +// divFactor = '/' factor +- (PKCollectionParser *)divFactorParser { + if (!divFactorParser) { + self.divFactorParser = [PKSequence sequence]; + [divFactorParser add:[[PKSymbol symbolWithString:@"/"] discard]]; + [divFactorParser add:self.factorParser]; + [divFactorParser setAssembler:self selector:@selector(didMatchDivide:)]; + } + return divFactorParser; +} + + +// exponentFactor = '^' factor +- (PKCollectionParser *)exponentFactorParser { + if (!exponentFactorParser) { + self.exponentFactorParser = [PKSequence sequence]; + [exponentFactorParser add:[[PKSymbol symbolWithString:@"^"] discard]]; + [exponentFactorParser add:self.factorParser]; + [exponentFactorParser setAssembler:self selector:@selector(didMatchExp:)]; + } + return exponentFactorParser; +} + + +// phrase = '(' expr ')' | Number +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + self.phraseParser = [PKAlternation alternation]; + + PKSequence *s = [PKSequence sequence]; + [s add:[[PKSymbol symbolWithString:@"("] discard]]; + [s add:self.exprParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + [phraseParser add:s]; + + PKNumber *n = [PKNumber number]; + [n setAssembler:self selector:@selector(didMatchNumber:)]; + [phraseParser add:n]; + } + return phraseParser; +} + + +#pragma mark - +#pragma mark Assembler + +- (void)didMatchNumber:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithDouble:tok.floatValue]]; +} + + +- (void)didMatchPlus:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + [a push:[NSNumber numberWithDouble:[n1 doubleValue] + [n2 doubleValue]]]; +} + + +- (void)didMatchMinus:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + [a push:[NSNumber numberWithDouble:[n1 doubleValue] - [n2 doubleValue]]]; +} + + +- (void)didMatchTimes:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + [a push:[NSNumber numberWithDouble:[n1 doubleValue] * [n2 doubleValue]]]; +} + + +- (void)didMatchDivide:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + [a push:[NSNumber numberWithDouble:[n1 doubleValue] / [n2 doubleValue]]]; +} + + +- (void)didMatchExp:(PKAssembly *)a { + NSNumber *n2 = [a pop]; + NSNumber *n1 = [a pop]; + + double d1 = [n1 doubleValue]; + double d2 = [n2 doubleValue]; + + double res = d1; + NSUInteger i = 1; + for ( ; i < d2; i++) { + res *= d1; + } + + [a push:[NSNumber numberWithDouble:res]]; +} + +@synthesize exprParser; +@synthesize termParser; +@synthesize plusTermParser; +@synthesize minusTermParser; +@synthesize factorParser; +@synthesize timesFactorParser; +@synthesize divFactorParser; +@synthesize exponentFactorParser; +@synthesize phraseParser; +@end diff --git a/test/TDArithmeticParserTest.h b/test/TDArithmeticParserTest.h new file mode 100644 index 0000000..c8a8389 --- /dev/null +++ b/test/TDArithmeticParserTest.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "TDArithmeticParser.h" + +@interface TDArithmeticParserTest : SenTestCase { + NSString *s; + TDArithmeticParser *p; + double result; +} + +@end diff --git a/test/TDArithmeticParserTest.m b/test/TDArithmeticParserTest.m new file mode 100644 index 0000000..8f9da90 --- /dev/null +++ b/test/TDArithmeticParserTest.m @@ -0,0 +1,348 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDArithmeticParserTest.h" + +@implementation TDArithmeticParserTest + +- (void)setUp { + p = [TDArithmeticParser parser]; +} + + +- (void)testOne { + s = @"1"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)testFortySeven { + s = @"47"; + result = [p parse:s]; + TDEquals((double)47.0, result); +} + + +- (void)testNegativeZero { + s = @"-0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testNegativeOne { + s = @"-1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testOnePlusOne { + s = @"1 + 1"; + result = [p parse:s]; + TDEquals((double)2.0, result); +} + + +- (void)testOnePlusNegativeOne { + s = @"1 + -1"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testNegativeOnePlusOne { + s = @"-1 + 1"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testOneHundredPlusZero { + s = @"100 + 0"; + result = [p parse:s]; + TDEquals((double)100.0, result); +} + + +- (void)testNegativeOnePlusZero { + s = @"-1 + 0"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testNegativeZeroPlusZero { + s = @"-0 + 0"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testNegativeZeroPlusNegativeZero { + s = @"-0 + -0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testOneMinusOne { + s = @"1 - 1"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testOneMinusNegativeOne { + s = @"1 - -1"; + result = [p parse:s]; + TDEquals((double)2.0, result); +} + + +- (void)testNegativeOneMinusOne { + s = @"-1 - 1"; + result = [p parse:s]; + TDEquals((double)-2.0, result); +} + + +- (void)testOneHundredMinusZero { + s = @"100 - 0"; + result = [p parse:s]; + TDEquals((double)100.0, result); +} + + +- (void)testNegativeOneMinusZero { + s = @"-1 - 0"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testNegativeZeroMinusZero { + s = @"-0 - 0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testNegativeZeroMinusNegativeZero { + s = @"-0 - -0"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testOneTimesOne { + s = @"1 * 1"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)testTwoTimesFour { + s = @"2 * 4"; + result = [p parse:s]; + TDEquals((double)8.0, result); +} + + +- (void)testOneTimesNegativeOne { + s = @"1 * -1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testNegativeOneTimesOne { + s = @"-1 * 1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testOneHundredTimesZero { + s = @"100 * 0"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testNegativeOneTimesZero { + s = @"-1 * 0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testNegativeZeroTimesZero { + s = @"-0 * 0"; + result = [p parse:s]; + TDEquals((double)-0.0, result); +} + + +- (void)testNegativeZeroTimesNegativeZero { + s = @"-0 * -0"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)testOneDivOne { + s = @"1 / 1"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)testTwoDivFour { + s = @"2 / 4"; + result = [p parse:s]; + TDEquals((double)0.5f, result); +} + + +- (void)testFourDivTwo { + s = @"4 / 2"; + result = [p parse:s]; + TDEquals((double)2.0, result); +} + + +- (void)testOneDivNegativeOne { + s = @"1 / -1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testNegativeOneDivOne { + s = @"-1 / 1"; + result = [p parse:s]; + TDEquals((double)-1.0, result); +} + + +- (void)testOneHundredDivZero { + s = @"100 / 0"; + result = [p parse:s]; + TDEquals((double)INFINITY, result); +} + + +- (void)testNegativeOneDivZero { + s = @"-1 / 0"; + result = [p parse:s]; + TDEquals((double)-INFINITY, result); +} + + +- (void)testNegativeZeroDivZero { + s = @"-0 / 0"; + result = [p parse:s]; + TDEquals((double)NAN, result); +} + + +- (void)testNegativeZeroDivNegativeZero { + s = @"-0 / -0"; + result = [p parse:s]; + TDEquals((double)NAN, result); +} + + +- (void)test1Exp1 { + s = @"1 ^ 1"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)test1Exp2 { + s = @"1 ^ 2"; + result = [p parse:s]; + TDEquals((double)1.0, result); +} + + +- (void)test9Exp2 { + s = @"9 ^ 2"; + result = [p parse:s]; + TDEquals((double)81.0, result); +} + + +- (void)test9ExpNegative2 { + s = @"9 ^ -2"; + result = [p parse:s]; + TDEquals((double)9.0, result); +} + + +#pragma mark - +#pragma mark Associativity + +- (void)test7minus3minus1 { // minus associativity + s = @"7 - 3 - 1"; + result = [p parse:s]; + TDEquals((double)3.0, (double)result); +} + + +- (void)test9exp2minus81 { // exp associativity + s = @"9^2 - 81"; + result = [p parse:s]; + TDEquals((double)0.0, result); +} + + +- (void)test2exp1exp4 { // exp + s = @"2 ^ 1 ^ 4"; + result = [p parse:s]; + TDEquals((double)2.0, result); +} + + +- (void)test100minus5exp2times3 { // exp + s = @"100 - 5^2*3"; + result = [p parse:s]; + TDEquals((double)25.0, result); +} + + +- (void)test100minus25times3 { // precedence + s = @"100 - 25*3"; + result = [p parse:s]; + STAssertEqualsWithAccuracy((double)25.0, result, 1.0, @""); +} + + +- (void)test100minus25times3Parens { // precedence + s = @"(100 - 25)*3"; + result = [p parse:s]; + TDEquals((double)225.0, result); +} + + +- (void)test100minus5exp2times3Parens { // precedence + s = @"(100 - 5^2)*3"; + result = [p parse:s]; + TDEquals((double)225.0, result); +} + +@end diff --git a/test/TDBlob.h b/test/TDBlob.h new file mode 100644 index 0000000..4fd9f5d --- /dev/null +++ b/test/TDBlob.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDBlob : PKTerminal { + +} ++ (id)blob; + ++ (id)blobWithStartMarker:(NSString *)s; +@end diff --git a/test/TDBlob.m b/test/TDBlob.m new file mode 100644 index 0000000..bd7dcba --- /dev/null +++ b/test/TDBlob.m @@ -0,0 +1,40 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDBlob.h" +#import +#import "PKToken+Blob.h" + +@implementation TDBlob + ++ (id)blob { + return [self blobWithStartMarker:nil]; +} + + ++ (id)blobWithStartMarker:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + BOOL result = tok.isBlob; + if (self.string) { + result = [tok.stringValue hasPrefix:self.string]; + } + return result; +} + +@end diff --git a/test/TDBlobState.h b/test/TDBlobState.h new file mode 100644 index 0000000..a1c07f0 --- /dev/null +++ b/test/TDBlobState.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDBlobState : PKTokenizerState { + +} + +@end diff --git a/test/TDBlobState.m b/test/TDBlobState.m new file mode 100644 index 0000000..3560258 --- /dev/null +++ b/test/TDBlobState.m @@ -0,0 +1,51 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDBlobState.h" +#import +#import +#import "PKToken+Blob.h" + +@interface PKToken () +@property (nonatomic, readwrite) NSUInteger offset; +@end + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation TDBlobState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + PKUniChar c = cin; + do { + [self append:c]; + c = [r read]; + } while (PKEOF != c && !isspace(c)); + + if (PKEOF != c) { + [r unread]; + } + + PKToken *tok = [PKToken tokenWithTokenType:PKTokenTypeBlob stringValue:[self bufferedString] floatValue:0.0]; + tok.offset = offset; + return tok; +} + +@end diff --git a/test/TDCharTest.h b/test/TDCharTest.h new file mode 100644 index 0000000..29288d0 --- /dev/null +++ b/test/TDCharTest.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + + +@interface TDCharTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + PKChar *p; + PKAssembly *result; +} + +@end diff --git a/test/TDCharTest.m b/test/TDCharTest.m new file mode 100644 index 0000000..8655c8f --- /dev/null +++ b/test/TDCharTest.m @@ -0,0 +1,65 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDCharTest.h" + +@interface PKAssembly () +- (BOOL)hasMore; +@end + +@implementation TDCharTest + +- (void)test123 { + s = @"123"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^123", [a description]); + p = [PKChar char]; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[1]1^23", [result description]); + TDTrue([a hasMore]); +} + + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKChar char]; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a]a^bc", [result description]); + TDTrue([a hasMore]); +} + +- (void)testRepetition { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKChar char]; + PKParser *r = [PKRepetition repetitionWithSubparser:p]; + + result = [r bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a, b, c]abc^", [result description]); + TDFalse([result hasMore]); +} + + +@end diff --git a/test/TDCharacterAssemblyTest.h b/test/TDCharacterAssemblyTest.h new file mode 100644 index 0000000..ff8d0a2 --- /dev/null +++ b/test/TDCharacterAssemblyTest.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + + +@interface TDCharacterAssemblyTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + PKAssembly *result; +} + +@end diff --git a/test/TDCharacterAssemblyTest.m b/test/TDCharacterAssemblyTest.m new file mode 100644 index 0000000..48118c3 --- /dev/null +++ b/test/TDCharacterAssemblyTest.m @@ -0,0 +1,65 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDCharacterAssemblyTest.h" + +@interface PKAssembly () +- (id)next; +- (BOOL)hasMore; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@property (nonatomic, readonly) NSUInteger objectsRemaining; +@end + +@implementation TDCharacterAssemblyTest + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDNotNil(a); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)0, a.objectsConsumed); + TDEquals((NSUInteger)3, a.objectsRemaining); + TDEquals(YES, [a hasMore]); + + id obj = [a next]; + TDEqualObjects(obj, [NSNumber numberWithInteger:'a']); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)1, a.objectsConsumed); + TDEquals((NSUInteger)2, a.objectsRemaining); + TDEquals(YES, [a hasMore]); + + obj = [a next]; + TDEqualObjects(obj, [NSNumber numberWithInteger:'b']); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)2, a.objectsConsumed); + TDEquals((NSUInteger)1, a.objectsRemaining); + TDEquals(YES, [a hasMore]); + + obj = [a next]; + TDEqualObjects(obj, [NSNumber numberWithInteger:'c']); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)3, a.objectsConsumed); + TDEquals((NSUInteger)0, a.objectsRemaining); + TDEquals(NO, [a hasMore]); + + obj = [a next]; + TDNil(obj); + TDEquals((NSUInteger)3, [s length]); + TDEquals((NSUInteger)3, a.objectsConsumed); + TDEquals((NSUInteger)0, a.objectsRemaining); + TDEquals(NO, [a hasMore]); +} + +@end diff --git a/test/TDCommentStateTest.h b/test/TDCommentStateTest.h new file mode 100644 index 0000000..7f4d89d --- /dev/null +++ b/test/TDCommentStateTest.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDCommentStateTest : SenTestCase { + PKCommentState *commentState; + PKReader *r; + PKTokenizer *t; + NSString *s; + PKToken *tok; +} + +@end diff --git a/test/TDCommentStateTest.m b/test/TDCommentStateTest.m new file mode 100644 index 0000000..90c96a7 --- /dev/null +++ b/test/TDCommentStateTest.m @@ -0,0 +1,492 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDCommentStateTest.h" + +@implementation TDCommentStateTest + +- (void)setUp { + r = [[PKReader alloc] init]; + t = [[PKTokenizer alloc] init]; + commentState = t.commentState; +} + + +- (void)tearDown { + [r release]; + [t release]; +} + + +- (void)testSlashSlashFoo { + s = @"// foo"; + r.string = s; + t.string = s; + tok = [commentState nextTokenFromReader:r startingWith:'/' tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(tok.offset, (NSUInteger)-1); + TDEquals([r read], PKEOF); +} + + +- (void)testReportSlashSlashFoo { + s = @"// foo"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.offset, (NSUInteger)0); + TDEqualObjects([t nextToken], [PKToken EOFToken]); +} + + +- (void)testReportSpaceSlashSlashFoo { + s = @" // foo"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"// foo"); + TDEquals(tok.offset, (NSUInteger)1); + TDEqualObjects([t nextToken], [PKToken EOFToken]); +} + + +- (void)testTurnOffSlashSlashFoo { + s = @"// foo"; + r.string = s; + t.string = s; + [commentState removeSingleLineStartMarker:@"//"]; + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"/"); + TDEquals(tok.offset, (NSUInteger)0); + TDEquals([r read], (PKUniChar)'/'); +} + + +- (void)testHashFoo { + s = @"# foo"; + r.string = s; + t.string = s; + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.offset, (NSUInteger)2); + + r.string = s; + t.string = s; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)1); +} + + +- (void)testAddHashFoo { + s = @"# foo"; + t.string = s; + [commentState addSingleLineStartMarker:@"#"]; + [t setTokenizerState:commentState from:'#' to:'#']; + tok = [t nextToken]; + TDEquals(tok, [PKToken EOFToken]); + TDEqualObjects(tok.stringValue, [[PKToken EOFToken] stringValue]); + TDEquals(tok.offset, (NSUInteger)-1); +} + + +- (void)testReportAddHashFoo { + s = @"# foo"; + t.string = s; + commentState.reportsCommentTokens = YES; + [commentState addSingleLineStartMarker:@"#"]; + [t setTokenizerState:commentState from:'#' to:'#']; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testSlashStarFooStarSlash { + s = @"/* foo */"; + t.string = s; + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals([r read], PKEOF); +} + + +- (void)testSlashStarFooStarSlashSpace { + s = @"/* foo */ "; + t.string = s; + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals([r read], PKEOF); +} + + +- (void)testReportSlashStarFooStarSlash { + s = @"/* foo */"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals([t nextToken], [PKToken EOFToken]); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testReportSlashStarFooStarSlashSpace { + s = @"/* foo */ "; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEquals(tok.offset, (NSUInteger)0); + TDEqualObjects(tok.stringValue, @"/* foo */"); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); +} + + +- (void)testReportSlashStarFooStarSlashSpaceA { + s = @"/* foo */ a"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)10); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)9); +} + + +- (void)testReportSlashStarStarFooStarSlashSpaceA { + s = @"/** foo */ a"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/** foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)11); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/** foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)10); +} + + +- (void)testReportSlashStarFooStarStarSlashSpaceA { + s = @"/* foo **/ a"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo **/"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)11); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo **/"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)10); +} + + +- (void)testReportSlashStarFooStarSlashSpaceStarSlash { + s = @"/* foo */ */"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"*"); + TDEquals(tok.offset, (NSUInteger)10); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)9); +} + + +- (void)testTurnOffSlashStarFooStarSlash { + s = @"/* foo */"; + t.string = s; + [commentState removeMultiLineStartMarker:@"/*"]; + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"/"); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testReportSlashStarFooStar { + s = @"/* foo *"; + t.string = s; + commentState.reportsCommentTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testReportBalancedSlashStarFooStar { + s = @"/* foo *"; + t.string = s; + commentState.reportsCommentTokens = YES; + commentState.balancesEOFTerminatedComments = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo **/"); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testReportBalancedSlashStarFoo { + s = @"/* foo "; + t.string = s; + commentState.reportsCommentTokens = YES; + commentState.balancesEOFTerminatedComments = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/* foo */"); + TDEquals(tok.offset, (NSUInteger)0); +} + + +- (void)testXMLFooStarXMLA { + s = @" a"; + t.string = s; + [commentState addMultiLineStartMarker:@""]; + [t setTokenizerState:commentState from:'<' to:'<']; + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)13); + + t.string = s; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)12); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)13); +} + + +- (void)testReportXMLFooStarXMLA { + s = @" a"; + t.string = s; + commentState.reportsCommentTokens = YES; + [commentState addMultiLineStartMarker:@""]; + [t setTokenizerState:commentState from:'<' to:'<']; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @""); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + TDEquals(tok.offset, (NSUInteger)13); + + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @""); + TDEquals(tok.offset, (NSUInteger)0); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals(tok.offset, (NSUInteger)12); +} + + +- (void)testXXMarker { + s = @"XX foo XX a"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + [commentState addMultiLineStartMarker:@"XX" endMarker:@"XX"]; + [t setTokenizerState:commentState from:'X' to:'X']; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"XX foo XX"); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + t.whitespaceState.reportsWhitespaceTokens = YES; + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"XX foo XX"); + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); +} + + +- (void)testXXMarkerFalseStartMarkerMatch { + s = @"X foo X a"; + r.string = s; + t.string = s; + commentState.reportsCommentTokens = YES; + [commentState addMultiLineStartMarker:@"XX" endMarker:@"XX"]; + [t setTokenizerState:commentState from:'X' to:'X']; + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"X"); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"X"); + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"a"); + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLuaComments { + s = @"--[comment"; + t.string = s; + + [t setTokenizerState:t.symbolState from:'/' to:'/']; + [t setTokenizerState:t.commentState from:'-' to:'-']; + + [t.commentState addSingleLineStartMarker:@"--"]; + [t.commentState addMultiLineStartMarker:@"--[[" endMarker:@"]]"]; + + t.commentState.reportsCommentTokens = YES; + + PKToken *eof = [PKToken EOFToken]; + + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + + tok = [t nextToken]; + TDEquals(eof, tok); +} + + +- (void)testLuaComments2 { + s = @"--[[[comment]]"; + t.string = s; + + [t setTokenizerState:t.symbolState from:'/' to:'/']; + [t setTokenizerState:t.commentState from:'-' to:'-']; + + [t.commentState addSingleLineStartMarker:@"--"]; + [t.commentState addMultiLineStartMarker:@"--[[" endMarker:@"]]"]; + + t.commentState.reportsCommentTokens = YES; + + PKToken *eof = [PKToken EOFToken]; + + tok = [t nextToken]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + + tok = [t nextToken]; + TDEquals(eof, tok); +} + +@end diff --git a/test/TDDelimitStateTest.h b/test/TDDelimitStateTest.h new file mode 100644 index 0000000..86df9ce --- /dev/null +++ b/test/TDDelimitStateTest.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDDelimitStateTest : SenTestCase { + PKDelimitState *delimitState; + PKTokenizer *t; + NSString *s; + PKToken *tok; +} + +@end diff --git a/test/TDDelimitStateTest.m b/test/TDDelimitStateTest.m new file mode 100644 index 0000000..29211b8 --- /dev/null +++ b/test/TDDelimitStateTest.m @@ -0,0 +1,830 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDDelimitStateTest.h" + +@implementation TDDelimitStateTest + +- (void)setUp { + t = [[PKTokenizer alloc] init]; + delimitState = t.delimitState; +} + + +- (void)tearDown { + [t release]; +} + + +- (void)testLtFooGt { + s = @""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testSlashFooSlash { + s = @"/foo/"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'/' to:'/']; + [delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testSlashFooSlashBar { + s = @"/foo/bar"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'/' to:'/']; + [delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"/foo/"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"bar"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testSlashFooSlashSemi { + s = @"/foo/;"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'/' to:'/']; + [delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"/foo/"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @";"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtFooGtWithFOAllowed { + s = @""; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"fo"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtFooGtWithFAllowed { + s = @""; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"f"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @">"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtFooGtWithFAllowedAndRemove { + s = @""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<" endMarker:@">" allowedCharacterSet:cs]; + [delimitState removeStartMarker:@"<"]; + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @">"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooGt { + s = @"<#foo>"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<#" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooGtWithFOAllowed { + s = @"<#foo>"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"fo"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<#" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooGtWithFAllowed { + s = @"<#foo>"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"f"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<#" endMarker:@">" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @">"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooGtWithFAllowedAndMultiCharSymbol { + s = @"<#foo>"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"f"]; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"<#" endMarker:@">" allowedCharacterSet:cs]; + + [t.symbolState add:@"<#"]; + + tok = [t nextToken]; + + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @">"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooHashGt { + s = @"=#foo#="; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'=' to:'=']; + [delimitState addStartMarker:@"=#" endMarker:@"#=" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooHashGtWithFOAllowed { + s = @"=#foo#="; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"fo"]; + + [t setTokenizerState:delimitState from:'=' to:'=']; + [delimitState addStartMarker:@"=#" endMarker:@"#=" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtHashFooHashGtWithFAllowed { + s = @"=#foo#="; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"f"]; + + [t setTokenizerState:delimitState from:'=' to:'=']; + [delimitState addStartMarker:@"=#" endMarker:@"#=" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"="); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"="); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollar123Dollar { + s = @"$123$"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$" endMarker:@"$" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarDollar { + s = @"$$123$$"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$$" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHash { + s = @"$$123$#"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHashDecimalDigitAllowed { + s = @"$$123$#"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet decimalDigitCharacterSet]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHashAlphanumericAllowed { + s = @"$$123$#"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet alphanumericCharacterSet]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHashAlphanumericAndWhitespaceAndNewlineAllowed { + s = @"$$123 456\t789\n0$#"; + t.string = s; + NSMutableCharacterSet *cs = [[[NSCharacterSet alphanumericCharacterSet] mutableCopy] autorelease]; + [cs formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]]; + [cs formUnionWithCharacterSet:[NSCharacterSet newlineCharacterSet]]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollar123DollarHashWhitespaceAllowed { + s = @"$$123$#"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet whitespaceCharacterSet]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"123"); + TDEquals(tok.floatValue, (CGFloat)123.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollarDollarHash { + s = @"$$$#"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollarDollar { + s = @"$$$"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"$"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testLtDollarDollarDollarBalanceEOFStrings { + s = @"$$$"; + t.string = s; + NSCharacterSet *cs = nil; + + delimitState.balancesEOFTerminatedStrings = YES; + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"$$" endMarker:@"$#" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"$$$$#"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testPHPPrint { + s = @""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testPHP { + s = @""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'<' to:'<']; + [delimitState addStartMarker:@"" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testEnvVars { + s = @"${PRODUCT_NAME} or ${EXECUTABLE_NAME}"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ_"]; + + [t setTokenizerState:delimitState from:'$' to:'$']; + [delimitState addStartMarker:@"${" endMarker:@"}" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"${PRODUCT_NAME}"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"or"); + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"${EXECUTABLE_NAME}"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testCocoaString { + s = @"@\"foo\""; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'@' to:'@']; + [delimitState addStartMarker:@"@\"" endMarker:@"\"" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAlphaMarkerXX { + s = @"XXfooXX"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'X' to:'X']; + [delimitState addStartMarker:@"XX" endMarker:@"XX" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAlphaMarkerXXAndXXX { + s = @"XXfooXXX"; + t.string = s; + NSCharacterSet *cs = nil; + + [t setTokenizerState:delimitState from:'X' to:'X']; + [delimitState addStartMarker:@"XX" endMarker:@"XXX" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAlphaMarkerXXFails { + s = @"XXfooXX"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet whitespaceCharacterSet]; + + [t setTokenizerState:delimitState from:'X' to:'X']; + [delimitState addStartMarker:@"XX" endMarker:@"XX" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAlphaMarkerXXFalseStartMarker { + s = @"XfooXX"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet whitespaceCharacterSet]; + + [t setTokenizerState:delimitState from:'X' to:'X']; + [delimitState addStartMarker:@"XX" endMarker:@"XX" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAtStartMarkerNilEndMarker { + s = @"@foo"; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet alphanumericCharacterSet]; + + [t setTokenizerState:delimitState from:'@' to:'@']; + [delimitState addStartMarker:@"@" endMarker:nil allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, s); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testAtStartMarkerNilEndMarker2 { + s = @"@foo bar @ @baz "; + t.string = s; + NSCharacterSet *cs = [NSCharacterSet alphanumericCharacterSet]; + + [t setTokenizerState:delimitState from:'@' to:'@']; + [delimitState addStartMarker:@"@" endMarker:nil allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"@foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"bar"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"@"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @"@baz"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDEqualObjects(tok, [PKToken EOFToken]); +} + + +- (void)testUnbalancedElementStartTag { + s = @"" allowedCharacterSet:cs]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"<"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEquals(tok.floatValue, (CGFloat)0.0); + + t.string = s; + delimitState.allowsUnbalancedStrings = YES; + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(tok.stringValue, @" + +@class PKTokenizer; +@class PKToken; + +@interface TDFastJsonParser : NSObject { + PKTokenizer *tokenizer; + NSMutableArray *stack; + PKToken *curly; + PKToken *bracket; +} +- (id)parse:(NSString *)s; +@end diff --git a/test/TDFastJsonParser.m b/test/TDFastJsonParser.m new file mode 100644 index 0000000..5fa6733 --- /dev/null +++ b/test/TDFastJsonParser.m @@ -0,0 +1,141 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDFastJsonParser.h" +#import "ParseKit.h" +#import "NSString+ParseKitAdditions.h" + +@interface TDFastJsonParser () +- (void)didMatchDictionary; +- (void)didMatchArray; +- (NSArray *)objectsAbove:(id)fence; + +@property (retain) PKTokenizer *tokenizer; +@property (retain) NSMutableArray *stack; +@property (retain) PKToken *curly; +@property (retain) PKToken *bracket; +@end + +@implementation TDFastJsonParser + +- (id)init { + if (self = [super init]) { + self.tokenizer = [PKTokenizer tokenizer]; + + // configure tokenizer + [tokenizer setTokenizerState:tokenizer.symbolState from: '/' to: '/']; // JSON doesn't have slash slash or slash star comments + [tokenizer setTokenizerState:tokenizer.symbolState from: '\'' to: '\'']; // JSON does not have single quoted strings + + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.0]; + self.bracket = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"[" floatValue:0.0]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.stack = nil; + self.curly = nil; + self.bracket = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + self.stack = [NSMutableArray array]; + + tokenizer.string = s; + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + while ((tok = [tokenizer nextToken]) != eof) { + NSString *sval = tok.stringValue; + + if (tok.isSymbol) { + if ([@"{" isEqualToString:sval]) { + [stack addObject:tok]; + } else if ([@"}" isEqualToString:sval]) { + [self didMatchDictionary]; + } else if ([@"[" isEqualToString:sval]) { + [stack addObject:tok]; + } else if ([@"]" isEqualToString:sval]) { + [self didMatchArray]; + } + } else { + id value = nil; + if (tok.isQuotedString) { + value = [sval stringByTrimmingQuotes]; + } else if (tok.isNumber) { + value = [NSNumber numberWithFloat:tok.floatValue]; + } else { // if (tok.isWord) { + if ([@"null" isEqualToString:sval]) { + value = [NSNull null]; + } else if ([@"true" isEqualToString:sval]) { + value = [NSNumber numberWithBool:YES]; + } else if ([@"false" isEqualToString:sval]) { + value = [NSNumber numberWithBool:NO]; + } + } + [stack addObject:value]; + } + } + + return [stack lastObject]; +} + + +- (void)didMatchDictionary { + NSArray *a = [self objectsAbove:curly]; + NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:[a count]/2.]; + + NSInteger i = [a count] - 1; + for ( ; i >= 0; i--) { + NSString *key = [a objectAtIndex:i--]; + id value = [a objectAtIndex:i]; + [result setObject:value forKey:key]; + } + + [stack addObject:result]; +} + + +- (void)didMatchArray { + NSArray *a = [self objectsAbove:bracket]; + NSMutableArray *result = [NSMutableArray arrayWithCapacity:[a count]]; + for (id obj in [a reverseObjectEnumerator]) { + [result addObject:obj]; + } + [stack addObject:result]; +} + + +- (NSArray *)objectsAbove:(id)fence { + NSMutableArray *result = [NSMutableArray array]; + while (1) { + id obj = [stack lastObject]; + [stack removeLastObject]; + if ([obj isEqual:fence]) { + break; + } + [result addObject:obj]; + } + return result; +} + +@synthesize stack; +@synthesize tokenizer; +@synthesize curly; +@synthesize bracket; +@end diff --git a/test/TDFastJsonParserTest.h b/test/TDFastJsonParserTest.h new file mode 100644 index 0000000..ecc5213 --- /dev/null +++ b/test/TDFastJsonParserTest.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "ParseKit.h" + +@interface TDFastJsonParserTest : SenTestCase { + +} + +@end diff --git a/test/TDFastJsonParserTest.m b/test/TDFastJsonParserTest.m new file mode 100644 index 0000000..46a6c5d --- /dev/null +++ b/test/TDFastJsonParserTest.m @@ -0,0 +1,39 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDFastJsonParserTest.h" +#import "TDFastJsonParser.h" + +@implementation TDFastJsonParserTest + +- (void)testRun { + NSString *s = @"{\"foo\":\"bar\"}"; + TDFastJsonParser *p = [[[TDFastJsonParser alloc] init] autorelease]; + id result = [p parse:s]; + + NSLog(@"result"); + TDNotNil(result); +} + + +- (void)testCrunchBaseJsonParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDFastJsonParser *parser = [[[TDFastJsonParser alloc] init] autorelease]; + [parser parse:s]; + // id res = [parser parse:s]; + //NSLog(@"res %@", res); +} + +@end diff --git a/test/TDGenericAssembler.h b/test/TDGenericAssembler.h new file mode 100644 index 0000000..6c502db --- /dev/null +++ b/test/TDGenericAssembler.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKAssembly; + +@interface TDGenericAssembler : NSObject { + NSMutableDictionary *attributes; + NSMutableDictionary *defaultProperties; + NSMutableDictionary *productionNames; + PKAssembly *currentAssembly; + NSString *prefix; + NSString *suffix; +} +@property (nonatomic, retain) NSMutableDictionary *attributes; +@property (nonatomic, retain) NSMutableDictionary *defaultProperties; +@property (nonatomic, retain) NSMutableDictionary *productionNames; +@property (nonatomic, retain) PKAssembly *currentAssembly; +@end diff --git a/test/TDGenericAssembler.m b/test/TDGenericAssembler.m new file mode 100644 index 0000000..31921fd --- /dev/null +++ b/test/TDGenericAssembler.m @@ -0,0 +1,175 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDGenericAssembler.h" +#import "NSArray+ParseKitAdditions.h" +#import + +@interface TDGenericAssembler () +- (void)didMatchTerminalNamed:(NSString *)name withAssembly:(PKAssembly *)a; +- (void)appendAttributedStringForObjects:(NSArray *)objs withAttrs:(id)attrs; +- (void)appendAttributedStringForObject:(id)obj withAttrs:(id)attrs; +- (NSMutableArray *)popWhitespaceTokensFrom:(PKAssembly *)a; +- (void)consumeWhitespaceTokens:(NSArray *)whitespaceToks; +- (void)consumeWhitespaceToken:(PKToken *)whitespaceTok; +- (void)consumeWhitespaceFrom:(PKAssembly *)a; + +@property (nonatomic, retain) NSString *prefix; +@property (nonatomic, retain) NSString *suffix; +@end + +@implementation TDGenericAssembler + +- (id)init { + if (self = [super init]) { + self.productionNames = [NSMutableDictionary dictionary]; + self.defaultProperties = [NSDictionary dictionaryWithObjectsAndKeys: + [NSColor blackColor], NSForegroundColorAttributeName, + [NSColor whiteColor], NSBackgroundColorAttributeName, + [NSFont fontWithName:@"Monaco" size:11.0], NSFontAttributeName, + nil]; + self.prefix = @"didMatch"; + self.suffix = @":"; + } + return self; +} + + +- (void)dealloc { + self.attributes = nil; + self.defaultProperties = nil; + self.productionNames = nil; + self.currentAssembly = nil; + self.prefix = nil; + self.suffix = nil; + [super dealloc]; +} + + +- (BOOL)respondsToSelector:(SEL)sel { + return YES; +} + + +- (id)performSelector:(SEL)sel withObject:(id)obj { + NSString *selName = NSStringFromSelector(sel); + + NSString *productionName = [productionNames objectForKey:selName]; + + if (!productionName) { + NSUInteger prefixLen = [prefix length]; + NSInteger c = ((NSInteger)[selName characterAtIndex:prefixLen]) + 32; // lowercase + NSRange r = NSMakeRange(prefixLen + 1, [selName length] - (prefixLen + [suffix length] + 1 /*:*/)); + productionName = [NSString stringWithFormat:@"%C%@", c, [selName substringWithRange:r]]; + [productionNames setObject:productionName forKey:selName]; + } + + [self didMatchTerminalNamed:productionName withAssembly:obj]; + + return nil; +} + + +- (void)didMatchTerminalNamed:(NSString *)name withAssembly:(PKAssembly *)a { + //NSLog(@"%@ : %@", name, a); + self.currentAssembly = a; + NSMutableArray *whitespaceToks = [self popWhitespaceTokensFrom:a]; + + id props = [attributes objectForKey:name]; + if (!props) props = defaultProperties; + + NSMutableArray *toks = nil; + PKToken *tok = nil; + while (tok = [a pop]) { + if (PKTokenTypeWhitespace != tok.tokenType) { + if (!toks) toks = [NSMutableArray array]; + [toks addObject:tok]; + } else { + [self consumeWhitespaceToken:tok]; + break; + } + } + + [self consumeWhitespaceFrom:a]; + [self appendAttributedStringForObjects:toks withAttrs:props]; + [self consumeWhitespaceTokens:whitespaceToks]; +} + + +- (void)appendAttributedStringForObjects:(NSArray *)objs withAttrs:(id)attrs { + for (id obj in objs) { + [self appendAttributedStringForObject:obj withAttrs:attrs]; + } +} + + +- (void)appendAttributedStringForObject:(id)obj withAttrs:(id)attrs { + NSMutableAttributedString *displayString = currentAssembly.target; + if (!displayString) { + displayString = [[[NSMutableAttributedString alloc] initWithString:@"" attributes:nil] autorelease]; + currentAssembly.target = displayString; + } + + + NSAttributedString *as = [[NSAttributedString alloc] initWithString:[obj stringValue] attributes:attrs]; + [displayString appendAttributedString:as]; + [as release]; +} + + +- (NSMutableArray *)popWhitespaceTokensFrom:(PKAssembly *)a { + NSMutableArray *whitespaceToks = nil; + PKToken *tok = nil; + while (tok = [a pop]) { + if (PKTokenTypeWhitespace == tok.tokenType) { + if (!whitespaceToks) { + whitespaceToks = [NSMutableArray array]; + } + [whitespaceToks addObject:tok]; + } else { + [a push:tok]; + break; + } + } + if (whitespaceToks) { + whitespaceToks = [whitespaceToks reversedMutableArray]; + } + return whitespaceToks; +} + + +- (void)consumeWhitespaceTokens:(NSArray *)whitespaceToks { + [self appendAttributedStringForObjects:whitespaceToks withAttrs:nil]; +} + + +- (void)consumeWhitespaceToken:(PKToken *)whitespaceTok { + [self appendAttributedStringForObject:whitespaceTok withAttrs:nil]; +} + + +- (void)consumeWhitespaceFrom:(PKAssembly *)a { + NSMutableArray *whitespaceToks = [self popWhitespaceTokensFrom:a]; + if (whitespaceToks) { + [self consumeWhitespaceTokens:whitespaceToks]; + } +} + +@synthesize attributes; +@synthesize defaultProperties; +@synthesize productionNames; +@synthesize currentAssembly; +@synthesize prefix; +@synthesize suffix; +@end diff --git a/test/TDGenericAssemblerTest.h b/test/TDGenericAssemblerTest.h new file mode 100644 index 0000000..006cc69 --- /dev/null +++ b/test/TDGenericAssemblerTest.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" +#import "TDMiniCSSAssembler.h" +#import "TDGenericAssembler.h" + +@interface TDGenericAssemblerTest : SenTestCase { + NSString *path; + NSString *grammarString; + NSString *s; + TDMiniCSSAssembler *cssAssember; + PKParserFactory *factory; + PKParser *cssParser; + PKAssembly *a; + TDGenericAssembler *genericAssember; +} + +@end diff --git a/test/TDGenericAssemblerTest.m b/test/TDGenericAssemblerTest.m new file mode 100644 index 0000000..2b26d93 --- /dev/null +++ b/test/TDGenericAssemblerTest.m @@ -0,0 +1,72 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDGenericAssemblerTest.h" + +@implementation TDGenericAssemblerTest + +- (void)setUp { + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + cssAssember = [[TDMiniCSSAssembler alloc] init]; + factory = [PKParserFactory factory]; + cssParser = [factory parserFromGrammar:grammarString assembler:cssAssember]; +} + + +- (void)tearDown { + [cssAssember release]; +} + + +- (void)testColor { + TDNotNil(cssParser); + + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"css"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + a = [PKTokenAssembly assemblyWithString:s]; + a = [cssParser bestMatchFor:a]; + + TDNotNil(cssAssember.attributes); + id props = [cssAssember.attributes objectForKey:@"openCurly"]; + TDNotNil(props); + +// color:red; +// background-color:blue; +// font-family:'Helvetica'; +// font-size:17px; + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Monaco"); + TDEquals((CGFloat)[font pointSize], (CGFloat)11.0); + + NSColor *bgColor = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(bgColor); + STAssertEqualsWithAccuracy([bgColor redComponent], (CGFloat)0.117, 0.001, @""); + STAssertEqualsWithAccuracy([bgColor greenComponent], (CGFloat)0.117, 0.001, @""); + STAssertEqualsWithAccuracy([bgColor blueComponent], (CGFloat)0.141, 0.001, @""); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)0.7, 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)0.14, 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)0.530, 0.001, @""); + +} + + + + +@end diff --git a/test/TDHtmlSyntaxHighlighter.h b/test/TDHtmlSyntaxHighlighter.h new file mode 100644 index 0000000..7eb7803 --- /dev/null +++ b/test/TDHtmlSyntaxHighlighter.h @@ -0,0 +1,60 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKTokenizer; +@class PKToken; + +@interface TDHtmlSyntaxHighlighter : NSObject { + BOOL isDarkBG; + BOOL inScript; + PKTokenizer *tokenizer; + NSMutableArray *stack; + PKToken *ltToken; + PKToken *gtToken; + PKToken *startCommentToken; + PKToken *endCommentToken; + PKToken *startCDATAToken; + PKToken *endCDATAToken; + PKToken *startPIToken; + PKToken *endPIToken; + PKToken *startDoctypeToken; + PKToken *fwdSlashToken; + PKToken *eqToken; + PKToken *scriptToken; + PKToken *endScriptToken; + + NSMutableAttributedString *highlightedString; + NSDictionary *tagAttributes; + NSDictionary *textAttributes; + NSDictionary *attrNameAttributes; + NSDictionary *attrValueAttributes; + NSDictionary *eqAttributes; + NSDictionary *commentAttributes; + NSDictionary *piAttributes; +} +- (id)initWithAttributesForDarkBackground:(BOOL)isDark; + +- (NSAttributedString *)attributedStringForString:(NSString *)s; + +@property (nonatomic, retain) NSMutableAttributedString *highlightedString; +@property (nonatomic, retain) NSDictionary *tagAttributes; +@property (nonatomic, retain) NSDictionary *textAttributes; +@property (nonatomic, retain) NSDictionary *attrNameAttributes; +@property (nonatomic, retain) NSDictionary *attrValueAttributes; +@property (nonatomic, retain) NSDictionary *eqAttributes; +@property (nonatomic, retain) NSDictionary *commentAttributes; +@property (nonatomic, retain) NSDictionary *piAttributes; +@end diff --git a/test/TDHtmlSyntaxHighlighter.m b/test/TDHtmlSyntaxHighlighter.m new file mode 100644 index 0000000..28c5747 --- /dev/null +++ b/test/TDHtmlSyntaxHighlighter.m @@ -0,0 +1,583 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDHtmlSyntaxHighlighter.h" +#import "NSArray+ParseKitAdditions.h" +#import + +@interface TDHtmlSyntaxHighlighter () +- (void)didMatchTag; +- (void)didMatchText; +- (void)didMatchComment; +- (void)didMatchCDATA; +- (void)didMatchPI; +- (void)didMatchDoctype; +- (void)didMatchScript; +- (id)peek; +- (id)pop; +- (NSArray *)objectsAbove:(id)fence; +- (PKToken *)nextNonWhitespaceTokenFrom:(NSEnumerator *)e; +- (void)consumeWhitespaceOnStack; + +@property (retain) PKTokenizer *tokenizer; +@property (retain) NSMutableArray *stack; +@property (retain) PKToken *ltToken; +@property (retain) PKToken *gtToken; +@property (retain) PKToken *startCommentToken; +@property (retain) PKToken *endCommentToken; +@property (retain) PKToken *startCDATAToken; +@property (retain) PKToken *endCDATAToken; +@property (retain) PKToken *startPIToken; +@property (retain) PKToken *endPIToken; +@property (retain) PKToken *startDoctypeToken; +@property (retain) PKToken *fwdSlashToken; +@property (retain) PKToken *eqToken; +@property (retain) PKToken *scriptToken; +@property (retain) PKToken *endScriptToken; +@end + +@implementation TDHtmlSyntaxHighlighter + +- (id)init { + return [self initWithAttributesForDarkBackground:NO]; +} + + +- (id)initWithAttributesForDarkBackground:(BOOL)isDark { + if (self = [super init]) { + isDarkBG = isDark; + self.tokenizer = [PKTokenizer tokenizer]; + + [tokenizer setTokenizerState:tokenizer.symbolState from:'/' to:'/']; // XML doesn't have slash slash or slash star comments + tokenizer.whitespaceState.reportsWhitespaceTokens = YES; + [tokenizer.wordState setWordChars:YES from:':' to:':']; + + self.ltToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"<" floatValue:0.0]; + self.gtToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@">" floatValue:0.0]; + + self.startCommentToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"" floatValue:0.0]; + [tokenizer.symbolState add:startCommentToken.stringValue]; + [tokenizer.symbolState add:endCommentToken.stringValue]; + + self.startCDATAToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"" floatValue:0.0]; + [tokenizer.symbolState add:startCDATAToken.stringValue]; + [tokenizer.symbolState add:endCDATAToken.stringValue]; + + self.startPIToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"" floatValue:0.0]; + [tokenizer.symbolState add:startPIToken.stringValue]; + [tokenizer.symbolState add:endPIToken.stringValue]; + + self.startDoctypeToken = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"" floatValue:0.0]; +// [tokenizer.symbolState add:endScriptToken.stringValue]; + + NSFont *monacoFont = [NSFont fontWithName:@"Monaco" size:11.]; + + NSColor *textColor = nil; + NSColor *tagColor = nil; + NSColor *attrNameColor = nil; + NSColor *attrValueColor = nil; + NSColor *eqColor = nil; + NSColor *commentColor = nil; + NSColor *piColor = nil; + + if (isDarkBG) { + textColor = [NSColor whiteColor]; + tagColor = [NSColor colorWithDeviceRed:.70 green:.14 blue:.53 alpha:1.]; + attrNameColor = [NSColor colorWithDeviceRed:.33 green:.45 blue:.48 alpha:1.]; + attrValueColor = [NSColor colorWithDeviceRed:.77 green:.18 blue:.20 alpha:1.]; + eqColor = tagColor; + commentColor = [NSColor colorWithDeviceRed:.24 green:.70 blue:.27 alpha:1.]; + piColor = [NSColor colorWithDeviceRed:.09 green:.62 blue:.74 alpha:1.]; + } else { + textColor = [NSColor blackColor]; + tagColor = [NSColor purpleColor]; + attrNameColor = [NSColor colorWithDeviceRed:0. green:0. blue:.75 alpha:1.]; + attrValueColor = [NSColor colorWithDeviceRed:.75 green:0. blue:0. alpha:1.]; + eqColor = [NSColor darkGrayColor]; + commentColor = [NSColor grayColor]; + piColor = [NSColor colorWithDeviceRed:.09 green:.62 blue:.74 alpha:1.]; + } + + self.textAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + textColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.tagAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + tagColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.attrNameAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + attrNameColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.attrValueAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + attrValueColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.eqAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + eqColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.commentAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + commentColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + self.piAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + piColor, NSForegroundColorAttributeName, + monacoFont, NSFontAttributeName, + nil]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.stack = nil; + self.ltToken = nil; + self.gtToken = nil; + self.startCommentToken = nil; + self.endCommentToken = nil; + self.startCDATAToken = nil; + self.endCDATAToken = nil; + self.startPIToken = nil; + self.endPIToken = nil; + self.startDoctypeToken = nil; + self.fwdSlashToken = nil; + self.eqToken = nil; + self.scriptToken = nil; + self.endScriptToken = nil; + self.highlightedString = nil; + self.textAttributes = nil; + self.tagAttributes = nil; + self.attrNameAttributes = nil; + self.attrValueAttributes = nil; + self.eqAttributes = nil; + self.commentAttributes = nil; + self.piAttributes = nil; + [super dealloc]; +} + + +- (NSAttributedString *)attributedStringForString:(NSString *)s { + self.stack = [NSMutableArray array]; + self.highlightedString = [[[NSMutableAttributedString alloc] init] autorelease]; + + tokenizer.string = s; + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + BOOL inComment = NO; + BOOL inCDATA = NO; + BOOL inPI = NO; + BOOL inDoctype = NO; + + while ((tok = [tokenizer nextToken]) != eof) { + + if (!inComment && !inCDATA && !inPI && !inDoctype && !inScript && tok.isSymbol) { + if ([startCommentToken isEqual:tok]) { + [stack addObject:tok]; + inComment = YES; + } else if ([startCDATAToken isEqual:tok]) { + [stack addObject:tok]; + inCDATA = YES; + } else if ([startPIToken isEqual:tok]) { + [stack addObject:tok]; + inPI = YES; + } else if ([startDoctypeToken isEqual:tok]) { + [stack addObject:tok]; + inDoctype = YES; + } else if ([ltToken isEqual:tok]) { + [self didMatchText]; + [stack addObject:tok]; + } else if ([gtToken isEqual:tok]) { + [stack addObject:tok]; + [self didMatchTag]; + } else { + [stack addObject:tok]; + } + } else if (inComment && [endCommentToken isEqual:tok]) { + inComment = NO; + [stack addObject:tok]; + [self didMatchComment]; + } else if (inCDATA && [endCDATAToken isEqual:tok]) { + inCDATA = NO; + [stack addObject:tok]; + [self didMatchCDATA]; + } else if (inPI && [endPIToken isEqual:tok]) { + inPI = NO; + [stack addObject:tok]; + [self didMatchPI]; + } else if (inDoctype && [gtToken isEqual:tok]) { + inDoctype = NO; + [stack addObject:tok]; + [self didMatchDoctype]; + } else if (inScript && [endScriptToken isEqual:tok]) { + inScript = NO; + [stack addObject:tok]; + [self didMatchScript]; + } else { + [stack addObject:tok]; + } + } + + // handle case where no elements were encountered (plain text basically) + if (![highlightedString length]) { + PKToken *tok = nil; + while (tok = [self pop]) { + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:textAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + NSAttributedString *result = [[highlightedString copy] autorelease]; + self.stack = nil; + self.highlightedString = nil; + tokenizer.string = nil; + return result; +} + + +- (PKToken *)nextNonWhitespaceTokenFrom:(NSEnumerator *)e { + PKToken *tok = [e nextObject]; + while (tok.isWhitespace) { + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + tok = [e nextObject]; + } + return tok; +} + + +- (void)consumeWhitespaceOnStack { + PKToken *tok = [self peek]; + while (tok.isWhitespace) { + tok = [self pop]; + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + tok = [self peek]; + } +} + + +- (void)didMatchComment { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startCommentToken] reversedMutableArray]; + + [self consumeWhitespaceOnStack]; + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:startCommentToken.stringValue attributes:commentAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + NSEnumerator *e = [toks objectEnumerator]; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:endCommentToken]) { + break; + } else { + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:commentAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:commentAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchCDATA { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startCDATAToken] reversedMutableArray]; + + [self consumeWhitespaceOnStack]; + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:startCDATAToken.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + NSEnumerator *e = [toks objectEnumerator]; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:endCDATAToken]) { + break; + } else { + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:textAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchPI { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startPIToken] reversedMutableArray]; + + [self consumeWhitespaceOnStack]; + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:startPIToken.stringValue attributes:piAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + NSEnumerator *e = [toks objectEnumerator]; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:endPIToken]) { + break; + } else { + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:piAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:piAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchDoctype { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startDoctypeToken] reversedMutableArray]; + + [self consumeWhitespaceOnStack]; + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:startDoctypeToken.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + NSEnumerator *e = [toks objectEnumerator]; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:gtToken]) { + break; + } else { + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchScript { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:startDoctypeToken] reversedMutableArray]; + + NSEnumerator *e = [toks objectEnumerator]; + NSAttributedString *as = nil; + + PKToken *tok = nil; + while (tok = [self nextNonWhitespaceTokenFrom:e]) { + if ([tok isEqual:endScriptToken]) { + break; + } else { + NSDictionary *attrs = nil; + if ([tok isEqual:scriptToken] || [tok isEqual:ltToken] || [tok isEqual:fwdSlashToken]) { + attrs = tagAttributes; + } else { + attrs = textAttributes; + } + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:attrs] autorelease]; + [highlightedString appendAttributedString:as]; + } + } + + as = [[[NSAttributedString alloc] initWithString:endScriptToken.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; +} + + +- (void)didMatchStartTag:(NSEnumerator *)e { + while (1) { + // attr name or ns prefix decl "xmlns:foo" or "/" for empty element + PKToken *tok = [self nextNonWhitespaceTokenFrom:e]; + if (!tok) return; + + NSDictionary *attrs = nil; + if ([tok isEqual:eqToken]) { + attrs = eqAttributes; + } else if ([tok isEqual:fwdSlashToken] || [tok isEqual:gtToken]) { + attrs = tagAttributes; + } else if (tok.isQuotedString) { + attrs = attrValueAttributes; + } else { + attrs = attrNameAttributes; + } + + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:attrs] autorelease]; + [highlightedString appendAttributedString:as]; + + // "=" + tok = [self nextNonWhitespaceTokenFrom:e]; + if (!tok) return; + + if ([tok isEqual:eqToken]) { + attrs = eqAttributes; + } else if ([tok isEqual:fwdSlashToken] || [tok isEqual:gtToken]) { + attrs = tagAttributes; + } else if (tok.isQuotedString) { + attrs = attrValueAttributes; + } else { + attrs = tagAttributes; + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:attrs] autorelease]; + [highlightedString appendAttributedString:as]; + + // quoted string attr value or ns url value + tok = [self nextNonWhitespaceTokenFrom:e]; + if (!tok) return; + + if ([tok isEqual:fwdSlashToken] || [tok isEqual:gtToken]) { + attrs = tagAttributes; + } else { + attrs = attrValueAttributes; + } + + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:attrs] autorelease]; + [highlightedString appendAttributedString:as]; + } +} + + +- (void)didMatchEndTag:(NSEnumerator *)e { + // consume tagName to ">" + PKToken *tok = nil; + while (tok = [e nextObject]) { + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } +} + + +- (void)didMatchTag { + // reverse toks to be in document order + NSMutableArray *toks = [[self objectsAbove:nil] reversedMutableArray]; + NSAttributedString *as = nil; + + NSEnumerator *e = [toks objectEnumerator]; + + // append "<" + [self nextNonWhitespaceTokenFrom:e]; // discard + as = [[[NSAttributedString alloc] initWithString:ltToken.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + // consume whitespace to tagName or "/" for end tags or "!" for comments + PKToken *tok = [self nextNonWhitespaceTokenFrom:e]; + + if (tok) { + if ([tok isEqual:scriptToken]) { + inScript = YES; + } else { + inScript = NO; + } + + // consume tagName or "/" or "!" + as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:tagAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + + if ([tok isEqual:fwdSlashToken]) { + [self didMatchEndTag:e]; + } else { + [self didMatchStartTag:e]; + } + } +} + + +- (void)didMatchText { + NSArray *a = [self objectsAbove:gtToken]; + for (PKToken *tok in [a reverseObjectEnumerator]) { + NSString *s = tok.stringValue; + if (s) { + NSAttributedString *as = [[[NSAttributedString alloc] initWithString:tok.stringValue attributes:textAttributes] autorelease]; + [highlightedString appendAttributedString:as]; + } + } +} + + +- (NSArray *)objectsAbove:(id)fence { + NSMutableArray *res = [NSMutableArray array]; + while (1) { + if (![stack count]) { + break; + } + id obj = [self pop]; + if ([obj isEqual:fence]) { + break; + } + [res addObject:obj]; + } + return res; +} + + +- (id)peek { + id obj = nil; + if ([stack count]) { + obj = [stack lastObject]; + } + return obj; +} + + +- (id)pop { + id obj = [self peek]; + if (obj) { + [stack removeLastObject]; + } + return obj; +} + +@synthesize stack; +@synthesize tokenizer; +@synthesize ltToken; +@synthesize gtToken; +@synthesize startCommentToken; +@synthesize endCommentToken; +@synthesize startCDATAToken; +@synthesize endCDATAToken; +@synthesize startPIToken; +@synthesize endPIToken; +@synthesize startDoctypeToken; +@synthesize fwdSlashToken; +@synthesize eqToken; +@synthesize scriptToken; +@synthesize endScriptToken; +@synthesize highlightedString; +@synthesize tagAttributes; +@synthesize textAttributes; +@synthesize attrNameAttributes; +@synthesize attrValueAttributes; +@synthesize eqAttributes; +@synthesize commentAttributes; +@synthesize piAttributes; +@end diff --git a/test/TDJavaScriptParser.h b/test/TDJavaScriptParser.h new file mode 100644 index 0000000..b1a4f78 --- /dev/null +++ b/test/TDJavaScriptParser.h @@ -0,0 +1,350 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDJavaScriptParser : PKRepetition { + PKCollectionParser *assignmentOpParser; + PKCollectionParser *relationalOpParser; + PKCollectionParser *equalityOpParser; + PKCollectionParser *shiftOpParser; + PKCollectionParser *incrementOpParser; + PKCollectionParser *unaryOpParser; + PKCollectionParser *multiplicativeOpParser; + + PKCollectionParser *programParser; + PKCollectionParser *elementParser; + PKCollectionParser *funcParser; + PKCollectionParser *paramListOptParser; + PKCollectionParser *paramListParser; + PKCollectionParser *commaIdentifierParser; + PKCollectionParser *compoundStmtParser; + PKCollectionParser *stmtsParser; + PKCollectionParser *stmtParser; + PKCollectionParser *ifStmtParser; + PKCollectionParser *ifElseStmtParser; + PKCollectionParser *whileStmtParser; + PKCollectionParser *forParenStmtParser; + PKCollectionParser *forBeginStmtParser; + PKCollectionParser *forInStmtParser; + PKCollectionParser *breakStmtParser; + PKCollectionParser *continueStmtParser; + PKCollectionParser *withStmtParser; + PKCollectionParser *returnStmtParser; + PKCollectionParser *variablesOrExprStmtParser; + PKCollectionParser *conditionParser; + PKCollectionParser *forParenParser; + PKCollectionParser *forBeginParser; + PKCollectionParser *variablesOrExprParser; + PKCollectionParser *varVariablesParser; + PKCollectionParser *variablesParser; + PKCollectionParser *commaVariableParser; + PKCollectionParser *variableParser; + PKCollectionParser *assignmentParser; + PKCollectionParser *exprOptParser; + PKCollectionParser *exprParser; + PKCollectionParser *commaAssignmentExprParser; + PKCollectionParser *assignmentExprParser; + PKCollectionParser *assignmentOpConditionalExprParser; + PKCollectionParser *conditionalExprParser; + PKCollectionParser *ternaryExprParser; + PKCollectionParser *orExprParser; + PKCollectionParser *orAndExprParser; + PKCollectionParser *andExprParser; + PKCollectionParser *andBitwiseOrExprParser; + PKCollectionParser *bitwiseOrExprParser; + PKCollectionParser *pipeBitwiseXorExprParser; + PKCollectionParser *bitwiseXorExprParser; + PKCollectionParser *caretBitwiseAndExprParser; + PKCollectionParser *bitwiseAndExprParser; + PKCollectionParser *ampEqualityExprParser; + PKCollectionParser *equalityExprParser; + PKCollectionParser *equalityOpRelationalExprParser; + PKCollectionParser *relationalExprParser; + PKCollectionParser *relationalOpShiftExprParser; + PKCollectionParser *shiftExprParser; + PKCollectionParser *shiftOpAdditiveExprParser; + PKCollectionParser *additiveExprParser; + PKCollectionParser *plusOrMinusExprParser; + PKCollectionParser *plusExprParser; + PKCollectionParser *minusExprParser; + PKCollectionParser *multiplicativeExprParser; + PKCollectionParser *multiplicativeOpUnaryExprParser; + PKCollectionParser *unaryExprParser; + PKCollectionParser *unaryExpr1Parser; + PKCollectionParser *unaryExpr2Parser; + PKCollectionParser *unaryExpr3Parser; + PKCollectionParser *unaryExpr4Parser; + PKCollectionParser *unaryExpr5Parser; + PKCollectionParser *unaryExpr6Parser; + PKCollectionParser *constructorCallParser; + PKCollectionParser *parenArgListOptParenParser; + PKCollectionParser *memberExprParser; + PKCollectionParser *memberExprExtParser; + PKCollectionParser *dotMemberExprParser; + PKCollectionParser *bracketMemberExprParser; + PKCollectionParser *argListOptParser; + PKCollectionParser *argListParser; + PKCollectionParser *primaryExprParser; + PKCollectionParser *parenExprParenParser; + + PKCollectionParser *funcLiteralParser; + PKCollectionParser *arrayLiteralParser; + PKCollectionParser *objectLiteralParser; + + PKParser *identifierParser; + PKParser *stringParser; + PKParser *numberParser; + + // keywords + PKParser *ifParser; + PKParser *elseParser; + PKParser *whileParser; + PKParser *forParser; + PKParser *inParser; + PKParser *breakParser; + PKParser *continueParser; + PKParser *withParser; + PKParser *returnParser; + PKParser *varParser; + PKParser *deleteParser; + PKParser *newParser; + PKParser *thisParser; + PKParser *falseParser; + PKParser *trueParser; + PKParser *nullParser; + PKParser *undefinedParser; + PKParser *voidParser; + PKParser *typeofParser; + PKParser *instanceofParser; + PKParser *functionParser; + + // multi-char symbols + PKParser *orParser; + PKParser *andParser; + PKParser *neParser; + PKParser *isNotParser; + PKParser *eqParser; + PKParser *isParser; + PKParser *leParser; + PKParser *geParser; + PKParser *plusPlusParser; + PKParser *minusMinusParser; + PKParser *plusEqParser; + PKParser *minusEqParser; + PKParser *timesEqParser; + PKParser *divEqParser; + PKParser *modEqParser; + PKParser *shiftLeftParser; + PKParser *shiftRightParser; + PKParser *shiftRightExtParser; + PKParser *shiftLeftEqParser; + PKParser *shiftRightEqParser; + PKParser *shiftRightExtEqParser; + PKParser *andEqParser; + PKParser *xorEqParser; + PKParser *orEqParser; + + // single char symbols + PKParser *openCurlyParser; + PKParser *closeCurlyParser; + PKParser *openParenParser; + PKParser *closeParenParser; + PKParser *openBracketParser; + PKParser *closeBracketParser; + PKParser *commaParser; + PKParser *dotParser; + PKParser *semiOptParser; + PKParser *semiParser; + PKParser *colonParser; + PKParser *equalsParser; + PKParser *notParser; + PKParser *ltParser; + PKParser *gtParser; + PKParser *ampParser; + PKParser *pipeParser; + PKParser *caretParser; + PKParser *tildeParser; + PKParser *questionParser; + PKParser *plusParser; + PKParser *minusParser; + PKParser *timesParser; + PKParser *divParser; + PKParser *modParser; +} +@property (nonatomic, retain) PKCollectionParser *assignmentOpParser; +@property (nonatomic, retain) PKCollectionParser *relationalOpParser; +@property (nonatomic, retain) PKCollectionParser *equalityOpParser; +@property (nonatomic, retain) PKCollectionParser *shiftOpParser; +@property (nonatomic, retain) PKCollectionParser *incrementOpParser; +@property (nonatomic, retain) PKCollectionParser *unaryOpParser; +@property (nonatomic, retain) PKCollectionParser *multiplicativeOpParser; + +@property (nonatomic, retain) PKCollectionParser *programParser; +@property (nonatomic, retain) PKCollectionParser *elementParser; +@property (nonatomic, retain) PKCollectionParser *funcParser; +@property (nonatomic, retain) PKCollectionParser *paramListOptParser; +@property (nonatomic, retain) PKCollectionParser *paramListParser; +@property (nonatomic, retain) PKCollectionParser *commaIdentifierParser; +@property (nonatomic, retain) PKCollectionParser *compoundStmtParser; +@property (nonatomic, retain) PKCollectionParser *stmtsParser; +@property (nonatomic, retain) PKCollectionParser *stmtParser; +@property (nonatomic, retain) PKCollectionParser *ifStmtParser; +@property (nonatomic, retain) PKCollectionParser *ifElseStmtParser; +@property (nonatomic, retain) PKCollectionParser *whileStmtParser; +@property (nonatomic, retain) PKCollectionParser *forParenStmtParser; +@property (nonatomic, retain) PKCollectionParser *forBeginStmtParser; +@property (nonatomic, retain) PKCollectionParser *forInStmtParser; +@property (nonatomic, retain) PKCollectionParser *breakStmtParser; +@property (nonatomic, retain) PKCollectionParser *continueStmtParser; +@property (nonatomic, retain) PKCollectionParser *withStmtParser; +@property (nonatomic, retain) PKCollectionParser *returnStmtParser; +@property (nonatomic, retain) PKCollectionParser *variablesOrExprStmtParser; +@property (nonatomic, retain) PKCollectionParser *conditionParser; +@property (nonatomic, retain) PKCollectionParser *forParenParser; +@property (nonatomic, retain) PKCollectionParser *forBeginParser; +@property (nonatomic, retain) PKCollectionParser *variablesOrExprParser; +@property (nonatomic, retain) PKCollectionParser *varVariablesParser; +@property (nonatomic, retain) PKCollectionParser *variablesParser; +@property (nonatomic, retain) PKCollectionParser *commaVariableParser; +@property (nonatomic, retain) PKCollectionParser *variableParser; +@property (nonatomic, retain) PKCollectionParser *assignmentParser; +@property (nonatomic, retain) PKCollectionParser *exprOptParser; +@property (nonatomic, retain) PKCollectionParser *exprParser; +@property (nonatomic, retain) PKCollectionParser *commaAssignmentExprParser; +@property (nonatomic, retain) PKCollectionParser *assignmentExprParser; +@property (nonatomic, retain) PKCollectionParser *assignmentOpConditionalExprParser; +@property (nonatomic, retain) PKCollectionParser *conditionalExprParser; +@property (nonatomic, retain) PKCollectionParser *ternaryExprParser; +@property (nonatomic, retain) PKCollectionParser *orExprParser; +@property (nonatomic, retain) PKCollectionParser *orAndExprParser; +@property (nonatomic, retain) PKCollectionParser *andExprParser; +@property (nonatomic, retain) PKCollectionParser *andBitwiseOrExprParser; +@property (nonatomic, retain) PKCollectionParser *bitwiseOrExprParser; +@property (nonatomic, retain) PKCollectionParser *pipeBitwiseXorExprParser; +@property (nonatomic, retain) PKCollectionParser *bitwiseXorExprParser; +@property (nonatomic, retain) PKCollectionParser *caretBitwiseAndExprParser; +@property (nonatomic, retain) PKCollectionParser *bitwiseAndExprParser; +@property (nonatomic, retain) PKCollectionParser *ampEqualityExprParser; +@property (nonatomic, retain) PKCollectionParser *equalityExprParser; +@property (nonatomic, retain) PKCollectionParser *equalityOpRelationalExprParser; +@property (nonatomic, retain) PKCollectionParser *relationalExprParser; +@property (nonatomic, retain) PKCollectionParser *relationalOpShiftExprParser; +@property (nonatomic, retain) PKCollectionParser *shiftExprParser; +@property (nonatomic, retain) PKCollectionParser *shiftOpAdditiveExprParser; +@property (nonatomic, retain) PKCollectionParser *additiveExprParser; +@property (nonatomic, retain) PKCollectionParser *plusOrMinusExprParser; +@property (nonatomic, retain) PKCollectionParser *plusExprParser; +@property (nonatomic, retain) PKCollectionParser *minusExprParser; +@property (nonatomic, retain) PKCollectionParser *multiplicativeExprParser; +@property (nonatomic, retain) PKCollectionParser *multiplicativeOpUnaryExprParser; +@property (nonatomic, retain) PKCollectionParser *unaryExprParser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr1Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr2Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr3Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr4Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr5Parser; +@property (nonatomic, retain) PKCollectionParser *unaryExpr6Parser; +@property (nonatomic, retain) PKCollectionParser *constructorCallParser; +@property (nonatomic, retain) PKCollectionParser *parenArgListOptParenParser; +@property (nonatomic, retain) PKCollectionParser *memberExprParser; +@property (nonatomic, retain) PKCollectionParser *memberExprExtParser; +@property (nonatomic, retain) PKCollectionParser *dotMemberExprParser; +@property (nonatomic, retain) PKCollectionParser *bracketMemberExprParser; +@property (nonatomic, retain) PKCollectionParser *argListOptParser; +@property (nonatomic, retain) PKCollectionParser *argListParser; +@property (nonatomic, retain) PKCollectionParser *primaryExprParser; +@property (nonatomic, retain) PKCollectionParser *parenExprParenParser; + +@property (nonatomic, retain) PKCollectionParser *funcLiteralParser; +@property (nonatomic, retain) PKCollectionParser *arrayLiteralParser; +@property (nonatomic, retain) PKCollectionParser *objectLiteralParser; + +@property (nonatomic, retain) PKParser *identifierParser; +@property (nonatomic, retain) PKParser *stringParser; +@property (nonatomic, retain) PKParser *numberParser; + +@property (nonatomic, retain) PKParser *ifParser; +@property (nonatomic, retain) PKParser *elseParser; +@property (nonatomic, retain) PKParser *whileParser; +@property (nonatomic, retain) PKParser *forParser; +@property (nonatomic, retain) PKParser *inParser; +@property (nonatomic, retain) PKParser *breakParser; +@property (nonatomic, retain) PKParser *continueParser; +@property (nonatomic, retain) PKParser *withParser; +@property (nonatomic, retain) PKParser *returnParser; +@property (nonatomic, retain) PKParser *varParser; +@property (nonatomic, retain) PKParser *deleteParser; +@property (nonatomic, retain) PKParser *newParser; +@property (nonatomic, retain) PKParser *thisParser; +@property (nonatomic, retain) PKParser *falseParser; +@property (nonatomic, retain) PKParser *trueParser; +@property (nonatomic, retain) PKParser *nullParser; +@property (nonatomic, retain) PKParser *undefinedParser; +@property (nonatomic, retain) PKParser *voidParser; +@property (nonatomic, retain) PKParser *typeofParser; +@property (nonatomic, retain) PKParser *instanceofParser; +@property (nonatomic, retain) PKParser *functionParser; + +@property (nonatomic, retain) PKParser *orParser; +@property (nonatomic, retain) PKParser *andParser; +@property (nonatomic, retain) PKParser *neParser; +@property (nonatomic, retain) PKParser *isNotParser; +@property (nonatomic, retain) PKParser *eqParser; +@property (nonatomic, retain) PKParser *isParser; +@property (nonatomic, retain) PKParser *leParser; +@property (nonatomic, retain) PKParser *geParser; +@property (nonatomic, retain) PKParser *plusPlusParser; +@property (nonatomic, retain) PKParser *minusMinusParser; +@property (nonatomic, retain) PKParser *plusEqParser; +@property (nonatomic, retain) PKParser *minusEqParser; +@property (nonatomic, retain) PKParser *timesEqParser; +@property (nonatomic, retain) PKParser *divEqParser; +@property (nonatomic, retain) PKParser *modEqParser; +@property (nonatomic, retain) PKParser *shiftLeftParser; +@property (nonatomic, retain) PKParser *shiftRightParser; +@property (nonatomic, retain) PKParser *shiftRightExtParser; +@property (nonatomic, retain) PKParser *shiftLeftEqParser; +@property (nonatomic, retain) PKParser *shiftRightEqParser; +@property (nonatomic, retain) PKParser *shiftRightExtEqParser; +@property (nonatomic, retain) PKParser *andEqParser; +@property (nonatomic, retain) PKParser *xorEqParser; +@property (nonatomic, retain) PKParser *orEqParser; + +@property (nonatomic, retain) PKParser *openCurlyParser; +@property (nonatomic, retain) PKParser *closeCurlyParser; +@property (nonatomic, retain) PKParser *openParenParser; +@property (nonatomic, retain) PKParser *closeParenParser; +@property (nonatomic, retain) PKParser *openBracketParser; +@property (nonatomic, retain) PKParser *closeBracketParser; +@property (nonatomic, retain) PKParser *commaParser; +@property (nonatomic, retain) PKParser *dotParser; +@property (nonatomic, retain) PKParser *semiOptParser; +@property (nonatomic, retain) PKParser *semiParser; +@property (nonatomic, retain) PKParser *colonParser; +@property (nonatomic, retain) PKParser *equalsParser; +@property (nonatomic, retain) PKParser *notParser; +@property (nonatomic, retain) PKParser *ltParser; +@property (nonatomic, retain) PKParser *gtParser; +@property (nonatomic, retain) PKParser *ampParser; +@property (nonatomic, retain) PKParser *pipeParser; +@property (nonatomic, retain) PKParser *caretParser; +@property (nonatomic, retain) PKParser *tildeParser; +@property (nonatomic, retain) PKParser *questionParser; +@property (nonatomic, retain) PKParser *plusParser; +@property (nonatomic, retain) PKParser *minusParser; +@property (nonatomic, retain) PKParser *timesParser; +@property (nonatomic, retain) PKParser *divParser; +@property (nonatomic, retain) PKParser *modParser; +@end diff --git a/test/TDJavaScriptParser.m b/test/TDJavaScriptParser.m new file mode 100644 index 0000000..edf20f5 --- /dev/null +++ b/test/TDJavaScriptParser.m @@ -0,0 +1,2398 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDJavaScriptParser.h" + +@interface PKParser () +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface TDJavaScriptParser () +- (PKAlternation *)zeroOrOne:(PKParser *)p; +- (PKSequence *)oneOrMore:(PKParser *)p; +@end + +@implementation TDJavaScriptParser + +- (id)init { + if (self = [super initWithSubparser:self.elementParser]) { + self.tokenizer = [PKTokenizer tokenizer]; + + // JS supports scientific number notation (exponents like 4E+12 or 2.0e-42) + tokenizer.numberState.allowsScientificNotation = YES; + + // Nums cannot end with '.' (e.g. 32. must be 32.0) + tokenizer.numberState.allowsTrailingDot = NO; + + [tokenizer setTokenizerState:tokenizer.numberState from:'-' to:'-']; + [tokenizer setTokenizerState:tokenizer.numberState from:'.' to:'.']; + [tokenizer setTokenizerState:tokenizer.numberState from:'0' to:'9']; + + // Words can start with '_' + [tokenizer setTokenizerState:tokenizer.wordState from:'_' to:'_']; + + // Words cannot contain '-' + [tokenizer.wordState setWordChars:NO from:'-' to:'-']; + + // Comments + tokenizer.commentState.reportsCommentTokens = YES; + [tokenizer setTokenizerState:tokenizer.commentState from:'/' to:'/']; + + // single-line Comments + [tokenizer.commentState addSingleLineStartMarker:@"//"]; + + // multi-line Comments + [tokenizer.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + [tokenizer.symbolState add:@"||"]; + [tokenizer.symbolState add:@"&&"]; + [tokenizer.symbolState add:@"!="]; + [tokenizer.symbolState add:@"!=="]; + [tokenizer.symbolState add:@"=="]; + [tokenizer.symbolState add:@"==="]; + [tokenizer.symbolState add:@"<="]; + [tokenizer.symbolState add:@">="]; + [tokenizer.symbolState add:@"++"]; + [tokenizer.symbolState add:@"--"]; + [tokenizer.symbolState add:@"+="]; + [tokenizer.symbolState add:@"-="]; + [tokenizer.symbolState add:@"*="]; + [tokenizer.symbolState add:@"/="]; + [tokenizer.symbolState add:@"%="]; + [tokenizer.symbolState add:@"<<"]; + [tokenizer.symbolState add:@">>"]; + [tokenizer.symbolState add:@">>>"]; + [tokenizer.symbolState add:@"<<="]; + [tokenizer.symbolState add:@">>="]; + [tokenizer.symbolState add:@">>>="]; + [tokenizer.symbolState add:@"&="]; + [tokenizer.symbolState add:@"^="]; + } + return self; +} + + +- (void)dealloc { + self.assignmentOpParser = nil; + self.relationalOpParser = nil; + self.equalityOpParser = nil; + self.shiftOpParser = nil; + self.incrementOpParser = nil; + self.unaryOpParser = nil; + self.multiplicativeOpParser = nil; + self.programParser = nil; + self.elementParser = nil; + self.funcParser = nil; + self.paramListOptParser = nil; + self.paramListParser = nil; + self.commaIdentifierParser = nil; + self.compoundStmtParser = nil; + self.stmtsParser = nil; + self.stmtParser = nil; + self.ifStmtParser = nil; + self.ifElseStmtParser = nil; + self.whileStmtParser = nil; + self.forParenStmtParser = nil; + self.forBeginStmtParser = nil; + self.forInStmtParser = nil; + self.breakStmtParser = nil; + self.continueStmtParser = nil; + self.withStmtParser = nil; + self.returnStmtParser = nil; + self.variablesOrExprStmtParser = nil; + self.conditionParser = nil; + self.forParenParser = nil; + self.forBeginParser = nil; + self.variablesOrExprParser = nil; + self.varVariablesParser = nil; + self.variablesParser = nil; + self.commaVariableParser = nil; + self.variableParser = nil; + self.assignmentParser = nil; + self.exprOptParser = nil; + self.exprParser = nil; + self.commaAssignmentExprParser = nil; + self.assignmentExprParser = nil; + self.assignmentOpConditionalExprParser = nil; + self.conditionalExprParser = nil; + self.ternaryExprParser = nil; + self.orExprParser = nil; + self.orAndExprParser = nil; + self.andExprParser = nil; + self.andBitwiseOrExprParser = nil; + self.bitwiseOrExprParser = nil; + self.pipeBitwiseXorExprParser = nil; + self.bitwiseXorExprParser = nil; + self.caretBitwiseAndExprParser = nil; + self.bitwiseAndExprParser = nil; + self.ampEqualityExprParser = nil; + self.equalityExprParser = nil; + self.equalityOpRelationalExprParser = nil; + self.relationalExprParser = nil; + self.relationalOpShiftExprParser = nil; + self.shiftExprParser = nil; + self.shiftOpAdditiveExprParser = nil; + self.additiveExprParser = nil; + self.plusOrMinusExprParser = nil; + self.plusExprParser = nil; + self.minusExprParser = nil; + self.multiplicativeExprParser = nil; + self.multiplicativeOpUnaryExprParser = nil; + self.unaryExprParser = nil; + self.unaryExpr1Parser = nil; + self.unaryExpr2Parser = nil; + self.unaryExpr3Parser = nil; + self.unaryExpr4Parser = nil; + self.unaryExpr5Parser = nil; + self.unaryExpr6Parser = nil; + self.constructorCallParser = nil; + self.parenArgListOptParenParser = nil; + self.memberExprParser = nil; + self.memberExprExtParser = nil; + self.dotMemberExprParser = nil; + self.bracketMemberExprParser = nil; + self.argListOptParser = nil; + self.argListParser = nil; + self.primaryExprParser = nil; + self.parenExprParenParser = nil; + + self.funcLiteralParser = nil; + self.arrayLiteralParser = nil; + self.objectLiteralParser = nil; + + self.identifierParser = nil; + self.stringParser = nil; + self.numberParser = nil; + + self.ifParser = nil; + self.elseParser = nil; + self.whileParser = nil; + self.forParser = nil; + self.inParser = nil; + self.breakParser = nil; + self.continueParser = nil; + self.withParser = nil; + self.returnParser = nil; + self.varParser = nil; + self.deleteParser = nil; + self.newParser = nil; + self.thisParser = nil; + self.falseParser = nil; + self.trueParser = nil; + self.nullParser = nil; + self.undefinedParser = nil; + self.voidParser = nil; + self.typeofParser = nil; + self.instanceofParser = nil; + self.functionParser = nil; + + self.orParser = nil; + self.andParser = nil; + self.neParser = nil; + self.isNotParser = nil; + self.eqParser = nil; + self.isParser = nil; + self.leParser = nil; + self.geParser = nil; + self.plusPlusParser = nil; + self.minusMinusParser = nil; + self.plusEqParser = nil; + self.minusEqParser = nil; + self.timesEqParser = nil; + self.divEqParser = nil; + self.modEqParser = nil; + self.shiftLeftParser = nil; + self.shiftRightParser = nil; + self.shiftRightExtParser = nil; + self.shiftLeftEqParser = nil; + self.shiftRightEqParser = nil; + self.shiftRightExtEqParser = nil; + self.andEqParser = nil; + self.xorEqParser = nil; + self.orEqParser = nil; + + self.openCurlyParser = nil; + self.closeCurlyParser = nil; + self.openParenParser = nil; + self.closeParenParser = nil; + self.openBracketParser = nil; + self.closeBracketParser = nil; + self.commaParser = nil; + self.dotParser = nil; + self.semiOptParser = nil; + self.semiParser = nil; + self.colonParser = nil; + self.equalsParser = nil; + self.notParser = nil; + self.ltParser = nil; + self.gtParser = nil; + self.ampParser = nil; + self.pipeParser = nil; + self.caretParser = nil; + self.tildeParser = nil; + self.questionParser = nil; + self.plusParser = nil; + self.minusParser = nil; + self.timesParser = nil; + self.divParser = nil; + self.modParser = nil; + + [super dealloc]; +} + + +- (PKAlternation *)zeroOrOne:(PKParser *)p { + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:p]; + return a; +} + + +- (PKSequence *)oneOrMore:(PKParser *)p { + PKSequence *s = [PKSequence sequence]; + [s add:p]; + [s add:[PKRepetition repetitionWithSubparser:p]]; + return s; +} + + +// assignmentOperator = equals | plusEq | minusEq | timesEq | divEq | modEq | shiftLeftEq | shiftRightEq | shiftRightExtEq | andEq | xorEq | orEq; +- (PKCollectionParser *)assignmentOpParser { + if (!assignmentOpParser) { + self.assignmentOpParser = [PKAlternation alternation]; + assignmentOpParser.name = @"assignmentOp"; + [assignmentOpParser add:self.equalsParser]; + [assignmentOpParser add:self.plusEqParser]; + [assignmentOpParser add:self.minusEqParser]; + [assignmentOpParser add:self.timesEqParser]; + [assignmentOpParser add:self.divEqParser]; + [assignmentOpParser add:self.modEqParser]; + [assignmentOpParser add:self.shiftLeftEqParser]; + [assignmentOpParser add:self.shiftRightEqParser]; + [assignmentOpParser add:self.shiftRightExtEqParser]; + [assignmentOpParser add:self.andEqParser]; + [assignmentOpParser add:self.orEqParser]; + [assignmentOpParser add:self.xorEqParser]; + } + return assignmentOpParser; +} + + +// relationalOperator = lt | gt | ge | le | instanceof; +- (PKCollectionParser *)relationalOpParser { + if (!relationalOpParser) { + self.relationalOpParser = [PKAlternation alternation]; + relationalOpParser.name = @"relationalOp"; + [relationalOpParser add:self.ltParser]; + [relationalOpParser add:self.gtParser]; + [relationalOpParser add:self.geParser]; + [relationalOpParser add:self.leParser]; + [relationalOpParser add:self.instanceofParser]; + } + return relationalOpParser; +} + + +// equalityOp = eq | ne | is | isnot; +- (PKCollectionParser *)equalityOpParser { + if (!equalityOpParser) { + self.equalityOpParser = [PKAlternation alternation];; + equalityOpParser.name = @"equalityOp"; + [equalityOpParser add:self.eqParser]; + [equalityOpParser add:self.neParser]; + [equalityOpParser add:self.isParser]; + [equalityOpParser add:self.isNotParser]; + } + return equalityOpParser; +} + + +//shiftOp = shiftLeft | shiftRight | shiftRightExt; +- (PKCollectionParser *)shiftOpParser { + if (!shiftOpParser) { + self.shiftOpParser = [PKAlternation alternation]; + shiftOpParser.name = @"shiftOp"; + [shiftOpParser add:self.shiftLeftParser]; + [shiftOpParser add:self.shiftRightParser]; + [shiftOpParser add:self.shiftRightExtParser]; + } + return shiftOpParser; +} + + +//incrementOperator = plusPlus | minusMinus; +- (PKCollectionParser *)incrementOpParser { + if (!incrementOpParser) { + self.incrementOpParser = [PKAlternation alternation]; + incrementOpParser.name = @"incrementOp"; + [incrementOpParser add:self.plusPlusParser]; + [incrementOpParser add:self.minusMinusParser]; + } + return incrementOpParser; +} + + +//unaryOperator = tilde | delete | typeof | void; +- (PKCollectionParser *)unaryOpParser { + if (!unaryOpParser) { + self.unaryOpParser = [PKAlternation alternation]; + unaryOpParser.name = @"unaryOp"; + [unaryOpParser add:self.tildeParser]; + [unaryOpParser add:self.deleteParser]; + [unaryOpParser add:self.typeofParser]; + [unaryOpParser add:self.voidParser]; + } + return unaryOpParser; +} + + +// multiplicativeOperator = times | div | mod; +- (PKCollectionParser *)multiplicativeOpParser { + if (!multiplicativeOpParser) { + self.multiplicativeOpParser = [PKAlternation alternation]; + multiplicativeOpParser.name = @"multiplicativeOperator"; + [multiplicativeOpParser add:self.timesParser]; + [multiplicativeOpParser add:self.divParser]; + [multiplicativeOpParser add:self.modParser]; + } + return multiplicativeOpParser; +} + + + +// Program: +// empty +// Element Program +// +//program = element*; +- (PKCollectionParser *)programParser { + if (!programParser) { + self.programParser = [PKRepetition repetitionWithSubparser:self.elementParser]; + programParser.name = @"program"; + } + return programParser; +} + + +// Element: +// function Identifier ( ParameterListOpt ) CompoundStatement +// Statement +// +//element = func | stmt; +- (PKCollectionParser *)elementParser { + if (!elementParser) { + self.elementParser = [PKAlternation alternation]; + elementParser.name = @"element"; + [elementParser add:self.funcParser]; + [elementParser add:self.stmtParser]; + } + return elementParser; +} + + +//func = function identifier openParen paramListOpt closeParen compoundStmt; +- (PKCollectionParser *)funcParser { + if (!funcParser) { + self.funcParser = [PKSequence sequence]; + funcParser.name = @"func"; + [funcParser add:self.functionParser]; + [funcParser add:self.identifierParser]; + [funcParser add:self.openParenParser]; + [funcParser add:self.paramListOptParser]; + [funcParser add:self.closeParenParser]; + [funcParser add:self.compoundStmtParser]; + } + return funcParser; +} + + +// ParameterListOpt: +// empty +// ParameterList +// +//paramListOpt = Empty | paramList; +- (PKCollectionParser *)paramListOptParser { + if (!paramListOptParser) { + self.paramListOptParser = [PKAlternation alternation]; + paramListOptParser.name = @"paramListOpt"; + [paramListOptParser add:[self zeroOrOne:self.paramListParser]]; + } + return paramListOptParser; +} + + +// ParameterList: +// Identifier +// Identifier , ParameterList +// +//paramList = identifier commaIdentifier*; +- (PKCollectionParser *)paramListParser { + if (!paramListParser) { + self.paramListParser = [PKSequence sequence]; + paramListParser.name = @"paramList"; + [paramListParser add:self.identifierParser]; + [paramListParser add:[PKRepetition repetitionWithSubparser:self.commaIdentifierParser]]; + } + return paramListParser; +} + + +//commaIdentifier = comma identifier; +- (PKCollectionParser *)commaIdentifierParser { + if (!commaIdentifierParser) { + self.commaIdentifierParser = [PKSequence sequence]; + commaIdentifierParser.name = @"commaIdentifier"; + [commaIdentifierParser add:self.commaParser]; + [commaIdentifierParser add:self.identifierParser]; + } + return commaIdentifierParser; +} + + +// CompoundStatement: +// { Statements } +// +//compoundStmt = openCurly stmts closeCurly; +- (PKCollectionParser *)compoundStmtParser { + if (!compoundStmtParser) { + self.compoundStmtParser = [PKSequence sequence]; + compoundStmtParser.name = @"compoundStmt"; + [compoundStmtParser add:self.openCurlyParser]; + [compoundStmtParser add:self.stmtsParser]; + [compoundStmtParser add:self.closeCurlyParser]; + } + return compoundStmtParser; +} + + +// Statements: +// empty +// Statement Statements +// +//stmts = stmt*; +- (PKCollectionParser *)stmtsParser { + if (!stmtsParser) { + self.stmtsParser = [PKRepetition repetitionWithSubparser:self.stmtParser]; + stmtsParser.name = @"stmts"; + } + return stmtsParser; +} + + +// Statement: +// ; +// if Condition Statement +// if Condition Statement else Statement +// while Condition Statement +// ForParen ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement +// ForBegin in Expression ) Statement +// break ; +// continue ; +// with ( Expression ) Statement +// return ExpressionOpt ; +// CompoundStatement +// VariablesOrExpression ; +// +//stmt = semi | ifStmt | ifElseStmt | whileStmt | forParenStmt | forBeginStmt | forInStmt | breakStmt | continueStmt | withStmt | returnStmt | compoundStmt | variablesOrExprStmt; +- (PKCollectionParser *)stmtParser { + if (!stmtParser) { + self.stmtParser = [PKAlternation alternation]; + stmtParser.name = @"stmt"; + [stmtParser add:self.semiParser]; + [stmtParser add:self.ifStmtParser]; + [stmtParser add:self.ifElseStmtParser]; + [stmtParser add:self.whileStmtParser]; + [stmtParser add:self.forParenStmtParser]; + [stmtParser add:self.forBeginStmtParser]; + [stmtParser add:self.forInStmtParser]; + [stmtParser add:self.breakStmtParser]; + [stmtParser add:self.continueStmtParser]; + [stmtParser add:self.withStmtParser]; + [stmtParser add:self.returnStmtParser]; + [stmtParser add:self.compoundStmtParser]; + [stmtParser add:self.variablesOrExprStmtParser]; + } + return stmtParser; +} + + +// if Condition Statement +//ifStmt = if condition stmt; +- (PKCollectionParser *)ifStmtParser { + if (!ifStmtParser) { + self.ifStmtParser = [PKSequence sequence]; + ifStmtParser.name = @"ifStmt"; + [ifStmtParser add:self.ifParser]; + [ifStmtParser add:self.conditionParser]; + [ifStmtParser add:self.stmtParser]; + } + return ifStmtParser; +} + + +// if Condition Statement else Statement +//ifElseStmt = if condition stmt else stmt; +- (PKCollectionParser *)ifElseStmtParser { + if (!ifElseStmtParser) { + self.ifElseStmtParser = [PKSequence sequence]; + ifElseStmtParser.name = @"ifElseStmt"; + [ifElseStmtParser add:self.ifParser]; + [ifElseStmtParser add:self.conditionParser]; + [ifElseStmtParser add:self.stmtParser]; + [ifElseStmtParser add:self.elseParser]; + [ifElseStmtParser add:self.stmtParser]; + } + return ifElseStmtParser; +} + + +// while Condition Statement +//whileStmt = while condition stmt; +- (PKCollectionParser *)whileStmtParser { + if (!whileStmtParser) { + self.whileStmtParser = [PKSequence sequence]; + whileStmtParser.name = @"whileStmt"; + [whileStmtParser add:self.whileParser]; + [whileStmtParser add:self.conditionParser]; + [whileStmtParser add:self.stmtParser]; + } + return whileStmtParser; +} + + +// ForParen ; ExpressionOpt ; ExpressionOpt ) Statement +//forParenStmt = forParen semi exprOpt semi exprOpt closeParen stmt; +- (PKCollectionParser *)forParenStmtParser { + if (!forParenStmtParser) { + self.forParenStmtParser = [PKSequence sequence]; + forParenStmtParser.name = @"forParenStmt"; + [forParenStmtParser add:self.forParenParser]; + [forParenStmtParser add:self.semiParser]; + [forParenStmtParser add:self.exprOptParser]; + [forParenStmtParser add:self.semiParser]; + [forParenStmtParser add:self.exprOptParser]; + [forParenStmtParser add:self.closeParenParser]; + [forParenStmtParser add:self.stmtParser]; + } + return forParenStmtParser; +} + + +// ForBegin ; ExpressionOpt ; ExpressionOpt ) Statement +//forBeginStmt = forBegin semi exprOpt semi exprOpt closeParen stmt; +- (PKCollectionParser *)forBeginStmtParser { + if (!forBeginStmtParser) { + self.forBeginStmtParser = [PKSequence sequence]; + forBeginStmtParser.name = @"forBeginStmt"; + [forBeginStmtParser add:self.forBeginParser]; + [forBeginStmtParser add:self.semiParser]; + [forBeginStmtParser add:self.exprOptParser]; + [forBeginStmtParser add:self.semiParser]; + [forBeginStmtParser add:self.exprOptParser]; + [forBeginStmtParser add:self.closeParenParser]; + [forBeginStmtParser add:self.stmtParser]; + } + return forBeginStmtParser; +} + + +// ForBegin in Expression ) Statement +//forInStmt = forBegin in expr closeParen stmt; +- (PKCollectionParser *)forInStmtParser { + if (!forInStmtParser) { + self.forInStmtParser = [PKSequence sequence]; + forInStmtParser.name = @"forInStmt"; + [forInStmtParser add:self.forBeginParser]; + [forInStmtParser add:self.inParser]; + [forInStmtParser add:self.exprParser]; + [forInStmtParser add:self.closeParenParser]; + [forInStmtParser add:self.stmtParser]; + } + return forInStmtParser; +} + + +// break ; +//breakStmt = break semi; +- (PKCollectionParser *)breakStmtParser { + if (!breakStmtParser) { + self.breakStmtParser = [PKSequence sequence]; + breakStmtParser.name = @"breakStmt"; + [breakStmtParser add:self.breakParser]; + [breakStmtParser add:self.semiOptParser]; + } + return breakStmtParser; +} + + +//continueStmt = continue semi; +- (PKCollectionParser *)continueStmtParser { + if (!continueStmtParser) { + self.continueStmtParser = [PKSequence sequence]; + continueStmtParser.name = @"continueStmt"; + [continueStmtParser add:self.continueParser]; + [continueStmtParser add:self.semiOptParser]; + } + return continueStmtParser; +} + + +// with ( Expression ) Statement +//withStmt = with openParen expr closeParen stmt; +- (PKCollectionParser *)withStmtParser { + if (!withStmtParser) { + self.withStmtParser = [PKSequence sequence]; + withStmtParser.name = @"withStmt"; + [withStmtParser add:self.withParser]; + [withStmtParser add:self.openParenParser]; + [withStmtParser add:self.exprParser]; + [withStmtParser add:self.closeParenParser]; + [withStmtParser add:self.stmtParser]; + } + return withStmtParser; +} + + +// return ExpressionOpt ; +//returnStmt = return exprOpt semi; +- (PKCollectionParser *)returnStmtParser { + if (!returnStmtParser) { + self.returnStmtParser = [PKSequence sequence]; + returnStmtParser.name = @"returnStmt"; + [returnStmtParser add:self.returnParser]; + [returnStmtParser add:self.exprOptParser]; + [returnStmtParser add:self.semiOptParser]; + } + return returnStmtParser; +} + + +// VariablesOrExpression ; +//variablesOrExprStmt = variablesOrExpr semi; +- (PKCollectionParser *)variablesOrExprStmtParser { + if (!variablesOrExprStmtParser) { + self.variablesOrExprStmtParser = [PKSequence sequence]; + variablesOrExprStmtParser.name = @"variablesOrExprStmt"; + [variablesOrExprStmtParser add:self.variablesOrExprParser]; + [variablesOrExprStmtParser add:self.semiOptParser]; + } + return variablesOrExprStmtParser; +} + + +// Condition: +// ( Expression ) +// +//condition = openParen expr closeParen; +- (PKCollectionParser *)conditionParser { + if (!conditionParser) { + self.conditionParser = [PKSequence sequence]; + conditionParser.name = @"condition"; + [conditionParser add:self.openParenParser]; + [conditionParser add:self.exprParser]; + [conditionParser add:self.closeParenParser]; + } + return conditionParser; +} + + +// ForParen: +// for ( +// +//forParen = for openParen; +- (PKCollectionParser *)forParenParser { + if (!forParenParser) { + self.forParenParser = [PKSequence sequence]; + forParenParser.name = @"forParen"; + [forParenParser add:self.forParser]; + [forParenParser add:self.openParenParser]; + } + return forParenParser; +} + + +// ForBegin: +// ForParen VariablesOrExpression +// +//forBegin = forParen variablesOrExpr; +- (PKCollectionParser *)forBeginParser { + if (!forBeginParser) { + self.forBeginParser = [PKSequence sequence]; + forBeginParser.name = @"forBegin"; + [forBeginParser add:self.forParenParser]; + [forBeginParser add:self.variablesOrExprParser]; + } + return forBeginParser; +} + + +// VariablesOrExpression: +// var Variables +// Expression +// +//variablesOrExpr = varVariables | expr; +- (PKCollectionParser *)variablesOrExprParser { + if (!variablesOrExprParser) { + self.variablesOrExprParser = [PKAlternation alternation]; + variablesOrExprParser.name = @"variablesOrExpr"; + [variablesOrExprParser add:self.varVariablesParser]; + [variablesOrExprParser add:self.exprParser]; + } + return variablesOrExprParser; +} + + +//varVariables = var variables; +- (PKCollectionParser *)varVariablesParser { + if (!varVariablesParser) { + self.varVariablesParser = [PKSequence sequence]; + varVariablesParser.name = @"varVariables"; + [varVariablesParser add:self.varParser]; + [varVariablesParser add:self.variablesParser]; + } + return varVariablesParser; +} + + +// Variables: +// Variable +// Variable , Variables +// +//variables = variable commaVariable*; +- (PKCollectionParser *)variablesParser { + if (!variablesParser) { + self.variablesParser = [PKSequence sequence]; + variablesParser.name = @"variables"; + [variablesParser add:self.variableParser]; + [variablesParser add:[PKRepetition repetitionWithSubparser:self.commaVariableParser]]; + } + return variablesParser; +} + + +//commaVariable = comma variable; +- (PKCollectionParser *)commaVariableParser { + if (!commaVariableParser) { + self.commaVariableParser = [PKSequence sequence]; + commaVariableParser.name = @"commaVariable"; + [commaVariableParser add:self.commaParser]; + [commaVariableParser add:self.variableParser]; + } + return commaVariableParser; +} + + +// Variable: +// Identifier +// Identifier = AssignmentExpression +// +//variable = identifier assignment?; +- (PKCollectionParser *)variableParser { + if (!variableParser) { + self.variableParser = [PKSequence sequence]; + variableParser.name = @"variableParser"; + [variableParser add:self.identifierParser]; + [variableParser add:[self zeroOrOne:self.assignmentParser]]; + } + return variableParser; +} + + +//assignment = equals assignmentExpr; +- (PKCollectionParser *)assignmentParser { + if (!assignmentParser) { + self.assignmentParser = [PKSequence sequence]; + assignmentParser.name = @"assignment"; + [assignmentParser add:self.equalsParser]; + [assignmentParser add:self.assignmentExprParser]; + } + return assignmentParser; +} + + +// ExpressionOpt: +// empty +// Expression +// +// exprOpt = Empty | expr; +- (PKCollectionParser *)exprOptParser { + if (!exprOptParser) { + self.exprOptParser = [self zeroOrOne:self.exprParser]; + exprOptParser.name = @"exprOpt"; + } + return exprOptParser; +} + + +// Expression: +// AssignmentExpression +// AssignmentExpression , Expression +// +//expr = assignmentExpr commaAssignmentExpr*; +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + exprParser.name = @"exprParser"; + [exprParser add:self.assignmentExprParser]; + [exprParser add:[PKRepetition repetitionWithSubparser:self.commaAssignmentExprParser]]; + } + return exprParser; +} + + +//commaAssignmentExpr = comma assignmentExpr; +- (PKCollectionParser *)commaAssignmentExprParser { + if (!commaAssignmentExprParser) { + self.commaAssignmentExprParser = [PKSequence sequence]; + commaAssignmentExprParser.name = @"commaAssignmentExpr"; + [commaAssignmentExprParser add:self.commaParser]; + [commaAssignmentExprParser add:self.assignmentExprParser]; + } + return commaAssignmentExprParser; +} + + +// AssignmentExpression: +// ConditionalExpression +// ConditionalExpression AssignmentOperator AssignmentExpression +// +// assignmentExpr = conditionalExpr assignmentOpConditionalExpr*; +- (PKCollectionParser *)assignmentExprParser { + if (!assignmentExprParser) { + self.assignmentExprParser = [PKSequence sequence]; + assignmentExprParser.name = @"assignmentExpr"; + [assignmentExprParser add:self.conditionalExprParser]; + [assignmentExprParser add:[PKRepetition repetitionWithSubparser:self.assignmentOpConditionalExprParser]]; + } + return assignmentExprParser; +} + + +// assignmentOpConditionalExpr = assignmentOperator conditionalExpr; +- (PKCollectionParser *)assignmentOpConditionalExprParser { + if (!assignmentOpConditionalExprParser) { + self.assignmentOpConditionalExprParser = [PKSequence sequence]; + assignmentOpConditionalExprParser.name = @"assignmentOpConditionalExpr"; + [assignmentOpConditionalExprParser add:self.assignmentOpParser]; + [assignmentOpConditionalExprParser add:self.conditionalExprParser]; + } + return assignmentOpConditionalExprParser; +} + + +// ConditionalExpression: +// OrExpression +// OrExpression ? AssignmentExpression : AssignmentExpression +// +// conditionalExpr = orExpr ternaryExpr?; +- (PKCollectionParser *)conditionalExprParser { + if (!conditionalExprParser) { + self.conditionalExprParser = [PKSequence sequence]; + conditionalExprParser.name = @"conditionalExpr"; + [conditionalExprParser add:self.orExprParser]; + [conditionalExprParser add:[self zeroOrOne:self.ternaryExprParser]]; + } + return conditionalExprParser; +} + + +// ternaryExpr = question assignmentExpr colon assignmentExpr; +- (PKCollectionParser *)ternaryExprParser { + if (!ternaryExprParser) { + self.ternaryExprParser = [PKSequence sequence]; + ternaryExprParser.name = @"ternaryExpr"; + [ternaryExprParser add:self.questionParser]; + [ternaryExprParser add:self.assignmentExprParser]; + [ternaryExprParser add:self.colonParser]; + [ternaryExprParser add:self.assignmentExprParser]; + } + return ternaryExprParser; +} + + +// OrExpression: +// AndExpression +// AndExpression || OrExpression +// +// orExpr = andExpr orAndExpr*; +- (PKCollectionParser *)orExprParser { + if (!orExprParser) { + self.orExprParser = [PKSequence sequence]; + orExprParser.name = @"orExpr"; + [orExprParser add:self.andExprParser]; + [orExprParser add:[PKRepetition repetitionWithSubparser:self.orAndExprParser]]; + } + return orExprParser; +} + + +// orAndExpr = or andExpr; +- (PKCollectionParser *)orAndExprParser { + if (!orAndExprParser) { + self.orAndExprParser = [PKSequence sequence]; + orAndExprParser.name = @"orAndExpr"; + [orAndExprParser add:self.orParser]; + [orAndExprParser add:self.andExprParser]; + } + return orAndExprParser; +} + + +// AndExpression: +// BitwiseOrExpression +// BitwiseOrExpression && AndExpression +// +// andExpr = bitwiseOrExpr andBitwiseOrExprParser*; +- (PKCollectionParser *)andExprParser { + if (!andExprParser) { + self.andExprParser = [PKSequence sequence]; + andExprParser.name = @"andExpr"; + [andExprParser add:self.bitwiseOrExprParser]; + [andExprParser add:[PKRepetition repetitionWithSubparser:self.andBitwiseOrExprParser]]; + } + return andExprParser; +} + + +// andBitwiseOrExprParser = and bitwiseOrExpr; +- (PKCollectionParser *)andBitwiseOrExprParser { + if (!andBitwiseOrExprParser) { + self.andBitwiseOrExprParser = [PKSequence sequence]; + andBitwiseOrExprParser.name = @"andBitwiseOrExpr"; + [andBitwiseOrExprParser add:self.andParser]; + [andBitwiseOrExprParser add:self.bitwiseOrExprParser]; + } + return andBitwiseOrExprParser; +} + + +// BitwiseOrExpression: +// BitwiseXorExpression +// BitwiseXorExpression | BitwiseOrExpression +// +// bitwiseOrExpr = bitwiseXorExpr pipeBitwiseXorExpr*; +- (PKCollectionParser *)bitwiseOrExprParser { + if (!bitwiseOrExprParser) { + self.bitwiseOrExprParser = [PKSequence sequence]; + bitwiseOrExprParser.name = @"bitwiseOrExpr"; + [bitwiseOrExprParser add:self.bitwiseXorExprParser]; + [bitwiseOrExprParser add:[PKRepetition repetitionWithSubparser:self.pipeBitwiseXorExprParser]]; + } + return bitwiseOrExprParser; +} + + +// pipeBitwiseXorExprParser = pipe bitwiseXorExpr; +- (PKCollectionParser *)pipeBitwiseXorExprParser { + if (!pipeBitwiseXorExprParser) { + self.pipeBitwiseXorExprParser = [PKSequence sequence]; + pipeBitwiseXorExprParser.name = @"pipeBitwiseXorExpr"; + [pipeBitwiseXorExprParser add:self.pipeParser]; + [pipeBitwiseXorExprParser add:self.bitwiseXorExprParser]; + } + return pipeBitwiseXorExprParser; +} + + +// BitwiseXorExpression: +// BitwiseAndExpression +// BitwiseAndExpression ^ BitwiseXorExpression +// +// bitwiseXorExpr = bitwiseAndExpr caretBitwiseAndExpr*; +- (PKCollectionParser *)bitwiseXorExprParser { + if (!bitwiseXorExprParser) { + self.bitwiseXorExprParser = [PKSequence sequence]; + bitwiseXorExprParser.name = @"bitwiseXorExpr"; + [bitwiseXorExprParser add:self.bitwiseAndExprParser]; + [bitwiseXorExprParser add:[PKRepetition repetitionWithSubparser:self.caretBitwiseAndExprParser]]; + } + return bitwiseXorExprParser; +} + + +// caretBitwiseAndExpr = caret bitwiseAndExpr; +- (PKCollectionParser *)caretBitwiseAndExprParser { + if (!caretBitwiseAndExprParser) { + self.caretBitwiseAndExprParser = [PKSequence sequence]; + caretBitwiseAndExprParser.name = @"caretBitwiseAndExpr"; + [caretBitwiseAndExprParser add:self.caretParser]; + [caretBitwiseAndExprParser add:self.bitwiseAndExprParser]; + } + return caretBitwiseAndExprParser; +} + + +// BitwiseAndExpression: +// EqualityExpression +// EqualityExpression & BitwiseAndExpression +// +// bitwiseAndExpr = equalityExpr ampEqualityExpr*; +- (PKCollectionParser *)bitwiseAndExprParser { + if (!bitwiseAndExprParser) { + self.bitwiseAndExprParser = [PKSequence sequence]; + bitwiseAndExprParser.name = @"bitwiseAndExpr"; + [bitwiseAndExprParser add:self.equalityExprParser]; + [bitwiseAndExprParser add:[PKRepetition repetitionWithSubparser:self.ampEqualityExprParser]]; + } + return bitwiseAndExprParser; +} + + +// ampEqualityExpression = amp equalityExpression; +- (PKCollectionParser *)ampEqualityExprParser { + if (!ampEqualityExprParser) { + self.ampEqualityExprParser = [PKSequence sequence]; + ampEqualityExprParser.name = @"ampEqualityExpr"; + [ampEqualityExprParser add:self.ampParser]; + [ampEqualityExprParser add:self.equalityExprParser]; + } + return ampEqualityExprParser; +} + + +// EqualityExpression: +// RelationalExpression +// RelationalExpression EqualityualityOperator EqualityExpression +// +// equalityExpr = relationalExpr equalityOpRelationalExpr*; +- (PKCollectionParser *)equalityExprParser { + if (!equalityExprParser) { + self.equalityExprParser = [PKSequence sequence]; + equalityExprParser.name = @"equalityExpr"; + [equalityExprParser add:self.relationalExprParser]; + [equalityExprParser add:[PKRepetition repetitionWithSubparser:self.equalityOpRelationalExprParser]]; + } + return equalityExprParser; +} + + +// equalityOpRelationalExpr = equalityOp relationalExpr; +- (PKCollectionParser *)equalityOpRelationalExprParser { + if (!equalityOpRelationalExprParser) { + self.equalityOpRelationalExprParser = [PKSequence sequence]; + equalityOpRelationalExprParser.name = @"equalityOpRelationalExpr"; + [equalityOpRelationalExprParser add:self.equalityOpParser]; + [equalityOpRelationalExprParser add:self.relationalExprParser]; + } + return equalityOpRelationalExprParser; +} + + +// RelationalExpression: +// ShiftExpression +// RelationalExpression RelationalationalOperator ShiftExpression +// + +// relationalExpr = shiftExpr relationalOpShiftExpr*; /// TODO ???? +- (PKCollectionParser *)relationalExprParser { + if (!relationalExprParser) { + self.relationalExprParser = [PKSequence sequence]; + relationalExprParser.name = @"relationalExpr"; + [relationalExprParser add:self.shiftExprParser]; + [relationalExprParser add:[PKRepetition repetitionWithSubparser:self.relationalOpShiftExprParser]]; + } + return relationalExprParser; +} + + +// relationalOpShiftExpr = relationalOperator shiftExpr; +- (PKCollectionParser *)relationalOpShiftExprParser { + if (!relationalOpShiftExprParser) { + self.relationalOpShiftExprParser = [PKSequence sequence]; + relationalOpShiftExprParser.name = @"relationalOpShiftExpr"; + [relationalOpShiftExprParser add:self.relationalOpParser]; + [relationalOpShiftExprParser add:self.shiftExprParser]; + } + return relationalOpShiftExprParser; +} + + +// ShiftExpression: +// AdditiveExpression +// AdditiveExpression ShiftOperator ShiftExpression +// +// shiftExpr = additiveExpr shiftOpAdditiveExpr?; +- (PKCollectionParser *)shiftExprParser { + if (!shiftExprParser) { + self.shiftExprParser = [PKSequence sequence]; + shiftExprParser.name = @"shiftExpr"; + [shiftExprParser add:self.additiveExprParser]; + [shiftExprParser add:[PKRepetition repetitionWithSubparser:self.shiftOpAdditiveExprParser]]; + } + return shiftExprParser; +} + + +// shiftOpShiftExpr = shiftOp additiveExpr; +- (PKCollectionParser *)shiftOpAdditiveExprParser { + if (!shiftOpAdditiveExprParser) { + self.shiftOpAdditiveExprParser = [PKSequence sequence]; + shiftOpAdditiveExprParser.name = @"shiftOpShiftExpr"; + [shiftOpAdditiveExprParser add:self.shiftOpParser]; + [shiftOpAdditiveExprParser add:self.additiveExprParser]; + } + return shiftOpAdditiveExprParser; +} + + +// AdditiveExpression: +// MultiplicativeExpression +// MultiplicativeExpression + AdditiveExpression +// MultiplicativeExpression - AdditiveExpression +// +// additiveExpr = multiplicativeExpr plusOrMinusExpr*; +- (PKCollectionParser *)additiveExprParser { + if (!additiveExprParser) { + self.additiveExprParser = [PKSequence sequence]; + additiveExprParser.name = @"additiveExpr"; + [additiveExprParser add:self.multiplicativeExprParser]; + [additiveExprParser add:[PKRepetition repetitionWithSubparser:self.plusOrMinusExprParser]]; + } + return additiveExprParser; +} + + +// plusOrMinusExpr = plusExpr | minusExpr; +- (PKCollectionParser *)plusOrMinusExprParser { + if (!plusOrMinusExprParser) { + self.plusOrMinusExprParser = [PKAlternation alternation]; + plusOrMinusExprParser.name = @"plusOrMinusExpr"; + [plusOrMinusExprParser add:self.plusExprParser]; + [plusOrMinusExprParser add:self.minusExprParser]; + } + return plusOrMinusExprParser; +} + + +// plusExpr = plus multiplicativeExprParser; +- (PKCollectionParser *)plusExprParser { + if (!plusExprParser) { + self.plusExprParser = [PKSequence sequence]; + plusExprParser.name = @"plusExpr"; + [plusExprParser add:self.plusParser]; + [plusExprParser add:self.multiplicativeExprParser]; + } + return plusExprParser; +} + + +// minusExpr = minus multiplicativeExprParser; +- (PKCollectionParser *)minusExprParser { + if (!minusExprParser) { + self.minusExprParser = [PKSequence sequence]; + minusExprParser.name = @"minusExpr"; + [minusExprParser add:self.minusParser]; + [minusExprParser add:self.multiplicativeExprParser]; + } + return minusExprParser; +} + + +// MultiplicativeExpression: +// UnaryExpression +// UnaryExpression MultiplicativeOperator MultiplicativeExpression +// +// multiplicativeExpr = unaryExpr multiplicativeOpUnaryExpr*; +- (PKCollectionParser *)multiplicativeExprParser { + if (!multiplicativeExprParser) { + self.multiplicativeExprParser = [PKSequence sequence]; + multiplicativeExprParser.name = @"multiplicativeExpr"; + [multiplicativeExprParser add:self.unaryExprParser]; + [multiplicativeExprParser add:[PKRepetition repetitionWithSubparser:self.multiplicativeOpUnaryExprParser]]; + } + return multiplicativeExprParser; +} + + +// multiplicativeOpUnaryExpr = multiplicativeOp unaryExpr; +- (PKCollectionParser *)multiplicativeOpUnaryExprParser { + if (!multiplicativeOpUnaryExprParser) { + self.multiplicativeOpUnaryExprParser = [PKSequence sequence]; + multiplicativeOpUnaryExprParser.name = @"multiplicativeOpUnaryExpr"; + [multiplicativeOpUnaryExprParser add:self.multiplicativeOpParser]; + [multiplicativeOpUnaryExprParser add:self.unaryExprParser]; + } + return multiplicativeOpUnaryExprParser; +} + + +// UnaryExpression: +// MemberExpression +// UnaryOperator UnaryExpression +// - UnaryExpression +// IncrementOperator MemberExpression +// MemberExpression IncrementOperator +// new Constructor +// delete MemberExpression +// +// unaryExpr = memberExpr | unaryExpr1 | unaryExpr2 | unaryExpr3 | unaryExpr4 | unaryExpr5 | unaryExpr6; +- (PKCollectionParser *)unaryExprParser { + if (!unaryExprParser) { + self.unaryExprParser = [PKAlternation alternation]; + unaryExprParser.name = @"unaryExpr"; + [unaryExprParser add:self.memberExprParser]; + [unaryExprParser add:self.unaryExpr1Parser]; + [unaryExprParser add:self.unaryExpr2Parser]; + [unaryExprParser add:self.unaryExpr3Parser]; + [unaryExprParser add:self.unaryExpr4Parser]; + [unaryExprParser add:self.unaryExpr5Parser]; + [unaryExprParser add:self.unaryExpr6Parser]; + } + return unaryExprParser; +} + + +// unaryExpr1 = unaryOperator unaryExpr; +- (PKCollectionParser *)unaryExpr1Parser { + if (!unaryExpr1Parser) { + self.unaryExpr1Parser = [PKSequence sequence]; + unaryExpr1Parser.name = @"unaryExpr1"; + [unaryExpr1Parser add:self.unaryOpParser]; + [unaryExpr1Parser add:self.unaryExprParser]; + } + return unaryExpr1Parser; +} + + +// unaryExpr2 = minus unaryExpr; +- (PKCollectionParser *)unaryExpr2Parser { + if (!unaryExpr2Parser) { + self.unaryExpr2Parser = [PKSequence sequence]; + unaryExpr2Parser.name = @"unaryExpr2"; + [unaryExpr2Parser add:self.minusParser]; + [unaryExpr2Parser add:self.unaryExprParser]; + } + return unaryExpr2Parser; +} + + +// unaryExpr3 = incrementOperator memberExpr; +- (PKCollectionParser *)unaryExpr3Parser { + if (!unaryExpr3Parser) { + self.unaryExpr3Parser = [PKSequence sequence]; + unaryExpr3Parser.name = @"unaryExpr3"; + [unaryExpr3Parser add:self.incrementOpParser]; + [unaryExpr3Parser add:self.memberExprParser]; + } + return unaryExpr3Parser; +} + + +// unaryExpr4 = memberExpr incrementOperator; +- (PKCollectionParser *)unaryExpr4Parser { + if (!unaryExpr4Parser) { + self.unaryExpr4Parser = [PKSequence sequence]; + unaryExpr4Parser.name = @"unaryExpr4"; + [unaryExpr4Parser add:self.memberExprParser]; + [unaryExpr4Parser add:self.incrementOpParser]; + } + return unaryExpr4Parser; +} + + +// unaryExpr5 = new constructor; +- (PKCollectionParser *)unaryExpr5Parser { + if (!unaryExpr5Parser) { + self.unaryExpr5Parser = [PKSequence sequence]; + unaryExpr5Parser.name = @"unaryExpr5"; + [unaryExpr5Parser add:self.newParser]; + [unaryExpr5Parser add:self.constructorCallParser]; + } + return unaryExpr5Parser; +} + + +// unaryExpr6 = delete memberExpr; +- (PKCollectionParser *)unaryExpr6Parser { + if (!unaryExpr6Parser) { + self.unaryExpr6Parser = [PKSequence sequence]; + unaryExpr6Parser.name = @"unaryExpr6"; + [unaryExpr6Parser add:self.deleteParser]; + [unaryExpr6Parser add:self.memberExprParser]; + } + return unaryExpr6Parser; +} + + +// ConstructorCall: +// Identifier +// Identifier ( ArgumentListOpt ) +// Identifier . ConstructorCall +// + +// constructorCall = identifier parentArgListOptParent? memberExprExt* +- (PKCollectionParser *)constructorCallParser { + if (!constructorCallParser) { + self.constructorCallParser = [PKSequence sequence]; + constructorCallParser.name = @"constructorCall"; + [constructorCallParser add:self.identifierParser]; + [constructorCallParser add:[self zeroOrOne:self.parenArgListOptParenParser]]; + [constructorCallParser add:[PKRepetition repetitionWithSubparser:self.memberExprExtParser]]; + } + return constructorCallParser; +} + + +// parenArgListParen = openParen argListOpt closeParen; +- (PKCollectionParser *)parenArgListOptParenParser { + if (!parenArgListOptParenParser) { + self.parenArgListOptParenParser = [PKSequence sequence]; + parenArgListOptParenParser.name = @"parenArgListParen"; + [parenArgListOptParenParser add:self.openParenParser]; + [parenArgListOptParenParser add:self.argListOptParser]; + [parenArgListOptParenParser add:self.closeParenParser]; + } + return parenArgListOptParenParser; +} + + +// MemberExpression: +// PrimaryExpression +// PrimaryExpression . MemberExpression +// PrimaryExpression [ Expression ] +// PrimaryExpression ( ArgumentListOpt ) +// +// memberExpr = primaryExpr memberExprExt?; // TODO ?????? +- (PKCollectionParser *)memberExprParser { + if (!memberExprParser) { + self.memberExprParser = [PKSequence sequence]; + memberExprParser.name = @"memberExpr"; + [memberExprParser add:self.primaryExprParser]; + [memberExprParser add:[PKRepetition repetitionWithSubparser:self.memberExprExtParser]]; + } + return memberExprParser; +} + + +// memberExprExt = dotMemberExpr | bracketMemberExpr | parenMemberExpr; +- (PKCollectionParser *)memberExprExtParser { + if (!memberExprExtParser) { + self.memberExprExtParser = [PKAlternation alternation]; + memberExprExtParser.name = @"memberExprExt"; + [memberExprExtParser add:self.dotMemberExprParser]; + [memberExprExtParser add:self.bracketMemberExprParser]; + [memberExprExtParser add:self.parenArgListOptParenParser]; + } + return memberExprExtParser; +} + + +// dotMemberExpr = dot memberExpr; +- (PKCollectionParser *)dotMemberExprParser { + if (!dotMemberExprParser) { + self.dotMemberExprParser = [PKSequence sequence]; + dotMemberExprParser.name = @"dotMemberExpr"; + [dotMemberExprParser add:self.dotParser]; + [dotMemberExprParser add:self.memberExprParser]; + } + return dotMemberExprParser; +} + + +// bracketMemberExpr = openBracket expr closeBracket; +- (PKCollectionParser *)bracketMemberExprParser { + if (!bracketMemberExprParser) { + self.bracketMemberExprParser = [PKSequence sequence]; + bracketMemberExprParser.name = @"bracketMemberExpr"; + [bracketMemberExprParser add:self.openBracketParser]; + [bracketMemberExprParser add:self.exprParser]; + [bracketMemberExprParser add:self.closeBracketParser]; + } + return bracketMemberExprParser; +} + + +// ArgumentListOpt: +// empty +// ArgumentList +// +// argListOpt = argList?; +- (PKCollectionParser *)argListOptParser { + if (!argListOptParser) { + self.argListOptParser = [self zeroOrOne:self.argListParser]; + argListOptParser.name = @"argListOpt"; + } + return argListOptParser; +} + + +// ArgumentList: +// AssignmentExpression +// AssignmentExpression , ArgumentList +// +// argList = assignmentExpr commaAssignmentExpr*; +- (PKCollectionParser *)argListParser { + if (!argListParser) { + self.argListParser = [PKSequence sequence]; + argListParser.name = @"argList"; + [argListParser add:self.assignmentExprParser]; + [argListParser add:[PKRepetition repetitionWithSubparser:self.commaAssignmentExprParser]]; + } + return argListParser; +} + + + // PrimaryExpression: + // ( Expression ) + // funcLiteral + // arrayLiteral + // Identifier + // IntegerLiteral + // FloatingPointLiteral + // StringLiteral + // false + // true + // null + // this +// primaryExpr = parenExprParen | funcLiteral | arrayLiteral | identifier | Number | QuotedString | false | true | null | undefined | this; +- (PKCollectionParser *)primaryExprParser { + if (!primaryExprParser) { + self.primaryExprParser = [PKAlternation alternation]; + primaryExprParser.name = @"primaryExpr"; + [primaryExprParser add:self.parenExprParenParser]; + [primaryExprParser add:self.funcLiteralParser]; + [primaryExprParser add:self.arrayLiteralParser]; + [primaryExprParser add:self.objectLiteralParser]; + [primaryExprParser add:self.identifierParser]; + [primaryExprParser add:self.numberParser]; + [primaryExprParser add:self.stringParser]; + [primaryExprParser add:self.trueParser]; + [primaryExprParser add:self.falseParser]; + [primaryExprParser add:self.nullParser]; + [primaryExprParser add:self.undefinedParser]; // TODO ?? + [primaryExprParser add:self.thisParser]; + } + return primaryExprParser; +} + + + +// parenExprParen = openParen expr closeParen; +- (PKCollectionParser *)parenExprParenParser { + if (!parenExprParenParser) { + self.parenExprParenParser = [PKSequence sequence]; + parenExprParenParser.name = @"parenExprParen"; + [parenExprParenParser add:self.openParenParser]; + [parenExprParenParser add:self.exprParser]; + [parenExprParenParser add:self.closeParenParser]; + } + return parenExprParenParser; +} + + +//funcLiteral = function openParen paramListOpt closeParen compoundStmt; +- (PKCollectionParser *)funcLiteralParser { + if (!funcLiteralParser) { + self.funcLiteralParser = [PKSequence sequence]; + funcLiteralParser.name = @"funcLiteral"; + [funcLiteralParser add:self.functionParser]; + [funcLiteralParser add:self.openParenParser]; + [funcLiteralParser add:self.paramListOptParser]; + [funcLiteralParser add:self.closeParenParser]; + [funcLiteralParser add:self.compoundStmtParser]; + } + return funcLiteralParser; +} + + +//arrayLiteral = '[' arrayContents ']'; +- (PKCollectionParser *)arrayLiteralParser { + if (!arrayLiteralParser) { + self.arrayLiteralParser = [PKTrack track]; + arrayLiteralParser.name = @"arrayLiteralParser"; + + PKSequence *commaPrimaryExpr = [PKSequence sequence]; + [commaPrimaryExpr add:self.commaParser]; + [commaPrimaryExpr add:self.primaryExprParser]; + + PKSequence *arrayContents = [PKSequence sequence]; + [arrayContents add:self.primaryExprParser]; + [arrayContents add:[PKRepetition repetitionWithSubparser:commaPrimaryExpr]]; + + PKAlternation *arrayContentsOpt = [PKAlternation alternation]; + [arrayContentsOpt add:[PKEmpty empty]]; + [arrayContentsOpt add:arrayContents]; + + [arrayLiteralParser add:self.openBracketParser]; + [arrayLiteralParser add:arrayContentsOpt]; + [arrayLiteralParser add:self.closeBracketParser]; + } + return arrayLiteralParser; +} + + +//objectLiteral = '{' objectContentsOpt '}'; +- (PKCollectionParser *)objectLiteralParser { + if (!objectLiteralParser) { + self.objectLiteralParser = [PKSequence sequence]; + objectLiteralParser.name = @"objectLiteralParser"; + + PKSequence *member = [PKSequence sequence]; + [member add:self.identifierParser]; + [member add:self.colonParser]; + [member add:self.primaryExprParser]; + + PKSequence *commaMember = [PKSequence sequence]; + [commaMember add:self.commaParser]; + [commaMember add:member]; + + PKSequence *objectContents = [PKSequence sequence]; + [objectContents add:member]; + [objectContents add:[PKRepetition repetitionWithSubparser:commaMember]]; + + PKAlternation *objectContentsOpt = [PKAlternation alternation]; + [objectContentsOpt add:[PKEmpty empty]]; + [objectContentsOpt add:objectContents]; + + [objectLiteralParser add:self.openCurlyParser]; + [objectLiteralParser add:objectContentsOpt]; + [objectLiteralParser add:self.closeCurlyParser]; + } + return objectLiteralParser; +} + + +// identifier = Word; +- (PKParser *)identifierParser { + if (!identifierParser) { + self.identifierParser = [PKWord word]; + identifierParser.name = @"identifier"; + } + return identifierParser; +} + + +- (PKParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKQuotedString quotedString]; + stringParser.name = @"string"; + } + return stringParser; +} + + +- (PKParser *)numberParser { + if (!numberParser) { + self.numberParser = [PKNumber number]; + numberParser.name = @"number"; + } + return numberParser; +} + + +#pragma mark - +#pragma mark keywords + +- (PKParser *)ifParser { + if (!ifParser) { + self.ifParser = [PKLiteral literalWithString:@"if"]; + ifParser.name = @"if"; + } + return ifParser; +} + + +- (PKParser *)elseParser { + if (!elseParser) { + self.elseParser = [PKLiteral literalWithString:@"else"]; + elseParser.name = @"else"; + } + return elseParser; +} + + +- (PKParser *)whileParser { + if (!whileParser) { + self.whileParser = [PKLiteral literalWithString:@"while"]; + whileParser.name = @"while"; + } + return whileParser; +} + + +- (PKParser *)forParser { + if (!forParser) { + self.forParser = [PKLiteral literalWithString:@"for"]; + forParser.name = @"for"; + } + return forParser; +} + + +- (PKParser *)inParser { + if (!inParser) { + self.inParser = [PKLiteral literalWithString:@"in"]; + inParser.name = @"in"; + } + return inParser; +} + + +- (PKParser *)breakParser { + if (!breakParser) { + self.breakParser = [PKLiteral literalWithString:@"break"]; + breakParser.name = @"break"; + } + return breakParser; +} + + +- (PKParser *)continueParser { + if (!continueParser) { + self.continueParser = [PKLiteral literalWithString:@"continue"]; + continueParser.name = @"continue"; + } + return continueParser; +} + + +- (PKParser *)withParser { + if (!withParser) { + self.withParser = [PKLiteral literalWithString:@"with"]; + withParser.name = @"with"; + } + return withParser; +} + + +- (PKParser *)returnParser { + if (!returnParser) { + self.returnParser = [PKLiteral literalWithString:@"return"]; + returnParser.name = @"return"; + } + return returnParser; +} + + +- (PKParser *)varParser { + if (!varParser) { + self.varParser = [PKLiteral literalWithString:@"var"]; + varParser.name = @"var"; + } + return varParser; +} + + +- (PKParser *)deleteParser { + if (!deleteParser) { + self.deleteParser = [PKLiteral literalWithString:@"delete"]; + deleteParser.name = @"delete"; + } + return deleteParser; +} + + +- (PKParser *)newParser { + if (!newParser) { + self.newParser = [PKLiteral literalWithString:@"new"]; + newParser.name = @"new"; + } + return newParser; +} + + +- (PKParser *)thisParser { + if (!thisParser) { + self.thisParser = [PKLiteral literalWithString:@"this"]; + thisParser.name = @"this"; + } + return thisParser; +} + + +- (PKParser *)falseParser { + if (!falseParser) { + self.falseParser = [PKLiteral literalWithString:@"false"]; + falseParser.name = @"false"; + } + return falseParser; +} + + +- (PKParser *)trueParser { + if (!trueParser) { + self.trueParser = [PKLiteral literalWithString:@"true"]; + trueParser.name = @"true"; + } + return trueParser; +} + + +- (PKParser *)nullParser { + if (!nullParser) { + self.nullParser = [PKLiteral literalWithString:@"null"]; + nullParser.name = @"null"; + } + return nullParser; +} + + +- (PKParser *)undefinedParser { + if (!undefinedParser) { + self.undefinedParser = [PKLiteral literalWithString:@"undefined"]; + undefinedParser.name = @"undefined"; + } + return undefinedParser; +} + + +- (PKParser *)voidParser { + if (!voidParser) { + self.voidParser = [PKLiteral literalWithString:@"void"]; + voidParser.name = @"void"; + } + return voidParser; +} + + +- (PKParser *)typeofParser { + if (!typeofParser) { + self.typeofParser = [PKLiteral literalWithString:@"typeof"]; + typeofParser.name = @"typeof"; + } + return typeofParser; +} + + +- (PKParser *)instanceofParser { + if (!instanceofParser) { + self.instanceofParser = [PKLiteral literalWithString:@"instanceof"]; + instanceofParser.name = @"instanceof"; + } + return instanceofParser; +} + + +- (PKParser *)functionParser { + if (!functionParser) { + self.functionParser = [PKLiteral literalWithString:@"function"]; + functionParser.name = @"function"; + } + return functionParser; +} + + +#pragma mark - +#pragma mark single-char symbols + +- (PKParser *)orParser { + if (!orParser) { + self.orParser = [PKSymbol symbolWithString:@"||"]; + orParser.name = @"or"; + } + return orParser; +} + + +- (PKParser *)andParser { + if (!andParser) { + self.andParser = [PKSymbol symbolWithString:@"&&"]; + andParser.name = @"and"; + } + return andParser; +} + + +- (PKParser *)neParser { + if (!neParser) { + self.neParser = [PKSymbol symbolWithString:@"!="]; + neParser.name = @"ne"; + } + return neParser; +} + + +- (PKParser *)isNotParser { + if (!isNotParser) { + self.isNotParser = [PKSymbol symbolWithString:@"!=="]; + isNotParser.name = @"isNot"; + } + return isNotParser; +} + + +- (PKParser *)eqParser { + if (!eqParser) { + self.eqParser = [PKSymbol symbolWithString:@"=="]; + eqParser.name = @"eq"; + } + return eqParser; +} + + +- (PKParser *)isParser { + if (!isParser) { + self.isParser = [PKSymbol symbolWithString:@"==="]; + isParser.name = @"is"; + } + return isParser; +} + + +- (PKParser *)leParser { + if (!leParser) { + self.leParser = [PKSymbol symbolWithString:@"<="]; + leParser.name = @"le"; + } + return leParser; +} + + +- (PKParser *)geParser { + if (!geParser) { + self.geParser = [PKSymbol symbolWithString:@">="]; + geParser.name = @"ge"; + } + return geParser; +} + + +- (PKParser *)plusPlusParser { + if (!plusPlusParser) { + self.plusPlusParser = [PKSymbol symbolWithString:@"++"]; + plusPlusParser.name = @"plusPlus"; + } + return plusPlusParser; +} + + +- (PKParser *)minusMinusParser { + if (!minusMinusParser) { + self.minusMinusParser = [PKSymbol symbolWithString:@"--"]; + minusMinusParser.name = @"minusMinus"; + } + return minusMinusParser; +} + + +- (PKParser *)plusEqParser { + if (!plusEqParser) { + self.plusEqParser = [PKSymbol symbolWithString:@"+="]; + plusEqParser.name = @"plusEq"; + } + return plusEqParser; +} + + +- (PKParser *)minusEqParser { + if (!minusEqParser) { + self.minusEqParser = [PKSymbol symbolWithString:@"-="]; + minusEqParser.name = @"minusEq"; + } + return minusEqParser; +} + + +- (PKParser *)timesEqParser { + if (!timesEqParser) { + self.timesEqParser = [PKSymbol symbolWithString:@"*="]; + timesEqParser.name = @"timesEq"; + } + return timesEqParser; +} + + +- (PKParser *)divEqParser { + if (!divEqParser) { + self.divEqParser = [PKSymbol symbolWithString:@"/="]; + divEqParser.name = @"divEq"; + } + return divEqParser; +} + + +- (PKParser *)modEqParser { + if (!modEqParser) { + self.modEqParser = [PKSymbol symbolWithString:@"%="]; + modEqParser.name = @"modEq"; + } + return modEqParser; +} + + +- (PKParser *)shiftLeftParser { + if (!shiftLeftParser) { + self.shiftLeftParser = [PKSymbol symbolWithString:@"<<"]; + shiftLeftParser.name = @"shiftLeft"; + } + return shiftLeftParser; +} + + +- (PKParser *)shiftRightParser { + if (!shiftRightParser) { + self.shiftRightParser = [PKSymbol symbolWithString:@">>"]; + shiftRightParser.name = @"shiftRight"; + } + return shiftRightParser; +} + + +- (PKParser *)shiftRightExtParser { + if (!shiftRightExtParser) { + self.shiftRightExtParser = [PKSymbol symbolWithString:@">>>"]; + shiftRightExtParser.name = @"shiftRightExt"; + } + return shiftRightExtParser; +} + + +- (PKParser *)shiftLeftEqParser { + if (!shiftLeftEqParser) { + self.shiftLeftEqParser = [PKSymbol symbolWithString:@"<<="]; + shiftLeftEqParser.name = @"shiftLeftEq"; + } + return shiftLeftEqParser; +} + + +- (PKParser *)shiftRightEqParser { + if (!shiftRightEqParser) { + self.shiftRightEqParser = [PKSymbol symbolWithString:@">>="]; + shiftRightEqParser.name = @"shiftRightEq"; + } + return shiftRightEqParser; +} + + +- (PKParser *)shiftRightExtEqParser { + if (!shiftRightExtEqParser) { + self.shiftRightExtEqParser = [PKSymbol symbolWithString:@">>>="]; + shiftRightExtEqParser.name = @"shiftRightExtEq"; + } + return shiftRightExtEqParser; +} + + +- (PKParser *)andEqParser { + if (!andEqParser) { + self.andEqParser = [PKSymbol symbolWithString:@"&="]; + andEqParser.name = @"andEq"; + } + return andEqParser; +} + + +- (PKParser *)xorEqParser { + if (!xorEqParser) { + self.xorEqParser = [PKSymbol symbolWithString:@"^="]; + xorEqParser.name = @"xorEq"; + } + return xorEqParser; +} + + +- (PKParser *)orEqParser { + if (!orEqParser) { + self.orEqParser = [PKSymbol symbolWithString:@"|="]; + orEqParser.name = @"orEq"; + } + return orEqParser; +} + + +#pragma mark - +#pragma mark single-char symbols + +- (PKParser *)openCurlyParser { + if (!openCurlyParser) { + self.openCurlyParser = [PKSymbol symbolWithString:@"{"]; + openCurlyParser.name = @"openCurly"; + } + return openCurlyParser; +} + + +- (PKParser *)closeCurlyParser { + if (!closeCurlyParser) { + self.closeCurlyParser = [PKSymbol symbolWithString:@"}"]; + closeCurlyParser.name = @"closeCurly"; + } + return closeCurlyParser; +} + + +- (PKParser *)openParenParser { + if (!openParenParser) { + self.openParenParser = [PKSymbol symbolWithString:@"("]; + openParenParser.name = @"openParen"; + } + return openParenParser; +} + + +- (PKParser *)closeParenParser { + if (!closeParenParser) { + self.closeParenParser = [PKSymbol symbolWithString:@")"]; + closeParenParser.name = @"closeParen"; + } + return closeParenParser; +} + + +- (PKParser *)openBracketParser { + if (!openBracketParser) { + self.openBracketParser = [PKSymbol symbolWithString:@"["]; + openBracketParser.name = @"openBracket"; + } + return openBracketParser; +} + + +- (PKParser *)closeBracketParser { + if (!closeBracketParser) { + self.closeBracketParser = [PKSymbol symbolWithString:@"]"]; + closeBracketParser.name = @"closeBracket"; + } + return closeBracketParser; +} + + +- (PKParser *)commaParser { + if (!commaParser) { + self.commaParser = [PKSymbol symbolWithString:@","]; + commaParser.name = @"comma"; + } + return commaParser; +} + + +- (PKParser *)dotParser { + if (!dotParser) { + self.dotParser = [PKSymbol symbolWithString:@"."]; + dotParser.name = @"dot"; + } + return dotParser; +} + + +- (PKParser *)semiOptParser { + if (!semiOptParser) { + self.semiOptParser = [self zeroOrOne:self.semiParser]; + semiOptParser.name = @"semiOpt"; + } + return semiOptParser; +} + + +- (PKParser *)semiParser { + if (!semiParser) { + self.semiParser = [PKSymbol symbolWithString:@";"]; + semiParser.name = @"semi"; + } + return semiParser; +} + + +- (PKParser *)colonParser { + if (!colonParser) { + self.colonParser = [PKSymbol symbolWithString:@":"]; + colonParser.name = @"colon"; + } + return colonParser; +} + + +- (PKParser *)equalsParser { + if (!equalsParser) { + self.equalsParser = [PKSymbol symbolWithString:@"="]; + equalsParser.name = @"equals"; + } + return equalsParser; +} + + +- (PKParser *)notParser { + if (!notParser) { + self.notParser = [PKSymbol symbolWithString:@"!"]; + notParser.name = @"not"; + } + return notParser; +} + + +- (PKParser *)ltParser { + if (!ltParser) { + self.ltParser = [PKSymbol symbolWithString:@"<"]; + ltParser.name = @"lt"; + } + return ltParser; +} + + +- (PKParser *)gtParser { + if (!gtParser) { + self.gtParser = [PKSymbol symbolWithString:@">"]; + gtParser.name = @"gt"; + } + return gtParser; +} + + +- (PKParser *)ampParser { + if (!ampParser) { + self.ampParser = [PKSymbol symbolWithString:@"&"]; + ampParser.name = @"amp"; + } + return ampParser; +} + + +- (PKParser *)pipeParser { + if (!pipeParser) { + self.pipeParser = [PKSymbol symbolWithString:@"|"]; + pipeParser.name = @"pipe"; + } + return pipeParser; +} + + +- (PKParser *)caretParser { + if (!caretParser) { + self.caretParser = [PKSymbol symbolWithString:@"^"]; + caretParser.name = @"caret"; + } + return caretParser; +} + + +- (PKParser *)tildeParser { + if (!tildeParser) { + self.tildeParser = [PKSymbol symbolWithString:@"~"]; + tildeParser.name = @"tilde"; + } + return tildeParser; +} + + +- (PKParser *)questionParser { + if (!questionParser) { + self.questionParser = [PKSymbol symbolWithString:@"?"]; + questionParser.name = @"question"; + } + return questionParser; +} + + +- (PKParser *)plusParser { + if (!plusParser) { + self.plusParser = [PKSymbol symbolWithString:@"+"]; + plusParser.name = @"plus"; + } + return plusParser; +} + + +- (PKParser *)minusParser { + if (!minusParser) { + self.minusParser = [PKSymbol symbolWithString:@"-"]; + minusParser.name = @"minus"; + } + return minusParser; +} + + +- (PKParser *)timesParser { + if (!timesParser) { + self.timesParser = [PKSymbol symbolWithString:@"x"]; + timesParser.name = @"times"; + } + return timesParser; +} + + +- (PKParser *)divParser { + if (!divParser) { + self.divParser = [PKSymbol symbolWithString:@"/"]; + divParser.name = @"div"; + } + return divParser; +} + + +- (PKParser *)modParser { + if (!modParser) { + self.modParser = [PKSymbol symbolWithString:@"%"]; + modParser.name = @"mod"; + } + return modParser; +} + +@synthesize assignmentOpParser; +@synthesize relationalOpParser; +@synthesize equalityOpParser; +@synthesize shiftOpParser; +@synthesize incrementOpParser; +@synthesize unaryOpParser; +@synthesize multiplicativeOpParser; + +@synthesize programParser; +@synthesize elementParser; +@synthesize funcParser; +@synthesize paramListOptParser; +@synthesize paramListParser; +@synthesize commaIdentifierParser; +@synthesize compoundStmtParser; +@synthesize stmtsParser; +@synthesize stmtParser; +@synthesize ifStmtParser; +@synthesize ifElseStmtParser; +@synthesize whileStmtParser; +@synthesize forParenStmtParser; +@synthesize forBeginStmtParser; +@synthesize forInStmtParser; +@synthesize breakStmtParser; +@synthesize continueStmtParser; +@synthesize withStmtParser; +@synthesize returnStmtParser; +@synthesize variablesOrExprStmtParser; +@synthesize conditionParser; +@synthesize forParenParser; +@synthesize forBeginParser; +@synthesize variablesOrExprParser; +@synthesize varVariablesParser; +@synthesize variablesParser; +@synthesize commaVariableParser; +@synthesize variableParser; +@synthesize assignmentParser; +@synthesize exprOptParser; +@synthesize exprParser; +@synthesize commaAssignmentExprParser; +@synthesize assignmentExprParser; +@synthesize assignmentOpConditionalExprParser; +@synthesize conditionalExprParser; +@synthesize ternaryExprParser; +@synthesize orExprParser; +@synthesize orAndExprParser; +@synthesize andExprParser; +@synthesize andBitwiseOrExprParser; +@synthesize bitwiseOrExprParser; +@synthesize pipeBitwiseXorExprParser; +@synthesize bitwiseXorExprParser; +@synthesize caretBitwiseAndExprParser; +@synthesize bitwiseAndExprParser; +@synthesize ampEqualityExprParser; +@synthesize equalityExprParser; +@synthesize equalityOpRelationalExprParser; +@synthesize relationalExprParser; +@synthesize relationalOpShiftExprParser; +@synthesize shiftExprParser; +@synthesize shiftOpAdditiveExprParser; +@synthesize additiveExprParser; +@synthesize plusOrMinusExprParser; +@synthesize plusExprParser; +@synthesize minusExprParser; +@synthesize multiplicativeExprParser; +@synthesize multiplicativeOpUnaryExprParser; +@synthesize unaryExprParser; +@synthesize unaryExpr1Parser; +@synthesize unaryExpr2Parser; +@synthesize unaryExpr3Parser; +@synthesize unaryExpr4Parser; +@synthesize unaryExpr5Parser; +@synthesize unaryExpr6Parser; +@synthesize constructorCallParser; +@synthesize parenArgListOptParenParser; +@synthesize memberExprParser; +@synthesize memberExprExtParser; +@synthesize dotMemberExprParser; +@synthesize bracketMemberExprParser; +@synthesize argListOptParser; +@synthesize argListParser; +@synthesize primaryExprParser; +@synthesize parenExprParenParser; + +@synthesize funcLiteralParser; +@synthesize arrayLiteralParser; +@synthesize objectLiteralParser; + +@synthesize identifierParser; +@synthesize stringParser; +@synthesize numberParser; + +@synthesize ifParser; +@synthesize elseParser; +@synthesize whileParser; +@synthesize forParser; +@synthesize inParser; +@synthesize breakParser; +@synthesize continueParser; +@synthesize withParser; +@synthesize returnParser; +@synthesize varParser; +@synthesize deleteParser; +@synthesize newParser; +@synthesize thisParser; +@synthesize falseParser; +@synthesize trueParser; +@synthesize nullParser; +@synthesize undefinedParser; +@synthesize voidParser; +@synthesize typeofParser; +@synthesize instanceofParser; +@synthesize functionParser; + +@synthesize orParser; +@synthesize andParser; +@synthesize neParser; +@synthesize isNotParser; +@synthesize eqParser; +@synthesize isParser; +@synthesize leParser; +@synthesize geParser; +@synthesize plusPlusParser; +@synthesize minusMinusParser; +@synthesize plusEqParser; +@synthesize minusEqParser; +@synthesize timesEqParser; +@synthesize divEqParser; +@synthesize modEqParser; +@synthesize shiftLeftParser; +@synthesize shiftRightParser; +@synthesize shiftRightExtParser; +@synthesize shiftLeftEqParser; +@synthesize shiftRightEqParser; +@synthesize shiftRightExtEqParser; +@synthesize andEqParser; +@synthesize xorEqParser; +@synthesize orEqParser; + +@synthesize openCurlyParser; +@synthesize closeCurlyParser; +@synthesize openParenParser; +@synthesize closeParenParser; +@synthesize openBracketParser; +@synthesize closeBracketParser; +@synthesize commaParser; +@synthesize dotParser; +@synthesize semiOptParser; +@synthesize semiParser; +@synthesize colonParser; +@synthesize equalsParser; +@synthesize notParser; +@synthesize ltParser; +@synthesize gtParser; +@synthesize ampParser; +@synthesize pipeParser; +@synthesize caretParser; +@synthesize tildeParser; +@synthesize questionParser; +@synthesize plusParser; +@synthesize minusParser; +@synthesize timesParser; +@synthesize divParser; +@synthesize modParser; +@end diff --git a/test/TDJavaScriptParserTest.h b/test/TDJavaScriptParserTest.h new file mode 100644 index 0000000..20a6de6 --- /dev/null +++ b/test/TDJavaScriptParserTest.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "TDJavaScriptParser.h" + +@interface TDJavaScriptParserTest : SenTestCase { + TDJavaScriptParser *jsp; + NSString *s; + PKTokenAssembly *a; + id res; +} + +@end diff --git a/test/TDJavaScriptParserTest.m b/test/TDJavaScriptParserTest.m new file mode 100644 index 0000000..4e6d16c --- /dev/null +++ b/test/TDJavaScriptParserTest.m @@ -0,0 +1,748 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDJavaScriptParserTest.h" + +@implementation TDJavaScriptParserTest + +- (void)setUp { + jsp = [TDJavaScriptParser parser]; +} + + +- (void)tearDown { + +} + + +- (void)testStmtParser { + s = @";"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.stmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[;];^"); + + s = @"{}"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.stmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[{, }]{/}^"); +} + + +- (void)testFunctionParser { + s = @"function"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.functionParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function]function^"); +} + + +- (void)testIdentifierParser { + s = @"foo"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.identifierParser bestMatchFor:a]; + TDEqualObjects([res description], @"[foo]foo^"); +} + + +- (void)testParamListOptParserParser { + s = @"a, b"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.paramListOptParser bestMatchFor:a]; + TDEqualObjects([res description], @"[a, ,, b]a/,/b^"); +} + + +- (void)testCompoundStmtParserParser { + s = @"{}"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.compoundStmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[{, }]{/}^"); +} + + +- (void)testFuncParser { + s = @"function foo(a, b) {}"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.funcParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function, foo, (, a, ,, b, ), {, }]function/foo/(/a/,/b/)/{/}^"); + + s = @"function foo(a, b) { return a + b; }"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.funcParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function, foo, (, a, ,, b, ), {, return, a, +, b, ;, }]function/foo/(/a/,/b/)/{/return/a/+/b/;/}^"); + + s = @"function foo(a, b) { a++; b--; return a + b; }"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.funcParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function, foo, (, a, ,, b, ), {, a, ++, ;, b, --, ;, return, a, +, b, ;, }]function/foo/(/a/,/b/)/{/a/++/;/b/--/;/return/a/+/b/;/}^"); + + s = @"function foo(a, b) { a++; b--; return a + b; }"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.elementParser bestMatchFor:a]; + TDEqualObjects([res description], @"[function, foo, (, a, ,, b, ), {, a, ++, ;, b, --, ;, return, a, +, b, ;, }]function/foo/(/a/,/b/)/{/a/++/;/b/--/;/return/a/+/b/;/}^"); +} + + +- (void)testBitwiseOrExprParser { + s = @"true"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.bitwiseOrExprParser bestMatchFor:a]; + TDEqualObjects([res description], @"[true]true^"); +} + + +- (void)testAndBitwiseOrExprParser { + s = @"&& true"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.andBitwiseOrExprParser bestMatchFor:a]; + TDEqualObjects([res description], @"[&&, true]&&/true^"); +} + + +- (void)testParamListParser { + s = @"baz, bat"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.paramListParser bestMatchFor:a]; + TDEqualObjects([res description], @"[baz, ,, bat]baz/,/bat^"); + + s = @"foo,bar,c_str"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.paramListParser bestMatchFor:a]; + TDEqualObjects([res description], @"[foo, ,, bar, ,, c_str]foo/,/bar/,/c_str^"); + + s = @"_x, __y"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.paramListParser bestMatchFor:a]; + TDEqualObjects([res description], @"[_x, ,, __y]_x/,/__y^"); +} + + +- (void)testCommaIdentifierParser { + s = @", foo"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.commaIdentifierParser bestMatchFor:a]; + TDEqualObjects([res description], @"[,, foo],/foo^"); + + s = @" ,bar"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.commaIdentifierParser bestMatchFor:a]; + TDEqualObjects([res description], @"[,, bar],/bar^"); +} + + +- (void)testBreakStmtParser { + s = @"break;"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.breakStmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[break, ;]break/;^"); +} + + +- (void)testContinueStmtParser { + s = @"continue;"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.continueStmtParser bestMatchFor:a]; + TDEqualObjects([res description], @"[continue, ;]continue/;^"); +} + + +- (void)testAssignmentOpParser { + s = @"="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.assignmentOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[=]=^"); + + s = @"*="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.assignmentOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[*=]*=^"); + + s = @"%="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.assignmentOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[%=]%=^"); + + s = @">>>="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.assignmentOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[>>>=]>>>=^"); +} + + +- (void)testRelationalOpParser { + s = @"<="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.relationalOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[<=]<=^"); + + s = @"instanceof"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.relationalOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[instanceof]instanceof^"); +} + + +- (void)testEqualityOpParser { + s = @"=="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.equalityOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[==]==^"); + + s = @"!=="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.equalityOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[!==]!==^"); + + s = @"==="; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.equalityOpParser bestMatchFor:a]; + TDEqualObjects([res description], @"[===]===^"); +} + + +- (void)testForParenParser { + s = @"for ("; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.forParenParser bestMatchFor:a]; + TDEqualObjects([res description], @"[for, (]for/(^"); + + s = @"for("; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.forParenParser bestMatchFor:a]; + TDEqualObjects([res description], @"[for, (]for/(^"); +} + + +- (void)testExprOptParser { + s = @"true"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.exprOptParser bestMatchFor:a]; + TDEqualObjects([res description], @"[true]true^"); +} + + +- (void)testForBeginParenStmtParser { + s = @"for(1"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.forBeginParser bestMatchFor:a]; + TDEqualObjects([res description], @"[for, (, 1]for/(/1^"); + + s = @";"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.semiParser bestMatchFor:a]; + TDEqualObjects([res description], @"[;];^"); + + s = @"3<2"; + jsp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:jsp.tokenizer]; + res = [jsp.exprOptParser bestMatchFor:a]; + TDEqualObjects([res description], @"[3, <, 2]3/ + +@interface TDJsonParser : PKAlternation { + BOOL shouldAssemble; + PKParser *stringParser; + PKParser *numberParser; + PKParser *nullParser; + PKCollectionParser *booleanParser; + PKCollectionParser *arrayParser; + PKCollectionParser *objectParser; + PKCollectionParser *valueParser; + PKCollectionParser *commaValueParser; + PKCollectionParser *propertyParser; + PKCollectionParser *commaPropertyParser; + + PKToken *curly; + PKToken *bracket; +} + +- (id)initWithIntentToAssemble:(BOOL)shouldAssemble; + +- (id)parse:(NSString *)s; + +@property (nonatomic, retain) PKParser *stringParser; +@property (nonatomic, retain) PKParser *numberParser; +@property (nonatomic, retain) PKParser *nullParser; +@property (nonatomic, retain) PKCollectionParser *booleanParser; +@property (nonatomic, retain) PKCollectionParser *arrayParser; +@property (nonatomic, retain) PKCollectionParser *objectParser; +@property (nonatomic, retain) PKCollectionParser *valueParser; +@property (nonatomic, retain) PKCollectionParser *commaValueParser; +@property (nonatomic, retain) PKCollectionParser *propertyParser; +@property (nonatomic, retain) PKCollectionParser *commaPropertyParser; +@end \ No newline at end of file diff --git a/test/TDJsonParser.m b/test/TDJsonParser.m new file mode 100644 index 0000000..14f12ae --- /dev/null +++ b/test/TDJsonParser.m @@ -0,0 +1,322 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDJsonParser.h" +#import "ParseKit.h" +#import "NSString+ParseKitAdditions.h" + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface PKCollectionParser () +@property (nonatomic, readwrite, retain) NSMutableArray *subparsers; +@end + +@interface TDJsonParser () +@property (nonatomic, retain) PKToken *curly; +@property (nonatomic, retain) PKToken *bracket; +@end + +@implementation TDJsonParser + +- (id)init { + return [self initWithIntentToAssemble:YES]; +} + + +- (id)initWithIntentToAssemble:(BOOL)yn { + if (self = [super init]) { + shouldAssemble = yn; + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.0]; + self.bracket = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"[" floatValue:0.0]; + + self.tokenizer = [PKTokenizer tokenizer]; + [self.tokenizer setTokenizerState:self.tokenizer.symbolState from: '/' to: '/']; // JSON doesn't have slash slash or slash star comments + [self.tokenizer setTokenizerState:self.tokenizer.symbolState from: '\'' to: '\'']; // JSON does not have single quoted strings + + [self add:self.objectParser]; + [self add:self.arrayParser]; + } + return self; +} + + +- (void)dealloc { + // yikes. this is necessary to prevent a very nasty retain cycle leak. + // to be safe, release the subparsers of all collection parsers (as they may have retain cycles in complex grammars like this one) + // technically i only need to release the valueParser.subparers in this case, but better to be paranoid than to leak. + booleanParser.subparsers = nil; + arrayParser.subparsers = nil; + objectParser.subparsers = nil; + valueParser.subparsers = nil; + commaValueParser.subparsers = nil; + propertyParser.subparsers = nil; + commaPropertyParser.subparsers = nil; + + self.tokenizer = nil; + self.stringParser = nil; + self.numberParser = nil; + self.nullParser = nil; + self.booleanParser = nil; + self.arrayParser = nil; + self.objectParser = nil; + self.valueParser = nil; + self.propertyParser = nil; + self.commaPropertyParser = nil; + self.commaValueParser = nil; + self.curly = nil; + self.bracket = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + self.tokenizer.string = s; + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:self.tokenizer]; + + PKAssembly *result = [self completeMatchFor:a]; + return [result pop]; +} + + +- (PKParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKQuotedString quotedString]; + if (shouldAssemble) { + [stringParser setAssembler:self selector:@selector(didMatchString:)]; + } + } + return stringParser; +} + + +- (PKParser *)numberParser { + if (!numberParser) { + self.numberParser = [PKNumber number]; + if (shouldAssemble) { + [numberParser setAssembler:self selector:@selector(didMatchNumber:)]; + } + } + return numberParser; +} + + +- (PKParser *)nullParser { + if (!nullParser) { + self.nullParser = [[PKLiteral literalWithString:@"null"] discard]; + if (shouldAssemble) { + [nullParser setAssembler:self selector:@selector(didMatchNull:)]; + } + } + return nullParser; +} + + +- (PKCollectionParser *)booleanParser { + if (!booleanParser) { + self.booleanParser = [PKAlternation alternation]; + [booleanParser add:[PKLiteral literalWithString:@"true"]]; + [booleanParser add:[PKLiteral literalWithString:@"false"]]; + if (shouldAssemble) { + [booleanParser setAssembler:self selector:@selector(didMatchBoolean:)]; + } + } + return booleanParser; +} + + +- (PKCollectionParser *)arrayParser { + if (!arrayParser) { + + // array = '[' content ']' + // content = Empty | actualArray + // actualArray = value commaValue* + + PKTrack *actualArray = [PKTrack sequence]; + [actualArray add:self.valueParser]; + [actualArray add:[PKRepetition repetitionWithSubparser:self.commaValueParser]]; + + PKAlternation *content = [PKAlternation alternation]; + [content add:[PKEmpty empty]]; + [content add:actualArray]; + + self.arrayParser = [PKSequence sequence]; + [arrayParser add:[PKSymbol symbolWithString:@"["]]; // serves as fence + [arrayParser add:content]; + [arrayParser add:[[PKSymbol symbolWithString:@"]"] discard]]; + + if (shouldAssemble) { + [arrayParser setAssembler:self selector:@selector(didMatchArray:)]; + } + } + return arrayParser; +} + + +- (PKCollectionParser *)objectParser { + if (!objectParser) { + + // object = '{' content '}' + // content = Empty | actualObject + // actualObject = property commaProperty* + // property = QuotedString ':' value + // commaProperty = ',' property + + PKTrack *actualObject = [PKTrack sequence]; + [actualObject add:self.propertyParser]; + [actualObject add:[PKRepetition repetitionWithSubparser:self.commaPropertyParser]]; + + PKAlternation *content = [PKAlternation alternation]; + [content add:[PKEmpty empty]]; + [content add:actualObject]; + + self.objectParser = [PKSequence sequence]; + [objectParser add:[PKSymbol symbolWithString:@"{"]]; // serves as fence + [objectParser add:content]; + [objectParser add:[[PKSymbol symbolWithString:@"}"] discard]]; + + if (shouldAssemble) { + [objectParser setAssembler:self selector:@selector(didMatchObject:)]; + } + } + return objectParser; +} + + +- (PKCollectionParser *)valueParser { + if (!valueParser) { + self.valueParser = [PKAlternation alternation]; + [valueParser add:self.stringParser]; + [valueParser add:self.numberParser]; + [valueParser add:self.nullParser]; + [valueParser add:self.booleanParser]; + [valueParser add:self.arrayParser]; + [valueParser add:self.objectParser]; + } + return valueParser; +} + + +- (PKCollectionParser *)commaValueParser { + if (!commaValueParser) { + self.commaValueParser = [PKTrack sequence]; + [commaValueParser add:[[PKSymbol symbolWithString:@","] discard]]; + [commaValueParser add:self.valueParser]; + } + return commaValueParser; +} + + +- (PKCollectionParser *)propertyParser { + if (!propertyParser) { + self.propertyParser = [PKSequence sequence]; + [propertyParser add:[PKQuotedString quotedString]]; + [propertyParser add:[[PKSymbol symbolWithString:@":"] discard]]; + [propertyParser add:self.valueParser]; + if (shouldAssemble) { + [propertyParser setAssembler:self selector:@selector(didMatchProperty:)]; + } + } + return propertyParser; +} + + +- (PKCollectionParser *)commaPropertyParser { + if (!commaPropertyParser) { + self.commaPropertyParser = [PKTrack sequence]; + [commaPropertyParser add:[[PKSymbol symbolWithString:@","] discard]]; + [commaPropertyParser add:self.propertyParser]; + } + return commaPropertyParser; +} + + +- (void)didMatchNull:(PKAssembly *)a { + [a push:[NSNull null]]; +} + + +- (void)didMatchNumber:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchString:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[tok.stringValue stringByTrimmingQuotes]]; +} + + +- (void)didMatchBoolean:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithBool:[tok.stringValue isEqualToString:@"true"] ? YES : NO]]; +} + + +- (void)didMatchArray:(PKAssembly *)a { + NSArray *elements = [a objectsAbove:self.bracket]; + NSMutableArray *array = [NSMutableArray arrayWithCapacity:[elements count]]; + + for (id element in [elements reverseObjectEnumerator]) { + if (element) { + [array addObject:element]; + } + } + [a pop]; // pop the [ + [a push:array]; +} + + +- (void)didMatchObject:(PKAssembly *)a { + NSArray *elements = [a objectsAbove:self.curly]; + NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:[elements count] / 2.]; + + NSInteger i = 0; + for ( ; i < [elements count] - 1; i++) { + id value = [elements objectAtIndex:i++]; + NSString *key = [elements objectAtIndex:i]; + if (key && value) { + [d setObject:value forKey:key]; + } + } + + [a pop]; // pop the { + [a push:d]; +} + + +- (void)didMatchProperty:(PKAssembly *)a { + id value = [a pop]; + PKToken *tok = [a pop]; + NSString *key = [tok.stringValue stringByTrimmingQuotes]; + + [a push:key]; + [a push:value]; +} + +@synthesize stringParser; +@synthesize numberParser; +@synthesize nullParser; +@synthesize booleanParser; +@synthesize arrayParser; +@synthesize objectParser; +@synthesize valueParser; +@synthesize commaValueParser; +@synthesize propertyParser; +@synthesize commaPropertyParser; +@synthesize curly; +@synthesize bracket; +@end diff --git a/test/TDJsonParserTest.h b/test/TDJsonParserTest.h new file mode 100644 index 0000000..229fc08 --- /dev/null +++ b/test/TDJsonParserTest.h @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@class TDJsonParser; + +@interface TDJsonParserTest : SenTestCase { + TDJsonParser *p; + NSString *s; + PKAssembly *a; + PKAssembly *result; +} + +@end diff --git a/test/TDJsonParserTest.m b/test/TDJsonParserTest.m new file mode 100644 index 0000000..49f1568 --- /dev/null +++ b/test/TDJsonParserTest.m @@ -0,0 +1,543 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDJsonParserTest.h" +#import "TDJsonParser.h" +#import "TDFastJsonParser.h" + +@implementation TDJsonParserTest + +- (void)setUp { + p = [TDJsonParser parser]; +} + + +- (void)testForAppleBossResultTokenization { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKTokenizer *t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + while (eof != (tok = [t nextToken])) { + //NSLog(@"tok: %@", tok); + } +} + + +- (void)testForAppleBossResult { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + @try { + result = [p parse:s]; + } + @catch (NSException *e) { + //NSLog(@"\n\n\nexception:\n\n %@", [e reason]); + } + + //NSLog(@"result %@", result); +} + + +- (void)testEmptyString { + s = @""; + a = [PKTokenAssembly assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testNum { + s = @"456"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p numberParser] bestMatchFor:a]; + TDNotNil(result); + + TDEqualObjects(@"[456]456^", [result description]); + id obj = [result pop]; + TDNotNil(obj); + TDEqualObjects([NSNumber numberWithFloat:456], obj); + + + s = @"-3.47"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p numberParser] bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[-3.47]-3.47^", [result description]); + obj = [result pop]; + TDNotNil(obj); + TDEqualObjects([NSNumber numberWithFloat:-3.47], obj); +} + + +- (void)testString { + s = @"'foobar'"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p stringParser] bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foobar]'foobar'^", [result description]); + id obj = [result pop]; + TDNotNil(obj); + TDEqualObjects(@"foobar", obj); + + s = @"\"baz boo boo\""; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p stringParser] bestMatchFor:a]; + TDNotNil(result); + + TDEqualObjects(@"[baz boo boo]\"baz boo boo\"^", [result description]); + obj = [result pop]; + TDNotNil(obj); + TDEqualObjects(@"baz boo boo", obj); +} + + +- (void)testBoolean { + s = @"true"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p booleanParser] bestMatchFor:a]; + TDNotNil(result); + + TDEqualObjects(@"[1]true^", [result description]); + id obj = [result pop]; + TDNotNil(obj); + TDEqualObjects([NSNumber numberWithBool:YES], obj); + + s = @"false"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p booleanParser] bestMatchFor:a]; + TDNotNil(result); + + TDEqualObjects(@"[0]false^", [result description]); + obj = [result pop]; + TDNotNil(obj); + TDEqualObjects([NSNumber numberWithBool:NO], obj); +} + + +- (void)testArray { + s = @"[1, 2, 3]"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p arrayParser] bestMatchFor:a]; + + NSLog(@"result: %@", result); + TDNotNil(result); + id obj = [result pop]; + TDEquals((int)3, (int)[obj count]); + TDEqualObjects([NSNumber numberWithInteger:1], [obj objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInteger:2], [obj objectAtIndex:1]); + TDEqualObjects([NSNumber numberWithInteger:3], [obj objectAtIndex:2]); + TDEqualObjects(@"[][/1/,/2/,/3/]^", [result description]); + + s = @"[true, 'garlic jazz!', .888]"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p arrayParser] bestMatchFor:a]; + TDNotNil(result); + + //TDEqualObjects(@"[true, 'garlic jazz!', .888]true/'garlic jazz!'/.888^", [result description]); + obj = [result pop]; + TDEqualObjects([NSNumber numberWithBool:YES], [obj objectAtIndex:0]); + TDEqualObjects(@"garlic jazz!", [obj objectAtIndex:1]); + TDEqualObjects([NSNumber numberWithFloat:.888], [obj objectAtIndex:2]); + + s = @"[1, [2, [3, 4]]]"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p arrayParser] bestMatchFor:a]; + TDNotNil(result); + //NSLog(@"result: %@", [a stack]); + TDEqualObjects([NSNumber numberWithInteger:1], [obj objectAtIndex:0]); +} + + +- (void)testObject { + s = @"{'key': 'value'}"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p objectParser] bestMatchFor:a]; + TDNotNil(result); + + id obj = [result pop]; + TDEqualObjects([obj objectForKey:@"key"], @"value"); + + s = @"{'foo': false, 'bar': true, \"baz\": -9.457}"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p objectParser] bestMatchFor:a]; + TDNotNil(result); + + obj = [result pop]; + TDEqualObjects([obj objectForKey:@"foo"], [NSNumber numberWithBool:NO]); + TDEqualObjects([obj objectForKey:@"bar"], [NSNumber numberWithBool:YES]); + TDEqualObjects([obj objectForKey:@"baz"], [NSNumber numberWithFloat:-9.457]); + + s = @"{'baz': {'foo': [1,2]}}"; + a = [PKTokenAssembly assemblyWithString:s]; + result = [[p objectParser] bestMatchFor:a]; + TDNotNil(result); + + obj = [result pop]; + NSDictionary *dict = [obj objectForKey:@"baz"]; + TDTrue([dict isKindOfClass:[NSDictionary class]]); + NSArray *arr = [dict objectForKey:@"foo"]; + TDTrue([arr isKindOfClass:[NSArray class]]); + TDEqualObjects([NSNumber numberWithInteger:1], [arr objectAtIndex:0]); + + // TDEqualObjects(@"['baz', 'foo', 1, 2]'baz'/'foo'/1/2^", [result description]); +} + + +- (void)testCrunchBaseJsonParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDJsonParser *parser = [[[TDJsonParser alloc] init] autorelease]; + [parser parse:s]; +// id res = [parser parse:s]; + //NSLog(@"res %@", res); +} + + +- (void)testCrunchBaseJsonParserTokenization { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKTokenizer *t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + while (eof != (tok = [t nextToken])) { + //NSLog(@"tok: %@", tok); + } +} + + +- (void)testCrunchBaseJsonTokenParser { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"yahoo" ofType:@"json"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + TDFastJsonParser *parser = [[[TDFastJsonParser alloc] init] autorelease]; + [parser parse:s]; + // id res = [parser parse:s]; + //NSLog(@"res %@", res); +} + + +- (void)testYahoo1 { + s = + @"{" + @"\"name\": \"Yahoo!\"," + @"\"permalink\": \"yahoo\"," + @"\"homepage_url\": \"http://www.yahoo.com\"," + @"\"blog_url\": \"http://yodel.yahoo.com/\"," + @"\"blog_feed_url\": \"http://ycorpblog.com/feed/\"," + @"\"category_code\": \"web\"," + @"\"number_of_employees\": 13600," + @"\"founded_year\": 1994," + @"\"founded_month\": null," + @"\"founded_day\": null," + @"\"deadpooled_year\": null," + @"\"deadpooled_month\": null," + @"\"deadpooled_day\": null," + @"\"deadpooled_url\": null," + @"\"tag_list\": \"search, portal, webmail, photos\"," + @"\"email_address\": \"\"," + @"\"phone_number\": \"(408) 349-3300\"" + @"}"; + result = [p parse:s]; + //NSLog(@"result %@", result); + TDNotNil(result); + id d = result; + TDNotNil(d); + TDTrue([d isKindOfClass:[NSDictionary class]]); + TDEqualObjects([d objectForKey:@"name"], @"Yahoo!"); + TDEqualObjects([d objectForKey:@"permalink"], @"yahoo"); + TDEqualObjects([d objectForKey:@"homepage_url"], @"http://www.yahoo.com"); + TDEqualObjects([d objectForKey:@"blog_url"], @"http://yodel.yahoo.com/"); + TDEqualObjects([d objectForKey:@"blog_feed_url"], @"http://ycorpblog.com/feed/"); + TDEqualObjects([d objectForKey:@"category_code"], @"web"); + TDEqualObjects([d objectForKey:@"number_of_employees"], [NSNumber numberWithInteger:13600]); + TDEqualObjects([d objectForKey:@"founded_year"], [NSNumber numberWithInteger:1994]); + TDEqualObjects([d objectForKey:@"founded_month"], [NSNull null]); + TDEqualObjects([d objectForKey:@"founded_day"], [NSNull null]); + TDEqualObjects([d objectForKey:@"deadpooled_year"], [NSNull null]); + TDEqualObjects([d objectForKey:@"deadpooled_month"], [NSNull null]); + TDEqualObjects([d objectForKey:@"deadpooled_day"], [NSNull null]); + TDEqualObjects([d objectForKey:@"deadpooled_url"], [NSNull null]); + TDEqualObjects([d objectForKey:@"tag_list"], @"search, portal, webmail, photos"); + TDEqualObjects([d objectForKey:@"email_address"], @""); + TDEqualObjects([d objectForKey:@"phone_number"], @"(408) 349-3300"); +} + + +- (void)testYahoo2 { + s = @"{\"image\":" + @" {\"available_sizes\":" + @" [[[150, 37]," + @" \"assets/images/resized/0001/0836/10836v1-max-250x150.png\"]," + @" [[200, 50]," + @" \"assets/images/resized/0001/0836/10836v1-max-250x250.png\"]," + @" [[200, 50]," + @" \"assets/images/resized/0001/0836/10836v1-max-450x450.png\"]]," + @" \"attribution\": null}" + @"}"; + result = [p parse:s]; + //NSLog(@"result %@", result); + + TDNotNil(result); + + id d = result; + TDNotNil(d); + TDTrue([d isKindOfClass:[NSDictionary class]]); + + id image = [d objectForKey:@"image"]; + TDNotNil(image); + TDTrue([image isKindOfClass:[NSDictionary class]]); + + NSArray *sizes = [image objectForKey:@"available_sizes"]; + TDNotNil(sizes); + TDTrue([sizes isKindOfClass:[NSArray class]]); + + TDEquals(3, (int)[sizes count]); + + NSArray *first = [sizes objectAtIndex:0]; + TDNotNil(first); + TDTrue([first isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[first count]); + + NSArray *firstKey = [first objectAtIndex:0]; + TDNotNil(firstKey); + TDTrue([firstKey isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[firstKey count]); + TDEqualObjects([NSNumber numberWithInteger:150], [firstKey objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInteger:37], [firstKey objectAtIndex:1]); + + NSArray *second = [sizes objectAtIndex:1]; + TDNotNil(second); + TDTrue([second isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[second count]); + + NSArray *secondKey = [second objectAtIndex:0]; + TDNotNil(secondKey); + TDTrue([secondKey isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[secondKey count]); + TDEqualObjects([NSNumber numberWithInteger:200], [secondKey objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInteger:50], [secondKey objectAtIndex:1]); + + NSArray *third = [sizes objectAtIndex:2]; + TDNotNil(third); + TDTrue([third isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[third count]); + + NSArray *thirdKey = [third objectAtIndex:0]; + TDNotNil(thirdKey); + TDTrue([thirdKey isKindOfClass:[NSArray class]]); + TDEquals(2, (int)[thirdKey count]); + TDEqualObjects([NSNumber numberWithInteger:200], [thirdKey objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInteger:50], [thirdKey objectAtIndex:1]); + + +// TDEqualObjects([d objectForKey:@"name"], @"Yahoo!"); +} + + +- (void)testYahoo3 { + s = + @"{\"products\":" + @"[" + @"{\"name\": \"Yahoo.com\", \"permalink\": \"yahoo-com\"}," + @"{\"name\": \"Yahoo! Mail\", \"permalink\": \"yahoo-mail\"}," + @"{\"name\": \"Yahoo! Search\", \"permalink\": \"yahoo-search\"}," + @"{\"name\": \"Yahoo! Directory\", \"permalink\": \"yahoo-directory\"}," + @"{\"name\": \"Yahoo! Finance\", \"permalink\": \"yahoo-finance\"}," + @"{\"name\": \"My Yahoo\", \"permalink\": \"my-yahoo\"}," + @"{\"name\": \"Yahoo! News\", \"permalink\": \"yahoo-news\"}," + @"{\"name\": \"Yahoo! Groups\", \"permalink\": \"yahoo-groups\"}," + @"{\"name\": \"Yahoo! Messenger\", \"permalink\": \"yahoo-messenger\"}," + @"{\"name\": \"Yahoo! Games\", \"permalink\": \"yahoo-games\"}," + @"{\"name\": \"Yahoo! People Search\", \"permalink\": \"yahoo-people-search\"}," + @"{\"name\": \"Yahoo! Movies\", \"permalink\": \"yahoo-movies\"}," + @"{\"name\": \"Yahoo! Weather\", \"permalink\": \"yahoo-weather\"}," + @"{\"name\": \"Yahoo! Video\", \"permalink\": \"yahoo-video\"}," + @"{\"name\": \"Yahoo! Music\", \"permalink\": \"yahoo-music\"}," + @"{\"name\": \"Yahoo! Sports\", \"permalink\": \"yahoo-sports\"}," + @"{\"name\": \"Yahoo! Maps\", \"permalink\": \"yahoo-maps\"}," + @"{\"name\": \"Yahoo! Auctions\", \"permalink\": \"yahoo-auctions\"}," + @"{\"name\": \"Yahoo! Widgets\", \"permalink\": \"yahoo-widgets\"}," + @"{\"name\": \"Yahoo! Shopping\", \"permalink\": \"yahoo-shopping\"}," + @"{\"name\": \"Yahoo! Real Estate\", \"permalink\": \"yahoo-real-estate\"}," + @"{\"name\": \"Yahoo! Travel\", \"permalink\": \"yahoo-travel\"}," + @"{\"name\": \"Yahoo! Classifieds\", \"permalink\": \"yahoo-classifieds\"}," + @"{\"name\": \"Yahoo! Answers\", \"permalink\": \"yahoo-answers\"}," + @"{\"name\": \"Yahoo! Mobile\", \"permalink\": \"yahoo-mobile\"}," + @"{\"name\": \"Yahoo! Buzz\", \"permalink\": \"yahoo-buzz\"}," + @"{\"name\": \"Yahoo! Open Search Platform\", \"permalink\": \"yahoo-open-search-platform\"}," + @"{\"name\": \"Fire Eagle\", \"permalink\": \"fireeagle\"}," + @"{\"name\": \"Shine\", \"permalink\": \"shine\"}," + @"{\"name\": \"Yahoo! Shortcuts\", \"permalink\": \"yahoo-shortcuts\"}" + @"]" + @"}"; + result = [p parse:s]; + //NSLog(@"result %@", result); + + TDNotNil(result); + + id d = result; + TDNotNil(d); + TDTrue([d isKindOfClass:[NSDictionary class]]); + + NSArray *products = [d objectForKey:@"products"]; + TDNotNil(products); + TDTrue([products isKindOfClass:[NSArray class]]); +} + + +- (void)testYahoo4 { + s = @"[" + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," + @"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1" + @"]"; + + p = [[[TDFastJsonParser alloc] init] autorelease]; + result = [p parse:s]; + //NSLog(@"result %@", result); + + TDNotNil(result); + + id d = result; + TDNotNil(d); + TDTrue([d isKindOfClass:[NSArray class]]); + +// NSArray *products = [d objectForKey:@"products"]; +// TDNotNil(products); +// TDTrue([products isKindOfClass:[NSArray class]]); +} +@end diff --git a/test/TDLetterTest.h b/test/TDLetterTest.h new file mode 100644 index 0000000..052741d --- /dev/null +++ b/test/TDLetterTest.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + + +@interface TDLetterTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + PKChar *p; + PKAssembly *result; +} + +@end diff --git a/test/TDLetterTest.m b/test/TDLetterTest.m new file mode 100644 index 0000000..41dd111 --- /dev/null +++ b/test/TDLetterTest.m @@ -0,0 +1,65 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDLetterTest.h" + +@interface PKAssembly () +- (BOOL)hasMore; +@end + +@implementation TDLetterTest + +- (void)test123 { + s = @"123"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^123", [a description]); + p = [PKLetter letter]; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDNil(result); + TDTrue([a hasMore]); +} + + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKLetter letter]; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a]a^bc", [result description]); + TDTrue([result hasMore]); +} + + +- (void)testRepetition { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKLetter letter]; + PKParser *r = [PKRepetition repetitionWithSubparser:p]; + + result = [r bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a, b, c]abc^", [result description]); + TDFalse([result hasMore]); +} + +@end diff --git a/test/TDLiteralTest.h b/test/TDLiteralTest.h new file mode 100644 index 0000000..c1dae34 --- /dev/null +++ b/test/TDLiteralTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDLiteralTest : SenTestCase { + PKParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/TDLiteralTest.m b/test/TDLiteralTest.m new file mode 100644 index 0000000..7804465 --- /dev/null +++ b/test/TDLiteralTest.m @@ -0,0 +1,97 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDLiteralTest.h" + +@implementation TDLiteralTest + +- (void)tearDown { + [a release]; +} + +- (void)testTrueCompleteMatchForLiteral123 { + s = @"123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + NSLog(@"a: %@", a); + + p = [PKNumber number]; + PKAssembly *result = [p completeMatchFor:a]; + + // -[PKParser completeMatchFor:] + // -[PKParser bestMatchFor:] + // -[PKParser matchAndAssemble:] + // -[PKTerminal allMatchesFor:] + // -[PKTerminal matchOneAssembly:] + // -[PKLiteral qualifies:] + // -[PKParser best:] + + NSLog(@"result: %@", result); + TDNotNil(result); + TDEqualObjects(@"[123]123^", [result description]); +} + + +- (void)testFalseCompleteMatchForLiteral123 { + s = @"1234"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKLiteral literalWithString:@"123"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); + TDEqualObjects(@"[]^1234", [a description]); +} + + +- (void)testTrueCompleteMatchForLiteralFoo { + s = @"Foo"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKLiteral literalWithString:@"Foo"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[Foo]Foo^", [result description]); +} + + +- (void)testFalseCompleteMatchForLiteralFoo { + s = @"Foo"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKLiteral literalWithString:@"foo"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testFalseCompleteMatchForCaseInsensitiveLiteralFoo { + s = @"Fool"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKCaseInsensitiveLiteral literalWithString:@"Foo"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testTrueCompleteMatchForCaseInsensitiveLiteralFoo { + s = @"Foo"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [PKCaseInsensitiveLiteral literalWithString:@"foo"]; + PKAssembly *result = [p completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[Foo]Foo^", [result description]); +} + +@end diff --git a/test/TDLowercaseWordTest.h b/test/TDLowercaseWordTest.h new file mode 100644 index 0000000..e150738 --- /dev/null +++ b/test/TDLowercaseWordTest.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDLowercaseWordTest : SenTestCase { + +} +@end + diff --git a/test/TDLowercaseWordTest.m b/test/TDLowercaseWordTest.m new file mode 100644 index 0000000..e586a45 --- /dev/null +++ b/test/TDLowercaseWordTest.m @@ -0,0 +1,63 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDLowercaseWordTest.h" + +@implementation TDLowercaseWordTest + +- (void)testFoobar { + NSString *s = @"Foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKLowercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)testfoobar { + NSString *s = @"foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKLowercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foobar]foobar^", [result description]); +} + + +- (void)test123 { + NSString *s = @"123"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKLowercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)testPercentFoobar { + NSString *s = @"%Foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKLowercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + +@end diff --git a/test/TDMiniCSSAssembler.h b/test/TDMiniCSSAssembler.h new file mode 100644 index 0000000..34864f0 --- /dev/null +++ b/test/TDMiniCSSAssembler.h @@ -0,0 +1,27 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKToken; + +@interface TDMiniCSSAssembler : NSObject { + NSMutableDictionary *attributes; + PKToken *paren; + PKToken *curly; +} +@property (nonatomic, retain) NSMutableDictionary *attributes; +@property (nonatomic, retain) PKToken *paren; +@property (nonatomic, retain) PKToken *curly; +@end diff --git a/test/TDMiniCSSAssembler.m b/test/TDMiniCSSAssembler.m new file mode 100644 index 0000000..dca1e1c --- /dev/null +++ b/test/TDMiniCSSAssembler.m @@ -0,0 +1,190 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDMiniCSSAssembler.h" +#import "NSString+ParseKitAdditions.h" +#import + +@interface TDMiniCSSAssembler () +- (void)gatherPropertiesIn:(id)props; +@end + +@implementation TDMiniCSSAssembler + +- (id)init { + if (self = [super init]) { + self.attributes = [NSMutableDictionary dictionary]; + self.paren = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"(" floatValue:0.0]; + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.0]; + } + return self; +} + + +- (void)dealloc { + self.attributes = nil; + self.paren = nil; + self.curly = nil; + [super dealloc]; +} + + +#pragma mark - +#pragma mark Assembler Callbacks + +// @start = ruleset*; +// ruleset = selector '{' decls >'}'; +// selector = LowercaseWord; // forcing selectors to be lowercase words for use in a future syntax-highlight framework where i want that +// decls = Empty | actualDecls; +// actualDecls = decl decl*; +// decl = property >':' expr >';'?; +// property = 'color' | 'background-color' | 'font-family' | 'font-size'; +// expr = pixelValue | rgb | string | constants; +// pixelValue = Number >'px'; +// rgb = >'rgb' '(' Number >',' Number >',' Number >')'; +// string = QuotedString; +// constants = 'bold' | 'normal' | 'italic'; + +- (void)didMatchProperty:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:tok.stringValue]; +} + + +- (void)didMatchString:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[tok.stringValue stringByTrimmingQuotes]]; +} + + +- (void)didMatchConstant:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:tok.stringValue]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchPixelValue:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchRgb:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:paren]; + [a pop]; // discard '(' + CGFloat blue = [(PKToken *)[objs objectAtIndex:0] floatValue]/255.0; + CGFloat green = [(PKToken *)[objs objectAtIndex:1] floatValue]/255.0; + CGFloat red = [(PKToken *)[objs objectAtIndex:2] floatValue]/255.0; + [a push:[NSColor colorWithDeviceRed:red green:green blue:blue alpha:1.0]]; +} + + +- (void)didMatchActualDecls:(PKAssembly *)a { + id d = [NSMutableDictionary dictionary]; + NSArray *objs = [a objectsAbove:curly]; + [a pop]; // discard curly + + NSInteger i = 0; + NSInteger count = [objs count]; + for ( ; i < count - 1; i++) { + id propVal = [objs objectAtIndex:i]; + id propName = [objs objectAtIndex:++i]; + [d setObject:propVal forKey:propName]; + } + + [a push:d]; +} + + +- (void)didMatchRuleset:(PKAssembly *)a { + id props = [a pop]; + [self gatherPropertiesIn:props]; + + for (PKToken *selectorTok in [a objectsAbove:nil]) { + NSString *selector = selectorTok.stringValue; + [attributes setObject:props forKey:selector]; + } +} + + +- (void)gatherPropertiesIn:(id)props { + NSColor *color = [props objectForKey:@"color"]; + if (!color) { + color = [NSColor blackColor]; + } + [props setObject:color forKey:NSForegroundColorAttributeName]; + [props removeObjectForKey:@"color"]; + + color = [props objectForKey:@"background-color"]; + if (!color) { + color = [NSColor whiteColor]; + } + [props setObject:color forKey:NSBackgroundColorAttributeName]; + [props removeObjectForKey:@"background-color"]; + + NSString *fontFamily = [props objectForKey:@"font-family"]; + if (![fontFamily length]) { + fontFamily = @"Monaco"; + } + + CGFloat fontSize = [[props objectForKey:@"font-size"] doubleValue]; + if (fontSize < 9.0) { + fontSize = 9.0; + } + + NSFont *font = [NSFont fontWithName:fontFamily size:fontSize]; + [props setObject:font forKey:NSFontAttributeName]; + [props removeObjectForKey:@"font-family"]; + [props removeObjectForKey:@"font-size"]; +} + +@synthesize attributes; +@synthesize paren; +@synthesize curly; +@end + + +//- (NSUInteger)hexValueFor:(NSString *)inStr { +// NSUInteger i = [[inStr substringWithRange:NSMakeRange(0, 1)] integerValue]; +// i = i *= 16; +// i += [[inStr substringWithRange:NSMakeRange(1, 1)] integerValue]; +// return i; +//} +// +//- (void)didMatchHexcolor:(PKAssembly *)a { +// PKToken *tok = [a pop]; +// NSString *s = tok.stringValue; +// NSColor *color = nil; +// +// if (6 == [s length]) { +// NSString *redStr = [s substringWithRange:NSMakeRange(0, 2)]; +// NSString *greenStr = [s substringWithRange:NSMakeRange(2, 2)]; +// NSString *blueStr = [s substringWithRange:NSMakeRange(4, 2)]; +// +// NSUInteger red = [self hexValueFor:redStr]; +// NSUInteger green = [self hexValueFor:greenStr]; +// NSUInteger blue = [self hexValueFor:blueStr]; +// +// color = [NSColor colorWithDeviceRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1.0]; +// } else { +// color = [NSColor magentaColor]; // signals incorrect value in stylesheet +// } +// [a push:color]; +//} diff --git a/test/TDMiniCSSAssemblerTest.h b/test/TDMiniCSSAssemblerTest.h new file mode 100644 index 0000000..92034dd --- /dev/null +++ b/test/TDMiniCSSAssemblerTest.h @@ -0,0 +1,29 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" +#import "TDMiniCSSAssembler.h" + +@interface TDMiniCSSAssemblerTest : SenTestCase { + NSString *path; + NSString *grammarString; + NSString *s; + TDMiniCSSAssembler *ass; + PKParserFactory *factory; + PKParser *lp; + PKAssembly *a; +} + +@end diff --git a/test/TDMiniCSSAssemblerTest.m b/test/TDMiniCSSAssemblerTest.m new file mode 100644 index 0000000..e7ff4d5 --- /dev/null +++ b/test/TDMiniCSSAssemblerTest.m @@ -0,0 +1,239 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDMiniCSSAssemblerTest.h" + +@implementation TDMiniCSSAssemblerTest + +- (void)setUp { + path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + ass = [[TDMiniCSSAssembler alloc] init]; + factory = [PKParserFactory factory]; + lp = [factory parserFromGrammar:grammarString assembler:ass]; +} + + +- (void)tearDown { + [ass release]; +} + + +- (void)testColor { + TDNotNil(lp); + + s = @"bar { color:rgb(10, 200, 30); }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]bar/{/color/:/rgb/(/10/,/200/,/30/)/;/}^", [a description]); + TDNotNil(ass.attributes); + id props = [ass.attributes objectForKey:@"bar"]; + TDNotNil(props); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); +} + + +- (void)testMultiSelectorColor { + TDNotNil(lp); + + s = @"foo, bar { color:rgb(10, 200, 30); }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]foo/,/bar/{/color/:/rgb/(/10/,/200/,/30/)/;/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"bar"]; + TDNotNil(props); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); + + props = [ass.attributes objectForKey:@"foo"]; + TDNotNil(props); + + color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); +} + + +- (void)testBackgroundColor { + TDNotNil(lp); + + s = @"foo { background-color:rgb(255.0, 0.0, 255.0) }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]foo/{/background-color/:/rgb/(/255.0/,/0.0/,/255.0/)/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"foo"]; + TDNotNil(props); + + NSColor *color = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(255.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(0.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(255.0/255.0), 0.001, @""); +} + + +- (void)testFontSize { + TDNotNil(lp); + + s = @"decl { font-size:12px }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]decl/{/font-size/:/12/px/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"decl"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEquals((CGFloat)[font pointSize], (CGFloat)12.0); + TDEqualObjects([font familyName], @"Monaco"); +} + + +- (void)testSmallFontSize { + TDNotNil(lp); + + s = @"decl { font-size:8px }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]decl/{/font-size/:/8/px/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"decl"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEquals((CGFloat)[font pointSize], (CGFloat)9.0); + TDEqualObjects([font familyName], @"Monaco"); +} + + +- (void)testFont { + TDNotNil(lp); + + s = @"expr { font-size:16px; font-family:'Helvetica' }"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]expr/{/font-size/:/16/px/;/font-family/:/'Helvetica'/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"expr"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Helvetica"); + TDEquals((CGFloat)[font pointSize], (CGFloat)16.0); +} + + +- (void)testAll { + TDNotNil(lp); + + s = @"expr { font-size:9.0px; font-family:'Courier'; background-color:rgb(255.0, 0.0, 255.0) ; color:rgb(10, 200, 30);}"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]expr/{/font-size/:/9.0/px/;/font-family/:/'Courier'/;/background-color/:/rgb/(/255.0/,/0.0/,/255.0/)/;/color/:/rgb/(/10/,/200/,/30/)/;/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"expr"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Courier"); + TDEquals((CGFloat)[font pointSize], (CGFloat)9.0); + + NSColor *bgColor = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(bgColor); + STAssertEqualsWithAccuracy([bgColor redComponent], (CGFloat)(255.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor greenComponent], (CGFloat)(0.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor blueComponent], (CGFloat)(255.0/255.0), 0.001, @""); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); +} + + +- (void)testMultiAll { + TDNotNil(lp); + + s = @"expr, decl { font-size:9.0px; font-family:'Courier'; background-color:rgb(255.0, 0.0, 255.0) ; color:rgb(10, 200, 30);}"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [lp bestMatchFor:a]; + TDEqualObjects(@"[]expr/,/decl/{/font-size/:/9.0/px/;/font-family/:/'Courier'/;/background-color/:/rgb/(/255.0/,/0.0/,/255.0/)/;/color/:/rgb/(/10/,/200/,/30/)/;/}^", [a description]); + TDNotNil(ass.attributes); + + id props = [ass.attributes objectForKey:@"expr"]; + TDNotNil(props); + + NSFont *font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Courier"); + TDEquals((CGFloat)[font pointSize], (CGFloat)9.0); + + NSColor *bgColor = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(bgColor); + STAssertEqualsWithAccuracy([bgColor redComponent], (CGFloat)(255.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor greenComponent], (CGFloat)(0.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor blueComponent], (CGFloat)(255.0/255.0), 0.001, @""); + + NSColor *color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); + + props = [ass.attributes objectForKey:@"decl"]; + TDNotNil(props); + + font = [props objectForKey:NSFontAttributeName]; + TDNotNil(font); + TDEqualObjects([font familyName], @"Courier"); + TDEquals((CGFloat)[font pointSize], (CGFloat)9.0); + + bgColor = [props objectForKey:NSBackgroundColorAttributeName]; + TDNotNil(bgColor); + STAssertEqualsWithAccuracy([bgColor redComponent], (CGFloat)(255.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor greenComponent], (CGFloat)(0.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([bgColor blueComponent], (CGFloat)(255.0/255.0), 0.001, @""); + + color = [props objectForKey:NSForegroundColorAttributeName]; + TDNotNil(color); + STAssertEqualsWithAccuracy([color redComponent], (CGFloat)(10.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color greenComponent], (CGFloat)(200.0/255.0), 0.001, @""); + STAssertEqualsWithAccuracy([color blueComponent], (CGFloat)(30.0/255.0), 0.001, @""); +} + +@end diff --git a/test/TDNCName.h b/test/TDNCName.h new file mode 100644 index 0000000..0af35d0 --- /dev/null +++ b/test/TDNCName.h @@ -0,0 +1,28 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKTerminal.h" +#import "PKToken.h" + +extern const NSInteger PKTokenTypeNCName; + +@interface PKToken (NCNameAdditions) +@property (readonly, getter=isNCName) BOOL NCName; +@end + +@interface TDNCName : PKTerminal { + +} ++ (id)NCName; +@end diff --git a/test/TDNCName.m b/test/TDNCName.m new file mode 100644 index 0000000..93e2081 --- /dev/null +++ b/test/TDNCName.m @@ -0,0 +1,39 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDNCName.h" + +const NSInteger PKTokenTypeNCName = 300; + +@implementation PKToken (NCNameAdditions) + +- (BOOL)isNCName { + return self.tokenType == PKTokenTypeNCName; +} + +@end + +@implementation TDNCName + ++ (id)NCName { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + return tok.isNCName; +} + +@end diff --git a/test/TDNCNameState.h b/test/TDNCNameState.h new file mode 100644 index 0000000..3123ce3 --- /dev/null +++ b/test/TDNCNameState.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKTokenizerState.h" + +@interface TDNCNameState : PKTokenizerState { + +} + +@end diff --git a/test/TDNCNameState.m b/test/TDNCNameState.m new file mode 100644 index 0000000..0dfa550 --- /dev/null +++ b/test/TDNCNameState.m @@ -0,0 +1,85 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDNCNameState.h" +#import "PKTokenizer.h" +#import "PKReader.h" +#import "TDXmlToken.h" + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface TDNCNameState () ++ (BOOL)isNameChar:(PKUniChar)c; ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c; ++ (BOOL)isValidNonStartSymbolChar:(PKUniChar)c; +@end + +// NCName ::= (Letter | '_') (NameChar)* +@implementation TDNCNameState + +//- (BOOL)isWhitespace:(PKUniChar)c { +// return (' ' == c || '\n' == c || '\r' == c || '\t' == c); +//} + + +// NameChar ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender ++ (BOOL)isNameChar:(PKUniChar)c { + if (isalnum(c)) { + return YES; + } else if ([self isValidNonStartSymbolChar:c]) { + return YES; + } + // TODO CombiningChar & Extender + return NO; +} + + ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c { + return ('_' == c); +} + + ++ (BOOL)isValidNonStartSymbolChar:(PKUniChar)c { + return ('_' == c || '.' == c || '-' == c); +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + [self resetWithReader:r]; + + NSInteger c = cin; + do { + [self append:c]; + c = [r read]; + } while ([TDNCNameState isNameChar:c]); + + if (PKEOF != c) { + [r unread]; + } + + if ([[self bufferedString] length] == 1 && [TDNCNameState isValidStartSymbolChar:cin]) { + return [t.symbolState nextTokenFromReader:r startingWith:cin tokenizer:t]; + } else { +// return [[[TDXmlToken alloc] initWithTokenType:TDTT_NAME +// stringValue:[[stringbuf copy] autorelease] +// floatValue:0.0] autorelease]; + return nil; + } +} + +@end diff --git a/test/TDNSPredicateBuilder.h b/test/TDNSPredicateBuilder.h new file mode 100644 index 0000000..b955b73 --- /dev/null +++ b/test/TDNSPredicateBuilder.h @@ -0,0 +1,82 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDNSPredicateBuilder : NSObject { + NSString *defaultAttr; + NSString *defaultRelation; + NSString *defaultValue; + PKToken *nonReservedWordFence; + PKCollectionParser *exprParser; + PKCollectionParser *orTermParser; + PKCollectionParser *termParser; + PKCollectionParser *andPrimaryExprParser; + PKCollectionParser *primaryExprParser; + PKCollectionParser *phraseParser; + PKCollectionParser *negatedPredicateParser; + PKCollectionParser *predicateParser; + PKCollectionParser *completePredicateParser; + PKCollectionParser *attrValuePredicateParser; + PKCollectionParser *attrPredicateParser; + PKCollectionParser *valuePredicateParser; + PKCollectionParser *attrParser; + PKCollectionParser *tagParser; + PKCollectionParser *relationParser; + PKCollectionParser *valueParser; + PKCollectionParser *boolParser; + PKParser *trueParser; + PKParser *falseParser; + PKCollectionParser *stringParser; + PKParser *quotedStringParser; + PKCollectionParser *unquotedStringParser; + PKCollectionParser *reservedWordParser; + PKCollectionParser *nonReservedWordParser; + PKPattern *reservedWordPattern; + PKParser *numberParser; + +} +- (NSPredicate *)buildFrom:(NSString *)s; + +@property (nonatomic, copy) NSString *defaultAttr; +@property (nonatomic, copy) NSString *defaultRelation; +@property (nonatomic, copy) NSString *defaultValue; + +@property (nonatomic, retain) PKCollectionParser *exprParser; +@property (nonatomic, retain) PKCollectionParser *orTermParser; +@property (nonatomic, retain) PKCollectionParser *termParser; +@property (nonatomic, retain) PKCollectionParser *andPrimaryExprParser; +@property (nonatomic, retain) PKCollectionParser *primaryExprParser; +@property (nonatomic, retain) PKCollectionParser *phraseParser; +@property (nonatomic, retain) PKCollectionParser *negatedPredicateParser; +@property (nonatomic, retain) PKCollectionParser *predicateParser; +@property (nonatomic, retain) PKCollectionParser *completePredicateParser; +@property (nonatomic, retain) PKCollectionParser *attrValuePredicateParser; +@property (nonatomic, retain) PKCollectionParser *attrPredicateParser; +@property (nonatomic, retain) PKCollectionParser *valuePredicateParser; +@property (nonatomic, retain) PKCollectionParser *attrParser; +@property (nonatomic, retain) PKCollectionParser *tagParser; +@property (nonatomic, retain) PKCollectionParser *relationParser; +@property (nonatomic, retain) PKCollectionParser *valueParser; +@property (nonatomic, retain) PKCollectionParser *boolParser; +@property (nonatomic, retain) PKParser *trueParser; +@property (nonatomic, retain) PKParser *falseParser; +@property (nonatomic, retain) PKCollectionParser *stringParser; +@property (nonatomic, retain) PKParser *quotedStringParser; +@property (nonatomic, retain) PKCollectionParser *unquotedStringParser; +@property (nonatomic, retain) PKCollectionParser *reservedWordParser; +@property (nonatomic, retain) PKCollectionParser *nonReservedWordParser; +@property (nonatomic, retain) PKPattern *reservedWordPattern; +@property (nonatomic, retain) PKParser *numberParser; +@end diff --git a/test/TDNSPredicateBuilder.m b/test/TDNSPredicateBuilder.m new file mode 100644 index 0000000..1416e43 --- /dev/null +++ b/test/TDNSPredicateBuilder.m @@ -0,0 +1,593 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDNSPredicateBuilder.h" +#import "NSString+ParseKitAdditions.h" + +// expr = term orTerm*; +// orTerm = 'or' term; +// term = primaryExpr andPrimaryExpr*; +// andPrimaryExpr = 'and' primaryExpr; +// primaryExpr = phrase | '(' expr ')'; +// phrase = predicate | negatedPredicate; +// negatedPredicate = 'not' predicate; +// predicate = completePredicate | attrValuePredicate | attrPredicate | valuePredicate; +// completePredicate = attr relation value; +// attrValuePredicate = attr value; +// attrPredicate = attr; +// valuePredicate = value; +// attr = tag | Word; +// tag = '@' Word; +// value = string | Number | bool; +// string = QuotedString | unquotedString; +// unquotedString = nonReservedWord+; +// bool = 'true' | 'false'; + +@interface TDNSPredicateBuilder () +@property (nonatomic, retain) PKToken *nonReservedWordFence; +@end + +@implementation TDNSPredicateBuilder + +- (id)init { + if (self = [super init]) { + self.defaultAttr = @"content"; + self.defaultRelation = @"="; + self.defaultValue = @""; + self.nonReservedWordFence = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"." floatValue:0.0]; + } + return self; +} + + +- (void)dealloc { + self.defaultAttr = nil; + self.defaultRelation = nil; + self.defaultValue = nil; + self.nonReservedWordFence = nil; + self.exprParser = nil; + self.orTermParser = nil; + self.termParser = nil; + self.andPrimaryExprParser = nil; + self.primaryExprParser = nil; + self.phraseParser = nil; + self.negatedPredicateParser = nil; + self.predicateParser = nil; + self.completePredicateParser = nil; + self.attrValuePredicateParser = nil; + self.attrPredicateParser = nil; + self.valuePredicateParser = nil; + self.attrParser = nil; + self.tagParser = nil; + self.relationParser = nil; + self.valueParser = nil; + self.boolParser = nil; + self.trueParser = nil; + self.falseParser = nil; + self.stringParser = nil; + self.quotedStringParser = nil; + self.unquotedStringParser = nil; + self.reservedWordParser = nil; + self.nonReservedWordParser = nil; + self.reservedWordPattern = nil; + self.numberParser = nil; + [super dealloc]; +} + + +- (NSPredicate *)buildFrom:(NSString *)s; { + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + return [[self.exprParser completeMatchFor:a] pop]; +} + + +// expression = term orTerm* +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + [exprParser add:self.termParser]; + [exprParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + } + return exprParser; +} + + +// orTerm = 'or' term +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKSequence sequence]; + orTermParser.name = @"orTerm"; + [orTermParser add:[[PKCaseInsensitiveLiteral literalWithString:@"or"] discard]]; + [orTermParser add:self.termParser]; + [orTermParser setAssembler:self selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// term = primaryExpr andPrimaryExpr* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + termParser.name = @"term"; + [termParser add:self.primaryExprParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.andPrimaryExprParser]]; + } + return termParser; +} + + +// andPrimaryExpr = 'and' primaryExpr +- (PKCollectionParser *)andPrimaryExprParser { + if (!andPrimaryExprParser) { + self.andPrimaryExprParser = [PKSequence sequence]; + andPrimaryExprParser.name = @"andPrimaryExpr"; + [andPrimaryExprParser add:[[PKCaseInsensitiveLiteral literalWithString:@"and"] discard]]; + [andPrimaryExprParser add:self.primaryExprParser]; + [andPrimaryExprParser setAssembler:self selector:@selector(didMatchAnd:)]; + } + return andPrimaryExprParser; +} + + +// primaryExpr = phrase | '(' expression ')' +- (PKCollectionParser *)primaryExprParser { + if (!primaryExprParser) { + self.primaryExprParser = [PKAlternation alternation]; + primaryExprParser.name = @"primaryExpr"; + [primaryExprParser add:self.phraseParser]; + + PKSequence *s = [PKSequence sequence]; + [s add:[[PKSymbol symbolWithString:@"("] discard]]; + [s add:self.exprParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + [primaryExprParser add:s]; + } + return primaryExprParser; +} + + +// phrase = predicate | negatedPredicate +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + self.phraseParser = [PKAlternation alternation]; + phraseParser.name = @"phrase"; + [phraseParser add:self.predicateParser]; + [phraseParser add:self.negatedPredicateParser]; + } + return phraseParser; +} + + +// negatedPredicate = 'not' predicate +- (PKCollectionParser *)negatedPredicateParser { + if (!negatedPredicateParser) { + self.negatedPredicateParser = [PKSequence sequence]; + negatedPredicateParser.name = @"negatedPredicate"; + [negatedPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"not"] discard]]; + [negatedPredicateParser add:self.predicateParser]; + [negatedPredicateParser setAssembler:self selector:@selector(didMatchNegatedValue:)]; + } + return negatedPredicateParser; +} + + +// predicate = bool | eqPredicate | nePredicate | gtPredicate | gteqPredicate | ltPredicate | lteqPredicate | beginswithPredicate | containsPredicate | endswithPredicate | matchesPredicate +- (PKCollectionParser *)predicateParser { + if (!predicateParser) { + self.predicateParser = [PKAlternation alternation]; + predicateParser.name = @"predicate"; + [predicateParser add:self.completePredicateParser]; + [predicateParser add:self.attrValuePredicateParser]; + [predicateParser add:self.attrPredicateParser]; + [predicateParser add:self.valuePredicateParser]; + [predicateParser setAssembler:self selector:@selector(didMatchPredicate:)]; + } + return predicateParser; +} + + +// completePredicate = attribute relation value +- (PKCollectionParser *)completePredicateParser { + if (!completePredicateParser) { + self.completePredicateParser = [PKSequence sequence]; + completePredicateParser.name = @"completePredicate"; + [completePredicateParser add:self.attrParser]; + [completePredicateParser add:self.relationParser]; + [completePredicateParser add:self.valueParser]; + } + return completePredicateParser; +} + + +// attrValuePredicate = attribute value +- (PKCollectionParser *)attrValuePredicateParser { + if (!attrValuePredicateParser) { + self.attrValuePredicateParser = [PKSequence sequence]; + attrValuePredicateParser.name = @"attrValuePredicate"; + [attrValuePredicateParser add:self.attrParser]; + [attrValuePredicateParser add:self.valueParser]; + [attrValuePredicateParser setAssembler:self selector:@selector(didMatchAttrValuePredicate:)]; + } + return attrValuePredicateParser; +} + + +// attrPredicate = attribute +- (PKCollectionParser *)attrPredicateParser { + if (!attrPredicateParser) { + self.attrPredicateParser = [PKSequence sequence]; + attrPredicateParser.name = @"attrPredicate"; + [attrPredicateParser add:self.attrParser]; + [attrPredicateParser setAssembler:self selector:@selector(didMatchAttrPredicate:)]; + } + return attrPredicateParser; +} + + +// valuePredicate = value +- (PKCollectionParser *)valuePredicateParser { + if (!valuePredicateParser) { + self.valuePredicateParser = [PKSequence sequence]; + valuePredicateParser.name = @"valuePredicate"; + [valuePredicateParser add:self.valueParser]; + [valuePredicateParser setAssembler:self selector:@selector(didMatchValuePredicate:)]; + } + return valuePredicateParser; +} + + +// attr = tag | 'uniqueid' | 'line' | 'type' | 'isgroupheader' | 'level' | 'index' | 'content' | 'parent' | 'project' | 'countofchildren' +- (PKCollectionParser *)attrParser { + if (!attrParser) { + self.attrParser = [PKAlternation alternation]; + attrParser.name = @"attr"; + [attrParser add:self.tagParser]; + [attrParser add:self.nonReservedWordParser]; + [attrParser setAssembler:self selector:@selector(didMatchAttr:)]; + } + return attrParser; +} + + +// relation = '=' | '!=' | '>' | '>=' | '<' | '<=' | 'beginswith' | 'contains' | 'endswith' | 'matches' +- (PKCollectionParser *)relationParser { + if (!relationParser) { + self.relationParser = [PKAlternation alternation]; + relationParser.name = @"relation"; + [relationParser add:[PKSymbol symbolWithString:@"="]]; + [relationParser add:[PKSymbol symbolWithString:@"!="]]; + [relationParser add:[PKSymbol symbolWithString:@">"]]; + [relationParser add:[PKSymbol symbolWithString:@">="]]; + [relationParser add:[PKSymbol symbolWithString:@"<"]]; + [relationParser add:[PKSymbol symbolWithString:@"<="]]; + [relationParser add:[PKCaseInsensitiveLiteral literalWithString:@"beginswith"]]; + [relationParser add:[PKCaseInsensitiveLiteral literalWithString:@"contains"]]; + [relationParser add:[PKCaseInsensitiveLiteral literalWithString:@"endswith"]]; + [relationParser add:[PKCaseInsensitiveLiteral literalWithString:@"matches"]]; + [relationParser setAssembler:self selector:@selector(didMatchRelation:)]; + } + return relationParser; +} + + +// tag = '@' Word +- (PKCollectionParser *)tagParser { + if (!tagParser) { + self.tagParser = [PKSequence sequence]; + tagParser.name = @"tag"; + [tagParser add:[[PKSymbol symbolWithString:@"@"] discard]]; + [tagParser add:[PKWord word]]; + } + return tagParser; +} + + +// value = QuotedString | Number | bool +- (PKCollectionParser *)valueParser { + if (!valueParser) { + self.valueParser = [PKAlternation alternation]; + valueParser.name = @"value"; + [valueParser add:self.stringParser]; + [valueParser add:self.numberParser]; + [valueParser add:self.boolParser]; + } + return valueParser; +} + + +- (PKCollectionParser *)boolParser { + if (!boolParser) { + self.boolParser = [PKAlternation alternation]; + boolParser.name = @"bool"; + [boolParser add:self.trueParser]; + [boolParser add:self.falseParser]; + [boolParser setAssembler:self selector:@selector(didMatchBool:)]; + } + return boolParser; +} + + +- (PKParser *)trueParser { + if (!trueParser) { + self.trueParser = [[PKCaseInsensitiveLiteral literalWithString:@"true"] discard]; + trueParser.name = @"true"; + [trueParser setAssembler:self selector:@selector(didMatchTrue:)]; + } + return trueParser; +} + + +- (PKParser *)falseParser { + if (!falseParser) { + self.falseParser = [[PKCaseInsensitiveLiteral literalWithString:@"false"] discard]; + falseParser.name = @"false"; + [falseParser setAssembler:self selector:@selector(didMatchFalse:)]; + } + return falseParser; +} + + +// string = quotedString | unquotedString +- (PKCollectionParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKAlternation alternation]; + stringParser.name = @"string"; + [stringParser add:self.quotedStringParser]; + [stringParser add:self.unquotedStringParser]; + } + return stringParser; +} + + +// quotedString = QuotedString +- (PKParser *)quotedStringParser { + if (!quotedStringParser) { + self.quotedStringParser = [PKQuotedString quotedString]; + quotedStringParser.name = @"quotedString"; + [quotedStringParser setAssembler:self selector:@selector(didMatchQuotedString:)]; + } + return quotedStringParser; +} + + +// unquotedString = nonReservedWord+ +- (PKCollectionParser *)unquotedStringParser { + if (!unquotedStringParser) { + self.unquotedStringParser = [PKSequence sequence]; + unquotedStringParser.name = @"unquotedString"; + [unquotedStringParser add:self.nonReservedWordParser]; + [unquotedStringParser add:[PKRepetition repetitionWithSubparser:self.nonReservedWordParser]]; + [unquotedStringParser setAssembler:self selector:@selector(didMatchUnquotedString:)]; + } + return unquotedStringParser; +} + + +- (PKCollectionParser *)reservedWordParser { + if (!reservedWordParser) { + self.reservedWordParser = [PKIntersection intersection]; + [reservedWordParser add:[PKWord word]]; + [reservedWordParser add:self.reservedWordPattern]; + reservedWordParser.name = @"reservedWord"; + [reservedWordParser setAssembler:self selector:@selector(didMatchReservedWord:)]; + } + return reservedWordParser; +} + + +// nonReservedWord = Word +- (PKCollectionParser *)nonReservedWordParser { + if (!nonReservedWordParser) { + self.nonReservedWordParser = [PKDifference differenceWithSubparser:[PKWord word] minus:self.reservedWordParser]; + nonReservedWordParser.name = @"nonReservedWord"; + [nonReservedWordParser setAssembler:self selector:@selector(didMatchNonReservedWord:)]; + } + return nonReservedWordParser; +} + + +- (PKPattern *)reservedWordPattern { + if (!reservedWordPattern) { + NSString *s = @"true|false|and|or|not|contains|beginswith|endswith|matches"; + self.reservedWordPattern = [PKPattern patternWithString:s options:PKPatternOptionsIgnoreCase]; + reservedWordPattern.name = @"reservedWordPattern"; + } + return reservedWordPattern; +} + + +- (PKParser *)numberParser { + if (!numberParser) { + self.numberParser = [PKNumber number]; + numberParser.name = @"number"; + [numberParser setAssembler:self selector:@selector(didMatchNumber:)]; + } + return numberParser; +} + + +- (void)didMatchAnd:(PKAssembly *)a { + NSPredicate *p2 = [a pop]; + NSPredicate *p1 = [a pop]; + NSArray *subs = [NSArray arrayWithObjects:p1, p2, nil]; + [a push:[NSCompoundPredicate andPredicateWithSubpredicates:subs]]; +} + + +- (void)didMatchOr:(PKAssembly *)a { + NSPredicate *p2 = [a pop]; + NSPredicate *p1 = [a pop]; + NSArray *subs = [NSArray arrayWithObjects:p1, p2, nil]; + [a push:[NSCompoundPredicate orPredicateWithSubpredicates:subs]]; +} + + +- (void)didMatchPredicate:(PKAssembly *)a { + id value = [a pop]; + id relation = [a pop]; + id attr = [a pop]; + NSString *predicateFormat = [NSString stringWithFormat:@"%@ %@ %%@", attr, relation, nil]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFormat, value, nil]; + [a push:predicate]; +} + + +- (void)didMatchAttrValuePredicate:(PKAssembly *)a { + id value = [a pop]; + id attr = [a pop]; + [a push:attr]; + [a push:defaultRelation]; + [a push:value]; +} + + +- (void)didMatchAttrPredicate:(PKAssembly *)a { + id attr = [a pop]; + [a push:attr]; + [a push:defaultRelation]; + [a push:defaultValue]; +} + + +- (void)didMatchValuePredicate:(PKAssembly *)a { + id value = [a pop]; + [a push:defaultAttr]; + [a push:defaultRelation]; + [a push:value]; +} + + +- (void)didMatchAttr:(PKAssembly *)a { + [a push:[[a pop] stringValue]]; +} + + +- (void)didMatchRelation:(PKAssembly *)a { + [a push:[[a pop] stringValue]]; +} + + +- (void)didMatchNegatedValue:(PKAssembly *)a { + id p = [a pop]; + [a push:[NSCompoundPredicate notPredicateWithSubpredicate:p]]; +} + + +- (void)didMatchBool:(PKAssembly *)a { + NSNumber *b = [a pop]; + [a push:[NSPredicate predicateWithValue:[b boolValue]]]; +} + + +- (void)didMatchTrue:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:YES]]; +} + + +- (void)didMatchFalse:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:NO]]; +} + + +- (void)didMatchQuotedString:(PKAssembly *)a { + [a push:[[[a pop] stringValue] stringByTrimmingQuotes]]; +} + + +- (void)didMatchReservedWord:(PKAssembly *)a { +// PKToken *tok = [a pop]; +// [a push:tok.stringValue]; +} + + +- (void)didMatchNonReservedWord:(PKAssembly *)a { +// id obj = [a pop]; +// [a push:nonReservedWordFence]; +// [a push:obj]; +} + + +- (void)didMatchUnquotedString:(PKAssembly *)a { + NSMutableArray *wordStrings = [NSMutableArray array]; + + while (1) { + NSArray *objs = [a objectsAbove:nonReservedWordFence]; + id next = [a pop]; // is the next obj a fence? + if (![nonReservedWordFence isEqual:next]) { + // if not, put the next token back + if (next) { + [a push:next]; + } + // also put back any toks we didnt mean to pop + for (id obj in [objs reverseObjectEnumerator]) { + [a push:obj]; + } + break; + } + NSAssert(1 == [objs count], @""); + [wordStrings addObject:[objs objectAtIndex:0]]; + } + + NSInteger last = [wordStrings count] - 1; + NSInteger i = 0; + NSMutableString *ms = [NSMutableString string]; + for (NSString *wordString in [wordStrings reverseObjectEnumerator]) { + if (i++ == last) { + [ms appendString:wordString]; + } else { + [ms appendFormat:@"%@ ", wordString]; + } + } + [a push:[[ms copy] autorelease]]; +} + + +- (void)didMatchNumber:(PKAssembly *)a { + NSNumber *n = [NSNumber numberWithFloat:[(PKToken *)[a pop] floatValue]]; + [a push:n]; +} + +@synthesize defaultAttr; +@synthesize defaultRelation; +@synthesize defaultValue; +@synthesize nonReservedWordFence; +@synthesize exprParser; +@synthesize orTermParser; +@synthesize termParser; +@synthesize andPrimaryExprParser; +@synthesize primaryExprParser; +@synthesize phraseParser; +@synthesize negatedPredicateParser; +@synthesize predicateParser; +@synthesize completePredicateParser; +@synthesize attrValuePredicateParser; +@synthesize attrPredicateParser; +@synthesize valuePredicateParser; +@synthesize attrParser; +@synthesize tagParser; +@synthesize relationParser; +@synthesize valueParser; +@synthesize boolParser; +@synthesize trueParser; +@synthesize falseParser; +@synthesize stringParser; +@synthesize quotedStringParser; +@synthesize unquotedStringParser; +@synthesize reservedWordParser; +@synthesize nonReservedWordParser; +@synthesize reservedWordPattern; +@synthesize numberParser; +@end diff --git a/test/TDNSPredicateBuilderTest.h b/test/TDNSPredicateBuilderTest.h new file mode 100644 index 0000000..1b01d16 --- /dev/null +++ b/test/TDNSPredicateBuilderTest.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "TDNSPredicateBuilder.h" + +@interface TDNSPredicateBuilderTest : SenTestCase { + TDNSPredicateBuilder *b; + NSString *s; + PKAssembly *a; +} + +@end diff --git a/test/TDNSPredicateBuilderTest.m b/test/TDNSPredicateBuilderTest.m new file mode 100644 index 0000000..caa236f --- /dev/null +++ b/test/TDNSPredicateBuilderTest.m @@ -0,0 +1,219 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDNSPredicateBuilderTest.h" + +@implementation TDNSPredicateBuilderTest + +- (void)setUp { + b = [[[TDNSPredicateBuilder alloc] init] autorelease]; +} + + +- (void)testEq { + // test numbers + s = @"foo = 1.0"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == 1]foo/=/1.0^", [a description]); + + s = @"foo = -1.0"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == -1]foo/=/-1.0^", [a description]); + + + // test bools + s = @"foo = true"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == TRUEPREDICATE]foo/=/true^", [a description]); + + s = @"foo = false"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == FALSEPREDICATE]foo/=/false^", [a description]); + + + // test strings + s = @"foo = 'bar'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == \"bar\"]foo/=/'bar'^", [a description]); + + s = @"foo = 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo == \"baz\"]foo/=/'baz'^", [a description]); +} + + +- (void)testNe { + // test numbers + s = @"foo != 1.0"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != 1]foo/!=/1.0^", [a description]); + + s = @"foo != 1.00"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != 1]foo/!=/1.00^", [a description]); + + + // test bools + s = @"foo != true"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != TRUEPREDICATE]foo/!=/true^", [a description]); + + s = @"foo != false"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != FALSEPREDICATE]foo/!=/false^", [a description]); + + + // test strings + s = @"foo != 'bar'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != \"bar\"]foo/!=/'bar'^", [a description]); + + s = @"foo != 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo != \"baz\"]foo/!=/'baz'^", [a description]); +} + + +- (void)testGt { + s = @"foo > 42"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo > 42]foo/>/42^", [a description]); +} + + +- (void)testLt { + s = @"foo < .3"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo < 0.3]foo/= 42"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo >= 42]foo/>=/42^", [a description]); +} + + +- (void)testLteq { + s = @"foo <= .3"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo <= 0.3]foo/<=/.3^", [a description]); +} + + +- (void)testBeginswith { + s = @"foo beginswith 'bar'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo BEGINSWITH \"bar\"]foo/beginswith/'bar'^", [a description]); +} + + +- (void)testContains { + s = @"foo contains 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo CONTAINS \"baz\"]foo/contains/'baz'^", [a description]); +} + + +- (void)testEndswith { + s = @"foo endswith 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo ENDSWITH \"baz\"]foo/endswith/'baz'^", [a description]); +} + + +- (void)testMatches { + s = @"foo matches 'baz'"; + a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo MATCHES \"baz\"]foo/matches/'baz'^", [a description]); +} + + +- (void)testUnqotedString { +// s = @"foo contains bar"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo CONTAINS \"bar\"]foo/contains/bar^", [a description]); +// +// s = @"foo matches bar baz"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo MATCHES \"bar baz\"]foo/matches/bar/baz^", [a description]); +// +// s = @"foo matches foo bar baz"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo MATCHES \"foo bar baz\"]foo/matches/foo/bar/baz^", [a description]); +// +// s = @"foo matches bar and baz contains bat"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo MATCHES \"bar\" AND baz CONTAINS \"bat\"]foo/matches/bar/and/baz/contains/bat^", [a description]); +// +// s = @"foo matches foo bar and baz contains bat"; +// a = [b.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; +// TDEqualObjects(@"[foo MATCHES \"foo bar\" AND baz CONTAINS \"bat\"]foo/matches/foo/bar/and/baz/contains/bat^", [a description]); +} + + +- (void)testBools { + s = @"true"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[content == TRUEPREDICATE]true^", [a description]); + + s = @"not true"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[NOT content == TRUEPREDICATE]not/true^", [a description]); + + s = @"false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[content == FALSEPREDICATE]false^", [a description]); + + s = @"not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[NOT content == FALSEPREDICATE]not/false^", [a description]); + + s = @"true and false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[content == TRUEPREDICATE AND content == FALSEPREDICATE]true/and/false^", [a description]); + + s = @"not true and false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[(NOT content == TRUEPREDICATE) AND content == FALSEPREDICATE]not/true/and/false^", [a description]); + + s = @"not true and not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[(NOT content == TRUEPREDICATE) AND (NOT content == FALSEPREDICATE)]not/true/and/not/false^", [a description]); + + s = @"true or false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[content == TRUEPREDICATE OR content == FALSEPREDICATE]true/or/false^", [a description]); + + s = @"(true and false) or false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[(content == TRUEPREDICATE AND content == FALSEPREDICATE) OR content == FALSEPREDICATE](/true/and/false/)/or/false^", [a description]); + + s = @"(true and false) or not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [b.exprParser bestMatchFor:a]; + TDEqualObjects(@"[(content == TRUEPREDICATE AND content == FALSEPREDICATE) OR (NOT content == FALSEPREDICATE)](/true/and/false/)/or/not/false^", [a description]); +} + +@end diff --git a/test/TDNSPredicateEvaluator.h b/test/TDNSPredicateEvaluator.h new file mode 100644 index 0000000..cf1b4c7 --- /dev/null +++ b/test/TDNSPredicateEvaluator.h @@ -0,0 +1,34 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class TDNSPredicateEvaluator; + +@protocol TDKeyPathResolver +- (id)resolvedValueForKeyPath:(NSString *)s; +@end + +@interface TDNSPredicateEvaluator : NSObject { + id resolver; + PKParser *parser; + PKToken *openCurly; +} +- (id)initWithKeyPathResolver:(id )r; + +- (BOOL)evaluate:(NSString *)s; + +@property (nonatomic, retain) PKParser *parser; +@end diff --git a/test/TDNSPredicateEvaluator.m b/test/TDNSPredicateEvaluator.m new file mode 100644 index 0000000..b6e3a6e --- /dev/null +++ b/test/TDNSPredicateEvaluator.m @@ -0,0 +1,230 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDNSPredicateEvaluator.h" +#import "PKParserFactory.h" +#import "NSString+ParseKitAdditions.h" +#import "NSArray+ParseKitAdditions.h" + +@interface TDNSPredicateEvaluator () +- (void)didMatchCollectionPredicateAssembly:(PKAssembly *)a ordered:(NSComparisonResult)ordered; + +@property (nonatomic, assign) id resolver; +@property (nonatomic, retain) PKToken *openCurly; +@end + +@implementation TDNSPredicateEvaluator + +- (id)initWithKeyPathResolver:(id )r { + if (self = [super init]) { + self.resolver = r; + + self.openCurly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0]; + + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"nspredicate" ofType:@"grammar"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + self.parser = [[PKParserFactory factory] parserFromGrammar:s assembler:self]; + } + return self; +} + + +- (void)dealloc { + resolver = nil; + self.parser = nil; + self.openCurly = nil; + [super dealloc]; +} + + +- (BOOL)evaluate:(NSString *)s { + id result = [parser parse:s]; + return [result boolValue]; +} + + +- (void)didMatchNegatedPredicate:(PKAssembly *)a { + BOOL b = [[a pop] boolValue]; + [a push:[NSNumber numberWithBool:!b]]; +} + + +- (void)didMatchNumComparisonPredicate:(PKAssembly *)a { + CGFloat n2 = [(PKToken *)[a pop] floatValue]; + NSString *op = [[a pop] stringValue]; + CGFloat n1 = [(PKToken *)[a pop] floatValue]; + + BOOL result = NO; + if ([op isEqualToString:@"<"]) { + result = n1 < n2; + } else if ([op isEqualToString:@">"]) { + result = n1 > n2; + } else if ([op isEqualToString:@"="] || [op isEqualToString:@"=="]) { + result = n1 == n2; + } else if ([op isEqualToString:@"<="] || [op isEqualToString:@"=<"]) { + result = n1 <= n2; + } else if ([op isEqualToString:@">="] || [op isEqualToString:@"=>"]) { + result = n1 >= n2; + } else if ([op isEqualToString:@"!="] || [op isEqualToString:@"<>"]) { + result = n1 != n2; + } + + [a push:[NSNumber numberWithBool:result]]; +} + + +- (void)didMatchCollectionLtPredicate:(PKAssembly *)a { + [self didMatchCollectionPredicateAssembly:a ordered:NSOrderedAscending]; +} + + +- (void)didMatchCollectionGtPredicate:(PKAssembly *)a { + [self didMatchCollectionPredicateAssembly:a ordered:NSOrderedDescending]; +} + + +- (void)didMatchCollectionEqPredicate:(PKAssembly *)a { + [self didMatchCollectionPredicateAssembly:a ordered:NSOrderedSame]; +} + + +- (void)didMatchCollectionPredicateAssembly:(PKAssembly *)a ordered:(NSComparisonResult)ordered { + id value = [a pop]; + [a pop]; // discard op + NSArray *array = [a pop]; + NSString *aggOp = [[a pop] stringValue]; + + BOOL isAny = NSOrderedSame == [aggOp caseInsensitiveCompare:@"ANY"]; + BOOL isSome = NSOrderedSame == [aggOp caseInsensitiveCompare:@"SOME"]; + BOOL isNone = NSOrderedSame == [aggOp caseInsensitiveCompare:@"NONE"]; + BOOL isAll = NSOrderedSame == [aggOp caseInsensitiveCompare:@"ALL"]; + + BOOL result = NO; + if (isAny || isSome || isNone) { + for (id obj in array) { + if (ordered == [obj compare:value]) { + result = YES; + break; + } + } + } else if (isAll) { + NSInteger c = 0; + for (id obj in array) { + if (ordered != [obj compare:value]) { + break; + } + c++; + } + result = c == [array count]; + } + + if (isNone) { + result = !result; + } + + [a push:[NSNumber numberWithBool:result]]; +} + + +- (void)didMatchString:(PKAssembly *)a { + NSString *s = [[[a pop] stringValue] stringByTrimmingQuotes]; + [a push:s]; +} + + +- (void)didMatchStringTestPredicate:(PKAssembly *)a { + NSString *s2 = [a pop]; + NSString *op = [[a pop] stringValue]; + NSString *s1 = [a pop]; + + BOOL result = NO; + if (NSOrderedSame == [op caseInsensitiveCompare:@"BEGINSWITH"]) { + result = [s1 hasPrefix:s2]; + } else if (NSOrderedSame == [op caseInsensitiveCompare:@"CONTAINS"]) { + result = (NSNotFound != [s1 rangeOfString:s2].location); + } else if (NSOrderedSame == [op caseInsensitiveCompare:@"ENDSWITH"]) { + result = [s1 hasSuffix:s2]; + } else if (NSOrderedSame == [op caseInsensitiveCompare:@"LIKE"]) { + result = NSOrderedSame == [s1 caseInsensitiveCompare:s2]; // TODO + } else if (NSOrderedSame == [op caseInsensitiveCompare:@"MATCHES"]) { + result = NSOrderedSame == [s1 caseInsensitiveCompare:s2]; // TODO + } + + [a push:[NSNumber numberWithBool:result]]; +} + + +- (void)didMatchAndAndTerm:(PKAssembly *)a { + BOOL b2 = [[a pop] boolValue]; + BOOL b1 = [[a pop] boolValue]; + [a push:[NSNumber numberWithBool:b1 && b2]]; +} + + +- (void)didMatchOrOrTerm:(PKAssembly *)a { + BOOL b2 = [[a pop] boolValue]; + BOOL b1 = [[a pop] boolValue]; + [a push:[NSNumber numberWithBool:b1 || b2]]; +} + + +- (void)didMatchArray:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:openCurly]; + [a pop]; // discard '{' + [a push:[objs reversedArray]]; +} + + +- (void)didMatchCollectionTestPredicate:(PKAssembly *)a { + NSArray *array = [a pop]; + NSAssert([array isKindOfClass:[NSArray class]], @""); + id value = [a pop]; + [a push:[NSNumber numberWithBool:[array containsObject:value]]]; +} + + +- (void)didMatchKeyPath:(PKAssembly *)a { + NSString *keyPath = [[a pop] stringValue]; + [a push:[resolver resolvedValueForKeyPath:keyPath]]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + [a push:[NSNumber numberWithFloat:[(PKToken *)[a pop] floatValue]]]; +} + + +- (void)didMatchTrue:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:YES]]; +} + + +- (void)didMatchFalse:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:NO]]; +} + + +- (void)didMatchTruePredicate:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:YES]]; +} + + +- (void)didMatchFalsePredicate:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:NO]]; +} + +@synthesize resolver; +@synthesize parser; +@synthesize openCurly; +@end diff --git a/test/TDNSPredicateEvaluatorTest.h b/test/TDNSPredicateEvaluatorTest.h new file mode 100644 index 0000000..cc918c1 --- /dev/null +++ b/test/TDNSPredicateEvaluatorTest.h @@ -0,0 +1,28 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "TDNSPredicateEvaluator.h" + +@interface TDNSPredicateEvaluatorTest : SenTestCase { + TDNSPredicateEvaluator *eval; + NSString *s; + PKAssembly *a; + PKAssembly *res; + PKTokenizer *t; + + NSMutableDictionary *d; +} + +@end diff --git a/test/TDNSPredicateEvaluatorTest.m b/test/TDNSPredicateEvaluatorTest.m new file mode 100644 index 0000000..8367588 --- /dev/null +++ b/test/TDNSPredicateEvaluatorTest.m @@ -0,0 +1,278 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDNSPredicateEvaluatorTest.h" + +@implementation TDNSPredicateEvaluatorTest + +- (id)resolvedValueForKeyPath:(NSString *)kp { + id result = [d objectForKey:kp]; + if (!result) { + result = [NSNumber numberWithBool:NO]; + } + return result; +} + + +- (void)dealloc { + [eval release]; + [super dealloc]; +} + + +- (void)setUp { + d = [NSMutableDictionary dictionary]; + eval = [[TDNSPredicateEvaluator alloc] initWithKeyPathResolver:self]; + t = eval.parser.tokenizer; +} + + +- (void)testKeyPath { + [d setObject:[NSNumber numberWithBool:YES] forKey:@"foo"]; + [d setObject:[NSNumber numberWithBool:NO] forKey:@"baz"]; + + t.string = @"foo"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[eval.parser parserNamed:@"keyPath"] completeMatchFor:a]; + TDEqualObjects(@"[1]foo^", [res description]); + + t.string = @"bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[eval.parser parserNamed:@"keyPath"] completeMatchFor:a]; + TDEqualObjects(@"[0]bar^", [res description]); + + t.string = @"baz"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[eval.parser parserNamed:@"keyPath"] completeMatchFor:a]; + TDEqualObjects(@"[0]baz^", [res description]); + + t.string = @"foo.bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[eval.parser parserNamed:@"keyPath"] completeMatchFor:a]; + TDEqualObjects(@"[0]foo.bar^", [res description]); +} + + +- (void)testNegatedPredicate { + t.string = @"not 0 < 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]not/0/ 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]1/>/2^", [res description]); + + t.string = @"1 != 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]1/!=/2^", [res description]); + + t.string = @"1 == 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]1/==/2^", [res description]); + + t.string = @"1 = 2"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]1/=/2^", [res description]); +} + + +- (void)testArray { + t.string = @"{1, 3}"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [[eval.parser parserNamed:@"array"] completeMatchFor:a]; + NSArray *array = [res pop]; + TDEquals((NSUInteger)2, [array count]); + TDEqualObjects([array objectAtIndex:0], [NSNumber numberWithInteger:1]); + TDEqualObjects([array objectAtIndex:1], [NSNumber numberWithInteger:3]); +} + + +- (void)testTrue { + t.string = @"true"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [[eval.parser parserNamed:@"bool"] completeMatchFor:a]; + TDEqualObjects(@"[1]true^", [res description]); +} + + +- (void)testFalse { + t.string = @"false"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [[eval.parser parserNamed:@"bool"] completeMatchFor:a]; + TDEqualObjects(@"[0]false^", [res description]); +} + + +- (void)testTruePredicate { + t.string = @"TRUEPREDICATE"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]TRUEPREDICATE^", [res description]); +} + + +- (void)testFalsePredicate { + t.string = @"FALSEPREDICATE"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]FALSEPREDICATE^", [res description]); +} + + +- (void)testCollectionTest { + t.string = @"1 IN {1}"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]1/IN/{/1/}^", [res description]); +} + + +- (void)testCollectionLtComparison { + t.string = @"ANY {3} < 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]ANY/{/3/}/ 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]ANY/{/3/}/>/4^", [res description]); + + t.string = @"SOME {3} > 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]SOME/{/3/}/>/4^", [res description]); + + t.string = @"NONE {3} > 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]NONE/{/3/}/>/4^", [res description]); + + t.string = @"ALL {3} > 4"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]ALL/{/3/}/>/4^", [res description]); +} + + +- (void)testOr { + t.string = @"TRUEPREDICATE OR FALSEPREDICATE"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1]TRUEPREDICATE/OR/FALSEPREDICATE^", [res description]); +} + + +- (void)testAnd { + t.string = @"TRUEPREDICATE AND FALSEPREDICATE"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[0]TRUEPREDICATE/AND/FALSEPREDICATE^", [res description]); +} + + +- (void)testCompoundExpr { + t.string = @"(TRUEPREDICATE)"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [eval.parser completeMatchFor:a]; + TDEqualObjects(@"[1](/TRUEPREDICATE/)^", [res description]); +} + +@end diff --git a/test/TDNegationTest.h b/test/TDNegationTest.h new file mode 100644 index 0000000..81fdc4b --- /dev/null +++ b/test/TDNegationTest.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDNegationTest : SenTestCase { + PKNegation *n; + PKTokenizer *t; + PKAssembly *a; + PKAssembly *res; + NSString *s; +} + +@end diff --git a/test/TDNegationTest.m b/test/TDNegationTest.m new file mode 100644 index 0000000..498845c --- /dev/null +++ b/test/TDNegationTest.m @@ -0,0 +1,66 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDNegationTest.h" + +@implementation TDNegationTest + +- (void)testFoo { + n = [PKNegation negationWithSubparser:[PKWord word]]; + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [n bestMatchFor:a]; + TDNil(res); + + s = @"'foo'"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [n bestMatchFor:a]; + TDEqualObjects(@"['foo']'foo'^", [res description]); + + n = [PKNegation negationWithSubparser:[PKLiteral literalWithString:@"foo"]]; + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [n bestMatchFor:a]; + TDNil(res); +} + + +- (void)testParserNamed { + PKWord *w = [PKWord word]; + w.name = @"w"; + n = [PKNegation negationWithSubparser:w]; + + TDEquals(w, [n parserNamed:@"w"]); + + PKCollectionParser *alt = [PKAlternation alternation]; + alt.name = @"alt"; + + PKParser *foo = [PKLiteral literalWithString:@"foo"]; + foo.name = @"foo"; + [alt add:foo]; + + PKParser *bar = [PKLiteral literalWithString:@"bar"]; + bar.name = @"bar"; + [alt add:bar]; + + n = [PKNegation negationWithSubparser:alt]; + + TDEquals(alt, [n parserNamed:@"alt"]); + TDEquals(foo, [n parserNamed:@"foo"]); + TDEquals(bar, [n parserNamed:@"bar"]); +} + +@end diff --git a/test/TDNonReservedWord.h b/test/TDNonReservedWord.h new file mode 100644 index 0000000..863caef --- /dev/null +++ b/test/TDNonReservedWord.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface TDNonReservedWord : PKWord { + +} + +@end diff --git a/test/TDNonReservedWord.m b/test/TDNonReservedWord.m new file mode 100644 index 0000000..8385b30 --- /dev/null +++ b/test/TDNonReservedWord.m @@ -0,0 +1,35 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import + +@interface TDReservedWord () ++ (NSArray *)reservedWords; +@end + +@implementation TDNonReservedWord + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + NSString *s = tok.stringValue; + return [s length] && ![[TDReservedWord reservedWords] containsObject:s]; +} + +@end diff --git a/test/TDNumberStateTest.h b/test/TDNumberStateTest.h new file mode 100644 index 0000000..820a7e4 --- /dev/null +++ b/test/TDNumberStateTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDNumberStateTest : SenTestCase { + PKNumberState *numberState; + PKTokenizer *t; + PKReader *r; + NSString *s; +} +@end diff --git a/test/TDNumberStateTest.m b/test/TDNumberStateTest.m new file mode 100644 index 0000000..05b46f0 --- /dev/null +++ b/test/TDNumberStateTest.m @@ -0,0 +1,668 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDNumberStateTest.h" + +@implementation TDNumberStateTest + +- (void)setUp { + t = [[PKTokenizer alloc] init]; + r = [[PKReader alloc] init]; + numberState = t.numberState; +} + + +- (void)tearDown { + [t release]; + [r release]; +} + + +- (void)testSingleDigit { + s = @"3"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)3.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"3", tok.stringValue); +} + + +- (void)testDoubleDigit { + s = @"47"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)47.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"47", tok.stringValue); +} + + +- (void)testTripleDigit { + s = @"654"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)654.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"654", tok.stringValue); +} + + +- (void)testSingleDigitPositive { + s = @"+3"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)3.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+3", tok.stringValue); +} + + +- (void)testDoubleDigitPositive { + s = @"+22"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)22.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)testDoubleDigitPositiveSpace { + s = @"+22 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)22.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)testMultipleDots { + s = @"1.1.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.1", tok.stringValue); + + tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".1", tok.stringValue); +} + + +- (void)testOneDot { + s = @"1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1", tok.stringValue); +} + + +- (void)testCustomOneDot { + s = @"1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.", tok.stringValue); +} + + +- (void)testOneDotZero { + s = @"1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.0", tok.stringValue); +} + + +- (void)testPositiveOneDot { + s = @"+1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1", tok.stringValue); +} + + +- (void)testPositiveOneDotCustom { + s = @"+1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.", tok.stringValue); +} + + +- (void)testPositiveOneDotZero { + s = @"+1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.0", tok.stringValue); +} + + +- (void)testPositiveOneDotZeroSpace { + s = @"+1.0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.0", tok.stringValue); +} + + +- (void)testNegativeOneDot { + s = @"-1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testNegativeOneDotCustom { + s = @"-1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.", tok.stringValue); +} + + +- (void)testNegativeOneDotSpace { + s = @"-1. "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testNegativeOneDotZero { + s = @"-1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.0", tok.stringValue); +} + + +- (void)testNegativeOneDotZeroSpace { + s = @"-1.0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.0", tok.stringValue); +} + + +- (void)testOneDotOne { + s = @"1.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.1", tok.stringValue); +} + + +- (void)testZeroDotOne { + s = @"0.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0.1", tok.stringValue); +} + + +- (void)testDotOne { + s = @".1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".1", tok.stringValue); +} + + +- (void)testDotZero { + s = @".0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); +} + + +- (void)testNegativeDotZero { + s = @"-.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.0", tok.stringValue); +} + + +- (void)testPositiveDotZero { + s = @"+.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+.0", tok.stringValue); +} + + +- (void)testPositiveDotOne { + s = @"+.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+.1", tok.stringValue); +} + + +- (void)testNegativeDotOne { + s = @"-.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1", tok.stringValue); +} + + +- (void)testNegativeDotOneOne { + s = @"-.11"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.11, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.11", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOne { + s = @"-.111"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.111", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZero { + s = @"-.1110"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1110", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZeroZero { + s = @"-.11100"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.11100", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZeroSpace { + s = @"-.1110 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1110", tok.stringValue); +} + + +- (void)testZeroDotThreeSixtyFive { + s = @"0.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0.365", tok.stringValue); +} + + +- (void)testNegativeZeroDotThreeSixtyFive { + s = @"-0.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0.365", tok.stringValue); +} + + +- (void)testNegativeTwentyFourDotThreeSixtyFive { + s = @"-24.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-24.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-24.365", tok.stringValue); +} + + +- (void)testTwentyFourDotThreeSixtyFive { + s = @"24.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)24.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"24.365", tok.stringValue); +} + + +- (void)testZero { + s = @"0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0", tok.stringValue); +} + + +- (void)testNegativeOne { + s = @"-1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testOne { + s = @"1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1", tok.stringValue); +} + + +- (void)testPositiveOne { + s = @"+1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1", tok.stringValue); +} + + +- (void)testPositiveZero { + s = @"+0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+0", tok.stringValue); +} + + +- (void)testPositiveZeroSpace { + s = @"+0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+0", tok.stringValue); +} + + +- (void)testNegativeZero { + s = @"-0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0", tok.stringValue); +} + + +- (void)testNull { + s = @"NULL"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testNil { + s = @"nil"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testEmptyString { + s = @""; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDot { + s = @"."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDotSpace { + s = @". "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDotSpaceOne { + s = @". 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlus { + s = @"+"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlusSpace { + s = @"+ "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlusSpaceOne { + s = @"+ 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinus { + s = @"-"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinusSpace { + s = @"- "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinusSpaceOne { + s = @"- 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testInitSig { + s = @"- (id)init {"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); +} + + +- (void)testInitSig2 { + s = @"-(id)init {"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); +} + + +- (void)testParenStuff { + s = @"-(ab+5)"; + t.string = s; + r.string = s; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); +} + +@end diff --git a/test/TDParseTreeTest.h b/test/TDParseTreeTest.h new file mode 100644 index 0000000..4533383 --- /dev/null +++ b/test/TDParseTreeTest.h @@ -0,0 +1,34 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "PKParseTree.h" +#import "PKRuleNode.h" +#import "PKTokenNode.h" +#import "PKParseTreeAssembler.h" + + +@interface TDParseTreeTest : SenTestCase { + PKParserFactory *factory; + PKParseTreeAssembler *as; + NSString *g; + NSString *s; + PKTokenAssembly *a; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; + PKToken *tok; +} + +@end diff --git a/test/TDParseTreeTest.m b/test/TDParseTreeTest.m new file mode 100644 index 0000000..bbe80be --- /dev/null +++ b/test/TDParseTreeTest.m @@ -0,0 +1,170 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDParseTreeTest.h" + +@implementation TDParseTreeTest + +- (void)setUp { + factory = [PKParserFactory factory]; + as = [[[PKParseTreeAssembler alloc] init] autorelease]; +} + + +- (void)testAddExpr { + g = @"@start = expr;" + @"expr = addExpr;" + @"addExpr = atom (('+'|'-') atom)*;" + @"atom = Number;"; + lp = [factory parserFromGrammar:g assembler:as preassembler:as]; + + lp.tokenizer.string = @"1 + 2"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp completeMatchFor:a]; + TDNotNil(res); + TDEqualObjects([res description], @"[]1/+/2^"); + + PKParseTree *tr = res.target; + TDEqualObjects([tr class], [PKParseTree class]); + TDEquals([[tr children] count], (NSUInteger)1); + + PKRuleNode *expr = [[tr children] objectAtIndex:0]; + TDEqualObjects([expr name], @"expr"); + TDEqualObjects([expr class], [PKRuleNode class]); + TDEquals([[expr children] count], (NSUInteger)1); + + PKRuleNode *addExpr = [[expr children] objectAtIndex:0]; + TDEqualObjects([addExpr name], @"addExpr"); + TDEqualObjects([addExpr class], [PKRuleNode class]); + TDEquals([[addExpr children] count], (NSUInteger)3); + + PKRuleNode *atom1 = [[addExpr children] objectAtIndex:0]; + TDEqualObjects([atom1 class], [PKRuleNode class]); + TDEqualObjects([atom1 name], @"atom"); + TDEquals([[atom1 children] count], (NSUInteger)1); + + PKTokenNode *one = [[atom1 children] objectAtIndex:0]; + TDEqualObjects([one class], [PKTokenNode class]); + TDEqualObjects([one token], [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:@"1" floatValue:1.0]); + + PKTokenNode *plus = [[addExpr children] objectAtIndex:1]; + TDEqualObjects([plus class], [PKTokenNode class]); + TDEqualObjects([plus token], [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"+" floatValue:0]); + + PKRuleNode *atom2 = [[addExpr children] objectAtIndex:2]; + TDEqualObjects([atom2 class], [PKRuleNode class]); + TDEqualObjects([atom2 name], @"atom"); + TDEquals([[atom2 children] count], (NSUInteger)1); + + PKTokenNode *two = [[atom2 children] objectAtIndex:0]; + TDEqualObjects([two class], [PKTokenNode class]); + TDEqualObjects([two token], [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:@"2" floatValue:2.0]); +} + + +- (void)testFoo { + g = @"@start = expr;" + @"expr = Word+;"; + lp = [factory parserFromGrammar:g assembler:as preassembler:as]; + + lp.tokenizer.string = @"foo"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp completeMatchFor:a]; + TDNotNil(res); + TDEqualObjects([res description], @"[]foo^"); + + PKParseTree *tr = res.target; + TDEqualObjects([tr class], [PKParseTree class]); + TDEquals([[tr children] count], (NSUInteger)1); + + PKRuleNode *expr = [[tr children] objectAtIndex:0]; + TDEqualObjects([expr name], @"expr"); + TDEqualObjects([expr class], [PKRuleNode class]); + TDEquals([[expr children] count], (NSUInteger)1); + + PKTokenNode *foo = [[expr children] objectAtIndex:0]; + TDEqualObjects([foo class], [PKTokenNode class]); + TDEqualObjects([foo token], [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:@"foo" floatValue:0.0]); +} + + +- (void)testFooBar { + g = @"@start = expr;" + @"expr = Word+;"; + lp = [factory parserFromGrammar:g assembler:as preassembler:as]; + + lp.tokenizer.string = @"foo bar"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp completeMatchFor:a]; + TDNotNil(res); + TDEqualObjects([res description], @"[]foo/bar^"); + + PKParseTree *tr = res.target; + TDEqualObjects([tr class], [PKParseTree class]); + TDEquals([[tr children] count], (NSUInteger)1); + + PKRuleNode *expr = [[tr children] objectAtIndex:0]; + TDEqualObjects([expr name], @"expr"); + TDEqualObjects([expr class], [PKRuleNode class]); + TDEquals([[expr children] count], (NSUInteger)2); + + PKTokenNode *foo = [[expr children] objectAtIndex:0]; + TDEqualObjects([foo class], [PKTokenNode class]); + TDEqualObjects([foo token], [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:@"foo" floatValue:0.0]); + + PKTokenNode *bar = [[expr children] objectAtIndex:1]; + TDEqualObjects([bar class], [PKTokenNode class]); + TDEqualObjects([bar token], [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:@"bar" floatValue:0.0]); +} + + +- (void)testArray { + g = @"@start = array;" + @"array = '[' Number (commaNumber)* ']';" + @"commaNumber = ',' Number;"; + + lp = [factory parserFromGrammar:g assembler:as preassembler:as]; + + lp.tokenizer.string = @"[1,2]"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp completeMatchFor:a]; + TDNotNil(res); + TDEqualObjects([res description], @"[][/1/,/2/]^"); + + PKRuleNode *root = res.target; + PKRuleNode *array = [[root children] objectAtIndex:0]; + + TDEqualObjects([array name], @"array"); + TDEqualObjects([array class], [PKRuleNode class]); + TDEquals([[array children] count], (NSUInteger)4); + + PKTokenNode *open = [[array children] objectAtIndex:0]; + TDEqualObjects([open class], [PKTokenNode class]); + TDEqualObjects([open token], [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"[" floatValue:0.0]); + + PKTokenNode *one = [[array children] objectAtIndex:1]; + TDEqualObjects([one class], [PKTokenNode class]); + TDEqualObjects([one token], [PKToken tokenWithTokenType:PKTokenTypeNumber stringValue:@"1" floatValue:1.0]); + + PKRuleNode *commaNumber = [[array children] objectAtIndex:2]; + TDEqualObjects([commaNumber name], @"commaNumber"); + TDEqualObjects([commaNumber class], [PKRuleNode class]); + TDEquals([[commaNumber children] count], (NSUInteger)2); + + PKTokenNode *close = [[array children] objectAtIndex:3]; + TDEqualObjects([close class], [PKTokenNode class]); + TDEqualObjects([close token], [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"]" floatValue:1.0]); +} + +@end diff --git a/test/TDParserBlocksTest.h b/test/TDParserBlocksTest.h new file mode 100644 index 0000000..627e17f --- /dev/null +++ b/test/TDParserBlocksTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDParserBlocksTest : SenTestCase { + PKAssembly *start; + NSString *s; + PKParser *p; +} + +@end diff --git a/test/TDParserBlocksTest.m b/test/TDParserBlocksTest.m new file mode 100644 index 0000000..af1fb9f --- /dev/null +++ b/test/TDParserBlocksTest.m @@ -0,0 +1,90 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDParserBlocksTest.h" + +@implementation TDParserBlocksTest + +- (void)setUp { +} + + +- (void)tearDown { +} + + +#ifdef TARGET_OS_SNOW_LEOPARD +- (void)testMath { + s = @"2 4 6 8"; + start = [PKTokenAssembly assemblyWithString:s]; + + PKNumber *n = [PKNumber number]; + p = [PKRepetition repetitionWithSubparser:n]; + + n.assemblerBlock = ^(PKAssembly *a) { + if (![a isStackEmpty]) { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; + } + }; + + p.assemblerBlock = ^(PKAssembly *a) { + NSNumber *total = [a pop]; + if (!total) { + total = [NSNumber numberWithFloat:0]; + } + + while (![a isStackEmpty]) { + NSNumber *n = [a pop]; + total = [NSNumber numberWithFloat:[total floatValue] + [n floatValue]]; + } + + [a push:total]; + }; + + PKAssembly *result = [p completeMatchFor:start]; + TDNotNil(result); + TDEqualObjects(@"[20]2/4/6/8^", [result description]); + TDEquals((double)20.0, [[result pop] doubleValue]); +} + + +- (void)testMath2 { + PKParser *addParser = [PKRepetition repetitionWithSubparser:[PKNumber number]]; + + addParser.assemblerBlock = ^(PKAssembly *a) { + NSArray *toks = [a objectsAbove:nil]; + double total = 0.0; + + for (PKToken *tok in toks) { + total += [tok floatValue]; + } + + [a push:[NSNumber numberWithDouble:total]]; + }; + + s = @"2.5 -5.5 8"; + +// NSNumber *result = [addParser parse:s]; +// NSAssert([result doubleValue] == 5.0, @""); + + start = [PKTokenAssembly assemblyWithString:s]; + PKAssembly *result = [addParser completeMatchFor:start]; + TDNotNil(result); + TDEqualObjects(@"[5]2.5/-5.5/8^", [result description]); + TDEquals(5.0, [(NSNumber *)[result pop] doubleValue]); +} +#endif + +@end diff --git a/test/TDParserFactoryPatternTest.h b/test/TDParserFactoryPatternTest.h new file mode 100644 index 0000000..509907f --- /dev/null +++ b/test/TDParserFactoryPatternTest.h @@ -0,0 +1,28 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" + +@interface TDParserFactoryPatternTest : SenTestCase { + NSString *g; + NSString *s; + PKTokenAssembly *a; + PKParserFactory *factory; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; +} + +@end diff --git a/test/TDParserFactoryPatternTest.m b/test/TDParserFactoryPatternTest.m new file mode 100644 index 0000000..c652dee --- /dev/null +++ b/test/TDParserFactoryPatternTest.m @@ -0,0 +1,90 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDParserFactoryPatternTest.h" + +@implementation TDParserFactoryPatternTest + +- (void)setUp { + factory = [PKParserFactory factory]; +} + + +- (void)test1 { + g = @"@start = /foo/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + + g = @"@start = /fo+/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + + g = @"@start = /fo+/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + + g = @"@start = /[fo]+/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + + g = @"@start = /\\w+/;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)testOptions { + g = @"@start = /foo/i;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"FOO"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[FOO]FOO^", [res description]); + + + g = @"@start = /foo/i;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"FoO"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[FoO]FoO^", [res description]); +} + +@end diff --git a/test/TDParserFactoryTest.h b/test/TDParserFactoryTest.h new file mode 100644 index 0000000..1d65617 --- /dev/null +++ b/test/TDParserFactoryTest.h @@ -0,0 +1,23 @@ +// +// PKParserFactoryTest.h +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf All rights reserved. +// + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" + +@interface TDParserFactoryTest : SenTestCase { + NSString *s; + PKTokenAssembly *a; + PKParserFactory *factory; + PKAssembly *res; + + PKSequence *exprSeq; + PKTokenizer *t; + PKParser *lp; // language parser +} + +@end diff --git a/test/TDParserFactoryTest.m b/test/TDParserFactoryTest.m new file mode 100644 index 0000000..1c863ae --- /dev/null +++ b/test/TDParserFactoryTest.m @@ -0,0 +1,1256 @@ +// +// PKParserFactoryTest.m +// ParseKit +// +// Created by Todd Ditchendorf on 12/12/08. +// Copyright 2009 Todd Ditchendorf All rights reserved. +// + +#import "TDParserFactoryTest.h" +#import + +@interface PKParserFactory () +- (PKTokenizer *)tokenizerForParsingGrammar; +- (PKSequence *)parserFromExpression:(NSString *)s; +@property (retain) PKCollectionParser *exprParser; +@end + +@protocol TDMockAssember +- (void)didMatchFoo:(PKAssembly *)a; +- (void)didMatchBaz:(PKAssembly *)a; +- (void)didMatchStart:(PKAssembly *)a; +- (void)didMatchStart:(PKAssembly *)a; +- (void)didMatch_Start:(PKAssembly *)a; +@end + +@implementation TDParserFactoryTest + +- (void)setUp { + factory = [PKParserFactory factory]; + PKSequence *seq = [PKSequence sequence]; + [seq add:factory.exprParser]; + exprSeq = seq; + t = [factory tokenizerForParsingGrammar]; +} + + +- (void)testJavaScript { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"javascript" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"var foo = 'bar';"; + lp.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; +// res = [lp bestMatchFor:a]; +// TDEqualObjects(@"[var, foo, =, 'bar', ;]var/foo/=/bar/;^", [res description]); +} + + +- (void)testCSS2_1 { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"css2_1" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + +// s = @"foo {font-size:12px}"; +// a = [PKTokenAssembly assemblyWithString:s]; +// res = [lp bestMatchFor:a]; +// TDEqualObjects(@"[foo, {, font-family, :, 'helvetica', ;, }]foo/{/font-family/:/'helvetica'/;/}^", [res description]); +} + + +- (void)testCSS { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + PKParser *selectorParser = [lp parserNamed:@"selector"]; + TDNotNil(selectorParser); + TDEqualObjects(selectorParser.name, @"selector"); + TDEqualObjects([selectorParser class], [PKLowercaseWord class]); + + PKParser *declParser = [lp parserNamed:@"decl"]; + TDNotNil(declParser); + TDEqualObjects(declParser.name, @"decl"); + TDEqualObjects([declParser class], [PKSequence class]); + + PKParser *rulesetParser = [lp parserNamed:@"ruleset"]; + TDNotNil(rulesetParser); + TDEqualObjects(rulesetParser, [(PKRepetition *)lp subparser]); + TDEqualObjects(rulesetParser.name, @"ruleset"); + TDEqualObjects([rulesetParser class], [PKSequence class]); + + PKParser *startParser = [lp parserNamed:@"@start"]; + TDNotNil(startParser); + TDEqualObjects(startParser, lp); + TDEqualObjects(startParser.name, @"@start"); + TDEqualObjects([startParser class], [PKRepetition class]); + + s = @"foo {font-family:'helvetica';}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, {, font-family, 'helvetica']foo/{/font-family/:/'helvetica'/;/}^", [res description]); + + s = @"foo {font-family:'helvetica'}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, {, font-family, 'helvetica']foo/{/font-family/:/'helvetica'/}^", [res description]); + + s = @"bar {color:rgb(1, 255, 255); font-size:13px;}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar, {, color, (, 1, 255, 255, font-size, 13]bar/{/color/:/rgb/(/1/,/255/,/255/)/;/font-size/:/13/px/;/}^", [res description]); + + s = @"bar {color:rgb(1, 255, 47.0); font-family:'Helvetica'}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar, {, color, (, 1, 255, 47.0, font-family, 'Helvetica']bar/{/color/:/rgb/(/1/,/255/,/47.0/)/;/font-family/:/'Helvetica'/}^", [res description]); + + s = @"foo {font-family:'Lucida Grande'} bar {color:rgb(1, 255, 255); font-size:9px;}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, {, font-family, 'Lucida Grande', bar, {, color, (, 1, 255, 255, font-size, 9]foo/{/font-family/:/'Lucida Grande'/}/bar/{/color/:/rgb/(/1/,/255/,/255/)/;/font-size/:/9/px/;/}^", [res description]); +} + + +- (void)testJSON { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"{'foo':'bar'}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', :, 'bar', }]{/'foo'/:/'bar'/}^", [res description]); + + s = @"{'foo':{}}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', :, {, }, }]{/'foo'/:/{/}/}^", [res description]); + + s = @"{'foo':{'bar':[]}}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', :, {, 'bar', :, [, ], }, }]{/'foo'/:/{/'bar'/:/[/]/}/}^", [res description]); + + s = @"['foo', true, null]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, 'foo', ,, true, ,, null, ]][/'foo'/,/true/,/null/]^", [res description]); + + s = @"[[]]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, [, ], ]][/[/]/]^", [res description]); + + s = @"[[[1]]]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, [, [, 1, ], ], ]][/[/[/1/]/]/]^", [res description]); +} + + +- (void)testJSONWithDiscards { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"json_with_discards" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"{'foo':'bar'}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', 'bar']{/'foo'/:/'bar'/}^", [res description]); + + s = @"{'foo':{}}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', {]{/'foo'/:/{/}/}^", [res description]); + + s = @"{'foo':{'bar':[]}}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', {, 'bar', []{/'foo'/:/{/'bar'/:/[/]/}/}^", [res description]); + + s = @"['foo', true, null]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, 'foo'][/'foo'/,/true/,/null/]^", [res description]); + + s = @"[[]]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, [][/[/]/]^", [res description]); + + s = @"[[[1]]]"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[[, [, [, 1][/[/[/1/]/]/]^", [res description]); +} + + +- (void)testStartLiteral { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = 'bar';"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralNonReserved { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo*; foo = 'bar';"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bar]bar/bar^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralNonReserved2 { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = (foo|baz)*; foo = 'bar'; baz = 'bat'"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + s = @"bar bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bat]bar/bat^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralNonReserved3 { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = (foo|baz)+; foo = 'bar'; baz = 'bat'"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + s = @"bar bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bat]bar/bat^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralNonReserved4 { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = (foo|baz)+; foo = 'bar'; baz = 'bat'"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + s = @"bar bat bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bat, bat]bar/bat/bat^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorDefault { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo = 'bar'; baz = 'bat'"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnAll { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo = 'bar'; baz = 'bat'"; + factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnAll; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); +// TDTrue(lp.assembler == mock); +// TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatch_Start:"); + +// [[mock expect] didMatch_Start:OCMOCK_ANY]; + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnTerminals { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo = 'bar'; baz = 'bat'"; + factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnTerminals; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDNil(lp.assembler); + TDNil(NSStringFromSelector(lp.assemblerSelector)); + + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnExplicit { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo (didMatchFoo:) = 'bar'; baz (didMatchBaz:) = 'bat'"; + factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnExplicit; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDNil(lp.assembler); + TDNil(NSStringFromSelector(lp.assemblerSelector)); + + [[mock expect] didMatchFoo:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnExplicitNone { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = foo|baz; foo = 'bar'; baz = 'bat'"; + factory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnExplicit; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDNil(lp.assembler); + TDNil(NSStringFromSelector(lp.assemblerSelector)); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testAssemblerSettingBehaviorOnExplicitOrTerminal { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start = (foo|baz)+; foo (didMatchFoo:) = 'bar'; baz = 'bat'"; + factory.assemblerSettingBehavior = (PKParserFactoryAssemblerSettingBehaviorOnExplicit | PKParserFactoryAssemblerSettingBehaviorOnTerminals); + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDNil(lp.assembler); + TDNil(NSStringFromSelector(lp.assemblerSelector)); + + [[mock expect] didMatchFoo:OCMOCK_ANY]; + [[mock expect] didMatchBaz:OCMOCK_ANY]; + s = @"bar bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp completeMatchFor:a]; + TDEqualObjects(@"[bar, bat]bar/bat^", [res description]); + [mock verify]; +} + + +- (void)testStartLiteralWithCallback { + id mock = [OCMockObject mockForProtocol:@protocol(TDMockAssember)]; + s = @"@start (didMatchStart:) = 'bar';"; + lp = [factory parserFromGrammar:s assembler:mock]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + TDEqualObjects(lp.name, @"@start"); + TDTrue(lp.assembler == mock); + TDEqualObjects(NSStringFromSelector(lp.assemblerSelector), @"didMatchStart:"); + + [[mock expect] didMatchStart:OCMOCK_ANY]; + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + [mock verify]; +} + + +- (void)testStartRefToLiteral { + s = @" @start = foo; foo = 'bar';"; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); +} + + +- (void)testStartRefToLiteral3 { + s = @" @start = foo|baz; baz = 'bat'; foo = 'bar';"; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); +} + + +- (void)testStartRefToLiteral2 { + s = @"foo = 'bar'; baz = 'bat'; @start = (foo | baz)*;"; + lp = [factory parserFromGrammar:s assembler:nil]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + + s = @"bat bat"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bat, bat]bat/bat^", [res description]); + + s = @"bat bat bat bat bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bat, bat, bat, bat, bar]bat/bat/bat/bat/bar^", [res description]); +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testStmtTrackException { + s = @"@start ="; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testCallbackTrackException { + s = @"@start ( = 'foo';"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start (foo: = 'foo'"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testSelectorTrackException { + s = @"@start (foo) = 'foo';"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testOrTrackException { + s = @"@start = 'foo'|;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +//- (void)testExprTrackException { +// s = @"@start=(foo;"; +// STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +//} + + +- (void)testIntersectionTrackException { + s = @"@start='foo' &;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testExclusionTrackException { + s = @"@start='foo' -;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testDelimitedStringTrackException { + s = @"@start=DelimitedString('/';"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start=DelimitedString('/', ;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} + + +- (void)testCardinalityTrackException { + s = @"@start='foo'{;"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start='foo'{};"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start='foo'{,};"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); + + s = @"@start='foo'{m};"; + STAssertThrowsSpecificNamed([factory parserFromGrammar:s assembler:nil], PKTrackException, PKTrackExceptionName, @""); +} +#endif + + +- (void)testExprHelloPlus { + s = @"'hello'+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello, hello]hello/hello^", [res description]); +} + + +- (void)testExprHelloStar { + s = @"'hello'*"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKRepetition class]); + + s = @"hello hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello, hello, hello]hello/hello/hello^", [res description]); +} + + +- (void)testExprHelloQuestion { + s = @"'hello'?"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKAlternation class]); + + s = @"hello hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello]hello^hello/hello", [res description]); +} + + +- (void)testExprOhHaiThereQuestion { + s = @"'oh'? 'hai'? 'there'?"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"there"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[there]there^", [res description]); +} + + +- (void)testExprFooBar { + s = @"'foo' 'bar'"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]'foo'/ /'bar'^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + TDEquals((NSUInteger)2, [seq.subparsers count]); + + PKLiteral *c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + c = [seq.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, bar]foo/bar^", [res description]); +} + + +- (void)testExprFooBarBaz { + s = @"'foo' 'bar' 'baz'"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]'foo'/ /'bar'/ /'baz'^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + TDEquals((NSUInteger)3, [seq.subparsers count]); + + PKLiteral *c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + c = [seq.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + c = [seq.subparsers objectAtIndex:2]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"baz", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [res description]); +} + + +- (void)testExprFooOrBar { + s = @"'foo'|'bar'"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]'foo'/|/'bar'^", [res description]); + + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKAlternation class]); + + s = @"bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^", [res description]); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)testExprFooOrBarStar { + s = @"'foo'|'bar'*"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]'foo'/|/'bar'/*^", [res description]); + + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + PKRepetition *rep = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKRepetition class], [rep class]); + c = (PKLiteral *)rep.subparser; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKAlternation class]]); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"foo foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^foo", [res description]); + + s = @"bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar, bar]bar/bar^", [res description]); +} + + +- (void)testExprFooOrBarPlus { + s = @"'foo'|'bar'+"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]'foo'/|/'bar'/+^", [res description]); + + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + PKSequence *seq = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKSequence class], [seq class]); + + c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + PKRepetition *rep = [seq.subparsers objectAtIndex:1]; + TDEqualObjects([PKRepetition class], [rep class]); + c = (PKLiteral *)rep.subparser; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKAlternation class]]); + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"foo foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^foo", [res description]); + + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^bar", [res description]); + + s = @"bar bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar, bar, bar]bar/bar/bar^", [res description]); +} + + +- (void)testExprFooOrBarQuestion { + s = @"'foo'|'bar'?"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]'foo'/|/'bar'/?^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + alt = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKAlternation class], [alt class]); + + PKEmpty *e = [alt.subparsers objectAtIndex:0]; + TDTrue([e isMemberOfClass:[PKEmpty class]]); + + c = (PKLiteral *)[alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKAlternation class]]); + s = @"bar bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^bar/bar", [res description]); + + s = @"foo bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^bar/bar", [res description]); +} + + +- (void)testExprParenFooOrBarParenStar { + s = @"('foo'|'bar')*"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Repetition](/'foo'/|/'bar'/)/*^", [res description]); + PKRepetition *rep = [res pop]; + TDTrue([rep isMemberOfClass:[PKRepetition class]]); + + PKAlternation *alt = (PKAlternation *)rep.subparser; + TDTrue([alt class] == [PKAlternation class]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKRepetition class]); + s = @"foo bar bar foo"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, bar, bar, foo]foo/bar/bar/foo^", [res description]); +} + + +- (void)testExprParenFooOrBooParenPlus { + s = @"('foo'|'bar')+"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence](/'foo'/|/'bar'/)/+^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + + TDEquals((NSUInteger)2, [seq.subparsers count]); + + PKAlternation *alt = [seq.subparsers objectAtIndex:0]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + PKRepetition *rep = [seq.subparsers objectAtIndex:1]; + TDTrue([rep isMemberOfClass:[PKRepetition class]]); + + alt = (PKAlternation *)rep.subparser; + TDEqualObjects([PKAlternation class], [alt class]); + + c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + s = @"foo foo bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo, foo, bar, bar]foo/foo/bar/bar^", [res description]); +} + + +- (void)testExprParenFooOrBarParenQuestion { + s = @"('foo'|'bar')?"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation](/'foo'/|/'bar'/)/?^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + + TDEquals((NSUInteger)2, [alt.subparsers count]); + PKEmpty *e = [alt.subparsers objectAtIndex:0]; + TDTrue([PKEmpty class] == [e class]); + + alt = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([alt class], [PKAlternation class]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKLiteral *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"foo", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isKindOfClass:[PKLiteral class]]); + TDEqualObjects(@"bar", c.string); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKAlternation class]); + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^bar", [res description]); + + s = @"bar bar"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[bar]bar^bar", [res description]); +} + + +- (void)testExprWord { + s = @"Word"; + t.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Word]Word^", [res description]); + PKWord *w = [res pop]; + TDTrue([w isMemberOfClass:[PKWord class]]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKWord class]); + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello]hello^hello", [res description]); +} + + +- (void)testExprWordPlus { + s = @"Word+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[hello, hello]hello/hello^", [res description]); +} + + +- (void)testExprNum { + s = @"Number"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Number]Number^", [res description]); + PKNumber *w = [res pop]; + TDTrue([w isMemberOfClass:[PKNumber class]]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKNumber class]]); + + s = @"333 444"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[333]333^444", [res description]); + + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDNil(res); +} + + +- (void)testExprNumCardinality { + s = @"Number{2}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]Number/{/2/}^", [res description]); + PKSequence *seq = [res pop]; + TDEqualObjects([seq class], [PKSequence class]); + + TDEquals((NSUInteger)2, [seq.subparsers count]); + PKNumber *n = [seq.subparsers objectAtIndex:0]; + TDEqualObjects([n class], [PKNumber class]); + + n = [seq.subparsers objectAtIndex:1]; + TDEqualObjects([n class], [PKNumber class]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + + s = @"333 444"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[333, 444]333/444^", [res description]); + + s = @"1.1 2.2 3.3"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[1.1, 2.2]1.1/2.2^3.3", [res description]); + + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDNil(res); +} + + +- (void)testExprNumCardinality2 { + s = @"Number{2,3}"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]Number/{/2/,/3/}^", [res description]); + PKSequence *seq = [res pop]; + TDEqualObjects([seq class], [PKSequence class]); + + TDEquals((NSUInteger)3, [seq.subparsers count]); + + PKNumber *n = [seq.subparsers objectAtIndex:0]; + TDEqualObjects([n class], [PKNumber class]); + + n = [seq.subparsers objectAtIndex:1]; + TDEqualObjects([n class], [PKNumber class]); + + n = [seq.subparsers objectAtIndex:2]; + TDEqualObjects([n class], [PKAlternation class]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSequence class]]); + + s = @"333 444"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[333, 444]333/444^", [res description]); + + s = @"1.1 2.2 3.3"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[1.1, 2.2, 3.3]1.1/2.2/3.3^", [res description]); + + s = @"1.1 2.2 3.3 4"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[1.1, 2.2, 3.3]1.1/2.2/3.3^4", [res description]); + + s = @"hello hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDNil(res); +} + + +- (void)testExprNumPlus { + s = @"Number+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + s = @"333 444"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[333, 444]333/444^", [res description]); +} + + +- (void)testExprSymbol { + s = @"Symbol"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Symbol]Symbol^", [res description]); + PKSymbol *w = [res pop]; + TDTrue([w isMemberOfClass:[PKSymbol class]]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKSymbol class]]); + + s = @"? #"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[?]?^#", [res description]); + + s = @"hello"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDNil(res); +} + + +- (void)testExprSymbolPlus { + s = @"Symbol+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + s = @"% *"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[%, *]%/*^", [res description]); +} + + +- (void)testExprQuotedString { + s = @"QuotedString"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [exprSeq bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[QuotedString]QuotedString^", [res description]); + PKQuotedString *w = [res pop]; + TDTrue([w isMemberOfClass:[PKQuotedString class]]); + + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + TDEqualObjects([lp class], [PKQuotedString class]); + s = @"'hello' 'hello'"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"['hello']'hello'^'hello'", [res description]); +} + + +- (void)testExprQuotedStringPlus { + s = @"QuotedString+"; + // use the result parser + lp = [factory parserFromExpression:s]; + TDNotNil(lp); + s = @"'hello' 'hello'"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"['hello', 'hello']'hello'/'hello'^", [res description]); +} + + +- (void)testRubyHash { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"rubyhash" ofType:@"grammar"]; + s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + lp = [factory parserFromGrammar:s assembler:nil]; + + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + +// s = @"{\"brand\"=>{\"name\"=>\"something\"," +// @"\"logo\"=>#," +// @"\"summary\"=>\"wee\", \"content\"=>\"woopy doo\"}, \"commit\"=>\"Save\"," +// @"\"authenticity_token\"=>\"43a94d60304a7fb13a4ff61a5960461ce714e92b\"," +// @"\"action\"=>\"create\", \"controller\"=>\"admin/brands\"}"; + + lp.tokenizer.string = @"{'foo'=> {'logo' => # } }"; + + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[{, 'foo', =>, {, 'logo', =>, #, }, }]{/'foo'/=>/{/'logo'/=>/#/}/}^", [res description]); +} + + +- (void)testSymbolState { + s = @"@symbolState = 'b'; @start = ('b'|'ar')*;"; + lp = [factory parserFromGrammar:s assembler:nil]; + + TDNotNil(lp); + TDTrue([lp isKindOfClass:[PKParser class]]); + + lp.tokenizer.string = @"bar"; + a = [PKTokenAssembly assemblyWithTokenizer:lp.tokenizer]; + res = [lp bestMatchFor:a]; + TDEqualObjects(@"[b, ar]b/ar^", [res description]); + [res pop]; // discar 'ar' + PKToken *tok = [res pop]; + TDEqualObjects([tok class], [PKToken class]); + TDEqualObjects(tok.stringValue, @"b"); + TDTrue(tok.isSymbol); +} + +@end \ No newline at end of file diff --git a/test/TDParserFactoryTest2.h b/test/TDParserFactoryTest2.h new file mode 100644 index 0000000..c694921 --- /dev/null +++ b/test/TDParserFactoryTest2.h @@ -0,0 +1,29 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "PKParserFactory.h" + +@interface TDParserFactoryTest2 : SenTestCase { + NSString *g; + NSString *s; + PKTokenAssembly *a; + PKParserFactory *factory; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; + PKToken *tok; +} + +@end diff --git a/test/TDParserFactoryTest2.m b/test/TDParserFactoryTest2.m new file mode 100644 index 0000000..97b058c --- /dev/null +++ b/test/TDParserFactoryTest2.m @@ -0,0 +1,710 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDParserFactoryTest2.h" + +@implementation TDParserFactoryTest2 + +- (void)setUp { + factory = [PKParserFactory factory]; +} + + +- (void)testOrVsAndPrecendence { + g = @"@start = Word | Number Symbol;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"foo %"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + g = @"@start = Word Number | Symbol;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo 3"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 3]foo/3^", [res description]); + + s = @"%"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[%]%^", [res description]); + + s = @"foo %"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + g = @"@start = Word (Number | Symbol);"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo 3"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 3]foo/3^", [res description]); + + s = @"foo"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + s = @"foo %"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, %]foo/%^", [res description]); +} + + +- (void)test1 { + g = @"@start = (Word | Number)*;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"24.5"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[24.5]24.5^", [res description]); + + s = @"foo bar 2 baz"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, baz]foo/bar/2/baz^", [res description]); + + s = @"foo bar 2 4 baz"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, 4, baz]foo/bar/2/4/baz^", [res description]); +} + + +- (void)test2 { + g = @"@start = (Word | Number)* QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 'bar']foo/'bar'^", [res description]); + + s = @"24.5 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[24.5, 'bar']24.5/'bar'^", [res description]); + + s = @"foo bar 2 baz 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, baz, 'bar']foo/bar/2/baz/'bar'^", [res description]); + + s = @"foo bar 2 4 baz 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, 4, baz, 'bar']foo/bar/2/4/baz/'bar'^", [res description]); +} + + +- (void)test3 { + g = @"@start = (Word | Number)* '$'+ QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, 'bar']foo/$/'bar'^", [res description]); + + s = @"foo $ $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, $, 'bar']foo/$/$/'bar'^", [res description]); + + s = @"24.5 $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[24.5, $, 'bar']24.5/$/'bar'^", [res description]); + + s = @"foo bar 2 baz $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, baz, $, 'bar']foo/bar/2/baz/$/'bar'^", [res description]); + + s = @"foo bar 2 4 baz $ 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, bar, 2, 4, baz, $, 'bar']foo/bar/2/4/baz/$/'bar'^", [res description]); +} + + +- (void)test4 { + g = @"@start = (Word | Number)* ('$' '%')+ QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, 'bar']foo/$/%/'bar'^", [res description]); + + s = @"foo $ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %, 'bar']foo/$/%/$/%/'bar'^", [res description]); +} + + +- (void)test5 { + g = @"@start = (Word | Number)* ('$' '%')+ QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, 'bar']foo/$/%/'bar'^", [res description]); + + s = @"foo $ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %, 'bar']foo/$/%/$/%/'bar'^", [res description]); + + s = @"foo 33 4 $ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 33, 4, $, %, $, %, 'bar']foo/33/4/$/%/$/%/'bar'^", [res description]); + + s = @"foo 33 bar 4 $ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 33, bar, 4, $, %, $, %, 'bar']foo/33/bar/4/$/%/$/%/'bar'^", [res description]); +} + + +- (void)test6 { + g = @"@start = ((Word | Number)* ('$' '%')+) | QuotedString;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar']'bar'^", [res description]); + + s = @"foo $ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %]foo/$/%/$/%^", [res description]); +} + + +- (void)test7 { + g = @"@start = ((Word | Number)* ('$' '%')+) | QuotedString+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"'bar' 'foo'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar', 'foo']'bar'/'foo'^", [res description]); + + s = @"foo $ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %]foo/$/%/$/%^", [res description]); + + s = @"$ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[$, %, $, %]$/%/$/%^", [res description]); +} + + +- (void)test8 { + g = @"@start = ((Word | Number)* ('$' '%')+) | QuotedString+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"'bar' 'foo'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar', 'foo']'bar'/'foo'^", [res description]); + + s = @"foo $ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, $, %, $, %]foo/$/%/$/%^", [res description]); + + s = @"$ % $ %"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[$, %, $, %]$/%/$/%^", [res description]); +} + + +- (void)test9 { + g = @"@start = Word | (Number);"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"42"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[42]42^", [res description]); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)test10 { + g = @"@start = Word | (Number QuotedString);"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + s = @"42 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[42, 'bar']42/'bar'^", [res description]); +} + + +- (void)test11 { + g = @"@start = ((Word | Number)* | ('$' '%')+) QuotedString+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo, 'bar']foo/'bar'^", [res description]); + + s = @"$ % $ % 'bar'"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[$, %, $, %, 'bar']$/%/$/%/'bar'^", [res description]); +} + + +- (void)test12 { + g = @"@delimitState = '$'; @delimitedString = '$' '%' nil; @start = DelimitedString('$', '%');"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"$foo%"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[$foo%]$foo%^", [res description]); + + + g = @"@delimitState = '$'; @delimitedString = '$' '%' nil; @start = DelimitedString('$', '');"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"$foo%"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[$foo%]$foo%^", [res description]); + + + g = @"@delimitState = '$'; @delimitedString = '$' '%' 'fo'; @start = DelimitedString('$', '%');"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"$foo%"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[$foo%]$foo%^", [res description]); + + + g = @"@delimitState = '$'; @delimitedString = '$' '%' 'f'; @start = DelimitedString('$', '%');"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"$foo%"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testWhitespace { + g = @"@reportsWhitespaceTokens = YES; @start = 'foo' S '+' S 'bar';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo + bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, , +, , bar]foo/ /+/ /bar^", [res description]); + + s = @"foo +bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + g = @"@start = 'foo' S '+' S 'bar';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo + bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + g = @"@reportsWhitespaceTokens = NO; @start = 'foo' S '+' S 'bar';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo + bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + + g = @"@reportsWhitespaceTokens = YES; @start = 'foo' S '+' S 'bar';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo \t \t + bar"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, \t \t , +, , bar]foo/ \t \t /+/ /bar^", [res description]); +} + + +- (void)testDiscard { + g = @"@start = 'foo'!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]foo^", [res description]); + + g = @"@start = /foo/!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]foo^", [res description]); + + g = @"@delimitState='<'; @delimitedStrings='<%' '%>' nil; @start=DelimitedString('<%', '%>')!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"<% foo %>"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]<% foo %>^", [res description]); +} + + +- (void)testDiscard2 { + g = @"@reportsWhitespaceTokens=YES;@start=S!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @" "; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[] ^", [res description]); + + g = @"@start=Any!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]foo^", [res description]); + + g = @"@start=Word!;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]foo^", [res description]); + +} + + +- (void)testComments { + g = + @"@commentState = '/';" + @"@singleLineComments = '//';" + @"@reportsCommentTokens = YES;" + @"@start = Any+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"# // foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[#, // foo]#/// foo^", [res description]); + + tok = [res pop]; + TDTrue(tok.isComment); + +} + + + +- (void)testFallbackState { + g = + @"@commentState = '/';" + @"@commentState.fallbackState = delimitState;" + @"@delimitedString = '/' '/' nil;" + @"@singleLineComments = '//';" + @"@multiLineComments = '/*' '*/';" + @"@start = Any+;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"/ %"; + t = lp.tokenizer; + + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, %]//%^", [res description]); + tok = [res pop]; + TDTrue(tok.isSymbol); + + s = @"/ /"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/ /]/ /^", [res description]); + tok = [res pop]; + TDTrue(tok.isDelimitedString); + + s = @"/foo/"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/foo/]/foo/^", [res description]); + tok = [res pop]; + TDTrue(tok.isDelimitedString); + + s = @"# // foo"; + t = lp.tokenizer; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[#]#^", [res description]); + tok = [res pop]; + TDTrue(tok.isSymbol); + +} + + +- (void)testPatternPredicate1 { + g = @"@wordChar = ':'; @start = Word;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"foo:bar"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo:bar]foo:bar^", [res description]); + tok = [res pop]; + TDTrue(tok.isWord); + + g = @"@wordChar = ':'; @start = Word & /[^:]+/;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + tok = [res pop]; + TDTrue(tok.isWord); + + s = @"foo:bar"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testPatternPredicate2 { + g = @"@wordChar = ':'; @start=ncName+; name=Word; ncName=name & /[^:]+/;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + tok = [res pop]; + TDTrue(tok.isWord); + + s = @"foo:bar"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testExclusionFoo { + g = @"@start = ex; ex = Word - 'foo';"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"bar"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[bar]bar^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[wee]wee^", [res description]); +} + + +- (void)testExclusionAlt { + g = @"@start = ex; m = ('foo'|'bar'); ex = Word - m;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[wee]wee^", [res description]); +} + + +- (void)testExclusionAlt2 { + g = @"@start = ex; ex = Word - ('foo'|'bar');"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[wee]wee^", [res description]); +} + + +- (void)testExclusionAlt3 { + g = @"@start = ex; s = 'foo'|'baz'; m = ('foo'|'bar'); ex = s - m;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testExclusionAlt4 { + g = @"@start = ex; m = ('foo'|'bar'); ex = ('foo'|'baz') - m;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + + +- (void)testExclusionAlt5 { + g = @"@start = ex; ex = ('foo'|'baz') - ('foo'|'bar');"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + s = @"baz"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[baz]baz^", [res description]); + + s = @"foo"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + s = @"wee"; + t.string = s; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); +} + +@end diff --git a/test/TDParserFactoryTest3.h b/test/TDParserFactoryTest3.h new file mode 100644 index 0000000..3adeefa --- /dev/null +++ b/test/TDParserFactoryTest3.h @@ -0,0 +1,28 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDParserFactoryTest3 : SenTestCase { + NSString *g; + NSString *s; + PKTokenAssembly *a; + PKParserFactory *factory; + PKAssembly *res; + PKParser *lp; // language parser + PKTokenizer *t; + PKToken *tok; +} + +@end diff --git a/test/TDParserFactoryTest3.m b/test/TDParserFactoryTest3.m new file mode 100644 index 0000000..b6a0dd0 --- /dev/null +++ b/test/TDParserFactoryTest3.m @@ -0,0 +1,182 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDParserFactoryTest3.h" + +@implementation TDParserFactoryTest3 + +- (void)setUp { + factory = [PKParserFactory factory]; +} + + +- (void)testOrVsAndPrecendence { + g = @" @start ( didMatchFoo: ) = foo;\n" + @" foo = Word & /foo/ | Number! { 1 } ( DelimitedString ( '/' , '/' ) Symbol- '%' ) * /bar/ ;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)testNegation { + g = @"@start = ~'foo';"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"foo"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + s = @"'bar'"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar']'bar'^", [res description]); + + s = @"bar"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[bar]bar^", [res description]); +} + + +- (void)testNegateSymbol { + g = @"@start = ~Symbol;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"1"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]1^", [res description]); + + s = @"'bar'"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"['bar']'bar'^", [res description]); + + s = @"bar"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[bar]bar^", [res description]); + + s = @"$"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + +} + + +- (void)testNegateMore { + g = @"@start = ~Symbol & ~Number;"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"1"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + s = @"$"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); +} + + +- (void)testNegateMore2 { + g = @"@start = ~(Symbol|Number);"; + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + + s = @"1"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); + + s = @"$"; + res = [lp completeMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDNil(res); +} + + +- (void)testNcName { + g = @"@wordChars=':' '_'; @wordState='_';" + @"@start = name;" + @"ncName = name & /[^:]+/;" + @"name = Word;"; + // @"nameTest = '*' | ncName ':' '*' | qName;" + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + t.string = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + t.string = @"foo:bar"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo:bar]foo:bar^", [res description]); +} + + +- (void)testFunctionName { + g = + @"@wordState = '_';" + @"@wordChars = '_' '.' '-';" + @"@start = functionName;" + @"functionName = qName - nodeType;" + @"nodeType = 'comment' | 'text' | 'processing-instruction' | 'node';" + @"qName = prefixedName | unprefixedName;" + @"prefixedName = prefix ':' localPart;" + @"unprefixedName = localPart;" + @"localPart = ncName;" + @"prefix = ncName;" + @"ncName = Word;"; + + lp = [factory parserFromGrammar:g assembler:nil]; + TDNotNil(lp); + t = lp.tokenizer; + + t.string = @"foo"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + t.string = @"foo:bar"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [res description]); + + t.string = @":bar"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"text"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"comment"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"node"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"processing-instruction"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNil(res); + + t.string = @"texts"; + res = [lp bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[texts]texts^", [res description]); + +} + +@end diff --git a/test/TDParserTest.h b/test/TDParserTest.h new file mode 100644 index 0000000..224d8b1 --- /dev/null +++ b/test/TDParserTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDParserTest : SenTestCase { + PKAssembly *a; + NSString *s; + PKParser *p; +} + +@end diff --git a/test/TDParserTest.m b/test/TDParserTest.m new file mode 100644 index 0000000..8d3eaa2 --- /dev/null +++ b/test/TDParserTest.m @@ -0,0 +1,183 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDParserTest.h" + +@implementation TDParserTest + +- (void)setUp { +} + + +- (void)tearDown { +} + + +#pragma mark - + +- (void)testMath { + s = @"2 4 6 8"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKRepetition repetitionWithSubparser:[PKNumber number]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[2, 4, 6, 8]2/4/6/8^", [result description]); +} + + +- (void)testMiniMath { + s = @"4.5 - 5.6 - 222.0"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKSequence *minusNum = [PKSequence sequence]; + [minusNum add:[[PKSymbol symbolWithString:@"-"] discard]]; + [minusNum add:[PKNumber number]]; + + PKSequence *e = [PKSequence sequence]; + [e add:[PKNumber number]]; + [e add:[PKRepetition repetitionWithSubparser:minusNum]]; + + PKAssembly *result = [e completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[4.5, 5.6, 222.0]4.5/-/5.6/-/222.0^", [result description]); +} + + +- (void)testMiniMathWithBrackets { + s = @"[4.5 - 5.6 - 222.0]"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKSequence *minusNum = [PKSequence sequence]; + [minusNum add:[[PKSymbol symbolWithString:@"-"] discard]]; + [minusNum add:[PKNumber number]]; + + PKSequence *e = [PKSequence sequence]; + [e add:[[PKSymbol symbolWithString:@"["] discard]]; + [e add:[PKNumber number]]; + [e add:[PKRepetition repetitionWithSubparser:minusNum]]; + [e add:[[PKSymbol symbolWithString:@"]"] discard]]; + + PKAssembly *result = [e completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[4.5, 5.6, 222.0][/4.5/-/5.6/-/222.0/]^", [result description]); +} + + +- (void)testHotHotSteamingHotCoffee { + PKAlternation *adjective = [PKAlternation alternation]; + [adjective add:[PKLiteral literalWithString:@"hot"]]; + [adjective add:[PKLiteral literalWithString:@"steaming"]]; + + PKRepetition *adjectives = [PKRepetition repetitionWithSubparser:adjective]; + + PKSequence *sentence = [PKSequence sequence]; + [sentence add:adjectives]; + [sentence add:[PKLiteral literalWithString:@"coffee"]]; + + s = @"hot hot steaming hot coffee"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKAssembly *result = [sentence bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[hot, hot, steaming, hot, coffee]hot/hot/steaming/hot/coffee^", [result description]); +} + + +- (void)testList { + PKAssembly *result = nil; + + PKSequence *commaTerm = [PKSequence sequence]; + [commaTerm add:[[PKSymbol symbolWithString:@","] discard]]; + [commaTerm add:[PKWord word]]; + + PKSequence *actualList = [PKSequence sequence]; + [actualList add:[PKWord word]]; + [actualList add:[PKRepetition repetitionWithSubparser:commaTerm]]; + + PKSequence *list = [PKSequence sequence]; + [list add:[[PKSymbol symbolWithString:@"["] discard]]; + [list add:actualList]; + [list add:[[PKSymbol symbolWithString:@"]"] discard]]; + + s = @"[foo, bar, baz]"; + a = [PKTokenAssembly assemblyWithString:s]; + + result = [list bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz][/foo/,/bar/,/baz/]^", [result description]); +} + + +- (void)testJavaScriptStatement { + s = @"123 'boo'"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKAlternation *literals = [PKAlternation alternation]; + [literals add:[PKQuotedString quotedString]]; + [literals add:[PKNumber number]]; + + PKAssembly *result = [literals bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[123]123^'boo'", [result description]); +} + + +- (void)testParserNamed { + + // seq = (foo|bar|seq) foo* w sy; + PKCollectionParser *seq = [PKSequence sequence]; + seq.name = @"seq"; + + PKCollectionParser *alt = [PKAlternation alternation]; + alt.name = @"alt"; + + PKParser *foo = [PKLiteral literalWithString:@"foo"]; + foo.name = @"w"; + [alt add:foo]; + + PKParser *bar = [PKLiteral literalWithString:@"bar"]; + bar.name = @"w"; + [alt add:bar]; + + [alt add:seq]; + + PKRepetition *r = [PKRepetition repetitionWithSubparser:foo]; + + PKWord *w = [PKWord word]; + w.name = @"w"; + + PKSymbol *sy = [PKSymbol symbol]; + sy.name = @"sy"; + + + [seq add:alt]; + [seq add:r]; + [seq add:w]; + [seq add:sy]; + + TDEquals(seq, [seq parserNamed:@"seq"]); + TDEquals(seq, [alt parserNamed:@"seq"]); + + TDEquals(alt, [seq parserNamed:@"alt"]); + TDEquals(w, [seq parserNamed:@"w"]); + TDEquals(sy, [seq parserNamed:@"sy"]); + + TDEquals(foo, [alt parserNamed:@"w"]); + TDEquals(foo, [r parserNamed:@"w"]); +} + +@end diff --git a/test/TDPatternTest.h b/test/TDPatternTest.h new file mode 100644 index 0000000..eaf2f7b --- /dev/null +++ b/test/TDPatternTest.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDPatternTest : SenTestCase { + PKTokenizer *t; + PKPattern *p; + PKIntersection *inter; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/TDPatternTest.m b/test/TDPatternTest.m new file mode 100644 index 0000000..3a7d575 --- /dev/null +++ b/test/TDPatternTest.m @@ -0,0 +1,245 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDPatternTest.h" + +@implementation TDPatternTest + +- (void)testFoo { + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"foo"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"foo"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"foo"]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKWord word]]; + + a = [inter completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"foo"]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKSymbol symbol]]; + + a = [inter completeMatchFor:a]; + + TDNil(a); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo+"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo*"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo{1,2}"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo{3,4}"]; + a = [p completeMatchFor:a]; + + TDNil(a); +} + + +- (void)testSlashFooSlash { + s = @"/foo/"; + + t = [PKTokenizer tokenizerWithString:s]; + [t setTokenizerState:t.quoteState from:'/' to:'/']; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + p = [PKPattern patternWithString:@"/foo/" options:PKPatternOptionsNone]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKQuotedString quotedString]]; + + a = [inter completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[/foo/]/foo/^"); + + t = [PKTokenizer tokenizerWithString:s]; + [t setTokenizerState:t.quoteState from:'/' to:'/']; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + p = [PKPattern patternWithString:@"/[^/]+/" options:PKPatternOptionsNone]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKQuotedString quotedString]]; + + a = [inter completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[/foo/]/foo/^"); +} + + +- (void)testAndOrOr { + s = @"and"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[and]and^"); + + s = @"and"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"an|or"]; + a = [p completeMatchFor:a]; + + TDNil(a); + + s = @"or"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"(and)|(or)"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[or]or^"); +} + + +- (void)testNotAnd { + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"[^and]+"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + s = @"and"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"[^(and)]"]; + a = [p completeMatchFor:a]; + + TDNil(a); +} + + +- (void)testInvertFoo { + s = @"foo"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"fo+"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[foo]foo^"); + + p = [PKNegation negationWithSubparser:p]; + a = [p completeMatchFor:a]; + + TDNil(a); +} + + +- (void)testInvertAndOrNotTrueFalse { + s = @"true"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or|not|true|false"]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[true]true^"); + + p = [PKNegation negationWithSubparser:p]; + a = [p completeMatchFor:a]; + + TDNil(a); + + s = @"TRUE"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or|not|true|false" options:PKPatternOptionsIgnoreCase]; + a = [p completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[TRUE]TRUE^"); + + p = [PKNegation negationWithSubparser:p]; + a = [p completeMatchFor:a]; + + TDNil(a); + + s = @"NOT"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or|not|true|false" options:PKPatternOptionsIgnoreCase]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKWord word]]; + + a = [inter completeMatchFor:a]; + + TDNotNil(a); + TDEqualObjects([a description], @"[NOT]NOT^"); + + p = [PKNegation negationWithSubparser:p]; + a = [p completeMatchFor:a]; + + TDNil(a); + + s = @"oR"; + a = [PKTokenAssembly assemblyWithString:s]; + p = [PKPattern patternWithString:@"and|or|not|true|false" options:PKPatternOptionsIgnoreCase]; + + inter = [PKIntersection intersection]; + [inter add:p]; + [inter add:[PKSymbol symbol]]; + + a = [inter completeMatchFor:a]; + + TDNil(a); +} + +@end diff --git a/test/TDPlistParser.h b/test/TDPlistParser.h new file mode 100644 index 0000000..6c5ed61 --- /dev/null +++ b/test/TDPlistParser.h @@ -0,0 +1,41 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDPlistParser : PKAlternation { + PKCollectionParser *dictParser; + PKCollectionParser *keyValuePairParser; + PKCollectionParser *arrayParser; + PKCollectionParser *commaValueParser; + PKCollectionParser *keyParser; + PKCollectionParser *valueParser; + PKCollectionParser *stringParser; + PKParser *numParser; + PKParser *nullParser; + PKToken *curly; + PKToken *paren; +} +- (id)parse:(NSString *)s; + +@property (nonatomic, retain) PKCollectionParser *dictParser; +@property (nonatomic, retain) PKCollectionParser *keyValuePairParser; +@property (nonatomic, retain) PKCollectionParser *arrayParser; +@property (nonatomic, retain) PKCollectionParser *commaValueParser; +@property (nonatomic, retain) PKCollectionParser *keyParser; +@property (nonatomic, retain) PKCollectionParser *valueParser; +@property (nonatomic, retain) PKCollectionParser *stringParser; +@property (nonatomic, retain) PKParser *numParser; +@property (nonatomic, retain) PKParser *nullParser; +@end diff --git a/test/TDPlistParser.m b/test/TDPlistParser.m new file mode 100644 index 0000000..3c3dcb9 --- /dev/null +++ b/test/TDPlistParser.m @@ -0,0 +1,322 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDPlistParser.h" +#import "NSString+ParseKitAdditions.h" + +//{ +// 0 = 0; +// dictKey = { +// bar = foo; +// }; +// 47 = 0; +// IntegerKey = 1; +// 47.7 = 0; +// = ; +// ArrayKey = ( +// "one one", +// two, +// three +// ); +// "Null Key" = ; +// emptyDictKey = { +// }; +// StringKey = String; +// "1.0" = 1; +// YESKey = 1; +// "NO Key" = 0; +//} + + +// dict = '{' dictContent '}' +// dictContent = keyValuePair* +// keyValuePair = key '=' value ';' +// key = num | string | null +// value = num | string | null | array | dict +// null = '' +// string = Word | QuotedString +// num = Number + +// array = '(' arrayContent ')' +// arrayContent = Empty | actualArray +// actualArray = value commaValue* +// commaValue = ',' value + +static NSString *kTDPlistNullString = @""; + +@interface PKParser (PKParserFactoryAdditionsFriend) +- (void)setTokenizer:(PKTokenizer *)t; +@end + +@interface PKCollectionParser () +@property (nonatomic, readwrite, retain) NSMutableArray *subparsers; +@end + +@interface TDPlistParser () +@property (nonatomic, retain) PKToken *curly; +@property (nonatomic, retain) PKToken *paren; +@end + +@implementation TDPlistParser + +- (id)init { + self = [super init]; + if (self != nil) { + + self.tokenizer = [PKTokenizer tokenizer]; + // add '' as a multichar symbol + [self.tokenizer.symbolState add:kTDPlistNullString]; + + self.curly = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"{" floatValue:0.]; + self.paren = [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"(" floatValue:0.]; + [self add:[PKEmpty empty]]; + [self add:self.arrayParser]; + [self add:self.dictParser]; + } + return self; +} + + +- (void)dealloc { + // avoid retain cycle leaks by releasing the subparsers of all collection parsers + dictParser.subparsers = nil; + keyValuePairParser.subparsers = nil; + arrayParser.subparsers = nil; + commaValueParser.subparsers = nil; + keyParser.subparsers = nil; + valueParser.subparsers = nil; + stringParser.subparsers = nil; + + self.tokenizer = nil; + self.dictParser = nil; + self.keyValuePairParser = nil; + self.arrayParser = nil; + self.commaValueParser = nil; + self.keyParser = nil; + self.valueParser = nil; + self.stringParser = nil; + self.numParser = nil; + self.nullParser = nil; + self.curly = nil; + self.paren = nil; + [super dealloc]; +} + + +- (id)parse:(NSString *)s { + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:self.tokenizer]; + + // parse + PKAssembly *res = [self completeMatchFor:a]; + + // pop the built result off the assembly's stack and return. + // this will be an array or a dictionary or nil + return [res pop]; +} + + +// dict = '{' dictContent '}' +// dictContent = keyValuePair* +- (PKCollectionParser *)dictParser { + if (!dictParser) { + self.dictParser = [PKTrack track]; + [dictParser add:[PKSymbol symbolWithString:@"{"]]; // dont discard. serves as fence + [dictParser add:[PKRepetition repetitionWithSubparser:self.keyValuePairParser]]; + [dictParser add:[[PKSymbol symbolWithString:@"}"] discard]]; + [dictParser setAssembler:self selector:@selector(didMatchDict:)]; + } + return dictParser; +} + + +// keyValuePair = key '=' value ';' +- (PKCollectionParser *)keyValuePairParser { + if (!keyValuePairParser) { + self.keyValuePairParser = [PKTrack track]; + [keyValuePairParser add:self.keyParser]; + [keyValuePairParser add:[[PKSymbol symbolWithString:@"="] discard]]; + [keyValuePairParser add:self.valueParser]; + [keyValuePairParser add:[[PKSymbol symbolWithString:@";"] discard]]; + } + return keyValuePairParser; +} + + +// array = '(' arrayContent ')' +// arrayContent = Empty | actualArray +// actualArray = value commaValue* +- (PKCollectionParser *)arrayParser { + if (!arrayParser) { + self.arrayParser = [PKTrack track]; + [arrayParser add:[PKSymbol symbolWithString:@"("]]; // dont discard. serves as fence + + PKAlternation *arrayContent = [PKAlternation alternation]; + [arrayContent add:[PKEmpty empty]]; + + PKSequence *actualArray = [PKSequence sequence]; + [actualArray add:self.valueParser]; + [actualArray add:[PKRepetition repetitionWithSubparser:self.commaValueParser]]; + + [arrayContent add:actualArray]; + [arrayParser add:arrayContent]; + [arrayParser add:[[PKSymbol symbolWithString:@")"] discard]]; + [arrayParser setAssembler:self selector:@selector(didMatchArray:)]; + } + return arrayParser; +} + + +// key = num | string | null +- (PKCollectionParser *)keyParser { + if (!keyParser) { + self.keyParser = [PKAlternation alternation]; + [keyParser add:self.numParser]; + [keyParser add:self.stringParser]; + [keyParser add:self.nullParser]; + } + return keyParser; +} + + +// value = num | string | null | array | dict +- (PKCollectionParser *)valueParser { + if (!valueParser) { + self.valueParser = [PKAlternation alternation]; + [valueParser add:self.arrayParser]; + [valueParser add:self.dictParser]; + [valueParser add:self.stringParser]; + [valueParser add:self.numParser]; + [valueParser add:self.nullParser]; + } + return valueParser; +} + + +- (PKCollectionParser *)commaValueParser { + if (!commaValueParser) { + self.commaValueParser = [PKSequence sequence]; + [commaValueParser add:[[PKSymbol symbolWithString:@","] discard]]; + [commaValueParser add:self.valueParser]; + } + return commaValueParser; +} + + +// string = QuotedString | Word +- (PKCollectionParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKAlternation alternation]; + + // we have to remove the quotes from QuotedString string values. so set an assembler method to do that + PKParser *quotedString = [PKQuotedString quotedString]; + [quotedString setAssembler:self selector:@selector(didMatchQuotedString:)]; + [stringParser add:quotedString]; + + // handle non-quoted string values (Words) in a separate assembler method for simplicity. + PKParser *word = [PKWord word]; + [word setAssembler:self selector:@selector(didMatchWord:)]; + [stringParser add:word]; + } + return stringParser; +} + + +- (PKParser *)numParser { + if (!numParser) { + self.numParser = [PKNumber number]; + [numParser setAssembler:self selector:@selector(didMatchNum:)]; + } + return numParser; +} + + +// null = '' +- (PKParser *)nullParser { + if (!nullParser) { + // thus must be a PKSymbol (not a PKLiteral) to match the resulting '' symbol tok + self.nullParser = [PKSymbol symbolWithString:kTDPlistNullString]; + [nullParser setAssembler:self selector:@selector(didMatchNull:)]; + } + return nullParser; +} + + +- (void)didMatchDict:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:self.curly]; + NSInteger count = [objs count]; + NSAssert1(0 == count % 2, @"in -%s, the assembly's stack's count should be a multiple of 2", _cmd); + + NSMutableDictionary *res = [NSMutableDictionary dictionaryWithCapacity:count / 2.]; + if (count) { + NSInteger i = 0; + for ( ; i < [objs count] - 1; i++) { + id value = [objs objectAtIndex:i++]; + id key = [objs objectAtIndex:i]; + [res setObject:value forKey:key]; + } + } + + [a pop]; // discard '{' tok + [a push:[[res copy] autorelease]]; +} + + +- (void)didMatchArray:(PKAssembly *)a { + NSArray *objs = [a objectsAbove:self.paren]; + NSMutableArray *res = [NSMutableArray arrayWithCapacity:[objs count]]; + + for (id obj in [objs reverseObjectEnumerator]) { + [res addObject:obj]; + } + + [a pop]; // discard '(' tok + [a push:[[res copy] autorelease]]; +} + + +- (void)didMatchQuotedString:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[tok.stringValue stringByTrimmingQuotes]]; +} + + +- (void)didMatchWord:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:tok.stringValue]; +} + + +- (void)didMatchNum:(PKAssembly *)a { + PKToken *tok = [a pop]; + [a push:[NSNumber numberWithFloat:tok.floatValue]]; +} + + +- (void)didMatchNull:(PKAssembly *)a { + [a pop]; // discard '' tok + [a push:[NSNull null]]; +} + +@synthesize dictParser; +@synthesize keyValuePairParser; +@synthesize arrayParser; +@synthesize commaValueParser; +@synthesize keyParser; +@synthesize valueParser; +@synthesize stringParser; +@synthesize numParser; +@synthesize nullParser; +@synthesize curly; +@synthesize paren; +@end diff --git a/test/TDPlistParserTest.h b/test/TDPlistParserTest.h new file mode 100644 index 0000000..81af3cd --- /dev/null +++ b/test/TDPlistParserTest.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "TDPlistParser.h" + +@interface TDPlistParserTest : SenTestCase { + TDPlistParser *p; + NSString *s; + PKTokenAssembly *a; + PKAssembly *res; +} + +@end diff --git a/test/TDPlistParserTest.m b/test/TDPlistParserTest.m new file mode 100644 index 0000000..385c5fd --- /dev/null +++ b/test/TDPlistParserTest.m @@ -0,0 +1,471 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDPlistParserTest.h" + +@implementation TDPlistParserTest + +- (void)setUp { + p = [[TDPlistParser alloc] init]; +} + + +- (void)tearDown { + [p release]; +} + + +- (void)testARealDict { + s = @" {" + @" ArrayKey = (" + @" one," + @" two," + @" three" + @" );" + @" FloatKey = 1;" + @" IntegerKey = 1;" + @" NOKey = 0;" + @" StringKey = String;" + @" YESKey = 1;" + @" }"; + + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + TDNotNil(res); + + id obj = [res pop]; + TDNotNil(obj); + TDTrue([obj isKindOfClass:[NSDictionary class]]); + TDEquals((NSUInteger)6, [obj count]); + + id arr = [obj objectForKey:@"ArrayKey"]; + TDNotNil(arr); + TDEquals((NSUInteger)3, [arr count]); + + id b = [obj objectForKey:@"YESKey"]; + TDNotNil(b); + TDEqualObjects([NSNumber numberWithInteger:1], b); +} + + +- (void)testARealDict2 { + //NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys: + // [NSNumber numberWithBool:NO], @"NO Key", + // [NSNumber numberWithBool:YES], @"YESKey", + // [NSNumber numberWithInteger:1], @"IntegerKey", + // [NSNumber numberWithFloat:1.0], @"1.0", + // [NSNumber numberWithInteger:0], @"0", + // [NSNumber numberWithInteger:0], [NSNumber numberWithInteger:47], + // [NSNumber numberWithInteger:0], [NSNumber numberWithFloat:47.7], + // @"String", @"StringKey", + // [NSNull null], @"Null Key", + // [NSNull null], [NSNull null], + // [NSDictionary dictionaryWithObject:@"foo" forKey:@"bar"], @"dictKey", + // [NSDictionary dictionary], @"emptyDictKey", + // [NSArray arrayWithObjects:@"one one", @"two", @"three", nil], @"ArrayKey", + // nil]; + //NSLog(@"%@", d); + + s = @"{" + @" 0 = 0;" + @" dictKey = {" + @" bar = foo;" + @" };" + @" 47 = 0;" + @" IntegerKey = 1;" + @" 47.7 = 0;" + @" = ;" + @" ArrayKey = (" + @" \"one one\"," + @" two," + @" three" + @" );" + @" \"Null Key\" = ;" + @" emptyDictKey = {" + @" };" + @" StringKey = String;" + @" \"1.0\" = 1;" + @" YESKey = 1;" + @" \"NO Key\" = 0;" + @"}"; + + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + TDNotNil(res); + + id obj = [res pop]; + TDNotNil(obj); + TDTrue([obj isKindOfClass:[NSDictionary class]]); + TDEquals((NSUInteger)13, [obj count]); + + id arr = [obj objectForKey:@"ArrayKey"]; + TDNotNil(arr); + TDEquals((NSUInteger)3, [arr count]); + + id b = [obj objectForKey:@"YESKey"]; + TDNotNil(b); + TDEqualObjects([NSNumber numberWithInteger:1], b); +} + + +- (void)testDictFooEqBar { + s = @"{foo = bar;}"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchDictionaryAssembly: has already executed. + id obj = [res pop]; // NSDictionary * + TDTrue([obj isKindOfClass:[NSDictionary class]]); + TDEquals((NSUInteger)1, [obj count]); + + TDEqualObjects(@"bar", [obj objectForKey:@"foo"]); +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testDictTrackFooEqBarMisingCurly { + s = @"{foo = bar;"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + STAssertThrowsSpecific([p.dictParser completeMatchFor:a], PKTrackException, @""); +} +#endif + + +- (void)testDictQuoteFooFooQuoteEqBarOneEq2 { + s = @"{\"foo foo\" = bar; 1 = 2.2;}"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.dictParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchDictionaryAssembly: has already executed. + id obj = [res pop]; // NSDictionary * + TDTrue([obj isKindOfClass:[NSDictionary class]]); + TDEquals((NSUInteger)2, [obj count]); + + TDEqualObjects(@"bar", [obj objectForKey:@"foo foo"]); + TDEqualObjects([NSNumber numberWithFloat:2.2], [obj objectForKey:[NSNumber numberWithInteger:1]]); +} + + +- (void)testKeyValuePairFooEqBar { + s = @"foo = bar;"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.keyValuePairParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchKeyValuePairAssembly: has already executed. + id value = [res pop]; // NSString * + id key = [res pop]; // NSString * + + TDTrue([key isKindOfClass:[NSString class]]); + TDEqualObjects(@"foo", key); + + TDTrue([value isKindOfClass:[NSString class]]); + TDEqualObjects(@"bar", value); +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testKeyValuePairTrackFooEqBarNoSemi { + s = @"foo = bar"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + STAssertThrowsSpecific([p.keyValuePairParser completeMatchFor:a], PKTrackException, @""); +} +#endif + + +- (void)testCommaValueComma1 { + s = @", 1"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.commaValueParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumberAssembly: has already executed. + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEquals((NSInteger)1, [obj integerValue]); +} + + +- (void)testCommaValueCommaFoo { + s = @", Foo"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.commaValueParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchWordAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"Foo", obj); +} + + +- (void)testCommaValueCommaQuoteFooSpaceBarQuote { + s = @", \"Foo Bar\""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.commaValueParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchQuotedStringAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"Foo Bar", obj); +} + + +- (void)testArrayEmptyArray { + s = @"()"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.arrayParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchArrayAssembly: has already executed. + id obj = [res pop]; // NSArray * + TDTrue([obj isKindOfClass:[NSArray class]]); + TDEquals((NSUInteger)0, [obj count]); +} + + +- (void)testArrayNumArray { + s = @"(1, 2, 3)"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.arrayParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchArrayAssembly: has already executed. + id obj = [res pop]; // NSArray * + TDTrue([obj isKindOfClass:[NSArray class]]); + TDEquals((NSUInteger)3, [obj count]); + TDEqualObjects([NSNumber numberWithInt:1], [obj objectAtIndex:0]); + TDEqualObjects([NSNumber numberWithInt:2], [obj objectAtIndex:1]); + TDEqualObjects([NSNumber numberWithInt:3], [obj objectAtIndex:2]); +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testArrayTrackNumArrayMissingParen { + s = @"(1, 2, 3"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + STAssertThrowsSpecific([p.arrayParser completeMatchFor:a], PKTrackException, @""); +} + + +- (void)testArrayTrackNumArrayMissingComma { + s = @"(1, 2 3)"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + STAssertThrowsSpecific([p.arrayParser completeMatchFor:a], PKTrackException, @""); +} +#endif + + +- (void)testNullLtNullGt { + s = @""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.nullParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNullAssembly: has already executed. + id obj = [res pop]; // NSNull * + TDTrue([obj isKindOfClass:[NSNull class]]); + TDEqualObjects([NSNull null], obj); +} + + +- (void)testNullQuoteLtNullGtQuote { + s = @"\"\""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.nullParser completeMatchFor:a]; + TDNil(res); +} + + +- (void)testStringQuote1Dot0Quote { + s = @"\"1.0\""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.stringParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchStringAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"1.0", obj); +} + + +- (void)testStringFoo { + s = @"foo"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.stringParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchStringAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"foo", obj); +} + + +- (void)testStringQuoteFooQuote { + s = @"\"foo\""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.stringParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchStringAssembly: has already executed. + id obj = [res pop]; // NSString * + TDTrue([obj isKindOfClass:[NSString class]]); + TDEqualObjects(@"foo", obj); +} + + +- (void)testNum1Dot0 { + s = @"1.0"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. 'floatness' has been lost + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"1", [obj stringValue]); + TDEquals((NSInteger)1, [obj integerValue]); + TDEquals((CGFloat)1.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNumMinus1Dot0 { + s = @"-1.0"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. 'floatness' has been lost + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"-1", [obj stringValue]); + TDEquals((NSInteger)-1, [obj integerValue]); + TDEquals((CGFloat)-1.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNumMinus1 { + s = @"-1"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"-1", [obj stringValue]); + TDEquals((NSInteger)-1, [obj integerValue]); + TDEquals((CGFloat)-1.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNum0 { + s = @"0"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"0", [obj stringValue]); + TDEquals((NSInteger)0, [obj integerValue]); + TDEquals((CGFloat)0.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNum0Dot0 { + s = @"0.0"; + a = [PKTokenAssembly assemblyWithString:s]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. 'floatness' has been lost + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"0", [obj stringValue]); + TDEquals((NSInteger)0, [obj integerValue]); + TDEquals((CGFloat)0.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNumMinus0Dot0 { + s = @"-0.0"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. 'floatness' has been lost + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"-0", [obj stringValue]); + TDEquals((NSInteger)-0, [obj integerValue]); + TDEquals((CGFloat)-0.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNum300 { + s = @"300"; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNotNil(res); + + // -didMatchNumAssembly: has already executed. + NSNumber *obj = [res pop]; + TDTrue([obj isKindOfClass:[NSNumber class]]); + TDEqualObjects(@"300", [obj stringValue]); + TDEquals((NSInteger)300, [obj integerValue]); + TDEquals((CGFloat)300.0, (CGFloat)[obj floatValue]); +} + + +- (void)testNumEmptyString { + s = @""; + p.tokenizer.string = s; + a = [PKTokenAssembly assemblyWithTokenizer:p.tokenizer]; + res = [p.numParser completeMatchFor:a]; + TDNil(res); +} + +@end diff --git a/test/TDPredicateEvaluator.h b/test/TDPredicateEvaluator.h new file mode 100644 index 0000000..6c55107 --- /dev/null +++ b/test/TDPredicateEvaluator.h @@ -0,0 +1,89 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@protocol TDPredicateEvaluatorDelegate +- (id)valueForAttributeKey:(NSString *)key; +- (CGFloat)floatForAttributeKey:(NSString *)key; +- (BOOL)boolForAttributeKey:(NSString *)key; +@end + +@interface TDPredicateEvaluator : NSObject { + id delegate; + PKCollectionParser *exprParser; + PKCollectionParser *orTermParser; + PKCollectionParser *termParser; + PKCollectionParser *andPrimaryExprParser; + PKCollectionParser *primaryExprParser; + PKCollectionParser *phraseParser; + PKCollectionParser *negatedPredicateParser; + PKCollectionParser *predicateParser; + PKCollectionParser *attrParser; + PKCollectionParser *tagParser; + PKCollectionParser *eqStringPredicateParser; + PKCollectionParser *eqNumberPredicateParser; + PKCollectionParser *eqBoolPredicateParser; + PKCollectionParser *neStringPredicateParser; + PKCollectionParser *neNumberPredicateParser; + PKCollectionParser *neBoolPredicateParser; + PKCollectionParser *gtPredicateParser; + PKCollectionParser *gteqPredicateParser; + PKCollectionParser *ltPredicateParser; + PKCollectionParser *lteqPredicateParser; + PKCollectionParser *beginswithPredicateParser; + PKCollectionParser *containsPredicateParser; + PKCollectionParser *endswithPredicateParser; + PKCollectionParser *matchesPredicateParser; + PKCollectionParser *valueParser; + PKCollectionParser *boolParser; + PKParser *trueParser; + PKParser *falseParser; + PKParser *stringParser; + PKParser *numberParser; +} +- (id)initWithDelegate:(id )d; +- (BOOL)evaluate:(NSString *)s; + +@property (nonatomic, retain) PKCollectionParser *exprParser; +@property (nonatomic, retain) PKCollectionParser *orTermParser; +@property (nonatomic, retain) PKCollectionParser *termParser; +@property (nonatomic, retain) PKCollectionParser *andPrimaryExprParser; +@property (nonatomic, retain) PKCollectionParser *primaryExprParser; +@property (nonatomic, retain) PKCollectionParser *phraseParser; +@property (nonatomic, retain) PKCollectionParser *negatedPredicateParser; +@property (nonatomic, retain) PKCollectionParser *predicateParser; +@property (nonatomic, retain) PKCollectionParser *attrParser; +@property (nonatomic, retain) PKCollectionParser *tagParser; +@property (nonatomic, retain) PKCollectionParser *eqStringPredicateParser; +@property (nonatomic, retain) PKCollectionParser *eqNumberPredicateParser; +@property (nonatomic, retain) PKCollectionParser *eqBoolPredicateParser; +@property (nonatomic, retain) PKCollectionParser *neStringPredicateParser; +@property (nonatomic, retain) PKCollectionParser *neNumberPredicateParser; +@property (nonatomic, retain) PKCollectionParser *neBoolPredicateParser; +@property (nonatomic, retain) PKCollectionParser *gtPredicateParser; +@property (nonatomic, retain) PKCollectionParser *gteqPredicateParser; +@property (nonatomic, retain) PKCollectionParser *ltPredicateParser; +@property (nonatomic, retain) PKCollectionParser *lteqPredicateParser; +@property (nonatomic, retain) PKCollectionParser *beginswithPredicateParser; +@property (nonatomic, retain) PKCollectionParser *containsPredicateParser; +@property (nonatomic, retain) PKCollectionParser *endswithPredicateParser; +@property (nonatomic, retain) PKCollectionParser *matchesPredicateParser; +@property (nonatomic, retain) PKCollectionParser *valueParser; +@property (nonatomic, retain) PKCollectionParser *boolParser; +@property (nonatomic, retain) PKParser *trueParser; +@property (nonatomic, retain) PKParser *falseParser; +@property (nonatomic, retain) PKParser *stringParser; +@property (nonatomic, retain) PKParser *numberParser; +@end diff --git a/test/TDPredicateEvaluator.m b/test/TDPredicateEvaluator.m new file mode 100644 index 0000000..eeca0f3 --- /dev/null +++ b/test/TDPredicateEvaluator.m @@ -0,0 +1,662 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDPredicateEvaluator.h" +#import "NSString+ParseKitAdditions.h" + +// expr = term orTerm* +// orTerm = 'or' term +// term = primaryExpr andPrimaryExpr* +// andPrimaryExpr = 'and' primaryExpr +// primaryExpr = phrase | '(' expression ')' +// phrase = predicate | negatedPredicate +// negatedPredicate = 'not' predicate +// predicate = bool | eqPredicate | nePredicate | gtPredicate | gteqPredicate | ltPredicate | lteqPredicate | beginswithPredicate | containsPredicate | endswithPredicate | matchesPredicate +// eqPredicate = attr '=' value +// nePredicate = attr '!=' value +// gtPredicate = attr '>' value +// gteqPredicate = attr '>=' value +// ltPredicate = attr '<' value +// lteqPredicate = attr '<=' value +// beginswithPredicate = attr 'beginswith' value +// containsPredicate = attr 'contains' value +// endswithPredicate = attr 'endswith' value +// matchesPredicate = attr 'matches' value + +// attr = tag | Word +// tag = '@' Word +// value = QuotedString | Number | bool +// bool = 'true' | 'false' + +@implementation TDPredicateEvaluator + +- (id)initWithDelegate:(id )d { + if (self = [super init]) { + delegate = d; + } + return self; +} + + +- (void)dealloc { + delegate = nil; + self.exprParser = nil; + self.orTermParser = nil; + self.termParser = nil; + self.andPrimaryExprParser = nil; + self.primaryExprParser = nil; + self.negatedPredicateParser = nil; + self.predicateParser = nil; + self.phraseParser = nil; + self.attrParser = nil; + self.tagParser = nil; + self.eqStringPredicateParser = nil; + self.eqNumberPredicateParser = nil; + self.eqBoolPredicateParser = nil; + self.neStringPredicateParser = nil; + self.neNumberPredicateParser = nil; + self.neBoolPredicateParser = nil; + self.gtPredicateParser = nil; + self.gteqPredicateParser = nil; + self.ltPredicateParser = nil; + self.lteqPredicateParser = nil; + self.beginswithPredicateParser = nil; + self.containsPredicateParser = nil; + self.endswithPredicateParser = nil; + self.matchesPredicateParser = nil; + self.valueParser = nil; + self.boolParser = nil; + self.trueParser = nil; + self.falseParser = nil; + self.stringParser = nil; + self.numberParser = nil; + [super dealloc]; +} + + +- (BOOL)evaluate:(NSString *)s { + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + return [[[self.exprParser completeMatchFor:a] pop] boolValue]; +} + + +// expression = term orTerm* +- (PKCollectionParser *)exprParser { + if (!exprParser) { + self.exprParser = [PKSequence sequence]; + [exprParser add:self.termParser]; + [exprParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + } + return exprParser; +} + + +// orTerm = 'or' term +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKSequence sequence]; + [orTermParser add:[[PKCaseInsensitiveLiteral literalWithString:@"or"] discard]]; + [orTermParser add:self.termParser]; + [orTermParser setAssembler:self selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// term = primaryExpr andPrimaryExpr* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + [termParser add:self.primaryExprParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.andPrimaryExprParser]]; + } + return termParser; +} + + +// andPrimaryExpr = 'and' primaryExpr +- (PKCollectionParser *)andPrimaryExprParser { + if (!andPrimaryExprParser) { + self.andPrimaryExprParser = [PKSequence sequence]; + [andPrimaryExprParser add:[[PKCaseInsensitiveLiteral literalWithString:@"and"] discard]]; + [andPrimaryExprParser add:self.primaryExprParser]; + [andPrimaryExprParser setAssembler:self selector:@selector(didMatchAnd:)]; + } + return andPrimaryExprParser; +} + + +// primaryExpr = phrase | '(' expression ')' +- (PKCollectionParser *)primaryExprParser { + if (!primaryExprParser) { + self.primaryExprParser = [PKAlternation alternation]; + [primaryExprParser add:self.phraseParser]; + + PKSequence *s = [PKSequence sequence]; + [s add:[[PKSymbol symbolWithString:@"("] discard]]; + [s add:self.exprParser]; + [s add:[[PKSymbol symbolWithString:@")"] discard]]; + + [primaryExprParser add:s]; + } + return primaryExprParser; +} + + +// phrase = predicate | negatedPredicate +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + self.phraseParser = [PKAlternation alternation]; + [phraseParser add:self.predicateParser]; + [phraseParser add:self.negatedPredicateParser]; + } + return phraseParser; +} + + +// negatedPredicate = 'not' predicate +- (PKCollectionParser *)negatedPredicateParser { + if (!negatedPredicateParser) { + self.negatedPredicateParser = [PKSequence sequence]; + [negatedPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"not"] discard]]; + [negatedPredicateParser add:self.predicateParser]; + [negatedPredicateParser setAssembler:self selector:@selector(didMatchNegatedValue:)]; + } + return negatedPredicateParser; +} + + +// predicate = bool | eqPredicate | nePredicate | gtPredicate | gteqPredicate | ltPredicate | lteqPredicate | beginswithPredicate | containsPredicate | endswithPredicate | matchesPredicate +- (PKCollectionParser *)predicateParser { + if (!predicateParser) { + self.predicateParser = [PKAlternation alternation]; + [predicateParser add:self.boolParser]; + [predicateParser add:self.eqStringPredicateParser]; + [predicateParser add:self.eqNumberPredicateParser]; + [predicateParser add:self.eqBoolPredicateParser]; + [predicateParser add:self.neStringPredicateParser]; + [predicateParser add:self.neNumberPredicateParser]; + [predicateParser add:self.neBoolPredicateParser]; + [predicateParser add:self.gtPredicateParser]; + [predicateParser add:self.gteqPredicateParser]; + [predicateParser add:self.ltPredicateParser]; + [predicateParser add:self.lteqPredicateParser]; + [predicateParser add:self.beginswithPredicateParser]; + [predicateParser add:self.containsPredicateParser]; + [predicateParser add:self.endswithPredicateParser]; + [predicateParser add:self.matchesPredicateParser]; + } + return predicateParser; +} + + +// attr = tag | Word +- (PKCollectionParser *)attrParser { + if (!attrParser) { + self.attrParser = [PKAlternation alternation]; + [attrParser add:self.tagParser]; + [attrParser add:[PKWord word]]; + [attrParser setAssembler:self selector:@selector(didMatchAttr:)]; + } + return attrParser; +} + + +// tag = '@' Word +- (PKCollectionParser *)tagParser { + if (!tagParser) { + self.tagParser = [PKSequence sequence]; + [tagParser add:[[PKSymbol symbolWithString:@"@"] discard]]; + [tagParser add:[PKWord word]]; + } + return tagParser; +} + + +// eqPredicate = attr '=' value +- (PKCollectionParser *)eqStringPredicateParser { + if (!eqStringPredicateParser) { + self.eqStringPredicateParser = [PKSequence sequence]; + [eqStringPredicateParser add:self.attrParser]; + [eqStringPredicateParser add:[[PKSymbol symbolWithString:@"="] discard]]; + [eqStringPredicateParser add:self.stringParser]; + [eqStringPredicateParser setAssembler:self selector:@selector(didMatchEqStringPredicate:)]; + } + return eqStringPredicateParser; +} + + +- (PKCollectionParser *)eqNumberPredicateParser { + if (!eqNumberPredicateParser) { + self.eqNumberPredicateParser = [PKSequence sequence]; + [eqNumberPredicateParser add:self.attrParser]; + [eqNumberPredicateParser add:[[PKSymbol symbolWithString:@"="] discard]]; + [eqNumberPredicateParser add:self.numberParser]; + [eqNumberPredicateParser setAssembler:self selector:@selector(didMatchEqNumberPredicate:)]; + } + return eqNumberPredicateParser; +} + + +- (PKCollectionParser *)eqBoolPredicateParser { + if (!eqBoolPredicateParser) { + self.eqBoolPredicateParser = [PKSequence sequence]; + [eqBoolPredicateParser add:self.attrParser]; + [eqBoolPredicateParser add:[[PKSymbol symbolWithString:@"="] discard]]; + [eqBoolPredicateParser add:self.boolParser]; + [eqBoolPredicateParser setAssembler:self selector:@selector(didMatchEqBoolPredicate:)]; + } + return eqBoolPredicateParser; +} + + +// nePredicate = attr '!=' value +- (PKCollectionParser *)neStringPredicateParser { + if (!neStringPredicateParser) { + self.neStringPredicateParser = [PKSequence sequence]; + [neStringPredicateParser add:self.attrParser]; + [neStringPredicateParser add:[[PKSymbol symbolWithString:@"!="] discard]]; + [neStringPredicateParser add:self.stringParser]; + [neStringPredicateParser setAssembler:self selector:@selector(didMatchNeStringPredicate:)]; + } + return neStringPredicateParser; +} + + +- (PKCollectionParser *)neNumberPredicateParser { + if (!neNumberPredicateParser) { + self.neNumberPredicateParser = [PKSequence sequence]; + [neNumberPredicateParser add:self.attrParser]; + [neNumberPredicateParser add:[[PKSymbol symbolWithString:@"!="] discard]]; + [neNumberPredicateParser add:self.numberParser]; + [neNumberPredicateParser setAssembler:self selector:@selector(didMatchNeNumberPredicate:)]; + } + return neNumberPredicateParser; +} + + +- (PKCollectionParser *)neBoolPredicateParser { + if (!neBoolPredicateParser) { + self.neBoolPredicateParser = [PKSequence sequence]; + [neBoolPredicateParser add:self.attrParser]; + [neBoolPredicateParser add:[[PKSymbol symbolWithString:@"!="] discard]]; + [neBoolPredicateParser add:self.boolParser]; + [neBoolPredicateParser setAssembler:self selector:@selector(didMatchNeBoolPredicate:)]; + } + return neBoolPredicateParser; +} + + +// gtPredicate = attr '>' value +- (PKCollectionParser *)gtPredicateParser { + if (!gtPredicateParser) { + self.gtPredicateParser = [PKSequence sequence]; + [gtPredicateParser add:self.attrParser]; + [gtPredicateParser add:[[PKSymbol symbolWithString:@">"] discard]]; + [gtPredicateParser add:self.valueParser]; + [gtPredicateParser setAssembler:self selector:@selector(didMatchGtPredicate:)]; + } + return gtPredicateParser; +} + + +// gteqPredicate = attr '>=' value +- (PKCollectionParser *)gteqPredicateParser { + if (!gteqPredicateParser) { + self.gteqPredicateParser = [PKSequence sequence]; + [gteqPredicateParser add:self.attrParser]; + [gteqPredicateParser add:[[PKSymbol symbolWithString:@">="] discard]]; + [gteqPredicateParser add:self.valueParser]; + [gteqPredicateParser setAssembler:self selector:@selector(didMatchGteqPredicate:)]; + } + return gteqPredicateParser; +} + + +// ltPredicate = attr '<' value +- (PKCollectionParser *)ltPredicateParser { + if (!ltPredicateParser) { + self.ltPredicateParser = [PKSequence sequence]; + [ltPredicateParser add:self.attrParser]; + [ltPredicateParser add:[[PKSymbol symbolWithString:@"<"] discard]]; + [ltPredicateParser add:self.valueParser]; + [ltPredicateParser setAssembler:self selector:@selector(didMatchLtPredicate:)]; + } + return ltPredicateParser; +} + + +// lteqPredicate = attr '<=' value +- (PKCollectionParser *)lteqPredicateParser { + if (!lteqPredicateParser) { + self.lteqPredicateParser = [PKSequence sequence]; + [lteqPredicateParser add:self.attrParser]; + [lteqPredicateParser add:[[PKSymbol symbolWithString:@"<="] discard]]; + [lteqPredicateParser add:self.valueParser]; + [lteqPredicateParser setAssembler:self selector:@selector(didMatchLteqPredicate:)]; + } + return lteqPredicateParser; +} + + +// beginswithPredicate = attr 'beginswith' value +- (PKCollectionParser *)beginswithPredicateParser { + if (!beginswithPredicateParser) { + self.beginswithPredicateParser = [PKSequence sequence]; + [beginswithPredicateParser add:self.attrParser]; + [beginswithPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"beginswith"] discard]]; + [beginswithPredicateParser add:self.valueParser]; + [beginswithPredicateParser setAssembler:self selector:@selector(didMatchBeginswithPredicate:)]; + } + return beginswithPredicateParser; +} + + +// containsPredicate = attr 'contains' value +- (PKCollectionParser *)containsPredicateParser { + if (!containsPredicateParser) { + self.containsPredicateParser = [PKSequence sequence]; + [containsPredicateParser add:self.attrParser]; + [containsPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"contains"] discard]]; + [containsPredicateParser add:self.valueParser]; + [containsPredicateParser setAssembler:self selector:@selector(didMatchContainsPredicate:)]; + } + return containsPredicateParser; +} + + +// endswithPredicate = attr 'endswith' value +- (PKCollectionParser *)endswithPredicateParser { + if (!endswithPredicateParser) { + self.endswithPredicateParser = [PKSequence sequence]; + [endswithPredicateParser add:self.attrParser]; + [endswithPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"endswith"] discard]]; + [endswithPredicateParser add:self.valueParser]; + [endswithPredicateParser setAssembler:self selector:@selector(didMatchEndswithPredicate:)]; + } + return endswithPredicateParser; +} + + +// matchesPredicate = attr 'matches' value +- (PKCollectionParser *)matchesPredicateParser { + if (!matchesPredicateParser) { + self.matchesPredicateParser = [PKSequence sequence]; + [matchesPredicateParser add:self.attrParser]; + [matchesPredicateParser add:[[PKCaseInsensitiveLiteral literalWithString:@"matches"] discard]]; + [matchesPredicateParser add:self.valueParser]; + [matchesPredicateParser setAssembler:self selector:@selector(didMatchMatchesPredicate:)]; + } + return matchesPredicateParser; +} + + +// value = QuotedString | Number | bool +- (PKCollectionParser *)valueParser { + if (!valueParser) { + self.valueParser = [PKAlternation alternation]; + [valueParser add:self.stringParser]; + [valueParser add:self.numberParser]; + [valueParser add:self.boolParser]; + } + return valueParser; +} + + +- (PKCollectionParser *)boolParser { + if (!boolParser) { + self.boolParser = [PKAlternation alternation]; + [boolParser add:self.trueParser]; + [boolParser add:self.falseParser]; + [boolParser setAssembler:self selector:@selector(didMatchBool:)]; + } + return boolParser; +} + + +- (PKParser *)trueParser { + if (!trueParser) { + self.trueParser = [[PKCaseInsensitiveLiteral literalWithString:@"true"] discard]; + [trueParser setAssembler:self selector:@selector(didMatchTrue:)]; + } + return trueParser; +} + + +- (PKParser *)falseParser { + if (!falseParser) { + self.falseParser = [[PKCaseInsensitiveLiteral literalWithString:@"false"] discard]; + [falseParser setAssembler:self selector:@selector(didMatchFalse:)]; + } + return falseParser; +} + + +- (PKParser *)stringParser { + if (!stringParser) { + self.stringParser = [PKQuotedString quotedString]; + [stringParser setAssembler:self selector:@selector(didMatchString:)]; + } + return stringParser; +} + + +- (PKParser *)numberParser { + if (!numberParser) { + self.numberParser = [PKNumber number]; + [numberParser setAssembler:self selector:@selector(didMatchNumber:)]; + } + return numberParser; +} + + +- (void)didMatchAnd:(PKAssembly *)a { + NSNumber *b2 = [a pop]; + NSNumber *b1 = [a pop]; + BOOL yn = ([b1 boolValue] && [b2 boolValue]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchOr:(PKAssembly *)a { + NSNumber *b2 = [a pop]; + NSNumber *b1 = [a pop]; + BOOL yn = ([b1 boolValue] || [b2 boolValue]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchEqStringPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [[delegate valueForAttributeKey:attrKey] isEqual:value]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchEqNumberPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [value isEqualToNumber:[delegate valueForAttributeKey:attrKey]]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchEqBoolPredicate:(PKAssembly *)a { + NSNumber *b = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = ([delegate boolForAttributeKey:attrKey] == [b boolValue]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchNeStringPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + + BOOL yn = ![[delegate valueForAttributeKey:attrKey] isEqual:value]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchNeNumberPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = ![value isEqualToNumber:[delegate valueForAttributeKey:attrKey]]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchNeBoolPredicate:(PKAssembly *)a { + NSNumber *b = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = ([delegate boolForAttributeKey:attrKey] != [b boolValue]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchGtPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = (NSOrderedDescending == [[delegate valueForAttributeKey:attrKey] compare:value]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchGteqPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = (NSOrderedAscending != [[delegate valueForAttributeKey:attrKey] compare:value]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchLtPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = (NSOrderedAscending == [[delegate valueForAttributeKey:attrKey] compare:value]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchLteqPredicate:(PKAssembly *)a { + NSNumber *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = (NSOrderedDescending != [[delegate valueForAttributeKey:attrKey] compare:value]); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchBeginswithPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [[delegate valueForAttributeKey:attrKey] hasPrefix:value]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchContainsPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + NSRange r = [[delegate valueForAttributeKey:attrKey] rangeOfString:value]; + BOOL yn = (NSNotFound != r.location); + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchEndswithPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [[delegate valueForAttributeKey:attrKey] hasSuffix:value]; + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchMatchesPredicate:(PKAssembly *)a { + NSString *value = [a pop]; + NSString *attrKey = [a pop]; + BOOL yn = [[delegate valueForAttributeKey:attrKey] isEqual:value]; // TODO should this be a regex match? + [a push:[NSNumber numberWithBool:yn]]; +} + + +- (void)didMatchAttr:(PKAssembly *)a { + [a push:[[a pop] stringValue]]; +} + + +- (void)didMatchNegatedValue:(PKAssembly *)a { + NSNumber *b = [a pop]; + [a push:[NSNumber numberWithBool:![b boolValue]]]; +} + + +- (void)didMatchBool:(PKAssembly *)a { + NSNumber *b = [a pop]; + [a push:[NSNumber numberWithBool:[b boolValue]]]; +} + + +- (void)didMatchTrue:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:YES]]; +} + + +- (void)didMatchFalse:(PKAssembly *)a { + [a push:[NSNumber numberWithBool:NO]]; +} + + +- (void)didMatchString:(PKAssembly *)a { + NSString *s = [[[a pop] stringValue] stringByTrimmingQuotes]; + [a push:s]; +} + + +- (void)didMatchNumber:(PKAssembly *)a { + NSNumber *b = [NSNumber numberWithFloat:[(PKToken *)[a pop] floatValue]]; + [a push:b]; +} + +@synthesize exprParser; +@synthesize orTermParser; +@synthesize termParser; +@synthesize andPrimaryExprParser; +@synthesize primaryExprParser; +@synthesize phraseParser; +@synthesize negatedPredicateParser; +@synthesize predicateParser; +@synthesize attrParser; +@synthesize tagParser; +@synthesize eqStringPredicateParser; +@synthesize eqNumberPredicateParser; +@synthesize eqBoolPredicateParser; +@synthesize neStringPredicateParser; +@synthesize neNumberPredicateParser; +@synthesize neBoolPredicateParser; +@synthesize gtPredicateParser; +@synthesize gteqPredicateParser; +@synthesize ltPredicateParser; +@synthesize lteqPredicateParser; +@synthesize beginswithPredicateParser; +@synthesize containsPredicateParser; +@synthesize endswithPredicateParser; +@synthesize matchesPredicateParser; +@synthesize valueParser; +@synthesize boolParser; +@synthesize trueParser; +@synthesize falseParser; +@synthesize stringParser; +@synthesize numberParser; +@end diff --git a/test/TDPredicateEvaluatorTest.h b/test/TDPredicateEvaluatorTest.h new file mode 100644 index 0000000..48dd14d --- /dev/null +++ b/test/TDPredicateEvaluatorTest.h @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "TDPredicateEvaluator.h" + +@interface TDPredicateEvaluatorTest : SenTestCase { + TDPredicateEvaluator *p; + NSString *s; + PKAssembly *a; + + NSMutableDictionary *d; +} + +@end diff --git a/test/TDPredicateEvaluatorTest.m b/test/TDPredicateEvaluatorTest.m new file mode 100644 index 0000000..5d122f7 --- /dev/null +++ b/test/TDPredicateEvaluatorTest.m @@ -0,0 +1,309 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDPredicateEvaluatorTest.h" + +@implementation TDPredicateEvaluatorTest + +- (id)valueForAttributeKey:(NSString *)key { + return [d objectForKey:key]; +} + + +- (CGFloat)floatForAttributeKey:(NSString *)key { + return [(NSNumber *)[d objectForKey:key] floatValue]; +} + + +- (BOOL)boolForAttributeKey:(NSString *)key { + return [[d objectForKey:key] boolValue]; +} + + +- (void)setUp { + d = [NSMutableDictionary dictionary]; + p = [[[TDPredicateEvaluator alloc] initWithDelegate:self] autorelease]; +} + + +- (void)testEq { + // test numbers + [d setValue:[NSNumber numberWithFloat:1.0] forKey:@"foo"]; + s = @"foo = 1.0"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/=/1.0^", [a description]); + + s = @"foo = -1.0"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/=/-1.0^", [a description]); + + + // test bools + [d setValue:[NSNumber numberWithBool:YES] forKey:@"foo"]; + s = @"foo = true"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/=/true^", [a description]); + + s = @"foo = false"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/=/false^", [a description]); + + [d setValue:[NSNumber numberWithBool:NO] forKey:@"foo"]; + s = @"foo = true"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/=/true^", [a description]); + + s = @"foo = false"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/=/false^", [a description]); + + + // test strings + [d setValue:@"bar" forKey:@"foo"]; + s = @"foo = 'bar'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/=/'bar'^", [a description]); + + s = @"foo = 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/=/'baz'^", [a description]); +} + + +- (void)testNe { + // test numbers + [d setValue:[NSNumber numberWithFloat:1.0] forKey:@"foo"]; + s = @"foo != 1.0"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/!=/1.0^", [a description]); + + s = @"foo != -1.0"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/!=/-1.0^", [a description]); + + + // test bools + [d setValue:[NSNumber numberWithBool:YES] forKey:@"foo"]; + s = @"foo != true"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/!=/true^", [a description]); + + s = @"foo != false"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/!=/false^", [a description]); + + [d setValue:[NSNumber numberWithBool:NO] forKey:@"foo"]; + s = @"foo != true"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/!=/true^", [a description]); + + s = @"foo != false"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/!=/false^", [a description]); + + + // test strings + [d setValue:@"bar" forKey:@"foo"]; + s = @"foo != 'bar'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/!=/'bar'^", [a description]); + + s = @"foo != 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/!=/'baz'^", [a description]); +} + + +- (void)testGt { + [d setValue:[NSNumber numberWithInteger:41] forKey:@"foo"]; + s = @"foo > 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/>/42^", [a description]); + + [d setValue:[NSNumber numberWithInteger:43] forKey:@"foo"]; + s = @"foo > 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/>/42^", [a description]); + + [d setValue:[NSNumber numberWithFloat:1.2] forKey:@"foo"]; + s = @"foo > 1.2"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/>/1.2^", [a description]); + + [d setValue:[NSNumber numberWithFloat:1.2001] forKey:@"foo"]; + s = @"foo > 1.2"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/>/1.2^", [a description]); +} + + +- (void)testLt { + [d setValue:[NSNumber numberWithInteger:41] forKey:@"foo"]; + s = @"foo < .3"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/= 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/>=/42^", [a description]); + + [d setValue:[NSNumber numberWithFloat:41.99] forKey:@"foo"]; + s = @"foo >= 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/>=/42^", [a description]); + + [d setValue:[NSNumber numberWithInteger:42] forKey:@"foo"]; + s = @"foo >= 42"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/>=/42^", [a description]); +} + + +- (void)testLteq { + [d setValue:[NSNumber numberWithInteger:41] forKey:@"foo"]; + s = @"foo <= .3"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/<=/.3^", [a description]); + + [d setValue:[NSNumber numberWithFloat:.3] forKey:@"foo"]; + s = @"foo <= .3"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/<=/.3^", [a description]); + + [d setValue:[NSNumber numberWithFloat:.3111] forKey:@"foo"]; + s = @"foo <= .3"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/<=/.3^", [a description]); +} + + +- (void)testBeginswith { + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo beginswith 'foo'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/beginswith/'foo'^", [a description]); + + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo beginswith 'bar'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/beginswith/'bar'^", [a description]); +} + + +- (void)testContains { + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo contains 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/contains/'baz'^", [a description]); + + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo contains 'bat'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/contains/'bat'^", [a description]); +} + + +- (void)testEndswith { + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo endswith 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[1]foo/endswith/'baz'^", [a description]); + + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo endswith 'bat'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/endswith/'bat'^", [a description]); +} + + +- (void)testMatches { + [d setValue:@"foobarbaz" forKey:@"foo"]; + s = @"foo matches 'baz'"; + a = [p.exprParser bestMatchFor:[PKTokenAssembly assemblyWithString:s]]; + TDEqualObjects(@"[0]foo/matches/'baz'^", [a description]); +} + + +- (void)testBools { + s = @"true"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[1]true^", [a description]); + + s = @"not true"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]not/true^", [a description]); + + s = @"false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]false^", [a description]); + + s = @"not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[1]not/false^", [a description]); + + s = @"true and false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]true/and/false^", [a description]); + + s = @"not true and false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]not/true/and/false^", [a description]); + + s = @"not true and not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0]not/true/and/not/false^", [a description]); + + s = @"true or false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[1]true/or/false^", [a description]); + + s = @"(true and false) or false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[0](/true/and/false/)/or/false^", [a description]); + + s = @"(true and false) or not false"; + a = [PKTokenAssembly assemblyWithString:s]; + a = [p.exprParser bestMatchFor:a]; + TDEqualObjects(@"[1](/true/and/false/)/or/not/false^", [a description]); +} + +@end diff --git a/test/TDQuoteStateTest.h b/test/TDQuoteStateTest.h new file mode 100644 index 0000000..0e62403 --- /dev/null +++ b/test/TDQuoteStateTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + + +@interface TDQuoteStateTest : SenTestCase { + PKQuoteState *quoteState; + PKReader *r; + NSString *s; +} +@end diff --git a/test/TDQuoteStateTest.m b/test/TDQuoteStateTest.m new file mode 100644 index 0000000..88b21cd --- /dev/null +++ b/test/TDQuoteStateTest.m @@ -0,0 +1,110 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDQuoteStateTest.h" + + +@implementation TDQuoteStateTest + +- (void)setUp { + quoteState = [[PKQuoteState alloc] init]; + r = [[PKReader alloc] init]; +} + + +- (void)tearDown { + [quoteState release]; + [r release]; +} + + +- (void)testQuotedString { + s = @"'stuff'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + +} + + +- (void)testQuotedStringEOFTerminated { + s = @"'stuff"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); +} + + +- (void)testQuotedStringRepairEOFTerminated { + s = @"'stuff"; + r.string = s; + quoteState.balancesEOFTerminatedQuotes = YES; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"'stuff'", tok.stringValue); +} + + +- (void)testQuotedStringPlus { + s = @"'a quote here' more"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"'a quote here'", tok.stringValue); +} + + +- (void)test14CharQuotedString { + s = @"'123456789abcef'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + + +- (void)test15CharQuotedString { + s = @"'123456789abcefg'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + + +- (void)test16CharQuotedString { + s = @"'123456789abcefgh'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + + +- (void)test31CharQuotedString { + s = @"'123456789abcefgh123456789abcefg'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + + +- (void)test32CharQuotedString { + s = @"'123456789abcefgh123456789abcefgh'"; + r.string = s; + PKToken *tok = [quoteState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDTrue(tok.isQuotedString); +} + +@end diff --git a/test/TDReaderTest.h b/test/TDReaderTest.h new file mode 100644 index 0000000..50ff128 --- /dev/null +++ b/test/TDReaderTest.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDReaderTest : SenTestCase { + PKReader *reader; + NSString *string; +} + +@end diff --git a/test/TDReaderTest.m b/test/TDReaderTest.m new file mode 100644 index 0000000..5effaf6 --- /dev/null +++ b/test/TDReaderTest.m @@ -0,0 +1,84 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDReaderTest.h" + + +@implementation TDReaderTest + +- (void)setUp { + string = @"abcdefghijklmnopqrstuvwxyz"; + [string retain]; + reader = [[PKReader alloc] initWithString:string]; +} + + +- (void)tearDown { + [string release]; + [reader release]; +} + + +#pragma mark - + +- (void)testReadCharsMatch { + TDNotNil(reader); + NSInteger len = [string length]; + PKUniChar c; + NSInteger i = 0; + for ( ; i < len; i++) { + c = [string characterAtIndex:i]; + TDEquals(c, [reader read]); + } +} + + +- (void)testReadTooFar { + NSInteger len = [string length]; + NSInteger i = 0; + for ( ; i < len; i++) { + [reader read]; + } + TDEquals(PKEOF, [reader read]); +} + + +- (void)testUnread { + [reader read]; + [reader unread]; + PKUniChar a = 'a'; + TDEquals(a, [reader read]); + + [reader read]; + [reader read]; + [reader unread]; + PKUniChar c = 'c'; + TDEquals(c, [reader read]); +} + + +- (void)testUnreadTooFar { + [reader unread]; + PKUniChar a = 'a'; + TDEquals(a, [reader read]); + + [reader unread]; + [reader unread]; + [reader unread]; + [reader unread]; + PKUniChar a2 = 'a'; + TDEquals(a2, [reader read]); +} + +@end diff --git a/test/TDRegularParser.h b/test/TDRegularParser.h new file mode 100644 index 0000000..7a5e21b --- /dev/null +++ b/test/TDRegularParser.h @@ -0,0 +1,41 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDRegularParser : PKSequence { + PKCollectionParser *expressionParser; + PKCollectionParser *termParser; + PKCollectionParser *orTermParser; + PKCollectionParser *factorParser; + PKCollectionParser *nextFactorParser; + PKCollectionParser *phraseParser; + PKCollectionParser *phraseStarParser; + PKCollectionParser *phrasePlusParser; + PKCollectionParser *phraseQuestionParser; + PKCollectionParser *letterOrDigitParser; +} ++ (id)parserFromGrammar:(NSString *)s; + +@property (retain) PKCollectionParser *expressionParser; +@property (retain) PKCollectionParser *termParser; +@property (retain) PKCollectionParser *orTermParser; +@property (retain) PKCollectionParser *factorParser; +@property (retain) PKCollectionParser *nextFactorParser; +@property (retain) PKCollectionParser *phraseParser; +@property (retain) PKCollectionParser *phraseStarParser; +@property (retain) PKCollectionParser *phrasePlusParser; +@property (retain) PKCollectionParser *phraseQuestionParser; +@property (retain) PKCollectionParser *letterOrDigitParser; +@end diff --git a/test/TDRegularParser.m b/test/TDRegularParser.m new file mode 100644 index 0000000..5650d11 --- /dev/null +++ b/test/TDRegularParser.m @@ -0,0 +1,321 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDRegularParser.h" + +@interface TDRegularParser () +- (void)didMatchChar:(PKAssembly *)a; +- (void)didMatchStar:(PKAssembly *)a; +- (void)didMatchPlus:(PKAssembly *)a; +- (void)didMatchQuestion:(PKAssembly *)a; +//- (void)didMatchAnd:(PKAssembly *)a; +- (void)didMatchOr:(PKAssembly *)a; +- (void)didMatchExpression:(PKAssembly *)a; +@end + +@implementation TDRegularParser + +- (id)init { + if (self = [super init]) { + [self add:self.expressionParser]; + } + return self; +} + + +- (void)dealloc { + self.expressionParser = nil; + self.termParser = nil; + self.orTermParser = nil; + self.factorParser = nil; + self.nextFactorParser = nil; + self.phraseParser = nil; + self.phraseStarParser = nil; + self.phrasePlusParser = nil; + self.phraseQuestionParser = nil; + self.letterOrDigitParser = nil; + [super dealloc]; +} + + ++ (id)parserFromGrammar:(NSString *)s { + TDRegularParser *p = [TDRegularParser parser]; + PKAssembly *a = [PKCharacterAssembly assemblyWithString:s]; + a = [p completeMatchFor:a]; + return [a pop]; +} + + +// expression = term orTerm* +// term = factor nextFactor* +// orTerm = '|' term +// factor = phrase | phraseStar | phrasePlus | phraseQuestion +// nextFactor = factor +// phrase = letterOrDigit | '(' expression ')' +// phraseStar = phrase '*' +// phraseStar = phrase '+' +// phraseStar = phrase '?' +// letterOrDigit = Letter | Digit + + +// expression = term orTerm* +- (PKCollectionParser *)expressionParser { + if (!expressionParser) { + self.expressionParser = [PKSequence sequence]; + expressionParser.name = @"expression"; + [expressionParser add:self.termParser]; + [expressionParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]]; + [expressionParser setAssembler:self selector:@selector(didMatchExpression:)]; + } + return expressionParser; +} + + +// term = factor nextFactor* +- (PKCollectionParser *)termParser { + if (!termParser) { + self.termParser = [PKSequence sequence]; + termParser.name = @"term"; + [termParser add:self.factorParser]; + [termParser add:[PKRepetition repetitionWithSubparser:self.nextFactorParser]]; + } + return termParser; +} + + +// orTerm = '|' term +- (PKCollectionParser *)orTermParser { + if (!orTermParser) { + self.orTermParser = [PKSequence sequence]; + orTermParser.name = @"orTerm"; + [orTermParser add:[[PKSpecificChar specificCharWithChar:'|'] discard]]; + [orTermParser add:self.termParser]; + [orTermParser setAssembler:self selector:@selector(didMatchOr:)]; + } + return orTermParser; +} + + +// factor = phrase | phraseStar | phrasePlus | phraseQuestion +- (PKCollectionParser *)factorParser { + if (!factorParser) { + self.factorParser = [PKAlternation alternation]; + factorParser.name = @"factor"; + [factorParser add:self.phraseParser]; + [factorParser add:self.phraseStarParser]; + [factorParser add:self.phrasePlusParser]; + [factorParser add:self.phraseQuestionParser]; + } + return factorParser; +} + + +// nextFactor = factor +- (PKCollectionParser *)nextFactorParser { + if (!nextFactorParser) { + self.nextFactorParser = [PKAlternation alternation]; + nextFactorParser.name = @"nextFactor"; + [nextFactorParser add:self.phraseParser]; + [nextFactorParser add:self.phraseStarParser]; + [nextFactorParser add:self.phrasePlusParser]; + [nextFactorParser add:self.phraseQuestionParser]; +// [nextFactorParser setAssembler:self selector:@selector(didMatchAnd:)]; + } + return nextFactorParser; +} + + +// phrase = letterOrDigit | '(' expression ')' +- (PKCollectionParser *)phraseParser { + if (!phraseParser) { + PKSequence *s = [PKSequence sequence]; + [s add:[[PKSpecificChar specificCharWithChar:'('] discard]]; + [s add:self.expressionParser]; + [s add:[[PKSpecificChar specificCharWithChar:')'] discard]]; + + self.phraseParser = [PKAlternation alternation]; + phraseParser.name = @"phrase"; + [phraseParser add:self.letterOrDigitParser]; + [phraseParser add:s]; + } + return phraseParser; +} + + +// phraseStar = phrase '*' +- (PKCollectionParser *)phraseStarParser { + if (!phraseStarParser) { + self.phraseStarParser = [PKSequence sequence]; + phraseStarParser.name = @"phraseStar"; + [phraseStarParser add:self.phraseParser]; + [phraseStarParser add:[[PKSpecificChar specificCharWithChar:'*'] discard]]; + [phraseStarParser setAssembler:self selector:@selector(didMatchStar:)]; + } + return phraseStarParser; +} + + +// phrasePlus = phrase '+' +- (PKCollectionParser *)phrasePlusParser { + if (!phrasePlusParser) { + self.phrasePlusParser = [PKSequence sequence]; + phrasePlusParser.name = @"phrasePlus"; + [phrasePlusParser add:self.phraseParser]; + [phrasePlusParser add:[[PKSpecificChar specificCharWithChar:'+'] discard]]; + [phrasePlusParser setAssembler:self selector:@selector(didMatchPlus:)]; + } + return phrasePlusParser; +} + + +// phrasePlus = phrase '?' +- (PKCollectionParser *)phraseQuestionParser { + if (!phraseQuestionParser) { + self.phraseQuestionParser = [PKSequence sequence]; + phraseQuestionParser.name = @"phraseQuestion"; + [phraseQuestionParser add:self.phraseParser]; + [phraseQuestionParser add:[[PKSpecificChar specificCharWithChar:'?'] discard]]; + [phraseQuestionParser setAssembler:self selector:@selector(didMatchQuestion:)]; + } + return phraseQuestionParser; +} + + +// letterOrDigit = Letter | Digit +- (PKCollectionParser *)letterOrDigitParser { + if (!letterOrDigitParser) { + self.letterOrDigitParser = [PKAlternation alternation]; + letterOrDigitParser.name = @"letterOrDigit"; + [letterOrDigitParser add:[PKLetter letter]]; + [letterOrDigitParser add:[PKDigit digit]]; + [letterOrDigitParser setAssembler:self selector:@selector(didMatchChar:)]; + } + return letterOrDigitParser; +} + + +- (void)didMatchChar:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id obj = [a pop]; + NSAssert([obj isKindOfClass:[NSNumber class]], @""); + NSInteger c = [obj integerValue]; + [a push:[PKSpecificChar specificCharWithChar:c]]; +} + + +- (void)didMatchStar:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + NSAssert([top isKindOfClass:[PKParser class]], @""); + PKRepetition *rep = [PKRepetition repetitionWithSubparser:top]; + [a push:rep]; +} + + +- (void)didMatchPlus:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + NSAssert([top isKindOfClass:[PKParser class]], @""); + PKSequence *seq = [PKSequence sequence]; + [seq add:top]; + [seq add:[PKRepetition repetitionWithSubparser:top]]; + [a push:seq]; +} + + +- (void)didMatchQuestion:(PKAssembly *)a { + // NSLog(@"%s", _cmd); + // NSLog(@"a: %@", a); + id top = [a pop]; + NSAssert([top isKindOfClass:[PKParser class]], @""); + PKAlternation *alt = [PKAlternation alternation]; + [alt add:[PKEmpty empty]]; + [alt add:top]; + [a push:alt]; +} + + +//- (void)didMatchAnd:(PKAssembly *)a { +//// NSLog(@"%s", _cmd); +//// NSLog(@"a: %@", a); +// id second = [a pop]; +// id first = [a pop]; +// NSAssert([first isKindOfClass:[PKParser class]], @""); +// NSAssert([second isKindOfClass:[PKParser class]], @""); +// PKSequence *p = [PKSequence sequence]; +// [p add:first]; +// [p add:second]; +// [a push:p]; +//} + + +- (void)didMatchExpression:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + + NSAssert(![a isStackEmpty], @""); + + id obj = nil; + NSMutableArray *objs = [NSMutableArray array]; + while (![a isStackEmpty]) { + obj = [a pop]; + [objs addObject:obj]; + NSAssert([obj isKindOfClass:[PKParser class]], @""); + } + + if ([objs count] > 1) { + PKSequence *seq = [PKSequence sequence]; + for (id obj in [objs reverseObjectEnumerator]) { + [seq add:obj]; + } + [a push:seq]; + } else { + NSAssert((NSUInteger)1 == [objs count], @""); + PKParser *p = [objs objectAtIndex:0]; + [a push:p]; + } +} + + +- (void)didMatchOr:(PKAssembly *)a { +// NSLog(@"%s", _cmd); +// NSLog(@"a: %@", a); + id second = [a pop]; + id first = [a pop]; +// NSLog(@"first: %@", first); +// NSLog(@"second: %@", second); + NSAssert(first, @""); + NSAssert(second, @""); + NSAssert([first isKindOfClass:[PKParser class]], @""); + NSAssert([second isKindOfClass:[PKParser class]], @""); + PKAlternation *p = [PKAlternation alternation]; + [p add:first]; + [p add:second]; + [a push:p]; +} + +@synthesize expressionParser; +@synthesize termParser; +@synthesize orTermParser; +@synthesize factorParser; +@synthesize nextFactorParser; +@synthesize phraseParser; +@synthesize phraseStarParser; +@synthesize phrasePlusParser; +@synthesize phraseQuestionParser; +@synthesize letterOrDigitParser; +@end diff --git a/test/TDRegularParserTest.h b/test/TDRegularParserTest.h new file mode 100644 index 0000000..646d3e2 --- /dev/null +++ b/test/TDRegularParserTest.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "TDRegularParser.h" + +@interface TDRegularParserTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + TDRegularParser *p; + PKAssembly *res; +} + +@end diff --git a/test/TDRegularParserTest.m b/test/TDRegularParserTest.m new file mode 100644 index 0000000..b0d5c0b --- /dev/null +++ b/test/TDRegularParserTest.m @@ -0,0 +1,407 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDRegularParserTest.h" + +@implementation TDRegularParserTest + +- (void)setUp { + p = [TDRegularParser parser]; +} + + +- (void)testAabPlus { + s = @"aab+"; + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"aabbbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, a, b, b, b, b]aabbbb^", [res description]); +} + + +- (void)testAabStar { + s = @"aab*"; + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"aabbbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, a, b, b, b, b]aabbbb^", [res description]); +} + + +- (void)testAabQuestion { + s = @"aab?"; + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"aabbbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, a, b]aab^bbb", [res description]); +} + + +- (void)testAb { + s = @"ab"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]ab^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + TDEquals((NSUInteger)2, [seq.subparsers count]); + + PKSpecificChar *c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + c = [seq.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"ab"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, b]ab^", [res description]); +} + + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence]abc^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + TDEquals((NSUInteger)3, [seq.subparsers count]); + + PKSpecificChar *c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + c = [seq.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + c = [seq.subparsers objectAtIndex:2]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"c", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a, b, c]abc^", [res description]); +} + + +- (void)testAOrB { + s = @"a|b"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]a|b^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"b"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b]b^", [res description]); +} + + +- (void)test4Or7 { + s = @"4|7"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]4|7^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"4", c.string); + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"7", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"4"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[4]4^", [res description]); +} + + +- (void)testAOrBStar { + s = @"a|b*"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]a|b*^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + PKRepetition *rep = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKRepetition class], [rep class]); + c = (PKSpecificChar *)rep.subparser; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"bbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b, b, b]bbb^", [res description]); +} + + +- (void)testAOrBPlus { + s = @"a|b+"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]a|b+^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + PKSequence *seq = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKSequence class], [seq class]); + + c = [seq.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + PKRepetition *rep = [seq.subparsers objectAtIndex:1]; + TDEqualObjects([PKRepetition class], [rep class]); + c = (PKSpecificChar *)rep.subparser; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"bbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b, b, b]bbb^", [res description]); + + s = @"abbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a]a^bbb", [res description]); +} + + +- (void)testAOrBQuestion { + s = @"a|b?"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation]a|b?^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + alt = [alt.subparsers objectAtIndex:1]; + TDEqualObjects([PKAlternation class], [alt class]); + + PKEmpty *e = [alt.subparsers objectAtIndex:0]; + TDTrue([e isMemberOfClass:[PKEmpty class]]); + + c = (PKSpecificChar *)[alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"bbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b]b^bb", [res description]); + + s = @"abbb"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[a]a^bbb", [res description]); +} + + +- (void)testParenAOrBParenStar { + s = @"(a|b)*"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Repetition](a|b)*^", [res description]); + PKRepetition *rep = [res pop]; + TDTrue([rep isMemberOfClass:[PKRepetition class]]); + + PKAlternation *alt = (PKAlternation *)rep.subparser; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKRepetition class]]); + s = @"bbbaaa"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b, b, b, a, a, a]bbbaaa^", [res description]); +} + + +- (void)testParenAOrBParenPlus { + s = @"(a|b)+"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Sequence](a|b)+^", [res description]); + PKSequence *seq = [res pop]; + TDTrue([seq isMemberOfClass:[PKSequence class]]); + + TDEquals((NSUInteger)2, [seq.subparsers count]); + + PKAlternation *alt = [seq.subparsers objectAtIndex:0]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + PKRepetition *rep = [seq.subparsers objectAtIndex:1]; + TDTrue([rep isMemberOfClass:[PKRepetition class]]); + + alt = (PKAlternation *)rep.subparser; + TDEqualObjects([PKAlternation class], [alt class]); + + c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKSequence class]]); + s = @"bbbaaa"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b, b, b, a, a, a]bbbaaa^", [res description]); +} + + +- (void)testParenAOrBParenQuestion { + s = @"(a|b)?"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[Alternation](a|b)?^", [res description]); + PKAlternation *alt = [res pop]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + + TDEquals((NSUInteger)2, [alt.subparsers count]); + PKEmpty *e = [alt.subparsers objectAtIndex:0]; + TDTrue([PKEmpty class] == [e class]); + + alt = [alt.subparsers objectAtIndex:1]; + TDTrue([alt isMemberOfClass:[PKAlternation class]]); + TDEquals((NSUInteger)2, [alt.subparsers count]); + + PKSpecificChar *c = [alt.subparsers objectAtIndex:0]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"a", c.string); + + c = [alt.subparsers objectAtIndex:1]; + TDTrue([c isMemberOfClass:[PKSpecificChar class]]); + TDEqualObjects(@"b", c.string); + + // use the result parser + p = [TDRegularParser parserFromGrammar:s]; + TDNotNil(p); + TDTrue([p isKindOfClass:[PKAlternation class]]); + s = @"bbbaaa"; + a = [PKCharacterAssembly assemblyWithString:s]; + res = (PKCharacterAssembly *)[p bestMatchFor:a]; + TDEqualObjects(@"[b]b^bbaaa", [res description]); +} + +@end diff --git a/test/TDRepetitionTest.h b/test/TDRepetitionTest.h new file mode 100644 index 0000000..26ff80b --- /dev/null +++ b/test/TDRepetitionTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDRepetitionTest : SenTestCase { + PKParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/TDRepetitionTest.m b/test/TDRepetitionTest.m new file mode 100644 index 0000000..f496f95 --- /dev/null +++ b/test/TDRepetitionTest.m @@ -0,0 +1,228 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDRepetitionTest.h" + +@interface PKParser () +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@implementation TDRepetitionTest + +- (void)setUp { +} + + +- (void)tearDown { + [a release]; + [p release]; +} + + +#pragma mark - + +- (void)testWordRepetitionAllMatchesForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + NSLog(@"all: %@", all); + + TDNotNil(all); + NSUInteger c = [all count]; + TDEquals((NSUInteger)4, c); +} + + +- (void)testWordRepetitionBestMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + + PKAssembly *result = [p bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testWordRepetitionBestMatchForFooSpaceBarSpace123 { + s = @"foo bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, bar]foo/bar^123", [result description]); +} + + +- (void)testWordRepetitionAllMatchesForFooSpaceBarSpace123 { + s = @"foo bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + NSLog(@"all: %@", all); + + TDNotNil(all); + NSUInteger c = [all count]; + TDEquals((NSUInteger)3, c); +} + + +- (void)testWordRepetitionAllMatchesFooSpace123SpaceBaz { + s = @"foo 123 baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + NSLog(@"all: %@", all); + + TDNotNil(all); + NSUInteger c = [all count]; + TDEquals((NSUInteger)2, c); +} + + +- (void)testNumRepetitionAllMatchesForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + NSLog(@"all: %@", all); + + TDNotNil(all); + NSUInteger c = [all count]; + TDEquals((NSUInteger)1, c); +} + + +- (void)testWordRepetitionCompleteMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testWordRepetitionCompleteMatchForFooSpaceBarSpace123 { + s = @"foo bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testWordRepetitionCompleteMatchFor456SpaceBarSpace123 { + s = @"456 bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testNumRepetitionCompleteMatchFor456SpaceBarSpace123 { + s = @"456 bar 123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testNumRepetitionAllMatchesFor123Space456SpaceBaz { + s = @"123 456 baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + NSSet *all = [p allMatchesFor:[NSSet setWithObject:a]]; + + TDNotNil(all); + NSInteger c = [all count]; + TDEquals((NSUInteger)3, (NSUInteger)c); +} + + +- (void)testNumRepetitionBestMatchFor123Space456SpaceBaz { + s = @"123 456 baz"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123, 456]123/456^baz", [result description]); +} + + +- (void)testNumRepetitionCompleteMatchFor123 { + s = @"123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKNumber number]]; + + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[123]123^", [result description]); +} + + +- (void)testWordRepetitionCompleteMatchFor123 { + s = @"123"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)testWordRepetitionBestMatchForFoo { + s = @"foo"; + a = [[PKTokenAssembly alloc] initWithString:s]; + + p = [[PKRepetition alloc] initWithSubparser:[PKWord word]]; + + PKAssembly *result = [p bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo]foo^", [result description]); +} + +@end diff --git a/test/TDReservedWord.h b/test/TDReservedWord.h new file mode 100644 index 0000000..fb52ba5 --- /dev/null +++ b/test/TDReservedWord.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface TDReservedWord : PKWord { + +} + ++ (void)setReservedWords:(NSArray *)inWords; +@end diff --git a/test/TDReservedWord.m b/test/TDReservedWord.m new file mode 100644 index 0000000..bfe9dc0 --- /dev/null +++ b/test/TDReservedWord.m @@ -0,0 +1,49 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +static NSArray *sTDReservedWords = nil; + +@interface TDReservedWord () ++ (NSArray *)reservedWords; +@end + +@implementation TDReservedWord + ++ (NSArray *)reservedWords { + return [[sTDReservedWords retain] autorelease]; +} + + ++ (void)setReservedWords:(NSArray *)inWords { + if (inWords != sTDReservedWords) { + [sTDReservedWords autorelease]; + sTDReservedWords = [inWords copy]; + } +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + NSString *s = tok.stringValue; + return [s length] && [[TDReservedWord reservedWords] containsObject:s]; +} + +@end diff --git a/test/TDReservedWordTest.h b/test/TDReservedWordTest.h new file mode 100644 index 0000000..61015d6 --- /dev/null +++ b/test/TDReservedWordTest.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDReservedWordTest : SenTestCase { + +} + +@end diff --git a/test/TDReservedWordTest.m b/test/TDReservedWordTest.m new file mode 100644 index 0000000..9ea1906 --- /dev/null +++ b/test/TDReservedWordTest.m @@ -0,0 +1,47 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDReservedWordTest.h" +#import "ParseKit.h" + +@implementation TDReservedWordTest + +- (void)testFoobar { + NSString *s = @"Foobar"; + [TDReservedWord setReservedWords:[NSArray arrayWithObject:@"Foobar"]]; + + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [TDReservedWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[Foobar]Foobar^", [result description]); +// TDNil(result); +} + + +- (void)testfoobar { + NSString *s = @"foobar"; + [TDReservedWord setReservedWords:[NSArray arrayWithObject:@"Foobar"]]; + + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [TDReservedWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + +@end diff --git a/test/TDRobotCommandTest.h b/test/TDRobotCommandTest.h new file mode 100644 index 0000000..bbfeb97 --- /dev/null +++ b/test/TDRobotCommandTest.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDRobotCommandTest : SenTestCase { + +} + +@end diff --git a/test/TDRobotCommandTest.m b/test/TDRobotCommandTest.m new file mode 100644 index 0000000..f485987 --- /dev/null +++ b/test/TDRobotCommandTest.m @@ -0,0 +1,183 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDRobotCommandTest.h" + +@interface RobotCommand : NSObject { + NSString *location; +} +@property (copy) NSString *location; +@end + +@implementation RobotCommand + +- (void)dealloc { + self.location = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + RobotCommand *c = [[RobotCommand allocWithZone:zone] init]; + c->location = [location copy]; + return c; +} + +@synthesize location; +@end + +@interface RobotPickCommand : RobotCommand {} +@end +@implementation RobotPickCommand +- (NSString *)description { return [NSString stringWithFormat:@"pick %@", self.location]; } +@end + +@interface RobotPlaceCommand : RobotCommand {} +@end +@implementation RobotPlaceCommand +- (NSString *)description { return [NSString stringWithFormat:@"place %@", self.location]; } +@end + +@interface RobotScanCommand : RobotCommand {} +@end +@implementation RobotScanCommand +- (NSString *)description { return [NSString stringWithFormat:@"scan %@", self.location]; } +@end + +@implementation TDRobotCommandTest + +// e = command* +// command = pickCommand | placeCommand | scanCommand +// pickCommand = "pick" "carrier" "from" location +// placeCommand = "place" "carrier" "at" location +// scanCommand = "scan" location +// location = Word + +- (PKParser *)location { + return [PKWord word]; +} + + +- (PKParser *)pickCommand { + PKSequence *s = [PKSequence sequence]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"pick"] discard]]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"carrier"] discard]]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"from"] discard]]; + [s add:[self location]]; + [s setAssembler:self selector:@selector(didMatchPickCommand:)]; + return s; +} + + +- (PKParser *)placeCommand { + PKSequence *s = [PKSequence sequence]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"place"] discard]]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"carrier"] discard]]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"at"] discard]]; + [s add:[self location]]; + [s setAssembler:self selector:@selector(didMatchPlaceCommand:)]; + return s; +} + + +- (PKParser *)scanCommand { + PKSequence *s = [PKSequence sequence]; + [s add:[[PKCaseInsensitiveLiteral literalWithString:@"scan"] discard]]; + [s add:[self location]]; + [s setAssembler:self selector:@selector(didMatchScanCommand:)]; + return s; +} + + +- (PKParser *)command { + PKAlternation *a = [PKAlternation alternation]; + [a add:[self pickCommand]]; + [a add:[self placeCommand]]; + [a add:[self scanCommand]]; + return a; +} + + +- (void)testPick { + NSString *s1 = @"pick carrier from LINE_IN"; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithString:s1]; + PKParser *p = [self command]; + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[]pick/carrier/from/LINE_IN^", [result description]); + + id target = result.target; + TDNotNil(target); + TDEqualObjects(@"pick LINE_IN", [target description]); +} + + +- (void)testPlace { + NSString *s2 = @"place carrier at LINE_OUT"; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithString:s2]; + PKParser *p = [self command]; + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[]place/carrier/at/LINE_OUT^", [result description]); + + id target = result.target; + TDNotNil(target); + TDEqualObjects(@"place LINE_OUT", [target description]); +} + + +- (void)testScan { + NSString *s3 = @"scan DB101_OUT"; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithString:s3]; + PKParser *p = [self command]; + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[]scan/DB101_OUT^", [result description]); + + id target = result.target; + TDNotNil(target); + TDEqualObjects(@"scan DB101_OUT", [target description]); +} + + +- (void)didMatchPickCommand:(PKAssembly *)a { + RobotPickCommand *c = [[[RobotPickCommand alloc] init] autorelease]; + PKToken *location = [a pop]; + c.location = location.stringValue; + a.target = c; +} + + +- (void)didMatchPlaceCommand:(PKAssembly *)a { + RobotPlaceCommand *c = [[[RobotPlaceCommand alloc] init] autorelease]; + PKToken *location = [a pop]; + c.location = location.stringValue; + a.target = c; +} + + +- (void)didMatchScanCommand:(PKAssembly *)a { + RobotScanCommand *c = [[[RobotScanCommand alloc] init] autorelease]; + PKToken *location = [a pop]; + c.location = location.stringValue; + a.target = c; +} + +@end diff --git a/test/TDScientificNumberStateTest.h b/test/TDScientificNumberStateTest.h new file mode 100644 index 0000000..53a8663 --- /dev/null +++ b/test/TDScientificNumberStateTest.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDScientificNumberStateTest : SenTestCase { + PKNumberState *numberState; + PKTokenizer *t; + PKReader *r; + NSString *s; +} + +@end diff --git a/test/TDScientificNumberStateTest.m b/test/TDScientificNumberStateTest.m new file mode 100644 index 0000000..e2728d9 --- /dev/null +++ b/test/TDScientificNumberStateTest.m @@ -0,0 +1,1229 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDScientificNumberStateTest.h" +#import "TDArithmeticParser.h" + +@implementation TDScientificNumberStateTest + +- (void)setUp { + t = [[PKTokenizer alloc] init]; + r = [[PKReader alloc] init]; + numberState = t.numberState; + numberState.allowsScientificNotation = YES; + [t setTokenizerState:numberState from:'0' to:'9']; + [t setTokenizerState:numberState from:'.' to:'.']; + [t setTokenizerState:numberState from:'-' to:'-']; +// NSLog(@"\n\n\n\n\n %f \n\n\n\n\n", 020); +} + + +- (void)tearDown { + [numberState release]; + [r release]; +} + + +//- (void)testScientificNumberStringArithmetic { +// t.string = @"1e2 + 1e1 + 1e0 + 1e-1 + 1e-2 + 1e-3"; +// TDArithmeticParser *p = [[[TDArithmeticParser alloc] init] autorelease]; +// PKAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; +// PKAssembly *res = [p bestMatchFor:a]; +// PKToken *tok = [res pop]; +// TDEquals((CGFloat)111.111, tok.floatValue); +//} + + +- (void)testSingleDigit { + s = @"3"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)3.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"3", tok.stringValue); +} + + +- (void)testDoubleDigit { + s = @"47"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)47.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"47", tok.stringValue); +} + + +- (void)testTripleDigit { + s = @"654"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)654.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"654", tok.stringValue); +} + + +- (void)testSingleDigitPositive { + s = @"+3"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)3.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+3", tok.stringValue); +} + + +- (void)testDoubleDigitPositive { + s = @"+22"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)22.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)testDoubleDigitPositiveSpace { + s = @"+22 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)22.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)testMultipleDots { + s = @"1.1.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.1", tok.stringValue); + + tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".1", tok.stringValue); +} + + +- (void)testOneDot { + s = @"1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1", tok.stringValue); +} + + +- (void)testCustomOneDot1 { + s = @"1."; + t.string = s; + numberState.allowsTrailingDot = YES; + numberState.allowsScientificNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.", tok.stringValue); +} + + +- (void)testCustomOneDot2 { + s = @"1."; + t.string = s; + numberState.allowsTrailingDot = YES; + numberState.allowsScientificNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.", tok.stringValue); +} + + +- (void)testOneDotZero { + s = @"1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.0", tok.stringValue); +} + + +- (void)testPositiveOneDot { + s = @"+1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1", tok.stringValue); +} + + +- (void)testPositiveOneDotCustom { + s = @"+1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.", tok.stringValue); +} + + +- (void)testPositiveOneDotZero { + s = @"+1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.0", tok.stringValue); +} + + +- (void)testPositiveOneDotZeroSpace { + s = @"+1.0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1.0", tok.stringValue); +} + + +- (void)testNegativeOneDot { + s = @"-1."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testNegativeOneDotCustom { + s = @"-1."; + t.string = s; + r.string = s; + numberState.allowsTrailingDot = YES; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.", tok.stringValue); +} + + +- (void)testNegativeOneDotSpace { + s = @"-1. "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testNegativeOneDotZero { + s = @"-1.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.0", tok.stringValue); +} + + +- (void)testNegativeOneDotZeroSpace { + s = @"-1.0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1.0", tok.stringValue); +} + + +- (void)testOneDotOne { + s = @"1.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1.1", tok.stringValue); +} + + +- (void)testZeroDotOne { + s = @"0.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0.1", tok.stringValue); +} + + +- (void)testDotOne { + s = @".1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".1", tok.stringValue); +} + + +- (void)testDotZero { + s = @".0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); +} + + +- (void)testNegativeDotZero { + s = @"-.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.0", tok.stringValue); +} + + +- (void)testPositiveDotZero { + s = @"+.0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+.0", tok.stringValue); +} + + +- (void)testPositiveDotOne { + s = @"+.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+.1", tok.stringValue); +} + + +- (void)testNegativeDotOne { + s = @"-.1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.1, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1", tok.stringValue); +} + + +- (void)testNegativeDotOneOne { + s = @"-.11"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.11, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.11", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOne { + s = @"-.111"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.111", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZero { + s = @"-.1110"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1110", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZeroZero { + s = @"-.11100"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.11100", tok.stringValue); +} + + +- (void)testNegativeDotOneOneOneZeroSpace { + s = @"-.1110 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.111, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-.1110", tok.stringValue); +} + + +- (void)testZeroDotThreeSixtyFive { + s = @"0.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0.365", tok.stringValue); +} + + +- (void)testNegativeZeroDotThreeSixtyFive { + s = @"-0.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0.365", tok.stringValue); +} + + +- (void)testNegativeTwentyFourDotThreeSixtyFive { + s = @"-24.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-24.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-24.365", tok.stringValue); +} + + +- (void)testTwentyFourDotThreeSixtyFive { + s = @"24.365"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)24.365, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"24.365", tok.stringValue); +} + + +- (void)testZero { + s = @"0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0", tok.stringValue); +} + + +- (void)testNegativeOne { + s = @"-1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-1", tok.stringValue); +} + + +- (void)testOne { + s = @"1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"1", tok.stringValue); +} + + +- (void)testPositiveOne { + s = @"+1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)1.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+1", tok.stringValue); +} + + +- (void)testPositiveZero { + s = @"+0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+0", tok.stringValue); +} + + +- (void)testPositiveZeroSpace { + s = @"+0 "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+0", tok.stringValue); +} + + +- (void)testNegativeZero { + s = @"-0"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)-0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0", tok.stringValue); +} + + +- (void)testNull { + s = @"NULL"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testNil { + s = @"nil"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testEmptyString { + s = @""; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDot { + s = @"."; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDotSpace { + s = @". "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testDotSpaceOne { + s = @". 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlus { + s = @"+"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlusSpace { + s = @"+ "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testPlusSpaceOne { + s = @"+ 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinus { + s = @"-"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinusSpace { + s = @"- "; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testMinusSpaceOne { + s = @"- 1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDFalse(tok.isNumber); +} + + +- (void)testInitSig { + s = @"- (id)init {"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(@"-", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); +} + + +#pragma mark - + +- (void)test1e1 { + s = @"1e1"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)10.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)test1e2 { + s = @"1e2"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)100.0, tok.floatValue); + TDTrue(tok.isNumber); +} + + +- (void)test2dot0e2 { + s = @"2.0e2"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); +} + + +- (void)test2dot0E2 { + s = @"2.0E2"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); +} + + +- (void)test2e2 { + s = @"2e2"; + t.string = s; + r.string = s; + PKToken *tok = [numberState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); +} + + +- (void)test2eNegative2Tok { + s = @"2e-2"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.02, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2e2Tok { + s = @"2e2"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(s, tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2e2fooTok { + s = @"2e2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2e2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2eNegative2fooTok { + s = @"2e-2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.02, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2e-2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2ePositive2fooTok { + s = @"2e+2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2e+2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2dot0ePositive2fooTok { + s = @"2.0e+2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)200.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2.0e+2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)test2dot0eNegative2fooTok { + s = @"2.0e-2 foo"; + t.string = s; + r.string = s; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.02, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2.0e-2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testNotAllowsScientificNotation2dot0e2 { + s = @"2.0e2"; + t.string = s; + r.string = s; + numberState.allowsScientificNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2.0", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"e2", tok.stringValue); +} + + +- (void)testNotAllowsScientificNotation2dot0E2 { + s = @"2.0E2"; + t.string = s; + r.string = s; + numberState.allowsScientificNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2.0", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"E2", tok.stringValue); +} + + +- (void)testNotAllowsScientificNotation2e2 { + s = @"2e2"; + t.string = s; + r.string = s; + numberState.allowsScientificNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"e2", tok.stringValue); +} + + +- (void)testOctal { + s = @"020"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testOctal2 { + s = @"020"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testMinusOctal { + s = @"-020"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)-16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-020", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testMinusOctal2 { + s = @"-020"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)-16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-020", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testOctalDecimal { + s = @"020.0"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testOctalDecimal2 { + s = @"020.0"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)16.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testOctalDecimalNO { + s = @"020.0"; + t.string = s; + numberState.allowsOctalNotation = NO; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)20.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"020.0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHex { + s = @"0x20"; + t.string = s; + numberState.allowsOctalNotation = NO; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)32.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x20", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHex2 { + s = @"0x20"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)32.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x20", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testNotHex { + s = @"0x"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isWord); + TDEqualObjects(@"x", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexAlpha { + s = @"0xA"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)10.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0xA", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); + + s = @"0xa"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + tok = [t nextToken]; + TDEquals((CGFloat)10.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0xa", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); + + s = @"0xB7"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + tok = [t nextToken]; + TDEquals((CGFloat)183.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0xB7", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); + + s = @"0x8EE"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + tok = [t nextToken]; + TDEquals((CGFloat)2286.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x8EE", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testMinusHex { + s = @"-0x20"; + t.string = s; + numberState.allowsHexadecimalNotation = NO; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)-32.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0x20", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testMinusHex2 { + s = @"-0x20"; + t.string = s; + numberState.allowsHexadecimalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)-32.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"-0x20", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexDecimal { + s = @"0x30.0"; + t.string = s; + numberState.allowsOctalNotation = NO; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)48.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x30", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexDecimal2 { + s = @"0x40.0"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)64.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"0x40", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexDecimal3 { + s = @"00x30.0"; + t.string = s; + numberState.allowsOctalNotation = NO; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"00", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"x30", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testHexDecimal4 { + s = @"00x30.0"; + t.string = s; + numberState.allowsOctalNotation = YES; + numberState.allowsHexadecimalNotation = YES; + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"00", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"x30", tok.stringValue); + + tok = [t nextToken]; + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@".0", tok.stringValue); + + tok = [t nextToken]; + TDTrue([PKToken EOFToken] == tok); +} + +@end diff --git a/test/TDSequenceTest.h b/test/TDSequenceTest.h new file mode 100644 index 0000000..54c1105 --- /dev/null +++ b/test/TDSequenceTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDSequenceTest : SenTestCase { + PKCollectionParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/TDSequenceTest.m b/test/TDSequenceTest.m new file mode 100644 index 0000000..97a0dcc --- /dev/null +++ b/test/TDSequenceTest.m @@ -0,0 +1,257 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDSequenceTest.h" + +@interface PKParser () +- (NSSet *)allMatchesFor:(NSSet *)inAssemblies; +@end + +@implementation TDSequenceTest + +- (void)tearDown { +} + +- (void)testDiscard { + s = @"foo -"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo]foo/-^", [result description]); +} + + +- (void)testDiscard2 { + s = @"foo foo -"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, foo]foo/foo/-^", [result description]); +} + + +- (void)testDiscard3 { + s = @"foo - foo"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, foo]foo/-/foo^", [result description]); +} + + +- (void)testDiscard1 { + s = @"- foo"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo]-/foo^", [result description]); +} + + +- (void)testDiscard4 { + s = @"- foo -"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo]-/foo/-^", [result description]); +} + + +- (void)testDiscard5 { + s = @"- foo + foo"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[[PKSymbol symbolWithString:@"-"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[[PKSymbol symbolWithString:@"+"] discard]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, foo]-/foo/+/foo^", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testTrueLiteralBestMatchForFooSpaceBarSpaceBaz1 { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *foo = [PKLiteral literalWithString:@"foo"]; + PKParser *bar = [PKLiteral literalWithString:@"bar"]; + PKParser *baz = [PKLiteral literalWithString:@"baz"]; + p = [PKSequence sequenceWithSubparsers:foo, baz, bar, nil]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNil(result); +} + + +- (void)testFalseLiteralBestMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testTrueLiteralCompleteMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testTrueLiteralCompleteMatchForFooSpaceBarSpaceBaz1 { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKWord word]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[foo, bar, baz]foo/bar/baz^", [result description]); +} + + +- (void)testFalseLiteralCompleteMatchForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testFalseLiteralCompleteMatchForFooSpaceBarSpaceBaz1 { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKNumber number]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testTrueLiteralAllMatchsForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"bar"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); +} + + +- (void)testFalseLiteralAllMatchsForFooSpaceBarSpaceBaz { + s = @"foo bar baz"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSequence sequence]; + [p add:[PKLiteral literalWithString:@"foo"]]; + [p add:[PKLiteral literalWithString:@"123"]]; + [p add:[PKLiteral literalWithString:@"baz"]]; + + NSSet *result = [p allMatchesFor:[NSSet setWithObject:a]]; + + TDNotNil(result); + NSUInteger c = [result count]; + TDEquals((NSUInteger)0, c); +} + +@end diff --git a/test/TDSignificantWhitespaceState.h b/test/TDSignificantWhitespaceState.h new file mode 100644 index 0000000..164298a --- /dev/null +++ b/test/TDSignificantWhitespaceState.h @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import + +// NOTE: this class is not currently in use or included in the Framework. It is an example of how to add a new token type + +static const NSInteger PKTokenTypeWhitespace = 5; + +@interface PKToken (TDSignificantWhitespaceStateAdditions) +@property (nonatomic, readonly, getter=isWhitespace) BOOL whitespace; +@end + +@interface TDSignificantWhitespaceState : PKWhitespaceState { + +} +@end diff --git a/test/TDSignificantWhitespaceState.m b/test/TDSignificantWhitespaceState.m new file mode 100644 index 0000000..0d66ba1 --- /dev/null +++ b/test/TDSignificantWhitespaceState.m @@ -0,0 +1,75 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation PKToken (TDSignificantWhitespaceStateAdditions) + +- (BOOL)isWhitespace { + return self.tokenType == PKTokenTypeWhitespace; +} + + +- (NSString *)debugDescription { + NSString *typeString = nil; + if (self.isNumber) { + typeString = @"Number"; + } else if (self.isQuotedString) { + typeString = @"Quoted String"; + } else if (self.isSymbol) { + typeString = @"Symbol"; + } else if (self.isWord) { + typeString = @"Word"; + } else if (self.isWhitespace) { + typeString = @"Whitespace"; + } + return [NSString stringWithFormat:@"<%@ %C%@%C>", typeString, 0x00ab, self.value, 0x00bb]; +} + +@end + +@implementation TDSignificantWhitespaceState + +- (void)dealloc { + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + [self resetWithReader:r]; + + c = cin; + while ([self isWhitespaceChar:c]) { + [self append:c]; + c = [r read]; + } + if (c != -1) { + [r unread]; + } + + return [PKToken tokenWithTokenType:PKTokenTypeWhitespace stringValue:[self bufferedString] floatValue:0.0]; +} + +@end diff --git a/test/TDSignificantWhitespaceStateTest.h b/test/TDSignificantWhitespaceStateTest.h new file mode 100644 index 0000000..e63e071 --- /dev/null +++ b/test/TDSignificantWhitespaceStateTest.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@interface TDSignificantWhitespaceStateTest : SenTestCase { + TDSignificantWhitespaceState *whitespaceState; + PKReader *r; + NSString *s; +} + +@end diff --git a/test/TDSignificantWhitespaceStateTest.m b/test/TDSignificantWhitespaceStateTest.m new file mode 100644 index 0000000..5bca46c --- /dev/null +++ b/test/TDSignificantWhitespaceStateTest.m @@ -0,0 +1,170 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDSignificantWhitespaceStateTest.h" + + +@implementation TDSignificantWhitespaceStateTest + +- (void)setUp { + whitespaceState = [[TDSignificantWhitespaceState alloc] init]; +} + + +- (void)tearDown { + [whitespaceState release]; + [r release]; +} + + +- (void)testSpace { + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testTwoSpaces { + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testEmptyString { + s = @""; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testTab { + s = @"\t"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testNewLine { + s = @"\n"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testCarriageReturn { + s = @"\r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testSpaceCarriageReturn { + s = @" \r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testSpaceTabNewLineSpace { + s = @" \t\n "; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(s, t.stringValue, @""); + STAssertEquals(PKEOF, [r read], @""); +} + + +- (void)testSpaceA { + s = @" a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@" ", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + +- (void)testSpaceASpace { + s = @" a "; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@" ", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +- (void)testTabA { + s = @"\ta"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@"\t", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +- (void)testNewLineA { + s = @"\na"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@"\n", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +- (void)testCarriageReturnA { + s = @"\ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@"\r", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +- (void)testNewLineSpaceCarriageReturnA { + s = @"\n \ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *t = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + STAssertNotNil(t, @""); + STAssertEqualObjects(@"\n \r", t.stringValue, @""); + STAssertEquals((PKUniChar)'a', [r read], @""); +} + + +@end diff --git a/test/TDSlashSlashState.h b/test/TDSlashSlashState.h new file mode 100644 index 0000000..934557e --- /dev/null +++ b/test/TDSlashSlashState.h @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class TDSlashSlashState + @brief A slash slash state ignores everything up to an end-of-line and returns the tokenizer's next token. +*/ +@interface TDSlashSlashState : PKTokenizerState { + +} + +@end diff --git a/test/TDSlashSlashState.m b/test/TDSlashSlashState.m new file mode 100644 index 0000000..3a8816b --- /dev/null +++ b/test/TDSlashSlashState.m @@ -0,0 +1,59 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import +#import + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation TDSlashSlashState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + BOOL reportTokens = t.slashState.reportsCommentTokens; + if (reportTokens) { + [self resetWithReader:r]; + [self append:'/']; + } + + NSInteger c = cin; + + while ('\n' != c && '\r' != c && -1 != c) { + if (reportTokens) { + [self append:c]; + } + c = [r read]; + } + if (-1 != c) { + [r unread]; + } + + if (reportTokens) { + return [PKToken tokenWithTokenType:PKTokenTypeComment stringValue:[self bufferedString] floatValue:0.0]; + } else { + return [t nextToken]; + } +} + +@end diff --git a/test/TDSlashStarState.h b/test/TDSlashStarState.h new file mode 100644 index 0000000..c9157ab --- /dev/null +++ b/test/TDSlashStarState.h @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class TDSlashStarState + @brief A slash star state ignores everything up to a closing star and slash, and then returns the tokenizer's next token. +*/ +@interface TDSlashStarState : PKTokenizerState { + +} + +@end diff --git a/test/TDSlashStarState.m b/test/TDSlashStarState.m new file mode 100644 index 0000000..a54e3a5 --- /dev/null +++ b/test/TDSlashStarState.m @@ -0,0 +1,78 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import +#import + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@implementation TDSlashStarState + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + BOOL reportTokens = t.slashState.reportsCommentTokens; + if (reportTokens) { + [self resetWithReader:r]; + [self append:'/']; + } + + NSInteger c = cin; + while (-1 != c) { + if (reportTokens) { + [self append:c]; + } + c = [r read]; + + if ('*' == c) { + NSInteger peek = [r read]; + if ('/' == peek) { + if (reportTokens) { + [self append:c]; + [self append:peek]; + } + c = [r read]; + break; + } else if ('*' == peek) { + [r unread]; + } else { + if (reportTokens) { + [self append:c]; + } + c = peek; + } + } + } + + if (-1 != c) { + [r unread]; + } + + if (reportTokens) { + return [PKToken tokenWithTokenType:PKTokenTypeComment stringValue:[self bufferedString] floatValue:0.0]; + } else { + return [t nextToken]; + } +} + +@end diff --git a/test/TDSlashState.h b/test/TDSlashState.h new file mode 100644 index 0000000..d5cc38d --- /dev/null +++ b/test/TDSlashState.h @@ -0,0 +1,33 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +@class TDSlashSlashState; +@class TDSlashStarState; + +/*! + @class TDSlashState + @brief This state will either delegate to a comment-handling state, or return a PKSymbol token with just a slash in it. +*/ +@interface TDSlashState : PKTokenizerState { + TDSlashSlashState *slashSlashState; + TDSlashStarState *slashStarState; + BOOL reportsCommentTokens; +} + + +@property (nonatomic) BOOL reportsCommentTokens; +@end diff --git a/test/TDSlashState.m b/test/TDSlashState.m new file mode 100644 index 0000000..2e4b7cb --- /dev/null +++ b/test/TDSlashState.m @@ -0,0 +1,65 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import +#import +#import +#import + +@interface TDSlashState () +@property (nonatomic, retain) TDSlashSlashState *slashSlashState; +@property (nonatomic, retain) TDSlashStarState *slashStarState; +@end + +@implementation TDSlashState + +- (id)init { + if (self = [super init]) { + self.slashSlashState = [[[TDSlashSlashState alloc] init] autorelease]; + self.slashStarState = [[[TDSlashStarState alloc] init] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.slashSlashState = nil; + self.slashStarState = nil; + [super dealloc]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + NSParameterAssert(t); + + NSInteger c = [r read]; + if ('/' == c) { + return [slashSlashState nextTokenFromReader:r startingWith:c tokenizer:t]; + } else if ('*' == c) { + return [slashStarState nextTokenFromReader:r startingWith:c tokenizer:t]; + } else { + if (-1 != c) { + [r unread]; + } + return [PKToken tokenWithTokenType:PKTokenTypeSymbol stringValue:@"/" floatValue:0.0]; + } +} + +@synthesize slashSlashState; +@synthesize slashStarState; +@synthesize reportsCommentTokens; +@end diff --git a/test/TDSlashStateTest.h b/test/TDSlashStateTest.h new file mode 100644 index 0000000..150df1e --- /dev/null +++ b/test/TDSlashStateTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDSlashStateTest : SenTestCase { + TDSlashState *slashState; + PKReader *r; + PKTokenizer *t; + NSString *s; +} +@end diff --git a/test/TDSlashStateTest.m b/test/TDSlashStateTest.m new file mode 100644 index 0000000..4776172 --- /dev/null +++ b/test/TDSlashStateTest.m @@ -0,0 +1,396 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDSlashStateTest.h" + +@implementation TDSlashStateTest + +- (void)setUp { + r = [[PKReader alloc] init]; + t = [[PKTokenizer alloc] init]; + slashState = t.slashState; +} + + +- (void)tearDown { + [r release]; + [t release]; +} + + +- (void)testSpace { + s = @" "; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlash { + s = @"/"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlash { + s = @"/"; + r.string = s; + t.string = s; + + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashSlash { + s = @"//"; + r.string = s; + t.string = s; + + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, s); + TDTrue(tok.isComment); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashSlashFoo { + s = @"// foo"; + r.string = s; + t.string = s; + + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, s); + TDTrue(tok.isComment); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashAbc { + s = @"/abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testReportSlashAbc { + s = @"/abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSlashSpaceAbc { + s = @"/ abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testReportSlashSpaceAbc { + s = @"/ abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok.stringValue, @"/"); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testSlashSlashAbc { + s = @"//abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashSlashAbc { + s = @"//abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashSlashSpaceAbc { + s = @"// abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashSlashSpaceAbc { + s = @"// abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcStarSlash { + s = @"/*abc*/"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcStarSlash { + s = @"/*abc*/"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcStarStar { + s = @"/*abc**"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAStarStarSpaceA { + s = @"/*a**/ a"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/*a**/"); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testReportSlashStarAbcStarStarSpaceA { + s = @"/*abc**/ a"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/*abc**/"); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testReportSlashStarStarSlash { + s = @"/**/"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarStarStarSlash { + s = @"/***/"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarStarSlashSpace { + s = @"/**/ "; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/**/"); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testReportSlashStarAbcStarSpaceStarSpaceA { + s = @"/*abc* */ a"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, @"/*abc* */"); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testSlashStarAbc { + s = @"/*abc"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbc { + s = @"/*abc"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcStar { + s = @"/*abc*"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcStarSpace { + s = @"/*abc* "; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcStarSpace { + s = @"/*abc* "; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcSlash { + s = @"/*abc/"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcSlashSpace { + s = @"/*abc/ "; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcSlashSpace { + s = @"/*abc/ "; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSlashStarAbcNewline { + s = @"/*abc\n"; + r.string = s; + t.string = s; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDEqualObjects(tok, [PKToken EOFToken]); + TDEquals(PKEOF, [r read]); +} + + +- (void)testReportSlashStarAbcNewline { + s = @"/*abc\n"; + r.string = s; + t.string = s; + slashState.reportsCommentTokens = YES; + PKToken *tok = [slashState nextTokenFromReader:r startingWith:[r read] tokenizer:t]; + TDTrue(tok.isComment); + TDEqualObjects(tok.stringValue, s); + TDEquals(PKEOF, [r read]); +} + +@end diff --git a/test/TDSpecificCharTest.h b/test/TDSpecificCharTest.h new file mode 100644 index 0000000..e5e83d3 --- /dev/null +++ b/test/TDSpecificCharTest.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + + +@interface TDSpecificCharTest : SenTestCase { + NSString *s; + PKCharacterAssembly *a; + PKChar *p; + PKAssembly *result; +} + +@end diff --git a/test/TDSpecificCharTest.m b/test/TDSpecificCharTest.m new file mode 100644 index 0000000..723eaa9 --- /dev/null +++ b/test/TDSpecificCharTest.m @@ -0,0 +1,65 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDSpecificCharTest.h" + +@interface PKAssembly () +- (BOOL)hasMore; +@end + +@implementation TDSpecificCharTest + +- (void)test123 { + s = @"123"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^123", [a description]); + p = [PKSpecificChar specificCharWithChar:'1']; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[1]1^23", [result description]); + TDTrue([a hasMore]); +} + + +- (void)testAbc { + s = @"abc"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^abc", [a description]); + p = [PKSpecificChar specificCharWithChar:'1']; + + result = [p bestMatchFor:a]; + TDNotNil(a); + TDNil(result); + TDTrue([a hasMore]); +} + + +- (void)testRepetition { + s = @"aaa"; + a = [PKCharacterAssembly assemblyWithString:s]; + + TDEqualObjects(@"[]^aaa", [a description]); + p = [PKSpecificChar specificCharWithChar:'a']; + PKParser *r = [PKRepetition repetitionWithSubparser:p]; + + result = [r bestMatchFor:a]; + TDNotNil(a); + TDEqualObjects(@"[a, a, a]aaa^", [result description]); + TDFalse([result hasMore]); +} + +@end diff --git a/test/TDSymbolStateTest.h b/test/TDSymbolStateTest.h new file mode 100644 index 0000000..f2ea819 --- /dev/null +++ b/test/TDSymbolStateTest.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDSymbolStateTest : SenTestCase { + PKSymbolState *symbolState; + PKReader *r; + NSString *s; +} +@end diff --git a/test/TDSymbolStateTest.m b/test/TDSymbolStateTest.m new file mode 100644 index 0000000..83839c7 --- /dev/null +++ b/test/TDSymbolStateTest.m @@ -0,0 +1,578 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDSymbolStateTest.h" + +@implementation TDSymbolStateTest + +- (void)setUp { + symbolState = [[PKSymbolState alloc] init]; +} + + +- (void)tearDown { + [symbolState release]; + [r release]; +} + + +- (void)testDot { + s = @"."; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testDotA { + s = @".a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testDotSpace { + s = @". "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testDotDot { + s = @".."; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)'.', [r read]); +} + + + +- (void)testAddDotDot { + s = @".."; + [symbolState add:s]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"..", tok.stringValue); + TDEqualObjects(@"..", tok.value); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testAddDotDotSpace { + s = @".. "; + [symbolState add:@".."]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"..", tok.stringValue); + TDEqualObjects(@"..", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testAddColonEqual { + s = @":="; + [symbolState add:s]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@":=", tok.stringValue); + TDEqualObjects(@":=", tok.value); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testAddColonEqualSpace { + s = @":= "; + [symbolState add:@":="]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@":=", tok.stringValue); + TDEqualObjects(@":=", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testAddGtEqualLtSpace { + s = @">=< "; + [symbolState add:@">=<"]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testAddGtEqualLt { + s = @">=<"; + [symbolState add:s]; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [symbolState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTokenzierAddGtEqualLt { + s = @">=<"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:s]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtSpaceFoo { + s = @">=< foo"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@">=<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@"foo", tok.stringValue); + TDEqualObjects(@"foo", tok.value); + TDTrue(tok.isWord); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtFoo { + s = @">==<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@"foo", tok.stringValue); + TDEqualObjects(@"foo", tok.value); + TDTrue(tok.isWord); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtDot { + s = @">=<."; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@">=<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtSpaceDot { + s = @">=< ."; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@">=<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddGtEqualLtSpaceDotSpace { + s = @">=< . "; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@">=<"]; + PKToken *tok = [t nextToken]; + TDEqualObjects(@">=<", tok.stringValue); + TDEqualObjects(@">=<", tok.value); + TDTrue(tok.isSymbol); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddLtBangDashDashSpaceDotSpace { + s = @""; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"-->"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"-->", tok.stringValue); + TDEqualObjects(@"-->", tok.value); + + tok = [t nextToken]; + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDashGtSpaceDot { + s = @"--> ."; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"-->"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"-->", tok.stringValue); + TDEqualObjects(@"-->", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDashGtSpaceDotSpace { + s = @"--> . "; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"-->"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"-->", tok.stringValue); + TDEqualObjects(@"-->", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDash { + s = @"--"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"--"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"--", tok.stringValue); + TDEqualObjects(@"--", tok.value); + + tok = [t nextToken]; + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDashSpaceDot { + s = @"-- ."; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"--"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"--", tok.stringValue); + TDEqualObjects(@"--", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierAddDashDashSpaceDotSpace { + s = @"-- . "; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"--"]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"--", tok.stringValue); + TDEqualObjects(@"--", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDEqualObjects(@".", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualButNotEqual { + s = @"="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualButNotEqualEqual { + s = @"=="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualCompareEqualEqualEqualEqual { + s = @"===="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"===", tok.stringValue); + TDEqualObjects(@"===", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualCompareEqualEqualEqualEqualEqual { + s = @"====="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"===", tok.stringValue); + TDEqualObjects(@"===", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualCompareEqualEqualEqualEqualEqualSpaceEqual { + s = @"===== ="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"==="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"===", tok.stringValue); + TDEqualObjects(@"===", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualEqualEqualEqual { + s = @"===="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualColonEqualButNotEqualColon { + s = @"=:"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"=:="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@":", tok.stringValue); + TDEqualObjects(@":", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierRemoveEqualEqual { + s = @"=="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState remove:@"=="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierRemoveEqualEqualAddEqualEqual { + s = @"===="; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState remove:@"=="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=", tok.stringValue); + TDEqualObjects(@"=", tok.value); + + [t.symbolState add:@"=="]; + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"==", tok.stringValue); + TDEqualObjects(@"==", tok.value); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTokenzierEqualColonEqualAndThenEqualColonEqualColon { + s = @"=:=:"; + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"=:="]; + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"=:=", tok.stringValue); + TDEqualObjects(@"=:=", tok.value); + + tok = [t nextToken]; + TDEqualObjects(@":", tok.stringValue); + TDEqualObjects(@":", tok.value); + TDTrue(tok.isSymbol); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testTrickyCase { + s = @"+++\n+++-\n+++-+"; + + PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; + [t.symbolState add:@"+++"]; + [t.symbolState add:@"+++-+"]; + + PKToken *eof = [PKToken EOFToken]; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+++"); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+++"); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+++-+"); + + tok = [t nextToken]; + TDEquals(eof, tok); +} + +@end diff --git a/test/TDSymbolTest.h b/test/TDSymbolTest.h new file mode 100644 index 0000000..13ae93b --- /dev/null +++ b/test/TDSymbolTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDSymbolTest : SenTestCase { + PKParser *p; + PKAssembly *a; + NSString *s; +} + +@end diff --git a/test/TDSymbolTest.m b/test/TDSymbolTest.m new file mode 100644 index 0000000..b5d15fe --- /dev/null +++ b/test/TDSymbolTest.m @@ -0,0 +1,72 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDSymbolTest.h" + + +@implementation TDSymbolTest + +- (void)tearDown { +} + + +- (void)testDash { + s = @"-"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSymbol symbolWithString:s]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[-]-^", [result description]); +} + + +- (void)testFalseDash { + s = @"-"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSymbol symbolWithString:@"+"]; + + PKAssembly *result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testTrueDash { + s = @"-"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [PKSymbol symbol]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[-]-^", [result description]); +} + + +- (void)testDiscardDash { + s = @"-"; + a = [PKTokenAssembly assemblyWithString:s]; + + p = [[PKSymbol symbolWithString:s] discard]; + + PKAssembly *result = [p bestMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[]-^", [result description]); +} +@end diff --git a/test/TDSyntaxHighlighter.h b/test/TDSyntaxHighlighter.h new file mode 100644 index 0000000..142c738 --- /dev/null +++ b/test/TDSyntaxHighlighter.h @@ -0,0 +1,35 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class PKParser; +@class PKTokenizer; +@class PKParserFactory; +@class TDMiniCSSAssembler; +@class TDGenericAssembler; + +@interface TDSyntaxHighlighter : NSObject { + PKParserFactory *parserFactory; + PKParser *miniCSSParser; + TDMiniCSSAssembler *miniCSSAssembler; + TDGenericAssembler *genericAssembler; + BOOL cacheParsers; + NSMutableDictionary *parserCache; + NSMutableDictionary *tokenizerCache; +} +- (NSAttributedString *)highlightedStringForString:(NSString *)s ofGrammar:(NSString *)grammarName; + +@property (nonatomic) BOOL cacheParsers; // default is NO +@end diff --git a/test/TDSyntaxHighlighter.m b/test/TDSyntaxHighlighter.m new file mode 100644 index 0000000..8c8d70d --- /dev/null +++ b/test/TDSyntaxHighlighter.m @@ -0,0 +1,174 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDSyntaxHighlighter.h" +#import +#import "PKParserFactory.h" +#import "TDMiniCSSAssembler.h" +#import "TDGenericAssembler.h" + +@interface TDSyntaxHighlighter () +- (NSMutableDictionary *)attributesForGrammarNamed:(NSString *)grammarName; +- (PKParser *)parserForGrammarNamed:(NSString *)grammarName; + +// all of the ivars for these properties are lazy loaded in the getters. +// thats so that if an application has syntax highlighting turned off, this class will +// consume much less memory/fewer resources. +@property (nonatomic, retain) PKParserFactory *parserFactory; +@property (nonatomic, retain) PKParser *miniCSSParser; +@property (nonatomic, retain) TDMiniCSSAssembler *miniCSSAssembler; +@property (nonatomic, retain) TDGenericAssembler *genericAssembler; +@property (nonatomic, retain) NSMutableDictionary *parserCache; +@property (nonatomic, retain) NSMutableDictionary *tokenizerCache; +@end + +@implementation TDSyntaxHighlighter + +- (id)init { + if (self = [super init]) { + + } + return self; +} + + +- (void)dealloc { + PKReleaseSubparserTree(miniCSSParser); + for (PKParser *p in parserCache) { + PKReleaseSubparserTree(p); + } + + self.parserFactory = nil; + self.miniCSSParser = nil; + self.miniCSSAssembler = nil; + self.genericAssembler = nil; + self.parserCache = nil; + self.tokenizerCache = nil; + [super dealloc]; +} + + +- (PKParserFactory *)parserFactory { + if (!parserFactory) { + self.parserFactory = [PKParserFactory factory]; + } + return parserFactory; +} + + +- (TDMiniCSSAssembler *)miniCSSAssembler { + if (!miniCSSAssembler) { + self.miniCSSAssembler = [[[TDMiniCSSAssembler alloc] init] autorelease]; + } + return miniCSSAssembler; +} + + +- (PKParser *)miniCSSParser { + if (!miniCSSParser) { + // create mini-css parser + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"mini_css" ofType:@"grammar"]; + NSString *grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + self.miniCSSParser = [self.parserFactory parserFromGrammar:grammarString assembler:self.miniCSSAssembler]; + } + return miniCSSParser; +} + + +- (TDGenericAssembler *)genericAssembler { + if (!genericAssembler) { + self.genericAssembler = [[[TDGenericAssembler alloc] init] autorelease]; + } + return genericAssembler; +} + + +- (NSMutableDictionary *)parserCache { + if (!parserCache) { + self.parserCache = [NSMutableDictionary dictionary]; + } + return parserCache; +} + + +- (NSMutableDictionary *)attributesForGrammarNamed:(NSString *)grammarName { + // parse CSS + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:grammarName ofType:@"css"]; + NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + [self.miniCSSParser bestMatchFor:a]; // produce dict of attributes from the CSS + return self.miniCSSAssembler.attributes; +} + + +- (PKParser *)parserForGrammarNamed:(NSString *)grammarName { + // create parser or the grammar requested or fetch parser from cache + PKParser *parser = nil; + if (cacheParsers) { + parser = [self.parserCache objectForKey:grammarName]; + } + + if (!parser) { + // get attributes from css && give to the generic assembler + parserFactory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnAll; + self.genericAssembler.attributes = [self attributesForGrammarNamed:grammarName]; + + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:grammarName ofType:@"grammar"]; + NSString *grammarString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + // generate a parser for the requested grammar + parserFactory.assemblerSettingBehavior = PKParserFactoryAssemblerSettingBehaviorOnTerminals; + parser = [self.parserFactory parserFromGrammar:grammarString assembler:self.genericAssembler]; + + if (cacheParsers) { + [self.parserCache setObject:parser forKey:grammarName]; + [self.tokenizerCache setObject:parser.tokenizer forKey:grammarName]; + } + } + + return parser; +} + + +- (NSAttributedString *)highlightedStringForString:(NSString *)s ofGrammar:(NSString *)grammarName { + // create or fetch the parser & tokenizer for this grammar + PKParser *parser = [self parserForGrammarNamed:grammarName]; + + // parse the string. take care to preseve the whitespace and comments in the string + parser.tokenizer.string = s; + parser.tokenizer.whitespaceState.reportsWhitespaceTokens = YES; + parser.tokenizer.commentState.reportsCommentTokens = YES; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:parser.tokenizer]; + a.preservesWhitespaceTokens = YES; + + PKAssembly *resultAssembly = [parser completeMatchFor:a]; // finally, parse the input. stores attributed string in resultAssembly.target + + if (!cacheParsers) { + PKReleaseSubparserTree(parser); + } + + id result = [[resultAssembly.target copy] autorelease]; + return result; +} + +@synthesize parserFactory; +@synthesize miniCSSParser; +@synthesize miniCSSAssembler; +@synthesize genericAssembler; +@synthesize cacheParsers; +@synthesize parserCache; +@synthesize tokenizerCache; +@end diff --git a/test/TDTestScaffold.h b/test/TDTestScaffold.h new file mode 100644 index 0000000..4aad9f3 --- /dev/null +++ b/test/TDTestScaffold.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import + +#define TDTrue(e) STAssertTrue((e), @"") +#define TDFalse(e) STAssertFalse((e), @"") +#define TDNil(e) STAssertNil((e), @"") +#define TDNotNil(e) STAssertNotNil((e), @"") +#define TDEquals(e1, e2) STAssertEquals((e1), (e2), @"") +#define TDEqualObjects(e1, e2) STAssertEqualObjects((e1), (e2), @"") diff --git a/test/TDTestScaffold.m b/test/TDTestScaffold.m new file mode 100644 index 0000000..4154388 --- /dev/null +++ b/test/TDTestScaffold.m @@ -0,0 +1,159 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +#define RUN_ALL_TEST_CASES 1 +#define SOLO_TEST_CASE @"TDParserBlocksTest" + +@interface SenTestSuite (TDAdditions) +- (void)addSuitesForClassNames:(NSArray *)classNames; +@end + +SenTestSuite *TDSoloTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Solo Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObject:SOLO_TEST_CASE]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +SenTestSuite *TDTokensTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Tokens Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDReaderTest", + @"TDTokenizerTest", + @"TDTokenizerTest", + @"TDNumberStateTest", + @"TDQuoteStateTest", + @"TDWhitespaceStateTest", + @"TDWordStateTest", + @"TDSlashStateTest", + @"TDSymbolStateTest", + @"TDCommentStateTest", + @"TDDelimitStateTest", + @"TDTokenizerStateTest", +#ifdef TARGET_OS_SNOW_LEOPARD + @"TDTokenizerBlocksTest", + @"TDParserBlocksTest", +#endif + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +SenTestSuite *TDCharsTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Chars Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDCharacterAssemblyTest", + @"TDDigitTest", + @"TDCharTest", + @"TDLetterTest", + @"TDSpecificCharTest", + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +SenTestSuite *TDParseTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"Parse Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDParserTest", + @"TDTokenAssemblyTest", + @"TDLiteralTest", + @"TDPatternTest", + @"TDRepetitionTest", + @"TDSequenceTest", + @"TDAlternationTest", + @"TDSymbolTest", + @"TDRobotCommandTest", + @"TDXmlParserTest", + @"TDJsonParserTest", + @"TDFastJsonParserTest", + @"TDRegularParserTest", + @"SRGSParserTest", + @"EBNFParserTest", + @"TDPlistParserTest", + @"TDXmlNameTest", + @"XPathParserTest", + @"XMLReaderTest", + @"TDXmlTokenizerTest", + @"TDArithmeticParserTest", + @"TDScientificNumberStateTest", + @"TDTokenArraySourceTest", + @"TDDifferenceTest", + @"TDNegationTest", + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +SenTestSuite *TDParserFactoryTestSuite() { + SenTestSuite *suite = [SenTestSuite testSuiteWithName:@"ParserFactory Test Suite"]; + + NSArray *classNames = [NSArray arrayWithObjects: + @"TDParserFactoryTest", + @"TDParserFactoryTest2", + @"TDParserFactoryPatternTest", + @"TDMiniCSSAssemblerTest", + @"TDPredicateEvaluatorTest", + @"TDNSPredicateEvaluatorTest", + @"TDNSPredicateBuilderTest", + @"TDJavaScriptParserTest", + @"TDXMLParserTest", + @"XPathParserGrammarTest", + @"ERBTest", + @"TDParseTreeTest", + @"SAXTest", + nil]; + + [suite addSuitesForClassNames:classNames]; + return suite; +} + +@implementation SenTestSuite (TDAdditions) + ++ (id)testSuiteForBundlePath:(NSString *)path { + SenTestSuite *suite = nil; + +#if RUN_ALL_TEST_CASES + suite = [self defaultTestSuite]; +#else + suite = [self testSuiteWithName:@"My Tests"]; + // [suite addTest:TDCharsTestSuite()]; + // [suite addTest:TDTokensTestSuite()]; + // [suite addTest:TDParseTestSuite()]; + // [suite addTest:TDParserFactoryTestSuite()]; + [suite addTest:TDSoloTestSuite()]; +#endif + + return suite; +} + + +- (void)addSuitesForClassNames:(NSArray *)classNames { + for (NSString *className in classNames) { + SenTestSuite *suite = [SenTestSuite testSuiteForTestCaseWithName:className]; + [self addTest:suite]; + } +} + +@end \ No newline at end of file diff --git a/test/TDToken+Blob.h b/test/TDToken+Blob.h new file mode 100644 index 0000000..5e2a09a --- /dev/null +++ b/test/TDToken+Blob.h @@ -0,0 +1,16 @@ +// +// PKToken+Blob.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +extern const NSInteger PKTokenTypeBlob; + +@interface PKToken (Blob) +- (BOOL)isBlob; +@end + diff --git a/test/TDToken+Blob.m b/test/TDToken+Blob.m new file mode 100644 index 0000000..dea88e7 --- /dev/null +++ b/test/TDToken+Blob.m @@ -0,0 +1,20 @@ +// +// PKToken+Blob.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKToken+Blob.h" + +const NSInteger PKTokenTypeBlob = 200; + +@implementation PKToken (Blob) + +- (BOOL)isBlob { + return PKTokenTypeBlob == self.tokenType; +} + +@end + diff --git a/test/TDTokenArraySourceTest.h b/test/TDTokenArraySourceTest.h new file mode 100644 index 0000000..9542385 --- /dev/null +++ b/test/TDTokenArraySourceTest.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDTokenArraySourceTest : SenTestCase { + PKTokenizer *t; + NSString *d; + NSString *s; + PKTokenArraySource *tas; +} + +@end diff --git a/test/TDTokenArraySourceTest.m b/test/TDTokenArraySourceTest.m new file mode 100644 index 0000000..34f2910 --- /dev/null +++ b/test/TDTokenArraySourceTest.m @@ -0,0 +1,57 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTokenArraySourceTest.h" + +@implementation TDTokenArraySourceTest + +- (void)setUp { +} + + +- (void)testFoo { + d = @";"; + s = @"I came; I saw; I left in peace.;"; + t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + tas = [[[PKTokenArraySource alloc] initWithTokenizer:t delimiter:d] autorelease]; + + TDTrue([tas hasMore]); + NSArray *a = [tas nextTokenArray]; + TDNotNil(a); + TDEquals((NSUInteger)2, [a count]); + TDEqualObjects(@"I", [[a objectAtIndex:0] stringValue]); + TDEqualObjects(@"came", [[a objectAtIndex:1] stringValue]); + + TDTrue([tas hasMore]); + a = [tas nextTokenArray]; + TDNotNil(a); + TDEquals((NSUInteger)2, [a count]); + TDEqualObjects(@"I", [[a objectAtIndex:0] stringValue]); + TDEqualObjects(@"saw", [[a objectAtIndex:1] stringValue]); + + TDTrue([tas hasMore]); + a = [tas nextTokenArray]; + TDNotNil(a); + TDEquals((NSUInteger)5, [a count]); + TDEqualObjects(@"I", [[a objectAtIndex:0] stringValue]); + TDEqualObjects(@"left", [[a objectAtIndex:1] stringValue]); + TDEqualObjects(@"in", [[a objectAtIndex:2] stringValue]); + TDEqualObjects(@"peace", [[a objectAtIndex:3] stringValue]); + TDEqualObjects(@".", [[a objectAtIndex:4] stringValue]); + + TDFalse([tas hasMore]); + a = [tas nextTokenArray]; + TDNil(a); +} +@end diff --git a/test/TDTokenAssemblyTest.h b/test/TDTokenAssemblyTest.h new file mode 100644 index 0000000..d669cb9 --- /dev/null +++ b/test/TDTokenAssemblyTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDTokenAssemblyTest : SenTestCase { + PKAssembly *a; + NSString *s; + PKParser *p; +} + +@end diff --git a/test/TDTokenAssemblyTest.m b/test/TDTokenAssemblyTest.m new file mode 100644 index 0000000..1d78e9a --- /dev/null +++ b/test/TDTokenAssemblyTest.m @@ -0,0 +1,298 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTokenAssemblyTest.h" + +@interface PKAssembly () +- (id)next; +- (BOOL)hasMore; +@property (nonatomic, readonly) NSUInteger length; +@property (nonatomic, readonly) NSUInteger objectsConsumed; +@property (nonatomic, readonly) NSUInteger objectsRemaining; +@end + +@implementation TDTokenAssemblyTest + +- (void)setUp { +} + + +- (void)tearDown { + [p release]; +} + + +#pragma mark - + +- (void)testWordOhSpaceHaiExclamation { + s = @"oh hai!"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)3, [a length]); + + TDEquals((NSUInteger)0, a.objectsConsumed); + TDEquals((NSUInteger)3, a.objectsRemaining); + TDEqualObjects(@"[]^oh/hai/!", [a description]); + TDTrue([a hasMore]); + TDEqualObjects(@"oh", [[a next] stringValue]); + + TDEquals((NSUInteger)1, a.objectsConsumed); + TDEquals((NSUInteger)2, a.objectsRemaining); + TDEqualObjects(@"[]oh^hai/!", [a description]); + TDTrue([a hasMore]); + TDEqualObjects(@"hai", [[a next] stringValue]); + + TDEquals((NSUInteger)2, a.objectsConsumed); + TDEquals((NSUInteger)1, a.objectsRemaining); + TDEqualObjects(@"[]oh/hai^!", [a description]); + TDTrue([a hasMore]); + TDEqualObjects(@"!", [[a next] stringValue]); + + TDEquals((NSUInteger)3, a.objectsConsumed); + TDEquals((NSUInteger)0, a.objectsRemaining); + TDEqualObjects(@"[]oh/hai/!^", [a description]); + TDFalse([a hasMore]); + TDNil([[a next] stringValue]); + + TDEquals((NSUInteger)3, a.objectsConsumed); + TDEquals((NSUInteger)0, a.objectsRemaining); + TDEqualObjects(@"[]oh/hai/!^", [a description]); + TDFalse([a hasMore]); + TDNil([[a next] stringValue]); + + TDEquals((NSUInteger)3, [a length]); +} + + +- (void)testBestMatchForWordFoobar { + s = @"foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^foobar", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[foobar]foobar^", [result description]); + TDFalse(result == a); + + + result = [p bestMatchFor:result]; + TDNil(result); +} + + +- (void)testCompleteMatchForWordFoobar { + s = @"foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^foobar", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDEqualObjects(@"[foobar]foobar^", [result description]); + TDFalse(result == a); +} + + +- (void)testBestMatchForWordFooSpaceBar { + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^foo/bar", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[foo]foo^bar", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForWordFooSpaceBar { + s = @"foo bar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^foo/bar", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testBestMatchForNumFoobar { + s = @"foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^foobar", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testCompleteMatchForNumFoobar { + s = @"foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^foobar", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testBestMatchForWord123 { + s = @"123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^123", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDNil(result); +} + + +- (void)testCompleteMatchForWord123 { + s = @"123"; + a = [PKTokenAssembly assemblyWithString:s]; + + + p = [[PKWord alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^123", [a description]); +} + + +- (void)testBestMatchForNum123 { + s = @"123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^123", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[123]123^", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForNum123 { + s = @"123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)1, [a length]); + TDEqualObjects(@"[]^123", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[123]123^", [result description]); + TDFalse(result == a); +} + + +- (void)testBestMatchForNum123Space456 { + s = @"123 456"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^123/456", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[123]123^456", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForNum123Space456 { + s = @"123 456"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^123/456", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testBestMatchForWordFoobarSpace123 { + s = @"foobar 123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^foobar/123", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[foobar]foobar^123", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForWordFoobarSpace123 { + s = @"foobar 123"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)2, [a length]); + TDEqualObjects(@"[]^foobar/123", [a description]); + + p = [[PKWord alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + + +- (void)testBestMatchForNum123Space456Foobar { + s = @"123 456 foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)3, [a length]); + TDEqualObjects(@"[]^123/456/foobar", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p bestMatchFor:a]; + TDEqualObjects(@"[123]123^456/foobar", [result description]); + TDFalse(result == a); +} + + +- (void)testCompleteMatchForNum123Space456Foobar { + s = @"123 456 foobar"; + a = [PKTokenAssembly assemblyWithString:s]; + + TDEquals((NSUInteger)3, [a length]); + TDEqualObjects(@"[]^123/456/foobar", [a description]); + + p = [[PKNumber alloc] init]; + PKAssembly *result = [p completeMatchFor:a]; + TDNil(result); +} + +@end + diff --git a/test/TDTokenTest.h b/test/TDTokenTest.h new file mode 100644 index 0000000..017ac8a --- /dev/null +++ b/test/TDTokenTest.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDTokenTest : SenTestCase { + PKToken *eof; +} + +@end diff --git a/test/TDTokenTest.m b/test/TDTokenTest.m new file mode 100644 index 0000000..0f3ba00 --- /dev/null +++ b/test/TDTokenTest.m @@ -0,0 +1,94 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTokenTest.h" + +@implementation TDTokenTest + +- (void)setUp { + eof = [PKToken EOFToken]; +} + + +- (void)testEOFTokenReleaseOnce1 { + TDNotNil(eof); + [eof release]; +} + + +- (void)testEOFTokenReleaseOnce2 { + TDNotNil(eof); + [eof release]; +} + + +- (void)testEOFTokenReleaseTwice1 { + TDNotNil(eof); + [eof release]; + TDNotNil(eof); + [eof release]; +} + + +- (void)testEOFTokenReleaseTwice2 { + TDNotNil(eof); + [eof release]; + TDNotNil(eof); + [eof release]; +} + + +- (void)testEOFTokenAutoreleaseOnce1 { + TDNotNil(eof); + [eof autorelease]; +} + + +- (void)testEOFTokenAutoreleaseOnce2 { + TDNotNil(eof); + [eof autorelease]; +} + + +- (void)testEOFTokenAutoreleaseTwice1 { + TDNotNil(eof); + [eof autorelease]; + TDNotNil(eof); + [eof autorelease]; +} + + +- (void)testEOFTokenAutoreleaseTwice2 { + TDNotNil(eof); + [eof autorelease]; + TDNotNil(eof); + [eof autorelease]; +} + + +- (void)testEOFTokenRetainCount { + TDTrue([eof retainCount] >= 17035104); + // NO IDEA WHY THIS WONT PASS + //TDEquals(UINT_MAX, [eof retainCount]); /*17035104 4294967295*/ +// TDEqualObjects([NSNumber numberWithUnsignedInt:4294967295], [NSNumber numberWithUnsignedInt:[eof retainCount]]); +} + + +- (void)testCopyIdentity { + id copy = [eof copy]; + TDTrue(copy == eof); + [copy release]; // appease clang sa +} + +@end diff --git a/test/TDTokenizer+BlobState.h b/test/TDTokenizer+BlobState.h new file mode 100644 index 0000000..fa2d019 --- /dev/null +++ b/test/TDTokenizer+BlobState.h @@ -0,0 +1,15 @@ +// +// PKTokenizer+BlobState.h +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import + +@class TDBlobState; + +@interface PKTokenizer (BlobState) +- (TDBlobState *)blobState; +@end diff --git a/test/TDTokenizer+BlobState.m b/test/TDTokenizer+BlobState.m new file mode 100644 index 0000000..f880358 --- /dev/null +++ b/test/TDTokenizer+BlobState.m @@ -0,0 +1,36 @@ +// +// PKTokenizer+BlobState.m +// ParseKit +// +// Created by Todd Ditchendorf on 6/7/09. +// Copyright 2009 Todd Ditchendorf. All rights reserved. +// + +#import "PKTokenizer+BlobState.h" +#import "TDBlobState.h" + +static NSMutableDictionary *sBlobCache = nil; + +@implementation PKTokenizer (BlobState) + +- (TDBlobState *)blobState { + TDBlobState *bs = nil; + + @synchronized (self) { + if (!sBlobCache) { + sBlobCache = [[NSMutableDictionary alloc] init]; + } + + NSString *key = [NSString stringWithFormat:@"%p", self]; + bs = [sBlobCache objectForKey:key]; + + if (!bs) { + bs = [[[TDBlobState alloc] init] autorelease]; + [sBlobCache setObject:bs forKey:key]; + } + } + + return bs; +} + +@end diff --git a/test/TDTokenizerBlocksTest.h b/test/TDTokenizerBlocksTest.h new file mode 100644 index 0000000..9b695bb --- /dev/null +++ b/test/TDTokenizerBlocksTest.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@class PKTokenizer; + +@interface TDTokenizerBlocksTest : SenTestCase { + PKTokenizer *t; + NSString *s; +} + +@end diff --git a/test/TDTokenizerBlocksTest.m b/test/TDTokenizerBlocksTest.m new file mode 100644 index 0000000..13df4f4 --- /dev/null +++ b/test/TDTokenizerBlocksTest.m @@ -0,0 +1,44 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTokenizerBlocksTest.h" + +@implementation TDTokenizerBlocksTest + +- (void)setUp { +} + + +- (void)tearDown { +} + + +#ifdef TARGET_OS_SNOW_LEOPARD +- (void)testBlastOff { + s = @"\"It's 123 blast-off!\", she said, // watch out!\n" + @"and <= 3 'ticks' later /* wince */, it's blast-off!"; + t = [PKTokenizer tokenizerWithString:s]; + + NSLog(@"\n\n starting!!! \n\n"); + + [t enumerateTokensUsingBlock:^(PKToken *tok, BOOL *stop) { + NSLog(@"(%@)", tok.stringValue); + }]; + + + NSLog(@"\n\n done!!! \n\n"); +} +#endif + +@end diff --git a/test/TDTokenizerStateTest.h b/test/TDTokenizerStateTest.h new file mode 100644 index 0000000..368a931 --- /dev/null +++ b/test/TDTokenizerStateTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDTokenizerStateTest : SenTestCase { + PKTokenizer *t; + NSString *s; + PKToken *tok; +} + +@end diff --git a/test/TDTokenizerStateTest.m b/test/TDTokenizerStateTest.m new file mode 100644 index 0000000..d1f9699 --- /dev/null +++ b/test/TDTokenizerStateTest.m @@ -0,0 +1,178 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTokenizerStateTest.h" + +@implementation TDTokenizerStateTest + +- (void)setUp { + t = [[PKTokenizer alloc] init]; +} + + +- (void)tearDown { + [t release]; +} + + +- (void)testFallbackStateCast { + [t setTokenizerState:t.symbolState from:'c' to:'c']; + [t.symbolState setFallbackState:t.wordState from:'c' to:'c']; + [t.symbolState add:@"cast"]; + + t.string = @"foo cast cat"; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"cast", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"c", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"at", tok.stringValue); + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testFallbackStateCastAs { + [t setTokenizerState:t.symbolState from:'c' to:'c']; + [t.symbolState setFallbackState:t.wordState from:'c' to:'c']; + [t.symbolState add:@"cast as"]; + + t.string = @"foo cast as cat"; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"cast as", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"c", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"at", tok.stringValue); + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testTrickyFwdSlash { + [t.delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:nil]; + + [t setTokenizerState:t.commentState from:'#' to:'#']; + [t setTokenizerState:t.commentState from:'/' to:'/']; + + [t.commentState addSingleLineStartMarker:@"##"]; + [t.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + t.commentState.fallbackState = t.symbolState; + [t.commentState setFallbackState:t.delimitState from:'/' to:'/']; + + t.string = @"foo /bar/ /*## */ # baz ## ja"; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(@"/bar/", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"#", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"baz", tok.stringValue); + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testTrickyFwdSlash2 { + [t.delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:nil]; + + [t setTokenizerState:t.commentState from:'#' to:'#']; + [t setTokenizerState:t.commentState from:'/' to:'/']; + + [t.commentState addSingleLineStartMarker:@"##"]; + [t.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + t.commentState.fallbackState = t.symbolState; + [t.commentState setFallbackState:t.delimitState from:'/' to:'/']; + + t.string = @"## ja"; + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + + +- (void)testTrickyFwdSlash3 { + [t.delimitState addStartMarker:@"/" endMarker:@"/" allowedCharacterSet:nil]; + + [t setTokenizerState:t.commentState from:'#' to:'#']; + [t setTokenizerState:t.commentState from:'/' to:'/']; + + [t.commentState addSingleLineStartMarker:@"##"]; + [t.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"]; + + t.commentState.fallbackState = t.delimitState; + [t.commentState setFallbackState:t.symbolState from:'#' to:'#']; + + t.string = @"foo /bar/ /*## */ # baz ## ja"; + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"foo", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isDelimitedString); + TDEqualObjects(@"/bar/", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(@"#", tok.stringValue); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(@"baz", tok.stringValue); + + tok = [t nextToken]; + TDEqualObjects(nil, tok.stringValue); + TDTrue([PKToken EOFToken] == tok); +} + +@end diff --git a/test/TDTokenizerTest.h b/test/TDTokenizerTest.h new file mode 100644 index 0000000..bdd2c38 --- /dev/null +++ b/test/TDTokenizerTest.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@class PKTokenizer; + +@interface TDTokenizerTest : SenTestCase { + PKTokenizer *t; + NSString *s; +} + +@end diff --git a/test/TDTokenizerTest.m b/test/TDTokenizerTest.m new file mode 100644 index 0000000..a168834 --- /dev/null +++ b/test/TDTokenizerTest.m @@ -0,0 +1,627 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTokenizerTest.h" +#import "ParseKit.h" + +@implementation TDTokenizerTest + +- (void)setUp { +} + + +- (void)tearDown { +} + + +- (void)testBlastOff { + s = @"\"It's 123 blast-off!\", she said, // watch out!\n" + @"and <= 3 'ticks' later /* wince */, it's blast-off!"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + //NSLog(@"\n\n starting!!! \n\n"); + while ((tok = [t nextToken]) != eof) { + //NSLog(@"(%@)", tok.stringValue); + } + //NSLog(@"\n\n done!!! \n\n"); + +} + +- (void)testStuff { + s = @"2 != 47. Blast-off!! 'Woo-hoo!'"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + while ((tok = [t nextToken]) != eof) { + //NSLog(@"(%@) (%.1f) : %@", tok.stringValue, tok.floatValue, [tok debugDescription]); + } +} + + +- (void)testStuff2 { + s = @"2 != 47. Blast-off!! 'Woo-hoo!'"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"2"); + TDEqualObjects(tok.value, [NSNumber numberWithFloat:2.0]); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"!="); + TDEqualObjects(tok.value, @"!="); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"47"); + TDEqualObjects(tok.value, [NSNumber numberWithFloat:47.0]); + TDEquals(tok.offset, (NSUInteger)5); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEqualObjects(tok.value, @"."); + TDEquals(tok.offset, (NSUInteger)7); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"Blast-off"); + TDEqualObjects(tok.value, @"Blast-off"); + TDEquals(tok.offset, (NSUInteger)9); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"!"); + TDEqualObjects(tok.value, @"!"); + TDEquals(tok.offset, (NSUInteger)18); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"!"); + TDEqualObjects(tok.value, @"!"); + TDEquals(tok.offset, (NSUInteger)19); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isQuotedString); + TDEqualObjects(tok.stringValue, @"'Woo-hoo!'"); + TDEqualObjects(tok.value, @"'Woo-hoo!'"); + TDEquals(tok.offset, (NSUInteger)21); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok == eof); + TDEquals(tok.offset, (NSUInteger)PKEOF); +} + + +- (void)testFortySevenDot { + s = @"47."; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"47"); + TDEqualObjects(tok.value, [NSNumber numberWithFloat:47.0]); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEqualObjects(tok.value, @"."); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok == eof); + TDEquals(tok.offset, (NSUInteger)PKEOF); +} + + +- (void)testFortySevenDotSpaceFoo { + s = @"47. foo"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"47"); + TDEqualObjects(tok.value, [NSNumber numberWithFloat:47.0]); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEqualObjects(tok.value, @"."); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok != eof); + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"foo"); + TDEqualObjects(tok.value, @"foo"); + TDEquals(tok.offset, (NSUInteger)4); + + tok = [t nextToken]; + TDNotNil(tok); + TDTrue(tok == eof); + TDEquals(tok.offset, (NSUInteger)PKEOF); +} + + +- (void)testDotOne { + s = @" .999"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + STAssertEqualsWithAccuracy((CGFloat)0.999, tok.floatValue, 0.01, @""); + TDTrue(tok.isNumber); + TDEquals(tok.offset, (NSUInteger)3); + +// if ([PKToken EOFToken] == token) break; + +} + + +- (void)testSpaceDotSpace { + s = @" . "; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@".", tok.stringValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)1); + + // if ([PKToken EOFToken] == token) break; + +} + + +- (void)testInitSig { + s = @"- (id)init {"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@"-", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(@"(", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)2); +} + + +- (void)testInitSig2 { + s = @"-(id)init {"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@"-", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(@"(", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)1); +} + + +- (void)testMinusSpaceTwo { + s = @"- 2"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@"-", tok.stringValue); + TDEquals((CGFloat)0.0, tok.floatValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(@"2", tok.stringValue); + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEquals(tok.offset, (NSUInteger)2); +} + + +- (void)testMinusPlusTwo { + s = @"+2"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDEqualObjects(@"+", tok.stringValue); + TDTrue(tok.isSymbol); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"2", tok.stringValue); + TDEquals(tok.offset, (NSUInteger)1); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testMinusPlusTwoCustom { + s = @"+2"; + t = [PKTokenizer tokenizerWithString:s]; + [t setTokenizerState:t.numberState from:'+' to:'+']; + + PKToken *tok = [t nextToken]; + TDEquals((CGFloat)2.0, tok.floatValue); + TDTrue(tok.isNumber); + TDEqualObjects(@"+2", tok.stringValue); + TDEquals(tok.offset, (NSUInteger)0); + + TDEquals([PKToken EOFToken], [t nextToken]); +} + + +- (void)testSimpleAPIUsage { + s = @". , () 12.33333 .:= .456\n\n>=< 'boooo'fasa this should /* not*/ appear \r /*but */this should >==<"]; + + NSMutableArray *toks = [NSMutableArray array]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *token = nil; + while (token = [t nextToken]) { + if (eof == token) break; + + [toks addObject:token]; + + } + + //NSLog(@"\n\n\n\ntoks: %@\n\n\n\n", toks); +} + + +- (void)testKatakana1 { + s = @"ア"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = [t nextToken]; + + TDNotNil(tok); + TDTrue(tok.isWord); + TDEqualObjects(s, tok.stringValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(eof, tok); +} + + +- (void)testKatakana2 { + s = @"アア"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = [t nextToken]; + + TDNotNil(tok); + TDTrue(tok.isWord); + TDEqualObjects(s, tok.stringValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(eof, tok); +} + + +- (void)testKatakana3 { + s = @"アェ"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = [t nextToken]; + + TDNotNil(tok); + TDTrue(tok.isWord); + TDEqualObjects(s, tok.stringValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDEqualObjects(eof, tok); +} + + +- (void)testParenStuff { + s = @"-(ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)4); + + tok = [t nextToken]; + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"5"); + TDEquals((CGFloat)5.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)5); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @")"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)6); +} + + +- (void)testParenStuff2 { + s = @"- (ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"-"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)3); +} + + +- (void)testParenStuff3 { + s = @"+(ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)4); + + tok = [t nextToken]; + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"5"); + TDEquals((CGFloat)5.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)5); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @")"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)6); +} + + +- (void)testParenStuff4 { + s = @"+ (ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)3); +} + + +- (void)testParenStuff5 { + s = @".(ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"+"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)4); + + tok = [t nextToken]; + TDTrue(tok.isNumber); + TDEqualObjects(tok.stringValue, @"5"); + TDEquals((CGFloat)5.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)5); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @")"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)6); +} + + +- (void)testParenStuff6 { + s = @". (ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + t.whitespaceState.reportsWhitespaceTokens = YES; + + PKToken *tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"."); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)0); + + tok = [t nextToken]; + TDTrue(tok.isWhitespace); + TDEqualObjects(tok.stringValue, @" "); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)1); + + tok = [t nextToken]; + TDTrue(tok.isSymbol); + TDEqualObjects(tok.stringValue, @"("); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)2); + + tok = [t nextToken]; + TDTrue(tok.isWord); + TDEqualObjects(tok.stringValue, @"ab"); + TDEquals((CGFloat)0.0, tok.floatValue); + TDEquals(tok.offset, (NSUInteger)3); +} + + +- (void)testParenStuff7 { + s = @"-(ab+5)"; + t = [PKTokenizer tokenizerWithString:s]; + + NSMutableString *final = [NSMutableString string]; + + PKToken *eof = [PKToken EOFToken]; + PKToken *tok = nil; + while ((tok = [t nextToken]) != eof) { + [final appendString:[tok stringValue]]; + } + + TDNotNil(tok); + TDEqualObjects(final, s); + TDEqualObjects(eof, [t nextToken]); +} + +@end diff --git a/test/TDTrackTest.h b/test/TDTrackTest.h new file mode 100644 index 0000000..25ae2bb --- /dev/null +++ b/test/TDTrackTest.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDTrackTest : SenTestCase { + +} + +@end diff --git a/test/TDTrackTest.m b/test/TDTrackTest.m new file mode 100644 index 0000000..a080845 --- /dev/null +++ b/test/TDTrackTest.m @@ -0,0 +1,118 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTrackTest.h" +#import "ParseKit.h" + + +@implementation TDTrackTest + +// list = '(' contents ')' +// contents = empty | actualList +// actualList = Word (',' Word)* + + +- (PKParser *)listParser { + PKTrack *commaWord = [PKTrack track]; + [commaWord add:[[PKSymbol symbolWithString:@","] discard]]; + [commaWord add:[PKWord word]]; + + PKSequence *actualList = [PKSequence sequence]; + [actualList add:[PKWord word]]; + [actualList add:[PKRepetition repetitionWithSubparser:commaWord]]; + + PKAlternation *contents = [PKAlternation alternation]; + [contents add:[PKEmpty empty]]; + [contents add:actualList]; + + PKTrack *list = [PKTrack track]; + [list add:[[PKSymbol symbolWithString:@"("] discard]]; + [list add:contents]; + [list add:[[PKSymbol symbolWithString:@")"] discard]]; + + return list; +} + + +#ifndef TARGET_CPU_X86_64 +- (void)testTrack { + + PKParser *list = [self listParser]; + + NSArray *test = [NSArray arrayWithObjects: + @"()", + @"(pilfer)", + @"(pilfer, pinch)", + @"(pilfer, pinch, purloin)", + @"(pilfer, pinch,, purloin)", + @"(", + @"(pilfer", + @"(pilfer, ", + @"(, pinch, purloin)", + @"pilfer, pinch", + nil]; + + for (NSString *s in test) { + //NSLog(@"\n----testing: %@", s); + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + @try { + PKAssembly *result = [list completeMatchFor:a]; + if (!result) { + //NSLog(@"[list completeMatchFor:] returns nil"); + } else { + //NSString *stack = [[[list completeMatchFor:a] stack] description]; + //NSLog(@"OK stack is: %@", stack); + } + } @catch (PKTrackException *e) { + //NSLog(@"\n\n%@\n\n", [e reason]); + } + } + +} + + +- (void)testMissingParen { + PKParser *open = [PKSymbol symbolWithString:@"("]; + PKParser *close = [PKSymbol symbolWithString:@")"]; + PKTrack *track = [PKTrack trackWithSubparsers:open, close, nil]; + + PKAssembly *a = [PKTokenAssembly assemblyWithString:@"("]; + STAssertThrowsSpecificNamed([track completeMatchFor:a], PKTrackException, PKTrackExceptionName, @""); + + @try { + [track completeMatchFor:a]; + STAssertTrue(0, @"Should not be reached"); + } @catch (PKTrackException *e) { + TDEqualObjects([e class], [PKTrackException class]); + TDEqualObjects([e name], PKTrackExceptionName); + + NSDictionary *userInfo = e.userInfo; + TDNotNil(userInfo); + + NSString *after = [userInfo objectForKey:@"after"]; + NSString *expected = [userInfo objectForKey:@"expected"]; + NSString *found = [userInfo objectForKey:@"found"]; + + TDNotNil(after); + TDNotNil(expected); + TDNotNil(found); + + TDEqualObjects(after, @"("); + TDEqualObjects(expected, @"Symbol )"); + TDEqualObjects(found, @"-nothing-"); + } +} +#endif + +@end diff --git a/test/TDUppercaseWordTest.h b/test/TDUppercaseWordTest.h new file mode 100644 index 0000000..1092cf5 --- /dev/null +++ b/test/TDUppercaseWordTest.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDUppercaseWordTest : SenTestCase { + +} + +@end diff --git a/test/TDUppercaseWordTest.m b/test/TDUppercaseWordTest.m new file mode 100644 index 0000000..04fcc94 --- /dev/null +++ b/test/TDUppercaseWordTest.m @@ -0,0 +1,64 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDUppercaseWordTest.h" +#import "ParseKit.h" + +@implementation TDUppercaseWordTest + +- (void)testFoobar { + NSString *s = @"Foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKUppercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNotNil(result); + TDEqualObjects(@"[Foobar]Foobar^", [result description]); +} + + +- (void)testfoobar { + NSString *s = @"foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKUppercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)test123 { + NSString *s = @"123"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKUppercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + + +- (void)testPercentFoobar { + NSString *s = @"%Foobar"; + PKAssembly *a = [PKTokenAssembly assemblyWithString:s]; + + PKParser *p = [PKUppercaseWord word]; + PKAssembly *result = [p completeMatchFor:a]; + + TDNil(result); +} + +@end diff --git a/test/TDWhitespaceStateTest.h b/test/TDWhitespaceStateTest.h new file mode 100644 index 0000000..f935871 --- /dev/null +++ b/test/TDWhitespaceStateTest.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDWhitespaceStateTest : SenTestCase { + PKWhitespaceState *whitespaceState; + PKReader *r; + NSString *s; +} +@end diff --git a/test/TDWhitespaceStateTest.m b/test/TDWhitespaceStateTest.m new file mode 100644 index 0000000..e21e429 --- /dev/null +++ b/test/TDWhitespaceStateTest.m @@ -0,0 +1,330 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDWhitespaceStateTest.h" + + +@implementation TDWhitespaceStateTest + +- (void)setUp { + whitespaceState = [[PKWhitespaceState alloc] init]; +} + + +- (void)tearDown { + [whitespaceState release]; + [r release]; +} + + +- (void)testSpace { + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTwoSpaces { + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testNil { + s = nil; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testNull { + s = NULL; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testEmptyString { + s = @""; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTab { + s = @"\t"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testNewLine { + s = @"\n"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testCarriageReturn { + s = @"\r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSpaceCarriageReturn { + s = @" \r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSpaceTabNewLineSpace { + s = @" \t\n "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSpaceA { + s = @" a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + +- (void)testSpaceASpace { + s = @" a "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testTabA { + s = @"\ta"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testNewLineA { + s = @"\na"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testCarriageReturnA { + s = @"\ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testNewLineSpaceCarriageReturnA { + s = @"\n \ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNil(tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +#pragma mark - +#pragma mark Significant + +- (void)testSignificantSpace { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantTwoSpaces { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantEmptyString { + whitespaceState.reportsWhitespaceTokens = YES; + s = @""; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantTab { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\t"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantNewLine { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\n"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantCarriageReturn { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantSpaceCarriageReturn { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" \r"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantSpaceTabNewLineSpace { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" \t\n "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(s, tok.stringValue); + TDEquals(PKEOF, [r read]); +} + + +- (void)testSignificantSpaceA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@" ", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantSpaceASpace { + whitespaceState.reportsWhitespaceTokens = YES; + s = @" a "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@" ", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantTabA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\ta"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@"\t", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantNewLineA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\na"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@"\n", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantCarriageReturnA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@"\r", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + + +- (void)testSignificantNewLineSpaceCarriageReturnA { + whitespaceState.reportsWhitespaceTokens = YES; + s = @"\n \ra"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [whitespaceState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDNotNil(tok); + TDEqualObjects(@"\n \r", tok.stringValue); + TDEquals((PKUniChar)'a', [r read]); +} + +@end \ No newline at end of file diff --git a/test/TDWordOrReservedState.h b/test/TDWordOrReservedState.h new file mode 100644 index 0000000..19cea58 --- /dev/null +++ b/test/TDWordOrReservedState.h @@ -0,0 +1,31 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +/*! + @class TDWordOrReservedState + @brief Override PKWordState to return known reserved words as tokens of type TDTT_RESERVED. +*/ +@interface TDWordOrReservedState : PKWordState { + NSMutableSet *reservedWords; +} + +/*! + @brief Adds the specified string as a known reserved word. + @param s reserved word to add +*/ +- (void)addReservedWord:(NSString *)s; +@end diff --git a/test/TDWordOrReservedState.m b/test/TDWordOrReservedState.m new file mode 100644 index 0000000..b8ead74 --- /dev/null +++ b/test/TDWordOrReservedState.m @@ -0,0 +1,48 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDWordOrReservedState () +@property (nonatomic, retain) NSMutableSet *reservedWords; +@end + +@implementation TDWordOrReservedState + +- (id)init { + if (self = [super init]) { + self.reservedWords = [NSMutableSet set]; + } + return self; +} + + +- (void)dealloc { + self.reservedWords = nil; + [super dealloc]; +} + + +- (void)addReservedWord:(NSString *)s { + [reservedWords addObject:s]; +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + NSParameterAssert(r); + return nil; +} + +@synthesize reservedWords; +@end diff --git a/test/TDWordStateTest.h b/test/TDWordStateTest.h new file mode 100644 index 0000000..2e72a4a --- /dev/null +++ b/test/TDWordStateTest.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDWordStateTest : SenTestCase { + PKWordState *wordState; + PKReader *r; + NSString *s; +} +@end diff --git a/test/TDWordStateTest.m b/test/TDWordStateTest.m new file mode 100644 index 0000000..c751994 --- /dev/null +++ b/test/TDWordStateTest.m @@ -0,0 +1,118 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDWordStateTest.h" + + +@implementation TDWordStateTest + +- (void)setUp { + wordState = [[PKWordState alloc] init]; +} + + +- (void)tearDown { + [wordState release]; + [r release]; +} + + +- (void)testA { + s = @"a"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"a", tok.stringValue); + TDEqualObjects(@"a", tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testASpace { + s = @"a "; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(@"a", tok.stringValue); + TDEqualObjects(@"a", tok.value); + TDTrue(tok.isWord); + TDEquals((PKUniChar)' ', [r read]); +} + + +- (void)testAb { + s = @"ab"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testAbc { + s = @"abc"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testItApostropheS { + s = @"it's"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTwentyDashFive { + s = @"twenty-five"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testTwentyUnderscoreFive { + s = @"twenty_five"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + + +- (void)testNumber1 { + s = @"number1"; + r = [[PKReader alloc] initWithString:s]; + PKToken *tok = [wordState nextTokenFromReader:r startingWith:[r read] tokenizer:nil]; + TDEqualObjects(s, tok.stringValue); + TDEqualObjects(s, tok.value); + TDTrue(tok.isWord); + TDEquals(PKEOF, [r read]); +} + +@end diff --git a/test/TDXMLParser.h b/test/TDXMLParser.h new file mode 100644 index 0000000..f1d3221 --- /dev/null +++ b/test/TDXMLParser.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface TDXMLParser : NSObject { + +} + +@end diff --git a/test/TDXMLParser.m b/test/TDXMLParser.m new file mode 100644 index 0000000..e1ba806 --- /dev/null +++ b/test/TDXMLParser.m @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXMLParser.h" + +@implementation TDXMLParser + + + +@end diff --git a/test/TDXMLParserTest.h b/test/TDXMLParserTest.h new file mode 100644 index 0000000..92cf2d5 --- /dev/null +++ b/test/TDXMLParserTest.h @@ -0,0 +1,27 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface TDXMLParserTest : SenTestCase { + NSString *s; + NSString *g; + PKParserFactory *factory; + PKTokenAssembly *a; + PKAssembly *res; + PKParser *p; + PKTokenizer *t; +} + +@end diff --git a/test/TDXMLParserTest.m b/test/TDXMLParserTest.m new file mode 100644 index 0000000..679f671 --- /dev/null +++ b/test/TDXMLParserTest.m @@ -0,0 +1,429 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXMLParserTest.h" + +@implementation TDXMLParserTest + +- (void)setUp { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xml" ofType:@"grammar"]; + g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + factory = [PKParserFactory factory]; + p = [factory parserFromGrammar:g assembler:self]; + t = p.tokenizer; +} + + +- (void)testSTag { + PKParser *sTag = [p parserNamed:@"sTag"]; + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, , >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, \t, >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, \n , >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, , bar, =, 'baz', >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, , bar, =, 'baz', , baz, =, 'bat', >]^", [res description]); + + t.string = @""; + res = [sTag bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, , bar, =, 'baz', , baz, =, \t, 'bat', >]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDEqualObjects(@"[<, foo, />]^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, ]/^", [res description]); + + t.string = @" "; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, , ]/ /^", [res description]); + + t.string = @"&bar;"; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &, bar, ;, ]/&/bar/;/^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#, 20, ;, ]/&#/20/;/^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, ]/&#x/FF20/;/^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , ]/&#x/FF20/;/ /^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, , ]//^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , ]/&#x/FF20/;//^", [res description]); + + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , , ]/&#x/FF20/;/ //^", [res description]); +} + + +- (void)testSmallSTagGrammar { + g = @"@delimitState='<';@reportsWhitespaceTokens=YES;@start=sTag;sTag='<' name (S attribute)* S? '>';name=/[^-:\\.]\\w+/;attribute=name eq attValue;eq=S? '=' S?;attValue=QuotedString;"; + PKParser *sTag = [factory parserFromGrammar:g assembler:nil]; + t = sTag.tokenizer; + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [sTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, >]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [sTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, , >]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [sTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, \n, >]^", [res description]); + + t.string = @"< foo>"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [sTag bestMatchFor:a]; + TDNil(res); +} + + +- (void)testSmallETagGrammar { + g = @"@symbols = '&#' '&#x' '' '' nil; @delimitedString='' nil; @delimitedString='' nil;" + @"@reportsWhitespaceTokens = YES;" + @"@start = eTag;" + @"eTag='';" + @"name=/[^-:\\.]\\w+/;"; + + PKParser *eTag = [factory parserFromGrammar:g assembler:nil]; + t = eTag.tokenizer; + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eTag bestMatchFor:a]; + TDEqualObjects(@"[]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eTag bestMatchFor:a]; + TDEqualObjects(@"[]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eTag bestMatchFor:a]; + TDNil(res); + + t.string = @"< /foo>"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [eTag bestMatchFor:a]; + TDNil(res); +} + + +- (void)testETag { + t.string = @""; + res = [[p parserNamed:@"eTag"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); +} + + +- (void)test1 { + t.string = @""; + res = [[p parserNamed:@"element"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, ]/^", [res description]); + + t.string = @""; + res = [[p parserNamed:@"emptyElemTag"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, />]^", [res description]); +} + + +- (void)testSmallEmptyElemTagGrammar { + g = @"@delimitState='<';@symbols='/>';@reportsWhitespaceTokens=YES;@start=emptyElemTag;emptyElemTag='<' name (S attribute)* S? '/>';name=/[^-:\\.]\\w+/;attribute=name eq attValue;eq=S? '=' S?;attValue=QuotedString;"; + PKParser *emptyElemTag = [factory parserFromGrammar:g assembler:nil]; + t = emptyElemTag.tokenizer; + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [emptyElemTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, />]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [emptyElemTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, , />]^", [res description]); + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [emptyElemTag bestMatchFor:a]; + TDEqualObjects(@"[<, foo, , bar, =, 'baz', />]^", [res description]); +} + + +- (void)testSmallCharDataGrammar { + g = @"@symbols = '&#' '&#x' '' '' nil '' nil '' nil;" + @"@reportsWhitespaceTokens = YES;" + @"@start = charData+;" + @"charData = /[^<\\&]+/ - (/[^\\]]*\\]\\]>[^<\\&]*/);"; + + PKParser *charData = [factory parserFromGrammar:g assembler:nil]; + t = charData.tokenizer; + + t.string = @" "; + res = [charData bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[ ] ^", [res description]); + + t.string = @"foo % 1"; + res = [charData bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, , %, , 1]foo/ /%/ /1^", [res description]); + + t.string = @"foo & 1"; + res = [charData bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo, ]foo/ ^&/ /1", [res description]); +} + + +- (void)testSmallElementGrammar { + g = @"@symbols = '&#' '&#x' '' '' nil '' nil '' nil;" + @"@reportsWhitespaceTokens = YES;" + @"@start = element;" + @"element = emptyElemTag | sTag content eTag;" + @"eTag = '';" + @"sTag = '<' name (S attribute)* S? '>';" + @"emptyElemTag = '<' name (S attribute)* S? '/>';" + //@"content = Empty | (element | reference | cdSect | pi | comment | charData)+;" + @"content = Empty | (element | reference | cdSect | charData)+;" + @"name = /[^-:\\.]\\w+/;" + @"attribute = name eq attValue;" + @"eq=S? '=' S?;" + @"attValue = QuotedString;" + @"charData = /[^<\\&]+/ - (/[^\\]]*\\]\\]>[^<\\&]*/);" + @"reference = entityRef | charRef;" + @"entityRef = '&' name ';';" + @"charRef = '&#' /[0-9]+/ ';' | '&#x' /[0-9a-fA-F]+/ ';';" + @"cdSect = DelimitedString('');" + ; + + PKParser *element = [factory parserFromGrammar:g assembler:nil]; + t = element.tokenizer; + + t.string = @""; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [element bestMatchFor:a]; + TDEqualObjects(@"[<, foo, />]^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, ]/^", [res description]); + + t.string = @" "; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, , ]/ /^", [res description]); + + t.string = @"&bar;"; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &, bar, ;, ]/&/bar/;/^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#, 20, ;, ]/&#/20/;/^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, ]/&#x/FF20/;/^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , ]/&#x/FF20/;/ /^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, , ]//^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , ]/&#x/FF20/;//^", [res description]); + + t.string = @""; + res = [element bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[<, foo, >, &#x, FF20, ;, , , ]/&#x/FF20/;/ //^", [res description]); +} + + +// [1] +- (void)testDocument { + // xmlDecl = ''; + t.string = @""; + res = [[p parserNamed:@"document"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[, <, foo, >, ]//^", [res description]); + + // xmlDecl = ''; + t.string = @""; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[, <, foo, >, ]//^", [res description]); + + // xmlDecl = ''; + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"xml"]; + t.string = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + NSDate *d = [NSDate date]; + res = [p bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + NSLog(@"time: %d", [d timeIntervalSinceNow]); + TDNotNil(res); + TDTrue([[res description] hasSuffix:@"^"]); +} + + +// [2] +- (void)test { + +} + + +// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) +// charData = /[^<\&]+/ - (/[^\]]*\]\]>[^<\&]*/); +- (void)testCharData { + t.string = @"foo"; + res = [[p parserNamed:@"charData"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[foo]foo^", [res description]); + + t.string = @"fo' +// comment = DelimitedString(''); +- (void)testComment { + t.string = @""; + res = [[p parserNamed:@"comment"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + + +} + + +// [16] PI ::= '' Char*)))? '?>' +// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) +// pi = '/* '?>'; +// piTarget = name - /xml/i; + +- (void)testPI { + NSString *gram = + @"@reportsWhitespaceTokens=YES;" + @"@symbols='';" + @"@symbolState = '<';" + @"name=/[^-:\\.]\\w+/;" + @"piTarget = name - /xml/i;" + @"@wordState = ':' '.' '-' '_';" + @"@wordChars = ':' '.' '-' '_';" + @"pi = '/* '?>';" + @"@start = pi;"; + PKParser *pi = [[PKParserFactory factory] parserFromGrammar:gram assembler:nil]; + pi.tokenizer.string = @""; + res = [pi bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:pi.tokenizer]]; + TDEqualObjects(@"[]^", [res description]); + + t.string = @""; + res = [[p parserNamed:@"pi"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + + t.string = @""; + res = [[p parserNamed:@"pi"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + +} + + +// [23] XMLDecl ::= '' +// xmlDecl = ''; +- (void)testXmlDecl { +// versionNum = /(['"])1\.[0-9]\1/; +// versionInfo = S 'version' eq versionNum; + + t.string = @" version='1.0'"; + res = [[p parserNamed:@"versionInfo"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[ , version, =, '1.0'] /version/=/'1.0'^", [res description]); + + // encodingDecl = S 'encoding' eq QuotedString; # TODO + t.string = @" encoding='UTF-8'"; + res = [[p parserNamed:@"encodingDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[ , encoding, =, 'UTF-8'] /encoding/=/'UTF-8'^", [res description]); + + // sdDecl = S 'standalone' eq QuotedString; # /(["'])(yes|no)\1/; # TODO + t.string = @" standalone='no'"; + res = [[p parserNamed:@"sdDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[ , standalone, =, 'no'] /standalone/=/'no'^", [res description]); + + t.string = @"'; + t.string = @""; + res = [[p parserNamed:@"xmlDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + + // xmlDecl = ''; + t.string = @""; + res = [[p parserNamed:@"xmlDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + + // xmlDecl = ''; + t.string = @""; + res = [[p parserNamed:@"xmlDecl"] bestMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[]^", [res description]); + +} + + +@end diff --git a/test/TDXmlAttribute.h b/test/TDXmlAttribute.h new file mode 100644 index 0000000..4e11711 --- /dev/null +++ b/test/TDXmlAttribute.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlAttribute : TDXmlTerminal { + +} ++ (id)attribute; ++ (id)attributeWithString:(NSString *)s; +@end diff --git a/test/TDXmlAttribute.m b/test/TDXmlAttribute.m new file mode 100644 index 0000000..3258a9e --- /dev/null +++ b/test/TDXmlAttribute.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlAttribute.h" +#import "TDXmlToken.h" + +@implementation TDXmlAttribute + ++ (id)attribute { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)attributeWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_ATTRIBUTE stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isAttribute; + } +} + +@end diff --git a/test/TDXmlCdata.h b/test/TDXmlCdata.h new file mode 100644 index 0000000..7e6e1e6 --- /dev/null +++ b/test/TDXmlCdata.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlCdata : TDXmlTerminal { + +} ++ (id)cdata; ++ (id)cdataWithString:(NSString *)s; +@end diff --git a/test/TDXmlCdata.m b/test/TDXmlCdata.m new file mode 100644 index 0000000..397b425 --- /dev/null +++ b/test/TDXmlCdata.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlCdata.h" +#import "TDXmlToken.h" + +@implementation TDXmlCdata + ++ (id)cdata { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)cdataWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_CDATA stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isCdata; + } +} + +@end diff --git a/test/TDXmlComment.h b/test/TDXmlComment.h new file mode 100644 index 0000000..4988fac --- /dev/null +++ b/test/TDXmlComment.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlComment : TDXmlTerminal { + +} ++ (id)comment; ++ (id)commentWithString:(NSString *)s; +@end diff --git a/test/TDXmlComment.m b/test/TDXmlComment.m new file mode 100644 index 0000000..896da0d --- /dev/null +++ b/test/TDXmlComment.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlComment.h" +#import "TDXmlToken.h" + +@implementation TDXmlComment + ++ (id)comment { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)commentWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_COMMENT stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isComment; + } +} + +@end diff --git a/test/TDXmlDecl.h b/test/TDXmlDecl.h new file mode 100644 index 0000000..fefba57 --- /dev/null +++ b/test/TDXmlDecl.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlDecl : TDXmlTerminal { + +} ++ (id)xmlDecl; ++ (id)xmlDeclWithString:(NSString *)s; +@end diff --git a/test/TDXmlDecl.m b/test/TDXmlDecl.m new file mode 100644 index 0000000..cefd291 --- /dev/null +++ b/test/TDXmlDecl.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlDecl.h" +#import "TDXmlToken.h" + +@implementation TDXmlDecl + ++ (id)xmlDecl { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)xmlDeclWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_XML_DECL stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isXmlDecl; + } +} + +@end diff --git a/test/TDXmlDoctype.h b/test/TDXmlDoctype.h new file mode 100644 index 0000000..9509cd6 --- /dev/null +++ b/test/TDXmlDoctype.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlDoctype : TDXmlTerminal { + +} ++ (id)doctype; ++ (id)doctypeWithString:(NSString *)s; +@end diff --git a/test/TDXmlDoctype.m b/test/TDXmlDoctype.m new file mode 100644 index 0000000..217b0f3 --- /dev/null +++ b/test/TDXmlDoctype.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlDoctype.h" +#import "TDXmlToken.h" + +@implementation TDXmlDoctype + ++ (id)doctype { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)doctypeWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_DOCTYPE stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isDoctype; + } +} + +@end diff --git a/test/TDXmlDocument.h b/test/TDXmlDocument.h new file mode 100644 index 0000000..1ef5c71 --- /dev/null +++ b/test/TDXmlDocument.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlDocument : TDXmlTerminal { + +} ++ (id)document; ++ (id)documentWithString:(NSString *)s; +@end diff --git a/test/TDXmlDocument.m b/test/TDXmlDocument.m new file mode 100644 index 0000000..e57ab66 --- /dev/null +++ b/test/TDXmlDocument.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlDocument.h" +#import "TDXmlToken.h" + +@implementation TDXmlDocument + ++ (id)document { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)documentWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_DOCUMENT stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isDocument; + } +} + +@end diff --git a/test/TDXmlEndEntity.h b/test/TDXmlEndEntity.h new file mode 100644 index 0000000..dcbd4bd --- /dev/null +++ b/test/TDXmlEndEntity.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlEndEntity : TDXmlTerminal { + +} ++ (id)endEntity; ++ (id)endEntityWithString:(NSString *)s; +@end diff --git a/test/TDXmlEndEntity.m b/test/TDXmlEndEntity.m new file mode 100644 index 0000000..19123f7 --- /dev/null +++ b/test/TDXmlEndEntity.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlEndEntity.h" +#import "TDXmlToken.h" + +@implementation TDXmlEndEntity + ++ (id)endEntity { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)endEntityWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_END_ENTITY stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isEndEntity; + } +} + +@end diff --git a/test/TDXmlEndTag.h b/test/TDXmlEndTag.h new file mode 100644 index 0000000..71e8a7b --- /dev/null +++ b/test/TDXmlEndTag.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlEndTag : TDXmlTerminal { + +} ++ (id)endTag; ++ (id)endTagWithString:(NSString *)s; +@end diff --git a/test/TDXmlEndTag.m b/test/TDXmlEndTag.m new file mode 100644 index 0000000..df287cd --- /dev/null +++ b/test/TDXmlEndTag.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlEndTag.h" +#import "TDXmlToken.h" + +@implementation TDXmlEndTag + ++ (id)endTag { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)endTagWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_END_TAG stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isEndTag; + } +} + +@end diff --git a/test/TDXmlEntity.h b/test/TDXmlEntity.h new file mode 100644 index 0000000..6b7cd83 --- /dev/null +++ b/test/TDXmlEntity.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlEntity : TDXmlTerminal { + +} ++ (id)entity; ++ (id)entityWithString:(NSString *)s; +@end diff --git a/test/TDXmlEntity.m b/test/TDXmlEntity.m new file mode 100644 index 0000000..e4e0f17 --- /dev/null +++ b/test/TDXmlEntity.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlEntity.h" +#import "TDXmlToken.h" + +@implementation TDXmlEntity + ++ (id)entity { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)entityWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_ENTITY stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isEntity; + } +} + +@end diff --git a/test/TDXmlEntityRef.h b/test/TDXmlEntityRef.h new file mode 100644 index 0000000..d6b972c --- /dev/null +++ b/test/TDXmlEntityRef.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlEntityRef : TDXmlTerminal { + +} ++ (id)entityRef; ++ (id)entityRefWithString:(NSString *)s; +@end diff --git a/test/TDXmlEntityRef.m b/test/TDXmlEntityRef.m new file mode 100644 index 0000000..2a6bde5 --- /dev/null +++ b/test/TDXmlEntityRef.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlEntityRef.h" +#import "TDXmlToken.h" + +@implementation TDXmlEntityRef + ++ (id)entityRef { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)entityRefWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_ENTITY_REF stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isEntityRef; + } +} + +@end diff --git a/test/TDXmlFragment.h b/test/TDXmlFragment.h new file mode 100644 index 0000000..65172f1 --- /dev/null +++ b/test/TDXmlFragment.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlFragment : TDXmlTerminal { + +} ++ (id)doctype; ++ (id)doctypeWithString:(NSString *)s; +@end diff --git a/test/TDXmlFragment.m b/test/TDXmlFragment.m new file mode 100644 index 0000000..fb41f96 --- /dev/null +++ b/test/TDXmlFragment.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlFragment.h" +#import "TDXmlToken.h" + +@implementation TDXmlFragment + ++ (id)doctype { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)doctypeWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_FRAGMENT stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isFragment; + } +} + +@end diff --git a/test/TDXmlName.h b/test/TDXmlName.h new file mode 100644 index 0000000..32be5e5 --- /dev/null +++ b/test/TDXmlName.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKTerminal.h" + +@interface TDXmlName : PKTerminal { + +} ++ (id)name; +@end diff --git a/test/TDXmlName.m b/test/TDXmlName.m new file mode 100644 index 0000000..b2623d7 --- /dev/null +++ b/test/TDXmlName.m @@ -0,0 +1,39 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlName.h" +#import "PKToken.h" + +@implementation TDXmlName + ++ (id)name { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +- (BOOL)qualifies:(id)obj { + PKToken *tok = (PKToken *)obj; + if (!tok.isWord) { + return NO; + } + + //NSString *s = tok.stringValue; + if (YES) { + + } + + return YES; +} + +@end diff --git a/test/TDXmlNameState.h b/test/TDXmlNameState.h new file mode 100644 index 0000000..8400989 --- /dev/null +++ b/test/TDXmlNameState.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKTokenizerState.h" + +@interface TDXmlNameState : PKTokenizerState { + +} + +@end diff --git a/test/TDXmlNameState.m b/test/TDXmlNameState.m new file mode 100644 index 0000000..921812b --- /dev/null +++ b/test/TDXmlNameState.m @@ -0,0 +1,87 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlNameState.h" +#import "PKTokenizer.h" +#import "PKReader.h" +#import "TDXmlToken.h" + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface TDXmlNameState () ++ (BOOL)isNameChar:(PKUniChar)c; ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c; ++ (BOOL)isValidNonStartSymbolChar:(PKUniChar)c; +@end + +//Name ::= (Letter | '_' | ':') (NameChar)* +@implementation TDXmlNameState + +//- (BOOL)isWhitespace:(PKUniChar)c { +// return (' ' == c || '\n' == c || '\r' == c || '\t' == c); +//} + + +// NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender ++ (BOOL)isNameChar:(PKUniChar)c { + if (isalpha(c)) { + return YES; + } else if (isdigit(c)) { + return YES; + } else if ([[self class] isValidNonStartSymbolChar:c]) { + return YES; + } + // TODO CombiningChar & Extender + return NO; +} + + ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c { + return ('_' == c || ':' == c); +} + + ++ (BOOL)isValidNonStartSymbolChar:(PKUniChar)c { + return ('_' == c || '.' == c || '-' == c || ':' == c); +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + [self resetWithReader:r]; + + NSInteger c = cin; + do { + [self append:c]; + c = [r read]; + } while ([[self class] isNameChar:c]); + + if (PKEOF != c) { + [r unread]; + } + + if ([[self bufferedString] length] == 1 && [[self class] isValidStartSymbolChar:cin]) { + return [t.symbolState nextTokenFromReader:r startingWith:cin tokenizer:t]; + } else { +// return [[[TDXmlToken alloc] initWithTokenType:TDTT_NAME +// stringValue:[[stringbuf copy] autorelease] +// floatValue:0.0] autorelease]; + return nil; + } +} + +@end diff --git a/test/TDXmlNameTest.h b/test/TDXmlNameTest.h new file mode 100644 index 0000000..2ec72d3 --- /dev/null +++ b/test/TDXmlNameTest.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +// + +@interface TDXmlNameTest : SenTestCase { + +} + +@end diff --git a/test/TDXmlNameTest.m b/test/TDXmlNameTest.m new file mode 100644 index 0000000..5db6245 --- /dev/null +++ b/test/TDXmlNameTest.m @@ -0,0 +1,68 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlNameTest.h" +#import "TDXmlNameState.h" +#import "TDXmlNmtokenState.h" +#import "TDXmlToken.h" + +@implementation TDXmlNameTest +// +//- (void)test { +// NSString *s = @"_foob?ar _foobar 2baz"; +// PKTokenizer *t = [PKTokenizer tokenizerWithString:s]; +// +// //Name ::= (Letter | '_' | ':') (NameChar)* +// TDXmlNameState *nameState = [[[TDXmlNameState alloc] init] autorelease]; +// +// [t setTokenizerState:nameState from: '_' to: '_']; +// [t setTokenizerState:nameState from: ':' to: ':']; +// [t setTokenizerState:nameState from: 'a' to: 'z']; +// [t setTokenizerState:nameState from: 'A' to: 'Z']; +// [t setTokenizerState:nameState from:0xc0 to:0xff]; +// +// TDXmlNmtokenState *nmtokenState = [[[TDXmlNmtokenState alloc] init] autorelease]; +// [t setTokenizerState:nmtokenState from: '0' to: '9']; +// +// TDXmlToken *tok = nil; +// +// // _foob +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isName); +// +// // '?' +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isSymbol); +// +// // ar +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isName); +// +// // _foobar +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isName); +// +// // 2baz +// tok = (TDXmlToken *)[t nextToken]; +// TDNotNil(tok); +// TDTrue(tok.isNmtoken); +// NSLog(@"tok: %@", tok); +// +//} + +@end diff --git a/test/TDXmlNmtoken.h b/test/TDXmlNmtoken.h new file mode 100644 index 0000000..0a7e8c5 --- /dev/null +++ b/test/TDXmlNmtoken.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "PKTerminal.h" + +@interface TDXmlNmtoken : PKTerminal { + +} ++ (id)nmtoken; +@end diff --git a/test/TDXmlNmtoken.m b/test/TDXmlNmtoken.m new file mode 100644 index 0000000..f8ad21e --- /dev/null +++ b/test/TDXmlNmtoken.m @@ -0,0 +1,30 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlNmtoken.h" +#import "TDXmlToken.h" + +@implementation TDXmlNmtoken + ++ (id)nmtoken { + return [[[self alloc] initWithString:nil] autorelease]; +} + + +//- (BOOL)qualifies:(id)obj { +// TDXmlToken *tok = (TDXmlToken *)obj; +// return tok.isNmtoken; +//} + +@end diff --git a/test/TDXmlNmtokenState.h b/test/TDXmlNmtokenState.h new file mode 100644 index 0000000..7fb578d --- /dev/null +++ b/test/TDXmlNmtokenState.h @@ -0,0 +1,21 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlNameState.h" + +@interface TDXmlNmtokenState : TDXmlNameState { + +} + +@end diff --git a/test/TDXmlNmtokenState.m b/test/TDXmlNmtokenState.m new file mode 100644 index 0000000..bd8fd87 --- /dev/null +++ b/test/TDXmlNmtokenState.m @@ -0,0 +1,65 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlNmtokenState.h" +#import "PKTokenizer.h" +#import "PKReader.h" +#import "TDXmlToken.h" + +@interface PKTokenizerState () +- (void)resetWithReader:(PKReader *)r; +- (void)append:(PKUniChar)c; +- (NSString *)bufferedString; +@end + +@interface TDXmlNameState () ++ (BOOL)isNameChar:(PKUniChar)c; ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c; +@end + +// NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender +@implementation TDXmlNmtokenState + ++ (BOOL)isValidStartSymbolChar:(PKUniChar)c { + return ('_' == c || ':' == c || '-' == c || '.' == c); +} + + +- (PKToken *)nextTokenFromReader:(PKReader *)r startingWith:(PKUniChar)cin tokenizer:(PKTokenizer *)t { + [self resetWithReader:r]; + + NSInteger c = cin; + do { + [self append:c]; + c = [r read]; + } while ([[self class] isNameChar:c]); + + if (PKEOF != c) { + [r unread]; + } + + NSString *s = [self bufferedString]; + if ([s length] == 1 && [[self class] isValidStartSymbolChar:cin]) { + return [t.symbolState nextTokenFromReader:r startingWith:cin tokenizer:t]; + } else if ([s length] == 1 && isdigit(cin)) { + return [t.numberState nextTokenFromReader:r startingWith:cin tokenizer:t]; + } else { + return nil; +// return [[[TDXmlToken alloc] initWithTokenType:TDTT_NMTOKEN +// stringValue:[[stringbuf copy] autorelease] +// floatValue:0.0] autorelease]; + } +} + +@end diff --git a/test/TDXmlNotation.h b/test/TDXmlNotation.h new file mode 100644 index 0000000..1284667 --- /dev/null +++ b/test/TDXmlNotation.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlNotation : TDXmlTerminal { + +} ++ (id)notation; ++ (id)notationWithString:(NSString *)s; +@end diff --git a/test/TDXmlNotation.m b/test/TDXmlNotation.m new file mode 100644 index 0000000..846a850 --- /dev/null +++ b/test/TDXmlNotation.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlNotation.h" +#import "TDXmlToken.h" + +@implementation TDXmlNotation + ++ (id)notation { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)notationWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_NOTATION stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isNotation; + } +} + +@end diff --git a/test/TDXmlProcessingInstruction.h b/test/TDXmlProcessingInstruction.h new file mode 100644 index 0000000..a74335f --- /dev/null +++ b/test/TDXmlProcessingInstruction.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlProcessingInstruction : TDXmlTerminal { + +} ++ (id)processingInstruction; ++ (id)processingInstructionWithString:(NSString *)s; +@end diff --git a/test/TDXmlProcessingInstruction.m b/test/TDXmlProcessingInstruction.m new file mode 100644 index 0000000..f3e851e --- /dev/null +++ b/test/TDXmlProcessingInstruction.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlProcessingInstruction.h" +#import "TDXmlToken.h" + +@implementation TDXmlProcessingInstruction + ++ (id)processingInstruction { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)processingInstructionWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_PROCESSING_INSTRUCTION stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isProcessingInstruction; + } +} + +@end diff --git a/test/TDXmlSignificantWhitespace.h b/test/TDXmlSignificantWhitespace.h new file mode 100644 index 0000000..55c7ec2 --- /dev/null +++ b/test/TDXmlSignificantWhitespace.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlSignificantWhitespace : TDXmlTerminal { + +} ++ (id)significantWhitespace; ++ (id)significantWhitespaceWithString:(NSString *)s; +@end diff --git a/test/TDXmlSignificantWhitespace.m b/test/TDXmlSignificantWhitespace.m new file mode 100644 index 0000000..d226aa4 --- /dev/null +++ b/test/TDXmlSignificantWhitespace.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlSignificantWhitespace.h" +#import "TDXmlToken.h" + +@implementation TDXmlSignificantWhitespace + ++ (id)significantWhitespace { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)significantWhitespaceWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_SIGNIFICANT_WHITESPACE stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isSignificantWhitespace; + } +} + +@end diff --git a/test/TDXmlStartTag.h b/test/TDXmlStartTag.h new file mode 100644 index 0000000..b21efe0 --- /dev/null +++ b/test/TDXmlStartTag.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlStartTag : TDXmlTerminal { + +} ++ (id)startTag; ++ (id)startTagWithString:(NSString *)s; +@end diff --git a/test/TDXmlStartTag.m b/test/TDXmlStartTag.m new file mode 100644 index 0000000..8a04fd5 --- /dev/null +++ b/test/TDXmlStartTag.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlStartTag.h" +#import "TDXmlToken.h" + +@implementation TDXmlStartTag + ++ (id)startTag { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)startTagWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_START_TAG stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isStartTag; + } +} + +@end diff --git a/test/TDXmlTerminal.h b/test/TDXmlTerminal.h new file mode 100644 index 0000000..8b0cf9e --- /dev/null +++ b/test/TDXmlTerminal.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class TDXmlToken; + +@interface TDXmlTerminal : PKTerminal { + TDXmlToken *tok; +} +@property (nonatomic, retain) TDXmlToken *tok; +@end diff --git a/test/TDXmlTerminal.m b/test/TDXmlTerminal.m new file mode 100644 index 0000000..1f89b26 --- /dev/null +++ b/test/TDXmlTerminal.m @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" +#import "TDXmlToken.h" + +@implementation TDXmlTerminal + +- (void)dealloc { + self.tok = nil; + [super dealloc]; +} + +@synthesize tok; +@end diff --git a/test/TDXmlText.h b/test/TDXmlText.h new file mode 100644 index 0000000..5ca67db --- /dev/null +++ b/test/TDXmlText.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlText : TDXmlTerminal { + +} ++ (id)text; ++ (id)textWithString:(NSString *)s; +@end diff --git a/test/TDXmlText.m b/test/TDXmlText.m new file mode 100644 index 0000000..31d01bd --- /dev/null +++ b/test/TDXmlText.m @@ -0,0 +1,57 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlText.h" +#import "TDXmlToken.h" + +@implementation TDXmlText + ++ (id)text { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)textWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + NSLog(@"%s", _cmd); + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_TEXT stringValue:s]; + NSLog(@"tok : %@", tok); + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + NSLog(@"%s obj: %@ isText: %d", _cmd, obj, other.isText); + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isText; + } +} + +@end diff --git a/test/TDXmlToken.h b/test/TDXmlToken.h new file mode 100644 index 0000000..0afdc83 --- /dev/null +++ b/test/TDXmlToken.h @@ -0,0 +1,95 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +typedef enum { + TDTT_XML_NONE = 0, + TDTT_XML_START_TAG = 1, + TDTT_XML_ATTRIBUTE = 2, + TDTT_XML_TEXT = 3, + TDTT_XML_CDATA = 4, + TDTT_XML_ENTITY_REF = 5, + TDTT_XML_ENTITY = 6, + TDTT_XML_PROCESSING_INSTRUCTION = 7, + TDTT_XML_COMMENT = 8, + TDTT_XML_DOCUMENT = 9, + TDTT_XML_DOCTYPE = 10, + TDTT_XML_FRAGMENT = 11, + TDTT_XML_NOTATION = 12, + TDTT_XML_WHITESPACE = 13, + TDTT_XML_SIGNIFICANT_WHITESPACE = 14, + TDTT_XML_END_TAG = 15, + TDTT_XML_END_ENTITY = 16, + TDTT_XML_XML_DECL = 17, + TDTT_XML_EOF = 18 +} TDXmlTokenType; + +@interface TDXmlToken : NSObject { + NSString *stringValue; + TDXmlTokenType tokenType; + + BOOL none; + BOOL startTag; + BOOL attribute; + BOOL text; + BOOL cdata; + BOOL entityRef; + BOOL entity; + BOOL processingInstruction; + BOOL comment; + BOOL document; + BOOL doctype; + BOOL fragment; + BOOL notation; + BOOL whitespace; + BOOL significantWhitespace; + BOOL endTag; + BOOL endEntity; + BOOL xmlDecl; + + id value; +} ++ (TDXmlToken *)EOFToken; ++ (id)tokenWithTokenType:(TDXmlTokenType)t stringValue:(NSString *)s; + +// designated initializer +- (id)initWithTokenType:(TDXmlTokenType)t stringValue:(NSString *)s; + +- (BOOL)isEqualIgnoringCase:(id)obj; + +- (NSString *)debugDescription; + +@property (nonatomic, readonly, getter=isNone) BOOL none; +@property (nonatomic, readonly, getter=isStartTag) BOOL startTag; +@property (nonatomic, readonly, getter=isAttribute) BOOL attribute; +@property (nonatomic, readonly, getter=isText) BOOL text; +@property (nonatomic, readonly, getter=isCdata) BOOL cdata; +@property (nonatomic, readonly, getter=isEntityRef) BOOL entityRef; +@property (nonatomic, readonly, getter=isEntity) BOOL entity; +@property (nonatomic, readonly, getter=isProcessingInstruction) BOOL processingInstruction; +@property (nonatomic, readonly, getter=isComment) BOOL comment; +@property (nonatomic, readonly, getter=isDocument) BOOL document; +@property (nonatomic, readonly, getter=isDoctype) BOOL doctype; +@property (nonatomic, readonly, getter=isFragment) BOOL fragment; +@property (nonatomic, readonly, getter=isNotation) BOOL notation; +@property (nonatomic, readonly, getter=isWhitespace) BOOL whitespace; +@property (nonatomic, readonly, getter=isSignificantWhitespace) BOOL significantWhitespace; +@property (nonatomic, readonly, getter=isEndTag) BOOL endTag; +@property (nonatomic, readonly, getter=isEndEntity) BOOL endEntity; +@property (nonatomic, readonly, getter=isXmlDecl) BOOL xmlDecl; +@property (nonatomic, readonly, copy) NSString *stringValue; +@property (nonatomic, readonly) TDXmlTokenType tokenType; +@property (nonatomic, readonly, copy) id value; +@end diff --git a/test/TDXmlToken.m b/test/TDXmlToken.m new file mode 100644 index 0000000..28ef312 --- /dev/null +++ b/test/TDXmlToken.m @@ -0,0 +1,209 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlToken.h" + +@interface TDXmlTokenEOF : TDXmlToken {} +@end + +@implementation TDXmlTokenEOF +- (NSString *)description { + return [NSString stringWithFormat:@"", self]; +} +@end + +@interface TDXmlToken () +@property (nonatomic, readwrite, getter=isNone) BOOL none; +@property (nonatomic, readwrite, getter=isStartTag) BOOL startTag; +@property (nonatomic, readwrite, getter=isAttribute) BOOL attribute; +@property (nonatomic, readwrite, getter=isText) BOOL text; +@property (nonatomic, readwrite, getter=isCdata) BOOL cdata; +@property (nonatomic, readwrite, getter=isEntityRef) BOOL entityRef; +@property (nonatomic, readwrite, getter=isEntity) BOOL entity; +@property (nonatomic, readwrite, getter=isProcessingInstruction) BOOL processingInstruction; +@property (nonatomic, readwrite, getter=isComment) BOOL comment; +@property (nonatomic, readwrite, getter=isDocument) BOOL document; +@property (nonatomic, readwrite, getter=isDoctype) BOOL doctype; +@property (nonatomic, readwrite, getter=isFragment) BOOL fragment; +@property (nonatomic, readwrite, getter=isNotation) BOOL notation; +@property (nonatomic, readwrite, getter=isWhitespace) BOOL whitespace; +@property (nonatomic, readwrite, getter=isSignificantWhitespace) BOOL significantWhitespace; +@property (nonatomic, readwrite, getter=isEndTag) BOOL endTag; +@property (nonatomic, readwrite, getter=isEndEntity) BOOL endEntity; +@property (nonatomic, readwrite, getter=isXmlDecl) BOOL xmlDecl; +@property (nonatomic, readwrite, copy) NSString *stringValue; +@property (nonatomic, readwrite) TDXmlTokenType tokenType; +@property (nonatomic, readwrite, copy) id value; +@end + +@implementation TDXmlToken + ++ (TDXmlToken *)EOFToken { + static TDXmlToken *EOFToken = nil; + @synchronized (self) { + if (!EOFToken) { + EOFToken = [[TDXmlTokenEOF alloc] initWithTokenType:TDTT_XML_EOF stringValue:nil]; + } + } + return EOFToken; +} + + ++ (id)tokenWithTokenType:(TDXmlTokenType)t stringValue:(NSString *)s { + return [[[self alloc] initWithTokenType:t stringValue:s] autorelease]; +} + + +#pragma mark - + +// designated initializer +- (id)initWithTokenType:(TDXmlTokenType)t stringValue:(NSString *)s { + if (self = [super init]) { + self.tokenType = t; + self.stringValue = s; + + self.none = (TDTT_XML_NONE == t); + self.startTag = (TDTT_XML_START_TAG == t); + self.attribute = (TDTT_XML_ATTRIBUTE == t); + self.text = (TDTT_XML_TEXT == t); + self.cdata = (TDTT_XML_CDATA == t); + self.entityRef = (TDTT_XML_ENTITY_REF == t); + self.entity = (TDTT_XML_ENTITY == t); + self.processingInstruction = (TDTT_XML_PROCESSING_INSTRUCTION == t); + self.comment = (TDTT_XML_COMMENT == t); + self.document = (TDTT_XML_DOCUMENT == t); + self.doctype = (TDTT_XML_DOCTYPE == t); + self.fragment = (TDTT_XML_FRAGMENT == t); + self.notation = (TDTT_XML_NOTATION == t); + self.whitespace = (TDTT_XML_WHITESPACE == t); + self.significantWhitespace = (TDTT_XML_SIGNIFICANT_WHITESPACE == t); + self.endTag = (TDTT_XML_END_TAG == t); + self.endEntity = (TDTT_XML_END_ENTITY == t); + self.xmlDecl = (TDTT_XML_XML_DECL == t); + + self.value = stringValue; + } + return self; +} + + +- (void)dealloc { + self.stringValue = nil; + self.value = nil; + [super dealloc]; +} + + +- (NSUInteger)hash { + return [stringValue hash]; +} + + +- (BOOL)isEqual:(id)rhv { + if (![rhv isMemberOfClass:[TDXmlToken class]]) { + return NO; + } + + TDXmlToken *that = (TDXmlToken *)rhv; + if (tokenType != that.tokenType) { + return NO; + } + + return [stringValue isEqualToString:that.stringValue]; +} + + +- (BOOL)isEqualIgnoringCase:(id)rhv { + if (![rhv isMemberOfClass:[TDXmlToken class]]) { + return NO; + } + + TDXmlToken *that = (TDXmlToken *)rhv; + if (tokenType != that.tokenType) { + return NO; + } + + return [stringValue.lowercaseString isEqualToString:that.stringValue.lowercaseString]; +} + + +- (NSString *)debugDescription { + NSString *typeString = nil; + if (self.isNone) { + typeString = @"None"; + } else if (self.isStartTag) { + typeString = @"Start Tag"; + } else if (self.isAttribute) { + typeString = @"Attribute"; + } else if (self.isText) { + typeString = @"Text"; + } else if (self.isCdata) { + typeString = @"CData"; + } else if (self.isEntityRef) { + typeString = @"Entity Reference"; + } else if (self.isEntity) { + typeString = @"Entity"; + } else if (self.isProcessingInstruction) { + typeString = @"Processing Instruction"; + } else if (self.isComment) { + typeString = @"Comment"; + } else if (self.isDocument) { + typeString = @"Document"; + } else if (self.isDoctype) { + typeString = @"Doctype"; + } else if (self.isFragment) { + typeString = @"Fragment"; + } else if (self.isNotation) { + typeString = @"Notation"; + } else if (self.isWhitespace) { + typeString = @"Whitespace"; + } else if (self.isSignificantWhitespace) { + typeString = @"Significant Whitespace"; + } else if (self.isEndTag) { + typeString = @"End Tag"; + } else if (self.isEndEntity) { + typeString = @"End Entity"; + } else if (self.isXmlDecl) { + typeString = @"XML Declaration"; + } + return [NSString stringWithFormat:@"<%@ %C%@%C>", typeString, 0x00ab, self.value, 0x00bb]; +} + + +- (NSString *)description { + return [self debugDescription]; +} + +@synthesize none; +@synthesize startTag; +@synthesize attribute; +@synthesize text; +@synthesize cdata; +@synthesize entityRef; +@synthesize entity; +@synthesize processingInstruction; +@synthesize comment; +@synthesize document; +@synthesize doctype; +@synthesize fragment; +@synthesize notation; +@synthesize whitespace; +@synthesize significantWhitespace; +@synthesize endTag; +@synthesize endEntity; +@synthesize xmlDecl; +@synthesize stringValue; +@synthesize tokenType; +@synthesize value; +@end diff --git a/test/TDXmlTokenAssembly.h b/test/TDXmlTokenAssembly.h new file mode 100644 index 0000000..eda4ab1 --- /dev/null +++ b/test/TDXmlTokenAssembly.h @@ -0,0 +1,24 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class TDXmlTokenizer; + +@interface TDXmlTokenAssembly : PKAssembly { + TDXmlTokenizer *tokenizer; + NSMutableArray *tokens; +} +@property (nonatomic, retain) TDXmlTokenizer *tokenizer; +@end diff --git a/test/TDXmlTokenAssembly.m b/test/TDXmlTokenAssembly.m new file mode 100644 index 0000000..41dc364 --- /dev/null +++ b/test/TDXmlTokenAssembly.m @@ -0,0 +1,156 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTokenAssembly.h" +#import "TDXmlTokenizer.h" +#import "TDXmlToken.h" + +@interface TDXmlTokenAssembly () +- (void)tokenize; + +@property (nonatomic, retain) NSMutableArray *tokens; +@end + +@implementation TDXmlTokenAssembly + +- (id)init { + return nil; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tokenizer = [[[TDXmlTokenizer alloc] initWithContentsOfFile:s] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.tokenizer = nil; + self.tokens = nil; + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + TDXmlTokenAssembly *a = (TDXmlTokenAssembly *)[super copyWithZone:zone]; + a->tokens = [self.tokens mutableCopy]; + return a; +} + + +- (NSMutableArray *)tokens { + if (!tokens) { + [self tokenize]; + } + return [[tokens retain] autorelease]; +} + + +- (void)setTokens:(NSMutableArray *)inArray { + if (inArray != tokens) { + [tokens autorelease]; + tokens = [inArray retain]; + } +} + + +- (void)tokenize { + self.tokens = [NSMutableArray array]; + + TDXmlToken *eof = [TDXmlToken EOFToken]; + TDXmlToken *tok = nil; + while ((tok = [tokenizer nextToken]) != eof) { + [tokens addObject:tok]; + } +} + + +- (id)peek { + if (index >= [self.tokens count]) { + return nil; + } + id tok = [self.tokens objectAtIndex:index]; + + return tok; +} + + +- (id)next { + id tok = [self peek]; + if (tok) { + index++; + } + return tok; +} + + +- (BOOL)hasMore { + return (index < [self.tokens count]); +} + + +- (NSUInteger)length { + return [self.tokens count]; +} + + +- (NSUInteger)consumedObjectCount { + return index; +} + + +- (NSUInteger)remainingObjectCount { + return ([self.tokens count] - index); +} + + +- (NSString *)consumedObjectsJoinedByString:(NSString *)delimiter { + NSMutableString *s = [NSMutableString string]; + + NSInteger i = 0; + NSInteger len = self.consumedObjectCount; + + for ( ; i < len; i++) { + TDXmlToken *tok = [self.tokens objectAtIndex:i]; + [s appendString:tok.stringValue]; + if (i != len - 1) { + [s appendString:delimiter]; + } + } + + return [[s copy] autorelease]; +} + + +- (NSString *)remainingObjectsJoinedByString:(NSString *)delimiter { + NSMutableString *s = [NSMutableString string]; + + NSInteger i = self.consumedObjectCount; + NSInteger len = [self length]; + + for ( ; i < len; i++) { + TDXmlToken *tok = [self.tokens objectAtIndex:i]; + [s appendString:tok.stringValue]; + if (i != len - 1) { + [s appendString:delimiter]; + } + } + return [[s copy] autorelease]; +} + +@synthesize tokenizer; +@end diff --git a/test/TDXmlTokenizer.h b/test/TDXmlTokenizer.h new file mode 100644 index 0000000..a7e6e86 --- /dev/null +++ b/test/TDXmlTokenizer.h @@ -0,0 +1,27 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class TDXmlToken; +@class XMLReader; + +@interface TDXmlTokenizer : NSObject { + XMLReader *reader; +} ++ (id)tokenizerWithContentsOfFile:(NSString *)path; + +- (id)initWithContentsOfFile:(NSString *)path; +- (TDXmlToken *)nextToken; +@end diff --git a/test/TDXmlTokenizer.m b/test/TDXmlTokenizer.m new file mode 100644 index 0000000..59f42bc --- /dev/null +++ b/test/TDXmlTokenizer.m @@ -0,0 +1,69 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTokenizer.h" +#import "XMLReader.h" +#import "TDXmlToken.h" + +@interface TDXmlTokenizer () +@property (nonatomic, retain) XMLReader *reader; +@end + +@implementation TDXmlTokenizer + ++ (id)tokenizerWithContentsOfFile:(NSString *)path { + return [[[self alloc] initWithContentsOfFile:path] autorelease]; +} + + +- (id)init { + return nil; +} + + +- (id)initWithContentsOfFile:(NSString *)path { + if (self = [super init]) { + self.reader = [[[XMLReader alloc] initWithContentsOfFile:path] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.reader = nil; + [super dealloc]; +} + + +- (TDXmlToken *)nextToken { + TDXmlToken *tok = nil; + NSInteger ret = -1; + NSInteger nodeType = -1; + + do { + ret = [reader read]; + nodeType = reader.nodeType; + } while (nodeType == TDTT_XML_SIGNIFICANT_WHITESPACE || nodeType == TDTT_XML_WHITESPACE); + + if (ret <= 0) { + tok = [TDXmlToken EOFToken]; + } else { + tok = [TDXmlToken tokenWithTokenType:reader.nodeType stringValue:reader.name]; + } + + return tok; +} + +@synthesize reader; +@end diff --git a/test/TDXmlTokenizerTest.h b/test/TDXmlTokenizerTest.h new file mode 100644 index 0000000..a4a5eb5 --- /dev/null +++ b/test/TDXmlTokenizerTest.h @@ -0,0 +1,23 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "TDXmlTokenizer.h" +#import "TDXmlToken.h" + +@interface TDXmlTokenizerTest : SenTestCase { + +} + +@end diff --git a/test/TDXmlTokenizerTest.m b/test/TDXmlTokenizerTest.m new file mode 100644 index 0000000..cb15bc7 --- /dev/null +++ b/test/TDXmlTokenizerTest.m @@ -0,0 +1,57 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTokenizerTest.h" +#import "TDXmlDecl.h" +#import "TDXmlStartTag.h" +#import "TDXmlEndTag.h" +#import "TDXmlText.h" +#import "TDXmlSignificantWhitespace.h" +#import "TDXmlTokenAssembly.h" + + +@implementation TDXmlTokenizerTest + +- (void)testFoo { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"xml"]; + + TDXmlTokenizer *t = [TDXmlTokenizer tokenizerWithContentsOfFile:path]; + NSLog(@"\n\n %@\n\n", t); + + TDXmlToken *eof = [TDXmlToken EOFToken]; + TDXmlToken *tok = nil; + + while ((tok = [t nextToken]) != eof) { + //NSLog(@" %@", [tok debugDescription]); + } +} + + +- (void)testAppleBoss { + PKSequence *s = [PKSequence sequence]; + s.name = @"parent sequence"; + [s add:[TDXmlStartTag startTagWithString:@"result"]]; + [s add:[TDXmlStartTag startTagWithString:@"url"]]; + [s add:[TDXmlText text]]; + [s add:[TDXmlEndTag endTagWithString:@"url"]]; + [s add:[TDXmlEndTag endTagWithString:@"result"]]; + + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"small-xml-file" ofType:@"xml"]; + TDXmlTokenAssembly *a = [TDXmlTokenAssembly assemblyWithString:path]; + + PKAssembly *result = [s bestMatchFor:a]; + NSLog(@"\n\n\n result: %@ \n\n\n", result); +} + +@end diff --git a/test/TDXmlWhitespace.h b/test/TDXmlWhitespace.h new file mode 100644 index 0000000..5f2662e --- /dev/null +++ b/test/TDXmlWhitespace.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlTerminal.h" + +@interface TDXmlWhitespace : TDXmlTerminal { + +} ++ (id)whitespace; ++ (id)whitespaceWithString:(NSString *)s; +@end diff --git a/test/TDXmlWhitespace.m b/test/TDXmlWhitespace.m new file mode 100644 index 0000000..366b46b --- /dev/null +++ b/test/TDXmlWhitespace.m @@ -0,0 +1,54 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDXmlWhitespace.h" +#import "TDXmlToken.h" + +@implementation TDXmlWhitespace + ++ (id)whitespace { + return [[[self alloc] initWithString:nil] autorelease]; +} + + ++ (id)whitespaceWithString:(NSString *)s { + return [[[self alloc] initWithString:s] autorelease]; +} + + +- (id)initWithString:(NSString *)s { + self = [super initWithString:s]; + if (self) { + self.tok = [TDXmlToken tokenWithTokenType:TDTT_XML_WHITESPACE stringValue:s]; + } + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + + +- (BOOL)qualifies:(id)obj { + TDXmlToken *other = (TDXmlToken *)obj; + + if ([string length]) { + return [tok isEqual:other]; + } else { + return other.isWhitespace; + } +} + +@end diff --git a/test/Tests-Info.plist b/test/Tests-Info.plist new file mode 100644 index 0000000..2e46062 --- /dev/null +++ b/test/Tests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.Tests + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSPrincipalClass + TDTestScaffold + + diff --git a/test/XMLReader.h b/test/XMLReader.h new file mode 100755 index 0000000..46ece02 --- /dev/null +++ b/test/XMLReader.h @@ -0,0 +1,251 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +//#import +#import + +/** + * XMLReaderMode: + * + * Internal state values for the reader. + */ +typedef enum { + XMLReaderReadStateInitial = 0, + XMLReaderReadStateInteractive = 1, + XMLReaderReadStateError = 2, + XMLReaderReadStateEOF = 3, + XMLReaderReadStateClosed = 4, + XMLReaderReadStateReading = 5 +} XMLReaderReadState; + +/** + * xmlParserProperties: + * + * Some common options to use with xmlTextReaderSetParserProp, but it + * is better to use xmlParserOption and the xmlReaderNewxxx and + * xmlReaderForxxx APIs now. + * +typedef enum { + XML_PARSER_LOADDTD = 1, + XML_PARSER_DEFAULTATTRS = 2, + XML_PARSER_VALIDATE = 3, + XML_PARSER_SUBST_ENTITIES = 4 +} xmlParserProperties; +*/ + +/** + * xmlParserSeverities: + * + * How severe an error callback is when the per-reader error callback API + * is used. + */ +typedef enum { + XMLReaderSeverityValidityWarning = 1, + XMLReaderSeverityValidityError = 2, + XMLReaderSeverityWarning = 3, + XMLReaderSeverityError = 4 +} XMLReaderSeverity; + +/** + * XMLReaderNodeType: + * + * Predefined constants for the different types of nodes. + */ +typedef enum { + XMLReaderNodeTypeNone = 0, + XMLReaderNodeTypeElement = 1, + XMLReaderNodeTypeAttribute = 2, + XMLReaderNodeTypeText = 3, + XMLReaderNodeTypeCDATA = 4, + XMLReaderNodeTypeEntityReference = 5, + XMLReaderNodeTypeEntity = 6, + XMLReaderNodeTypeProcessingInstruction = 7, + XMLReaderNodeTypeComment = 8, + XMLReaderNodeTypeDocument = 9, + XMLReaderNodeTypeDocumentType = 10, + XMLReaderNodeTypeDocumentFragment = 11, + XMLReaderNodeTypeNotation = 12, + XMLReaderNodeTypeWhitespace = 13, + XMLReaderNodeTypeSignificantWhitespace = 14, + XMLReaderNodeTypeEndElement = 15, + XMLReaderNodeTypeEndEntity = 16, + XMLReaderNodeTypeXmlDeclaration = 17 +} XMLReaderNodeType; + + +@interface NSObject (XMLReaderErrorHandler) +- (void)validityWarning:(NSString *)msg lineNumber:(NSInteger)n; +- (void)validityError:(NSString *)msg lineNumber:(NSInteger)n; +- (void)warning:(NSString *)msg lineNumber:(NSInteger)n; +- (void)error:(NSString *)msg lineNumber:(NSInteger)n; +- (void)fatalError:(NSString *)msg lineNumber:(NSInteger)n; +@end + +@interface XMLReader : NSObject { + xmlTextReaderPtr _reader; + xmlRelaxNGPtr _schema; + NSString *path; + id errorHandler; + NSString *relaxNGSchemaPath; +} + ++ (id)parserWithContentsOfFile:(NSString *)newPath; +//+ (id)parserWithXMLString:(NSString *)XMLString; + +- (id)initWithContentsOfFile:(NSString *)path; +//- (id)initWithXMLString:(NSString *)XMLString; + +// Gets the number of attributes on the current node. +@property (nonatomic, readonly) NSInteger attributeCount; +//- (NSInteger)attributeCount; + +// Gets the base Uniform Resource Identifier (URI) of the current node. +@property (nonatomic, readonly, copy) NSString *baseURI; +//- (NSString *)baseURI; + +// Gets a value indicating whether this reader can parse and resolve entities. +//@property (nonatomic, readonly) BOOL canResolveEntity; +//- (BOOL)canResolveEntity; + +// Gets the depth of the current node in the XML document. +@property (nonatomic, readonly) NSInteger depth; +//- (NSInteger)depth; + +// Gets a value indicating whether the XMLReader.ReadState is ReadState.EndOfFile, signifying the reader is positioned at the end of the stream. +@property (nonatomic, readonly) BOOL isEOF; +//- (BOOL)isEOF; + +// Gets a value indicating whether the current node has any attributes. +@property (nonatomic, readonly) BOOL hasAttributes; +//- (BOOL)hasAttributes; + +// Gets a value indicating whether the current node can have an associated text value. +@property (nonatomic, readonly) BOOL hasValue; +//- (BOOL)hasValue; + +// Gets a value indicating whether the current node is an attribute that was generated from the default value defined in the DTD or schema. +@property (nonatomic, readonly) BOOL isDefault; +//- (BOOL)isDefault; + +// Gets a value indicating whether the current node is an empty element (for example, ). +@property (nonatomic, readonly) BOOL isEmptyElement; +//- (BOOL)isEmptyElement; + +// Gets the local name of the current node. +@property (nonatomic, readonly, copy) NSString *localName; +//- (NSString *)localName; + +// Gets the qualified name of the current node. +@property (nonatomic, readonly, copy) NSString *name; +//- (NSString *)name; + +// Gets the namespace URI associated with the node on which the reader is positioned. +@property (nonatomic, readonly, copy) NSString *namespaceURI; +//- (NSString *)namespaceURI; + +// Gets the name table used by the current instance to store and look up element and attribute names, prefixes, and namespaces. +//- (XmlNameTable)NameTable; + +// Gets the type of the current node. +@property (nonatomic, readonly) XMLReaderNodeType nodeType; +//- (XMLReaderNodeType)nodeType; + +// Gets the namespace prefix associated with the current node. +@property (nonatomic, readonly, copy) NSString *prefix; +//- (NSString *)prefix; + +// Gets the quotation mark character used to enclose the value of an attribute. +@property (nonatomic, readonly) char quoteChar; +//- (char)quoteChar; + +// Gets the read state of the reader. +@property (nonatomic, readonly) XMLReaderReadState readState; +//- (XMLReaderReadState)readState; + +// Gets the text value of the current node. +@property (nonatomic, readonly, copy) NSString *value; +//- (NSString *)value; + +// Gets the current xml:lang scope. +@property (nonatomic, readonly, copy) NSString *XMLLang; +//- (NSString *)XMLLang; + +// Gets the current xml:space scope. +//- (XMLSpace)XMLSpace; + +// Changes the XMLReader.ReadState to XMLReaderReadState.Closed. +- (void)close; + +// Returns the value of the attribute with the specified index relative to the containing element. +- (NSString *)attributeAtIndex:(NSInteger)index; + +// Returns the value of the attribute with the specified qualified name. +- (NSString *)attributeWithQName:(NSString *)qName; + +// Returns the value of the attribute with the specified local name and namespace URI. +- (NSString *)attributeWithLocalName:(NSString *)localName namespaceURI:(NSString *)nsURI; + +// Determines whether the specified string is a valid XML name. ++ (BOOL)isName:(NSString *)str; + +// Determines whether the specified string is a valid XML name token (Nmtoken). ++ (BOOL)isNameToken:(NSString *)str; + +// Resolves a namespace prefix in the scope of the current element. +- (NSString *)lookupNamespace:(NSString *)prefix; + +// Moves the position of the current instance to the attribute with the specified index relative to the containing element. +- (void)moveToAttributeAtIndex:(NSInteger)index; + +// Moves the position of the current instance to the attribute with the specified qualified name. +- (BOOL)moveToAttributeWithQName:(NSString *)qName; + +// Moves the position of the current instance to the attribute with the specified local name and namespace URI. +- (BOOL)moveToAttributeWithLocalName:(NSString *)localName namespaceURI:(NSString *)nsURI; + +// Moves the position of the current instance to the node that contains the current Attribute node. +- (BOOL)moveToElement; + +// Moves the position of the current instance to the first attribute associated with the current node. +- (BOOL)moveToFirstAttribute; + +// Moves the position of the current instance to the next attribute associated with the current node. +- (BOOL)moveToNextAttribute; + +// Moves the position of the current instance to the next node in the stream, exposing its properties. +- (BOOL)read; + +// Parses an attribute value into one or more Text, EntityReference, and EndEntity nodes. +- (BOOL)readAttributeValue; + +// Reads the contents of a text-only element. +- (NSString *)readElementString; + +// Reads the contents of the current node, including child nodes and markup. +- (NSString *)readInnerXML; + +// Reads the current node and its contents, including child nodes and markup. +- (NSString *)readOuterXML; + +// Reads the contents of an element or text node as a string. +- (NSString *)readString; + +// Skips over the current element and moves the position of the current instance to the next node in the stream. +- (void)skip; + +@property (nonatomic, copy) NSString *relaxNGSchemaPath; +@property (nonatomic, readonly) BOOL isValid; +@property (nonatomic, retain) id errorHandler; +@end diff --git a/test/XMLReader.m b/test/XMLReader.m new file mode 100755 index 0000000..2ae9812 --- /dev/null +++ b/test/XMLReader.m @@ -0,0 +1,425 @@ + +#import "XMLReader.h" +//#import +#import + +@interface NSString (libxml2Support) ++ (id)stringWithXmlChar:(xmlChar *)xc; +- (xmlChar *)xmlChar; +@end + +@implementation NSString (libxml2Support) + ++ (id)stringWithXmlChar:(xmlChar *)xc { + if (!xc) { + return nil; + } + return [NSString stringWithUTF8String:(char *)xc]; +} + + +- (xmlChar *)xmlChar { + return (unsigned char *)[self UTF8String]; +} + +@end + + +@interface XMLReader () +@property (nonatomic, copy) NSString *path; +@end + + +@implementation XMLReader + +// don't know what this handles. can't get it to fire +static void readerErr(XMLReader *self, const char *msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator) { + NSString *str = [NSString stringWithUTF8String:msg]; + int line = xmlTextReaderLocatorLineNumber(locator); + NSLog(@"some kinda error! %s, severity: %i, line: %i", msg, severity, line); + + switch (severity) { + case XMLReaderSeverityValidityWarning: + [self.errorHandler validityWarning:str lineNumber:line]; + break; + case XMLReaderSeverityValidityError: + [self.errorHandler validityError:str lineNumber:line]; + break; + case XMLReaderSeverityWarning: + [self.errorHandler warning:str lineNumber:line]; + break; + case XMLReaderSeverityError: + [self.errorHandler error:str lineNumber:line]; + break; + } + +} + + +// handles well-formedness errors in instance document +// and handles validity errors in instance doc +static void structErr(XMLReader *self, xmlErrorPtr error) { + const char *msg = error->message; + int line = error->line; + int level = error->level; + + NSLog(@"Instance doc well-formedness or validity error, level: %i", level); + NSLog(@"message: = %s", msg); + NSLog(@"line: = %i", line); + + NSString *str = [NSString stringWithUTF8String:msg]; + + switch (level) { + case XML_ERR_WARNING: + [self.errorHandler warning:str lineNumber:line]; + break; + case XML_ERR_ERROR: + [self.errorHandler error:str lineNumber:line]; + break; + case XML_ERR_FATAL: + [self.errorHandler fatalError:str lineNumber:line]; + break; + } +} + + ++ (id)parserWithContentsOfFile:(NSString *)path { + return [[[XMLReader alloc] initWithContentsOfFile:path] autorelease]; +} + +/* ++ (id)parserWithXMLString:(NSString *)XMLString { + return [[[self alloc] initWithXMLString:XMLStirng] autorelease]; +} +*/ + +- (id)initWithContentsOfFile:(NSString *)newPath { + if (self = [super init]) { + self.path = newPath; + + _reader = xmlNewTextReaderFilename([path UTF8String]); + xmlTextReaderSetParserProp(_reader, XML_PARSE_RECOVER, 1); + xmlTextReaderSetParserProp(_reader, XML_PARSE_XINCLUDE, 1); + xmlTextReaderSetErrorHandler(_reader, (xmlTextReaderErrorFunc)readerErr, (void *)self); + xmlTextReaderSetStructuredErrorHandler(_reader, (xmlStructuredErrorFunc)structErr, (void *)self); + } + return self; +} + + +- (void)dealloc { + self.path = nil; + self.errorHandler = nil; + self.relaxNGSchemaPath = nil; + if (_reader) { + xmlFreeTextReader(_reader); + } + if (_schema) { + xmlRelaxNGFree(_schema); + } + [super dealloc]; +} + + +#pragma mark - +#pragma mark Properties + +- (NSInteger)attributeCount { + return xmlTextReaderAttributeCount(_reader); +} + + +- (NSString *)baseURI { + return [NSString stringWithXmlChar:xmlTextReaderBaseUri(_reader)]; +} + + +//- (BOOL)canResolveEntity { +// return YES; +//} + + +- (NSInteger)depth { + return xmlTextReaderDepth(_reader); +} + + +- (BOOL)isEOF { + return XMLReaderReadStateEOF == [self readState]; +} + + +- (BOOL)hasAttributes { + return xmlTextReaderHasAttributes(_reader); +} + + +- (BOOL)hasValue { + return xmlTextReaderHasValue(_reader); +} + + +- (BOOL)isDefault { + return xmlTextReaderIsDefault(_reader); +} + + +- (BOOL)isEmptyElement { + return xmlTextReaderIsEmptyElement(_reader); +} + + +- (NSString *)localName { + xmlChar *c = xmlTextReaderLocalName(_reader); + if (c) { + return [NSString stringWithXmlChar:c]; + } + return nil; +} + + +- (NSString *)name { + xmlChar *c = xmlTextReaderName(_reader); + if (c) { + return [NSString stringWithXmlChar:c]; + } + return nil; +} + + +- (NSString *)namespaceURI { + xmlChar *c = xmlTextReaderNamespaceUri(_reader); + if (c) { + return [NSString stringWithXmlChar:c]; + } + return nil; +} + + +#pragma mark - +#pragma mark Methods + +- (XMLReaderNodeType)nodeType { + return xmlTextReaderNodeType(_reader); +} + + +- (NSString *)prefix { + return [NSString stringWithXmlChar:xmlTextReaderPrefix(_reader)]; +} + + +- (char)quoteChar { + return xmlTextReaderQuoteChar(_reader); +} + + +- (XMLReaderReadState)readState { + return xmlTextReaderReadState(_reader); +} + + +- (NSString *)value { + return [NSString stringWithXmlChar:xmlTextReaderValue(_reader)]; +} + + +- (NSString *)XMLLang { + return [NSString stringWithXmlChar:xmlTextReaderXmlLang(_reader)]; +} + + +- (void)close { + xmlTextReaderClose(_reader); +} + + +- (NSString *)attributeAtIndex:(NSInteger)index { + return [NSString stringWithXmlChar:xmlTextReaderGetAttributeNo(_reader, index)]; +} + + +- (NSString *)attributeWithQName:(NSString *)qName { + return [NSString stringWithXmlChar:xmlTextReaderGetAttribute(_reader, [qName xmlChar])]; +} + + +- (NSString *)attributeWithLocalName:(NSString *)localName namespaceURI:(NSString *)nsURI { + return [NSString stringWithXmlChar:xmlTextReaderGetAttributeNs(_reader, [localName xmlChar], [nsURI xmlChar])]; +} + + ++ (BOOL)isName:(NSString *)str { + return YES; +} + + ++ (BOOL)isNameToken:(NSString *)str { + return YES; +} + + +- (NSString *)lookupNamespace:(NSString *)prefix { + return [NSString stringWithXmlChar:xmlTextReaderLookupNamespace(_reader, [prefix xmlChar])]; +} + + +- (void)moveToAttributeAtIndex:(NSInteger)index { + xmlTextReaderMoveToAttributeNo(_reader, index); +} + + +- (BOOL)moveToAttributeWithQName:(NSString *)qName { + return xmlTextReaderMoveToAttribute(_reader, [qName xmlChar]); +} + + +- (BOOL)moveToAttributeWithLocalName:(NSString *)localName namespaceURI:(NSString *)nsURI { + return xmlTextReaderMoveToAttributeNs(_reader, [localName xmlChar], [nsURI xmlChar]); +} + + +- (BOOL)moveToElement { + return xmlTextReaderMoveToElement(_reader); +} + + +- (BOOL)moveToFirstAttribute { + return xmlTextReaderMoveToFirstAttribute(_reader); +} + + +- (BOOL)moveToNextAttribute { + return xmlTextReaderMoveToNextAttribute(_reader); +} + + +- (BOOL)read { + return xmlTextReaderRead(_reader); +} + + +- (BOOL)readAttributeValue { + return xmlTextReaderReadAttributeValue(_reader); +} + + +- (NSString *)readElementString { + return [NSString stringWithXmlChar:xmlTextReaderReadString(_reader)]; +} + + +- (NSString *)readInnerXML { + return [NSString stringWithXmlChar:xmlTextReaderReadInnerXml(_reader)]; +} + + +- (NSString *)readOuterXML { + return [NSString stringWithXmlChar:xmlTextReaderReadOuterXml(_reader)]; +} + + +- (NSString *)readString { + return [NSString stringWithXmlChar:xmlTextReaderReadString(_reader)]; +} + + +- (void)skip { + xmlTextReaderNextSibling(_reader); +} + + +// handles warnings encountered while parsing RNG schema +static void rngWarn(XMLReader *self, const char *msg, ...) { + va_list ap; + va_start(ap, msg); + + NSMutableString *str = [NSMutableString stringWithFormat:[NSString stringWithUTF8String:msg], ap]; + NSLog(@"RELAX NG warn: %s", msg); + va_end(ap); + + [str replaceOccurrencesOfString:@"<" + withString:@"<" + options:0 + range:NSMakeRange(0, [str length])]; + + str = [NSString stringWithFormat:@"Warning while parsing RELAX NG schema: %s",msg]; + [self.errorHandler validityWarning:str lineNumber:-1]; +} + + +// handles errors encountered while parsing RNG schema +static void rngErr(XMLReader *self, const char *msg, ...) { + va_list ap; + va_start(ap, msg); + + NSMutableString *str = [NSMutableString stringWithFormat:[NSString stringWithUTF8String:msg], ap]; + NSLog(@"RELAX NG err %@",str); + va_end(ap); + + [str replaceOccurrencesOfString:@"<" + withString:@"<" + options:0 + range:NSMakeRange(0, [str length])]; + + str = [NSString stringWithFormat:@"Error while parsing RELAX NG schema:
%@
",str]; + [self.errorHandler validityError:str lineNumber:-1]; + +} + + +- (NSString *)relaxNGSchemaPath { + return [[relaxNGSchemaPath retain] autorelease]; +} + + +- (void)setRelaxNGSchemaPath:(NSString *)newPath { + if (relaxNGSchemaPath != newPath) { + [relaxNGSchemaPath autorelease]; + relaxNGSchemaPath = [newPath retain]; + + const char *schemafurl = [relaxNGSchemaPath UTF8String]; + + // RELAX NG Parser Context + xmlRelaxNGParserCtxtPtr ctxt = xmlRelaxNGNewParserCtxt(schemafurl); + xmlRelaxNGSetParserErrors(ctxt, + (xmlRelaxNGValidityErrorFunc)rngErr, + (xmlRelaxNGValidityWarningFunc)rngWarn, + (void *)self); + // xmlRelaxNGSetParserStructuredErrors(ctxt, (xmlStructuredErrorFunc)structErr, NULL); + + if (_schema) { + xmlRelaxNGFree(_schema); + _schema = NULL; + } + + NSLog(@"gonna parse schema"); + _schema = xmlRelaxNGParse(ctxt); + NSLog(@"did parse schema"); + xmlRelaxNGFreeParserCtxt(ctxt); + + if (_reader) { + xmlFreeTextReader(_reader); + } + _reader = xmlNewTextReaderFilename([path UTF8String]); + xmlTextReaderSetParserProp(_reader, XML_PARSE_RECOVER, 1); + xmlTextReaderSetParserProp(_reader, XML_PARSE_XINCLUDE, 1); + + xmlTextReaderRelaxNGSetSchema(_reader, _schema); + + xmlTextReaderSetErrorHandler(_reader, (xmlTextReaderErrorFunc)readerErr, (void *)self); + + xmlTextReaderSetStructuredErrorHandler(_reader, (xmlStructuredErrorFunc)structErr, (void *)self); + } + +} + + +- (BOOL)isValid { + return xmlTextReaderIsValid(_reader); +} + +@synthesize path; +@synthesize errorHandler; +@synthesize relaxNGSchemaPath; +@end diff --git a/test/XMLReaderTest.h b/test/XMLReaderTest.h new file mode 100644 index 0000000..7938eaa --- /dev/null +++ b/test/XMLReaderTest.h @@ -0,0 +1,22 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" +#import "XMLReader.h" + +@interface XMLReaderTest : SenTestCase { + +} + +@end diff --git a/test/XMLReaderTest.m b/test/XMLReaderTest.m new file mode 100644 index 0000000..128602a --- /dev/null +++ b/test/XMLReaderTest.m @@ -0,0 +1,33 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "XMLReaderTest.h" + +@implementation XMLReaderTest + +- (void)test { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"apple-boss" ofType:@"xml"]; + + NSLog(@"\n\npath: %@\n\n", path); + + XMLReader *p = [XMLReader parserWithContentsOfFile:path]; + NSInteger ret = [p read]; + while (ret == 1) { + //NSLog(@"nodeType: %d, name: %@", p.nodeType, p.name); + ret = [p read]; + + } +} + +@end diff --git a/test/XPathAssembler.h b/test/XPathAssembler.h new file mode 100644 index 0000000..5ae79af --- /dev/null +++ b/test/XPathAssembler.h @@ -0,0 +1,25 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class XPathContext; +@class PKReader; + +@interface XPathAssembler : NSObject { + XPathContext *context; +} +- (void)resetWithReader:(PKReader *)r; +@property (retain) XPathContext *context; +@end diff --git a/test/XPathAssembler.m b/test/XPathAssembler.m new file mode 100644 index 0000000..3ca6a41 --- /dev/null +++ b/test/XPathAssembler.m @@ -0,0 +1,65 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "XPathAssembler.h" +#import +#import "XPathContext.h" + +@implementation XPathAssembler + +- (id)init { + if (self = [super init]) { + self.context = [[[XPathContext alloc] init] autorelease]; + } + return self; +} + + +- (void)dealloc { + self.context = nil; + [super dealloc]; +} + + +- (void)resetWithReader:(PKReader *)r { + [context resetWithCurrentNode:nil]; +} + + +- (void)didMatchAxisSpecifier:(PKAssembly *)a { + //NSLog(@"\n\n %s\n\n %@ \n\n", _cmd, a); + + //PKToken *tok = [a pop]; + +} + + +- (void)didMatchNodeTest:(PKAssembly *)a { + //NSLog(@"\n\n %s\n\n %@ \n\n", _cmd, a); +} + + +- (void)didMatchPredicate:(PKAssembly *)a { + //NSLog(@"\n\n %s\n\n %@ \n\n", _cmd, a); +} + +// [4] Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep +- (void)didMatchStep:(PKAssembly *)a { + //NSLog(@"\n\n %s\n\n %@ \n\n", _cmd, a); +} + + + +@synthesize context; +@end diff --git a/test/XPathContext.h b/test/XPathContext.h new file mode 100644 index 0000000..6a017ef --- /dev/null +++ b/test/XPathContext.h @@ -0,0 +1,35 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface XPathContext : NSObject { + // static context + NSString *baseURIString; + NSMutableDictionary *namespaces; + NSMutableDictionary *variables; + NSMutableDictionary *functions; + + // dynamic context + NSXMLNode *currentNode; + NSXMLNode *contextNode; + NSArray *contextNodeSet; + + // +} +- (void)resetWithCurrentNode:(NSXMLNode *)n; +@property (retain) NSXMLNode *currentNode; +@property (retain) NSXMLNode *contextNode; +@property (retain) NSArray *contextNodeSet; +@end diff --git a/test/XPathContext.m b/test/XPathContext.m new file mode 100644 index 0000000..987d728 --- /dev/null +++ b/test/XPathContext.m @@ -0,0 +1,43 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "XPathContext.h" + +@implementation XPathContext + +- (id)init { + if (self = [super init]) { + } + return self; +} + + +- (void)resetWithCurrentNode:(NSXMLNode *)n { + self.currentNode = n; + self.contextNode = nil; + self.contextNodeSet = nil; +} + + +- (void)dealloc { + self.currentNode = nil; + self.contextNode = nil; + self.contextNodeSet = nil; + [super dealloc]; +} + +@synthesize currentNode; +@synthesize contextNode; +@synthesize contextNodeSet; +@end diff --git a/test/XPathParser.h b/test/XPathParser.h new file mode 100644 index 0000000..ece099f --- /dev/null +++ b/test/XPathParser.h @@ -0,0 +1,102 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class XPathAssembler; +@class PKAssembly; + +@interface XPathParser : PKSequence { + XPathAssembler *xpathAssembler; + PKCollectionParser *locationPath; + PKCollectionParser *absoluteLocationPath; + PKCollectionParser *relativeLocationPath; + PKCollectionParser *step; + PKCollectionParser *axisSpecifier; + PKCollectionParser *axisName; + PKCollectionParser *nodeTest; + PKCollectionParser *predicate; + PKCollectionParser *predicateExpr; + PKCollectionParser *abbreviatedAbsoluteLocationPath; + PKCollectionParser *abbreviatedRelativeLocationPath; + PKCollectionParser *abbreviatedStep; + PKCollectionParser *abbreviatedAxisSpecifier; + PKCollectionParser *expr; + PKCollectionParser *primaryExpr; + PKCollectionParser *functionCall; + PKCollectionParser *argument; + PKCollectionParser *unionExpr; + PKCollectionParser *pathExpr; + PKCollectionParser *filterExpr; + PKCollectionParser *orExpr; + PKCollectionParser *andExpr; + PKCollectionParser *equalityExpr; + PKCollectionParser *relationalExpr; + PKCollectionParser *additiveExpr; + PKCollectionParser *multiplicativeExpr; + PKCollectionParser *unaryExpr; + PKCollectionParser *exprToken; + PKParser *literal; + PKParser *number; + PKCollectionParser *operator; + PKCollectionParser *operatorName; + PKParser *multiplyOperator; + PKParser *functionName; + PKCollectionParser *variableReference; + PKCollectionParser *nameTest; + PKCollectionParser *nodeType; + PKCollectionParser *QName; +} +- (id)parse:(NSString *)s; +- (PKAssembly *)assemblyWithString:(NSString *)s; + +@property (retain) PKCollectionParser *locationPath; +@property (retain) PKCollectionParser *absoluteLocationPath; +@property (retain) PKCollectionParser *relativeLocationPath; +@property (retain) PKCollectionParser *step; +@property (retain) PKCollectionParser *axisSpecifier; +@property (retain) PKCollectionParser *axisName; +@property (retain) PKCollectionParser *nodeTest; +@property (retain) PKCollectionParser *predicate; +@property (retain) PKCollectionParser *predicateExpr; +@property (retain) PKCollectionParser *abbreviatedAbsoluteLocationPath; +@property (retain) PKCollectionParser *abbreviatedRelativeLocationPath; +@property (retain) PKCollectionParser *abbreviatedStep; +@property (retain) PKCollectionParser *abbreviatedAxisSpecifier; +@property (retain) PKCollectionParser *expr; +@property (retain) PKCollectionParser *primaryExpr; +@property (retain) PKCollectionParser *functionCall; +@property (retain) PKCollectionParser *argument; +@property (retain) PKCollectionParser *unionExpr; +@property (retain) PKCollectionParser *pathExpr; +@property (retain) PKCollectionParser *filterExpr; +@property (retain) PKCollectionParser *orExpr; +@property (retain) PKCollectionParser *andExpr; +@property (retain) PKCollectionParser *equalityExpr; +@property (retain) PKCollectionParser *relationalExpr; +@property (retain) PKCollectionParser *additiveExpr; +@property (retain) PKCollectionParser *multiplicativeExpr; +@property (retain) PKCollectionParser *unaryExpr; +@property (retain) PKCollectionParser *exprToken; +@property (retain) PKParser *literal; +@property (retain) PKParser *number; +@property (retain) PKCollectionParser *operator; +@property (retain) PKCollectionParser *operatorName; +@property (retain) PKParser *multiplyOperator; +@property (retain) PKParser *functionName; +@property (retain) PKCollectionParser *variableReference; +@property (retain) PKCollectionParser *nameTest; +@property (retain) PKCollectionParser *nodeType; +@property (retain) PKCollectionParser *QName; +@end diff --git a/test/XPathParser.m b/test/XPathParser.m new file mode 100644 index 0000000..9739d0d --- /dev/null +++ b/test/XPathParser.m @@ -0,0 +1,979 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "XPathParser.h" +//#import "TDNCName.h" + +#import "TDNCNameState.h" +#import "XPathAssembler.h" + +@interface XPathParser () +@property (retain) XPathAssembler *xpathAssembler; +@end + +@implementation XPathParser + +- (id)init { + if (self = [super init]) { + self.xpathAssembler = [[[XPathAssembler alloc] init] autorelease]; + [self add:self.locationPath]; + } + return self; +} + + +- (void)dealloc { + self.xpathAssembler = nil; + self.locationPath = nil; + self.absoluteLocationPath = nil; + self.relativeLocationPath = nil; + self.step = nil; + self.axisSpecifier = nil; + self.axisName = nil; + self.nodeTest = nil; + self.predicate = nil; + self.predicateExpr = nil; + self.abbreviatedAbsoluteLocationPath = nil; + self.abbreviatedRelativeLocationPath = nil; + self.abbreviatedStep = nil; + self.abbreviatedAxisSpecifier = nil; + self.expr = nil; + self.primaryExpr = nil; + self.functionCall = nil; + self.argument = nil; + self.unionExpr = nil; + self.pathExpr = nil; + self.filterExpr = nil; + self.orExpr = nil; + self.andExpr = nil; + self.equalityExpr = nil; + self.relationalExpr = nil; + self.additiveExpr = nil; + self.multiplicativeExpr = nil; + self.unaryExpr = nil; + self.exprToken = nil; + self.literal = nil; + self.number = nil; + self.operator = nil; + self.operatorName = nil; + self.multiplyOperator = nil; + self.functionName = nil; + self.variableReference = nil; + self.nameTest = nil; + self.nodeType = nil; + self.QName = nil; + [super dealloc]; +} + + +- (PKAssembly *)assemblyWithString:(NSString *)s { + PKTokenizer *t = [[[PKTokenizer alloc] initWithString:s] autorelease]; + [t.symbolState add:@"::"]; + [t.symbolState add:@"!="]; + [t.symbolState add:@"<="]; + [t.symbolState add:@">="]; + [t.symbolState add:@".."]; + [t.symbolState add:@"//"]; + [t setTokenizerState:t.wordState from: '_' to: '_']; +// [t setTokenizerState:NCNameState from: 'a' to: 'z']; +// [t setTokenizerState:NCNameState from: 'A' to: 'Z']; +// [t setTokenizerState:NCNameState from:0xc0 to:0xff]; + + PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:t]; +// TDNCNameState *NCNameState = [[[TDNCNameState alloc] init] autorelease]; + + return a; +} + + +- (id)parse:(NSString *)s { + [xpathAssembler resetWithReader:nil]; + PKAssembly *a = [self assemblyWithString:s]; + id result = [self completeMatchFor:a]; + return result; +} + + +// [1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath +- (PKCollectionParser *)locationPath { + //NSLog(@"%s", _cmd); + if (!locationPath) { + self.locationPath = [PKAlternation alternation]; + locationPath.name = @"locationPath"; + + [locationPath add:self.relativeLocationPath]; + [locationPath add:self.absoluteLocationPath]; + } + return locationPath; +} + + +//[2] AbsoluteLocationPath ::= '/' RelativeLocationPath? | AbbreviatedAbsoluteLocationPath +- (PKCollectionParser *)absoluteLocationPath { + //NSLog(@"%s", _cmd); + if (!absoluteLocationPath) { + self.absoluteLocationPath = [PKAlternation alternation]; + absoluteLocationPath.name = @"absoluteLocationPath"; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.relativeLocationPath]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"/"]]; + [s add:a]; + + [absoluteLocationPath add:s]; + [absoluteLocationPath add:self.abbreviatedAbsoluteLocationPath]; + } + return absoluteLocationPath; +} + +#pragma mark - +#pragma mark left recursion + +//[3] RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | AbbreviatedRelativeLocationPath + +// avoiding left recursion by changing to this +//[3] RelativeLocationPath ::= Step SlashStep* | AbbreviatedRelativeLocationPath + +- (PKCollectionParser *)relativeLocationPath { + //NSLog(@"%s", _cmd); + if (!relativeLocationPath) { + self.relativeLocationPath = [PKAlternation alternation]; + relativeLocationPath.name = @"relativeLocationPath"; + + PKSequence *s = [PKSequence sequence]; + [s add:self.step]; + + PKSequence *slashStep = [PKSequence sequence]; + [slashStep add:[PKSymbol symbolWithString:@"/"]]; + [slashStep add:self.step]; + [s add:[PKRepetition repetitionWithSubparser:slashStep]]; + + [relativeLocationPath add:s]; + // TODO this is causing and infinite loop! +// [relativeLocationPath add:self.abbreviatedRelativeLocationPath]; + } + return relativeLocationPath; +} + + +// [4] Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep +- (PKCollectionParser *)step { + NSLog(@"%s", _cmd); + if (!step) { + self.step = [PKAlternation alternation]; + step.name = @"step"; + + PKSequence *s = [PKSequence sequence]; + [s add:self.axisSpecifier]; + [s add:self.nodeTest]; + [s add:[PKRepetition repetitionWithSubparser:self.predicate]]; + + [step add:s]; + [step add:self.abbreviatedStep]; + + [step setAssembler:xpathAssembler selector:@selector(didMatchStep:)]; + } + return step; +} + + +// [5] AxisSpecifier ::= AxisName '::' | AbbreviatedAxisSpecifier +- (PKCollectionParser *)axisSpecifier { + //NSLog(@"%s", _cmd); + if (!axisSpecifier) { + self.axisSpecifier = [PKAlternation alternation]; + axisSpecifier.name = @"axisSpecifier"; + + PKSequence *s = [PKSequence sequence]; + [s add:self.axisName]; + [s add:[PKSymbol symbolWithString:@"::"]]; + + [axisSpecifier add:s]; + [axisSpecifier add:self.abbreviatedAxisSpecifier]; + [axisSpecifier setAssembler:xpathAssembler selector:@selector(didMatchAxisSpecifier:)]; + } + return axisSpecifier; +} + + +// [6] AxisName ::= 'ancestor' | 'ancestor-or-self' | 'attribute' | 'child' | 'descendant' | 'descendant-or-self' +// | 'following' | 'following-sibling' | 'namespace' | 'parent' | 'preceding' | 'preceding-sibling' | 'self' +- (PKCollectionParser *)axisName { + //NSLog(@"%s", _cmd); + if (!axisName) { + self.axisName = [PKAlternation alternation]; + axisName.name = @"axisName"; + [axisName add:[PKLiteral literalWithString:@"ancestor"]]; + [axisName add:[PKLiteral literalWithString:@"ancestor-or-self"]]; + [axisName add:[PKLiteral literalWithString:@"attribute"]]; + [axisName add:[PKLiteral literalWithString:@"child"]]; + [axisName add:[PKLiteral literalWithString:@"descendant"]]; + [axisName add:[PKLiteral literalWithString:@"descendant-or-self"]]; + [axisName add:[PKLiteral literalWithString:@"following"]]; + [axisName add:[PKLiteral literalWithString:@"following-sibling"]]; + [axisName add:[PKLiteral literalWithString:@"preceeding"]]; + [axisName add:[PKLiteral literalWithString:@"preceeding-sibling"]]; + [axisName add:[PKLiteral literalWithString:@"namespace"]]; + [axisName add:[PKLiteral literalWithString:@"parent"]]; + [axisName add:[PKLiteral literalWithString:@"self"]]; + } + return axisName; +} + + +// [7] NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' +- (PKCollectionParser *)nodeTest { + //NSLog(@"%s", _cmd); + if (!nodeTest) { + self.nodeTest = [PKAlternation alternation]; + nodeTest.name = @"nodeTest"; + [nodeTest add:self.nameTest]; + + PKSequence *s = [PKSequence sequence]; + [s add:self.nodeType]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:[PKSymbol symbolWithString:@")"]]; + [nodeTest add:s]; + + s = [PKSequence sequence]; + [s add:[PKLiteral literalWithString:@"processing-instruction"]]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:self.literal]; + [s add:[PKSymbol symbolWithString:@")"]]; + [nodeTest add:s]; + } + return nodeTest; +} + + +// [8] Predicate ::= '[' PredicateExpr ']' +- (PKCollectionParser *)predicate { + //NSLog(@"%s", _cmd); + if (!predicate) { + self.predicate = [PKSequence sequence]; + predicate.name = @"predicate"; + [predicate add:[PKSymbol symbolWithString:@"["]]; + [predicate add:self.predicateExpr]; + [predicate add:[PKSymbol symbolWithString:@"]"]]; + } + return predicate; +} + + +// [9] PredicateExpr ::= Expr +- (PKCollectionParser *)predicateExpr { + //NSLog(@"%s", _cmd); + if (!predicateExpr) { + self.predicateExpr = self.expr; + predicateExpr.name = @"predicateExpr"; + } + return predicateExpr; +} + + +// [10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath +- (PKCollectionParser *)abbreviatedAbsoluteLocationPath { + //NSLog(@"%s", _cmd); + if (!abbreviatedAbsoluteLocationPath) { + self.abbreviatedAbsoluteLocationPath = [PKSequence sequence]; + abbreviatedAbsoluteLocationPath.name = @"abbreviatedAbsoluteLocationPath"; + [abbreviatedAbsoluteLocationPath add:[PKSymbol symbolWithString:@"//"]]; + [abbreviatedAbsoluteLocationPath add:self.relativeLocationPath]; + } + return abbreviatedAbsoluteLocationPath; +} + + +// [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step +- (PKCollectionParser *)abbreviatedRelativeLocationPath { + //NSLog(@"%s", _cmd); + if (!abbreviatedRelativeLocationPath) { + self.abbreviatedRelativeLocationPath = [PKSequence sequence]; + abbreviatedRelativeLocationPath.name = @"abbreviatedRelativeLocationPath"; + [abbreviatedRelativeLocationPath add:self.relativeLocationPath]; + [abbreviatedRelativeLocationPath add:[PKSymbol symbolWithString:@"//"]]; + [abbreviatedRelativeLocationPath add:self.step]; + } + return abbreviatedRelativeLocationPath; +} + + +// [12] AbbreviatedStep ::= '.' | '..' +- (PKCollectionParser *)abbreviatedStep { + //NSLog(@"%s", _cmd); + if (!abbreviatedStep) { + self.abbreviatedStep = [PKAlternation alternation]; + abbreviatedStep.name = @"abbreviatedStep"; + [abbreviatedStep add:[PKSymbol symbolWithString:@"."]]; + [abbreviatedStep add:[PKSymbol symbolWithString:@".."]]; + } + return abbreviatedStep; +} + + +// [13] AbbreviatedAxisSpecifier ::= '@'? +- (PKCollectionParser *)abbreviatedAxisSpecifier { + //NSLog(@"%s", _cmd); + if (!abbreviatedAxisSpecifier) { + self.abbreviatedAxisSpecifier = [PKAlternation alternation]; + abbreviatedAxisSpecifier.name = @"abbreviatedAxisSpecifier"; + [abbreviatedAxisSpecifier add:[PKEmpty empty]]; + [abbreviatedAxisSpecifier add:[PKSymbol symbolWithString:@"@"]]; + } + return abbreviatedAxisSpecifier; +} + + +// [14] Expr ::= OrExpr +- (PKCollectionParser *)expr { + //NSLog(@"%s", _cmd); + if (!expr) { + self.expr = self.orExpr; + expr.name = @"expr"; + } + return expr; +} + + +// [15] PrimaryExpr ::= VariableReference +// | '(' Expr ')' +// | Literal +// | Number +// | FunctionCall +- (PKCollectionParser *)primaryExpr { + //NSLog(@"%s", _cmd); + if (!primaryExpr) { + self.primaryExpr = [PKAlternation alternation]; + primaryExpr.name = @"primaryExpr"; + [primaryExpr add:self.variableReference]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKSymbol symbolWithString:@"("]]; + [s add:self.expr]; + [s add:[PKSymbol symbolWithString:@")"]]; + [primaryExpr add:s]; + + [primaryExpr add:self.literal]; + [primaryExpr add:self.number]; + [primaryExpr add:self.functionCall]; + } + return primaryExpr; +} + + +// [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' + +// commaArg ::= ',' Argument +// [16] FunctionCall ::= FunctionName '(' ( Argument commaArg* )? ')' +- (PKCollectionParser *)functionCall { + //NSLog(@"%s", _cmd); + if (!functionCall) { + self.functionCall = [PKSequence sequence]; + functionCall.name = @"functionCall"; + [functionCall add:self.functionName]; + [functionCall add:[PKSymbol symbolWithString:@"("]]; + + PKSequence *commaArg = [PKSequence sequence]; + [commaArg add:[PKSymbol symbolWithString:@","]]; + [commaArg add:self.argument]; + + PKSequence *args = [PKSequence sequence]; + [args add:self.argument]; + [args add:[PKRepetition repetitionWithSubparser:commaArg]]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:args]; + + [functionCall add:a]; + [functionCall add:[PKSymbol symbolWithString:@")"]]; + } + return functionCall; +} + + +// [17] Argument ::= Expr +- (PKCollectionParser *)argument { + //NSLog(@"%s", _cmd); + if (!argument) { + self.argument = self.expr; + argument.name = @"argument"; + } + return argument; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [18] UnionExpr ::= PathExpr | UnionExpr '|' PathExpr + +// pipePathExpr :: = | PathExpr +// [18] UnionExpr ::= PathExpr PipePathExpr* +- (PKCollectionParser *)unionExpr { + //NSLog(@"%s", _cmd); + if (!unionExpr) { + self.unionExpr = [PKSequence sequence]; + unionExpr.name = @"unionExpr"; + + PKSequence *pipePathExpr = [PKSequence sequence]; + [pipePathExpr add:[PKSymbol symbolWithString:@"|"]]; + [pipePathExpr add:self.pathExpr]; + + [unionExpr add:self.pathExpr]; + [unionExpr add:[PKRepetition repetitionWithSubparser:pipePathExpr]]; + } + return unionExpr; +} + + +//[19] PathExpr ::= LocationPath +// | FilterExpr +// | FilterExpr '/' RelativeLocationPath +// | FilterExpr '//' RelativeLocationPath +- (PKCollectionParser *)pathExpr { + //NSLog(@"%s", _cmd); + if (!pathExpr) { + self.pathExpr = [PKAlternation alternation]; + pathExpr.name = @"pathExpr"; + [pathExpr add:self.locationPath]; + [pathExpr add:self.filterExpr]; + + PKSequence *s = [PKSequence sequence]; + [s add:self.filterExpr]; + [s add:[PKSymbol symbolWithString:@"/"]]; + [s add:self.relativeLocationPath]; + [pathExpr add:s]; + + s = [PKSequence sequence]; + [s add:self.filterExpr]; + [s add:[PKSymbol symbolWithString:@"//"]]; + [s add:self.relativeLocationPath]; + [pathExpr add:s]; + } + return pathExpr; +} + + +#pragma mark - +#pragma mark Left Recursion???????????? + +// [20] FilterExpr ::= PrimaryExpr | FilterExpr Predicate + + +// [20] FilterExpr ::= PrimaryExpr Predicate? +- (PKCollectionParser *)filterExpr { + //NSLog(@"%s", _cmd); + if (!filterExpr) { + self.filterExpr = [PKSequence sequence]; + filterExpr.name = @"filterExpr"; + [filterExpr add:self.primaryExpr]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:self.predicate]; + [filterExpr add:a]; + } + return filterExpr; +} + + +#pragma mark - +#pragma mark Left Recursion +// [21] OrExpr ::= AndExpr | OrExpr 'or' AndExpr + +// orAndExpr ::= 'or' AndExpr +// me: AndExpr orAndExpr* +- (PKCollectionParser *)orExpr { + //NSLog(@"%s", _cmd); + if (!orExpr) { + self.orExpr = [PKSequence sequence]; + orExpr.name = @"orExpr"; + + [orExpr add:self.andExpr]; + + PKSequence *orAndExpr = [PKSequence sequence]; + [orAndExpr add:[PKLiteral literalWithString:@"or"]]; + [orAndExpr add:self.andExpr]; + + [orExpr add:[PKRepetition repetitionWithSubparser:orAndExpr]]; + } + return orExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [22] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr + + +// andEqualityExpr +// EqualityExpr andEqualityExpr + +- (PKCollectionParser *)andExpr { + //NSLog(@"%s", _cmd); + if (!andExpr) { + self.andExpr = [PKSequence sequence]; + andExpr.name = @"andExpr"; + [andExpr add:self.equalityExpr]; + + PKSequence *andEqualityExpr = [PKSequence sequence]; + [andEqualityExpr add:[PKLiteral literalWithString:@"and"]]; + [andEqualityExpr add:self.equalityExpr]; + + [andExpr add:[PKRepetition repetitionWithSubparser:andEqualityExpr]]; + } + return andExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [23] EqualityExpr ::= RelationalExpr +// | EqualityExpr '=' RelationalExpr +// | EqualityExpr '!=' RelationalExpr + +// RelationalExpr (equalsRelationalExpr | notEqualsRelationalExpr)? + +- (PKCollectionParser *)equalityExpr { + //NSLog(@"%s", _cmd); + if (!equalityExpr) { + self.equalityExpr = [PKSequence sequence]; + equalityExpr.name = @"equalityExpr"; + [equalityExpr add:self.relationalExpr]; + + PKSequence *equalsRelationalExpr = [PKSequence sequence]; + [equalsRelationalExpr add:[PKSymbol symbolWithString:@"="]]; + [equalsRelationalExpr add:self.relationalExpr]; + + PKSequence *notEqualsRelationalExpr = [PKSequence sequence]; + [notEqualsRelationalExpr add:[PKSymbol symbolWithString:@"!="]]; + [notEqualsRelationalExpr add:self.relationalExpr]; + + PKAlternation *a = [PKAlternation alternation]; + [a add:equalsRelationalExpr]; + [a add:notEqualsRelationalExpr]; + + PKAlternation *a1 = [PKAlternation alternation]; + [a1 add:[PKEmpty empty]]; + [a1 add:a]; + + [equalityExpr add:a1]; + } + return equalityExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [24] RelationalExpr ::= AdditiveExpr +// | RelationalExpr '<' AdditiveExpr +// | RelationalExpr '>' AdditiveExpr +// | RelationalExpr '<=' AdditiveExpr +// | RelationalExpr '>=' AdditiveExpr + +// RelationalExpr = AdditiveExpr (ltAdditiveExpr | gtAdditiveExpr | lteAdditiveExpr | gteAdditiveExpr)? +- (PKCollectionParser *)relationalExpr { + //NSLog(@"%s", _cmd); + if (!relationalExpr) { + + self.relationalExpr = [PKSequence sequence]; + relationalExpr.name = @"relationalExpr"; + [relationalExpr add:self.additiveExpr]; + + PKAlternation *a = [PKAlternation alternation]; + + PKSequence *ltAdditiveExpr = [PKSequence sequence]; + [ltAdditiveExpr add:[PKSymbol symbolWithString:@"<"]]; + [a add:ltAdditiveExpr]; + + PKSequence *gtAdditiveExpr = [PKSequence sequence]; + [gtAdditiveExpr add:[PKSymbol symbolWithString:@">"]]; + [a add:gtAdditiveExpr]; + + PKSequence *lteAdditiveExpr = [PKSequence sequence]; + [lteAdditiveExpr add:[PKSymbol symbolWithString:@"<="]]; + [a add:lteAdditiveExpr]; + + PKSequence *gteAdditiveExpr = [PKSequence sequence]; + [gteAdditiveExpr add:[PKSymbol symbolWithString:@">="]]; + [a add:gteAdditiveExpr]; + + PKAlternation *a1 = [PKAlternation alternation]; + [a1 add:[PKEmpty empty]]; + [a1 add:a]; + + [relationalExpr add:a1]; + } + return relationalExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [25] AdditiveExpr ::= MultiplicativeExpr +// | AdditiveExpr '+' MultiplicativeExpr +// | AdditiveExpr '-' MultiplicativeExpr + +// AdditiveExpr ::= MultiplicativeExpr (plusMultiplicativeExpr | minusMultiplicativeExpr)? +- (PKCollectionParser *)additiveExpr { + //NSLog(@"%s", _cmd); + if (!additiveExpr) { + self.additiveExpr = [PKSequence sequence]; + additiveExpr.name = @"additiveExpr"; + [additiveExpr add:self.multiplicativeExpr]; + + PKAlternation *a = [PKAlternation alternation]; + + PKSequence *plusMultiplicativeExpr = [PKSequence sequence]; + [plusMultiplicativeExpr add:[PKSymbol symbolWithString:@"+"]]; + [plusMultiplicativeExpr add:self.multiplicativeExpr]; + [a add:plusMultiplicativeExpr]; + + PKSequence *minusMultiplicativeExpr = [PKSequence sequence]; + [minusMultiplicativeExpr add:[PKSymbol symbolWithString:@"-"]]; + [minusMultiplicativeExpr add:self.multiplicativeExpr]; + [a add:minusMultiplicativeExpr]; + + PKAlternation *a1 = [PKAlternation alternation]; + [a1 add:[PKEmpty empty]]; + [a1 add:a]; + + [additiveExpr add:a1]; + } + return additiveExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [26] MultiplicativeExpr ::= UnaryExpr +// | MultiplicativeExpr MultiplyOperator UnaryExpr +// | MultiplicativeExpr 'div' UnaryExpr +// | MultiplicativeExpr 'mod' UnaryExpr + +// MultiplicativeExpr :: = UnaryExpr (multiplyUnaryExpr | divUnaryExpr | modUnaryExpr)? +- (PKCollectionParser *)multiplicativeExpr { + //NSLog(@"%s", _cmd); + if (!multiplicativeExpr) { + self.multiplicativeExpr = [PKSequence sequence]; + multiplicativeExpr.name = @"multiplicativeExpr"; + [multiplicativeExpr add:self.unaryExpr]; + + PKAlternation *a = [PKAlternation alternation]; + + PKSequence *multiplyUnaryExpr = [PKSequence sequence]; + [multiplyUnaryExpr add:self.multiplyOperator]; + [multiplyUnaryExpr add:self.unaryExpr]; + [a add:multiplyUnaryExpr]; + + PKSequence *divUnaryExpr = [PKSequence sequence]; + [divUnaryExpr add:[PKLiteral literalWithString:@"div"]]; + [divUnaryExpr add:self.unaryExpr]; + [a add:divUnaryExpr]; + + PKSequence *modUnaryExpr = [PKSequence sequence]; + [modUnaryExpr add:[PKLiteral literalWithString:@"mod"]]; + [modUnaryExpr add:self.unaryExpr]; + [a add:modUnaryExpr]; + + PKAlternation *a1 = [PKAlternation alternation]; + [a1 add:[PKEmpty empty]]; + [a1 add:a]; + + [multiplicativeExpr add:a1]; + } + return multiplicativeExpr; +} + + +#pragma mark - +#pragma mark Left Recursion + +// [27] UnaryExpr ::= UnionExpr | '-' UnaryExpr + +// UnaryExpr ::= '-'? UnionExpr +- (PKCollectionParser *)unaryExpr { + //NSLog(@"%s", _cmd); + if (!unaryExpr) { + self.unaryExpr = [PKSequence sequence]; + unaryExpr.name = @"unaryExpr"; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKEmpty empty]]; + [a add:[PKSymbol symbolWithString:@"-"]]; + + [unaryExpr add:a]; + [unaryExpr add:self.unionExpr]; + + // self.unaryExpr = [PKAlternation alternation]; +// [unaryExpr add:self.unionExpr]; +// +// PKSequence *s = [PKSequence sequence]; +// [s add:[PKSymbol symbolWithString:@"-"]]; +// [s add:unaryExpr]; +// [unionExpr add:s]; + } + return unaryExpr; +} + + +// [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' +// | NameTest +// | NodeType +// | Operator +// | FunctionName +// | AxisName +// | Literal +// | Number +// | VariableReference +- (PKCollectionParser *)exprToken { + //NSLog(@"%s", _cmd); + if (!exprToken) { + self.exprToken = [PKAlternation alternation]; + exprToken.name = @"exprToken"; + + PKAlternation *a = [PKAlternation alternation]; + [a add:[PKSymbol symbolWithString:@"("]]; + [a add:[PKSymbol symbolWithString:@")"]]; + [a add:[PKSymbol symbolWithString:@"["]]; + [a add:[PKSymbol symbolWithString:@"]"]]; + [a add:[PKSymbol symbolWithString:@"."]]; + [a add:[PKSymbol symbolWithString:@".."]]; + [a add:[PKSymbol symbolWithString:@"@"]]; + [a add:[PKSymbol symbolWithString:@","]]; + [a add:[PKSymbol symbolWithString:@"::"]]; + [exprToken add:a]; + + [exprToken add:self.nameTest]; + [exprToken add:self.nodeType]; + [exprToken add:self.operator]; + [exprToken add:self.functionName]; + [exprToken add:self.axisName]; + [exprToken add:self.literal]; + [exprToken add:self.number]; + [exprToken add:self.variableReference]; + } + return exprToken; +} + + +- (PKParser *)literal { + //NSLog(@"%s", _cmd); + if (!literal) { + self.literal = [PKQuotedString quotedString]; + literal.name = @"literal"; + } + return literal; +} + + +- (PKParser *)number { + //NSLog(@"%s", _cmd); + if (!number) { + self.number = [PKNumber number]; + number.name = @"number"; + } + return number; +} + + +// [32] Operator ::= OperatorName +// | MultiplyOperator +// | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' +- (PKCollectionParser *)operator { + //NSLog(@"%s", _cmd); + if (!operator) { + self.operator = [PKAlternation alternation]; + operator.name = @"operator"; + [operator add:self.operatorName]; + [operator add:self.multiplyOperator]; + [operator add:[PKSymbol symbolWithString: @"/"]]; + [operator add:[PKSymbol symbolWithString:@"//"]]; + [operator add:[PKSymbol symbolWithString: @"|"]]; + [operator add:[PKSymbol symbolWithString: @"+"]]; + [operator add:[PKSymbol symbolWithString: @"-"]]; + [operator add:[PKSymbol symbolWithString: @"="]]; + [operator add:[PKSymbol symbolWithString:@"!="]]; + [operator add:[PKSymbol symbolWithString: @"<"]]; + [operator add:[PKSymbol symbolWithString:@"<="]]; + [operator add:[PKSymbol symbolWithString: @">"]]; + [operator add:[PKSymbol symbolWithString:@">="]]; + } + return operator; +} + + +// [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div' +- (PKCollectionParser *)operatorName { + //NSLog(@"%s", _cmd); + if (!operatorName) { + self.operatorName = [PKAlternation alternation]; + operatorName.name = @"operatorName"; + [operatorName add:[PKLiteral literalWithString:@"and"]]; + [operatorName add:[PKLiteral literalWithString: @"or"]]; + [operatorName add:[PKLiteral literalWithString:@"mod"]]; + [operatorName add:[PKLiteral literalWithString:@"div"]]; + } + return operatorName; +} + + +// [34] MultiplyOperator ::= '*' +- (PKParser *)multiplyOperator { + //NSLog(@"%s", _cmd); + if (!multiplyOperator) { + self.multiplyOperator = [PKSymbol symbolWithString:@"*"]; + multiplyOperator.name = @"multiplyOperator"; + } + return multiplyOperator; +} + + +//[7] QName ::= PrefixedName| UnprefixedName +//[8] PrefixedName ::= Prefix ':' LocalPart +//[9] UnprefixedName ::= LocalPart +//[10] Prefix ::= NCName +//[11] LocalPart ::= NCName +- (PKCollectionParser *)QName { + //NSLog(@"%s", _cmd); + if (!QName) { + self.QName = [PKAlternation alternation]; + QName.name = @"QName"; + + PKParser *prefix = [PKWord word]; + PKParser *localPart = [PKWord word]; + PKParser *unprefixedName = localPart; + + PKSequence *prefixedName = [PKSequence sequence]; + [prefixedName add:prefix]; + [prefixedName add:[PKSymbol symbolWithString:@":"]]; + [prefixedName add:localPart]; + + [QName add:prefixedName]; + [QName add:unprefixedName]; + } + return QName; +} + + +// [35] FunctionName ::= QName - NodeType +- (PKParser *)functionName { + //NSLog(@"%s", _cmd); + if (!functionName) { + self.functionName = self.QName; // TODO QName - NodeType + functionName.name = @"functionName"; + } + return functionName; +} + + +// [36] VariableReference ::= '$' QName +- (PKCollectionParser *)variableReference { + //NSLog(@"%s", _cmd); + if (!variableReference) { + self.variableReference = [PKSequence sequence]; + variableReference.name = @"variableReference"; + [variableReference add:[PKSymbol symbolWithString:@"$"]]; + [variableReference add:self.QName]; + } + return variableReference; +} + + +// [37] NameTest ::= '*' | NCName ':' '*' | QName +- (PKCollectionParser *)nameTest { + //NSLog(@"%s", _cmd); + if (!nameTest) { + self.nameTest = [PKAlternation alternation]; + nameTest.name = @"nameTest"; + [nameTest add:[PKSymbol symbolWithString:@"*"]]; + + PKSequence *s = [PKSequence sequence]; + [s add:[PKWord word]]; + [s add:[PKSymbol symbolWithString:@":"]]; + [s add:[PKSymbol symbolWithString:@"*"]]; + [nameTest add:s]; + + [nameTest add:self.QName]; + } + return nameTest; +} + + +// [38] NodeType ::= 'comment' +// | 'text' +// | 'processing-instruction' +// | 'node' +- (PKCollectionParser *)nodeType { + //NSLog(@"%s", _cmd); + if (!nodeType) { + self.nodeType = [PKAlternation alternation]; + nodeType.name = @"nodeType"; + [nodeType add:[PKLiteral literalWithString:@"comment"]]; + [nodeType add:[PKLiteral literalWithString:@"text"]]; + [nodeType add:[PKLiteral literalWithString:@"processing-instruction"]]; + [nodeType add:[PKLiteral literalWithString:@"node"]]; + } + return nodeType; +} + +@synthesize xpathAssembler; +@synthesize locationPath; +@synthesize absoluteLocationPath; +@synthesize relativeLocationPath; +@synthesize step; +@synthesize axisSpecifier; +@synthesize axisName; +@synthesize nodeTest; +@synthesize predicate; +@synthesize predicateExpr; +@synthesize abbreviatedAbsoluteLocationPath; +@synthesize abbreviatedRelativeLocationPath; +@synthesize abbreviatedStep; +@synthesize abbreviatedAxisSpecifier; +@synthesize expr; +@synthesize primaryExpr; +@synthesize functionCall; +@synthesize argument; +@synthesize unionExpr; +@synthesize pathExpr; +@synthesize filterExpr; +@synthesize orExpr; +@synthesize andExpr; +@synthesize equalityExpr; +@synthesize relationalExpr; +@synthesize additiveExpr; +@synthesize multiplicativeExpr; +@synthesize unaryExpr; +@synthesize exprToken; +@synthesize literal; +@synthesize number; +@synthesize operator; +@synthesize operatorName; +@synthesize multiplyOperator; +@synthesize functionName; +@synthesize variableReference; +@synthesize nameTest; +@synthesize nodeType; +@synthesize QName; +@end diff --git a/test/XPathParserGrammarTest.h b/test/XPathParserGrammarTest.h new file mode 100644 index 0000000..2fc3388 --- /dev/null +++ b/test/XPathParserGrammarTest.h @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +@interface XPathParserGrammarTest : SenTestCase { + NSString *s; + PKParser *p; + PKTokenizer *t; + PKAssembly *a; + PKAssembly *res; + PKToken *tok; +} + +@end diff --git a/test/XPathParserGrammarTest.m b/test/XPathParserGrammarTest.m new file mode 100644 index 0000000..58c6108 --- /dev/null +++ b/test/XPathParserGrammarTest.m @@ -0,0 +1,292 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "XPathParserGrammarTest.h" + +@implementation XPathParserGrammarTest + +- (void)setUp { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"xpath1_0" ofType:@"grammar"]; + NSString *g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + p = [[PKParserFactory factory] parserFromGrammar:g assembler:nil]; + t = p.tokenizer; +} + + +- (void)testFoo { + t.string = @"foo"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDNotNil(res); + TDEqualObjects(@"[foo]foo^", [res description]); +} + + +- (void)test { + t.string = @"child::foo"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + // NSLog(@"\n\n res: %@ \n\n", res); + //TDEqualObjects(@"[/, foo]//foo^", [res description]); + + + t.string = @"/foo"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; +// NSLog(@"\n\n res: %@ \n\n", res); + TDEqualObjects(@"[/, foo]//foo^", [res description]); + + t.string = @"/foo/bar"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar]//foo///bar^", [res description]); + + t.string = @"/foo/bar/baz"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, /, baz]//foo///bar///baz^", [res description]); + + t.string = @"/foo/bar[baz]"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, [, baz, ]]//foo///bar/[/baz/]^", [res description]); + + t.string = @"/foo/bar[@baz]"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, [, @, baz, ]]//foo///bar/[/@/baz/]^", [res description]); + + t.string = @"/foo/bar[@baz='foo']"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, [, @, baz, =, 'foo', ]]//foo///bar/[/@/baz/=/'foo'/]^", [res description]); + + t.string = @"/foo/bar[baz]/foo"; + res = [p completeMatchFor:[PKTokenAssembly assemblyWithTokenizer:t]]; + TDEqualObjects(@"[/, foo, /, bar, [, baz, ], /, foo]//foo///bar/[/baz/]///foo^", [res description]); + + // not supported + t.string = @"//foo"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + NSLog(@"\n\n res: %@ \n\n", res); + TDEqualObjects(@"[//, foo]///foo^", [res description]); +} + + +- (void)testAxisName { + t.string = @"child"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"axisName"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[child]child^", [res description]); + + t.string = @"preceding-sibling"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"axisName"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[preceding-sibling]preceding-sibling^", [res description]); +} + + +- (void)testAxisSpecifier { + t.string = @"child::"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"axisSpecifier"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[child, ::]child/::^", [res description]); + t.string = @"preceding-sibling::"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"axisSpecifier"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[preceding-sibling, ::]preceding-sibling/::^", [res description]); +} + + +- (void)testQName { + t.string = @"foo:bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"qName"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [res description]); + + t.string = @"foo:bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + //TDAssertThrowsSpecificNamed([p.QName bestMatchFor:a], [NSException class], @"PKTrackException"); +} + + +- (void)testNameTest { + t.string = @"foo:bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [res description]); + + t.string = @"*"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[*]*^", [res description]); + + t.string = @"foo:*"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, :, *]foo/:/*^", [res description]); + + t.string = @"*:bar"; // NOT ALLOWED + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[*]*^:/bar", [res description]); + + t.string = @"foo"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nameTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo]foo^", [res description]); + + t.string = @"foo:bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + //TDAssertThrowsSpecificNamed([p.nameTest bestMatchFor:a], [NSException class], @"PKTrackException"); +} + + +- (void)testNodeType { + t.string = @"comment"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeType"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[comment]comment^", [res description]); + + t.string = @"node"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeType"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[node]node^", [res description]); + +} + + +- (void)testNodeTest { + t.string = @"comment()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[comment, (, )]comment/(/)^", [res description]); + + t.string = @"processing-instruction()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[processing-instruction, (, )]processing-instruction/(/)^", [res description]); + + t.string = @"processing-instruction('baz')"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[processing-instruction, (, 'baz', )]processing-instruction/(/'baz'/)^", [res description]); + + t.string = @"node()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[node, (, )]node/(/)^", [res description]); + + t.string = @"text()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[text, (, )]text/(/)^", [res description]); + + t.string = @"*"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[*]*^", [res description]); + + t.string = @"foo:*"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, :, *]foo/:/*^", [res description]); + + t.string = @"bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"nodeTest"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[bar]bar^", [res description]); +} + + +- (void)testVariableReference { + t.string = @"$foo"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + p = [p parserNamed:@"pathExpr"]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[$, foo]$/foo^", [res description]); + + t.string = @"$bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + p = [p parserNamed:@"pathExpr"]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[$, bar]$/bar^", [res description]); +} + + +- (void)testFunctionCall { + t.string = @"foo()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, )]foo/(/)^", [res description]); + + t.string = @"foo('bar')"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, 'bar', )]foo/(/'bar'/)^", [res description]); + + t.string = @"foo('bar', 'baz')"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, 'bar', ,, 'baz', )]foo/(/'bar'/,/'baz'/)^", [res description]); + + t.string = @"foo('bar', 1)"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [p bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, 'bar', ,, 1, )]foo/(/'bar'/,/1/)^", [res description]); +} + +- (void)testOrExpr { + t.string = @"foo or bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"orExpr"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, or, bar]foo/or/bar^", [res description]); +} + + +- (void)testAndExpr { + t.string = @"foo() and bar()"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"andExpr"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, (, ), and, bar, (, )]foo/(/)/and/bar/(/)^", [res description]); + + t.string = @"foo and bar"; + a = [PKTokenAssembly assemblyWithTokenizer:t]; + res = [[p parserNamed:@"andExpr"] bestMatchFor:a]; + TDNotNil(res); + TDEqualObjects(@"[foo, and, bar]foo/and/bar^", [res description]); +} + +@end diff --git a/test/XPathParserTest.h b/test/XPathParserTest.h new file mode 100644 index 0000000..513f85c --- /dev/null +++ b/test/XPathParserTest.h @@ -0,0 +1,26 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TDTestScaffold.h" + +#import "XPathParser.h" + +@interface XPathParserTest : SenTestCase { + NSString *s; + XPathParser *p; + PKAssembly *a; + PKAssembly *result; +} + +@end diff --git a/test/XPathParserTest.m b/test/XPathParserTest.m new file mode 100644 index 0000000..f262d5b --- /dev/null +++ b/test/XPathParserTest.m @@ -0,0 +1,309 @@ +// Copyright 2010 Todd Ditchendorf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "XPathParserTest.h" +#import "TDNCName.h" + +@implementation XPathParserTest + +- (void)setUp { + p = [[[XPathParser alloc] init] autorelease]; +} + +- (void)test { + s = @"child::foo"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; +// NSLog(@"\n\n result: %@ \n\n", result); + //TDEqualObjects(@"[/, foo]//foo^", [result description]); + + + s = @"/foo"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + NSLog(@"\n\n result: %@ \n\n", result); + TDEqualObjects(@"[/, foo]//foo^", [result description]); + + s = @"/foo/bar"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar]//foo///bar^", [result description]); + + s = @"/foo/bar/baz"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, /, baz]//foo///bar///baz^", [result description]); + + s = @"/foo/bar[baz]"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, [, baz, ]]//foo///bar/[/baz/]^", [result description]); + + s = @"/foo/bar[@baz]"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, [, @, baz, ]]//foo///bar/[/@/baz/]^", [result description]); + + s = @"/foo/bar[@baz='foo']"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, [, @, baz, =, 'foo', ]]//foo///bar/[/@/baz/=/'foo'/]^", [result description]); + + s = @"/foo/bar[baz]/foo"; + a = [p assemblyWithString:s]; + result = [p bestMatchFor:a]; + TDEqualObjects(@"[/, foo, /, bar, [, baz, ], /, foo]//foo///bar/[/baz/]///foo^", [result description]); + + // not supported +// s = @"//foo"; +// a = [p assemblyWithString:s]; +// result = [p bestMatchFor:a]; +// NSLog(@"\n\n result: %@ \n\n", result); +// TDEqualObjects(@"[//, foo]///foo^", [result description]); +} + + +- (void)testAxisName { + s = @"child"; + a = [p assemblyWithString:s]; + NSLog(@"\n\n a: %@ \n\n", a); + result = [p.axisName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[child]child^", [result description]); + + s = @"preceeding-sibling"; + a = [p assemblyWithString:s]; + result = [p.axisName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[preceeding-sibling]preceeding-sibling^", [result description]); +} + + +- (void)testAxisSpecifier { + s = @"child::"; + a = [p assemblyWithString:s]; + result = [p.axisSpecifier bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[child, ::]child/::^", [result description]); + s = @"preceeding-sibling::"; + a = [p assemblyWithString:s]; + result = [p.axisSpecifier bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[preceeding-sibling, ::]preceeding-sibling/::^", [result description]); +} + + +- (void)testOperatorName { + s = @"and"; + a = [p assemblyWithString:s]; + result = [p.operatorName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[and]and^", [result description]); + + s = @"or"; + a = [p assemblyWithString:s]; + result = [p.operatorName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[or]or^", [result description]); +} + + +- (void)testQName { + s = @"foo:bar"; + a = [p assemblyWithString:s]; + result = [p.QName bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [result description]); + + s = @"foo:bar"; + a = [p assemblyWithString:s]; + //TDAssertThrowsSpecificNamed([p.QName bestMatchFor:a], [NSException class], @"PKTrackException"); +} + + +- (void)testNameTest { + s = @"foo:bar"; + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, :, bar]foo/:/bar^", [result description]); + + s = @"*"; + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[*]*^", [result description]); + + s = @"foo:*"; + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, :, *]foo/:/*^", [result description]); + + s = @"*:bar"; // NOT ALLOWED + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[*]*^:/bar", [result description]); + + s = @"foo"; + a = [p assemblyWithString:s]; + result = [p.nameTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo]foo^", [result description]); + + s = @"foo:bar"; + a = [p assemblyWithString:s]; + //TDAssertThrowsSpecificNamed([p.nameTest bestMatchFor:a], [NSException class], @"PKTrackException"); +} + + +- (void)testNodeType { + s = @"comment"; + a = [p assemblyWithString:s]; + result = [p.nodeType bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[comment]comment^", [result description]); + + s = @"node"; + a = [p assemblyWithString:s]; + result = [p.nodeType bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[node]node^", [result description]); + +} + + +- (void)testNodeTest { + s = @"comment()"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[comment, (, )]comment/(/)^", [result description]); + + s = @"processing-instruction()"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[processing-instruction, (, )]processing-instruction/(/)^", [result description]); + + s = @"processing-instruction('baz')"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[processing-instruction, (, 'baz', )]processing-instruction/(/'baz'/)^", [result description]); + + s = @"node()"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[node, (, )]node/(/)^", [result description]); + + s = @"text()"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[text, (, )]text/(/)^", [result description]); + + s = @"*"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[*]*^", [result description]); + + s = @"foo:*"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, :, *]foo/:/*^", [result description]); + + s = @"bar"; + a = [p assemblyWithString:s]; + result = [p.nodeTest bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[bar]bar^", [result description]); +} + + +- (void)testVariableReference { + s = @"$foo"; + a = [p assemblyWithString:s]; + result = [p.variableReference bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[$, foo]$/foo^", [result description]); + + s = @"$bar"; + a = [p assemblyWithString:s]; + result = [p.variableReference bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[$, bar]$/bar^", [result description]); + + s = @"$foo:bar"; + a = [p assemblyWithString:s]; + result = [p.variableReference bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[$, foo, :, bar]$/foo/:/bar^", [result description]); +} + + +- (void)testFunctionCall { + s = @"foo()"; + a = [p assemblyWithString:s]; + result = [p.functionCall bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, )]foo/(/)^", [result description]); + + s = @"foo('bar')"; + a = [p assemblyWithString:s]; + result = [p.functionCall bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, 'bar', )]foo/(/'bar'/)^", [result description]); + + s = @"foo('bar', 'baz')"; + a = [p assemblyWithString:s]; + result = [p.functionCall bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, 'bar', ,, 'baz', )]foo/(/'bar'/,/'baz'/)^", [result description]); + + s = @"foo('bar', 1)"; + a = [p assemblyWithString:s]; + result = [p.functionCall bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, 'bar', ,, 1, )]foo/(/'bar'/,/1/)^", [result description]); +} + +- (void)testOrExpr { + s = @"foo or bar"; + a = [p assemblyWithString:s]; + result = [p.orExpr bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, or, bar]foo/or/bar^", [result description]); +} + + +- (void)testAndExpr { + s = @"foo() and bar()"; + a = [p assemblyWithString:s]; + result = [p.andExpr bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, (, ), and, bar, (, )]foo/(/)/and/bar/(/)^", [result description]); + + s = @"foo and bar"; + a = [p assemblyWithString:s]; + result = [p.andExpr bestMatchFor:a]; + TDNotNil(result); + TDEqualObjects(@"[foo, and, bar]foo/and/bar^", [result description]); +} + +@end

){Qs<*;hswKLXxR@>lEa7Yc^6AUQ&&=IeGp#m!Kr=UYOY?dw-} zIhn3=<9<*v+Ss4&y5m9(2z3ars6+}5%~Sz6Bg2R3w}3f_vnND`Q%5O3w8z^z06vH| z9MYePDv)wF*rtj;+VaJ!0&rNow;RrAm^k)C;Qvge-2jy`5*4xmFY<|ljNImbqsHD7 z^Bd(jok=Kf{H*}r-}-t1{sL9Ky9CvPBX{}E{0FJZ=L>JIzB^ps=;4i>xxw(Rt3eXw{*NC1 zm1?`f2K`QlfX4`VXoj~E6;By;@2xBD+t${h(r(D1-4B4e`Z11l)~%Kw{I@yw^XS35 zau!SuM@Sao0>#aHJOfACByNB_ngo1^8JJoW9zp7>FTu3e+u#Pr#oOHh2sWRNlb`>; zXAsdcLFcP_%dgtQQ=lD>8nu%l>97o7$Ub8K9X@*_2!cMje5JIG10G#`mXAq41SE}p=DxfkhN~3MH1JLX?=-|jJBUV{m1!>rdO_My>PU% zdHU$#1G75^{x;PEcg!9#{U+3CUWC@sJcb(9ip&E9q+3#W|fkFk6`ux;|3r;TXkby8bOluKI2{Qe;{Mn0= zGuND}=;=S~pS!quLRv|!4;IV^2Pk(pC&zOGe)`liTSq5XcQ0SE?jV0i{NZwOz)zpG zb9~`SB!?t)01EZ>Qlx{vI6v?Bf=u-hqLut)6Lgafzq)QM8_rd#<**u<4NN5#r?!EM z*HUVdITY~v7b(=oMQ0!iNj4+2AT42RWLS`&*UKxtB#Pv!a0;*gWYVyvVU3E(&({k% zODkJq(c)T6kntOr{yGWiX7 z1Fp)?wD{Vb)xuR}UpL-j9+H@#8hn5AfrTR$l%A0fB)&x?hO`se3<@1X33sl?JL!A3c&XYV`Xx zfja(yfdT%$9_E)nIm!CV9K~@5*A^c1E2Lv=UVZ)X*;su&RwbzC*Xvx_UjM4Dy1b;w z|Mx=hj?=F#U9<1nod>q=Uf$kE2kW|vy{SKbD)FW+_+9L+WKVJ7c@-T8gsoYU#y+>59jbDmZ1l!6>{N|FHk19;v+9*T>_5L@v#YBh ztrG20BumO2SDXIH6?4lcPpxfiZw$8HFvHgN`Yfl>NST(z* zmYYdQgjb@%W9ui}$WdIb%9%afKR(5|236WW?wxy_OE{L-)Ud0uqC3IWAV5v(hU<^4 z?HryzciQmz)2r0`PT#L^a{6wC)BInYoaX)_c2csUSmRD3>`k|+Iyq_HcXFEX8}WnF z%z3L9Om*752zNpbYIfF-Z*EMjd2=5^hDu}h4_71sEAn<`6^F~KZ+Hd0s6o?tvhC$h z8)A(b8dT2hYdEtWZ!jpQI0px363*uJ^*nA(b=F;?4YX_1zq@4X=mT#~YJoTIuX}o?zrUZax2L=F zg<}JG6I2Xm{A{RDhT6j0K3GGuKqwON4-ERycu9Wv$QdUMoKq)=M58bLDiWPipSx0& zH+#xrQ_<}oMZz{gb0ah0HZkUC*Oop$VF!6o!@@rJ0}s~^(!CL|X7GeB*M!^6HCR0V zq&R%~ONw83xaVl2PbO~;*Lo2i?zeZ^-g#HUeU}fKvozdq{OlKypgz#w@$8d(GJ315*k-7ZHC0aD zgU3}O9%Q*t6|tW^$btQsY_+XSVdLE zfLv*}%xl^tcmtpSbzIWMwYZf=&d|A!O=F7~m4!^D>|jPSQxhvIjJy0eSMfZpU=rxv zaiReYq*)xY&ubu|y%o|D+9#!9d};gG8sa}1~s0ypLR-2Qz} z!>)#1s(XIF?UN6o~5 zWetJ*SfzOxiD@bsd8I7HxNktT!@0_}HLU8_Rj;d*t64R*_1xH6A%O!@JL0a(yblLN zjX=#3u14CqzxuG0tC@Pf;>}O@p6`jOajsVCc}8a@kUlx@J=@A3KhNO4S#SkY9r3s> zH|ZRM`zG1@m}y7?#Pca{62Fge-kJM=OG(ltD4ctf3c3%oooNSLxE5S${5f42jpY8D zLE$jRsd27-SgVwLj-gu%e`=Hecmt7M15$O72NB)Kony&SPWq#QqYHm(h<`kasv%9N z8B*A&-A5Z$iJ*a1>@8xyWSO%NOUzdFE@n0K`EWOguPteN&7u1_Jh*o5_+j^h<_FP1 z?Zd~x+TzG^9d)ZADIuzl+`DhwkR)=Ez+8;bS`&|CpSLTE0-)hY&q! zH1U{4DG~lJUpTtkncE>dZO0cc{UcI}n7pQe(h#*aaLV&iV!{Ib+{m@NiVsK@Tq+XqUvZe_bXt*n zp?M)H)GngY%bA>4e1S;X9}W47UWK%z5}}}}p$^v7)$Ud1Rj5j<8rIfz4NU@}M0!tg zw;(hsf7gKmE|rMdTATQ<8yei}&Fc{?Lp5IWn_AmM5-Hv{h4$B-3A2?{Dh6!P<|;53 zNCl`(RVWfmrTAUNwRe5hF^Cb2OI;=A5~&1-{0X=Fe53=!nIdy!s<>F!7r5VIok*m= zVqIRs{)%;((fcXZr5FEyT}s|F-yoyB_w`?@y@&Nvs%u~Bzu3F}qtJfRkJA3{^w@X( zr`^icbyd<&Gj*Ng`ziK+r#0nkkN=Rbcm3yG|ADY>eXq;j&==qJpZ}Tu^DxRZ${a3k zAMJeyGsVo|Vk+zn|BJs0FdL+;jI z``#mlK$)nAU;!~lQHbK72+?jS{;hEJDy?ET(s1}di%Ul!L&{)+_A4p1`X=PDyingv z{Ff#*m6}VVq!iyoX&d})g{yZ}BMnE&IFksds=2s;nmk@e{NW3zI&`Uk8f_>QsNCEs zNFEQF2$IKR0#h&*MF}XLQi0l1#vkVh+TeRDT)oJnkxFt&Bz&rB2F|B8u!MYS z{CGZ}s#7H8Q^SW#`6_j_{P^*ZBcOqW@lE;W{3t%f9nw-(P&iq97`NP8;ZjIi&N+{& znvC^bu2_#4l&T~#xr9IF2?Dd)XEzu|;w znlbjT<%FqRs^TP6Ru0M{gYd)CvcUNjS_K>yk7LR)=R|QRj$+R6d`dZov-ub&Z7i#6 zEPf`Z4SsKhs|Rz^5zr)Le}QyAs*yN0CSWXNcaFn6-opY$e|#45(`kSI}NSQ7%HeEMSZj8%8D`BVy*mO)k&_O|8<(n@gmZ^P8gYpr^Z`@3kw(=Y?c|aH zQ%T%{rk1Lx|U9{o9&+Znwc)Ct#I|jSi=O>ag!&1N9^T89QcrF#IAnT`zPda z;@ymmPU=8>d1|Ng|; zThyd;;MCbORvb1QHp=vK$GzGsYHLMhqdF@pZTtFXs7S(>S42fA_)6-=7KrgWu*RxK zlmqxl?Hlxrl+a!KR?m8B?kPpnW{C`&r&NzC$=Lb%SGuwaXQ4T$0szSsI5Q;q1m>^q0Qe; z+rvT4+a`Rv05mh;UR94&_8dBS^03rPZR)HKK6>)PONyrG9c}U(Ds9Bjt$ip<^}ZOL zKMXOqW^bWPtpg{I{qoI? z`_^t3A4ocQEb*J-b_aNzC`GEpUr!bi8Jl#tNbjUESI(jYsY;g|PMX-kq`F#Z(qIN6 zGC@uhde7~}B#1uaaza7|n&bP{OcGs_y5ptLi)s%EyL9z}QSM~4>oU4UoVS3C9^Z7)y{94Uc)ac$+sU_r%jcwPY26W5g%OqrO#}N%07=CIZLW61iW%Bk0 zCXcOycsb9RUyIe&z}u;L(!vVo*C*+@H_GM z=_`J1&zuB(;^$RDV%+$CPEbCj1Z|wO{M!#C4IMqS6bYtWLS%YJbZeyXCE)nak<+hr za?Iak`0-b$VTiFizV(-1JsckVaojSB1AR}A*$O(4otJ`?bb=NsQi6!~ z5OlU)0%_x3Bh(;MsGls^qjIY_6U3tMA%|`gguEyIdD}7d6;f|Vef-_|X9;znbv?W1B^?BWERw*RXC4*9(cfJs2@G_q1LMjkx8C-N z9S7g`iEqx5PyDs{6nGqY?llN*d(GQDe+9SUq<5r@5UPMyGiMJu3J5fRk1LJ#|^OJ3kY!G1!X?ZHZ z1-4!rfi{#)_Dq4~2gG|aOYOfy6lCVg59AT(+XZz*NR{_W38oTVCN{<@qEk@F1xciW zBx2L6^4c49H=2s%#oz~d)<_wgxO!{__havQC~5{mJgp{TepNQvKP*uu=)Z|dR1diQ za=rtVkYcWs2e3E)2Dzy~-z9}W3!IRz3e(|Jl%^s<`!AAx7qUe{vdH!lzU7GQyt~m* zBrn$~Cy7V~Wf`qN*C$>^5N|B2Pu~a-AZ}APqj^7RsO$ zA>=T0;e>QjWK}5hVr-><$LRDgVI!ICt{&;Q-ElH|+>VU^-?TQsbbvR(VjPEn^ng4? zkfUDQ05GXu@Cty6GI56t&ksc;+!w&;-$zNECf9nTaTV32{6gR)pSOfaowit5L)}GX zk-vDfQy4f#>afVZLQ2+V=U$Q&-fR@;G_?*GTY+)5t5y2Vb#$6F{|Zv-v^@SDoYZL~ zRDhE(5+ap?^#&l)9q1Wv2a!6gH3|?Cjtp8UwFr5Bjjn!&lBOf%v_eFTg%lhRJAsqP zYE2x8YX1gK>cT@$n1mz4?kuEDA>{64;IG1^E*$hiOE?;$V)A|vuh(B?E^vLNjoq%{Ne06J(vJU)GdG-DkA9o_Cor(KZ$4(ash7E?EF zh16*6f~b;$jF%!K!rp;;f|&Dvr0ramdDa#{jA}O&b5GtL{}qY>A#k;Hge-T`(JV59Nf#kV_@N~+nA)5?@lyhRsCLI6vM%+n;g7C!UoQYMA#KgP zc{};-V_yDXA3_AniMP<^Z{-rgfh2>h2y~&^176(kc-{Ybc+qth z?v5^Cc&rn^%Cbq&Br~$eVFX1&;a&oc{sA1(F?;_V96=oTZQnTk>qvs2A?v1Zha@^@ z`GFyc&Ut-c<-2b5{S_P`_hJ9L2A3|=T(2DrF;Z%wHP#^|UWxD(fh8KisZp8#a9>V7 z>=E4#gTC_5Aq%hovo}mxZ)8}HR8wXyTr+H2Ju!{LluqQtg?ex9&SXNpSrdtR{~c%n zJbbtpj6N*zDy$pqh!DMBbtmp3cR<2c%v#F_d}1|e5o6sL zu;`HcD(kY4=Ug29p46ot7}eMxRz!6SOaC1TQF0gw2y#ffsbx;3e6wWNH)3Sm1%kAv z`IT8~V66RdXEPGF>eL}{z+L#U7i<^7W=d59`r-x3QoAeubXsBI5UFg3=J;i_ZFsJD zqNqzPSreNV_(sYF{x8vrl07MKyS>G}ecxr*HZX}7xWT@S6d96eg|OK_S}Qlnz=YYR zp9Z^NpUqE%4yj5?jNxb|$8+%wlr;gN-FHwcMJU_siCiX{{l{IfzICZ4%V^!52)V%j z9j;MIrX)*{P8X{Sv4iuT@H*Jsko`&$A;@tJA+Hs=k_XES$lI!u2l7fDkF=Jck)*s# zgifvr`3B^j2=d+~@xrf6 zyU0xLL>Zb)j1Y~OBYYUImgEqb+$P2HC!@36g?UwLhHAp z&bmmz+_d0)=P35igR3r+Z%^9|WN&YxOTl1X%O34#D?K(KI9ja z;xMZs1OTi_iW-{9eJ?QN)C&l6;@<~gT^gs;j+0KLXRc{C#SD1As|zieH7A)k8`42% zz$TpzI&X)=IvyJ+ta|qV;b1!8t@(Fq9mpA@|1Y#eGo_isC7{81+kVbdJuEjZH-}45 z{)TeoQ9@Iefc1uQb*6RZa0y_?z2ADtW3Q%s0sjr<$kVr`0)gNS8)_7(acR!VnDjQ5+k>DBk&dSz{ZlC2?^JH~+wo#SFy<7)h^?9#zBh^s~RX zFnEp4(8rtVSq1I~F4717Ji>-DLce(&SjtXVF-qs-3sqQtp!E-7j6U58dkGH|N-v-B zi7H_Dt-X446y*dxGs^GcO?uxH6uB-LVvO8_R$+~)CTF_bZyxL}w zMAXcsJv<#i>+eUGj0UfvaxB)%Glm%NdX8NsDV}$a z?b)&C*d33Q5_nD}_H?%gaqxN}<5+fg@PdJ|qBtWyA}l;Uqqw3CQ;#`a0?!#5LU}R- zrTn?}siO^3V^ma>S5&|lr$LnMuW${f83jcM3Hl^hi)lrif-(fR?S*iNx=C`|UMm;V zB??8$c^feTN{k{(;o!;BUZ@V!Bnv@7Y%mc+Q&AxvrWH<5BChsQIE48m#H0*qC-n-` zB}XiN09RR@YS5 z9Ij?vv7SU9AA}D^Ll7xOXL;OEIvgJ+9V#}k8Dcub9ImDzVgu<=xJQN!C1_Jd%lO0% z@!?V^D>AT?mu(p$g0j+KIFyyOZ}+kiC~Ge-+X`hR-O8fTgwAo$IYC!4wAJ8+ysUUg zYnQTw+B?fip{#hQwSlRDIb3`LG0-G<1v+FoTuzfHCmL!iFV}1!>QWBm0hx%pr69iq z%Gt}ywL&=w(36t%pbROy6nK>EUyy9x8fX zVp?Jjm!L#U$4l`tyc_{CLKvzh&6rdRtH=dpuS#sj*Vw(1b%>DZJ zvxj>Yti6}J%u$-}l4qJ{4wp1flrJs73#CPfhKi*nh^}5*R#skK!C*`(DW=h!7Z(0B zE5s--FX`#}rPv!gr6L+_LU~y!-EC2E-h`dwiyn@@b8J~&o_1)?l@;09Gpr&hX0|ro&ofOk&EXQj z^O9_ogK|+G%0~sth44IHtXx8;myWB%7z~faWu-34<4ZREPCK@+uuwZ9|LTg|+?kJZ zrX7@IzsNGpGKWhHH1Hg0t`@;VL1AH05v>>p$y7_r2)QP(AXci^VvJF-V|>1Sa|e;)RchEcB^X$@0yJ?!=> zOj+%xHO7)KCEvp@1!2m2h8gWD3NsC3hG~Q_Febr8trlpMV6jiI(p1V(JXpzFliC`r^bKYEt6=4g7ao2n35I~j7Hz>Q0ea7~6N-XO zgPFk^LFE-PhO`KFAfj(YS*gD;09j~zK(zI!s9=cIY+)e^(0yRx=@$?Z9UT(j=V|c( zZfqGef7!=dP8~K`xorNREg1m;0V)YeN!w@PNt7T~0Cmwuae(S2ikPDe28D!%g#-oqIo^RAvyE4+S-XDI#&v7gd}=&9 z!_U``x^1S^&uHIt-8pys{Ep2(KJuX7%4r6p@<5G7GZ=&gI#Eg(1~ zEId3cG&sQRt_W_p2Zn@(M?{2&h6K73H^whA`D)XatzU21^p(jXqYQ6fZ|c`Gq~1ms z9g|jn=itsnthe{lUEbaw{17-}8SXvg{h|9^H|Tl*l~s;^s9p5-@%9mW8(LHDdmqrA_4p4p zXP?KEmqFgY>EDUorD;>{ZR*YR*6=DKg<)1}U7C9sJ348FN6}Fop@;5$_n?sQ$f&5u z@X#Rl`yvlrGmqe~h^UyDsEDv&4>Pzi>7%XRZ2xiZo*%Y(_3&D=#N&yo zv&SPPM~_p=HXa^xcZT`;Qm%R&7!&Iky5LKJhv5^-U5^8Ug9E%N*F7vK&%Hd1*9Lio zX#802Vd_!op8Uu${_7B#cbbxFZj%Y<&a7A_&-QL*vyv5+;v#X{t!Yvu}Z<>M0* z<6|O2UCrRe^2Oi(xc9*EWBd31uzm6J3^!jl>XzwJH{BDHCrldQ=JwlocQ-ea*|?j| z$LrkI>rI_H{e3sLrCVCuCQmzIO}T4iafRyUc1QW?*ULTKw(5NG`Dc_JZf@_x^>XlD zco=u1Zkj1@8}f*92fn>@bEe#MGo#qLx#=B%pJr_+cQbWkx@oxQ0sp0C3{2}@CF9tP zo!iyZzg!}8K{ncq6Z;9e2^Zr*t>|%m^2kU&rGvgU{(WySU6<=dx!|WL#XVi_4PDEiRL% z9rKv-{#dWeR2LWTQQsL{b9pgz>!CxxFCOFK^8R)gmnW37+#WoX^U%D-Rz;<;n`K~15PuID4~=!E3d z)Z~O1??;{@C*7A;KCy`@si`T6u|8HW;fBY&)%%Z~yL9R7(cf0R?~&o;>qOl&9e2{a zq-^zYg|3s+FGjf2U}u$O2N#Z9?_{U3#m33P$!YWK7AK9VN1XOk_BxqTaVPb?YQsI8 zj_Ld3enYG%=bh%f|HN^do{Q5jI+vX;Yg`gI89t!g08&m)_LOT*w<%AYoc0;sa@?o< zq}<8WiRq-_oRyPbKr1OL*D_<2Juyhh&&>+c6gucSyV?ZCll%wTx;l&ChJ$SoAy7&} zkgWr8!~OmTn~$9R^WvGq8|UA5&v5W{pl+OoJ7~Inq&n!Z-a?0;jBp2o=lAE$Ik#l9 z!;1%o>O)33I9QDyazfysG4-&6(>W)Hi&We}-Ck+8gTsPv9C3#sZj(Q9n6qfaV7>d# z9ey&LJ6!pD4}pW>eaclJ=HOsMx$JP0V&&lA^`)}D-eu=<2U7>8gN9Q^R&IVFyu(`e zDoRWC>wI7wopxSmr)%%wYVQ*f8yDeY@9JSMB5pX?dPl^@M)=q|kT)CyEIu~bbzuLG z>sMF=IA+-S+ED`{rFI&jfze)}K6c*GQoA8;VPVc1hwSX!Vtj(5?d)E}c(@4cG$K9h z96cTFToZ9S>RlE16B;0~8x$36H~af2&saA*yPu50d?Ni@?S?;3bOu6pcJ_%bcFu{8 z@K0crN8HOYJ5xKRorYstW_B*of3z4dgcfGUWTvOux7ldhx(7HpLZ5pP;BHHP^?zpT zApZsd?A9d#I4eP%?9p!JIZsTsFVsB$(Yb&x*UGVh}Q-;5g+EDFnB{md?R+|rsp*+Hg!Z(`ON)!3@iS7B?F7#> ztsP*ngJI6Wy0ym_n-`&}IXS7JFKp7D**#Nxa`?-S_xM_KpS3)r{_vpr8TIHT@iXeR z13}MBpD~|l*d?bD%~MpYRYs>3=H+CjB`4anJVDQp4SL4!_*AvFwX?IePI+ScM8(zH z&*NF`la?pcmk!NOsIJe&PpA&=K~GGdFrR4HBqpb2=HwO9w8~0~3Uag3QOGrvh&jQtIl@=G~L$xW1aZm58tXzp!P?k6?HeW1Uth8js ziaRTrD>a_RC8hw;{6ejgA}E>;MPnY_sj05f=2TASf)x zFSDq$lEt}S!>rMG6a$YFO4KSY%*)P5gBL!^O7?UWqa;5tErFOX+=I-6@E~ns0!i@B zDlEn1Pg_Mns*kjc>^v=6L2h<>DkQmyd`LdchNpAC7+J5$Vcyo zM#RJ=rDSAl6|AsJ|MJwrp+AS1$saArOMcE^lvk9y0rZ!`a!jqlAt|>+{-jw*cr*;5 z=~-I&(;uZTA7$gH<$sTOQj^6j$w{zhGAo(VN@c8~ywrzoNmnif04S_fwM)pMRm$qV z7aT_DJ3SL9SfwpL9TTbKc88##&Z;cQPOzz}l2ofyVdbSIKE;->QYtOSC{=j1W>s}n zl}&thv7F3ZB0~!_MFv48b@{pI2xZqx1Q`v2OuRKLQ>1L=DvVy_o%b+LsfZ3##B4Q| zb$oV-oWva>br7^&hSqH*tCZz`M1?E6baE1BUColPRjSHqk)b}mmcGiNk+gD3m4vO% zs{1gWBzY;PA-U zgp_oxT%s!xxpVw)J*`oSy>qvYwP`wkpAak})3(mBhd5Tftgg6up*J!wQe(CH#V1O0D3t5J^r z#j~uHSzhhjl^Y@s z$A`-53WV+!pPUA1v*dO8-L$SzVIOcTWwt`Is$*pZX;HGuFtRcozl!p*vf}K7&<4g! zP7dM_4v^tJgd^0)QD?K9v&%WJTT0th1ob}W*kMGKH~l)ROeJ0nNZ>dsU_DTOJiQRlFoGU=>W{89*ZQImV1TE-M)Eh1jK)UN5nfT@zb z-kF60IwhAHoW-VV(DKvcf)2wfPR^MKQKgqe$0)bJ58IDj1#2iqi8Pe@qL|>WRJ8jW zk~@6MEriIJ1)bc9n|g3Z^f=7H;*}r|n=|Gv+X53dj<)l+9IXIY})T(V0^U7GYbvz1}&r_|f%s5}b3GdZIWWxH& zggxvVpDoN)n!7O@{ptzJ1s7E_3Q`kE zSu=en+>$#{66f*AFbU{e59#L#X!UnMGEeS> zDSM#($RC^utT3u>*=UV=^|$;IDuabrYkl4Y zOn7LZ?+vnDPx=ODh%%KOD9)LZ%n84aU-mpRbMoD(W34hXlx76 zI4A%{9pW7IDf}4q9Jr$E`Vkf$aidUF!=&YqDwuIN5|{f{>OtfLG6X}L?yrXyUPP;p z7^HQo0Q_ey$9#cMvOajjPm!I}llx}M%M-5~aRLwy3Etd;kn`%^8ptcAl;ce3*Vv?C z(}Rj`{Pg{ZZDF&=yRcX%CVdjbVokH1Il+bXq4F%tsx7l8(1a}2Dq7ZUxoU2JYQlTI zk~Xd?E>F+-g$cuzPYwwSmxfQUGY&ML8y>E;@a5qJ;q6~O^9gtM44iksdNo)Sq_Xi? zfGDB(F-oEY^uia3BuLnX#DZ2j=!L3QiX#oVkEI?HVp9-tA9z&1goILf4crXN<$)h? z1bVq^un(cQVKCH8k)7z1yK>6Q6MB)K6qNgY_UajV#WTtv3lxlIjJqEmOg}!zE=Oxs z+J#jmAv5w_mz0!ff0TS_c}a*tNs0Z`lH%gF5|x6i2TxtXU74;LT}FZxe_ny#8r5nn%c zA9^}yrnMD`_>BV8*vM|z%n-R(CK17dj5dMhUzZ|17A+yJm_L z!pFKIsZ@T-Q0D(hK4H-1P@&vcw6|(#)5|ahp_+<^TXtlg+*DRJ)~C#7ZrRZpJ9nxV zmgz*5xfz#*8j7`$=PI^3%{9;IcN!q^f)`}f3zNn~V61HvPeQHHYCC978pqVC^av7w=n6z&iy4#>{!Fkk4=X}mgJw>ukvoIR z{6vxLk&YvWFyzXdN)_maQYry^yS~-dow=vK#;~ygnB6>V$LF|*CLPmB!aU!@qK4v_ za_+B#f`yoBMRBe}d_j02v#_gbHr`A+we_nZD}8R*FjOlt?gd6Ci_(?TX0A?FOZTIs z-y0GoP1n%&Pq&^V`(F?KPapLpX4!W4j)4Xyv3QZ9M=5dPq>Ul85Q9SCZnsc@QNJJ zJnv_C>xK=c%E){e6q_#0Qwm!)a@NY}WAgHTg~f0}o_1KC1HRx)DyT)$q-&nSo8k*aDY({}rwvWwsHct(*t z*9AP@N!{hs%Xm7uyr8K(-q$l+t;c?}924?X*=2d&nT&7r3*==RsTGMf}3#aoa0I zNohGxNy$}&NJ)6;l2cLB*jg%75%5YJbHfyf-%(BJnW&QLR#r7j9ae4`(N8Emo0j&VpG9X@UE1*xo zq$GfOSy%;mVoH%pTijuPmB%o zb-v0ZRw6_lbfk@0o2;BUZu*2Zcd^$@1vN1w)u>AKsBoMO+qJ!cnd)B~(h$#SOGSu{(44^AQuqjy0YL^^WQXv#ZEKyP6!d zd-YI4`?9PHGqU`_U^dWtBQq*GgAEKuNoS~O&H7-W@l=wRzA-iM(gjra)XU%FL`O$o zZ_uC_QznnsS-faI(Hf)F`i8c^Nf&JU&vK%rYcOPxuF=HzrW?(c03W@eq-H0SBsyp( zmV7Hdj+w|i%3OxI_ui2N}=nt*V43IH++k!0?XGLPb@UBXySF!Lc*&^)s{ftH3vqedA>MHpJT} z8a6S}R0672Fo_D0lCVtts#l+)Q!1rkEmC8>#bDn5M5=3IjvmZfHMkP3HXLT;&M>dnCQJZAs&B(VyVbG+^`27oOw5~y@{kB@PtS1M(UKP6KnFOm zSPz*?$zU42Ibe`RRD~RLL10~8g%04TaCTKOF>lic^U>hd&rl}iwJcT!1QGiT-8BRc zRwN7DdF{8zS+Ek8N7o4Mr51)9)6Y!3SKZ%IVeNL?bRuPS`W=16LknWY7Cgx4`~Ynhny z>k#_fndD5T-4_$g2tt7xxL(QvbP}&b^q^GI>2gMN56(KQ+_J@q8JrWOw)l5v?Ap*l zk+MYtFc#32F;0!7R=KK-V64|3|1XWCFHSI%Ac`5l5$J-9hS zgrwyHfh>H42vK-ofoLMbatai%A?2c4wT_ITgp#`R;cu9{YhiS_rTU>O&6t`e)f>Z- zCR7mW0&|7hGH{iwpx%bDxy|56X=lUMKz>}3!!B?DoG(v5=5cxs;G{0N>YXWMd-Je+ zdz7P+Te#&2-y0+k#`I1e)YWwu2wl^UroVE3~IfNEU1JBn_ zyhlSUyTTQB$80P_vTcF7e~80HFfN%IhFR)cgI30SE(y{IB{&Ra_>PBY`CkRRs!S=r&4;+^Io>B)66R~@rVAvc-Sup>Wb_I%uW&i5`(`~fE{`H7vboxkR zj&ddWiqmw(#9Q`gtwQ!_wltm2h~&uwXkq!Z2))Ww#$Cyz-4n2c5tm;O+$CZ6J|(!z zrdWG;#K^hR*FgIZP89=p4l68vMdFe8LVZJ-*LTqu zSdN%BY2Go+c77+%=x!OoGy3TRgx0zN&q9N+tYLeW85JOzWw;NXNq%jgTUb1|CHZF3 zDrr=1iIDh{_7{5wY{=f=V#@hgX%PsKO@}`LEwEtP`AmScU|?^AAXbF&wiaIK-a|7@ z|N3L6yT4eJ2?P~S_TO^4cU?+T!G#h*MIB9()?7_17BFcw4HB9X1J&U)B{pIJw~|r` zO+`{lla&4)uE`mr1u3x&ngm2h6qo_-?dEi0v!=Fv2BGPPrbT-^Hgk`PayPep85-$K zuvtcHXsn|RCfIDOrO}FuX=NfBjUg2Rqs`I|MoVZ48I^K1YHRwLQ@SiI99Qt36If11oDyWp5270 zaEexFC;~D3n;WH6TuQ^MaSd_nD`tT^hf^c1mBAYtHI60btH&3>Ntw*p=Th2WyrN22 zODhMDBVgrq3GM&1_uX+#UGM)1Tb2W5C|hvhsH3hrtF5!N)>b?0w5?s**7|9!8@HlT zT&S%J_dr2f2P#ekK~QEOLUIX&gb)%4gphIX`8{`J00Dy5zP_K&k3X)F6X2rD2!2I8Gs5&<=5!TGG}0yejR!!707Q#<@SDSTE; z;xjOylr#Y1o*q5A4F*^f^_9g0$Bkc(Q>t)^@rry-zD`zIR{<7O>iDJ>@U$FN0ayS! zbC?e;^_T7`eM=Jyig5@6uq)en`EFV^CxT0Gt>8R@qJW)szBvm_-ffI4hoE-}5cS;6 zOeY?(Z-L%yIK9Dfc&ZTC*bhNo<)u%a7TKB4$`uko)Fmf z%Z!AJvCXMzeWOrbjVtW$LRUyjO*q6jwOfI@zDiX|XG3%Y~ow?Oi0Ozn+f z5P|H*^bTSL_nusfSh(gnbn)6V0K;O3@Ui>>ocF?B_Fis$A5&qYM(y|5i(y;7c)QzY znfed#)|Lerw#qwjDz_cw0|zdc)f%O;(5)v=M)o!QRd9p zNWU3E(u%@v#30YEKT(FP3)O$n_AH)CVBL8`K9BLasBfc1A7NP3%T%#3&00i(t;6pR z8S#GPF}+1J_YWeI%TX3dy3e&}ENQ-haLi?N_myDKcf35WWc?c?oZjE}3V{vZ-GjH{ zm0bSR-!bNcHtBYUJ6K_o1NX7l8Eo$es@q))%ID94-U)5hyh(t=?03FA;)8F-k6x}r zc2pygdFC9{h|C`cCPC(O*;2R6=V~MzbBnZl0wztJ*lj+r0WxoxVAF)%U=z2~u@!@- z293^u9AQP>pUVW9(ya(j(c*rA0pt%R0)g}?f-ufnlGELsW%K_v z`1*mmz0VLBd-9G_jJ;wGXuM)hwpn%1br%|z1^T)Tb_;m72V_{&Q~+-fELYmW+Al6g zmdp%>zKzly=Fh#Gc>RjU;k9Cn&AShaA?bObMb2Z;BImJrEjnsSauQDgHk;`c&^2Ic zuP@sCK<(-9+12YiI?a5=98!TzGG)%C?OzY{^PS*7;&z*bKRi9L$CVWxo4+w9JQvyC z{t34$&b4)eCEe^ZPB*Ge zj|`UXJ$x!AE&@1)Svwl+Xqc?}K!u5WjH^6`Wd^|F7fYwbpm%I;sUeglA6PXyZDg1R zjfwgp;+`ECPM|Jp7r*zNVR4;aV{g2}L25;wbuigziBD{91wpS?2YPo3)^8w11hYTY z@xb;S%N9%+_|vY@wgWdr?cYa6b>tJM+Xo*r6obYD{17PbAp}w)+&}MTCzXC}onB&Z zs-S=pO;F z(3oByg4sPuI-#pCSId2m>zCNc4J%k_zuK^MVL6>%4WlCoBXB9szSN>0b*c`we%^l5 z^HeGqu3W`ZYE`zA-2HltxLmAaPyZ9Bnq9bBRjJCpRxT>cIB9Cb>i36z>}}nD(dy4S zj{NiWrOR;SKz0SS^B-g)SyzckUU~>T_aK>qX7?LDJcuL$L5s;q)|+rLqfjKT zjZjHd?3kt|+)hmJ+z`8o>}mUf z5W1vVt0+}C$Rz?!YP89MAL{tyuagE2UisUy<;zxo{l)Z^3vtu|tkACPt)^1LIvZ2b zLxi{o@Bo!}g&ks{O(C;HPk%Hv!mzX#oyrkN2JZ4uS=ydA$~z=Jvt702*lG9wh_{CuT78^za9KxuGEx5S{nK77ap@K zq{VOfj(cejLs-pxmp-w3&?QnT#Y$}>JvXY)ujNwva$#Xs(jmj%ZV|G+`?}i$4YHd3 zrdS7$bwIB^UqF6UIz_C}4G;}(1KdDczJZwfHogAX5dI7K%l&2jB9>s^uaBZ{y3{y;2#tVra&QCKS48mbks$8RA-5)^d7+!9fQL@Hq)Z>ayWsVVCR zkpa7tI#T+}oo#)427gpU(RxpdBIK^Wx{e9q%a6JC^)D#t`wEbHPny^*C~)$9xm+-_ z+nDJM*tzAv^evxoRGv1@YwE-(h76qfE+xo2_ykE7P7!|F$cGFYva4KfFBS81Q;rzM z7;`qzha8WjM^o1PnZJC4M7|w4p-Dt}4cr>>3PLvWgW-h)6J@ z_Xc8bv6dtVuT!$I8m-bA7{QfD$rdWaN(V)ykehxS&;qmFV^$j+W_ddiedaPkDOIx1 zH&lm$M;ECWXi}Xtk{mo;SE{pD*H&OzXABc$GZ5G?L!ZgQDr(gcI;oBwXQl=^%9^Ty z+-plWZVDP_FY|bqjHscvmD&WR8i)EYu(+J$tf*^@jm<^vw1U@+xYf|3n<8X2%~Sy) zC~2&?a}7r#Lw7ept}Qx_M6OLCqB*b(=VD2M45)TN_t2)*HgabLWWsF#O-+^w$p$k) z%!c035@HVBG&TSTCFb5h$^g7OiVN%u1l*{$>phz?#KfYYFLyzighme0BPD%1Gm16$ z?m#KVY=A>rC;iScvH&u_T2kPZiN;+*wJco^-1DAh6Ck*QbJ5sMu(j@=B%2(GLa8#1 z4px)l9n>zfA%dz6I*Q9pbZi|kM}rHu=ykjwOp#inkr%4>z<=q06p9{T?iRB;nnqVy zq9gOT7y_su64nwtjOOfTRCKt}mr^miBLt^(xWh!HP%6&ZZ$?F(Y3x-K4TnCA?he6w zS0EIkQ5Q7TuvM(P46pSmL9?RpA6YsFO~=!jZw8}9>mj`3n~#`S6ckF8X|sa2(vxr8 zz2)&o3ktRZKtGz{`4iBtcm_v-ZYcS!nMa1J+=al3klvw6e;RQ%lxg~ul(g)-C+VjL z-~GhKZ&pjbYlsUS02jg|s>9*fGFt^lj^QKheZU-KoCz$ChDPIxYfYZkR`np;uuDrW zY7ER^b z#N4VKODQ}2xBeCPZF3L6Ge~vaPI_md*JpA4|3RtDd~xwY^Bt~v^w4U18rIO7)3_Pf z(5j1@pXLl>3vd$sy}R#dbH&ZCwHaL606FNx{n@YYBariq*O~bKgFi3m(fP9{ z!-B3OMCY+UcZci?A&?V=8-P8Ngb%kZbBo!qqvrY&OnXfi+#oDmAN5bFdBB$m^WWii zLmA-wmTb>k`Xm(Sqo``9WZ)U50S5hX=f&vR6hV-BGI9T;p1+4Mf&M!_Lnt8d5xP7| zpDIG$Sy27{7c?I-fDDpmXzrF5q-RqY!8RTMAoYCxLnh*%L^T0{>7<@a>V{q3!-o%n zfMHTWKpOPN3(~VGm~b;52Y~0|l4}7S|4&Ye$d%TU$)hmvK46Nz2N^KIe7p!f8)FLN znE;R8!PBx3a|(de(1q3zQP~V0_Jh@}?W0jBi724m$&VNF{4l`6g1Sb%XXmfGU0e&bivcB$lL!8rW|($e+da_kfp!nHd*Hum zhH2Ne-2?wk9thvEaedh8mCKj@@?mrFa~AIzefZ1L5T)BKq*b15vwoMr`~3 zxut%;En?^Hr~?NN|D#gB+qNTeSJeJL4>?93IrvA^o}IsM+xq-bx!;9v|9#iqeSaKs zJa+WZAN%(1`h9!&chBvC7cF(os#PnO{kG)i#f#=Vx2~V8SQWNzJd_~x{F!xTq}r76^HU$jChtkMewdoi zXO)=~MsE`U)1xEsY2LW{_oa*HPOmj1%vw}Zn13;6caBwlVF^oQPSpBy7idC1$E5wU zu3z~({(^Z?HswIrSrl8ir_j2HUsA?`M7bupZ<)a5u+!%*#*xgAj_(YA8ElM;IeRLs ziC$WXb-AdlG`3_c3kv!~WHk#tfLDKU5V@*~Gi zor#H!zwG$(u%VYPT|9f{c=QU3@Ba0VL(#`ipS=)A)qOes;`uYDR$F}cvcu6QPM-&- zl0E>3#$7PygXT0}8GYi+c_1mj>X^L$ZRjSKpz@|IdtG8xE)vQGa)FglR4$hg*>`XmSiTFM)aKt4zkUtYR!ZhaGrZc1!KxtqQUl~0jRu?bzUDOXe@u_@=r z?%tRbX0vg3EFaq3oVVAJEp;^^@s49g>Vx~YZ(jX7_QJ*{(i0`N!ku$=r7PrwoUm1- z?|L^sw8%0CwDy*l$0bv(sY~R(y} zcUiFzQ+qHbFN32{C-(~AeV5obV2mHa8_dGQ_0GV@? zXOniiD{&S-{OM6a5x*Fy&N{5p2|7HS(0_2e;Kqn>-yXwK1cKGxfzt$chxT2}6Reyg z5MUUukej~bp_tS&bAQs~teo83yxiOoJKc8>xlZ4C^_@H`H*IQ<5h0tjxmNdBX+&<& zn*)M2BQ+e9KhulKwgC#t7Vo=Afiv^#5ArP#XBk235KrlH% zEAW5J$`=S8c&l9-sk1e@Lv2#8`kUJ*C-u%*q=C#dPDbyw0u z{BZqkkyKt?Q(Ln*h+9*W%A2>MX5HAD`~EdGj;p?^dE%H^Bd>XB4PN8C>7$w&MYUWi zzPpip9GuECqmp>V00=~f#uDO=`@PGKg%lNzd0+g^yt4bFi` zIbAGXKJHF<*S+GeCzlXnmp?{{#gLVuRKS0*&%(#Se}I{x7mO&+4Ufg-wJKl?RD9oQ zZ1AY;>s}$hxSf0$pwaYL`;A8PtNq{!nyi7nM}}#_Kh*%KU~RSFuW)kkaVmd$@Oq)R zqEaTCe2|cJ6nBmhe&F8k%MWF#baakoYSz*sU?+pA_=8`3o304nVJ>iV3 zm`pDq6Z9RORaptdw?#J(S~xHb@Hb<{9f=)3cJq^J4X}b*X}BagE@XDA(E&&ZQcTGkh*Kpk*r#>I=kAeqlQV1mT=+fiaHA#eBP4@AnM>Cs2 zAePla0;%lS@E_*OKa+oEJO799*lYk&b|UVbgR2*PmHegMSBq93yu%flhfp} zoST{`zaqb4lbD)YEGD6#@M+egq*R+nSx<${Ktao-Uxya}v9PqNqzYaDgyM3UhiX~n!H~62F?3Az`xR4@NSl|fLvDZjKa7waE z!oIh{g%*aa)lai){@3jYNUd^lpFEqPDGzQ9C;WWc8Wf6F8)SJonJ?Gg zuUheo0nz@SE!W_I}mguiDaIn3bqj$I147^nD|V`}iYV#z)=ROXDsi}EtpCZf^#ppW zp0M0LDE~&A$|E$h9$6sY*Pk4nqO?l;S)p&tnDIvFEUgm$l&IHeC9SwVIGEffh|)^! z-{z@9BE}1fO4B{M@;+E zf^y!U9J_VOf^vVJAQ0bza-38Z|7mOGo@W-*042um_^|j$xGLi7&CG@V!^Z_fsl?r| zh7*Yr5i33k68*B`>)c65>Lcg zmy+;$__q!&Gu6%N|JJw>v6KDPlj`v@1YY8( zV6(PFbicT`QwGID0C&^e0X)YXkx(iM6Ge&=MXYG8$UU1?BofX3S(NG{G^HaDi0a|@ zI=IYeH+(!ScTn2VGyvXz`2d;qUF>`>?5`dZmjO+m)4Wdy{lM##jA2d>fFmiU8;&^v zl@wX-hEw5R-Z<8c;$I_~1K>+K-9I*_e@q1hm=ZD8K`rK<&dS5EQ{MdVer~`YAi(P3 z_d2-D=;kwF@)){Zg>2h9gwXq{uaL~-AKP1a)%%TUB|f5GW3f$-*_tdKYUAO?6=Jl3O2iMlM2INe;`rFI-(W2XR)3Ng{8iyywV$R z00@Nj@OvFx=Ct$i?dw5#PQtc*KuEgW^plX;`2Xr7x#?Fr?qdm+S>JZhUP-j|V_d@i z+Z}=)APC~7TZUxAhfqc$$>>m;-#w1X-w%J%N%uuXS*lRZZWh@&H@kpr8-PSO!Rmf3+_e)ll-%f0&f{XM+8HafVd; z>}ys;kn?tkZn)z!Z-mbSC`HIUX84bsJy<#|N=}7BQ0eqDy~hl_C6$NCBjt&5)@iNW z>M5&~kax;qpOH7n&@Ye!{5f3*S4--Zk_qw&CA(Hqt+Y{;D@C5R61n))|jN&FILvW*N|xcd`org)`h_$d!mjNr_`~(T}_Z_^7D1| z@OK?tE#7GusDWy%40iG%({O%ELpB9p$R1(g5N|Bs;>1A)su`t*Az%RE7@6x6TQZ>> z*{bfwY+JPM5@kym0wefZo#g@~$O-#1bV7gMegRXqV^vp-V!pc81~D?!@$_4R{kr=G z`}hS9U9>;)#E%#xs;=Tv@^&EhQAq8Nkag;WcOg>3V)H<(dpA$-z+MACTyy;J$ukG` zgo9XD0gi0QM4EUBB|ZV!*af(Sav`;2Mqo8!zX2Kcp{~y-OgP`Bx}06yx^{hc_mQJ# zPKM7NM1<(8s;@(Z-HlZ}t$%j`RHaieRk2YrF@Zg+7Lwpv+H5k!av|KDUOoKVk5fGZ ze0+ifLvYl0;IV$g{z4_whKx)@x#Kr^))!BEX$B-B4;g(5(wYji@5G^lzo5xBLr>z! zI$~76A1fL22iQGD|M?Ihny)iHupgxLCjx3w;vA5J(7;2%*J|JIJ70uq=LSp~2Ht5y z50fDq=gw|!-SH4R#{n-75AFk+_I6!dbEzv{jiIeyq72*LwP@v!keHmIy>bg?Rn zwNs~%-a-D(BS#D+Kv5T00YV-Rk>bY3Q&EOLf!uF8uT~<4`O5X%P@GXzgRJupcS|wq zIooe1LNveTlb%%id{aF!#3b;2>li|0cWaYF9bMeIbaL?v?A6b2pw6IW!KL13wt<#` zII_)uH%LuVTRBUR>o36)MoAsA#Yg@4Akd(uz1`CXo%x95%nVdt9Na`rFg|46{riv5 zptxsHlkB2w*M8~{)SL9=6_go-K3j*jlB`+;vad$SlS?sIb#oQ08mb_91ob?dhZ?wpz|}0H@}VP z*tv7R-aUPS=lxLtUC>of2Y#UA$$-F5rNk*-C`i#O(*em|6+&{_sh4PKOzS#rIvB=M z0OfEE5Co9_Y5O2siR^`!7W(v`e;fnfy9#bnJ~)fm>498wKCxsXn0j#Q7-|mVBDO$h zkf0V)5-ggL{O4_H^DOxKwl?4L=?`tbW!?(vmS>-9{WdHk=lAEGYbWob-WScxwS2^0 zQ&o(tQWkC`P%cTNa}i!a+dl1n^(|$onQ0ehT)TkYy$^^H+eM&8HZX98M$3W3%p)m@ zsxma1tnxXh;?VU>{f(z$2&=Tq7m{^rknJZ?z=)xdBX&xNj4QzMwV%}mWu zIgW$G0`$p<{zuTIF1{1cmlqJwQ3i%XDtxj84g+Pc z4nva<{xtWc*XUx%NL)$H$_XDMH1;s!&p`?O179tor+!GNzG>Md%A+q}cAs)2dM0CS z)7gEr-QrCV`n>t879%w51`6$&S>UQhAA}PLb^?@5qyp8=`_K%aCU9Gl)RuG!9NFC& z2-8*PTL3%gVn!Cs{R`2?^;I3~IqtL2ws7QkkJvnqh7Y09C&tw4t^Ic)!f3nAM^EXq z@9V8Sh>(pGcPoKh?E<7p-Rxkn7C16Vip)^D1Y_-|FzWWAiy7H8UkhFI_INb*`qteZ zy3s`s0YsF!){_{-I&^+-V2&UkmH~GECeEPfNnd6X`0GuLM#xrLX$5nOivaW9d&6id zP-&7(nq+E!TdBTbKSzBKQw)9(xFGb)Zw$!T@bh@d#EU~vVhBP~#~O0VwGRERTM}*R zi^VFoE@u|5)MFLO&It?wK;(Pqj16>P$_g~>IEu3o9G!$xZFK0n)l>%twoM@0)R%}W zLR1g_9CbxZIisNzPU)24Hy&*YT!(ZX7&_i~9I#xMCG4G-cAD{>Q5IR0yLk^ED0#H4P zps0#NqsfY&6G1UcN${vNTFfAjM?)o2`$&*Zfsh{u4z8qx6p*$XRd^mGWzeAsk|L02 z10~9OJt673(Q4a}p9$2DLQ2%i2f4Zd2rBBe9#O}FMwZg-LsbK`=syb(8m~&|@6r${ zMHt4Qe{UTG2;oeP={fQ^yu*@A(_Y}wzT_lAEsanMAgB=vLc{J6{XFqUGXMp-G=xEV zQ~pgD)TndxnKcJU=k%u7Ql|Lh$d6niL5&g4%H^pazmmS}5Fi}e1`uZl(@T%3({4X3#AH%|oxDkW*g+_>weqMNHV1{!)N1whizLZO4niFUE7&26S`l$KyYF* zDcS@#0w)2fQ-%!rSfL;PvOC9;HtY%9ie|shm_#6ddJV?dFf{T&bEhL+r@bWdux$iA zem6Y!F9v#;OwSFW2aJ^!DtH5}QPt4vG7QFG=~$ArpwvGBG7QuD^MVY+H2*vx!!Yr; z6=clRPyd!92E&AJ`7MU6#AgK=aCo2I?R!p;q2J6g12VM8O3A6NKvvQMbtMTjt5vNw9q^z)D*+m!ypr*xYuBWHM+?MVt^sCmoh z=>n)ZBap25Md1$6V(b^NS|o&Xn-!g-5h6r-HEK1a8tkd(GEJ3uQOLvUA?vXYx#<^Y zejl-l-Y?nG1=d!BO;E?d#UFe9AVZ-$s0E%cFCg9&pWb)S_7Q!q;b>&IOWJTR#ThPtw`yhOuT^>0EHtD{~3GP~#(X$BQD zn=hZer$xag_(adGOt1665d7)KwMbj%T!G-6^YDomU;_#^XG-K~`U#X_w_Q7_Z*FcE zoZj(SvJTC4&(sELOlrvptQ{72lQH?H|B_>gzhn~hG zq&GU?p8BmY6Qik}EsxN^8ye4^D$}Ym0@afj&^Et7Fl7iGfH}J{nCe(E#p_l7>Bco2 zcoU&Fs_yq0_-5~qzzPGH((_dt?9c1%+b53iJ8{ILF=&^U(f;rrgO>Q@8593h8aa^LW8@}e zl>*ouaRR1UgaDn@;7DFe?W4gGkW59cM*b7%%tSxq5>OgRk1f_O;k04@%tRW!4wOs= zqZlN$VKK-csjWE8aAO-lm;M25zXf`gCCg{+PJZT4r~j!w#tGv@!lmLsaBzzOUb~CJ ziX!1s6}4KDigyeXs)VhUtO%=!giBS?YDp?eH%y^Yv|5si7YY&-s62;qO8(09H5^%&w4Jj7R+34SMM zg2o4_G?*j**78}ShrKdu#Vvkqvv-*u2hm}!{HMQ8+QOA7W!$J&e|gHUYxX`kZqn$W z6^_~PlRx^hSc`0R{IA|m;j7wkGl6yC=YRae)9QM7T_v03iZ87u^F7tbggNKFU(Icc1cY_vUwd!g<-)T2aFx;!v`=EA)RNol!7Sh3)H*4(VLq#Fl* z&g5%aaH_fEULF`PdC}QBX^*pWa|<|w?ayarq~5!*cmL1xZ@fuP&JT~2wN%_(?V z^rQ9O0#453lxr()wJ4~S17aZa=GtqIa`GX|+iCWHFn&=%PR7l3H(Hk2^2srfd28+8 zPx6ZdLhexEOOyghF~tjHP^Ge0SFiEyp_E_!UYm z#oQt3Ddapg2qP;u6q8_`$YQrZpgWx#)qJ@MtTR;(${Gu@0tkOQI*Y48pcLzJofJr3 z`jYrnaCu(i5{ps?xpk8c^q{QbB}~e z<*xJ4dE#EEJJEyiHr_+{TY)189|ZRh)IDmC6U;qYcQthn0r$Y~P!G$G@OKOhATwf8 z?jvi0U%j-RhdjbOBH^m_(0USHLZSOE@(d&rt_>K?V{QRW_%hnl(vXKEp>VFg&h zJ%m5)C9)nIv{QMWVD8a+sK6TBq#gq9VFeP!4?tXCz!To;s#HX$j-8 zK(c|69|0|aQ+jE=4m0JIo?5U2?}3B2;CI@?P@dL_l&=Gw)LzG!@@h{t$k&10w0tNR G@c#f+RltD& literal 0 HcmV?d00001 diff --git a/docs/web/img/step4b.png b/docs/web/img/step4b.png new file mode 100644 index 0000000000000000000000000000000000000000..63c4288b835a5b26c331bd3d13d3a0f3a332d694 GIT binary patch literal 25070 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 W87=27!++p_qo#6C`JJM9(Ek8>#Sr5F literal 0 HcmV?d00001 diff --git a/docs/web/img/step4b.psd b/docs/web/img/step4b.psd new file mode 100644 index 0000000000000000000000000000000000000000..dceeabad7093384853b9e8e24ec03d39bfc30b34 GIT binary patch literal 85694 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 Cc!ABaH$0T?V@f6R~VJ$Z|rG2;mx1OeYv`y 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 V7A2xTub_aJoRqR;rMOAJ{{yeW)3N{n literal 0 HcmV?d00001 diff --git a/docs/web/img/step6a.png b/docs/web/img/step6a.png new file mode 100644 index 0000000000000000000000000000000000000000..dbee4ef761aeff258a4c85cd37d29adbd132d1f6 GIT binary patch literal 49927 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�i-<^94rdcK#3(QHu%sxqx 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 literal 0 HcmV?d00001 diff --git a/docs/web/img/step7a.png b/docs/web/img/step7a.png new file mode 100644 index 0000000000000000000000000000000000000000..554615d37b174cfe829fffeee3675505e6bdf277 GIT binary patch literal 41304 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 G@c#f+RltD& literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step4b.png.svn-base b/docs/web/img/.svn/text-base/step4b.png.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..63c4288b835a5b26c331bd3d13d3a0f3a332d694 GIT binary patch literal 25070 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 W87=27!++p_qo#6C`JJM9(Ek8>#Sr5F literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step4b.psd.svn-base b/docs/web/img/.svn/text-base/step4b.psd.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..dceeabad7093384853b9e8e24ec03d39bfc30b34 GIT binary patch literal 85694 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 Cc!ABaH$0T?V@f6R~VJ$Z|rG2;mx1OeYv`y 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 V7A2xTub_aJoRqR;rMOAJ{{yeW)3N{n literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step6a.png.svn-base b/docs/web/img/.svn/text-base/step6a.png.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..dbee4ef761aeff258a4c85cd37d29adbd132d1f6 GIT binary patch literal 49927 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�i-<^94rdcK#3(QHu%sxqx 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 literal 0 HcmV?d00001 diff --git a/docs/web/img/.svn/text-base/step7a.png.svn-base b/docs/web/img/.svn/text-base/step7a.png.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..554615d37b174cfe829fffeee3675505e6bdf277 GIT binary patch literal 41304 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

R3_CuBYzq!>7Cymaej1+V1g}Hxd;Y1 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 .r1241 +OUTPUT_DIRECTORY = /Users/itod/work/tpk/trunk/docs/doxygen + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, +# Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = /Applications/ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = /Users/itod/work/tpk/trunk/src + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.vhd \ + *.vhdl + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. + +GENERATE_TREEVIEW = ALL + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = /Applications/Doxygen.app/Contents/Resources/ + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = /Applications/Doxygen.app/Contents/Resources/ + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 1000 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Options related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/docs/Doxyfile b/docs/Doxyfile new file mode 100644 index 0000000..1f3b885 --- /dev/null +++ b/docs/Doxyfile @@ -0,0 +1,291 @@ +# Doxyfile 1.5.7 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = ParseKit +PROJECT_NUMBER = 1.4 +OUTPUT_DIRECTORY = /Users/itod/work/tpk/trunk/docs/doxygen +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = /Applications/ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = NO +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = /Users/itod/work/tpk/trunk/src +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.vhd \ + *.vhdl +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHG_LOCATION = +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = ALL +TREEVIEW_WIDTH = 250 +FORMULA_FONTSIZE = 10 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = YES +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +MSCGEN_PATH = /Applications/Doxygen.app/Contents/Resources/ +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +DOT_FONTNAME = FreeSans +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = /Applications/Doxygen.app/Contents/Resources/ +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/docs/web/.svn/all-wcprops b/docs/web/.svn/all-wcprops new file mode 100644 index 0000000..4e65fec --- /dev/null +++ b/docs/web/.svn/all-wcprops @@ -0,0 +1,53 @@ +K 25 +svn:wc:ra_dav:version-url +V 33 +/svn/!svn/ver/1396/trunk/docs/web +END +tokenization.html +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1388/trunk/docs/web/tokenization.html +END +common-nav.inc +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/1388/trunk/docs/web/common-nav.inc +END +iphone.html +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/1390/trunk/docs/web/iphone.html +END +common-header.inc +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1388/trunk/docs/web/common-header.inc +END +index.html +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/1396/trunk/docs/web/index.html +END +common-footer.inc +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/1388/trunk/docs/web/common-footer.inc +END +grammars.html +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/!svn/ver/1388/trunk/docs/web/grammars.html +END +htaccess +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/1388/trunk/docs/web/htaccess +END diff --git a/docs/web/.svn/entries b/docs/web/.svn/entries new file mode 100644 index 0000000..4cba904 --- /dev/null +++ b/docs/web/.svn/entries @@ -0,0 +1,346 @@ +10 + +dir +1411 +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/docs/web +https://todd.ditchendorf@todparsekit.googlecode.com/svn + + + +2009-09-18T01:37:04.877278Z +1396 +todd.ditchendorf + + + + + + + + + + + + + + +7c5183cd-b054-0410-b1f0-833f5c61cfe1 + +tokenization.html +file + + + + +2009-09-18T00:46:34.000000Z +231833577a2aac8d91acdb40171aeef0 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +18423 + +common-nav.inc +file + + + + +2009-09-18T00:46:27.000000Z +303dc91898ec9ff6bed3be6d4f7b11f4 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +502 + +iphone.html +file + + + + +2009-09-18T00:47:57.000000Z +cc43bbfb050c326fabdce0b543f626a7 +2009-09-18T00:48:13.680423Z +1390 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +3259 + +common-header.inc +file + + + + +2009-09-18T00:46:26.000000Z +d6e41f5fe6ece66c354975e61e0ce6e0 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +315 + +css +dir + + + + + + + + + + + + + + + + + + +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/docs/css +1385 + +index.html +file + + + + +2009-09-18T00:53:41.000000Z +082d349d133c41c842c52ea8a9cb942c +2009-09-18T01:37:04.877278Z +1396 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +12295 + +common-footer.inc +file + + + + +2009-09-18T00:46:25.000000Z +7a4cfbd7ab01793f625d133a0cb1691d +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +420 + +grammars.html +file + + + + +2009-09-18T00:46:29.000000Z +a0e9bdb1d3fceaafd7db8bf58bd7ebee +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +7512 + +img +dir + + + + + + + + + + + + + + + + + + +https://todd.ditchendorf@todparsekit.googlecode.com/svn/trunk/docs/img +1385 + +htaccess +file + + + + +2009-09-18T00:46:30.000000Z +6fd4f2f185f03a39c0e85f3a9f0cc041 +2009-09-18T00:46:54.438360Z +1388 +todd.ditchendorf + + + + + + + + + + + + + + + + + + + + + +172 + diff --git a/docs/web/.svn/text-base/common-footer.inc.svn-base b/docs/web/.svn/text-base/common-footer.inc.svn-base new file mode 100644 index 0000000..594ae23 --- /dev/null +++ b/docs/web/.svn/text-base/common-footer.inc.svn-base @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/docs/web/.svn/text-base/common-header.inc.svn-base b/docs/web/.svn/text-base/common-header.inc.svn-base new file mode 100644 index 0000000..16d80ec --- /dev/null +++ b/docs/web/.svn/text-base/common-header.inc.svn-base @@ -0,0 +1,6 @@ + + + + + diff --git a/docs/web/.svn/text-base/common-nav.inc.svn-base b/docs/web/.svn/text-base/common-nav.inc.svn-base new file mode 100644 index 0000000..d44c86b --- /dev/null +++ b/docs/web/.svn/text-base/common-nav.inc.svn-base @@ -0,0 +1,16 @@ + + +