summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MLKDynamicContext.m20
-rw-r--r--MLKLowLevelTests.m22
-rw-r--r--MLKParenReader.m7
-rw-r--r--MLKReader.m16
-rw-r--r--MLKReadtable.h1
-rw-r--r--MLKReadtable.m6
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)