|
|
@ -101,13 +101,17 @@ setInTopNamespace(__identifier, __value) { |
|
|
|
__namespaces__.last()[__identifier] = __value; |
|
|
|
} |
|
|
|
|
|
|
|
println = (x) { |
|
|
|
println(x) { |
|
|
|
if (!x) { |
|
|
|
print("\n"); |
|
|
|
if (len(__env__().__delegate__) == 0){ |
|
|
|
print("\n"); |
|
|
|
} else { |
|
|
|
print(nil, "\n"); |
|
|
|
} |
|
|
|
} else { |
|
|
|
print(x, "\n", full: 1); |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
Object.subtype(name) { self.new(__name__: name) } |
|
|
|
|
|
|
@ -137,7 +141,7 @@ Stream.peek() { !self.atEnd() && self.content[self.position] } |
|
|
|
Context = Object.subtype(#Context); |
|
|
|
Context.init() { self.variables = []; self; } |
|
|
|
Context.declareVariable(var) { |
|
|
|
found = 0; |
|
|
|
local found = 0; |
|
|
|
for (key in self.variables.keys()) { |
|
|
|
if (key == var) { |
|
|
|
found = 1; |
|
|
@ -163,6 +167,18 @@ StringLiteral.match(stream, context, actions) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
StringLiteral.getMatchingExpression() { |
|
|
|
//return `(@stream).match(@self.string) && ((@stream).position += len(@self.string)) && @true; |
|
|
|
return `{ |
|
|
|
if (stream.match(@self.string)) { |
|
|
|
stream.position += len(@self.string); |
|
|
|
@true; |
|
|
|
} else { |
|
|
|
@false; |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
//StringLiteral.match(stream, context, actions) { |
|
|
|
// |
|
|
|
// n = len(self.string); |
|
|
@ -190,10 +206,10 @@ CharacterClass = Object.subtype(#CharacterClass); |
|
|
|
|
|
|
|
CharacterClass.match(stream, context, actions) { |
|
|
|
|
|
|
|
classLength = len(self.value); |
|
|
|
i = 0; |
|
|
|
prevChar = nil; |
|
|
|
success = 0; |
|
|
|
local classLength = len(self.value); |
|
|
|
local i = 0; |
|
|
|
local prevChar = nil; |
|
|
|
local success = 0; |
|
|
|
|
|
|
|
while (i < classLength && success == 0 && !stream.atEnd()) { |
|
|
|
|
|
|
@ -211,8 +227,8 @@ CharacterClass.match(stream, context, actions) { |
|
|
|
// [a-z] case |
|
|
|
if (i+1 < classLength) { |
|
|
|
// println("[a-z] case"); |
|
|
|
rangeStart = prevChar; |
|
|
|
rangeEnd = self.value[i+1]; |
|
|
|
local rangeStart = prevChar; |
|
|
|
local rangeEnd = self.value[i+1]; |
|
|
|
// print("Range Start: ", rangeStart, " | "); |
|
|
|
// print("Range End: ", rangeEnd, "\n"); |
|
|
|
if (stream.peek() >= rangeStart |
|
|
@ -250,6 +266,73 @@ CharacterClass.match(stream, context, actions) { |
|
|
|
success == 1; |
|
|
|
} |
|
|
|
|
|
|
|
CharacterClass.staticmatch(stream, context, actions, value) { |
|
|
|
|
|
|
|
local classLength = len(value); |
|
|
|
local i = 0; |
|
|
|
local prevChar = nil; |
|
|
|
local success = 0; |
|
|
|
|
|
|
|
while (i < classLength && success == 0 && !stream.atEnd()) { |
|
|
|
|
|
|
|
// [a] case |
|
|
|
if (prevChar == nil) { |
|
|
|
//println("[a] case"); |
|
|
|
prevChar = value[i]; |
|
|
|
|
|
|
|
if (stream.peek() == value[i]) { |
|
|
|
success = 1; |
|
|
|
} |
|
|
|
|
|
|
|
} else if (prevChar != nil && value[i] == '-') { |
|
|
|
|
|
|
|
// [a-z] case |
|
|
|
if (i+1 < classLength) { |
|
|
|
// println("[a-z] case"); |
|
|
|
local rangeStart = prevChar; |
|
|
|
local rangeEnd = 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 && value[i] != '-') { |
|
|
|
// println("[ab] case"); |
|
|
|
prevChar = value[i]; |
|
|
|
if (stream.peek() == value[i]) { |
|
|
|
success = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
// print("prevChar: ", prevChar, "\n"); |
|
|
|
i = i + 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (success == 1) { |
|
|
|
stream.inc(); |
|
|
|
} |
|
|
|
|
|
|
|
success == 1; |
|
|
|
} |
|
|
|
|
|
|
|
CharacterClass.getMatchingExpression() { |
|
|
|
//return `CharacterClass.staticmatch(@stream, @context, @actions, @self.value); |
|
|
|
return `{ CharacterClass.staticmatch(stream, context, actions, @self.value) }; |
|
|
|
} |
|
|
|
|
|
|
|
// Dot |
|
|
|
|
|
|
|
Dot = Object.subtype(#Dot); |
|
|
@ -263,6 +346,11 @@ Dot.match(stream, context, actions) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Dot.getMatchingExpression() { |
|
|
|
//return `!(@stream).atEnd() && (@stream).inc() && @true; |
|
|
|
return `{ !stream.atEnd() && stream.inc() && @true }; |
|
|
|
} |
|
|
|
|
|
|
|
// Begin |
|
|
|
|
|
|
|
Begin = Object.subtype(#Begin); |
|
|
@ -272,6 +360,11 @@ Begin.match(stream, context, actions) { |
|
|
|
true; |
|
|
|
} |
|
|
|
|
|
|
|
Begin.getMatchingExpression() { |
|
|
|
//return `(@stream).setLastBegin() && true; |
|
|
|
return `{ stream.setLastBegin() && @true }; |
|
|
|
} |
|
|
|
|
|
|
|
// End |
|
|
|
|
|
|
|
End = Object.subtype(#End); |
|
|
@ -281,6 +374,13 @@ End.match(stream, context, actions) { |
|
|
|
true; |
|
|
|
} |
|
|
|
|
|
|
|
End.getMatchingExpression() { |
|
|
|
//return `((@context.variables).yytext = (@stream.content)[(@stream).lastBegin..(@stream).position].unescaped()) |
|
|
|
// && true; |
|
|
|
return `{ (context.variables.yytext = stream.content[stream.lastBegin..stream.position].unescaped()) |
|
|
|
&& @true }; |
|
|
|
} |
|
|
|
|
|
|
|
// Optional (? postfix operator) |
|
|
|
|
|
|
|
Optional = Object.subtype(#Optional); |
|
|
@ -290,6 +390,11 @@ Optional.match(stream, context, actions) { |
|
|
|
true; |
|
|
|
} |
|
|
|
|
|
|
|
Optional.getMatchingExpression() { |
|
|
|
//return `(@self.expression.getMatchingExpression(stream, context, actions)) || @true; |
|
|
|
return `{ (@self.expression.getMatchingExpression()); @true }; |
|
|
|
} |
|
|
|
|
|
|
|
// Star |
|
|
|
|
|
|
|
Star = Object.subtype(#Star); |
|
|
@ -299,6 +404,10 @@ Star.match(stream, context, actions) { |
|
|
|
true; |
|
|
|
} |
|
|
|
|
|
|
|
Star.getMatchingExpression() { |
|
|
|
return `{ while (@self.expression.getMatchingExpression()) {} @true }; |
|
|
|
} |
|
|
|
|
|
|
|
// Plus |
|
|
|
|
|
|
|
Plus = Object.subtype(#Plus); |
|
|
@ -312,12 +421,23 @@ Plus.match(stream, context, actions) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Plus.getMatchingExpression() { |
|
|
|
return `{ |
|
|
|
if (@self.expression.getMatchingExpression()) { |
|
|
|
while (@self.expression.getMatchingExpression()) {} |
|
|
|
@true; |
|
|
|
} else { |
|
|
|
@false; |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
// And |
|
|
|
|
|
|
|
And = Object.subtype(#And); |
|
|
|
|
|
|
|
And.match(stream, context, actions) { |
|
|
|
position = stream.position; |
|
|
|
local position = stream.position; |
|
|
|
|
|
|
|
if (self.expression.match(stream, context, actions) == true) { |
|
|
|
stream.position = position; |
|
|
@ -327,12 +447,24 @@ And.match(stream, context, actions) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
And.getMatchingExpression() { |
|
|
|
return `{ |
|
|
|
local position = stream.position; |
|
|
|
if (@self.expression.getMatchingExpression()) { |
|
|
|
stream.position = position; |
|
|
|
@true; |
|
|
|
} else { |
|
|
|
@false; |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
// Not |
|
|
|
|
|
|
|
Not = Object.subtype(#Not); |
|
|
|
|
|
|
|
Not.match(stream, context, actions) { |
|
|
|
position = stream.position; |
|
|
|
local position = stream.position; |
|
|
|
|
|
|
|
if (self.expression.match(stream, context, actions) == true) { |
|
|
|
stream.position = position; |
|
|
@ -342,6 +474,18 @@ Not.match(stream, context, actions) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Not.getMatchingExpression() { |
|
|
|
return `{ |
|
|
|
local position = stream.position; |
|
|
|
if (@self.expression.getMatchingExpression()) { |
|
|
|
stream.position = position; |
|
|
|
@false; |
|
|
|
} else { |
|
|
|
@true; |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
// Sequence |
|
|
|
|
|
|
|
Sequence = Object.subtype(#Sequence); |
|
|
@ -354,10 +498,10 @@ Sequence._match(stream, context, actions, index) { |
|
|
|
} |
|
|
|
|
|
|
|
Sequence.match(stream, context, actions) { |
|
|
|
initialActionCount = actions.length(); |
|
|
|
startingPosition = stream.position; |
|
|
|
local initialActionCount = actions.length(); |
|
|
|
local startingPosition = stream.position; |
|
|
|
|
|
|
|
success = self._match(stream, context, actions, 0); |
|
|
|
local success = self._match(stream, context, actions, 0); |
|
|
|
|
|
|
|
if (success == false) { |
|
|
|
while (actions.length() > initialActionCount) { |
|
|
@ -369,6 +513,31 @@ Sequence.match(stream, context, actions) { |
|
|
|
success; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Sequence._getMatchingExpression(index) { |
|
|
|
if (index == self.length() - 1) { |
|
|
|
return self[index].getMatchingExpression(); |
|
|
|
} |
|
|
|
return `(@self[index].getMatchingExpression()) |
|
|
|
&& @self._getMatchingExpression(index + 1); |
|
|
|
} |
|
|
|
|
|
|
|
Sequence.getMatchingExpression() { |
|
|
|
return `{ |
|
|
|
local initialActionCount = actions.length(); |
|
|
|
local startingPosition = stream.position; |
|
|
|
({ |
|
|
|
(@self._getMatchingExpression(0)); |
|
|
|
} || { |
|
|
|
while (actions.length() > initialActionCount) { |
|
|
|
actions.pop(); |
|
|
|
} |
|
|
|
stream.position = startingPosition; |
|
|
|
@false; |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Alternation |
|
|
|
|
|
|
|
Alternation = Object.subtype(#Alternation); |
|
|
@ -384,6 +553,18 @@ Alternation.match(stream, context, actions) { |
|
|
|
return self._match(stream, context, actions, 0); |
|
|
|
} |
|
|
|
|
|
|
|
Alternation._getMatchingExpression(index) { |
|
|
|
if (index == self.length() - 1) { |
|
|
|
return self[index].getMatchingExpression(); |
|
|
|
} |
|
|
|
return `(@self[index].getMatchingExpression()) |
|
|
|
|| @self._getMatchingExpression(index + 1); |
|
|
|
} |
|
|
|
|
|
|
|
Alternation.getMatchingExpression() { |
|
|
|
return `{ @self._getMatchingExpression(0) }; |
|
|
|
} |
|
|
|
|
|
|
|
// Action |
|
|
|
|
|
|
|
Action = Object.subtype(#Action); |
|
|
@ -393,6 +574,10 @@ Action.match(stream, context, actions) { |
|
|
|
true; |
|
|
|
} |
|
|
|
|
|
|
|
Action.getMatchingExpression() { |
|
|
|
return `{ actions.push([action: @self, context: context]); @true; } |
|
|
|
} |
|
|
|
|
|
|
|
Action.execute(context) { |
|
|
|
|
|
|
|
// Declare all variables that a value is set to in the context |
|
|
@ -403,7 +588,7 @@ Action.execute(context) { |
|
|
|
} |
|
|
|
|
|
|
|
// Evaluate the parse tree and return to outer context if needed |
|
|
|
returnValue = eval(self.parseTree, env: context.variables); |
|
|
|
local returnValue = eval(self.parseTree, env: context.variables); |
|
|
|
if (context.outerContext != nil) { |
|
|
|
context.outerContext.variables[context.returnValueName] = returnValue; |
|
|
|
} |
|
|
@ -423,16 +608,28 @@ ParseTimeAction.match(stream, context, actions) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ParseTimeAction.getMatchingExpression() { |
|
|
|
return `{ (@self.action).execute(context) }; |
|
|
|
} |
|
|
|
|
|
|
|
// Assignment |
|
|
|
|
|
|
|
Assignment = Object.subtype(#Assignment); |
|
|
|
|
|
|
|
Assignment.match(stream, context, actions) { |
|
|
|
context.declareVariable(self.name); |
|
|
|
innerContext = Context.new(outerContext: context, returnValueName: self.name).init(); |
|
|
|
local innerContext = Context.new(outerContext: context, returnValueName: self.name).init(); |
|
|
|
self.rule.match(stream, innerContext, actions); |
|
|
|
} |
|
|
|
|
|
|
|
Assignment.getMatchingExpression() { |
|
|
|
return `{ |
|
|
|
context.declareVariable(@self.name); |
|
|
|
local context = Context.new(outerContext: context, returnValueName: @self.name).init(); |
|
|
|
@self.rule.getMatchingExpression(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// RuleCall |
|
|
|
|
|
|
|
RuleCall = Object.subtype(#RuleCall); |
|
|
@ -440,29 +637,72 @@ RuleCall = Object.subtype(#RuleCall); |
|
|
|
RuleCall.match(stream, context, actions) { |
|
|
|
//if (rules[self.name] == nil) { print("Trying to call undefined rule: ", self.name, "\n"); exit(); } |
|
|
|
//print("calling rule ", self.name, " | ", stream.position, "\n"); |
|
|
|
res = get(self.name).match(stream, context, actions); |
|
|
|
local res = get(self.name).match(stream, context, actions); |
|
|
|
//print("matching rule ", self.name, ": ", res, "\n"); |
|
|
|
res; |
|
|
|
} |
|
|
|
|
|
|
|
RuleCall.getMatchingExpression() { |
|
|
|
//print("Calling rule ", self.name, "\n"); |
|
|
|
//local res = `{get(@self.name).getMatchingExpression(@stream, @context, @actions).__eval__()}; |
|
|
|
|
|
|
|
//if (innerContext == nil) { |
|
|
|
`{ Invoke.new(self: self, method: @self.name, arguments: [stream, context, actions]).__eval__() }; |
|
|
|
//} else { |
|
|
|
// `{ self.rules[@self.name](stream, @innerContext, actions) }; |
|
|
|
//} |
|
|
|
|
|
|
|
//print("Pos ", stream.position, " | Called rule ", self.name, "\n"); |
|
|
|
} |
|
|
|
|
|
|
|
// NamespacedRuleCall |
|
|
|
|
|
|
|
NamespacedRuleCall = Object.subtype(#NamespacedRuleCall); |
|
|
|
|
|
|
|
NamespacedRuleCall.match(stream, context, actions) { |
|
|
|
NamespacedRuleCall.match() { |
|
|
|
with(self.namespace); |
|
|
|
res = get(self.name).match(stream, context, actions); |
|
|
|
local res = get(self.name).match(stream, context, actions); |
|
|
|
without(); |
|
|
|
res; |
|
|
|
} |
|
|
|
|
|
|
|
NamespacedRuleCall.getMatchingExpression(innerContext) { |
|
|
|
//return `{ |
|
|
|
// with(@self.namespace); |
|
|
|
// local res = get(@self.name).getMatchingExpression(@stream, @context, @actions).__eval__(); |
|
|
|
// without(); |
|
|
|
// res; |
|
|
|
//} |
|
|
|
//if (innerContext == nil) { |
|
|
|
`{ Invoke.new(self: @get(self.namespace), method: @self.name, arguments: [stream, context, actions]).__eval__() }; |
|
|
|
//} else { |
|
|
|
// `{ (@get(self.namespace)).rules[@self.name](stream, @innerContext, actions) }; |
|
|
|
//} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Definition = Object.subtype(#Definition); |
|
|
|
|
|
|
|
Grammar = Object.subtype(#Grammar); |
|
|
|
|
|
|
|
Grammar.addRulesFromNamespace(namespace) { |
|
|
|
for (key in __namespaces__[namespace].keys()) { |
|
|
|
if (key == #__nsname__) continue; |
|
|
|
self[key] = Closure.new( |
|
|
|
environment: nil, |
|
|
|
function: Lambda.new( |
|
|
|
parameters: [#stream, #context, #actions], |
|
|
|
body: __namespaces__[namespace][key].getMatchingExpression().body |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ----- Grammar of Meta Language (Minimal) ----- |
|
|
|
|
|
|
|
hcmeta = with(#HardCodedMeta); |
|
|
|
with(#HardCodedMeta); |
|
|
|
|
|
|
|
hcmeta.metaStatement = |
|
|
|
metaStatement = |
|
|
|
Alternation.new() |
|
|
|
.push(Sequence.new() |
|
|
|
.push(Assignment.new(name: #b, rule: RuleCall.new(name: #block))) |
|
|
@ -477,7 +717,7 @@ hcmeta.metaStatement = |
|
|
|
.push(Action.new(parseTree: `{ e; })) |
|
|
|
); |
|
|
|
|
|
|
|
hcmeta.metaExpression = |
|
|
|
metaExpression = |
|
|
|
Alternation.new(id: 1234) |
|
|
|
.push(Sequence.new() |
|
|
|
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #metaPrimary))) |
|
|
@ -509,7 +749,7 @@ hcmeta.metaExpression = |
|
|
|
.push(Action.new(parseTree: `{ pf; })) |
|
|
|
); |
|
|
|
|
|
|
|
hcmeta.metaPostfix = |
|
|
|
metaPostfix = |
|
|
|
Sequence.new() |
|
|
|
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #metaPrimary))) |
|
|
|
.push(Star.new(expression: Alternation.new() |
|
|
@ -537,7 +777,7 @@ hcmeta.metaPostfix = |
|
|
|
)) |
|
|
|
.push(Action.new(parseTree: `{ p; })); |
|
|
|
|
|
|
|
hcmeta.args = |
|
|
|
args = |
|
|
|
Sequence.new() |
|
|
|
.push(RuleCall.new(name: #lparen)) |
|
|
|
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #mklist))) |
|
|
@ -573,23 +813,23 @@ hcmeta.args = |
|
|
|
.push(RuleCall.new(name: #rparen)) |
|
|
|
.push(Action.new(parseTree: `{ a; })); |
|
|
|
|
|
|
|
hcmeta.mklist = Action.new(parseTree: `{ Object.new(); }); |
|
|
|
mklist = Action.new(parseTree: `{ Object.new(); }); |
|
|
|
|
|
|
|
hcmeta.metaPrimary = |
|
|
|
metaPrimary = |
|
|
|
Alternation.new() |
|
|
|
.push(RuleCall.new(name: #nil)) |
|
|
|
.push(RuleCall.new(name: #number)) |
|
|
|
.push(RuleCall.new(name: #metaVar)) |
|
|
|
.push(RuleCall.new(name: #metaSubExpr)); |
|
|
|
|
|
|
|
hcmeta.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; })); |
|
|
|
.push(Action.new(parseTree: `{ e; })); |
|
|
|
|
|
|
|
hcmeta.block = |
|
|
|
block = |
|
|
|
Sequence.new() |
|
|
|
.push(RuleCall.new(name: #lbrace)) |
|
|
|
.push(Assignment.new(name: #b, rule: RuleCall.new(name: #mklist))) |
|
|
@ -603,7 +843,7 @@ hcmeta.block = |
|
|
|
.push(RuleCall.new(name: #rbrace)) |
|
|
|
.push(Action.new(parseTree: `{ Block.new(body: b); })); |
|
|
|
|
|
|
|
hcmeta.number = |
|
|
|
number = |
|
|
|
Alternation.new() |
|
|
|
.push(Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "-")) |
|
|
@ -620,7 +860,7 @@ hcmeta.number = |
|
|
|
.push(Action.new(parseTree: `{ n })) |
|
|
|
); |
|
|
|
|
|
|
|
hcmeta.unsign = |
|
|
|
unsign = |
|
|
|
Sequence.new() |
|
|
|
.push(Begin.new()) |
|
|
|
.push(Plus.new(expression: RuleCall.new(name: #digit))) |
|
|
@ -628,12 +868,12 @@ hcmeta.unsign = |
|
|
|
.push(RuleCall.new(name: #ws)) |
|
|
|
.push(Action.new(parseTree: `{ yytext.asInteger(10); })); |
|
|
|
|
|
|
|
hcmeta.metaVar = |
|
|
|
metaVar = |
|
|
|
Sequence.new() |
|
|
|
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId))) |
|
|
|
.push(Action.new(parseTree: `{ GetVar.new(name: i); })); |
|
|
|
|
|
|
|
hcmeta.metaId = |
|
|
|
metaId = |
|
|
|
Sequence.new() |
|
|
|
.push(Begin.new()) |
|
|
|
.push(RuleCall.new(name: #letter)) |
|
|
@ -642,52 +882,52 @@ hcmeta.metaId = |
|
|
|
.push(RuleCall.new(name: #ws)) |
|
|
|
.push(Action.new(parseTree: `{ intern(yytext); })); |
|
|
|
|
|
|
|
hcmeta.digit = CharacterClass.new(value: "0-9"); |
|
|
|
hcmeta.letter = CharacterClass.new(value: "A-Za-z_"); |
|
|
|
hcmeta.alnum = |
|
|
|
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)); |
|
|
|
hcmeta.nil = |
|
|
|
nil = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "nil")) |
|
|
|
.push(Not.new(expression: RuleCall.new(name: #alnum))) |
|
|
|
.push(RuleCall.new(name: #ws)); |
|
|
|
|
|
|
|
hcmeta.semi = Sequence.new().push(StringLiteral.new(string: ";" )).push(RuleCall.new(name: #ws)); |
|
|
|
hcmeta.comma = Sequence.new().push(StringLiteral.new(string: "," )).push(RuleCall.new(name: #ws)); |
|
|
|
hcmeta.lparen = Sequence.new().push(StringLiteral.new(string: "(" )).push(RuleCall.new(name: #ws)); |
|
|
|
hcmeta.rparen = Sequence.new().push(StringLiteral.new(string: ")" )).push(RuleCall.new(name: #ws)); |
|
|
|
hcmeta.lbrak = Sequence.new().push(StringLiteral.new(string: "[" )).push(RuleCall.new(name: #ws)); |
|
|
|
hcmeta.rbrak = Sequence.new().push(StringLiteral.new(string: "]" )).push(RuleCall.new(name: #ws)); |
|
|
|
hcmeta.lbrace = Sequence.new().push(StringLiteral.new(string: "{" )).push(RuleCall.new(name: #ws)); |
|
|
|
hcmeta.rbrace = Sequence.new().push(StringLiteral.new(string: "}" )).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)); |
|
|
|
|
|
|
|
hcmeta.assign = |
|
|
|
assign = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "=")) |
|
|
|
.push(Not.new(expression: CharacterClass.new(value: "="))) |
|
|
|
.push(RuleCall.new(name: #ws)); |
|
|
|
hcmeta.dot = |
|
|
|
dot = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: ".")) |
|
|
|
.push(Not.new(expression: CharacterClass.new(value: "."))) |
|
|
|
.push(RuleCall.new(name: #ws)); |
|
|
|
hcmeta.colon = |
|
|
|
colon = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: ":")) |
|
|
|
.push(Not.new(expression: CharacterClass.new(value: ":"))) |
|
|
|
.push(RuleCall.new(name: #ws)); |
|
|
|
|
|
|
|
hcmeta.end_of_file = Not.new(expression: Dot.new()); |
|
|
|
end_of_file = Not.new(expression: Dot.new()); |
|
|
|
|
|
|
|
hcmeta.end_of_line = |
|
|
|
end_of_line = |
|
|
|
Alternation.new() |
|
|
|
.push(StringLiteral.new(string: "\r\n")) |
|
|
|
.push(StringLiteral.new(string: "\n")) |
|
|
|
.push(StringLiteral.new(string: "\r")); |
|
|
|
|
|
|
|
hcmeta.comment = |
|
|
|
comment = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "//")) |
|
|
|
.push(Star.new(expression: |
|
|
@ -697,13 +937,13 @@ hcmeta.comment = |
|
|
|
)) |
|
|
|
.push(RuleCall.new(name: #end_of_line)); |
|
|
|
|
|
|
|
hcmeta.space = |
|
|
|
space = |
|
|
|
Alternation.new() |
|
|
|
.push(StringLiteral.new(string: " ")) |
|
|
|
.push(StringLiteral.new(string: "\t")) |
|
|
|
.push(RuleCall.new(name: #end_of_line)); |
|
|
|
|
|
|
|
hcmeta.ws = |
|
|
|
ws = |
|
|
|
Star.new(expression: Alternation.new() |
|
|
|
.push(RuleCall.new(name: #space)) |
|
|
|
.push(RuleCall.new(name: #comment)) |
|
|
@ -711,9 +951,9 @@ hcmeta.ws = |
|
|
|
|
|
|
|
// ----- Grammar of Grammars ----- |
|
|
|
|
|
|
|
hcpeg = with(#HardCodedPeg); |
|
|
|
with(#HardCodedPeg); |
|
|
|
|
|
|
|
hcpeg.grammar = |
|
|
|
grammar = |
|
|
|
Sequence.new() |
|
|
|
.push(RuleCall.new(name: #ws)) |
|
|
|
.push(Plus.new(expression: Sequence.new() |
|
|
@ -722,7 +962,7 @@ hcpeg.grammar = |
|
|
|
)) |
|
|
|
.push(RuleCall.new(name: #end_of_file)); |
|
|
|
|
|
|
|
hcpeg.definition = |
|
|
|
definition = |
|
|
|
Sequence.new() |
|
|
|
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #identifier))) |
|
|
|
.push(RuleCall.new(name: #assign)) |
|
|
@ -730,7 +970,7 @@ hcpeg.definition = |
|
|
|
.push(Optional.new(expression: RuleCall.new(name: #semi))) |
|
|
|
.push(Action.new(parseTree: `{ Definition.new(name: i, expression: e); })); |
|
|
|
|
|
|
|
hcpeg.expression = |
|
|
|
expression = |
|
|
|
Alternation.new() |
|
|
|
.push(Sequence.new() |
|
|
|
.push(Assignment.new(name: #s, rule: RuleCall.new(name: #sequence))) |
|
|
@ -748,7 +988,7 @@ hcpeg.expression = |
|
|
|
.push(Action.new(parseTree: `{ s1; })) |
|
|
|
); |
|
|
|
|
|
|
|
hcpeg.sequence = |
|
|
|
sequence = |
|
|
|
Sequence.new() |
|
|
|
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #prefix))) |
|
|
|
.push(Action.new(parseTree: `{ p = Sequence.new().push(p); })) |
|
|
@ -758,7 +998,7 @@ hcpeg.sequence = |
|
|
|
)) |
|
|
|
.push(Action.new(parseTree: `{ p; })); |
|
|
|
|
|
|
|
hcpeg.prefix = |
|
|
|
prefix = |
|
|
|
Alternation.new() |
|
|
|
.push(Sequence.new() |
|
|
|
.push(RuleCall.new(name: #and)) |
|
|
@ -781,7 +1021,7 @@ hcpeg.prefix = |
|
|
|
) |
|
|
|
); |
|
|
|
|
|
|
|
hcpeg.suffix = |
|
|
|
suffix = |
|
|
|
Sequence.new() |
|
|
|
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #primary))) |
|
|
|
.push(Optional.new(expression: Alternation.new() |
|
|
@ -800,7 +1040,7 @@ hcpeg.suffix = |
|
|
|
)) |
|
|
|
.push(Action.new(parseTree: `{ p; })); |
|
|
|
|
|
|
|
hcpeg.primary = |
|
|
|
primary = |
|
|
|
Alternation.new() |
|
|
|
.push(Sequence.new() |
|
|
|
.push(Assignment.new(name: #i1, rule: RuleCall.new(name: #identifier))) |
|
|
@ -845,7 +1085,7 @@ hcpeg.primary = |
|
|
|
.push(Action.new(parseTree: `{ End.new(); })) |
|
|
|
); |
|
|
|
|
|
|
|
hcpeg.identifier = |
|
|
|
identifier = |
|
|
|
Sequence.new() |
|
|
|
.push(Begin.new()) |
|
|
|
.push(CharacterClass.new(value: "-a-zA-Z_")) |
|
|
@ -854,7 +1094,7 @@ hcpeg.identifier = |
|
|
|
.push(RuleCall.new(name: #ws)) |
|
|
|
.push(Action.new(parseTree: `{ intern(yytext); })); |
|
|
|
|
|
|
|
hcpeg.ruleCall = |
|
|
|
ruleCall = |
|
|
|
Alternation.new() |
|
|
|
.push(Sequence.new() |
|
|
|
.push(Assignment.new(name: #n, rule: RuleCall.new(name: #identifier))) |
|
|
@ -867,7 +1107,7 @@ hcpeg.ruleCall = |
|
|
|
.push(Action.new(parseTree: `{ RuleCall.new(name: i); })) |
|
|
|
); |
|
|
|
|
|
|
|
hcpeg.literal = |
|
|
|
literal = |
|
|
|
Alternation.new() |
|
|
|
.push(Sequence.new() |
|
|
|
.push(CharacterClass.new(value: "\'")) |
|
|
@ -894,7 +1134,7 @@ hcpeg.literal = |
|
|
|
.push(Action.new(parseTree: `{ StringLiteral.new(string: yytext); })) |
|
|
|
); |
|
|
|
|
|
|
|
hcpeg.class = |
|
|
|
class = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "[")) |
|
|
|
.push(Begin.new()) |
|
|
@ -907,7 +1147,7 @@ hcpeg.class = |
|
|
|
.push(RuleCall.new(name: #ws)) |
|
|
|
.push(Action.new(parseTree: `{ CharacterClass.new(value: yytext); })); |
|
|
|
|
|
|
|
hcpeg.range = |
|
|
|
range = |
|
|
|
Alternation.new() |
|
|
|
.push(Sequence.new() |
|
|
|
.push(RuleCall.new(name: #char)) |
|
|
@ -918,7 +1158,7 @@ hcpeg.range = |
|
|
|
RuleCall.new(name: #char) |
|
|
|
); |
|
|
|
|
|
|
|
hcpeg.char = |
|
|
|
char = |
|
|
|
Alternation.new() |
|
|
|
.push(Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "\\")) |
|
|
@ -940,47 +1180,47 @@ hcpeg.char = |
|
|
|
.push(Dot.new()) |
|
|
|
); |
|
|
|
|
|
|
|
hcpeg.action = |
|
|
|
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); })); |
|
|
|
|
|
|
|
hcpeg.bar = Sequence.new().push(StringLiteral.new(string: "|")).push(RuleCall.new(name: #ws)); |
|
|
|
hcpeg.not = Sequence.new().push(StringLiteral.new(string: "!")).push(RuleCall.new(name: #ws)); |
|
|
|
hcpeg.query = Sequence.new().push(StringLiteral.new(string: "?")).push(RuleCall.new(name: #ws)); |
|
|
|
hcpeg.begin = Sequence.new().push(StringLiteral.new(string: "<")).push(RuleCall.new(name: #ws)); |
|
|
|
hcpeg.end = Sequence.new().push(StringLiteral.new(string: ">")).push(RuleCall.new(name: #ws)); |
|
|
|
hcpeg.tilde = Sequence.new().push(StringLiteral.new(string: "~")).push(RuleCall.new(name: #ws)); |
|
|
|
hcpeg.rpercent = Sequence.new().push(StringLiteral.new(string: "%}")).push(RuleCall.new(name: #ws)); |
|
|
|
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)); |
|
|
|
|
|
|
|
hcpeg.ccolon = Sequence.new().push(StringLiteral.new(string: "::")).push(RuleCall.new(name: #ws)); |
|
|
|
ccolon = Sequence.new().push(StringLiteral.new(string: "::")).push(RuleCall.new(name: #ws)); |
|
|
|
|
|
|
|
hcpeg.and = |
|
|
|
and = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "&")) |
|
|
|
.push(Not.new(expression: CharacterClass.new(value: "&="))) |
|
|
|
.push(RuleCall.new(name: #ws)); |
|
|
|
hcpeg.plus = |
|
|
|
plus = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "+")) |
|
|
|
.push(Not.new(expression: CharacterClass.new(value: "+="))) |
|
|
|
.push(RuleCall.new(name: #ws)); |
|
|
|
hcpeg.star = |
|
|
|
star = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "*")) |
|
|
|
.push(Not.new(expression: CharacterClass.new(value: "="))) |
|
|
|
.push(RuleCall.new(name: #ws)); |
|
|
|
|
|
|
|
hcpeg.end_of_file = Not.new(expression: Dot.new()); |
|
|
|
end_of_file = Not.new(expression: Dot.new()); |
|
|
|
|
|
|
|
hcpeg.end_of_line = |
|
|
|
end_of_line = |
|
|
|
Alternation.new() |
|
|
|
.push(StringLiteral.new(string: "\r\n")) |
|
|
|
.push(StringLiteral.new(string: "\n")) |
|
|
|
.push(StringLiteral.new(string: "\r")); |
|
|
|
|
|
|
|
hcpeg.comment = |
|
|
|
comment = |
|
|
|
Sequence.new() |
|
|
|
.push(StringLiteral.new(string: "#")) |
|
|
|
.push(Star.new(expression: |
|
|
@ -990,13 +1230,13 @@ hcpeg.comment = |
|
|
|
)) |
|
|
|
.push(RuleCall.new(name: #end_of_line)); |
|
|
|
|
|
|
|
hcpeg.space = |
|
|
|
space = |
|
|
|
Alternation.new() |
|
|
|
.push(StringLiteral.new(string: " ")) |
|
|
|
.push(StringLiteral.new(string: "\t")) |
|
|
|
.push(RuleCall.new(name: #end_of_line)); |
|
|
|
|
|
|
|
hcpeg.ws = |
|
|
|
ws = |
|
|
|
Star.new(expression: Alternation.new() |
|
|
|
.push(RuleCall.new(name: #space)) |
|
|
|
.push(RuleCall.new(name: #comment)) |
|
|
@ -1004,11 +1244,21 @@ hcpeg.ws = |
|
|
|
|
|
|
|
// ----- Main ----- |
|
|
|
|
|
|
|
stream = newStream(readfile("rawminproto.leg")); |
|
|
|
context = Context.new(outerContext: nil).init(); |
|
|
|
actions = []; |
|
|
|
without(all: 1); |
|
|
|
|
|
|
|
HardCodedPeg = Grammar.new(); |
|
|
|
HardCodedMeta = Grammar.new(); |
|
|
|
|
|
|
|
HardCodedPeg.addRulesFromNamespace(#HardCodedPeg); |
|
|
|
HardCodedMeta.addRulesFromNamespace(#HardCodedMeta); |
|
|
|
|
|
|
|
print("Matching rawminproto.leg : ", grammar.match(stream, context, actions), "\n"); |
|
|
|
HardCodedPeg.__delegate__ = HardCodedMeta; |
|
|
|
|
|
|
|
global stream = newStream(readfile("rawminproto.leg")); |
|
|
|
global context = Context.new(outerContext: nil).init(); |
|
|
|
global actions = []; |
|
|
|
|
|
|
|
print("Matching rawminproto.leg : ", HardCodedPeg.grammar(stream, context, actions), "\n"); |
|
|
|
|
|
|
|
with(#metaLanguage); |
|
|
|
for (actionAndContext in actions) { |
|
|
@ -1018,29 +1268,11 @@ without(#metaLanguage); |
|
|
|
println("\n--------- META ---------\n\n"); |
|
|
|
println(__namespaces__.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); |
|
|
|
|
|
|
|
stream = newStream(readfile("rawgrammar.leg")); |
|
|
|
context = Context.new(outerContext: nil).init(); |
|
|
|
actions = []; |
|
|
|
global stream = newStream(readfile("rawgrammar.leg")); |
|
|
|
global context = Context.new(outerContext: nil).init(); |
|
|
|
global actions = []; |
|
|
|
|
|
|
|
print("Matching : ", grammar.match(stream, context, actions), "\n"); |
|
|
|
print("Matching rawgrammar.leg : ", HardCodedPeg.grammar(stream, context, actions), "\n"); |
|
|
|
|
|
|
|
// Execute all actions after all matching |
|
|
|
|
|
|
@ -1055,17 +1287,20 @@ println("\n--------- PEG ---------\n\n"); |
|
|
|
println(__namespaces__.peg); |
|
|
|
|
|
|
|
// Circularity test |
|
|
|
without(all: 1); |
|
|
|
|
|
|
|
with(#metaLanguage); |
|
|
|
with(#peg); |
|
|
|
peg = Grammar.new(); |
|
|
|
metaLanguage = Grammar.new(); |
|
|
|
|
|
|
|
peg.addRulesFromNamespace(#peg); |
|
|
|
metaLanguage.addRulesFromNamespace(#metaLanguage); |
|
|
|
|
|
|
|
stream2 = newStream(readfile("rawminproto.leg")); |
|
|
|
//stream2 = newStream("a = b:c::d { print(a[b].c); }"); |
|
|
|
context2 = Context.new(outerContext: nil).init(); |
|
|
|
actions2 = []; |
|
|
|
peg.__delegate__ = metaLanguage; |
|
|
|
|
|
|
|
print("\nMatching : ", grammar.match(stream2, context2, actions2), "\n"); |
|
|
|
global stream2 = newStream(readfile("rawminproto.leg")); |
|
|
|
global context2 = Context.new(outerContext: nil).init(); |
|
|
|
global actions2 = []; |
|
|
|
|
|
|
|
print("\nMatching : ", peg.grammar(stream2, context2, actions2), "\n"); |
|
|
|
|
|
|
|
with(#metaLanguageCircular); |
|
|
|
|
|
|
@ -1077,11 +1312,11 @@ without(#metaLanguageCircular); |
|
|
|
println("\n--------- CIRCULAR META ---------\n\n"); |
|
|
|
println(__namespaces__.metaLanguageCircular); |
|
|
|
|
|
|
|
stream2 = newStream(readfile("rawgrammar.leg")); |
|
|
|
context2 = Context.new(outerContext: nil).init(); |
|
|
|
actions2 = []; |
|
|
|
global stream2 = newStream(readfile("rawgrammar.leg")); |
|
|
|
global context2 = Context.new(outerContext: nil).init(); |
|
|
|
global actions2 = []; |
|
|
|
|
|
|
|
print("\nMatching : ", grammar.match(stream2, context2, actions2), "\n"); |
|
|
|
print("\nMatching : ", peg.grammar(stream2, context2, actions2), "\n"); |
|
|
|
|
|
|
|
with(#pegCircular); |
|
|
|
|
|
|
@ -1093,10 +1328,8 @@ without(#pegCircular); |
|
|
|
println("\n--------- CIRCULAR PEG ---------\n\n"); |
|
|
|
println(__namespaces__.pegCircular); |
|
|
|
|
|
|
|
without(all: 1); |
|
|
|
|
|
|
|
compareGrammars(grammar1, grammar2) { |
|
|
|
success = 1; |
|
|
|
local success = 1; |
|
|
|
for (key in __namespaces__[grammar1].keys()) { |
|
|
|
if (key == #__nsname__) continue; |
|
|
|
|
|
|
|