aboutsummaryrefslogtreecommitdiffstats
path: root/NSFileHandle+LispExtensions.m
blob: 87e4059ce63dcae4f159f3b6f863e8c563ddd8af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//
//  NSFileHandle+LispExtensions.m
//  Moxie
//
//  Created by Brian Cully on Fri Sep 10 2004.
//  Copyright (c) 2004 Brian Cully. All rights reserved.
//

#import "NSFileHandle+LispExtensions.h"

@implementation NSFileHandle (LispExtensions)
- (void)alertDidEndSelector: (NSAlert *)alert
                 returnCode: (int)returnCode
                contextInfo: (void *)contextInfo
{
    [NSApp terminate: self];
}

- (unichar)readNextCharFromBufferAndMove: (BOOL)moveFilePointer
{
    // XXX: SO not thread safe.
    static NSString *buffer = nil;
    static unsigned int bindex = 0;
    unichar c;

    if (buffer == nil || bindex >= [buffer length]) {
        NSData *formData;

        formData = [self availableData];
        if ([formData length] == 0) {
            [[NSException exceptionWithName: @"REPLDeath" reason: @"The plug in subsystem died." userInfo: nil] raise];
        } else {
            if (buffer)
                [buffer release];
            buffer = [[NSString alloc] initWithCString: [formData bytes]
                                                length: [formData length]];
            bindex = 0;
        }
    }
    c = [buffer characterAtIndex: bindex];
    if (moveFilePointer)
        bindex++;
    return c;
}

- (NSString *)readLispString
{
    NSMutableString *result;
    unichar c;
    
    result = [NSMutableString string];
    c = [self readNextCharFromBufferAndMove: YES];
    while ((c = [self readNextCharFromBufferAndMove: YES]) != '"') {
        if (c == '\\')
            c = [self readNextCharFromBufferAndMove: YES];
        [result appendFormat: @"%c", c];
    }
    return result;
}

- (LispSymbol *)readLispSymbol
{
    NSMutableString *formString;
    unichar c;

    formString = [NSMutableString string];
    c = [self readNextCharFromBufferAndMove: NO];
    while (c != '(' && c != ')' &&
           [[NSCharacterSet whitespaceAndNewlineCharacterSet] characterIsMember: c] == NO) {
        // Handle string lengths.
        if (c == '"') {
            [formString appendFormat: @"\"%@\"", [self readLispString]];
        } else {
            c = [self readNextCharFromBufferAndMove: YES];
            [formString appendFormat: @"%c", c];
        }
        
        // Get the next char without swallowing, so we can see if
        // we use it before we swallow.
        c = [self readNextCharFromBufferAndMove: NO];
    }
    return [LispSymbol symbolNamed: formString];
}

- (id)readLispAtom
{
    id result;
    unichar c;

    c = [self readNextCharFromBufferAndMove: NO];
    if (c == '"') {
        // Parse as a string.
        result = [self readLispString];
    } else {
        result = [self readLispSymbol];
    }
    return result;
}

- (id)readLispForm
{
    id result;
    unichar c;

    result = nil;
    
    // Advance past white space and unmatched parens.
    c = [self readNextCharFromBufferAndMove: NO];
    while ([[NSCharacterSet whitespaceAndNewlineCharacterSet] characterIsMember: c] ||
           c == ')') {
        [self readNextCharFromBufferAndMove: YES];
        c = [self readNextCharFromBufferAndMove: NO];
    }
    
    // Begin form parsing.
    if (c == '(') {
        NSMutableArray *form;
        
        // Recursively parse form until closing paren.
        [self readNextCharFromBufferAndMove: YES];
        form = [NSMutableArray array];
        while ([self readNextCharFromBufferAndMove: NO] != ')') {
            id obj;
            
            obj = [self readLispForm];
            if ([obj isEqual: @"."] == NO) {
                if ([obj isEqual: @"NIL"])
                    [form addObject: [NSArray array]];
                else
                    [form addObject: obj];
            }
        }
        [self readNextCharFromBufferAndMove: YES];
        result = form;
    } else
        result = [self readLispAtom];
    return result;
}
@end