mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-17 18:30:58 +00:00
139 lines
3.6 KiB
R
139 lines
3.6 KiB
R
#include "Lexer.h"
|
|
#include "Number.h"
|
|
#include "string.h"
|
|
#include "Boolean.h"
|
|
#include "Error.h"
|
|
#include "defs.h"
|
|
|
|
BOOL isdigit (string x)
|
|
{
|
|
return (x == "0" || x == "1" || x == "2" || x == "3" ||
|
|
x == "4" || x == "5" || x == "6" || x == "7" ||
|
|
x == "8" || x == "9");
|
|
}
|
|
|
|
BOOL isspace (string x)
|
|
{
|
|
return (x == " " || x == "\t" || x == "\n" || x == "\r");
|
|
}
|
|
|
|
BOOL isjunk (string x)
|
|
{
|
|
return isspace (x) || x == ";";
|
|
}
|
|
|
|
BOOL issymbol (string x)
|
|
{
|
|
return (x != "" && x != "(" && x !=")" && !isjunk (x));
|
|
}
|
|
|
|
@implementation Lexer
|
|
|
|
+ (id) newFromSource: (string) s file: (string) f
|
|
{
|
|
return [[Lexer alloc] initWithSource: s file: f];
|
|
}
|
|
|
|
- (id) initWithSource: (string) s file: (string) f
|
|
{
|
|
self = [super init];
|
|
source = str_new();
|
|
str_copy(source, s);
|
|
filename = f;
|
|
linenum = 1;
|
|
return self;
|
|
}
|
|
|
|
- (SchemeObject*) nextToken
|
|
{
|
|
local int len;
|
|
local Number *num;
|
|
local Symbol *sym;
|
|
local String *str;
|
|
local Boolean *bl;
|
|
|
|
for (len = 0; isjunk(str_mid(source, len, len+1)); len++) {
|
|
if (str_mid(source, len, len+1) == ";") {
|
|
while (str_mid(source, len, len+1) != "\n") {
|
|
len++;
|
|
}
|
|
}
|
|
if (str_mid(source, len, len+1) == "\n") {
|
|
linenum++;
|
|
}
|
|
}
|
|
|
|
str_copy (source, str_mid(source, len));
|
|
|
|
switch (str_mid (source, 0, 1)) {
|
|
case "(":
|
|
str_copy (source, str_mid (source, 1));
|
|
return [Symbol leftParen];
|
|
case ")":
|
|
str_copy (source, str_mid (source, 1));
|
|
return [Symbol rightParen];
|
|
case "0": case "1": case "2":
|
|
case "3": case "4": case "5":
|
|
case "6": case "7": case "8":
|
|
case "9":
|
|
for (len = 1; isdigit(str_mid(source, len, len+1)); len++);
|
|
num = [Number newFromInt: stoi (str_mid(source, 0, len))];
|
|
[num source: filename];
|
|
[num line: linenum];
|
|
str_copy (source, str_mid(source, len));
|
|
return num;
|
|
case "\"":
|
|
for (len = 1; str_mid(source, len, len+1) != "\""; len++);
|
|
str = [String newFromString: str_mid(source, 1, len)];
|
|
[str source: filename];
|
|
[str line: linenum];
|
|
str_copy (source, str_mid(source, len+1));
|
|
return str;
|
|
case "'":
|
|
str_copy (source, str_mid (source, 1));
|
|
return [Symbol quote];
|
|
case ".":
|
|
str_copy (source, str_mid (source, 1));
|
|
return [Symbol dot];
|
|
case "#":
|
|
str_copy (source, str_mid (source, 1));
|
|
switch (str_mid (source, 0, 1)) {
|
|
case "t":
|
|
bl = [Boolean trueConstant];
|
|
str_copy (source, str_mid (source, 1));
|
|
return bl;
|
|
case "f":
|
|
bl = [Boolean falseConstant];
|
|
str_copy (source, str_mid (source, 1));
|
|
return bl;
|
|
default:
|
|
return [Error type: "parse"
|
|
message: "Invalid # constant"
|
|
by: self];
|
|
}
|
|
case "":
|
|
return nil;
|
|
default:
|
|
for (len = 1; issymbol(str_mid(source, len, len+1)); len++);
|
|
sym = [Symbol forString: str_mid (source, 0, len)];
|
|
str_copy (source, str_mid(source, len));
|
|
return sym;
|
|
}
|
|
}
|
|
|
|
- (int) lineNumber
|
|
{
|
|
return linenum;
|
|
}
|
|
|
|
- (int) line
|
|
{
|
|
return linenum;
|
|
}
|
|
|
|
- (string) source
|
|
{
|
|
return filename;
|
|
}
|
|
|
|
@end
|