/// <summary> /// Builds the set of rule definitions that are represented by the given AST /// </summary> /// <param name="context">The current context</param> /// <param name="node">The AST node of a syntactic rule</param> /// <returns>The set of possible rule definitions</returns> private RuleBodySet BuildAtomicDefinition(LoaderContext context, ASTNode node) { if (node.Symbol.ID == HimeGrammarParser.ID.VariableRuleSymAction) { return(BuildAtomicAction(node)); } if (node.Symbol.ID == HimeGrammarParser.ID.VariableRuleSymVirtual) { return(BuildAtomicVirtual(node)); } if (node.Symbol.ID == HimeGrammarParser.ID.VariableRuleSymRefSimple) { return(BuildAtomicSimpleReference(context, node)); } if (node.Symbol.ID == HimeGrammarParser.ID.VariableRuleSymRefTemplate) { return(BuildAtomicTemplateReference(context, node)); } if (node.Symbol.ID == HimeGrammarLexer.ID.TerminalLiteralText) { return(BuildAtomicInlineText(node)); } // nothing found ... OnError(node.Position, "Failed to recognize syntactic rule"); RuleBodySet set = new RuleBodySet(); set.Add(new RuleBody()); return(set); }
/// <summary> /// Builds the set of rule definitions that represents a single reference to a template variable /// </summary> /// <param name="context">The current context</param> /// <param name="node">The AST node of a syntactic rule</param> /// <returns>The set of possible rule definitions</returns> private RuleBodySet BuildAtomicTemplateReference(LoaderContext context, ASTNode node) { RuleBodySet defs = new RuleBodySet(); // Get the information string name = node.Children[0].Value; int paramCount = node.Children[1].Children.Count; // check for meta-rule existence if (!context.IsTemplateRule(name, paramCount)) { OnError(node.Children[0].Position, "Unknown meta-rule {0}<{1}> in rule definition", name, paramCount); defs.Add(new RuleBody()); return(defs); } // Recognize the parameters List <Symbol> parameters = new List <Symbol>(); foreach (ASTNode symbolNode in node.Children[1].Children) { parameters.Add(BuildAtomicDefinition(context, symbolNode)[0][0].Symbol); } // Get the corresponding variable Variable variable = context.InstantiateMetaRule(name, parameters); // Create the definition defs.Add(new RuleBody(variable)); return(defs); }
/// <summary> /// Builds the union of the left and right set /// </summary> /// <param name="left">A set of rule bodies</param> /// <param name="right">A set of rule bodies</param> public static RuleBodySet Union(RuleBodySet left, RuleBodySet right) { RuleBodySet result = new RuleBodySet(); result.AddRange(left); result.AddRange(right); return(result); }
/// <summary> /// Builds the set of rule definitions that represents a single semantic action /// </summary> /// <param name="node">The AST node of a syntactic rule</param> /// <returns>The set of possible rule definitions</returns> private RuleBodySet BuildAtomicAction(ASTNode node) { RuleBodySet set = new RuleBodySet(); string name = node.Children[0].Value; Action action = grammar.GetAction(name) ?? grammar.AddAction(name); set.Add(new RuleBody(action)); return(set); }
/// <summary> /// Loads the syntactic rule in the given AST /// </summary> /// <param name="context">The current context</param> /// <param name="node">The AST node of a syntactic rule</param> private void LoadRule(LoaderContext context, ASTNode node) { string name = node.Children[0].Value; Variable var = grammar.GetVariable(name); RuleBodySet defs = BuildDefinitions(context, node.Children[1]); foreach (RuleBody def in defs) { var.AddRule(new Rule(var, TreeAction.None, def, 0)); } }
/// <summary> /// Builds the set of rule definitions that represents a single virtual symbol /// </summary> /// <param name="node">The AST node of a syntactic rule</param> /// <returns>The set of possible rule definitions</returns> private RuleBodySet BuildAtomicVirtual(ASTNode node) { RuleBodySet set = new RuleBodySet(); string name = node.Children[0].Value; name = ReplaceEscapees(name.Substring(1, name.Length - 2)); Virtual vir = grammar.GetVirtual(name) ?? grammar.AddVirtual(name); set.Add(new RuleBody(vir)); return(set); }
/// <summary> /// Builds the product of the left and right set /// </summary> /// <param name="left">A set of rule bodies</param> /// <param name="right">A set of rule bodies</param> public static RuleBodySet Multiply(RuleBodySet left, RuleBodySet right) { RuleBodySet result = new RuleBodySet(); foreach (RuleBody defLeft in left) { foreach (RuleBody defRight in right) { result.Add(RuleBody.Concatenate(defLeft, defRight)); } } return(result); }
/// <summary> /// Builds the set of rule definitions that represents a single reference to a simple variable /// </summary> /// <param name="context">The current context</param> /// <param name="node">The AST node of a syntactic rule</param> /// <returns>The set of possible rule definitions</returns> private RuleBodySet BuildAtomicSimpleReference(LoaderContext context, ASTNode node) { RuleBodySet defs = new RuleBodySet(); Symbol symbol = ResolveSymbol(node.Children[0].Value, context); if (symbol == null) { OnError(node.Children[0].Position, "Unknown symbol {0} in rule definition", node.Children[0].Value); defs.Add(new RuleBody()); } else { defs.Add(new RuleBody(symbol)); } return(defs); }
/// <summary> /// Compile this rule and generate the associated grammar rule /// </summary> /// <param name="context">The current context</param> public void Compile(LoaderContext context) { // Create a new context for recognizing the rule LoaderContext newContext = new LoaderContext(context); // Add the parameters as references in the new context for (int i = 0; i != parameters.Count; i++) { newContext.AddBinding(templateRule.Parameters[i], parameters[i]); } // Recognize the rule with the new context RuleBodySet set = newContext.Loader.BuildDefinitions(newContext, templateRule.DefinitionNode); // Add recognized rules to the variable foreach (RuleBody def in set) { variable.AddRule(new Rule(variable, TreeAction.None, def, 0)); } }
/// <summary> /// Builds the set of rule definitions that represents a single inline piece of text /// </summary> /// <param name="node">The AST node of a syntactic rule</param> /// <returns>The set of possible rule definitions</returns> private RuleBodySet BuildAtomicInlineText(ASTNode node) { // Construct the terminal name string value = node.Value; value = value.Substring(1, value.Length - 2); value = ReplaceEscapees(value); // Check for previous instance in the grammar Terminal terminal = grammar.GetTerminalByValue(value); if (terminal == null) { // Create the terminal NFA nfa = BuildNFAFromText(node); terminal = grammar.AddTerminalAnon(value, nfa); nfa.StateExit.AddItem(terminal); } // Create the definition set RuleBodySet set = new RuleBodySet(); set.Add(new RuleBody(terminal)); return(set); }
/// <summary> /// Builds the set of rule definitions that are represented by the given AST /// </summary> /// <param name="context">The current context</param> /// <param name="node">The AST node of a syntactic rule</param> /// <returns>The set of possible rule definitions</returns> public RuleBodySet BuildDefinitions(LoaderContext context, ASTNode node) { if (node.Symbol.ID == HimeGrammarParser.ID.VariableRuleDefContext) { int contextID = grammar.ResolveContext(node.Children[0].Value); RuleBodySet setInner = BuildDefinitions(context, node.Children[1]); Variable subVar = grammar.GenerateVariable(); foreach (RuleBody def in setInner) { subVar.AddRule(new Rule(subVar, TreeAction.ReplaceByChildren, def, contextID)); } RuleBodySet setVar = new RuleBodySet(); setVar.Add(new RuleBody(subVar)); return(setVar); } else if (node.Symbol.ID == HimeGrammarParser.ID.VariableRuleDefSub) { RuleBodySet setInner = BuildDefinitions(context, node.Children[0]); Variable subVar = grammar.GenerateVariable(); foreach (RuleBody def in setInner) { subVar.AddRule(new Rule(subVar, TreeAction.ReplaceByEpsilon, def, 0)); } RuleBodySet setVar = new RuleBodySet(); setVar.Add(new RuleBody(subVar)); return(setVar); } else if (node.Symbol.ID == HimeGrammarLexer.ID.TerminalOperatorOptional) { RuleBodySet setInner = BuildDefinitions(context, node.Children[0]); setInner.Insert(0, new RuleBody()); return(setInner); } else if (node.Symbol.ID == HimeGrammarLexer.ID.TerminalOperatorZeromore) { RuleBodySet setInner = BuildDefinitions(context, node.Children[0]); Variable subVar = grammar.GenerateVariable(); foreach (RuleBody def in setInner) { subVar.AddRule(new Rule(subVar, TreeAction.ReplaceByChildren, def, 0)); } RuleBodySet setVar = new RuleBodySet(); setVar.Add(new RuleBody(subVar)); setVar = RuleBodySet.Multiply(setVar, setInner); foreach (RuleBody def in setVar) { subVar.AddRule(new Rule(subVar, TreeAction.ReplaceByChildren, def, 0)); } setVar = new RuleBodySet(); setVar.Add(new RuleBody()); setVar.Add(new RuleBody(subVar)); return(setVar); } else if (node.Symbol.ID == HimeGrammarLexer.ID.TerminalOperatorOnemore) { RuleBodySet setInner = BuildDefinitions(context, node.Children[0]); Variable subVar = grammar.GenerateVariable(); foreach (RuleBody def in setInner) { subVar.AddRule(new Rule(subVar, TreeAction.ReplaceByChildren, def, 0)); } RuleBodySet setVar = new RuleBodySet(); setVar.Add(new RuleBody(subVar)); setVar = RuleBodySet.Multiply(setVar, setInner); foreach (RuleBody def in setVar) { subVar.AddRule(new Rule(subVar, TreeAction.ReplaceByChildren, def, 0)); } setVar = new RuleBodySet(); setVar.Add(new RuleBody(subVar)); return(setVar); } else if (node.Symbol.ID == HimeGrammarLexer.ID.TerminalOperatorUnion) { RuleBodySet setLeft = BuildDefinitions(context, node.Children[0]); RuleBodySet setRight = BuildDefinitions(context, node.Children[1]); return(RuleBodySet.Union(setLeft, setRight)); } else if (node.Symbol.ID == HimeGrammarLexer.ID.TerminalTreeActionPromote) { RuleBodySet setInner = BuildDefinitions(context, node.Children[0]); setInner.ApplyAction(TreeAction.Promote); return(setInner); } else if (node.Symbol.ID == HimeGrammarLexer.ID.TerminalTreeActionDrop) { RuleBodySet setInner = BuildDefinitions(context, node.Children[0]); setInner.ApplyAction(TreeAction.Drop); return(setInner); } else if (node.Symbol.Name == "concat") { RuleBodySet setLeft = BuildDefinitions(context, node.Children[0]); RuleBodySet setRight = BuildDefinitions(context, node.Children[1]); return(RuleBodySet.Multiply(setLeft, setRight)); } else if (node.Symbol.Name == "emptypart") { RuleBodySet set = new RuleBodySet(); set.Add(new RuleBody()); return(set); } return(BuildAtomicDefinition(context, node)); }