diff options
-rw-r--r-- | MLKDynamicContext.m | 20 | ||||
-rw-r--r-- | MLKLowLevelTests.m | 22 | ||||
-rw-r--r-- | MLKParenReader.m | 7 | ||||
-rw-r--r-- | MLKReader.m | 16 | ||||
-rw-r--r-- | MLKReadtable.h | 1 | ||||
-rw-r--r-- | MLKReadtable.m | 6 |
6 files changed, 55 insertions, 17 deletions
diff --git a/MLKDynamicContext.m b/MLKDynamicContext.m index 6d135a4..92b2384 100644 --- a/MLKDynamicContext.m +++ b/MLKDynamicContext.m @@ -28,6 +28,7 @@ #import "MLKEnvironment.h" #import "MLKLinkedList.h" #import "MLKPackage.h" +#import "MLKParenReader.h" #import "MLKReadtable.h" #import "MLKSymbol.h" #import "MLKInteger.h" @@ -110,14 +111,14 @@ static MLKDynamicContext *global_context; [readtable setSyntaxType:CONSTITUENT forCharacter:'-']; [readtable setConstituentTrait:MINUS_SIGN forCharacter:'-']; [readtable setConstituentTrait:SIGN forCharacter:'-']; - + [readtable setSyntaxType:CONSTITUENT forCharacter:'.']; [readtable setConstituentTrait:DOT forCharacter:'.']; [readtable setConstituentTrait:DECIMAL_POINT forCharacter:'.']; - + [readtable setSyntaxType:CONSTITUENT forCharacter:'/']; [readtable setConstituentTrait:RATIO_MARKER forCharacter:'/']; - + // Maybe distinguish different types of exponent markers as the CLHS // does? For now, the MLKFloat class cluster's string-parsing // constructor does the discrimination. @@ -131,7 +132,7 @@ static MLKDynamicContext *global_context; [readtable setConstituentTrait:EXPONENT_MARKER forCharacter:'F']; [readtable setConstituentTrait:EXPONENT_MARKER forCharacter:'L']; [readtable setConstituentTrait:EXPONENT_MARKER forCharacter:'S']; - + [readtable setConstituentTrait:NUMBER_MARKER forCharacter:'d']; [readtable setConstituentTrait:NUMBER_MARKER forCharacter:'e']; [readtable setConstituentTrait:NUMBER_MARKER forCharacter:'f']; @@ -144,17 +145,20 @@ static MLKDynamicContext *global_context; [readtable setConstituentTrait:NUMBER_MARKER forCharacter:'S']; [readtable setSyntaxType:MULTI_ESCAPE forCharacter:'|']; - + // [readtable setSyntaxType:TERMINATING_MACRO forCharacter:';']; // [readtable setSyntaxType:TERMINATING_MACRO forCharacter:'"']; // [readtable setSyntaxType:NONTERMINATING_MACRO forCharacter:'#']; // [readtable setSyntaxType:TERMINATING_MACRO forCharacter:'\'']; - // [readtable setSyntaxType:TERMINATING_MACRO forCharacter:'(']; // [readtable setSyntaxType:TERMINATING_MACRO forCharacter:'`']; - // [readtable setSyntaxType:TERMINATING_MACRO forCharacter:')']; // [readtable setSyntaxType:TERMINATING_MACRO forCharacter:',']; [readtable setSyntaxType:SINGLE_ESCAPE forCharacter:'\\']; + + [readtable setSyntaxType:TERMINATING_MACRO forCharacter:'(']; + [readtable setMacroFunction:[[MLKParenReader alloc] init] + forCharacter:'(']; + [readtable setSyntaxType:TERMINATING_MACRO forCharacter:')']; for (ch = '0'; ch <= '9'; ch++) { @@ -162,7 +166,7 @@ static MLKDynamicContext *global_context; [readtable setConstituentTrait:ALPHA_DIGIT forCharacter:ch]; [readtable unsetConstituentTrait:ALPHABETIC forCharacter:ch]; } - + for (ch = 'A'; ch <= 'Z'; ch++) { [readtable setSyntaxType:CONSTITUENT forCharacter:ch]; diff --git a/MLKLowLevelTests.m b/MLKLowLevelTests.m index 4eef0c9..ae04bf3 100644 --- a/MLKLowLevelTests.m +++ b/MLKLowLevelTests.m @@ -170,6 +170,28 @@ UKStringsEqual ([[MLKReader readFromString:@"|Class Name|"] name], @"Class Name"); UKStringsEqual ([[MLKReader readFromString:@"class\\ name"] name], @"CLASS NAME"); UKStringsEqual ([[MLKReader readFromString:@"\\100"] name], @"100"); + + UKStringsEqual ([[MLKReader readFromString:@"a b c d e"] name], @"A"); + + return nil; +} + + +-(id) testParenReading +{ + UKObjectKindOf ([MLKReader readFromString:@"(1 2)"], MLKCons); + UKObjectKindOf ([MLKReader readFromString:@"(1 . 2)"], MLKCons); + UKObjectKindOf ([MLKReader readFromString:@"(a b)"], MLKCons); + + UKNil ([MLKReader readFromString:@"()"]); + + UKObjectKindOf ([[MLKReader readFromString:@"(1 . 2)"] car], MLKInteger); + UKObjectKindOf ([[MLKReader readFromString:@"(1 . 2)"] cdr], MLKInteger); + + UKObjectKindOf ([[MLKReader readFromString:@"(a b)"] car], MLKSymbol); + UKObjectKindOf ([[MLKReader readFromString:@"(a b)"] cdr], MLKCons); + + UKObjectKindOf ([[MLKReader readFromString:@"((a) b)"] car], MLKCons); return nil; } diff --git a/MLKParenReader.m b/MLKParenReader.m index f50cf68..2470aba 100644 --- a/MLKParenReader.m +++ b/MLKParenReader.m @@ -55,8 +55,7 @@ static unichar slurpWhitespaceAndPeek (MLKStream *stream, MLKReadtable *readtabl cons = nil; tail = nil; - nextChar = slurpWhitespaceAndPeek(stream, readtable); - while (nextChar != ')') + while ((nextChar = slurpWhitespaceAndPeek(stream, readtable)) != ')') { id item; @@ -78,7 +77,7 @@ static unichar slurpWhitespaceAndPeek (MLKStream *stream, MLKReadtable *readtabl tail = [tail cdr]; } } - - return [NSArray arrayWithObject:cons]; + + return [NSArray arrayWithObject:(cons ? (id)cons : (id)[NSNull null])]; } @end diff --git a/MLKReader.m b/MLKReader.m index da5e743..fd6daa3 100644 --- a/MLKReader.m +++ b/MLKReader.m @@ -55,7 +55,7 @@ readtable = [[MLKDynamicContext currentContext] valueForBinding:[[MLKPackage findPackage:@"COMMON-LISP"] intern:@"*READTABLE*"]]; - + start: if ([stream isEOF]) { @@ -86,7 +86,9 @@ } returnValues = [macrofun applyToArray:args]; if ([returnValues count]) - return [returnValues objectAtIndex:0]; + return ([returnValues objectAtIndex:0] == [NSNull null] + ? nil + : [returnValues objectAtIndex:0]); else goto start; } @@ -123,7 +125,8 @@ ch = [stream readChar]; if ([readtable isConstituentCharacter:ch] || [readtable isNonTerminatingMacroCharacter:ch] || - (escaped && [readtable isWhitespaceCharacter:ch])) + (escaped && (![readtable isMultipleEscapeCharacter:ch] + && ![readtable isSingleEscapeCharacter:ch]))) { if (escaped) [token appendFormat:@"%C", ch]; @@ -148,9 +151,12 @@ [stream unreadChar:ch]; break; } - else if ([readtable isInvalid:ch]) + else if ([readtable isConstituentCharacter:ch] + && [readtable isInvalid:ch]) { - [[[MLKReaderError alloc] initWithStream:stream] raise]; + //[[[MLKReaderError alloc] initWithStream:stream] raise]; + [NSException raise:@"MLKReaderError" + format:@"'%c' is an invalid constituent character.", ch]; } else if ([readtable isWhitespaceCharacter:ch]) { diff --git a/MLKReadtable.h b/MLKReadtable.h index 00da691..8084890 100644 --- a/MLKReadtable.h +++ b/MLKReadtable.h @@ -101,6 +101,7 @@ enum MLKConstituentTrait -(int) digitWeight:(unichar)ch; -(MLKFuncallable *) macroFunctionForCharacter:(unichar)ch; +-(void) setMacroFunction:(MLKFuncallable *)function forCharacter:(unichar)ch; -(unichar) charWithReadtableCase:(unichar)ch; -(int) characterConstituentTraits:(unichar)ch; diff --git a/MLKReadtable.m b/MLKReadtable.m index dd2a428..349688e 100644 --- a/MLKReadtable.m +++ b/MLKReadtable.m @@ -96,6 +96,12 @@ DEFINE_SYNTAX_PREDICATE(isConstituentCharacter:, CONSTITUENT) return [_readerMacros objectForKey:[NSNumber numberWithLong:ch]]; } +-(void) setMacroFunction:(MLKFuncallable *)function forCharacter:(unichar)ch +{ + [_readerMacros setObject:function + forKey:[NSNumber numberWithLong:ch]]; +} + -(unichar) charWithReadtableCase:(unichar)ch { switch (_case) |