Преглед изворни кода

Merge range access and grammar parser changes

родитељ
комит
7aa229bb22
2 измењених фајлова са 542 додато и 10 уклоњено
  1. +495
    -0
      grammar_parser.meta
  2. +47
    -10
      minproto.leg

+ 495
- 0
grammar_parser.meta Прегледај датотеку

@ -0,0 +1,495 @@
// Utils
println = (x) {
if (!x) {
print("\n");
} else {
print(x, "\n", full: 1);
}
};
Object.subtype(name) { self.new(__name__: name) }
// Input stream
Stream = Object.subtype(#Stream);
newStream(string) {
self = Stream.new(
content: string,
position: 0,
limit: len(string)
);
print("Created new stream object: { position: ", self.position, ", limit: ", self.limit, ", !atEnd(): ", !self.atEnd(), " }\n");
self;
}
Stream.atEnd() { self.position >= self.limit }
Stream.peek() { !self.atEnd() && self.content[self.position] }
Stream.inc() { !self.atEnd() && { self.position = self.position + 1; } }
Stream.next() {
!self.atEnd() && {
c = self.content[self.position];
self.position = self.position + 1;
c;
}
}
Stream.setLastBegin = () { self.lastBegin = self.position; };
// Context
Context = Object.subtype(#Context);
Context.init() { self.variables = []; self; }
Context.declareVariable(var) { self.variables[var] = nil }
// ----- Grammar Constructs -----
// String Literal
StringLiteral = Object.subtype(#StringLiteral);
StringLiteral.match(stream, context, actions) {
n = len(self.string);
i = 0;
success = 1;
if (stream.atEnd()) { success = 0; }
startPosition = stream.position;
while(i < n && success == 1) {
if (self.string[i] != stream.peek()) {
success = 0;
stream.position = startPosition;
} else {
i = i + 1;
stream.inc();
}
}
success;
}
// Character Class
CharacterClass = Object.subtype(#CharacterClass);
CharacterClass.match(stream, context, actions) {
classLength = len(self.value);
i = 0;
prevChar = nil;
success = 0;
while (i < classLength && success == 0 && !stream.atEnd()) {
// [a] case
if (prevChar == nil) {
// println("[a] case");
prevChar = self.value[i];
if (stream.peek() == self.value[i]) {
success = 1;
}
} else if (prevChar != nil && self.value[i] == ord('-')) {
// [a-z] case
if (i+1 < classLength) {
// println("[a-z] case");
rangeStart = charValue(prevChar);
rangeEnd = charValue(self.value[i+1]);
// print("Range Start: ", rangeStart, " | ");
// print("Range End: ", rangeEnd, "\n");
if (charValue(stream.peek()) >= rangeStart
&& charValue(stream.peek()) <= rangeEnd
) {
success = 1;
}
prevChar = nil;
i = i + 1;
// [a-] case
} else {
// println("[a-] case");
if (stream.peek() == ord('-')) {
success = 1;
}
}
// [ab] case
} else if (prevChar != nil && self.value[i] != ord('-')) {
// println("[ab] case");
prevChar = self.value[i];
if (stream.peek() == self.value[i]) {
success = 1;
}
}
// print("prevChar: ", prevChar, "\n");
i = i + 1;
}
if (success == 1) {
stream.inc();
}
success;
}
// Dot
Dot = Object.subtype(#Dot);
Dot.match(stream, context, actions) {
if (!stream.atEnd()) {
stream.inc();
1;
} else {
0;
}
}
// Begin
Begin = Object.subtype(#Begin);
Begin.match(stream, context, actions) {
stream.setLastBegin();
1;
}
// End
End = Object.subtype(#End);
End.match(stream, context, actions) {
context.input = stream.string[stream.lastBegin..stream.position];
1;
}
// Optional (? postfix operator)
Optional = Object.subtype(#Optional);
Optional.match(stream, context, actions) {
self.expression.match(stream, context, actions);
1;
}
// Star
Star = Object.subtype(#Star);
Star.match(stream, context, actions) {
while (self.expression.match(stream, context, actions) == 1) {}
1;
}
// Plus
Plus = Object.subtype(#Plus);
Plus.match(stream, context, actions) {
if (self.expression.match(stream, context, actions) == 1) {
while (self.expression.match(stream, context, actions) == 1) {}
1;
} else {
0;
}
}
// And
And = Object.subtype(#And);
And.match(stream, context, actions) {
position = stream.position;
if (self.expression.match(stream, context, actions) == 1) {
stream.position = position;
1;
} else {
0;
}
}
// Not
Not = Object.subtype(#Not);
Not.match(stream, context, actions) {
position = stream.position;
if (self.expression.match(stream, context, actions) == 1) {
stream.position = position;
0;
} else {
1;
}
}
// Sequence
Sequence = Object.subtype(#Sequence);
Sequence.match(stream, context, actions) {
i = 0;
match = 1;
while (i < self.length() && match == 1) {
match = self[i].match(stream, context, actions);
i = i + 1;
}
match;
}
// Alternation
Alternation = Object.subtype(#Alternation);
Alternation.match(stream, context, actions) {
i = 0;
success = 0;
while (i < self.length() && success == 0) {
initialActionCount = actions.length();
startingPosition = stream.position;
success = self[i].match(stream, context, actions);
if (success == 0) {
while (actions.length() > initialActionCount) {
actions.pop();
}
stream.position = startingPosition;
}
i = i + 1;
print(i, " | ", success, " | ", self.length(), "\n");
}
success;
}
// Action
Action = Object.subtype(#Action);
Action.match(stream, context, actions) {
actions.push(self);
self.context = context;
1;
}
Action.execute() {
// Declare all variables that a value is set to in the context
for (statement in self.parseTree.body) {
if (statement.__name__ == "SetVar") {
self.context.declareVariable(statement.name);
}
}
// Evaluate the parse tree and return to outer context if needed
returnValue = eval(self.parseTree, env: self.context.variables);
if (self.context.outerContext != nil) {
self.context.outerContext.variables[self.context.returnValueName] = returnValue;
}
}
// Assignment
Assignment = Object.subtype(#Assignment);
Assignment.match(stream, context, actions) {
context.declareVariable(self.variableName);
innerContext = Context.new(outerContext: context, returnValueName: self.variableName).init();
self.rule.match(stream, innerContext, actions);
}
// ----- Grammar of Grammars -----
// Whitespace
// - = ( space | comment )*
// space = ' ' | '\t' | end-of-line
// comment = '#' ( !end-of-line . )* end-of-line
// end-of-line = '\r\n' | '\n' | '\r'
// end-of-file = !.
end_of_file = Not.new(expression: Dot.new());
end_of_line = Alternation.new()
.push(StringLiteral.new(string: "\r\n"))
.push(StringLiteral.new(string: "\n"))
.push(StringLiteral.new(string: "\r"));
comment = Sequence.new()
.push(StringLiteral.new(string: "#"))
.push(Star.new(expression:
Sequence.new()
.push(Not.new(expression: end_of_line))
.push(Dot.new())
))
.push(end_of_line);
space = Alternation.new()
.push(StringLiteral.new(string: " "))
.push(StringLiteral.new(string: "\t"))
.push(end_of_line);
ws = Star.new(expression: Alternation.new()
.push(space)
.push(comment)
);
// Literal Terminators
Terminators = [];
// BAR = '|' -
// NOT = '!' -
// QUERY = '?' -
// BEGIN = '<' -
// END = '>' -
// TILDE = '~' -
// RPERCENT = '%}' -
Terminators.bar = Sequence.new().push(StringLiteral.new(string: "|")).push(ws);
Terminators.not = Sequence.new().push(StringLiteral.new(string: "!")).push(ws);
Terminators.query = Sequence.new().push(StringLiteral.new(string: "?")).push(ws);
Terminators.begin = Sequence.new().push(StringLiteral.new(string: "<")).push(ws);
Terminators.end = Sequence.new().push(StringLiteral.new(string: ">")).push(ws);
Terminators.tilde = Sequence.new().push(StringLiteral.new(string: "~")).push(ws);
Terminators.rpercent = Sequence.new().push(StringLiteral.new(string: "%}")).push(ws);
// DIGIT = [0-9]
// LETTER = [A-Za-z_]
// ALNUM = LETTER | DIGIT
// NIL = "nil" !ALNUM -
digit = CharacterClass.new(value: "0-9");
letter = CharacterClass.new(value: "A-Za-z_");
alnum = Alternation.new().push(letter).push(digit);
nil = Sequence.new().push(StringLiteral.new(string: "nil")).push(Not.new(expression: alnum)).push(ws);
// SEMI = ";" -
// COMMA = "," -
// COLON = ":" -
// LPAREN = "(" -
// RPAREN = ")" -
// LBRAK = "[" -
// RBRAK = "]" -
// LBRACE = "{" -
// RBRACE = "}" -
// ASSIGN = "=" ![=] -
// AND = "&" ![&=] -
// PLUS = "+" ![+=] -
// STAR = "*" ![=] -
// DOT = "." ![.] -
Terminators.semi = Sequence.new().push(StringLiteral.new(string: ";")).push(ws);
Terminators.comma = Sequence.new().push(StringLiteral.new(string: ",")).push(ws);
Terminators.colon = Sequence.new().push(StringLiteral.new(string: ":")).push(ws);
Terminators.lparen = Sequence.new().push(StringLiteral.new(string: "(")).push(ws);
Terminators.rparen = Sequence.new().push(StringLiteral.new(string: ")")).push(ws);
Terminators.lbrak = Sequence.new().push(StringLiteral.new(string: "[")).push(ws);
Terminators.rbrak = Sequence.new().push(StringLiteral.new(string: "]")).push(ws);
Terminators.lbrace = Sequence.new().push(StringLiteral.new(string: "{")).push(ws);
Terminators.rbrace = Sequence.new().push(StringLiteral.new(string: "}")).push(ws);
Terminators.assign = Sequence.new()
.push(StringLiteral.new(string: "="))
.push(Not.new(expression: CharacterClass.new(value: "=")))
.push(ws);
Terminators.and = Sequence.new()
.push(StringLiteral.new(string: "&"))
.push(Not.new(expression: CharacterClass.new(value: "&=")))
.push(ws);
Terminators.plus = Sequence.new()
.push(StringLiteral.new(string: "+"))
.push(Not.new(expression: CharacterClass.new(value: "+=")))
.push(ws);
Terminators.star = Sequence.new()
.push(StringLiteral.new(string: "*"))
.push(Not.new(expression: CharacterClass.new(value: "=")))
.push(ws);
Terminators.dot = Sequence.new()
.push(StringLiteral.new(string: "."))
.push(Not.new(expression: CharacterClass.new(value: ".")))
.push(ws);
// ----- Main -----
// stream = newStream(readfile("input.txt"));
stream = newStream("baaababbaabaaa");
context = Context.new(outerContext: nil).init();
actions = [];
// s = StringLiteral.new(string: "ab");
// print("Success : ", s.match(stream), "\n");
// c = CharacterClass.new(value: " \n\t");
// print("Parsing Character: ", stream.peek(), " | CharacterClass [", c.value,"] : ", c.match(stream), "\n");
// d = Dot.new();
// print("Parsing Character: ", stream.peek(), " | Dot : ", d.match(stream, context), "\n");
println("\n--- Action Test ---\n");
actionParseTree = `{
innerVar = 151;
};
act = Action.new(parseTree: actionParseTree);
assign = Assignment.new(variableName: #outerVar, rule: act);
assign.match(stream, context, actions);
actionParseTree2 = `{
x = 69;
};
act2 = Action.new(parseTree: actionParseTree2);
act2.match(stream, context, actions);
for (action in actions) {
action.execute();
}
print("global variable named innerVar => ", innerVar, " should be nil\n");
print("global variable named x => ", x, " should be nil\n");
print(context, "\n", full: 1);
print("\nMatching : ", Terminators.bar.match(stream, context, actions), "\n");
println(stream);
print("\nMatching : ", Star.new(expression: Alternation.new()
.push(StringLiteral.new(string: "a"))
.push(StringLiteral.new(string: "b"))
).match(stream, context, actions), "\n");
println(stream);
// print("\nMatching : ", ws.match(stream, context, actions), "\n");
// println(stream);
// c = CharacterClass.new(value: "a");
// u = Not.new(expression: c);
// println(u.match(stream, context));
// println(stream);
//
// println();
// println();
// println();
//
// gensokyo = [buses: 0, inhabitants: 1337];
//
// reimu = [location: gensokyo];
// marisa = [location: gensokyo];
//
// println(marisa.location);
// reimu.location.inhabitants = 42;
// println(marisa.location);

+ 47
- 10
minproto.leg Прегледај датотеку

@ -97,9 +97,9 @@ oop printOn(oop buf, oop obj, int indent);
#endif
#if PRIMCLOSURE
#define doProtos(_) _(Object) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal)
#define doProtos(_) _(Object) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Range)
#else
#define doProtos(_) _(Object) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure)
#define doProtos(_) _(Object) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure) _(Range)
#endif
#define declareProto(NAME) oop p##NAME = 0;
@ -127,7 +127,7 @@ doTypes(makeProto);
doProperties(declareProp);
#undef declareProp
#define doSymbols(_) _(t) _(name) _(expr) _(function) _(arguments) _(object) _(index) _(key) _(value) _(self) _(method) _(parameters) _(body) _(lambda) _(environment) _(operation) _(full) _(condition) _(consequent) _(alternate) _(expression) _(identifier) _(initialise) _(update) _(first) _(last) _(fixed) _(keyvals)
#define doSymbols(_) _(t) _(name) _(expr) _(function) _(arguments) _(object) _(index) _(key) _(value) _(self) _(method) _(parameters) _(body) _(lambda) _(environment) _(operation) _(full) _(condition) _(consequent) _(alternate) _(expression) _(identifier) _(initialise) _(update) _(first) _(last) _(fixed) _(keyvals) _(start) _(end) _(env)
#define declareSym(NAME) oop sym_##NAME = 0;
doSymbols(declareSym);
@ -1353,6 +1353,17 @@ oop GetArray_eval(oop exp, oop env)
default: fatal("[]: %s is not indexable", storeString(obj, 0));
}
}
if (getType(ind) == Object) {
switch (getType(obj)) {
case String: {
int start = integerValue(eval(Object_get(ind, sym_start), env), "[..]");
int end = integerValue(eval(Object_get(ind, sym_end ), env), "[..]");
oop slice = newStringLen(String_aref(obj, start), end - start);
return slice;
}
default: fatal("[]: %s is not range - indexable", storeString(obj, 0));
}
}
if (!is(Object, obj)) fatal("[]: %s is not an object", storeString(obj, 0));
return Object_getLocal(obj, ind);
}
@ -1402,6 +1413,25 @@ void SetArray_codeOn(oop exp, oop str, oop env)
codeOn(str, Object_get(exp, sym_value), 0);
}
oop newRange(oop start, oop end) {
oop o = new(pRange);
Object_put(o, sym_start, start);
Object_put(o, sym_end, end);
return o;
}
oop Range_eval(oop exp, oop env)
{
return exp;
}
void Range_codeOn(oop exp, oop str, oop env)
{
codeOn(str, Object_get(exp, sym_start), 0);
String_appendAll(str, "..");
codeOn(str, Object_get(exp, sym_end), 0);
}
oop newCall(oop function, oop arguments)
{
oop o = new(pCall);
@ -2573,10 +2603,13 @@ sum = l:prod ( PLUS r:prod { l = newBinop(opAdd, l, r) }
| MINUS r:prod { l = newBinop(opSub, l, r) }
)* { $$ = l }
prod = l:prefix ( STAR r:prefix { l = newBinop(opMul, l, r) }
| SLASH r:prefix { l = newBinop(opDiv, l, r) }
| PCENT r:prefix { l = newBinop(opMod, l, r) }
)* { $$ = l }
prod = l:range ( STAR r:range { l = newBinop(opMul, l, r) }
| SLASH r:range { l = newBinop(opDiv, l, r) }
| PCENT r:range { l = newBinop(opMod, l, r) }
) * { $$ = l }
range = i1:prefix ( DOTDOT i2:prefix { i1 = newRange(i1, i2) }
) ? { $$ = i1 }
prefix = PPLUS l:lvalue { $$ = newBinop(opPreAdd, l, newInteger(1)) }
| MMINUS l:lvalue { $$ = newBinop(opPreSub, l, newInteger(1)) }
@ -2649,8 +2682,7 @@ number = "-" u:unsign { $$ = neg(u) }
| "+" n:number { $$ = u }
| u:unsign { $$ = u }
unsign = < DIGIT+ '.' DIGIT* EXP? > - { $$ = newFloat(strtod(yytext, 0)) }
| < DIGIT* '.' DIGIT+ EXP? > - { $$ = newFloat(strtod(yytext, 0)) }
unsign = < DIGIT* '.' DIGIT+ EXP? > - { $$ = newFloat(strtod(yytext, 0)) }
| "0" [bB] < BIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 2)) }
| "0" [xX] < HIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 16)) }
| "0" < OIGIT* > - { $$ = newInteger(strtol(yytext, 0, 8)) }
@ -2735,7 +2767,7 @@ SLASH = "/" ![/=] -
SLASHEQ = "/=" -
PCENT = "%" ![=] -
PCENTEQ = "%=" -
DOT = "." -
DOT = "." ![.] -
PLING = "!" ![=] -
TILDE = "~" -
@ -2973,6 +3005,11 @@ oop prim_eval(oop func, oop self, oop args, oop env)
int argc = _get(args, Object,isize);
oop *indexed = _get(args, Object,indexed);
oop result = nil;
if (nil != Object_getLocal(args, sym_env)) {
env = Object_getLocal(args, sym_env);
}
for (int i = 0; i < argc; ++i) result = eval(indexed[i], env);
return result;
}

Loading…
Откажи
Сачувај