From a5b9103da38961bcb13e91bf8508ec8c7f4562ca Mon Sep 17 00:00:00 2001 From: MaximeBarniaudy Date: Wed, 22 May 2024 13:35:51 +0900 Subject: [PATCH] Add with and without functions for namespace manimulation, add namespace support to grammars, add test of parser circularity --- grammar_parser.meta | 1278 +++++++++++++++++++++++-------------------- rawMetaGrammar.leg | 67 +++ rawgrammar.leg | 132 ++--- 3 files changed, 790 insertions(+), 687 deletions(-) create mode 100644 rawMetaGrammar.leg diff --git a/grammar_parser.meta b/grammar_parser.meta index 996cd11..094981c 100644 --- a/grammar_parser.meta +++ b/grammar_parser.meta @@ -1,4 +1,101 @@ -// Utils +// ----- 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) { @@ -59,13 +156,13 @@ Context.declareVariable(var) { StringLiteral = Object.subtype(#StringLiteral); -StringLiteral.match(stream, context, rules, actions) { +StringLiteral.match(stream, context, actions) { let n = len(self.string); let i = 0; let success = 1; if (stream.atEnd()) { success = 0; } - startPosition = stream.position; + let startPosition = stream.position; while(i < n && success == 1) { if (self.string[i] != stream.peek()) { @@ -84,7 +181,7 @@ StringLiteral.match(stream, context, rules, actions) { CharacterClass = Object.subtype(#CharacterClass); -CharacterClass.match(stream, context, rules, actions) { +CharacterClass.match(stream, context, actions) { let classLength = len(self.value); let i = 0; @@ -107,8 +204,8 @@ CharacterClass.match(stream, context, rules, actions) { // [a-z] case if (i+1 < classLength) { // println("[a-z] case"); - rangeStart = prevChar; - rangeEnd = self.value[i+1]; + let rangeStart = prevChar; + let rangeEnd = self.value[i+1]; // print("Range Start: ", rangeStart, " | "); // print("Range End: ", rangeEnd, "\n"); if (stream.peek() >= rangeStart @@ -150,7 +247,7 @@ CharacterClass.match(stream, context, rules, actions) { Dot = Object.subtype(#Dot); -Dot.match(stream, context, rules, actions) { +Dot.match(stream, context, actions) { if (!stream.atEnd()) { stream.inc(); 1; @@ -163,7 +260,7 @@ Dot.match(stream, context, rules, actions) { Begin = Object.subtype(#Begin); -Begin.match(stream, context, rules, actions) { +Begin.match(stream, context, actions) { stream.setLastBegin(); 1; } @@ -172,7 +269,7 @@ Begin.match(stream, context, rules, actions) { End = Object.subtype(#End); -End.match(stream, context, rules, actions) { +End.match(stream, context, actions) { context.variables.yytext = stream.content[stream.lastBegin..stream.position].unescaped(); 1; } @@ -181,10 +278,10 @@ End.match(stream, context, rules, actions) { Optional = Object.subtype(#Optional); -Optional.match(stream, context, rules, actions) { +Optional.match(stream, context, actions) { let initialActionCount = actions.length(); let startingPosition = stream.position; - let success = self.expression.match(stream, context, rules, actions); + let success = self.expression.match(stream, context, actions); if (success == 0) { while (actions.length() > initialActionCount) { @@ -200,8 +297,8 @@ Optional.match(stream, context, rules, actions) { Star = Object.subtype(#Star); -Star.match(stream, context, rules, actions) { - while (self.expression.match(stream, context, rules, actions) == 1) {} +Star.match(stream, context, actions) { + while (self.expression.match(stream, context, actions) == 1) {} 1; } @@ -209,9 +306,9 @@ Star.match(stream, context, rules, actions) { Plus = Object.subtype(#Plus); -Plus.match(stream, context, rules, actions) { - if (self.expression.match(stream, context, rules, actions) == 1) { - while (self.expression.match(stream, context, rules, actions) == 1) {} +Plus.match(stream, context, actions) { + if (self.expression.match(stream, context, actions) == 1) { + while (self.expression.match(stream, context, actions) == 1) {} 1; } else { 0; @@ -222,10 +319,10 @@ Plus.match(stream, context, rules, actions) { And = Object.subtype(#And); -And.match(stream, context, rules, actions) { +And.match(stream, context, actions) { let position = stream.position; - if (self.expression.match(stream, context, rules, actions) == 1) { + if (self.expression.match(stream, context, actions) == 1) { stream.position = position; 1; } else { @@ -237,10 +334,10 @@ And.match(stream, context, rules, actions) { Not = Object.subtype(#Not); -Not.match(stream, context, rules, actions) { +Not.match(stream, context, actions) { let position = stream.position; - if (self.expression.match(stream, context, rules, actions) == 1) { + if (self.expression.match(stream, context, actions) == 1) { stream.position = position; 0; } else { @@ -252,11 +349,11 @@ Not.match(stream, context, rules, actions) { Sequence = Object.subtype(#Sequence); -Sequence.match(stream, context, rules, actions) { +Sequence.match(stream, context, actions) { let i = 0; let match = 1; while (i < self.length() && match == 1) { - match = self[i].match(stream, context, rules, actions); + match = self[i].match(stream, context, actions); i = i + 1; } match; @@ -266,13 +363,13 @@ Sequence.match(stream, context, rules, actions) { Alternation = Object.subtype(#Alternation); -Alternation.match(stream, context, rules, actions) { +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, rules, actions); + success = self[i].match(stream, context, actions); if (success == 0) { while (actions.length() > initialActionCount) { @@ -290,7 +387,7 @@ Alternation.match(stream, context, rules, actions) { Action = Object.subtype(#Action); -Action.match(stream, context, rules, actions) { +Action.match(stream, context, actions) { actions.push([action: self, context: context]); 1; } @@ -317,7 +414,7 @@ Action.execute(context) { ParseTimeAction = Object.subtype(#ParseTimeAction); -ParseTimeAction.match(stream, context, rules, actions) { +ParseTimeAction.match(stream, context, actions) { if(self.action.execute(context)) { 1; } else { @@ -329,56 +426,266 @@ ParseTimeAction.match(stream, context, rules, actions) { Assignment = Object.subtype(#Assignment); -Assignment.match(stream, context, rules, actions) { +Assignment.match(stream, context, actions) { context.declareVariable(self.name); - innerContext = Context.new(outerContext: context, returnValueName: self.name).init(); - self.rule.match(stream, innerContext, rules, actions); + 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, rules, actions) { - if (rules[self.name] == nil) { print("Trying to call undefined rule: ", self.name, "\n"); exit(); } - rules[self.name].match(stream, context, rules, actions); +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; } -// ----- Grammar of Grammars ----- - -rules = []; +// NamespacedRuleCall +NamespacedRuleCall = Object.subtype(#NamespacedRuleCall); -// grammar = - g:mklist -// ( d:definition { g.push(d); } -// ) + end-of-file { print(g, full: Object.new()); } +NamespacedRuleCall.match(stream, context, actions) { + with(self.namespace); + let res = get(self.name).match(stream, context, actions); + without(); + res; +} -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: `{ g; })); +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(RuleCall.new(name: #semi)) + .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: #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); })); + +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)) + ); -Definition = Object.subtype(#Definition); +// ----- Grammar of Grammars ----- -// definition = i:identifier ASSIGN e:expression SEMI? { newDefinition(i, e); } +with(#HardCodedPeg); -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); })); +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); })) + )) + .push(RuleCall.new(name: #end_of_file)); -// expression = s1:sequence ( BAR s2:sequence { s1 = newAlternation(s1, s2); } -// ) * { s1; } +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); })); -rules.expression = Sequence.new() +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() @@ -386,563 +693,348 @@ rules.expression = Sequence.new() .push(Assignment.new(name: #s2, rule: RuleCall.new(name: #sequence))) .push(Action.new(parseTree: `{ s1.push(s2); })) )) - .push(Action.new(parseTree: `{ s1; })); + .push(Action.new(parseTree: `{ s1; })) + ); -// sequence = p:prefix -// ( q:prefix { p = newSequence(p, q); } -// ) * { p; } +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)) + ); -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: `{ intern(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(name: 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(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 = '[' < ( !']' 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) - ); +// ----- Main ----- -// char = '\\' [abefnrtv'"\[\]\\] -// | '\\' [0-3][0-7][0-7] -// | '\\' [0-7][0-7]? -// | !'\\' . +with(#reading); -rules.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()) - ); +stream = newStream(readfile("rawMetaGrammar.leg")); +context = Context.new(outerContext: nil).init(); +actions = []; -// 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 { 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: `{ 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(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 = p:metaPrimary -// ( DOT i:id a:args !ASSIGN !LBRACE { p = newInvoke(p, i, a) } -// | DOT i:id !ASSIGN { p = newGetProp(p, i) } -// | a:args !ASSIGN !LBRACE { p = newCall(p, a); } -// ) * { p; } - -rules.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 = 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); } - -// metaPrimary = nil | metaVar | metaSubExpr - -// 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)); - -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: `{ Block.new(body: 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 - -// BAR = '|' - -// NOT = '!' - -// QUERY = '?' - -// BEGIN = '<' - -// END = '>' - -// TILDE = '~' - -// RPERCENT = '%}' - - -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 - - -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 = "," - -// COLON = ":" - -// LPAREN = "(" - -// RPAREN = ")" - -// LBRAK = "[" - -// RBRAK = "]" - -// LBRACE = "{" - -// RBRACE = "}" - -// ASSIGN = "=" ![=] - -// AND = "&" ![&=] - -// PLUS = "+" ![+=] - -// STAR = "*" ![=] - -// DOT = "." ![.] - - -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)); - -// Whitespace - -// - = ( space | comment )* -// space = ' ' | '\t' | end-of-line -// comment = '#' ( !end-of-line . )* end-of-line -// end-of-line = '\r\n' | '\n' | '\r' -// end-of-file = !. - -rules.end_of_file = Not.new(expression: Dot.new()); - -rules.end_of_line = Alternation.new() - .push(StringLiteral.new(string: "\r\n")) - .push(StringLiteral.new(string: "\n")) - .push(StringLiteral.new(string: "\r")); - -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)); - -rules.space = Alternation.new() - .push(StringLiteral.new(string: " ")) - .push(StringLiteral.new(string: "\t")) - .push(RuleCall.new(name: #end_of_line)); - -rules.ws = Star.new(expression: Alternation.new() - .push(RuleCall.new(name: #space)) - .push(RuleCall.new(name: #comment)) -); +print("Matching : ", grammar.match(stream, context, actions), "\n"); -// ----- Main ----- +// 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("\nMatching : ", rules.grammar.match(stream, context, rules, actions), "\n"); +print("Matching : ", grammar.match(stream, context, actions), "\n"); // Execute all actions after all matching +with(#peg); -grammar = { for (actionAndContext in actions) { +for (actionAndContext in actions) { actionAndContext.action.execute(actionAndContext.context); -}}; +} + +println("\n--------- PEG ---------\n\n"); +println(__namespaces__.peg); +without(#peg); + +without(#reading); -println(grammar); +// Circularity test +without(all: 1); + +with(#metaLanguage); +with(#peg); +with(#reading); + +stream2 = newStream(readfile("rawMetaGrammar.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.grammar.match(stream2, context2, grammar, actions2), "\n"); +print("\nMatching : ", grammar.match(stream2, context2, actions2), "\n"); -grammar2 = { - for (actionAndContext in actions2) { - grammar2 = actionAndContext.action.execute(actionAndContext.context); - } -}; +with(#pegCircular); -println(grammar2); +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); diff --git a/rawMetaGrammar.leg b/rawMetaGrammar.leg new file mode 100644 index 0000000..b923850 --- /dev/null +++ b/rawMetaGrammar.leg @@ -0,0 +1,67 @@ +statement = b:block { b; } + | e:expression SEMI { e; } + +expression = p:primary + ( DOT i:id ASSIGN e:expression # { $$ = newSetProp(p, i, e) } + | LBRAK i:expression RBRAK ASSIGN e:expression { SetArray.new(object: p, index: i, value: e); } + ) + | i:id ASSIGN e:expression { SetVar.new(name: i, value: e); } + | pf:postfix { pf; } + +postfix = p:primary + ( DOT i:id a:args !ASSIGN !LBRACE { p = Invoke.new(self: p, method: i, arguments: a); } + | DOT i:id !ASSIGN { p = GetProp.new(object: p, key: i); } + | a:args !ASSIGN !LBRACE { p = Call.new(function: p, arguments: a); } + ) * { p; } + +args = LPAREN a:mklist + ( + ( k:id COLON e:expression { a[k] = e; } + | e:expression { a.push(e); } + ) + ( COMMA + ( k:id COLON e:expression { a[k] = e; } + | e:expression { a.push(e); } + ) + ) * + ) ? RPAREN { a; } + +mklist = { Object.new(); } + +primary = nil | var | subExpr + +subExpr = LPAREN e:expression RPAREN { e; } + +block = LBRACE b:mklist + ( e:statement { b.push(e); } + ) * RBRACE { Block.new(body: b); } + +nil = NIL { nil; } + +var = i:id { GetVar.new(name: i); } + +id = < LETTER ALNUM* > - { intern(yytext); } + +DIGIT = [0-9] +LETTER = [A-Za-z_] +ALNUM = LETTER | DIGIT + +NIL = "nil" !ALNUM - + +SEMI = ";" - +COMMA = "," - +LPAREN = "(" - +RPAREN = ")" - +LBRAK = "[" - +RBRAK = "]" - +LBRACE = "{" - +RBRACE = "}" - +COLON = ":" ![:] - +ASSIGN = "=" ![=] - +DOT = "." ![.] - + +- = ( space | comment )* +space = ' ' | '\t' | end-of-line +comment = '//' ( !end-of-line . )* end-of-line +end-of-line = '\r\n' | '\n' | '\r' +end-of-file = !. diff --git a/rawgrammar.leg b/rawgrammar.leg index 7a61225..0aebb67 100644 --- a/rawgrammar.leg +++ b/rawgrammar.leg @@ -1,48 +1,50 @@ -grammar = - g:mklist - ( d:definition { g[d.name] = d.expression; } - ) + end-of-file { g; } +grammar = - + ( d:definition { set(d.name, d.expression); } + ) + end-of-file -definition = i:identifier ASSIGN e:expression SEMI? { Definition.new(name: i, expression: e); } +definition = i:identifier ASSIGN e:expression SEMI? { Definition.new(name: i, expression: e); } -expression = s1:sequence { s1 = Alternation.new().push(s1); } - ( BAR s2:sequence { s1.push(s2); } - ) * { s1; } +expression = s:sequence !BAR { s; } + | s1:sequence { s1 = Alternation.new().push(s1); } + ( BAR s2:sequence { s1.push(s2); } + ) * { s1; } -sequence = p:prefix { p = Sequence.new().push(p); } - ( q:prefix { p.push(q); } - ) * { p; } +sequence = p:prefix { p = Sequence.new().push(p); } + ( q:prefix { p.push(q); } + ) * { p; } -prefix = AND a:action { ParseTimeAction.new(action: a); } +prefix = AND a:action { ParseTimeAction.new(action: a); } | - ( AND s:suffix { And.new(expression: s); } - | NOT s:suffix { Not.new(expression: s); } - | s:suffix { s; } + ( AND s:suffix { And.new(expression: s); } + | NOT s:suffix { Not.new(expression: s); } + | s:suffix { s; } ) suffix = p:primary - ( QUERY { p = Optional.new(expression: p); } - | STAR { p = Star.new(expression: p); } - | PLUS { p = Plus.new(expression: p); } - ) ? { p; } + ( QUERY { p = Optional.new(expression: p); } + | STAR { p = Star.new(expression: p); } + | PLUS { p = Plus.new(expression: p); } + ) ? { p; } -primary = i1:identifier COLON i2:ruleCallIdent !ASSIGN { Assignment.new(name: i1, rule: i2); } - | i:ruleCallIdent !ASSIGN { i; } - | LPAREN e:expression RPAREN { e; } - | l:literal { l; } - | c:class { c; } - | DOT { Dot.new(); } - | a:action { a; } - | BEGIN { Begin.new(); } - | END { End.new(); } +primary = i1:identifier COLON i2:ruleCall !ASSIGN { Assignment.new(name: i1, rule: i2); } + | i:ruleCall !ASSIGN { i; } + | LPAREN e:expression RPAREN { e; } + | l:literal { l; } + | c:class { c; } + | DOT { Dot.new(); } + | a:action { a; } + | BEGIN { Begin.new(); } + | END { End.new(); } -identifier = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { intern(yytext); } +identifier = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { intern(yytext); } -ruleCallIdent = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { RuleCall.new(name: intern(yytext)); } +ruleCall = n:identifier CCOLON r:identifier { NamespacedRuleCall.new(namespace: n, name: r); } + | i:identifier { RuleCall.new(name: i); } -literal = ['] < ( !['] char )* > ['] - { StringLiteral.new(value: yytext); } - | ["] < ( !["] char )* > ["] - { StringLiteral.new(value: yytext); } +literal = ['] < ( !['] char )* > ['] - { StringLiteral.new(string: yytext); } + | ["] < ( !["] char )* > ["] - { StringLiteral.new(string: yytext); } -class = '[' < ( !']' range )* > ']' - { CharacterClass.new(value: yytext); } +class = '[' < ( !']' range )* > ']' - { CharacterClass.new(value: yytext); } range = char '-' char | char @@ -51,7 +53,7 @@ char = '\\' [abefnrtv'"\[\]\\] | '\\' [0-7][0-7]? | !'\\' . -action = m:metaBlock - { Action.new(parseTree: m); } +action = m:metaLanguage::block - { Action.new(parseTree: m); } - = ( space | comment )* space = ' ' | '\t' | end-of-line @@ -59,76 +61,18 @@ comment = '#' ( !end-of-line . )* end-of-line end-of-line = '\r\n' | '\n' | '\r' end-of-file = !. -metaStatement = b:metaBlock { b; } - | e:metaExpression SEMI { e; } - -metaExpression = p:metaPrimary - ( DOT i:metaId ASSIGN e:metaExpression # { $$ = newSetProp(p, i, e) } - | LBRAK i:metaExpression RBRAK ASSIGN e:metaExpression { SetArray.new(object: p, index: i, value: e); } - ) - | i:metaId ASSIGN e:metaExpression { SetVar.new(name: i, value: e); } - | pf:metaPostfix { pf; } - -metaPostfix = p:metaPrimary - ( DOT i:metaId a:args !ASSIGN !LBRACE { p = Invoke.new(self: p, method: i, arguments: a); } - | DOT i:metaId !ASSIGN { p = GetProp.new(object: p, key: i); } - | a:args !ASSIGN !LBRACE { p = Call.new(function: p, arguments: a); } - ) * { p; } - -args = LPAREN a:mklist - ( - ( k:metaId COLON e:metaExpression { a[k] = e; } - | e:metaExpression { a.push(e); } - ) - ( COMMA - ( k:metaId COLON e:metaExpression { a[k] = e; } - | e:metaExpression { a.push(e); } - ) - ) * - ) ? RPAREN { a; } - -mklist = { Object.new(); } - -metaPrimary = nil | metaVar | metaSubExpr - -metaSubExpr = LPAREN e:metaExpression RPAREN { e; } - -metaBlock = LBRACE b:mklist - ( e:metaStatement { b.push(e); } - ) * RBRACE { Block.new(body: b); } - -nil = NIL { nil; } - -metaVar = i:metaId { GetVar.new(name: i); } - -metaId = < LETTER ALNUM* > - { intern(yytext); } - -DIGIT = [0-9] -LETTER = [A-Za-z_] -ALNUM = LETTER | DIGIT - BAR = '|' - NOT = '!' - QUERY = '?' - BEGIN = '<' - END = '>' - -TILDE = '~' - -RPERCENT = '%}' - - -NIL = "nil" !ALNUM - - SEMI = ";" - -ASSIGN = "=" ![=] - -COMMA = "," - -COLON = ":" - +CCOLON = "::" - LPAREN = "(" - RPAREN = ")" - -LBRAK = "[" - -RBRAK = "]" - -LBRACE = "{" - -RBRACE = "}" - +ASSIGN = "=" ![=] - AND = "&" ![&=] - PLUS = "+" ![+=] - STAR = "*" ![=] - DOT = "." ![.] - - +COLON = ":" ![:] -