Ver a proveniência

Minimal grammar parsing

master
MaximeBarniaudy há 1 ano
ascendente
cometimento
4eeaa54367
1 ficheiros alterados com 606 adições e 192 eliminações
  1. +606
    -192
      grammar_parser.meta

+ 606
- 192
grammar_parser.meta Ver ficheiro

@ -15,7 +15,7 @@ Object.subtype(name) { self.new(__name__: name) }
Stream = Object.subtype(#Stream);
newStream(string) {
self = Stream.new(
let self = Stream.new(
content: string,
position: 0,
limit: len(string)
@ -30,7 +30,7 @@ Stream.inc() { !self.atEnd() && { self.position = self.position + 1; } }
Stream.next() {
!self.atEnd() && {
c = self.content[self.position];
let c = self.content[self.position];
self.position = self.position + 1;
c;
}
@ -42,7 +42,17 @@ Stream.setLastBegin = () { self.lastBegin = self.position; };
Context = Object.subtype(#Context);
Context.init() { self.variables = []; self; }
Context.declareVariable(var) { self.variables[var] = nil }
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 -----
@ -50,11 +60,11 @@ Context.declareVariable(var) { self.variables[var] = nil }
StringLiteral = Object.subtype(#StringLiteral);
StringLiteral.match(stream, context, actions) {
StringLiteral.match(stream, context, rules, actions) {
n = len(self.string);
i = 0;
success = 1;
let n = len(self.string);
let i = 0;
let success = 1;
if (stream.atEnd()) { success = 0; }
startPosition = stream.position;
@ -75,12 +85,12 @@ StringLiteral.match(stream, context, actions) {
CharacterClass = Object.subtype(#CharacterClass);
CharacterClass.match(stream, context, actions) {
CharacterClass.match(stream, context, rules, actions) {
classLength = len(self.value);
i = 0;
prevChar = nil;
success = 0;
let classLength = len(self.value);
let i = 0;
let prevChar = nil;
let success = 0;
while (i < classLength && success == 0 && !stream.atEnd()) {
@ -98,12 +108,12 @@ CharacterClass.match(stream, context, actions) {
// [a-z] case
if (i+1 < classLength) {
// println("[a-z] case");
rangeStart = charValue(prevChar);
rangeEnd = charValue(self.value[i+1]);
rangeStart = prevChar;
rangeEnd = self.value[i+1];
// print("Range Start: ", rangeStart, " | ");
// print("Range End: ", rangeEnd, "\n");
if (charValue(stream.peek()) >= rangeStart
&& charValue(stream.peek()) <= rangeEnd
if (stream.peek() >= rangeStart
&& stream.peek() <= rangeEnd
) {
success = 1;
}
@ -141,7 +151,7 @@ CharacterClass.match(stream, context, actions) {
Dot = Object.subtype(#Dot);
Dot.match(stream, context, actions) {
Dot.match(stream, context, rules, actions) {
if (!stream.atEnd()) {
stream.inc();
1;
@ -154,7 +164,7 @@ Dot.match(stream, context, actions) {
Begin = Object.subtype(#Begin);
Begin.match(stream, context, actions) {
Begin.match(stream, context, rules, actions) {
stream.setLastBegin();
1;
}
@ -163,8 +173,8 @@ Begin.match(stream, context, actions) {
End = Object.subtype(#End);
End.match(stream, context, actions) {
context.input = stream.string[stream.lastBegin..stream.position];
End.match(stream, context, rules, actions) {
context.variables.yytext = stream.content[stream.lastBegin..stream.position];
1;
}
@ -172,8 +182,18 @@ End.match(stream, context, actions) {
Optional = Object.subtype(#Optional);
Optional.match(stream, context, actions) {
self.expression.match(stream, context, actions);
Optional.match(stream, context, rules, actions) {
let initialActionCount = actions.length();
let startingPosition = stream.position;
let success = self.expression.match(stream, context, rules, actions);
if (success == 0) {
while (actions.length() > initialActionCount) {
actions.pop();
}
stream.position = startingPosition;
}
1;
}
@ -181,8 +201,8 @@ Optional.match(stream, context, actions) {
Star = Object.subtype(#Star);
Star.match(stream, context, actions) {
while (self.expression.match(stream, context, actions) == 1) {}
Star.match(stream, context, rules, actions) {
while (self.expression.match(stream, context, rules, actions) == 1) {}
1;
}
@ -190,9 +210,9 @@ Star.match(stream, context, actions) {
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) {}
Plus.match(stream, context, rules, actions) {
if (self.expression.match(stream, context, rules, actions) == 1) {
while (self.expression.match(stream, context, rules, actions) == 1) {}
1;
} else {
0;
@ -203,10 +223,10 @@ Plus.match(stream, context, actions) {
And = Object.subtype(#And);
And.match(stream, context, actions) {
position = stream.position;
And.match(stream, context, rules, actions) {
let position = stream.position;
if (self.expression.match(stream, context, actions) == 1) {
if (self.expression.match(stream, context, rules, actions) == 1) {
stream.position = position;
1;
} else {
@ -218,10 +238,10 @@ And.match(stream, context, actions) {
Not = Object.subtype(#Not);
Not.match(stream, context, actions) {
position = stream.position;
Not.match(stream, context, rules, actions) {
let position = stream.position;
if (self.expression.match(stream, context, actions) == 1) {
if (self.expression.match(stream, context, rules, actions) == 1) {
stream.position = position;
0;
} else {
@ -233,11 +253,11 @@ Not.match(stream, context, actions) {
Sequence = Object.subtype(#Sequence);
Sequence.match(stream, context, actions) {
i = 0;
match = 1;
Sequence.match(stream, context, rules, actions) {
let i = 0;
let match = 1;
while (i < self.length() && match == 1) {
match = self[i].match(stream, context, actions);
match = self[i].match(stream, context, rules, actions);
i = i + 1;
}
match;
@ -247,13 +267,13 @@ Sequence.match(stream, context, actions) {
Alternation = Object.subtype(#Alternation);
Alternation.match(stream, context, actions) {
i = 0;
success = 0;
Alternation.match(stream, context, rules, actions) {
let i = 0;
let success = 0;
while (i < self.length() && success == 0) {
initialActionCount = actions.length();
startingPosition = stream.position;
success = self[i].match(stream, context, actions);
let initialActionCount = actions.length();
let startingPosition = stream.position;
success = self[i].match(stream, context, rules, actions);
if (success == 0) {
while (actions.length() > initialActionCount) {
@ -263,7 +283,6 @@ Alternation.match(stream, context, actions) {
}
i = i + 1;
print(i, " | ", success, " | ", self.length(), "\n");
}
success;
}
@ -272,25 +291,24 @@ Alternation.match(stream, context, actions) {
Action = Object.subtype(#Action);
Action.match(stream, context, actions) {
actions.push(self);
self.context = context;
Action.match(stream, context, rules, actions) {
actions.push([action: self, context: context]);
1;
}
Action.execute() {
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") {
self.context.declareVariable(statement.name);
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;
returnValue = eval(self.parseTree, env: context.variables);
if (context.outerContext != nil) {
context.outerContext.variables[context.returnValueName] = returnValue;
}
}
@ -299,52 +317,468 @@ Action.execute() {
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);
Assignment.match(stream, context, rules, actions) {
context.declareVariable(self.name);
innerContext = Context.new(outerContext: context, returnValueName: self.name).init();
self.rule.match(stream, innerContext, rules, actions);
}
// ----- Grammar of Grammars -----
// RuleCall
// Whitespace
RuleCall = Object.subtype(#RuleCall);
// - = ( space | comment )*
// space = ' ' | '\t' | end-of-line
// comment = '#' ( !end-of-line . )* end-of-line
// end-of-line = '\r\n' | '\n' | '\r'
// end-of-file = !.
RuleCall.match(stream, context, rules, actions) {
rules[self.name].match(stream, context, rules, actions);
}
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"));
// ----- Grammar of Grammars -----
comment = Sequence.new()
.push(StringLiteral.new(string: "#"))
.push(Star.new(expression:
Sequence.new()
.push(Not.new(expression: end_of_line))
rules = [];
// grammar = - g:mklist
// ( d:definition { Object_push(g, d); }
// ) + end-of-file { printTree(g); }
rules.grammar = Sequence.new()
.push(RuleCall.new(name: #ws))
.push(Assignment.new(name: #g, rule: RuleCall.new(name: #mklist)))
.push(Plus.new(expression: Sequence.new()
.push(Assignment.new(name: #d, rule: RuleCall.new(name: #definition)))
.push(Action.new(parseTree: `{ g[d.name] = d.expression; }))
))
.push(RuleCall.new(name: #end_of_file))
.push(Action.new(parseTree: `{ print(g, full: 1) }));
Definition = Object.subtype(#Definition);
// definition = i:identifier ASSIGN e:expression SEMI? { newDefinition(i, e); }
rules.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 = s1:sequence ( BAR s2:sequence { s1 = newAlternation(s1, s2); }
// ) * { s1; }
rules.expression = 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 = p:prefix
// ( q:prefix { p = newSequence(p, q); }
// ) * { p; }
rules.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 = AND action
// |
// ( AND s:suffix { newAnd(s); }
// | NOT s:suffix { newNot(s); }
// | s:suffix { s; }
// )
rules.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 = p:primary
// ( QUERY { p = newOptional(p); }
// | STAR { p = newStar(p); }
// | PLUS { p = newPlus(p); }
// ) ? { p; }
rules.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 = i1:identifier COLON i2:ruleCallIdent !ASSIGN { newAssignment(i1, i2); }
// | i:ruleCallIdent !ASSIGN { i; }
// | LPAREN e:expression RPAREN { e; }
// | l:literal { l; }
// | c:class { c; }
// | DOT { newDot(); }
// | a:action { a; }
// | BEGIN { newBegin(); }
// | END { newEnd(); }
rules.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: #ruleCallIdent)))
.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: #ruleCallIdent)))
.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 = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { newStringEscaped(yytext); }
rules.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: `{ yytext }));
// ruleCallIdent = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { newIdentifier(yytext); }
rules.ruleCallIdent = 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: `{ RuleCall.new(intern(yytext)); }));
// literal = ['] < ( !['] char )* > ['] - { newStringEscaped(yytext); }
// | ["] < ( !["] char )* > ["] - { newStringEscaped(yytext); }
rules.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(value: 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(value: yytext); }))
);
// class = '[' < ( !']' range )* > ']' - { newCharacterClass(yytext); }
rules.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 = char '-' char | char
rules.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 = '\\' [abefnrtv'"\[\]\\]
// | '\\' [0-3][0-7][0-7]
// | '\\' [0-7][0-7]?
// | !'\\' .
rules.char = Alternation.new()
.push(Sequence.new()
.push(StringLiteral.new(string: "\\"))
.push(Alternation.new()
.push(CharacterClass.new(value: "abefnrtv\'[]\\"))
.push(CharacterClass.new(value: '\"')) // I hate this
)
)
.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())
))
.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)
);
);
// action = m:metaBlock - { newAction(m); }
rules.action = Sequence.new()
.push(Assignment.new(name: #m, rule: RuleCall.new(name: #metaBlock)))
.push(RuleCall.new(name: #ws))
.push(Action.new(parseTree: `{ Action.new(parseTree: m); }));
// metaStatement = b:metaBlock { newBlock(b); }
// | e:metaExpression SEMI { e; }
rules.metaStatement = Alternation.new()
.push(Sequence.new()
.push(Assignment.new(name: #b, rule: RuleCall.new(name: #metaBlock)))
.push(Action.new(parseTree: `{ Block.new(b); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression)))
.push(RuleCall.new(name: #semi))
.push(Action.new(parseTree: `{ e; }))
);
// metaExpression = p:metaPrimary
// ( DOT i:metaId ASSIGN e:metaExpression # { $$ = newSetProp(p, i, e) }
// | LBRAK i:metaExpression RBRAK ASSIGN e:metaExpression # { $$ = newSetArray(p, i, e) }
// )
// | i:metaId ASSIGN e:metaExpression { newSetVar(i, e); }
// | pf:metaPostfix { pf; }
rules.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(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, expr: e); }))
)
.push(Sequence.new()
.push(Assignment.new(name: #pf, rule: RuleCall.new(name: #metaPostfix)))
.push(Action.new(parseTree: `{ pf; }))
);
// metaPostfix = p:metaPrimary
// ( a:args !ASSIGN { p = newCall(p, a); }
// ) * { p; }
rules.metaPostfix = Sequence.new()
.push(Assignment.new(name: #p, rule: RuleCall.new(name: #metaPrimary)))
.push(Star.new(expression: Sequence.new()
.push(Assignment.new(name: #a, rule: RuleCall.new(name: #args)))
.push(Not.new(expression: RuleCall.new(name: #assign)))
.push(Action.new(parseTree: `{ p = Call.new(function: p, arguments: a); }))
))
.push(Action.new(parseTree: `{ p; }));
// args = LPAREN a:mklist
// (
// ( k:metaId COLON e:metaExpression { Object_put(a, k, e); }
// | e:metaExpression { Object_push(a, e); }
// )
// ( COMMA
// ( k:metaId COLON e:metaExpression { Object_put(a, k, e); }
// | e:metaExpression { Object_push(a, e); }
// )
// ) *
// ) ? RPAREN { a; }
rules.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 = { new(pObject); }
// !!!!! TODO: ADD IMPLICIT RETURN !!!!!
// metaPrimary = nil | metaVar | metaSubExpr
// !!!!! CONVERTING TO THIS FOR NOW: !!!!!
// metaPrimary = nil | x:metaVar | x:metaSubExpr {x;}
// metaSubExpr = LPAREN e:metaExpression RPAREN { e; }
rules.mklist = Action.new(parseTree: `{ Object.new(); });
rules.metaPrimary = Alternation.new()
.push(RuleCall.new(name: #nil))
.push(RuleCall.new(name: #metaVar))
.push(RuleCall.new(name: #metaSubExpr));
//.push(Assignment.new(name: #x, rule: RuleCall.new(name: #metaVar)))
//.push(Assignment.new(name: #x, rule: RuleCall.new(name: #metaSubExpr)))
//.push(Action.new(parseTree: `{ x; }));
rules.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; }));
// metaBlock = LBRACE b:mklist
// ( e:metaStatement { b.push(e); }
// ) * RBRACE { b; }
rules.metaBlock = 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: `{ b; }));
// metaVar = i:metaId { newGetVar(i); }
// metaId = < LETTER ALNUM* > - { intern(yytext); }
rules.metaVar = Sequence.new()
.push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId)))
.push(Action.new(parseTree: `{ GetVar.new(name: i); }));
rules.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); }));
// Literal Terminators
Terminators = [];
// BAR = '|' -
// NOT = '!' -
// QUERY = '?' -
@ -353,23 +787,28 @@ Terminators = [];
// 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);
rules.bar = Sequence.new().push(StringLiteral.new(string: "|")).push(RuleCall.new(name: #ws));
rules.not = Sequence.new().push(StringLiteral.new(string: "!")).push(RuleCall.new(name: #ws));
rules.query = Sequence.new().push(StringLiteral.new(string: "?")).push(RuleCall.new(name: #ws));
rules.begin = Sequence.new().push(StringLiteral.new(string: "<")).push(RuleCall.new(name: #ws));
rules.end = Sequence.new().push(StringLiteral.new(string: ">")).push(RuleCall.new(name: #ws));
rules.tilde = Sequence.new().push(StringLiteral.new(string: "~")).push(RuleCall.new(name: #ws));
rules.rpercent = Sequence.new().push(StringLiteral.new(string: "%}")).push(RuleCall.new(name: #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);
rules.digit = CharacterClass.new(value: "0-9");
rules.letter = CharacterClass.new(value: "A-Za-z_");
rules.alnum = Alternation.new()
.push(RuleCall.new(name: #letter))
.push(RuleCall.new(name: #digit));
rules.nil = Sequence.new()
.push(StringLiteral.new(string: "nil"))
.push(Not.new(expression: RuleCall.new(name: #alnum)))
.push(RuleCall.new(name: #ws));
// SEMI = ";" -
// COMMA = "," -
@ -386,110 +825,85 @@ nil = Sequence.new().push(StringLiteral.new(string: "nil")).push(Not.new(express
// 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);
rules.semi = Sequence.new().push(StringLiteral.new(string: ";")).push(RuleCall.new(name: #ws));
rules.comma = Sequence.new().push(StringLiteral.new(string: ",")).push(RuleCall.new(name: #ws));
rules.colon = Sequence.new().push(StringLiteral.new(string: ":")).push(RuleCall.new(name: #ws));
rules.lparen = Sequence.new().push(StringLiteral.new(string: "(")).push(RuleCall.new(name: #ws));
rules.rparen = Sequence.new().push(StringLiteral.new(string: ")")).push(RuleCall.new(name: #ws));
rules.lbrak = Sequence.new().push(StringLiteral.new(string: "[")).push(RuleCall.new(name: #ws));
rules.rbrak = Sequence.new().push(StringLiteral.new(string: "]")).push(RuleCall.new(name: #ws));
rules.lbrace = Sequence.new().push(StringLiteral.new(string: "{")).push(RuleCall.new(name: #ws));
rules.rbrace = Sequence.new().push(StringLiteral.new(string: "}")).push(RuleCall.new(name: #ws));
rules.assign = Sequence.new()
.push(StringLiteral.new(string: "="))
.push(Not.new(expression: CharacterClass.new(value: "=")))
.push(RuleCall.new(name: #ws));
rules.and = Sequence.new()
.push(StringLiteral.new(string: "&"))
.push(Not.new(expression: CharacterClass.new(value: "&=")))
.push(RuleCall.new(name: #ws));
rules.plus = Sequence.new()
.push(StringLiteral.new(string: "+"))
.push(Not.new(expression: CharacterClass.new(value: "+=")))
.push(RuleCall.new(name: #ws));
rules.star = Sequence.new()
.push(StringLiteral.new(string: "*"))
.push(Not.new(expression: CharacterClass.new(value: "=")))
.push(RuleCall.new(name: #ws));
rules.dot = Sequence.new()
.push(StringLiteral.new(string: "."))
.push(Not.new(expression: CharacterClass.new(value: ".")))
.push(RuleCall.new(name: #ws));
// ----- Main -----
// Whitespace
// stream = newStream(readfile("input.txt"));
stream = newStream("baaababbaabaaa");
context = Context.new(outerContext: nil).init();
actions = [];
// - = ( space | comment )*
// space = ' ' | '\t' | end-of-line
// comment = '#' ( !end-of-line . )* end-of-line
// end-of-line = '\r\n' | '\n' | '\r'
// end-of-file = !.
// s = StringLiteral.new(string: "ab");
// print("Success : ", s.match(stream), "\n");
rules.end_of_file = Not.new(expression: Dot.new());
// c = CharacterClass.new(value: " \n\t");
// print("Parsing Character: ", stream.peek(), " | CharacterClass [", c.value,"] : ", c.match(stream), "\n");
rules.end_of_line = Alternation.new()
.push(StringLiteral.new(string: "\r\n"))
.push(StringLiteral.new(string: "\n"))
.push(StringLiteral.new(string: "\r"));
// d = Dot.new();
// print("Parsing Character: ", stream.peek(), " | Dot : ", d.match(stream, context), "\n");
rules.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));
println("\n--- Action Test ---\n");
rules.space = Alternation.new()
.push(StringLiteral.new(string: " "))
.push(StringLiteral.new(string: "\t"))
.push(RuleCall.new(name: #end_of_line));
actionParseTree = `{
innerVar = 151;
};
rules.ws = Star.new(expression: Alternation.new()
.push(RuleCall.new(name: #space))
.push(RuleCall.new(name: #comment))
);
act = Action.new(parseTree: actionParseTree);
// ----- Main -----
assign = Assignment.new(variableName: #outerVar, rule: act);
assign.match(stream, context, actions);
stream = newStream(readfile("rawgrammar.leg"));
//stream = newStream("rule1 = rule2* | b:rule3 {a = b;} rule4 = 'hello' ");
context = Context.new(outerContext: nil).init();
actions = [];
actionParseTree2 = `{
x = 69;
};
print("\nMatching : ", rules.grammar.match(stream, context, rules, actions), "\n");
act2 = Action.new(parseTree: actionParseTree2);
act2.match(stream, context, actions);
// Execute all actions after all matching
for (action in actions) {
action.execute();
for (actionAndContext in actions) {
//println(actionAndContext.action.parseTree);
actionAndContext.action.execute(actionAndContext.context);
}
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);
println();

Carregando…
Cancelar
Guardar