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