public void EvalTryParse(RCRunner runner, RCClosure closure, RCString right) { bool fragment; RCValue val; RCBlock result = RCBlock.Empty; try { val = DoParse(new RCLParser(RCSystem.Activator), right, false, out fragment); result = new RCBlock(result, "status", ":", new RCLong(0)); result = new RCBlock(result, "fragment", ":", new RCBoolean(fragment)); result = new RCBlock(result, "data", ":", val); } catch (Exception ex) { result = new RCBlock(result, "status", ":", new RCLong(1)); result = new RCBlock(result, "fragment", ":", new RCBoolean(false)); string message = ex.ToString(); RCBlock report = new RCBlock("", ":", new RCString(message + "\n")); int escapeCount = RCTemplate.CalculateReportTemplateEscapeLevel(message); result = new RCBlock(result, "error", ":", new RCTemplate(report, escapeCount, true)); } runner.Yield(closure, result); }
/* * protected Type InferType(string[] name, string original) * { * //Let's try to figure it out! * RCValue target = null; * * //Try the block under construction. * if (_block != null) * { * target = _block.Get(name); * } * * //Try to find it higher up the stack. * if (target == null) * { * RCBlock[] parents = _blocks.ToArray(); * //When you ToArray the stack items come out in the same order * //you would have taken them off the stack. * for (int i = 0; i < parents.Length; ++i) * { * //There will be null blocks on the stack. * if (parents[i] != null) * { * target = parents[i].Get(name); * if (target != null) break; * } * } * } * * if (target == null) * { * throw new Exception("Unable to infer type for reference " + original + "."); * } * else return target.Yields; * } */ protected RCVectorBase MakeVector(RCArray <RCToken> vector) { RCVectorBase result = null; if (vector[0].Text[0] == '~') { switch (vector[0].Text[1]) { case 'x': return(RCByte.Empty); case 'b': return(RCBoolean.Empty); case 'l': return(RCLong.Empty); case 'd': return(RCDouble.Empty); case 'm': return(RCDecimal.Empty); case 's': return(RCString.Empty); case 'y': return(RCSymbol.Empty); case 't': return(RCTime.Empty); case 'n': return(RCIncr.Empty); default: throw new Exception("Unrecognized type code: " + vector[0].Text[1]); } } if (vector[0].Type == RCTokenType.Symbol) { RCArray <RCSymbolScalar> list = new RCArray <RCSymbolScalar> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseSymbol(_lexer)); } result = new RCSymbol(list); } else if (vector[0].Type == RCTokenType.String) { RCArray <string> list = new RCArray <string> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseString(_lexer)); } result = new RCString(list); } else if (vector[0].Type == RCTokenType.Boolean) { RCArray <bool> list = new RCArray <bool> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseBoolean(_lexer)); } result = new RCBoolean(list); } else if (vector[0].Type == RCTokenType.Incr) { RCArray <RCIncrScalar> list = new RCArray <RCIncrScalar> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseIncr(_lexer)); } result = new RCIncr(list); } else if (vector[0].Type == RCTokenType.Literal) { char type = vector[0].Text[1]; switch (type) { case 'x': RCArray <byte> list = new RCArray <byte> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseByte(_lexer)); } result = new RCByte(list); break; default: throw new Exception("Unknown type specifier:" + type); } } else if (vector[0].Type == RCTokenType.Time) { RCArray <RCTimeScalar> list = new RCArray <RCTimeScalar> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseTime(_lexer)); } result = new RCTime(list); } else if (vector[0].Type == RCTokenType.Number) { // have a look at the last character in the last token // if there is a type specifier there we will use it to // create the appropriate type of vector. RCToken last = vector[vector.Count - 1]; char type = last.Text[last.Text.Length - 1]; if (type == 'l') { RCArray <long> list = new RCArray <long> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseLong(_lexer)); } result = new RCLong(list); } if (type == 'd') { RCArray <double> list = new RCArray <double> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseDouble(_lexer)); } result = new RCDouble(list); } else if (type == 'm') { RCArray <decimal> list = new RCArray <decimal> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseDecimal(_lexer)); } result = new RCDecimal(list); } else // default to double { if (vector[0].Text.IndexOf('.') > -1 || vector[0].Text == "NaN") { RCArray <double> list = new RCArray <double> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseDouble(_lexer)); } result = new RCDouble(list); } else { RCArray <long> list = new RCArray <long> (vector.Count); for (int i = 0; i < vector.Count; ++i) { list.Write(vector[i].ParseLong(_lexer)); } result = new RCLong(list); } } } return(result); }
protected static RCString ExpandTemplate(StringBuilder builder, RCTemplate template, RCBlock right, int I, string parentIndent) { string indent = parentIndent; for (int i = 0; i < right.Count; ++i) { RCValue child = right.Get(i); RCVector <string> text = child as RCVector <string>; if (text == null) { RCArray <string> strings = new RCArray <string> (right.Count); RCBlock nestedBlock = (RCBlock)child; for (int j = 0; j < nestedBlock.Count; ++j) { strings.Write(nestedBlock.GetString(j)); } text = new RCString(strings); // ExpandTemplate (builder, template, (RCBlock) child, I + i, indent); } // else { bool somethingAdded = false; for (int j = 0; j < text.Count; ++j) { string section = text[j]; int start = 0; int lineNum = 0; for (int k = 0; k < section.Length; ++k) { if (section[k] == '\n') { string line; if (i % 2 == 1) { if (k > 0 && section.Length > 0 && section[k - 1] == '\r') { line = section.Substring(start, k - start - 1); } else { line = section.Substring(start, k - start); } // if (j > 0 || start > 0) // Using j and start here didn't work because sometimes empty strings // are added. Instead keep track of whether a line has been added. // We may need this variable to handle other cases as well, but // they haven't cropped yet. if (somethingAdded) { // Notice below in the section with w. If there is extra content // before the code section on the same line, it will have been // inserted/indented already. builder.Append(indent); } builder.Append(line); builder.Append("\n"); somethingAdded = true; } else { // In content sections after the first one, // skip newlines if they are the first thing in the section. line = section.Substring(start, k - start); if (I + i == 0) { builder.Append(line); builder.Append("\n"); } else if (line != "") { if (builder[builder.Length - 1] == '\n') { if (start == 0 && (k < section.Length - 1 || i == right.Count - 1)) { builder.Append(indent); } else if (k == section.Length - 1 && i < right.Count - 1) { builder.Append(indent); } } builder.Append(line); builder.Append("\n"); } else if (k > 0 || (builder.Length > 0 && builder[builder.Length - 1] != '\n')) { builder.Append(line); builder.Append("\n"); } } start = k + 1; ++lineNum; } } if (template.Multiline) { // If this is a code section, the lastPiece is just the last line of the // template. // There is no newline at the end. // If this is a text section, the lastPiece is a prefix for the next code // section. string lastPiece = section.Substring(start, section.Length - start); if (i % 2 == 1) { // Odd sections are always code sections. // Code sections don't have a newline at the end. if (j == 0) { // This means there was a newline at the end of section. if (start > 0 && lastPiece != "") { builder.Append(indent); } } else if (j == text.Count - 1) { indent = parentIndent; } builder.Append(lastPiece); } else { int w; for (w = 0; w < lastPiece.Length; ++w) { if (lastPiece[w] != ' ') { break; } } // indent only includes spaces before the first non-space character. // The non-space part of the text is only inserted once. // An edge case involves spaces inserted between code sections on the same // line. // \t not spoken here. // while (builder.Length == 0 || builder[builder.Length - 1] == '\n') { string end; if (builder.Length == 0 || builder[builder.Length - 1] == '\n') { indent = parentIndent + lastPiece.Substring(0, w); end = lastPiece.Substring(w, lastPiece.Length - w); } else { end = lastPiece; } if (i < right.Count - 1) { if (section.Length > 0) { if (builder.Length == 0 || builder[builder.Length - 1] == '\n') { builder.Append(indent); } } } builder.Append(end); } } } else { // If there are no newlines in the template then just drop the whole thing // in as is. builder.Append(text[j]); } } } } // Go back and remove the final newline now. // Let the enclosing template decide how to finish off. if (template.Multiline) { if (builder.Length > 0 && builder[builder.Length - 1] != '\n') { builder.Append("\n"); } } return(new RCString(builder.ToString())); }
// Kicks off evaluation for a block. public static void DoEval(RCRunner runner, RCClosure closure, RCBlock block) { if (block.Count == 0) { DoYield(runner, closure, block); } else { RCBlock current = block.GetName(closure.Index); if (current.Evaluator.Invoke) { string op = ((RCString)current.Value)[0]; RCSystem.Activator.Invoke(runner, closure, op, closure.Result); } else if (current.Evaluator.Template) { try { RCString result = ExpandTemplate(new StringBuilder(), (RCTemplate)current, closure.Result, 0, ""); runner.Yield(closure, result); } catch (Exception ex) { RCException rcex = new RCException(closure, ex, RCErrors.Native, "An exception was thrown by the template."); runner.Finish(closure, rcex, (int)RCErrors.Native); } } else if (current.Evaluator.Pass) { DoYield(runner, closure, current.Value); } // This means that Value is an operator or a reference. else if (current.Value.ArgumentEval) { current.Value.Eval(runner, new RCClosure(closure, closure.Bot, current.Value, closure.Left, closure.Result, 0)); } else if (current.Evaluator.Return) { DoYield(runner, closure, current.Value); } else { // I need something different to happen when we are at the top level already. // Or maybe I need to inject a wrapper closure when I do Rep this way? if ((closure.Index < block.Count - 1) || (closure.Parent != null)) { DoYield(runner, closure, current.Value); } else { DoYield(runner, closure, current); } } } }
public void EvalEval(RCRunner runner, RCClosure closure, RCBlock left, RCString right) { runner.Yield(closure, right); }
public RCLArgv(params string[] argv) { Exit = false; Batch = false; NoKeys = false; NoResult = false; Version = false; FullStack = false; Program = ""; Action = ""; Output = "full"; Show = new string[] { "*" }; Hide = new string[] { }; RCBlock custom = RCBlock.Empty; List <string> arguments = new List <string> (); for (int i = 0; i < argv.Length; ++i) { string[] kv = argv[i].Split('='); if (kv.Length == 1) { if (kv[0].StartsWith("--")) { string option = kv[0].Substring(2); if (option.Equals("exit")) { Exit = true; } else if (option.Equals("batch")) { Batch = true; } else if (option.Equals("nokeys")) { NoKeys = true; } else if (option.Equals("noread")) { NoRead = true; } else if (option.Equals("noresult")) { NoResult = true; } else if (option.Equals("fullstack")) { FullStack = true; } else if (option.Equals("version")) { // This option forces the version to display no matter what. // Useful when you need to check the version number from a test. Version = true; } else { custom = new RCBlock(custom, option, ":", RCBoolean.True); } } else if (kv[0].StartsWith("-")) { for (int j = 1; j < kv[0].Length; ++j) { char c; switch (c = kv[0][j]) { case 'x': Exit = true; break; case 'b': Batch = true; break; case 'k': NoKeys = true; break; case 'r': NoRead = true; break; case 'v': Version = true; break; default: Usage("Unknown option '" + kv[0][j] + "'"); break; } } } else { // do position. arguments.Add(kv[0]); } } else { // do named arguments. if (kv[0].StartsWith("--")) { string option = kv[0].Substring(2); if (option.Equals("program")) { Program = kv[1]; } else if (option.Equals("action")) { Action = kv[1]; } else if (option.Equals("output")) { Output = kv[1]; } else if (option.Equals("show")) { Show = kv[1].Split(','); } else if (option.Equals("hide")) { Hide = kv[1].Split(','); } else { custom = new RCBlock(custom, option, ":", new RCString(kv[1])); } } else { Usage("Named options start with --"); } } } Arguments = new RCString(arguments.ToArray()); Options = RCBlock.Empty; Options = new RCBlock(Options, "program", ":", new RCString(Program)); Options = new RCBlock(Options, "action", ":", new RCString(Action)); Options = new RCBlock(Options, "output", ":", new RCString(Output)); Options = new RCBlock(Options, "show", ":", new RCString(Show)); Options = new RCBlock(Options, "hide", ":", new RCString(Hide)); Options = new RCBlock(Options, "batch", ":", new RCBoolean(Batch)); Options = new RCBlock(Options, "nokeys", ":", new RCBoolean(NoKeys)); Options = new RCBlock(Options, "noread", ":", new RCBoolean(NoRead)); Options = new RCBlock(Options, "noresult", ":", new RCBoolean(NoResult)); Options = new RCBlock(Options, "exit", ":", new RCBoolean(Exit)); Options = new RCBlock(Options, "version", ":", new RCBoolean(Version)); Options = new RCBlock(Options, "fullstack", ":", new RCBoolean(FullStack)); OutputEnum = (RCOutput)Enum.Parse(typeof(RCOutput), Output, true); for (int i = 0; i < custom.Count; ++i) { RCBlock name = custom.GetName(i); Options = new RCBlock(Options, name.Name, ":", name.Value); } }
public static void DoFormat(RCTemplate template, StringBuilder builder, RCFormat args, RCColmap colmap, int level) { // templates need to follow the same indenting rules as everyone else please. builder.Append("["); builder.Append('?', template.EscapeCount); // Use AppendLine not args.Newline, because the newline is signficant // and needs to be there no matter what. Otherwise when we parse it again ++level; if (template.Multiline) { builder.Append("\n"); for (int tab = args.Fragment ? 1 : 0; tab < level; ++tab) { builder.Append(args.Indent); } } for (int i = 0; i < template.Count - 1; ++i) { RCValue child = template.Get(i); RCString str = child as RCString; if (str != null && i % 2 == 0) { for (int j = 0; j < str.Count; ++j) { // Now go through str one char at a time to find the newlines. int start = 0, end = 0; for (; end < str[j].Length; ++end) { if (str[j][end] == '\n') { string line = str[j].Substring(start, end - start); builder.Append(line); builder.Append("\n"); if (i < template.Count - 2 || end < str[j].Length - 1) { for (int tab = args.Fragment ? 1 : 0; tab < level; ++tab) { builder.Append(args.Indent); } } start = end + 1; } else if (end == str[j].Length - 1) { builder.Append(str[j].Substring(start, 1 + end - start)); } } } } else { if (template.Multiline) { // for (int tab = 0; tab < level; ++tab) // { // builder.Append (args.Indent); // } /* * int k = builder.Length - 1; * while (k >= 0) * { * if (builder[k] == '\n') * { * for (int tab = 0; tab < level; ++tab) * { * builder.Append (args.Indent); * } * break; * } * else if (builder[k] != ' ') * { * break; * } * --k; * } */ } builder.Append("["); builder.Append('!', template.EscapeCount); builder.Append(' '); child.Format(builder, RCFormat.Default, colmap, level); builder.Append(' '); builder.Append('!', template.EscapeCount); builder.Append("]"); } } --level; if (template.Multiline) { for (int tab = args.Fragment ? 1 : 0; tab < level; ++tab) { builder.Append(args.Indent); } } builder.Append('?', template.EscapeCount); builder.Append("]"); }
public void EvalFail(RCRunner runner, RCClosure closure, RCString right) { runner.Finish(closure, new RCException(closure, RCErrors.Custom, right[0]), (int)RCErrors.Custom); }