Minimal (?) protype-based language.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 

1082 rindas
37 KiB

// ----- Utils -----
Object.contains(item) {
for (i in self.length()) {
if (self[i] == item) {
return 1;
}
}
return nil;
}
with(namespace) {
//print("--- With ", namespace, " ---\n\n");
if (__namespaces__.length() == 0) {
__namespaces__.push([]);
}
if (!__namespaces__.keys().contains(namespace)) {
let newNamespace = [__nsname__: namespace];
__namespaces__[namespace] = newNamespace;
__namespaces__[0][namespace] = newNamespace;
} else {
__namespaces__[0][namespace] = __namespaces__[namespace];
}
__namespaces__.push(__namespaces__[namespace]);
}
//without(); // latest
//without(#peg); // remove a plate from the middle the pile without smashing everything
//without(all: 1); // ALL
without(namespace, all: nil) {
// Remove all
if (all != nil) {
for (i in (__namespaces__.length() - 1)) {
let removedNamespace = __namespaces__.pop().__nsname__;
//print("--- Without ", removedNamespace, " ---\n\n");
__namespaces__[0][removedNamespace] = nil;
}
__namespaces__.pop();
return;
}
// Remove last
if (namespace == nil) {
let removedNamespace = __namespaces__.pop().__nsname__;
//print("--- Without ", removedNamespace, " ---\n\n");
__namespaces__[0][removedNamespace] = nil;
if (__namespaces__.length() == 1) {
__namespaces__.pop();
}
return;
}
// Remove a given namespace
// Find its index
let namespaceIndex = nil;
for (i from (__namespaces__.length() - 1) to 1) {
if (__namespaces__[i].__nsname__ == namespace) {
namespaceIndex = i;
break;
}
}
// If it's on top of the stack, just pop
if (namespaceIndex == __namespaces__.length() - 1) {
__namespaces__.pop();
//print("--- Without ", namespace, " ---\n\n");
__namespaces__[0][namespace] = nil;
if (__namespaces__.length() == 1) {
__namespaces__.pop();
}
return;
}
// If it's not on top, offset all the namespaces on top of it by one, and then pop
for (i from namespaceIndex to (__namespaces__.length() - 2)) {
__namespaces__[i] = __namespaces__[i + 1];
}
__namespaces__.pop();
//print("--- Without ", namespace, " ---\n\n");
__namespaces__[0][namespace] = nil;
if (__namespaces__.length() == 1) {
__namespaces__.pop();
}
}
get(__identifier) {
eval(GetVar.new(name: __identifier));
}
set(__identifier, __value) {
eval(SetVar.new(name: __identifier, value: __value));
}
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) {
let self = Stream.new(
content: string,
position: 0,
limit: len(string)
);
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() && {
let 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) {
let found = 0;
for (key in self.variables.keys()) {
if (key == var) {
found = 1;
}
}
if (found == 0) {
self.variables[var] = nil;
}
}
// ----- Grammar Constructs -----
// String Literal
StringLiteral = Object.subtype(#StringLiteral);
StringLiteral.match(stream, context, actions) {
let n = len(self.string);
let i = 0;
let success = 1;
if (stream.atEnd()) { success = 0; }
let 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) {
let classLength = len(self.value);
let i = 0;
let prevChar = nil;
let 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] == '-') {
// [a-z] case
if (i+1 < classLength) {
// println("[a-z] case");
let rangeStart = prevChar;
let rangeEnd = self.value[i+1];
// print("Range Start: ", rangeStart, " | ");
// print("Range End: ", rangeEnd, "\n");
if (stream.peek() >= rangeStart
&& stream.peek() <= rangeEnd
) {
success = 1;
}
prevChar = nil;
i = i + 1;
// [a-] case
} else {
// println("[a-] case");
if (stream.peek() == '-') {
success = 1;
}
}
// [ab] case
} else if (prevChar != nil && self.value[i] != '-') {
// 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.variables.yytext = stream.content[stream.lastBegin..stream.position].unescaped();
1;
}
// Optional (? postfix operator)
Optional = Object.subtype(#Optional);
Optional.match(stream, context, actions) {
let initialActionCount = actions.length();
let startingPosition = stream.position;
let success = self.expression.match(stream, context, actions);
if (success == 0) {
while (actions.length() > initialActionCount) {
actions.pop();
}
stream.position = startingPosition;
}
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) {
let 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) {
let 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) {
let i = 0;
let 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) {
let i = 0;
let success = 0;
while (i < self.length() && success == 0) {
let initialActionCount = actions.length();
let 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;
}
success;
}
// Action
Action = Object.subtype(#Action);
Action.match(stream, context, actions) {
actions.push([action: self, context: context]);
1;
}
Action.execute(context) {
// Declare all variables that a value is set to in the context
for (statement in self.parseTree.body) {
if (statement.__name__ == "SetVar") {
context.declareVariable(statement.name);
}
}
// Evaluate the parse tree and return to outer context if needed
let returnValue = eval(self.parseTree, env: context.variables);
if (context.outerContext != nil) {
context.outerContext.variables[context.returnValueName] = returnValue;
}
returnValue;
}
// Parse-time Action
ParseTimeAction = Object.subtype(#ParseTimeAction);
ParseTimeAction.match(stream, context, actions) {
if(self.action.execute(context)) {
1;
} else {
0;
}
}
// Assignment
Assignment = Object.subtype(#Assignment);
Assignment.match(stream, context, actions) {
context.declareVariable(self.name);
let innerContext = Context.new(outerContext: context, returnValueName: self.name).init();
self.rule.match(stream, innerContext, actions);
}
// RuleCall
RuleCall = Object.subtype(#RuleCall);
RuleCall.match(stream, context, actions) {
//if (rules[self.name] == nil) { print("Trying to call undefined rule: ", self.name, "\n"); exit(); }
let res = get(self.name).match(stream, context, actions);
//print("matching rule ", self.name, ": ", res, "\n");
res;
}
// NamespacedRuleCall
NamespacedRuleCall = Object.subtype(#NamespacedRuleCall);
NamespacedRuleCall.match(stream, context, actions) {
with(self.namespace);
let res = get(self.name).match(stream, context, actions);
without();
res;
}
Definition = Object.subtype(#Definition);
// ----- Grammar of Meta Language (Minimal) -----
with(#HardCodedMeta);
metaStatement = Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #b, rule: RuleCall.new(name: #block)))
.push(Action.new(parseTree: `{ b; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Alternation.new()
.push(RuleCall.new(name: #semi))
.push(And.new(expression: RuleCall.new(name: #rbrace)))
)
.push(Action.new(parseTree: `{ e; }))
);
metaExpression = Alternation.new(id: 1234)
.push(Sequence.new()
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #metaPrimary)))
.push(Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #dot))
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(RuleCall.new(name: #assign))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
)
.push(Sequence.new()
.push(RuleCall.new(name: #lbrak))
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaExpression)))
.push(RuleCall.new(name: #rbrak))
.push(RuleCall.new(name: #assign))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ SetArray.new(object: p, index: i, value: e); }))
)
)
)
.push(Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(RuleCall.new(name: #assign))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ SetVar.new(name: i, value: e); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #pf, rule: RuleCall.new(name: #metaPostfix)))
.push(Action.new(parseTree: `{ pf; }))
);
metaPostfix = Sequence.new()
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #metaPrimary)))
.push(Star.new(expression: Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #dot))
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #args)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Not.new(expression: RuleCall.new(name: #lbrace)))
.push(Action.new(parseTree: `{ p = Invoke.new(self: p, method: i, arguments: a); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #dot))
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Action.new(parseTree: `{ p = GetProp.new(object: p, key: i); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #args)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Not.new(expression: RuleCall.new(name: #lbrace)))
.push(Action.new(parseTree: `{ p = Call.new(function: p, arguments: a); }))
// TODO: Voir si c'est toujours bon avec le newApply()
)
))
.push(Action.new(parseTree: `{ p; }));
args = Sequence.new()
.push(RuleCall.new(name: #lparen))
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #mklist)))
.push(Optional.new(expression: Sequence.new()
.push(Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #k, rule: RuleCall.new(name: #metaId)))
.push(RuleCall.new(name: #colon))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ a[k] = e; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ a.push(e); }))
)
)
.push(Star.new(expression: Sequence.new()
.push(RuleCall.new(name: #comma))
.push(Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #k, rule: RuleCall.new(name: #metaId)))
.push(RuleCall.new(name: #colon))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ a[k] = e; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(Action.new(parseTree: `{ a.push(e); }))
)
)
))
))
.push(RuleCall.new(name: #rparen))
.push(Action.new(parseTree: `{ a; }));
mklist = Action.new(parseTree: `{ Object.new(); });
metaPrimary = Alternation.new()
.push(RuleCall.new(name: #nil))
.push(RuleCall.new(name: #number))
.push(RuleCall.new(name: #metaVar))
.push(RuleCall.new(name: #metaSubExpr));
metaSubExpr = Sequence.new()
.push(RuleCall.new(name: #lparen))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(RuleCall.new(name: #rparen))
.push(Action.new(parseTree = `{ e; }));
block = Sequence.new()
.push(RuleCall.new(name: #lbrace))
.push(Assignment.new(name: #b, rule: RuleCall.new(name: #mklist)))
.push(
Star.new(
expression: Sequence.new()
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaStatement)))
.push(Action.new(parseTree: `{ b.push(e); }))
)
)
.push(RuleCall.new(name: #rbrace))
.push(Action.new(parseTree: `{ Block.new(body: b); }));
number = Alternation.new()
.push(Sequence.new()
.push(StringLiteral.new(string: "-"))
.push(Assignment.new(name: #n, rule: RuleCall.new(name: #unsign)))
.push(Action.new(parseTree: `{ Unyop.new(operation: __opNeg).push(n) }))
)
.push(Sequence.new()
.push(StringLiteral.new(string: "+"))
.push(Assignment.new(name: #n, rule: RuleCall.new(name: #number)))
.push(Action.new(parseTree: `{ n }))
)
.push(Sequence.new()
.push(Assignment.new(name: #n, rule: RuleCall.new(name: #unsign)))
.push(Action.new(parseTree: `{ n }))
);
unsign = Sequence.new()
.push(Begin.new())
.push(Plus.new(expression: RuleCall.new(name: #digit)))
.push(End.new())
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ yytext.asInteger(10); }));
metaVar = Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(Action.new(parseTree: `{ GetVar.new(name: i); }));
metaId = Sequence.new()
.push(Begin.new())
.push(RuleCall.new(name: #letter))
.push(Star.new(expression: RuleCall.new(name: #alnum)))
.push(End.new())
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ intern(yytext); }));
digit = CharacterClass.new(value: "0-9");
letter = CharacterClass.new(value: "A-Za-z_");
alnum = Alternation.new()
.push(RuleCall.new(name: #letter))
.push(RuleCall.new(name: #digit));
nil = Sequence.new()
.push(StringLiteral.new(string: "nil"))
.push(Not.new(expression: RuleCall.new(name: #alnum)))
.push(RuleCall.new(name: #ws));
semi = Sequence.new().push(StringLiteral.new(string: ";" )).push(RuleCall.new(name: #ws));
comma = Sequence.new().push(StringLiteral.new(string: "," )).push(RuleCall.new(name: #ws));
lparen = Sequence.new().push(StringLiteral.new(string: "(" )).push(RuleCall.new(name: #ws));
rparen = Sequence.new().push(StringLiteral.new(string: ")" )).push(RuleCall.new(name: #ws));
lbrak = Sequence.new().push(StringLiteral.new(string: "[" )).push(RuleCall.new(name: #ws));
rbrak = Sequence.new().push(StringLiteral.new(string: "]" )).push(RuleCall.new(name: #ws));
lbrace = Sequence.new().push(StringLiteral.new(string: "{" )).push(RuleCall.new(name: #ws));
rbrace = Sequence.new().push(StringLiteral.new(string: "}" )).push(RuleCall.new(name: #ws));
assign = Sequence.new()
.push(StringLiteral.new(string: "="))
.push(Not.new(expression: CharacterClass.new(value: "=")))
.push(RuleCall.new(name: #ws));
dot = Sequence.new()
.push(StringLiteral.new(string: "."))
.push(Not.new(expression: CharacterClass.new(value: ".")))
.push(RuleCall.new(name: #ws));
colon = Sequence.new()
.push(StringLiteral.new(string: ":"))
.push(Not.new(expression: CharacterClass.new(value: ":")))
.push(RuleCall.new(name: #ws));
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: RuleCall.new(name: #end_of_line)))
.push(Dot.new())
))
.push(RuleCall.new(name: #end_of_line));
space = Alternation.new()
.push(StringLiteral.new(string: " "))
.push(StringLiteral.new(string: "\t"))
.push(RuleCall.new(name: #end_of_line));
ws = Star.new(expression: Alternation.new()
.push(RuleCall.new(name: #space))
.push(RuleCall.new(name: #comment))
);
// ----- Grammar of Grammars -----
with(#HardCodedPeg);
grammar = Sequence.new()
.push(RuleCall.new(name: #ws))
.push(Plus.new(expression: Sequence.new()
.push(Assignment.new(name: #d, rule: RuleCall.new(name: #definition)))
.push(Action.new(parseTree: `{ set(d.name, d.expression); print("Parsed rule ", d.name, "\n"); }))
))
.push(RuleCall.new(name: #end_of_file));
definition = Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #identifier)))
.push(RuleCall.new(name: #assign))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #expression)))
.push(Optional.new(expression: RuleCall.new(name: #semi)))
.push(Action.new(parseTree: `{ Definition.new(name: i, expression: e); }));
expression = Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #s, rule: RuleCall.new(name: #sequence)))
.push(Not.new(expression: RuleCall.new(name: #bar)))
.push(Action.new(parseTree: `{ s; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #s1, rule: RuleCall.new(name: #sequence)))
.push(Action.new(parseTree: `{ s1 = Alternation.new().push(s1); }))
.push(Star.new(expression: Sequence.new()
.push(RuleCall.new(name: #bar))
.push(Assignment.new(name: #s2, rule: RuleCall.new(name: #sequence)))
.push(Action.new(parseTree: `{ s1.push(s2); }))
))
.push(Action.new(parseTree: `{ s1; }))
);
sequence = Sequence.new()
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #prefix)))
.push(Action.new(parseTree: `{ p = Sequence.new().push(p); }))
.push(Star.new(expression: Sequence.new()
.push(Assignment.new(name: #q, rule: RuleCall.new(name: #prefix)))
.push(Action.new(parseTree: `{ p.push(q); }))
))
.push(Action.new(parseTree: `{ p; }));
prefix = Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #and))
.push(RuleCall.new(name: #action))
)
.push(Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #and))
.push(Assignment.new(name: #s, rule: RuleCall.new(name: #suffix)))
.push(Action.new(parseTree: `{ And.new(expression: s); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #not))
.push(Assignment.new(name: #s, rule: RuleCall.new(name: #suffix)))
.push(Action.new(parseTree: `{ Not.new(expression: s); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #s, rule: RuleCall.new(name: #suffix)))
.push(Action.new(parseTree: `{ s; }))
)
);
suffix = Sequence.new()
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #primary)))
.push(Optional.new(expression: Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #query))
.push(Action.new(parseTree: `{ p = Optional.new(expression: p); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #star))
.push(Action.new(parseTree: `{ p = Star.new(expression: p); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #plus))
.push(Action.new(parseTree: `{ p = Plus.new(expression: p); }))
)
))
.push(Action.new(parseTree: `{ p; }));
primary = Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #i1, rule: RuleCall.new(name: #identifier)))
.push(RuleCall.new(name: #colon))
.push(Assignment.new(name: #i2, rule: RuleCall.new(name: #ruleCall)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Action.new(parseTree: `{ Assignment.new(name: i1, rule: i2); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #ruleCall)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Action.new(parseTree: `{ i; }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #lparen))
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #expression)))
.push(RuleCall.new(name: #rparen))
.push(Action.new(parseTree: `{ e; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #l, rule: RuleCall.new(name: #literal)))
.push(Action.new(parseTree: `{ l; }))
)
.push(Sequence.new()
.push(Assignment.new(name: #c, rule: RuleCall.new(name: #class)))
.push(Action.new(parseTree: `{ c; }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #dot))
.push(Action.new(parseTree: `{ Dot.new(); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #action)))
.push(Action.new(parseTree: `{ a; }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #begin))
.push(Action.new(parseTree: `{ Begin.new(); }))
)
.push(Sequence.new()
.push(RuleCall.new(name: #end))
.push(Action.new(parseTree: `{ End.new(); }))
);
identifier = Sequence.new()
.push(Begin.new())
.push(CharacterClass.new(value: "-a-zA-Z_"))
.push(Star.new(expression: CharacterClass.new(value: "-a-zA-Z_0-9")))
.push(End.new())
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ intern(yytext); }));
ruleCall = Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #n, rule: RuleCall.new(name: #identifier)))
.push(RuleCall.new(name: #ccolon))
.push(Assignment.new(name: #r, rule: RuleCall.new(name: #identifier)))
.push(Action.new(parseTree: `{ NamespacedRuleCall.new(namespace: n, name: r); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #identifier)))
.push(Action.new(parseTree: `{ RuleCall.new(name: i); }))
);
literal = Alternation.new()
.push(Sequence.new()
.push(CharacterClass.new(value: "\'"))
.push(Begin.new())
.push(Star.new(expression: Sequence.new()
.push(Not.new(expression: CharacterClass.new(value: "\'")))
.push(RuleCall.new(name: #char))
))
.push(End.new())
.push(CharacterClass.new(value: "\'"))
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ StringLiteral.new(string: yytext); }))
)
.push(Sequence.new()
.push(CharacterClass.new(value: "\""))
.push(Begin.new())
.push(Star.new(expression: Sequence.new()
.push(Not.new(expression: CharacterClass.new(value: "\"")))
.push(RuleCall.new(name: #char))
))
.push(End.new())
.push(CharacterClass.new(value: "\""))
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ StringLiteral.new(string: yytext); }))
);
class = Sequence.new()
.push(StringLiteral.new(string: "["))
.push(Begin.new())
.push(Star.new(expression: Sequence.new()
.push(Not.new(expression: StringLiteral.new(string: "]")))
.push(RuleCall.new(name: #range))
))
.push(End.new())
.push(StringLiteral.new(string: "]"))
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ CharacterClass.new(value: yytext); }));
range = Alternation.new()
.push(Sequence.new()
.push(RuleCall.new(name: #char))
.push(StringLiteral.new(string: "-"))
.push(RuleCall.new(name: #char))
)
.push(
RuleCall.new(name: #char)
);
char = Alternation.new()
.push(Sequence.new()
.push(StringLiteral.new(string: "\\"))
.push(CharacterClass.new(value: "abefnrtv\'\"[]\\"))
)
.push(Sequence.new()
.push(StringLiteral.new(string: "\\"))
.push(CharacterClass.new(value: "0-3"))
.push(CharacterClass.new(value: "0-7"))
.push(CharacterClass.new(value: "0-7"))
)
.push(Sequence.new()
.push(StringLiteral.new(string: "\\"))
.push(CharacterClass.new(value: "0-7"))
.push(Optional.new(expression: CharacterClass.new(value: "0-7")))
)
.push(Sequence.new()
.push(Not.new(expression: StringLiteral.new(string: "\\")))
.push(Dot.new())
);
action = Sequence.new()
.push(Assignment.new(name: #m, rule: NamespacedRuleCall.new(namespace: #HardCodedMeta, name: #block)))
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ Action.new(parseTree: m); }));
bar = Sequence.new().push(StringLiteral.new(string: "|")).push(RuleCall.new(name: #ws));
not = Sequence.new().push(StringLiteral.new(string: "!")).push(RuleCall.new(name: #ws));
query = Sequence.new().push(StringLiteral.new(string: "?")).push(RuleCall.new(name: #ws));
begin = Sequence.new().push(StringLiteral.new(string: "<")).push(RuleCall.new(name: #ws));
end = Sequence.new().push(StringLiteral.new(string: ">")).push(RuleCall.new(name: #ws));
tilde = Sequence.new().push(StringLiteral.new(string: "~")).push(RuleCall.new(name: #ws));
rpercent = Sequence.new().push(StringLiteral.new(string: "%}")).push(RuleCall.new(name: #ws));
ccolon = Sequence.new().push(StringLiteral.new(string: "::")).push(RuleCall.new(name: #ws));
and = Sequence.new()
.push(StringLiteral.new(string: "&"))
.push(Not.new(expression: CharacterClass.new(value: "&=")))
.push(RuleCall.new(name: #ws));
plus = Sequence.new()
.push(StringLiteral.new(string: "+"))
.push(Not.new(expression: CharacterClass.new(value: "+=")))
.push(RuleCall.new(name: #ws));
star = Sequence.new()
.push(StringLiteral.new(string: "*"))
.push(Not.new(expression: CharacterClass.new(value: "=")))
.push(RuleCall.new(name: #ws));
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: RuleCall.new(name: #end_of_line)))
.push(Dot.new())
))
.push(RuleCall.new(name: #end_of_line));
space = Alternation.new()
.push(StringLiteral.new(string: " "))
.push(StringLiteral.new(string: "\t"))
.push(RuleCall.new(name: #end_of_line));
ws = Star.new(expression: Alternation.new()
.push(RuleCall.new(name: #space))
.push(RuleCall.new(name: #comment))
);
// ----- Main -----
with(#reading);
stream = newStream(readfile("rawminproto.leg"));
context = Context.new(outerContext: nil).init();
actions = [];
grammar.match(stream, context, actions);
with(#metaLanguage);
for (actionAndContext in actions) {
actionAndContext.action.execute(actionAndContext.context);
}
println("\n--------- META ---------\n\n");
println(__namespaces__.metaLanguage);
without(#metaLanguage);
//stream = newStream(readfile("rawMetaGrammar.leg"));
//context = Context.new(outerContext: nil).init();
//actions = [];
//
//print("Matching : ", grammar.match(stream, context, actions), "\n");
//
//// Execute all actions after all matching
//// Open the namespace where rules will be declared
//with(#metaLanguage);
//
//for (actionAndContext in actions) {
// actionAndContext.action.execute(actionAndContext.context);
//}
//
//println("\n--------- META ---------\n\n");
//println(__namespaces__.metaLanguage);
//without(#metaLanguage);
without(#reading);
with(#reading);
stream = newStream(readfile("rawgrammar.leg"));
context = Context.new(outerContext: nil).init();
actions = [];
print("Matching : ", grammar.match(stream, context, actions), "\n");
// Execute all actions after all matching
with(#peg);
for (actionAndContext in actions) {
actionAndContext.action.execute(actionAndContext.context);
}
println("\n--------- PEG ---------\n\n");
println(__namespaces__.peg);
without(#peg);
without(#reading);
// Circularity test
without(all: 1);
with(#metaLanguage);
with(#peg);
with(#reading);
stream2 = newStream(readfile("rawminproto.leg"));
//stream2 = newStream("a = b:c::d { print(a[b].c); }");
context2 = Context.new(outerContext: nil).init();
actions2 = [];
print("\nMatching : ", grammar.match(stream2, context2, actions2), "\n");
with(#metaLanguageCircular);
for (actionAndContext in actions2) {
actionAndContext.action.execute(actionAndContext.context);
}
println("\n--------- CIRCULAR META ---------\n\n");
println(__namespaces__.metaLanguageCircular);
without(#metaLanguageCircular);
stream2 = newStream(readfile("rawgrammar.leg"));
context2 = Context.new(outerContext: nil).init();
actions2 = [];
print("\nMatching : ", grammar.match(stream2, context2, actions2), "\n");
with(#pegCircular);
for (actionAndContext in actions2) {
actionAndContext.action.execute(actionAndContext.context);
}
println("\n--------- CIRCULAR PEG ---------\n\n");
println(__namespaces__.pegCircular);
without(#pegCircular);
without(all: 1);
compareGrammars(grammar1, grammar2) {
let success = 1;
for (key in __namespaces__[grammar1].keys()) {
if (key == #__nsname__) continue;
if (codeString(__namespaces__[grammar1][key]) != codeString(__namespaces__[grammar2][key])) {
print("Found different objects for rule ", key, ":\n");
println(__namespaces__[grammar1][key]);
println(__namespaces__[grammar2][key]);
success = 0;
}
}
if (success == 1) {
print("Grammars ", grammar1, " and ", grammar2, " are equal\n");
}
}
compareGrammars(#peg, #pegCircular);
compareGrammars(#metaLanguage, #metaLanguageCircular);