2005-05-01 11:48:36 +00:00
|
|
|
#include "Cons.h"
|
|
|
|
#include "Parser.h"
|
|
|
|
#include "Nil.h"
|
2005-05-02 04:58:22 +00:00
|
|
|
#include "Error.h"
|
2005-05-01 11:48:36 +00:00
|
|
|
#include "defs.h"
|
|
|
|
|
|
|
|
@implementation Parser
|
|
|
|
|
2005-05-02 04:58:22 +00:00
|
|
|
+ (id) newFromSource: (string) s file: (string) f
|
2005-05-01 11:48:36 +00:00
|
|
|
{
|
2005-05-02 04:58:22 +00:00
|
|
|
return [[self alloc] initWithSource: s file: f];
|
2005-05-01 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2005-05-02 04:58:22 +00:00
|
|
|
- (id) initWithSource: (string) s file: (string) f
|
2005-05-01 11:48:36 +00:00
|
|
|
{
|
2005-05-02 02:33:44 +00:00
|
|
|
self = [super init];
|
2005-05-02 04:58:22 +00:00
|
|
|
lexer = [Lexer newFromSource: s file: f];
|
|
|
|
file = f;
|
2005-05-02 02:33:44 +00:00
|
|
|
return self;
|
2005-05-01 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2011-01-09 10:41:24 +00:00
|
|
|
- (SchemeObject[]) readList
|
2005-05-01 11:48:36 +00:00
|
|
|
{
|
2011-01-09 10:41:24 +00:00
|
|
|
local SchemeObject []token, res;
|
2005-05-02 04:58:22 +00:00
|
|
|
local integer line;
|
2011-01-09 10:41:24 +00:00
|
|
|
local Error []err;
|
2005-05-01 11:48:36 +00:00
|
|
|
|
2005-05-02 04:58:22 +00:00
|
|
|
line = [lexer lineNumber];
|
|
|
|
token = [self readAtomic];
|
|
|
|
|
|
|
|
if ([token isError])
|
|
|
|
return token;
|
|
|
|
|
|
|
|
if (!token) {
|
|
|
|
err = [Error type: "parse" message: "Unmatched open parenthesis"];
|
|
|
|
[err source: file];
|
|
|
|
[err line: [lexer lineNumber]];
|
|
|
|
return err;
|
|
|
|
}
|
2005-05-01 11:48:36 +00:00
|
|
|
|
|
|
|
if (token == [Symbol rightParen]) {
|
|
|
|
return [Nil nil];
|
2005-05-06 23:25:06 +00:00
|
|
|
} else if (token == [Symbol dot]) {
|
|
|
|
res = [self readAtomic];
|
|
|
|
if ([res isError]) return res;
|
|
|
|
if ([self readAtomic] != [Symbol rightParen]) {
|
|
|
|
err = [Error type: "parse" message: "Improper use of dot"];
|
|
|
|
[err source: file];
|
|
|
|
[err line: [lexer lineNumber]];
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
return res;
|
2005-05-01 11:48:36 +00:00
|
|
|
} else {
|
2005-05-02 04:58:22 +00:00
|
|
|
res = [self readList];
|
|
|
|
if ([res isError]) return res;
|
|
|
|
res = cons(token, res);
|
|
|
|
[res source: file];
|
|
|
|
[res line: line];
|
|
|
|
return res;
|
2005-05-01 11:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-09 10:41:24 +00:00
|
|
|
- (SchemeObject[]) readAtomic
|
2005-05-01 11:48:36 +00:00
|
|
|
{
|
2011-01-09 10:41:24 +00:00
|
|
|
local SchemeObject []token, list, res;
|
2005-05-02 04:58:22 +00:00
|
|
|
local integer line;
|
|
|
|
|
|
|
|
line = [lexer lineNumber];
|
2005-05-06 23:25:06 +00:00
|
|
|
|
2005-05-01 11:48:36 +00:00
|
|
|
token = [lexer nextToken];
|
|
|
|
|
2005-05-02 04:58:22 +00:00
|
|
|
if ([token isError]) {
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
|
2005-05-01 11:48:36 +00:00
|
|
|
if (!token) {
|
|
|
|
return NIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (token == [Symbol leftParen]) {
|
|
|
|
list = [self readList];
|
|
|
|
return list;
|
|
|
|
} else if (token == [Symbol quote]) {
|
2005-05-02 04:58:22 +00:00
|
|
|
res = [self read];
|
|
|
|
if ([res isError]) return res;
|
|
|
|
res = cons(res, [Nil nil]);
|
|
|
|
[res source: file];
|
|
|
|
[res line: line];
|
|
|
|
res = cons([Symbol forString: "quote"], res);
|
|
|
|
[res source: file];
|
|
|
|
[res line: line];
|
|
|
|
return res;
|
2005-05-01 11:48:36 +00:00
|
|
|
} else return token;
|
|
|
|
}
|
|
|
|
|
2011-01-09 10:41:24 +00:00
|
|
|
- (SchemeObject[]) read
|
2005-05-02 04:58:22 +00:00
|
|
|
{
|
2011-01-09 10:41:24 +00:00
|
|
|
local SchemeObject []token;
|
|
|
|
local Error []err;
|
2005-05-02 04:58:22 +00:00
|
|
|
|
|
|
|
token = [self readAtomic];
|
|
|
|
if (token == [Symbol rightParen]) {
|
|
|
|
err = [Error type: "parse" message: "mismatched close parentheis"];
|
|
|
|
[err source: file];
|
|
|
|
[err line: [lexer lineNumber]];
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) markReachable
|
|
|
|
{
|
|
|
|
[lexer mark];
|
|
|
|
}
|
|
|
|
|
2005-05-01 11:48:36 +00:00
|
|
|
@end
|