/// <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> /// Inherits the variables from the parent grammar /// </summary> /// <param name="parent">The parent's grammar</param> /// <param name="doClone">Clone the symbols</param> private void InheritVariables(Grammar parent, bool doClone) { foreach (Variable variable in parent.Variables) { if (doClone) { Variable clone = new Variable(variable.ID, variable.Name); variables.Add(clone.Name, clone); } else { AddVariable(variable.Name); } } foreach (Variable variable in parent.Variables) { Variable clone = variables[variable.Name]; foreach (Rule rule in variable.Rules) { List <RuleBodyElement> parts = new List <RuleBodyElement>(); for (int i = 0; i != rule.Body.Length; i++) { RuleBodyElement part = rule.Body[i]; Symbol symbol = null; if (part.Symbol is Variable) { symbol = variables[part.Symbol.Name]; } else if (part.Symbol is Terminal) { symbol = terminalsByName[part.Symbol.Name]; } else if (part.Symbol is Virtual) { symbol = virtuals[part.Symbol.Name]; } else if (part.Symbol is Action) { symbol = actions[part.Symbol.Name]; } parts.Add(new RuleBodyElement(symbol, part.Action)); } clone.AddRule(new Rule(clone, rule.HeadAction, new RuleBody(parts), ResolveContext(parent.contexts[rule.Context]))); } } }
/// <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> /// Adds the real axiom to this grammar /// </summary> /// <returns>An error message, if any</returns> private string AddRealAxiom() { // Search for Axiom option if (!options.ContainsKey(OPTION_AXIOM)) { return("No axiom variable has been defined for grammar " + name); } // Search for the variable specified as the Axiom string axiomName = options[OPTION_AXIOM]; if (!variables.ContainsKey(axiomName)) { return("The specified axiom variable " + axiomName + " is undefined"); } // Create the real axiom rule variable and rule Variable axiom = AddVariable(GENERATED_AXIOM); List <RuleBodyElement> parts = new List <RuleBodyElement>(); parts.Add(new RuleBodyElement(variables[axiomName], TreeAction.Promote)); parts.Add(new RuleBodyElement(Dollar.Instance, TreeAction.Drop)); axiom.AddRule(new Rule(axiom, TreeAction.None, new RuleBody(parts), 0)); return(null); }
/// <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)); }