diff --git a/dowhile.meta b/dowhile.meta index 3d5c655..f308234 100644 --- a/dowhile.meta +++ b/dowhile.meta @@ -25,10 +25,7 @@ Do.__codeon__(str) { // parse the grammar expression // put it at the beginning of stmt (which is an alternation) -__namespaces__.metaLanguage.stmt.prepend("\"whatever i want\" - b:stmt WHILE LPAREN c:expr RPAREN EOS { Do.new(b, c); }"); - -// regenerate the expression to be executed -metaLanguage.addRule(#stmt, __namespaces__.metaLanguage.stmt); +metaGrammar.stmt.prepend("\"whatever i want\" - b:stmt WHILE LPAREN c:expr RPAREN EOS { $$ = Do.new(b, c); }"); { diff --git a/fstring.meta b/fstring.meta index 901282d..1fcf2df 100644 --- a/fstring.meta +++ b/fstring.meta @@ -32,37 +32,36 @@ FormatString.__codeon__(str) { str.push("\""); } -__namespaces__.metaLanguage.primary.prepend("fstring"); - nonSpaceEatingId = parseDefinition( -"nonSpaceEatingId = < LETTER ALNUM* > { intern(yytext) } +"nonSpaceEatingId = < LETTER ALNUM* > { $$ = intern(yytext) } "); nonSpaceEatingBlock = parseDefinition( "nonSpaceEatingBlock = LBRACE b:mkobj - ( e:stmt { b.push(e) } - )* \"}\" { b } + ( e:stmt { $$ = b.push(e) } + )* \"}\" { $$ = b } "); fStringChar = parseDefinition( -"fStringChar = < (!\"\\\"\" !\"$\" char )+ > { yytext } - | \"\\\\$\" { \"$\" } +"fStringChar = < (!\"\\\"\" !\"$\" char )+ > { $$ = yytext.unescaped() } + | \"\\\\$\" { $$ = \"$\" } "); fStringRule = parseDefinition( "fstring = \"f\\\"\" elements:mkobj - ( \"$\" i:nonSpaceEatingId { elements.push(GetVar.new(name: i)) } - | \"$\" b:nonSpaceEatingBlock { elements.push(Block.new(body: b)) } - | c:fStringChar { elements.push(c) } - )* \"\\\"\" { FormatString.new(elements) } + ( \"$\" i:nonSpaceEatingId { $$ = elements.push(GetVar.new(name: i)) } + | \"$\" b:nonSpaceEatingBlock { $$ = elements.push(Block.new(body: b)) } + | c:fStringChar { $$ = elements.push(c) } + )* \"\\\"\" { $$ = FormatString.new(elements) } "); // regenerate the expression to be executed -metaLanguage.addRule(nonSpaceEatingBlock.name, nonSpaceEatingBlock.expression); -metaLanguage.addRule(nonSpaceEatingId.name, nonSpaceEatingId.expression); -metaLanguage.addRule(fStringChar.name, fStringChar.expression); -metaLanguage.addRule(fStringRule.name, fStringRule.expression); -metaLanguage.addRule(#primary, __namespaces__.metaLanguage.primary); +metaGrammar.addRule(nonSpaceEatingBlock.name, nonSpaceEatingBlock.expression); +metaGrammar.addRule(nonSpaceEatingId.name, nonSpaceEatingId.expression); +metaGrammar.addRule(fStringChar.name, fStringChar.expression); +metaGrammar.addRule(fStringRule.name, fStringRule.expression); + +metaGrammar.primary.prepend("fstring"); formatInt(integer) { if (integer > 1000) { @@ -71,10 +70,12 @@ formatInt(integer) { return f"$integer"; } a = 69; -print(f"Reimu has $a power and ${6*7} point items and \$${ formatInt(1 << 24) } money.\n"); +print(f"Reimu has $a power and ${6*7} point items and \$${ formatInt(1 << 32) } money.\n"); + n = 100; print(f"Sum of integers from 1 to $n : ${local sum = 0; for (i in n + 1) sum += i}\n"); print(f"${formatInt.function}\n"); + //{ // print(f"${__env__()}\n"); //} diff --git a/grammar_parser.meta b/grammar_parser.meta index 42437d2..56d2e39 100644 --- a/grammar_parser.meta +++ b/grammar_parser.meta @@ -155,13 +155,14 @@ OpCodes = [ RULE2: 7, RULE: 8, // RULE symbol 0 ok ko CALL: 9, // CALL nil 0 ok ko do not use this; VM internal use only - SUCCEED: 10, // SUCCEED nil 0 0 0 next pcs are ignored - FAIL: 11, // FAIL nil 0 0 0 - ACTION: 12, // ACTION function 0 ok ok both pcs should be the same - BEGIN: 13, // BEGIN nil 0 ok ok - END: 14, // END nil 0 ok ok - UNEND: 15, // UNEND nil 0 ok ok - SET: 16 // SET symbol 0 ok ok + CALL2: 10, // CALL nil 0 ok ko do not use this; VM internal use only + SUCCEED: 11, // SUCCEED nil 0 0 0 next pcs are ignored + FAIL: 12, // FAIL nil 0 0 0 + ACTION: 13, // ACTION function 0 ok ok both pcs should be the same + BEGIN: 14, // BEGIN nil 0 ok ok + END: 15, // END nil 0 ok ok + UNEND: 16, // UNEND nil 0 ok ok + SET: 17 // SET symbol 0 ok ok ]; OpCodeNames = [ @@ -175,6 +176,7 @@ OpCodeNames = [ "RULE2", "RULE", "CALL", + "CALL2", "SUCCEED", "FAIL", "ACTION", @@ -197,23 +199,13 @@ Instruction.new(op, arg, arglen, ok, ko) { } Instruction.printline() { - print(OpCodeNames[self.op], " ", self.arg, " ", self.arglen, " ", self.ok, " ", self.ko, "\n"); + print(OpCodeNames[self.op], " ", codeString(self.arg), " ", self.arglen, " ", self.ok, " ", self.ko, "\n"); } // String Literal StringLiteral = Object.subtype(#StringLiteral); -StringLiteral.getMatchingExpression() { - return `{ - ((stream.content.compareFrom(stream.position, @self.string) == 0) && - (stream.position += len(@self.string)) && - @true) - || - @false - }; -} - StringLiteral.emitByteCode(instructions, ok, ko) { //emit(STRING, (byte *)node->String.string, strlen(node->String.string), ok, ko); instructions.push(Instruction.new(OpCodes.STRING, self.string, len(self.string), ok, ko)); @@ -225,10 +217,6 @@ StringLiteral.emitByteCode(instructions, ok, ko) { CharacterClass = Object.subtype(#CharacterClass); -CharacterClass.getMatchingExpression() { - return `{ !stream.atEnd() && (@self.value.charClass()).bitTest(stream.peek()) && stream.inc() && @true }; -} - CharacterClass.emitByteCode(instructions, ok, ko) { //emit(CLASS, node->Class.bits, 32, ok, ko); instructions.push(Instruction.new(OpCodes.CLASS, self.value.charClass(), 32, ok, ko)); @@ -239,10 +227,6 @@ CharacterClass.emitByteCode(instructions, ok, ko) { Dot = Object.subtype(#Dot); -Dot.getMatchingExpression() { - return `{ !stream.atEnd() && stream.inc() && @true }; -} - Dot.emitByteCode(instructions, ok, ko) { //emit(DOT, 0, 0, ok, ko); instructions.push(Instruction.new(OpCodes.DOT, 0, 0, ok, ko)); @@ -253,14 +237,6 @@ Dot.emitByteCode(instructions, ok, ko) { Capture = Object.subtype(#Capture); -Capture.getMatchingExpression() { - return `{ stream.setLastBegin() - && (@self.expression.getMatchingExpression()) - && (context.variables.yytext = stream.content[stream.lastBegin:stream.position].unescaped()) - && @true - }; -} - Capture.emitByteCode(instructions, ok, ko) { //ok = emit(END, 0, 0, ok, ok); //ko = emit(UNEND, 0, 0, ko, ko); @@ -282,10 +258,6 @@ Capture.emitByteCode(instructions, ok, ko) { Optional = Object.subtype(#Optional); -Optional.getMatchingExpression() { - return `{ (@self.expression.getMatchingExpression()); @true }; -} - Optional.emitByteCode(instructions, ok, ko) { self.expression.emitByteCode(instructions, ok, ok); instructions.length() - 1; @@ -295,10 +267,6 @@ Optional.emitByteCode(instructions, ok, ko) { Star = Object.subtype(#Star); -Star.getMatchingExpression() { - return `{ while (@self.expression.getMatchingExpression()) @true; @true }; -} - Star.emitByteCode(instructions, ok, ko) { local last = instructions.length(); self.expression.emitByteCode(instructions, ok, ok); @@ -310,17 +278,6 @@ Star.emitByteCode(instructions, ok, ko) { Plus = Object.subtype(#Plus); -Plus.getMatchingExpression() { - return `{ - if (@self.expression.getMatchingExpression()) { - while (@self.expression.getMatchingExpression()) {} - @true; - } else { - @false; - } - }; -} - Plus.emitByteCode(instructions, ok, ko) { local last = instructions.length(); local next = self.expression.emitByteCode(instructions, ok, ok); @@ -333,18 +290,6 @@ Plus.emitByteCode(instructions, ok, ko) { And = Object.subtype(#And); -And.getMatchingExpression() { - return `{ - local position = stream.position; - if (@self.expression.getMatchingExpression()) { - stream.position = position; - @true; - } else { - @false; - } - }; -} - And.emitByteCode(instructions, ok, ko) { instructions.push(Instruction.new(OpCodes.POP, 0, 0, ok, ok)); ok = instructions.length() - 1; @@ -359,18 +304,6 @@ And.emitByteCode(instructions, ok, ko) { Not = Object.subtype(#Not); -Not.getMatchingExpression() { - return `{ - local position = stream.position; - if (@self.expression.getMatchingExpression()) { - stream.position = position; - @false; - } else { - @true; - } - }; -} - Not.emitByteCode(instructions, ok, ko) { instructions.push(Instruction.new(OpCodes.POP, 0, 0, ko, ko)); local nok = instructions.length() - 1; @@ -386,29 +319,6 @@ Not.emitByteCode(instructions, ok, ko) { Sequence = Object.subtype(#Sequence); -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; - }); - } -} - Sequence.emitByteCode(instructions, ok, ko) { instructions.push(Instruction.new(OpCodes.DROP, 0, 0, ok, ok)); ok = instructions.length() - 1; @@ -427,46 +337,23 @@ Sequence.emitByteCode(instructions, ok, ko) { Alternation = Object.subtype(#Alternation); -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) }; -} - -Alternation.prepend(pegString) { - local stream = newStream(pegString); - local context = Context.new(outerContext: nil).init(); - local actions = []; - - peg.expression(stream, context, actions); - - local expression = { for (actionAndContext in actions) { - actionAndContext.action.execute(actionAndContext.context); - } }; - self.push(self[len(self) - 1]); - for (i from len(self) - 2 to 0) { - self[i + 1] = self[i]; - } - self[0] = expression; +Alternation.prepend(sequenceString) { + alt = self; + parse(sequenceString, pegGrammar, #startSequence, + (result) { + alt.push(alt[len(alt) - 1]); + for (i from len(alt) - 2 to 0) { + alt[i + 1] = alt[i]; + } + alt[0] = result; + } + ); + self.parser.__update(self.name, self); } parseDefinition(pegString) { - local stream = newStream(pegString); - local context = Context.new(outerContext: nil).init(); - local actions = []; - - peg.definition(stream, context, actions); - - local definition = { for (actionAndContext in actions) { - actionAndContext.action.execute(actionAndContext.context); - } }; - + local definition = nil; + parse(pegString, pegGrammar, #grammar, (result){ definition = result }); definition; } @@ -488,10 +375,6 @@ Alternation.emitByteCode(instructions, ok, ko) { Action = Object.subtype(#Action); -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 @@ -531,10 +414,6 @@ Action.emitByteCode(instructions, ok, ko) { ParseTimeAction = Object.subtype(#ParseTimeAction); -ParseTimeAction.getMatchingExpression() { - return `{ (@self.action).execute(context) }; -} - ParseTimeAction.emitByteCode(instructions, ok, ko) { instructions.push(Instruction.new( OpCodes.TEST, @@ -556,10 +435,6 @@ ParseTimeAction.emitByteCode(instructions, ok, ko) { ExecuteAction = Object.subtype(#ExecuteAction); -ExecuteAction.getMatchingExpression() { - return `{ (@self.action).execute(context); @true; }; -} - ExecuteAction.emitByteCode(instructions, ok, ko) { instructions.push(Instruction.new( OpCodes.TEST, @@ -581,14 +456,6 @@ ExecuteAction.emitByteCode(instructions, ok, ko) { Assignment = Object.subtype(#Assignment); -Assignment.getMatchingExpression() { - return `{ - context.declareVariable(@self.name); - local context = Context.new(outerContext: context, returnValueName: @self.name).init(); - @self.rule.getMatchingExpression(); - } -} - Assignment.emitByteCode(instructions, ok, ko) { instructions.push(Instruction.new(OpCodes.SET, self.name, 0, ok, ok)); ok = instructions.length() - 1; @@ -600,10 +467,6 @@ Assignment.emitByteCode(instructions, ok, ko) { RuleCall = Object.subtype(#RuleCall); -RuleCall.getMatchingExpression() { - `{ /*increaseCount(@self.name);*/ Invoke.new(self: self, method: @self.name, arguments: [stream, context, actions]).__eval__() }; -} - RuleCall.emitByteCode(instructions, ok, ko) { instructions.push(Instruction.new(OpCodes.RULE, self.name, 0, ok, ko)); instructions.length() - 1; @@ -613,47 +476,26 @@ RuleCall.emitByteCode(instructions, ok, ko) { NamespacedRuleCall = Object.subtype(#NamespacedRuleCall); -NamespacedRuleCall.getMatchingExpression(innerContext) { - `{ Invoke.new(self: @get(self.namespace), method: @self.name, arguments: [stream, context, actions]).__eval__() }; -} - NamespacedRuleCall.emitByteCode(instructions, ok, ko) { - instructions.push(Instruction.new(OpCodes.RULE, self.name, self.namespace, ok, ko)); + instructions.push(Instruction.new(OpCodes.RULE2, self.name, self.namespace, ok, ko)); instructions.length() - 1; } Definition = Object.subtype(#Definition); -Grammar = Object.subtype(#Grammar); +// Initialize grammar objects -Grammar.addRulesFromNamespace(namespace) { - for (key in __namespaces__[namespace].keys()) { - if (key == #__nsname__) continue; - self.addRule(key, __namespaces__[namespace][key]); - } -} +Grammar = Object.subtype(#Grammar); +Parser = Object.subtype(#Parser); -Grammar.addRule(ruleName, rule) { - self[ruleName] = Closure.new( - environment: nil, - function: Lambda.new( - parameters: [#stream, #context, #actions], - body: rule.getMatchingExpression().body, - name: ruleName, - parent: self - ) - ); +Grammar.new() { + self = super.new(); + self.parser = Parser.new(); + self; } -//global functionCounts = []; -// -//increaseCount(function) { -// if (!functionCounts.keys().contains(function)){ -// functionCounts[function] = 1; -// } else { -// functionCounts[function]++; -// } -//} +minPegGrammar = Grammar.new(); +minMetaGrammar = Grammar.new(); // ----- Grammar of Meta Language (Minimal) ----- @@ -663,7 +505,7 @@ metaStatement = Alternation.new() .push(Sequence.new() .push(Assignment.new(name: #b, rule: RuleCall.new(name: #block))) - .push(Action.new(parseTree: `{ b; })) + .push(Action.new(parseTree: `{ $$ = b; })) ) .push(Sequence.new() .push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaExpression))) @@ -671,11 +513,11 @@ metaStatement = .push(RuleCall.new(name: #semi)) .push(And.new(expression: RuleCall.new(name: #rbrace))) ) - .push(Action.new(parseTree: `{ e; })) + .push(Action.new(parseTree: `{ $$ = e; })) ); metaExpression = - Alternation.new(id: 1234) + Alternation.new() .push(Sequence.new() .push(Assignment.new(name: #p, rule: RuleCall.new(name: #metaPrimary))) .push(Alternation.new() @@ -684,6 +526,7 @@ metaExpression = .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: `{ $$ = SetProp.new(object: p, key: i, value: e); })) ) .push(Sequence.new() .push(RuleCall.new(name: #lbrak)) @@ -691,7 +534,7 @@ 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(Action.new(parseTree: `{ $$ = SetArray.new(object: p, index: i, value: e); })) ) ) ) @@ -701,17 +544,17 @@ metaExpression = .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: `{ SetGlobal.new(name: i, value: e); })) + .push(Action.new(parseTree: `{ $$ = SetGlobal.new(name: 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(Action.new(parseTree: `{ $$ = SetVar.new(name: i, value: e); })) ) .push(Sequence.new() .push(Assignment.new(name: #pf, rule: RuleCall.new(name: #metaPrefix))) - .push(Action.new(parseTree: `{ pf; })) + .push(Action.new(parseTree: `{ $$ = pf; })) ); metaPrefix = @@ -756,7 +599,7 @@ metaPostfix = // TODO: Voir si c'est toujours bon avec le newApply() ) )) - .push(Action.new(parseTree: `{ p; })); + .push(Action.new(parseTree: `{ $$ = p; })); args = Sequence.new() @@ -792,9 +635,9 @@ args = )) )) .push(RuleCall.new(name: #rparen)) - .push(Action.new(parseTree: `{ a; })); + .push(Action.new(parseTree: `{ $$ = a; })); -mklist = Action.new(parseTree: `{ Object.new(); }); +mklist = Action.new(parseTree: `{ $$ = Object.new(); }); metaPrimary = Alternation.new() @@ -809,7 +652,7 @@ metaSubExpr = .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; })); block = Sequence.new() @@ -819,11 +662,11 @@ block = Star.new( expression: Sequence.new() .push(Assignment.new(name: #e, rule: RuleCall.new(name: #metaStatement))) - .push(Action.new(parseTree: `{ b.push(e); })) + .push(Action.new(parseTree: `{ $$ = b.push(e); })) ) ) .push(RuleCall.new(name: #rbrace)) - .push(Action.new(parseTree: `{ b; })); + .push(Action.new(parseTree: `{ $$ = b; })); string = Sequence.new() @@ -868,16 +711,16 @@ number = .push(Sequence.new() .push(StringLiteral.new(string: "-")) .push(Assignment.new(name: #n, rule: RuleCall.new(name: #unsign))) - .push(Action.new(parseTree: `{ Unyop.new(operation: opNeg).push(n) })) + .push(Action.new(parseTree: `{ $$ = Unyop.new(operation: opNeg).push(n) })) ) .push(Sequence.new() .push(StringLiteral.new(string: "+")) .push(Assignment.new(name: #n, rule: RuleCall.new(name: #number))) - .push(Action.new(parseTree: `{ n })) + .push(Action.new(parseTree: `{ $$ = n })) ) .push(Sequence.new() .push(Assignment.new(name: #n, rule: RuleCall.new(name: #unsign))) - .push(Action.new(parseTree: `{ n })) + .push(Action.new(parseTree: `{ $$ = n })) ); unsign = @@ -886,7 +729,7 @@ unsign = Plus.new(expression: RuleCall.new(name: #digit))) ) .push(RuleCall.new(name: #ws)) - .push(Action.new(parseTree: `{ yytext.asInteger(10); })); + .push(Action.new(parseTree: `{ $$ = yytext.asInteger(10); })); metaVar = Alternation.new() @@ -895,12 +738,12 @@ metaVar = .push(StringLiteral.new(string: "global")) .push(RuleCall.new(name: #ws)) .push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId))) - .push(Action.new(parseTree: `{ GetGlobal.new(name: i); })) + .push(Action.new(parseTree: `{ $$ = GetGlobal.new(name: i); })) ) .push( Sequence.new() .push(Assignment.new(name: #i, rule: RuleCall.new(name: #metaId))) - .push(Action.new(parseTree: `{ GetVar.new(name: i); })) + .push(Action.new(parseTree: `{ $$ = GetVar.new(name: i); })) ); metaId = @@ -910,7 +753,7 @@ metaId = .push(Star.new(expression: RuleCall.new(name: #alnum))) )) .push(RuleCall.new(name: #ws)) - .push(Action.new(parseTree: `{ intern(yytext); })); + .push(Action.new(parseTree: `{ $$ = intern(yytext); })); digit = CharacterClass.new(value: "0-9"); higit = CharacterClass.new(value: "0-9A-Fa-f"); @@ -923,7 +766,8 @@ nil = Sequence.new() .push(StringLiteral.new(string: "nil")) .push(Not.new(expression: RuleCall.new(name: #alnum))) - .push(RuleCall.new(name: #ws)); + .push(RuleCall.new(name: #ws)) + .push(Action.new(parseTree: `{ $$ = nil })); semi = Sequence.new().push(StringLiteral.new(string: ";" )).push(RuleCall.new(name: #ws)); comma = Sequence.new().push(StringLiteral.new(string: "," )).push(RuleCall.new(name: #ws)); @@ -991,11 +835,11 @@ grammar = .push(Alternation.new() .push(Sequence.new() .push(Assignment.new(name: #d, rule: RuleCall.new(name: #definition))) - .push(Action.new(parseTree: `{ d; })) + .push(Action.new(parseTree: `{ global yysval = d; })) ) .push(Sequence.new() .push(RuleCall.new(name: #end_of_file)) - .push(Action.new(parseTree: `{ nil; })) + .push(Action.new(parseTree: `{ global yysval = nil; })) ) ); @@ -1005,24 +849,24 @@ definition = .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); })); + .push(Action.new(parseTree: `{ $$ = Definition.new(name: i, expression: e); })); expression = Alternation.new() .push(Sequence.new() .push(Assignment.new(name: #s, rule: RuleCall.new(name: #sequence))) .push(Not.new(expression: RuleCall.new(name: #bar))) - .push(Action.new(parseTree: `{ s; })) + .push(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(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.push(s2); })) )) - .push(Action.new(parseTree: `{ s1; })) + .push(Action.new(parseTree: `{ $$ = s1; })) ); sequence = @@ -1030,13 +874,13 @@ sequence = .push(Assignment.new(name: #p, rule: RuleCall.new(name: #prefix))) .push(Optional.new(expression: Sequence.new() .push(Assignment.new(name: #q, rule: RuleCall.new(name: #prefix))) - .push(Action.new(parseTree: `{ p = Sequence.new().push(p).push(q); })) + .push(Action.new(parseTree: `{ $$ = p = Sequence.new().push(p).push(q); })) .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.push(q); })) )) )) - .push(Action.new(parseTree: `{ p; })); + .push(Action.new(parseTree: `{ $$ = p; })); prefix = Alternation.new() @@ -1047,22 +891,22 @@ prefix = .push(Sequence.new() .push(RuleCall.new(name: #at)) .push(Assignment.new(name: #a, rule: RuleCall.new(name: #action))) - .push(Action.new(parseTree: `{ ExecuteAction.new(action: a); })) + .push(Action.new(parseTree: `{ $$ = ExecuteAction.new(action: a); })) ) .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(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(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; })) + .push(Action.new(parseTree: `{ $$ = s; })) ) ); @@ -1083,7 +927,7 @@ suffix = .push(Action.new(parseTree: `{ p = Plus.new(expression: p); })) ) )) - .push(Action.new(parseTree: `{ p; })); + .push(Action.new(parseTree: `{ $$ = p; })); primary = Alternation.new() @@ -1092,40 +936,40 @@ primary = .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(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(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(Action.new(parseTree: `{ $$ = e; })) ) .push(Sequence.new() .push(Assignment.new(name: #l, rule: RuleCall.new(name: #literal))) - .push(Action.new(parseTree: `{ l; })) + .push(Action.new(parseTree: `{ $$ = l; })) ) .push(Sequence.new() .push(Assignment.new(name: #c, rule: RuleCall.new(name: #class))) - .push(Action.new(parseTree: `{ c; })) + .push(Action.new(parseTree: `{ $$ = c; })) ) .push(Sequence.new() .push(RuleCall.new(name: #dot)) - .push(Action.new(parseTree: `{ Dot.new(); })) + .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(Action.new(parseTree: `{ $$ = a; })) ) .push(Sequence.new() .push(RuleCall.new(name: #begin)) .push(Assignment.new(name: #e, rule: RuleCall.new(name: #expression))) .push(RuleCall.new(name: #end)) - .push(Action.new(parseTree: `{ Capture.new(expression: e); })) + .push(Action.new(parseTree: `{ $$ = Capture.new(expression: e); })) ); identifier = @@ -1135,7 +979,7 @@ identifier = .push(Star.new(expression: CharacterClass.new(value: "-a-zA-Z_0-9"))) )) .push(RuleCall.new(name: #ws)) - .push(Action.new(parseTree: `{ intern(yytext); })); + .push(Action.new(parseTree: `{ $$ = intern(yytext); })); ruleCall = Alternation.new() @@ -1143,11 +987,16 @@ ruleCall = .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(Action.new(parseTree: `{ + $$ = NamespacedRuleCall.new( + namespace: GetProp.new(object: GetVar.new(name: n), key: #parser).__eval__(), + name: r + ); + })) ) .push(Sequence.new() .push(Assignment.new(name: #i, rule: RuleCall.new(name: #identifier))) - .push(Action.new(parseTree: `{ RuleCall.new(name: i); })) + .push(Action.new(parseTree: `{ $$ = RuleCall.new(name: i); })) ); literal = @@ -1161,7 +1010,7 @@ literal = )) .push(CharacterClass.new(value: "\'")) .push(RuleCall.new(name: #ws)) - .push(Action.new(parseTree: `{ StringLiteral.new(string: yytext); })) + .push(Action.new(parseTree: `{ $$ = StringLiteral.new(string: yytext.unescaped()); })) ) .push(Sequence.new() .push(CharacterClass.new(value: "\"")) @@ -1172,7 +1021,7 @@ literal = )) .push(CharacterClass.new(value: "\"")) .push(RuleCall.new(name: #ws)) - .push(Action.new(parseTree: `{ StringLiteral.new(string: yytext); })) + .push(Action.new(parseTree: `{ $$ = StringLiteral.new(string: yytext.unescaped()); })) ); class = @@ -1185,7 +1034,7 @@ class = )) .push(StringLiteral.new(string: "]")) .push(RuleCall.new(name: #ws)) - .push(Action.new(parseTree: `{ CharacterClass.new(value: yytext.unescaped()); })); + .push(Action.new(parseTree: `{ $$ = CharacterClass.new(value: yytext.unescaped()); })); range = Alternation.new() @@ -1222,9 +1071,9 @@ char = action = Sequence.new() - .push(Assignment.new(name: #m, rule: NamespacedRuleCall.new(namespace: #HardCodedMeta, name: #block))) + .push(Assignment.new(name: #m, rule: NamespacedRuleCall.new(namespace: minMetaGrammar.parser, name: #block))) .push(RuleCall.new(name: #ws)) - .push(Action.new(parseTree: `{ Action.new(parseTree: Block.new(body: m)); })); + .push(Action.new(parseTree: `{ $$ = Action.new(parseTree: Block.new(body: 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)); @@ -1233,7 +1082,6 @@ begin = Sequence.new().push(StringLiteral.new(string: "<")).push(RuleCall.new end = Sequence.new().push(StringLiteral.new(string: ">")).push(RuleCall.new(name: #ws)); tilde = Sequence.new().push(StringLiteral.new(string: "~")).push(RuleCall.new(name: #ws)); at = 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)); @@ -1445,244 +1293,145 @@ strtol(text, _, base) { } newStringUnescaped(text) { - text; + text.unescaped(); } -HardCodedPeg = Grammar.new(); -HardCodedMeta = Grammar.new(); - -HardCodedPeg.addRulesFromNamespace(#HardCodedPeg); -HardCodedMeta.addRulesFromNamespace(#HardCodedMeta); -HardCodedPeg.__delegate__ = HardCodedMeta; +//-------------------------------------------------------------------------------------------------- -global stream = newStream(readfile("minproto.grammar")); -global context = Context.new(outerContext: nil).init(); -global actions = []; -global lineno = 0; - -while(!stream.atEnd()) { - HardCodedPeg.grammar(stream, context, actions); - - with(#metaLanguage); - local definition = { for (actionAndContext in actions) { - actionAndContext.action.execute(actionAndContext.context); - } }; - if (definition == nil) continue; // end of file case - setInTopNamespace(definition.name, definition.expression); - without(#metaLanguage); - - global actions = []; -} +Parser.__update(ruleName, ruleExpression, v: false) { -//println("\n--------- META ---------\n\n"); -//println(__namespaces__.metaLanguage); - -global stream = newStream(readfile("rawgrammar.leg")); -global context = Context.new(outerContext: nil).init(); -global actions = []; - -while(!stream.atEnd()) { - HardCodedPeg.grammar(stream, context, actions); - - with(#peg); - local definition = { for (actionAndContext in actions) { - actionAndContext.action.execute(actionAndContext.context); - } }; - if (definition == nil) continue; // end of file case - setInTopNamespace(definition.name, definition.expression); - without(#peg); - - global actions = []; -} -//println("\n--------- PEG ---------\n\n"); -//println(__namespaces__.peg); - -global peg = Grammar.new(); -global metaLanguage = Grammar.new(); - -peg.addRulesFromNamespace(#peg); -metaLanguage.addRulesFromNamespace(#metaLanguage); - -peg.__delegate__ = metaLanguage; + local instructions = []; -global now = cputime(); -print("Parser Generation Time : ", now - then, "s\n"); + instructions.push(Instruction.new(OpCodes.FAIL, nil, 0, 0, 0)); + local ko = instructions.length() - 1; -// Circularity test -if (nil) { + instructions.push(Instruction.new(OpCodes.SUCCEED, nil, 0, 0, 0)); + local ok = instructions.length() - 1; -println("circularity test\n"); + ruleExpression.emitByteCode(instructions, ok, ko); -global stream2 = newStream(readfile("minproto.grammar")); -global context2 = Context.new(outerContext: nil).init(); -global actions2 = []; + for (n from 0 to (instructions.length() - 1 - ((instructions.length() - 1) % 2)) / 2) { + local i = instructions[n]; + instructions[n] = instructions[instructions.length() - 1 - n]; + instructions[instructions.length() - 1 - n] = i; + } -while(!stream2.atEnd()) { - peg.grammar(stream2, context2, actions2); + if (v) { + println(ruleName); + } - with(#metaLanguageCircular); - local definition = { for (actionAndContext in actions2) { - actionAndContext.action.execute(actionAndContext.context); - } }; - if (definition == nil) continue; // end of file case - setInTopNamespace(definition.name, definition.expression); - without(#metaLanguageCircular); + for (n in instructions.length()) { + i = instructions[n]; + i.ok = instructions.length() - 1 - i.ok; + i.ko = instructions.length() - 1 - i.ko; + if (v) { + print(" ", { if (n < 100) { "0" } else { "" } }, { if (n < 10) { "0" } else { "" } }, n, " "); + i.printline(); + } + } - global actions2 = []; + self[ruleName] = []; + for (instruction in instructions) { + self[ruleName].push(instruction.op); + self[ruleName].push(instruction.arg); + self[ruleName].push(instruction.arglen); + self[ruleName].push(instruction.ok); + self[ruleName].push(instruction.ko); + } } -//println("\n--------- CIRCULAR META ---------\n\n"); -//println(__namespaces__.metaLanguageCircular); +Grammar.addRule(ruleName, ruleExpression, v: false) { -global stream2 = newStream(readfile("rawgrammar.leg")); -global context2 = Context.new(outerContext: nil).init(); -global actions2 = []; + self[ruleName] = ruleExpression; + self[ruleName].parser = self.parser; + self[ruleName].name = ruleName; + self.parser.__update(ruleName, ruleExpression, v: v); -while(!stream2.atEnd()) { - peg.grammar(stream2, context2, actions2); - - with(#pegCircular); - local definition = { for (actionAndContext in actions2) { - actionAndContext.action.execute(actionAndContext.context); - } }; - if (definition == nil) continue; // end of file case - setInTopNamespace(definition.name, definition.expression); - without(#pegCircular); - - global actions2 = []; } -//println("\n--------- CIRCULAR PEG ---------\n\n"); -//println(__namespaces__.pegCircular); - -compareGrammars(grammar1, grammar2) { - local 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"); - } +// Grammar object construction +for (ruleName in __namespaces__.HardCodedPeg.keys()) { + if (ruleName == #__nsname__) continue; + minPegGrammar.addRule(ruleName, __namespaces__.HardCodedPeg[ruleName]); } -compareGrammars(#peg, #pegCircular); -compareGrammars(#metaLanguage, #metaLanguageCircular); - +for (ruleName in __namespaces__.HardCodedMeta.keys()) { + if (ruleName == #__nsname__) continue; + minMetaGrammar.addRule(ruleName, __namespaces__.HardCodedMeta[ruleName]); } -//global functionCounts = []; -global then = cputime(); - -global stream3 = newStream(readfile("dowhile.meta")); -global context3 = Context.new(outerContext: nil).init(); -global actions3 = []; +minPegGrammar.parser.__delegate__ = minMetaGrammar.parser; -while(!stream3.atEnd()) { - metaLanguage.start(stream3, context3, actions3); - local res = { for (actionAndContext in actions3) { - actionAndContext.action.execute(actionAndContext.context); - } }; - eval(res, env: nil); - global actions3 = []; -} +// Parsing function -global now = cputime(); -print("---\nFile Execution time : ", now - then, "s\n---\n"); -//println(functionCounts); +parse(input, grammar, startRule, resultCallback){ -global then = cputime(); + local cursor = 0; + matchedCharacters = __match__(grammar.parser, startRule, input, cursor); + cursor += matchedCharacters; -global streamFString = newStream(readfile("fstring.meta")); -global contextFString = Context.new(outerContext: nil).init(); -global actionsFString = []; + while (yysval != 0 && yysval != nil && matchedCharacters >= 0) { + resultCallback(yysval); + matchedCharacters = __match__(grammar.parser, startRule, input, cursor); + cursor += matchedCharacters; + } -while(!streamFString.atEnd()) { - metaLanguage.start(streamFString, contextFString, actionsFString); - local res = { for (actionAndContext in actionsFString) { - actionAndContext.action.execute(actionAndContext.context); - } }; - eval(res, env: nil); - global actionsFString = []; } -global now = cputime(); - -print("---\nFile Execution time : ", now - then, "s\n---\n"); +input = readfile("minproto.grammar"); +metaGrammar = Grammar.new(); +global lineno = 0; // This is for the grammar above -global stream4 = newStream(readfile("minproto.grammar")); -global context4 = Context.new(outerContext: nil).init(); -global actions4 = []; +// How to read the following function call : +// parse input with minPegGrammar starting with rule grammar applying this function to each result +parse(input, minPegGrammar, #grammar, (result){ metaGrammar.addRule(result.name, result.expression) }); -addRule(grammar, definition) { - - local instructions = []; +input = readfile("rawgrammar.leg"); +pegGrammar = Grammar.new(); +parse(input, minPegGrammar, #grammar, (result){ pegGrammar.addRule(result.name, result.expression) }); - instructions.push(Instruction.new(OpCodes.FAIL, nil, 0, 0, 0)); - local ko = instructions.length() - 1; - - instructions.push(Instruction.new(OpCodes.SUCCEED, nil, 0, 0, 0)); - local ok = instructions.length() - 1; - - definition.expression.emitByteCode(instructions, ok, ko); - - for (n from 0 to (instructions.length() - 1 - ((instructions.length() - 1) % 2)) / 2) { - local i = instructions[n]; - instructions[n] = instructions[instructions.length() - 1 - n]; - instructions[instructions.length() - 1 - n] = i; - } +circularityTest = false; +//circularityTest = true; +if (circularityTest) { - //println(definition.name); + compareGrammars(grammar1, grammar2) { + for (rule in grammar1.parser.keys()) { - for (n in instructions.length()) { - i = instructions[n]; - i.ok = instructions.length() - 1 - i.ok; - i.ko = instructions.length() - 1 - i.ko; - //print(" 0", { if (n < 10) { "0" } else { "" } }, n, " "); - //i.printline(); - } + if (grammar1.parser[rule].length() != grammar2.parser[rule].length()) { + print("Unmatching lengths for rule ", rule, "\n"); + return false; + } + + for (i in grammar1[rule].length()) { + if (codeString(grammar1.parser[rule][i]) != codeString(grammar2.parser[rule][i])) { + print("Unmatching contents for rule ", rule, " at index ", i, ":\n", + grammar1.parser[rule][i], "\n", grammar2.parser[rule][i], "\n"); + return false; + } + } - grammar[definition.name] = []; - for (instruction in instructions) { - grammar[definition.name].push(instruction.op); - grammar[definition.name].push(instruction.arg); - grammar[definition.name].push(instruction.arglen); - grammar[definition.name].push(instruction.ok); - grammar[definition.name].push(instruction.ko); + } + return true; } -} - -minprotoVMGrammar = []; -while(!stream4.atEnd()) { - peg.grammar(stream4, context4, actions4); + input = readfile("rawgrammar.leg"); + pegGrammarCircular = Grammar.new(); + parse(input, pegGrammar, #grammar, (result){ pegGrammarCircular.addRule(result.name, result.expression) }); - local definition = { for (actionAndContext in actions4) { - actionAndContext.action.execute(actionAndContext.context); - } }; - if (definition == nil) continue; // end of file case + input = readfile("minproto.grammar"); + metaGrammarCircular = Grammar.new(); + parse(input, pegGrammar, #grammar, (result){ metaGrammarCircular.addRule(result.name, result.expression) }); - addRule(minprotoVMGrammar, definition); + if (compareGrammars(pegGrammar, pegGrammarCircular)) + print("Grammars pegGrammar and pegGrammarCircular are equal\n"); + if (compareGrammars(metaGrammar, metaGrammarCircular)) + print("Grammars metaGrammar and metaGrammarCircular are equal\n"); - global actions4 = []; } -global then = cputime(); - -input = readfile("grammar_parser.meta"); -cursor = 0; -while (yysval != 0) { - matchedCharacters = __match__(minprotoVMGrammar, #start, input, cursor); - //print(yysval, "\n"); - cursor += matchedCharacters; -} +input = readfile("dowhile.meta"); +parse(input, metaGrammar, #start, (result){ eval(result, env: nil) }); -global now = cputime(); -print("---\nFile Parsing time : ", now - then, "s\nSpeed: ", 1688/(now-then), " lines per second\n---\n"); +input = readfile("fstring.meta"); +parse(input, metaGrammar, #start, (result){ eval(result, env: nil) }); diff --git a/minproto.grammar b/minproto.grammar index 172b147..8fc7023 100644 --- a/minproto.grammar +++ b/minproto.grammar @@ -1,6 +1,6 @@ # minproto.leg -- minimal prototype langauge for semantic experiments # -# last edited: 2024-07-05 17:16:16 by piumarta on zora-1034.local +# last edited: 2024-07-10 11:28:02 by piumarta on zora-1034.local start = - ( s:stmt { global yysval = s } diff --git a/rawgrammar.leg b/rawgrammar.leg index 5f338c8..dc0837c 100644 --- a/rawgrammar.leg +++ b/rawgrammar.leg @@ -1,50 +1,54 @@ -grammar = - ( d:definition { d; } - | end-of-file { nil; } +grammar = - ( d:definition { global yysval = d; } + | end-of-file { global yysval = nil; } ) -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 = s:sequence !BAR { s; } +expression = s:sequence !BAR { $$ = s; } | s1:sequence { s1 = Alternation.new().push(s1); } ( BAR s2:sequence { s1.push(s2); } - ) * { s1; } + ) * { $$ = s1; } + +startSequence = - s:sequence { global yysval = s; } sequence = p:prefix ( q:prefix { p = Sequence.new().push(p).push(q); } ( q:prefix { p.push(q); } - ) * ) ? { p; } + ) * ) ? { $$ = p; } -prefix = AND a:action { ParseTimeAction.new(action: a); } - | AT a:action { ExecuteAction.new(action: a); } +prefix = AND a:action { $$ = ParseTimeAction.new(action: a); } + | AT a:action { $$ = ExecuteAction.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; } + ) ? { $$ = p; } -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 e:expression END { Capture.new(expression: e); } +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 e:expression END { $$ = Capture.new(expression: e); } -identifier = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { intern(yytext); } +identifier = < [-a-zA-Z_][-a-zA-Z_0-9]* > - { $$ = intern(yytext); } -ruleCall = n:identifier CCOLON r:identifier { NamespacedRuleCall.new(namespace: n, name: r); } - | i:identifier { RuleCall.new(name: i); } +ruleCall = n:identifier CCOLON r:identifier { $$ = NamespacedRuleCall + .new(namespace: GetVar.new(name: n).__eval__(), name: r); + } + | i:identifier { $$ = RuleCall.new(name: i); } -literal = ['] < ( !['] char )* > ['] - { StringLiteral.new(string: yytext); } - | ["] < ( !["] char )* > ["] - { StringLiteral.new(string: yytext); } +literal = ['] < ( !['] char )* > ['] - { $$ = StringLiteral.new(string: yytext.unescaped()); } + | ["] < ( !["] char )* > ["] - { $$ = StringLiteral.new(string: yytext.unescaped()); } -class = '[' < ( !']' range )* > ']' - { CharacterClass.new(value: yytext); } +class = '[' < ( !']' range )* > ']' - { $$ = CharacterClass.new(value: yytext.unescaped()); } range = char '-' char | char @@ -53,7 +57,7 @@ char = '\\' [abefnrtv'"\[\]\\] | '\\' [0-7][0-7]? | !'\\' . -action = m:metaLanguage::block - { Action.new(parseTree: Block.new(body: m)); } +action = m:metaGrammar::block - { $$ = Action.new(parseTree: Block.new(body: m)); } - = ( space | comment )* space = ' ' | '\t' | end-of-line