internal ProductionInfo(SymbolPosition pos, string lhsSymbol, RecursiveEnum recursive, IEnumerable <RhsSymbol> rhsSymbols, string altMarkWith) { this.Position = pos; this.LhsSymbol = lhsSymbol; this.Recursive = recursive; this.rhsSymbols = rhsSymbols.ToList(); this.TabooSymbols = rhsSymbols.Select(it => it.TabooSymbols).ToArray(); this.PassedMarkedWith = altMarkWith; this.EffectiveMarkedWith = altMarkWith ?? rhsSymbols.Where(it => it.IsMarked).Select(it => it.SymbolName).SingleOrDefault(); this.IdentityOuterFunctionParamIndex = NoIdentityFunction; }
private IEnumerable <ProductionInfo> buildAltRule(string lhsSymbol, RecursiveEnum recursive, AltRule alt, string treeNodeName) { // for each group assign a selector which enables/disables given symbols, to make all valid variations // for example // a -> X? [Y Z] // is turned into (\ denotes disabled symbol) // a -> \X Y \Z // a -> \X \Y Z // a -> X Y \Z // a -> X \Y Z IEnumerable <RhsEntitySelector> selectors = alt.RhsGroups.Select(it => new RhsEntitySelector(it)).ToArray(); while (true) { yield return(makeBuilderCall(lhsSymbol, recursive, alt, selectors.Select(it => it.BuildConfiguration()).Flatten().ToArray(), treeNodeName)); if (!selectors.Iterate()) { break; } } }
private ProductionInfo makeBuilderCall(string lhsSymbol, RecursiveEnum recursive, AltRule alt, IEnumerable <SymbolMarked> symbolsMarked, string treeNodeName) { // add production with no code var prod_info = new ProductionInfo(alt.Position, lhsSymbol, recursive, symbolsMarked.Where(it => it.IsEnabled).Select(it => it.Symbol), alt.MarkWith); CodeBody code_body = null; if (alt.Code != null) { code_body = (alt.Code as CodeMix).BuildBody(symbolsMarked.Where(sym => sym.Symbol.ObjName != null) .Select(sym => sym.Symbol.GetCodeArgumentNames().Select(it => Tuple.Create(it, sym.IsEnabled))).Flatten()) .Trim(); string identity_function_on = null; // are we just passing one of the parameters? if (code_body.IsIdentity) { identity_function_on = code_body.IdentityIdentifier; } foreach (string var_name in code_body.GetVariables()) { SymbolMarked sym = symbolsMarked .Where(sm => sm.Symbol.GetCodeArgumentNames().Contains(var_name)) // there could be duplicates so we "prefer" enabled element .OrderBy(it => it.IsEnabled ? 0 : 1) .FirstOrDefault(); if (sym != null) { sym.IsParamUsed = true; } } var anon_args = new Dictionary <SymbolMarked, string>(); foreach (Tuple <SymbolMarked, int> sym_pair in symbolsMarked.ZipWithIndex()) { if (sym_pair.Item1.Symbol.ObjName == null) { anon_args.Add(sym_pair.Item1, code_body.RegisterNewIdentifier("_" + sym_pair.Item2)); } } IEnumerable <SymbolMarked> arg_symbols = symbolsMarked.Where(it => it.IsEnabled || it.IsParamUsed).ToList(); // build external function to run the user code string func_ref = registerLambda(lhsSymbol, arg_symbols.Select(sym => sym.Symbol.GetCodeArgumentTypes(grammar)).Flatten(), grammar.TreeNodeName, arg_symbols.Select(sym => sym.Symbol.GetCodeArgumentNames() .Select(it => Tuple.Create(it, anon_args.GetOrNull(sym)))).Flatten(), code_body); // build a lambda with call to a just built function // note that our lambda can have fewer arguments than the actual fuction // in such case we pass "nulls" for disabled arguments // we add nulls to params in order to keep track which arguments comes from which parameters IEnumerable <FuncParameter> lambda_params = arg_symbols.Where(it => it.IsEnabled) .Select(it => FuncParameter.Create(it.Symbol.ObjName, anon_args.GetOrNull(it), grammar.GetTypeNameOfSymbol(it.Symbol))).ToArray(); // if the code indicates that this is identity function, then just find out which parameter is passed along if (identity_function_on != null) { // we can fail for two reasons here: // (1) ok -- single variable we found in the code body is not a parameter, but global variable // (2) BAD -- we have case of unpacking the data, and that case so far we cannot handle // ad.2) consider such rule as // x -> (a b)+ { b }; // "a" and "b" will be handled as tuple of lists // so in entry function we will get a tuple, and then we will call actuall user action code // some "__function_13__(a,b)" which returns the "b" // so we could compute index for inner parameter (for "b" it is 1) // but we cannot compute index for outer function, because there is no index for "b" at all // there is only one parameter -- tuple -- holding "a" (in Item1) and "b" (in Item2) at the same time // so if anything we would have to introduce some combo index: // outer index --> optional unpacking index --> inner index // too much trouble for now Option <int> index = lambda_params.Select(it => it.Name) .ZipWithIndex().Where(it => it.Item1 == identity_function_on).Select(it => it.Item2).OptSingle(); if (index.HasValue) { prod_info.IdentityOuterFunctionParamIndex = index.Value; } } prod_info.ActionCode = CodeLambda.CreateProxy( lhsSymbol, // lambda arguments lambda_params, treeNodeName, func_ref, arg_symbols.Select(arg => arg.Symbol.CombinedSymbols == null // regular symbols ? new[] { new CodeBody().AddIdentifier(arg.IsEnabled ? (arg.Symbol.ObjName ?? anon_args[arg]) : CodeWords.Null) } // compound symbols, we have to use embedded atomic symbols instead now : arg.Symbol.UnpackTuple(arg.IsEnabled) ) .Flatten()); prod_info.CodeComment = alt.Code.Comment; } return(prod_info); }
public static Production CreateUser(SymbolInfo lhsSymbol, RecursiveEnum recursive, IEnumerable <AltRule> alternatives) { return(new Production(lhsSymbol, recursive, alternatives)); }
private Production(SymbolInfo lhsSymbol, RecursiveEnum recursive, IEnumerable <AltRule> alternatives) { this.LhsSymbol = lhsSymbol; this.Recursive = recursive; this.rhsAlternatives = alternatives.ToList(); }
public Production <SYMBOL_ENUM, TREE_NODE> AddProduction(SYMBOL_ENUM nonterm, RecursiveEnum recursive, SYMBOL_ENUM s1, SYMBOL_ENUM s2, SYMBOL_ENUM s3, SYMBOL_ENUM s4, Func <object, object, object, object, TREE_NODE> action) { return(addProduction(new Production <SYMBOL_ENUM, TREE_NODE>(symbolsRep, nonterm, recursive, new SYMBOL_ENUM[] { s1, s2, s3, s4 }, ProductionAction <TREE_NODE> .Convert(action)))); }
public Production <SYMBOL_ENUM, TREE_NODE> AddProduction(SYMBOL_ENUM nonterm, RecursiveEnum recursive, SYMBOL_ENUM s1, SYMBOL_ENUM s2, SYMBOL_ENUM s3, Func <object, object, object, TREE_NODE> action, int identityParamIndex = Production.NoIdentityFunction) { return(addProduction(new Production <SYMBOL_ENUM, TREE_NODE>(symbolsRep, nonterm, recursive, new SYMBOL_ENUM[] { s1, s2, s3 }, ProductionAction <TREE_NODE> .Convert(action), identityParamIndex))); }
public Production <SYMBOL_ENUM, TREE_NODE> AddIdentityProduction(SYMBOL_ENUM nonterm, RecursiveEnum recursive, SYMBOL_ENUM s1) { return(AddProduction(nonterm, recursive, s1, (object x) => (TREE_NODE)x, 0)); }
public Production <SYMBOL_ENUM, TREE_NODE> AddProduction(SYMBOL_ENUM nonterm, RecursiveEnum recursive, Func <TREE_NODE> action) { return(addProduction(new Production <SYMBOL_ENUM, TREE_NODE>(symbolsRep, nonterm, recursive, new SYMBOL_ENUM[] { }, ProductionAction <TREE_NODE> .Convert(action)))); }
public Production <SYMBOL_ENUM, TREE_NODE> AddProduction(SYMBOL_ENUM nonterm, RecursiveEnum recursive, params SYMBOL_ENUM[] ss) { return(addProduction(new Production <SYMBOL_ENUM, TREE_NODE>(symbolsRep, nonterm, recursive, ss, null))); }