/// <summary> /// An EXPR is normally just a string literal, but is still an AST that /// we must evaluate. The EXPR can be any expression such as a template /// include or string cat expression etc... /// /// Evaluate with its own writer so that we can convert to string and then /// reuse, don't want to compute all the time; must precompute w/o writing /// to output buffer. /// </summary> protected internal string EvaluateExpression(StringTemplate self, object expr) { if (expr == null) { return null; } if (expr is StringTemplateAST) { StringTemplateAST exprTree = (StringTemplateAST) expr; // must evaluate, writing to a string so we can hand on to it StringWriter buf = new StringWriter(); IStringTemplateWriter sw = self.group.CreateInstanceOfTemplateWriter(buf); ActionEvaluator eval = new ActionEvaluator(self, this, sw); try { eval.action(exprTree); // eval tree } catch (RecognitionException ex) { self.Error("can't evaluate tree: " + exprTree.ToStringList(), ex); } return buf.ToString(); } else { // just in case we expand in the future and it's something else return expr.ToString(); } }
/// <summary> /// To write out the value of an ASTExpr, invoke the evaluator in eval.g /// to walk the tree writing out the values. For efficiency, don't /// compute a bunch of strings and then pack them together. Write out directly. /// /// Compute separator and wrap expressions, save as strings so we don't /// recompute for each value in a multi-valued attribute or expression. /// /// If they set anchor option, then inform the writer to push current /// char position. /// </summary> public override int Write(StringTemplate self, IStringTemplateWriter output) { if (exprTree == null || self == null || output == null) { return 0; } output.PushIndentation(Indentation); // handle options, anchor, wrap, separator... StringTemplateAST anchorAST = (StringTemplateAST)GetOption("anchor"); if (anchorAST != null) // any non-empty expr means true; check presence { output.PushAnchorPoint(); } HandleExprOptions(self); ActionEvaluator eval = new ActionEvaluator(self, this, output); ActionParser.initializeASTFactory(eval.getASTFactory()); int n = 0; try { n = eval.action(exprTree); // eval and write out tree } catch (RecognitionException re) { self.Error("can't evaluate tree: " + exprTree.ToStringList(), re); } output.PopIndentation(); if (anchorAST != null) { output.PopAnchorPoint(); } return n; }