void GenerateCondPost(TextWriter tw, AST.Cond node, int n, bool match_args, string indent) { string condition = TrimBraces(node.GetText().Trim()).Trim(); condition = condition.Replace("\t", " "); tw.Write(indent); tw.WriteLine("// COND"); string index = match_args ? "_arg_index" : "_index"; string results = match_args ? "_memo.ArgResults" : "_memo.Results"; if (condition.Contains("return") || condition.Contains("_IM_Result")) { if (!condition.Contains("return")) condition = "return " + condition; if (!condition.EndsWith(";")) condition = condition + ";"; tw.Write(indent); tw.WriteLine("Func<{2}, bool> lambda{0} = (_IM_Result) => {{ {1} }};", n, condition, tItem); tw.Write(indent); tw.WriteLine("if ({1}.Peek() == null || !lambda{0}({1}.Peek())) {{ {1}.Pop(); {1}.Push(null); {2} = _start_i{0}; }}", n, results, index); } else { tw.Write(indent); tw.WriteLine("if ({2}.Peek() == null || !({1})) {{ {2}.Pop(); {2}.Push(null); {3} = _start_i{0}; }}", n, condition, results, index); } tw.WriteLine(); }
void GenerateLiteralPost(TextWriter tw, AST.Code node, int n, bool match_args, string indent) { string literal = TrimBraces(node.GetText().Trim()).Trim(); tw.Write(indent); tw.WriteLine("// LITERAL {0}", literal); if (match_args) { tw.Write(indent); tw.WriteLine("_ParseLiteralArgs(_memo, ref _arg_index, ref _arg_input_index, {0}, _args);", literal); } else { bool isCharMatcher = tInput == "char" || tInput.EndsWith("Character"); tw.Write(indent); if (isCharMatcher && literal.StartsWith("\"")) tw.WriteLine("_ParseLiteralString(_memo, ref _index, {0});", literal); else if (isCharMatcher && literal.StartsWith("'")) tw.WriteLine("_ParseLiteralChar(_memo, ref _index, {0});", literal); else tw.WriteLine("_ParseLiteralObj(_memo, ref _index, {0});", literal); } tw.WriteLine(); }
void GenerateRegexpPost(TextWriter tw, AST.Regexp node, int n, bool match_args, string indent) { bool isCharMatcher = tInput == "char" || tInput.EndsWith("Character"); if (!isCharMatcher) throw new Exception("Can only use regular expressions when matching characters."); if (match_args) throw new Exception("Cannot use a regular expression in rule arguments."); var text = node.GetText().Trim(' ', '/'); string name; if (!regexps.TryGetValue(text, out name)) { name = string.Format("_re{0}", regexps.Count); regexps.Add(text, name); } tw.Write(indent); tw.WriteLine("// REGEXP {0}", text); tw.Write(indent); tw.WriteLine("_ParseRegexp(_memo, ref _index, {0});", name); tw.WriteLine(); }
void Analyze(AST.AstNode node, AST.Rule currentRule) { // get grammar name & generic parameters if (node is AST.Grammar) { AST.Grammar gr = node as AST.Grammar; tInput = gr.GetText(gr.TInput).Trim(); tResult = gr.GetText(gr.TResult).Trim(); gName = gr.GetText(gr.Name).Trim(); tItem = string.Format("_{0}_Item", gName); gBase = gr.GetText(gr.Base).Trim(); if (string.IsNullOrWhiteSpace(gBase)) gBase = string.Format("IronMeta.Matcher.Matcher<{0}, {1}>", tInput, tResult); } // also analyze arguments (because they are not children) else if (node is AST.Args) { AST.Args args = node as AST.Args; if (args.Parms != null) Analyze(args.Parms, currentRule); } // collect rule bodies else if (node is AST.Rule) { currentRule = node as AST.Rule; ruleNodes.Add(currentRule); string ruleName = node.GetText().Trim(); if (!string.IsNullOrEmpty(currentRule.Override)) overrides[ruleName] = currentRule.Override; AST.AstNode oldBody; if (ruleBodies.TryGetValue(ruleName, out oldBody)) ruleBodies[ruleName] = new AST.Or(oldBody, currentRule.Body); else ruleBodies.Add(ruleName, currentRule.Body); } // collect input classes else if (node is AST.InputClass) { AST.InputClass input = node as AST.InputClass; foreach (AST.AstNode child in input.Inputs) { if (child is AST.Code) { input.Chars.Add(TrimBraces(child.GetText().Trim()).Trim()); } else if (child is AST.ClassRange) { foreach (char ch in ((AST.ClassRange)child).Inputs) { input.Chars.Add(string.Format("'\\u{0:x4}'", (int)ch)); } } } } // hoist rule bodies inside calls else if (node is AST.Call) { HoistCalledDisjunctions(currentRule, node as AST.Call); } // recurse if (node.Children != null) { foreach (AST.AstNode child in node.Children) { if (child != null) Analyze(child, currentRule); } } }
void GenerateBindPost(TextWriter tw, HashSet<string> vars, AST.Bind node, int n, bool match_args, string indent) { string name = node.GetText().Trim(); tw.Write(indent); tw.WriteLine("// BIND {0}", name); tw.Write(indent); if (match_args) tw.WriteLine("{0} = _memo.ArgResults.Peek();", name); else tw.WriteLine("{0} = _memo.Results.Peek();", name); tw.WriteLine(); vars.Add(name); }
void GenerateActPost(TextWriter tw, AST.Act node, int n, bool match_args, string indent) { string action = TrimBraces(node.GetText().Trim()).Trim(); action = action.Replace("\t", " "); if (!action.Contains("return")) action = "return " + action + ";"; tw.Write(indent); tw.WriteLine("// ACT"); if (match_args) { tw.Write(indent); tw.WriteLine("var _r{0} = _memo.ArgResults.Peek();", n); tw.Write(indent); tw.WriteLine("if (_r{0} != null)", n); tw.Write(indent); tw.WriteLine("{"); tw.Write(indent); tw.WriteLine(" _memo.ArgResults.Pop();"); tw.Write(indent); tw.WriteLine(" _memo.ArgResults.Push( new {1}(_r{0}.StartIndex, _r{0}.NextIndex, _r{0}.Inputs, _Thunk(_IM_Result => {{ {2} }}, _r{0}), false) );", n, tItem, action); tw.Write(indent); tw.WriteLine("}"); } else { tw.Write(indent); tw.WriteLine("var _r{0} = _memo.Results.Peek();", n); tw.Write(indent); tw.WriteLine("if (_r{0} != null)", n); tw.Write(indent); tw.WriteLine("{"); tw.Write(indent); tw.WriteLine(" _memo.Results.Pop();"); tw.Write(indent); tw.WriteLine(" _memo.Results.Push( new {2}(_r{0}.StartIndex, _r{0}.NextIndex, _memo.InputEnumerable, _Thunk(_IM_Result => {{ {1} }}, _r{0}), true) );", n, action, tItem); tw.Write(indent); tw.WriteLine("}"); } tw.WriteLine(); }
void GenerateCallPost(TextWriter tw, HashSet<string> vars, AST.Call node, int n, bool match_args, string indent) { string name = node.GetText().Trim(); tw.Write(indent); tw.WriteLine("// CALL {0}", name); if (match_args) { throw new Exception(string.Format("{0}: you are not allowed to call rules in argument patterns.", name)); } else { tw.Write(indent); tw.WriteLine("var _start_i{0} = _index;", n); tw.Write(indent); tw.WriteLine("{1} _r{0};", n, tItem); bool isVar = vars.Contains(name); if (node.Params != null && node.Params.Any()) { List<string> plist = GenerateActualParams(tw, vars, node, n, name, indent); tw.WriteLine(); tw.Write(indent); tw.WriteLine("_r{3} = _MemoCall(_memo, {0}, _index, {4}, new {2}[] {{ {1} }});", isVar ? name + ".ProductionName" : "\"" + name + "\"", string.Join(", ", plist.ToArray()), tItem, n, isVar ? name + ".Production" : name); } else { tw.Write(indent); tw.WriteLine("_r{1} = _MemoCall(_memo, {0}, _index, {2}, null);", isVar ? name + ".ProductionName" : "\"" + name + "\"", n, isVar ? name + ".Production" : name); } tw.WriteLine(); tw.Write(indent); tw.WriteLine("if (_r{0} != null) _index = _r{0}.NextIndex;", n); tw.WriteLine(); } }
void GenerateCallOrVarPost(TextWriter tw, HashSet<string> vars, AST.CallOrVar node, int n, bool match_args, string indent) { string name = node.GetText().Trim(); tw.Write(indent); tw.WriteLine("// CALLORVAR {0}", name); if (match_args) { if (vars.Contains(name)) { tw.Write(indent); tw.WriteLine("var _r{0} = _ParseLiteralArgs(_memo, ref _arg_index, ref _arg_input_index, {1}.Inputs, _args);", n, name); tw.Write(indent); tw.WriteLine("if (_r{0} != null) _arg_index = _r{0}.NextIndex;", n); } else { throw new Exception(string.Format("{0}: you are not allowed to call rules in argument patterns.", name)); } } else { tw.Write(indent); tw.WriteLine("{1} _r{0};", n, tItem); tw.WriteLine(); if (vars.Contains(name)) { tw.Write(indent); tw.WriteLine("if ({0}.Production != null)", name); tw.Write(indent); tw.WriteLine("{"); tw.Write(indent); tw.WriteLine(" var _p{0} = (System.Action<_{3}_Memo, int, IEnumerable<{1}>>)(object){2}.Production; // what type safety?", n, tItem, name, gName); tw.Write(indent); tw.WriteLine(" _r{0} = _MemoCall(_memo, RuntimeReflectionExtensions.GetMethodInfo({1}.Production).Name, _index, _p{0}, null);", n, name); tw.Write(indent); tw.WriteLine("}"); tw.Write(indent); tw.WriteLine("else"); tw.Write(indent); tw.WriteLine("{"); tw.Write(indent); tw.WriteLine(" _r{0} = _ParseLiteralObj(_memo, ref _index, {1}.Inputs);", n, name); tw.Write(indent); tw.WriteLine("}"); } else { tw.Write(indent); tw.WriteLine("_r{1} = _MemoCall(_memo, \"{0}\", _index, {0}, null);", name, n); } tw.WriteLine(); tw.Write(indent); tw.WriteLine("if (_r{0} != null) _index = _r{0}.NextIndex;", n); } tw.WriteLine(); }