/// <summary> /// Consumes an ASTNode + Child elements to produce a JListValue node + Child elements. /// </summary> /// <returns>The ASTN ode.</returns> /// <param name="astNode">Ast node.</param> internal static Value FromASTNode(AbstractSyntaxNode astNode) { AbstractSyntaxTerminalNode terminalNode = astNode.As <AbstractSyntaxTerminalNode>(); AbstractSyntaxRuleNode ruleNode = astNode.As <AbstractSyntaxRuleNode>(); if (terminalNode != null) { if (terminalNode.TerminalSymbol.Name.Equals("NUMBER", StringComparison.Ordinal)) { long l; if (long.TryParse(terminalNode.Value, out l)) { return(new LongValue(l)); } else { return(new ErrorValue($"Invalid number '{terminalNode.Value}'.")); } } else if (terminalNode.TerminalSymbol.Name.Equals("SYMBOL", StringComparison.Ordinal)) { return(new SymbolValue(terminalNode.Value)); } else if (terminalNode.TerminalSymbol.Name.Equals("STRING", StringComparison.Ordinal)) { return(StringValue.ReadRegexString(terminalNode.Value)); } else if (terminalNode.TerminalSymbol.Name.Equals("COMMENT", StringComparison.Ordinal)) { return(new SExprValue()); } } else if (ruleNode != null) { if (new string[] { "JLisp", "SExpr" }.Contains(ruleNode.ProductionRule.Name)) { var s = new SExprValue(); BuildJLispExprValueChildren(ruleNode, s.Cell); return(s); } else if (ruleNode.ProductionRule.Name.Equals("QExpr", StringComparison.Ordinal)) { var q = new QExprValue(); BuildJLispExprValueChildren(ruleNode, q.Cell); return(q); } else if (ruleNode.ProductionRule.Name.Equals("Expr", StringComparison.Ordinal)) { return(FromASTNode(ruleNode.Children[0])); // Should only be one !! } } return(new ErrorValue("No handling for astNode: " + astNode)); }
/// <summary> /// Is the tree a single expression, or multiple expressions to be evaluated in turn. /// </summary> static bool IsMultiExpression(AbstractSyntaxNode node) { // if this is a Root Node "JLisp" // And each child node is an Expr by virtue of being an SExpr then we consider this to be multiple expression // This is typically of use when dealing with files. // Each expression should be fully formed i.e "(+ 1 2 3)" not "+ 1 2 3" if (node is AbstractSyntaxRuleNode && node.As <AbstractSyntaxRuleNode>().ProductionRule.Name.Equals("JLisp") && node.As <AbstractSyntaxRuleNode>().Children.TrueForAll( c => c is AbstractSyntaxRuleNode && c.As <AbstractSyntaxRuleNode>().ProductionRule.Name.Equals("Expr") && (c.As <AbstractSyntaxRuleNode>().RulePartIndex == 4 || // S-Expr c.As <AbstractSyntaxRuleNode>().RulePartIndex == 3) // Comment ) ) { return(true); } return(false); }
/// <summary> /// Process an ast which could lead to zero or many Value Trees.. /// </summary> public IEnumerable <Value> Evaluate(AbstractSyntaxNode asTree) { if (IsMultiExpression(asTree)) { foreach (var subTree in asTree.As <AbstractSyntaxRuleNode>().Children) { var valueTree = Value.FromASTNode(subTree); yield return(Evaluate(valueTree)); } } else { var valueTree = Value.FromASTNode(asTree); yield return(Evaluate(valueTree)); } yield break; }