private void BuildList(PropertyInfo property, object astNode, CstNonterminalNode cstNode) { ConsumeExpression[] expressions = astAttributes[cstNode.Nonterminal].Select(o => o.GetExpression()).ToArray(); Expression expression = cstNode.Nonterminal.Expression; if (expressions.Length > 0 || (expression is Sequence || expression is ZeroOrMore || expression is OneOrMore)) { IEnumerable <ICstNonterminalNode> itemNodes; if (expressions.Length > 0) { itemNodes = GetChildrenByAstExpression(cstNode, expressions); } else { Func <Expression, Nonterminal> findNonterminal = null; findNonterminal = current => { if (current is Nonterminal) { return((Nonterminal)current); } else if (current is Sequence) { return(findNonterminal(((Sequence)current).Expressions.First())); } else if (current is ZeroOrMore) { return(findNonterminal(((ZeroOrMore)current).Operand)); } else { return(findNonterminal(((OneOrMore)current).Operand)); } }; Nonterminal nonterminal = findNonterminal(expression); itemNodes = GetChildrenByNonterminal(cstNode, nonterminal); } IList list = (IList)Activator.CreateInstance(property.PropertyType); Type listType = property.PropertyType.GetListElementType(); foreach (var childNode in itemNodes) { object listItemAstNode = Build(listType, childNode); list.Add(listItemAstNode); } property.SetValue(astNode, list, null); } else { IList list = (IList)Activator.CreateInstance(property.PropertyType); Type listType = property.PropertyType.GetListElementType(); object listItemAstNode = Build(listType, cstNode); list.Add(listItemAstNode); property.SetValue(astNode, list, null); } }
// public static PegBuilder<ConsumeChoice> Builder = new PegBuilder<ConsumeChoice>(Grammar); public static ConsumeExpression Parse(string s) { var result = Parser.ParseString(s); // Bypass BnfBuilder because that depends on this in order to work CstNonterminalNode cst = CstBuilder.Build(result); return(BuildChoice(cst)); }
private static ConsumeIndexExpression BuildIndexExpression(CstNonterminalNode node) { ConsumeIndexExpression expression = new ConsumeIndexExpression(); CstNonterminalNode targetNode = (CstNonterminalNode)node.Children[0]; expression.Target = BuildExpression(targetNode); // CstNonterminalNode indexNode = (CstNonterminalNode)((Token)((ICstTerminalNode)node.Children[2]).Terminal).StructuredLexeme; expression.Index = int.Parse(node.Children[2].Coalesce()); return(expression); }
/// <summary> /// Replaces all occurances of the pattern within input according to the definition provided /// by replacements. /// </summary> public static string Replace(this Expression expression, string input, params Replacement[] replacements) { // We want the expression to act like a nonterminal so that its contents get grouped up in the CST if (!(expression is Nonterminal)) { expression = expression.Capture(); } // Modify the expression to allow any character (allows matching substrings) var exp = +(expression | new AnyCharacter(true)); var parser = CreateParser(exp); var output = parser.ParseString(input); if (!output.Any()) { return(input); } var cst = CstBuilder.Build(output); cst = (CstNonterminalNode)cst.Children[0]; var transformedCst = new CstNonterminalNode(cst.Nonterminal, -1); foreach (var child in cst.Children) { if (child is CstNonterminalNode) { var childNonterminal = (CstNonterminalNode)child; var cache = new CstCache(childNonterminal); var map = replacements.ToDictionary(x => x.From, x => x.To.Replace(cache)); var transformed = childNonterminal.Transform(x => map.ContainsKey(x.Nonterminal) ? map[x.Nonterminal] : null); transformedCst.Children.Add(transformed); } else { transformedCst.Children.Add(child); } } return(transformedCst.Coalesce()); }
public Type GetSubclass(ref CstNonterminalNode node, string ruleName) { foreach (var type in astTypes[ruleName]) { if (type.expression == null || type.expression.Resolve(node).Any()) { return(type.type); } } if (node.Children.Count == 1 && node.Children[0] is CstNonterminalNode) { CstNonterminalNode childNode = (CstNonterminalNode)node.Children[0]; Type result = GetSubclass(ref childNode, childNode.Nonterminal.Name); node = childNode; return(result); } throw new InvalidOperationException("No subclass registered for " + ruleName + ". Consider adding [Ast(typeof(YourAstNode)] to " + ruleName); }
private static ConsumeChoice BuildChoice(CstNonterminalNode node) { ConsumeChoice result = new ConsumeChoice(); CstNonterminalNode current = node; while (current != null) { if (current.Children.Count == 1) { result.Choices.Insert(0, BuildConditional((CstNonterminalNode)current.Children[0])); current = null; } else { result.Choices.Insert(0, BuildConditional((CstNonterminalNode)current.Children[2])); current = (CstNonterminalNode)current.Children[0]; } } return(result); }
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); }
private static ConsumeExpression BuildExpression(CstNonterminalNode node) { CstNonterminalNode expressionType = (CstNonterminalNode)node.Children[0]; if (expressionType.Nonterminal.Name == "Expression") { expressionType = (CstNonterminalNode)expressionType.Children[0]; } switch (expressionType.Nonterminal.Name) { case "ReferenceExpression": return(BuildReferenceExpression(expressionType)); case "IndexExpression": return(BuildIndexExpression(expressionType)); default: throw new InvalidOperationException(); } }
private static ConsumeConditional BuildConditional(CstNonterminalNode node) { CstNonterminalNode predicate; CstNonterminalNode expression; if (node.Children.Count == 1) { predicate = null; expression = (CstNonterminalNode)node.Children[0]; } else { predicate = (CstNonterminalNode)node.Children[0]; expression = (CstNonterminalNode)node.Children[2]; } ConsumeConditional conditional = new ConsumeConditional(); if (predicate != null) { conditional.Predicate = BuildExpression(predicate); } conditional.Expression = BuildExpression(expression); return(conditional); }
public T Build(CstNonterminalNode rootNode) { object astNode = Build(typeof(T), rootNode); return((T)astNode); }
public T Build(IEnumerable <OutputRecord> outputStream) { CstNonterminalNode cstNode = CstBuilder.Build(outputStream); return(Build((CstNonterminalNode)cstNode.Children[0])); }
/// <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); }