private static ConsumeReferenceExpression BuildReferenceExpression(CstNonterminalNode node) { ConsumeReferenceExpression expression = new ConsumeReferenceExpression(); if (node.Children.Count == 1) { // CstNonterminalNode nonterminal = (CstNonterminalNode)((Token)((ICstTerminalNode)node.Children[0]).Terminal).StructuredLexeme; expression.NonTerminal = node.Children[0].Coalesce(); } else { CstNonterminalNode targetNode = (CstNonterminalNode)node.Children[0]; ConsumeExpression target = BuildExpression(targetNode); expression.Target = target; // CstNonterminalNode nonterminal = (CstNonterminalNode)((Token)((ICstTerminalNode)node.Children[2]).Terminal).StructuredLexeme; expression.NonTerminal = node.Children[2].Coalesce();//nonterminal.Coalesce(); } return(expression); }
/// <summary> /// /// </summary> /// <param name="astNodeType">The type of node we are creating. A subclass might possibly be selected.</param> /// <param name="cstNode">The CST node that represents the structured input for the specified AST node</param> /// <returns>The new astNode of the specified astNodeType that consumes the cstNode</returns> private object Build(Type astNodeType, ICstNode cstNode) { int consumeIndex = 0; if (astNodeType.IsAbstract || astNodeType.IsInterface) { string ruleName = ((CstNonterminalNode)cstNode).Nonterminal.Name; CstNonterminalNode cstNonterminalNode = (CstNonterminalNode)cstNode; astNodeType = GetSubclass(ref cstNonterminalNode, ruleName); cstNode = cstNonterminalNode; } object astNode; try { if (astNodeType == typeof(string)) { return(cstNode.Coalesce()); } else if (astNodeType == typeof(int)) { return(int.Parse(cstNode.Coalesce())); } else if (astNodeType == typeof(byte)) { return(byte.Parse(cstNode.Coalesce())); } else if (astNodeType == typeof(short)) { return(short.Parse(cstNode.Coalesce())); } else if (astNodeType == typeof(long)) { return(long.Parse(cstNode.Coalesce())); } else if (astNodeType == typeof(float)) { return(float.Parse(cstNode.Coalesce())); } else if (astNodeType == typeof(double)) { return(double.Parse(cstNode.Coalesce())); } else if (astNodeType == typeof(decimal)) { return(decimal.Parse(cstNode.Coalesce())); } else if (astNodeType == typeof(bool)) { return(bool.Parse(cstNode.Coalesce())); } else { astNode = CreateAstNode(astNodeType); } } catch (Exception e) { throw new InvalidOperationException("Error instantiating " + astNodeType.FullName, e); } foreach (PropertyInfo property in astNode.GetType().GetAllPropertiesInAncestry()) { ConsumeAttribute[] consumeAttributes = property.GetAttributes <ConsumeAttribute>(); foreach (ConsumeAttribute consumeAttribute in consumeAttributes) { if (consumeIndex > 0 && consumeIndex != consumeAttribute.Production) { continue; } CstNonterminalNode productionNode = cstNode as CstNonterminalNode; // 1) Handle the simple case where the NonTerminal exactly matches the NonTerminal property of our consume attribute // 2) Handle the empty [Consume] case, which means it goes into this block no matter what. // Get the expression (parsed from the NonTerminal property) ConsumeExpression expression = consumeAttribute.GetExpression(); // The goal of the expression is to bring us to a new CST node (a descendent of the current one) ICstNode newCstNode; try { newCstNode = expression != null?expression.Resolve(productionNode).FirstOrDefault() : productionNode; } catch (Exception e) { throw new InvalidOperationException("Error resolving expression '" + consumeAttribute.Expression + "' for " + property.GetPath(), e); } // There are a number of reasons why the new cst node might be null. It is perfectly // legal to specify nonterminal expressions that only resolve under certain productions. // In other scenarios, it will remain null. if (newCstNode != null) { // If the Value property is set, then we simply assign the property to that value (since newCstNode is not null) if (consumeAttribute.Value != null) { property.SetValue(astNode, consumeAttribute.Value, null); } else if (consumeAttribute.Type != null) { Coalesce(astNode, property, newCstNode, consumeAttribute.Type); } else { MapProperty(property, astNode, newCstNode); } goto nextProperty; } } var impliedCstNode = ((CstNonterminalNode)cstNode).Children.OfType <ICstNonterminalNode>().SingleOrDefault(o => o.Nonterminal.Name == property.Name); if (impliedCstNode != null) { MapProperty(property, astNode, impliedCstNode); } nextProperty :; } return(astNode); }
public TypeRecord(ConsumeExpression expression, Type type) { this.expression = expression; this.type = type; }