示例#1
0
        private static AltRule createSubstitution(SymbolPosition position, string substSymbolName)
        {
            var code = new CodeBody().AddIdentifier("obj");

            return(AltRule.CreateInternally(position, new RhsGroup[] {
                RhsGroup.CreateSequence(position, RepetitionEnum.Once, new RhsSymbol(position, "obj", substSymbolName))
            },
                                            new CodeMix(CodeMix.SubstitutionComment).AddBody(code)));
        }
示例#2
0
        private static AltRule createAppend(SymbolPosition position,
                                            string lhsSymbolName,
                                            IEnumerable <string> elementTypeNames,
                                            params RhsSymbol[] symbols)
        {
            // if it does not exists it means we don't care about adding it
            IEnumerable <RhsSymbol> named_symbols = symbols.Where(it => it.ObjName != null).ToArray();

            string list_obj_name;

            if (named_symbols.Count() == 1)
            {
                list_obj_name = "list";
            }
            else
            {
                list_obj_name = "tuple_list";
            }

            // since we are creating this code, the only conflict can come from symbol object names
            list_obj_name = Grammar.RegisterName(list_obj_name, named_symbols.Select(it => it.ObjName).ToList());

            var code = new CodeBody().AddSnippet("{");

            if (named_symbols.Count() == 1)
            {
                code.AddWithIdentifier(list_obj_name, ".", "Add", "(", named_symbols.Single().ObjName, ");");
            }
            else
            {
                foreach (Tuple <RhsSymbol, int> sym_pair in named_symbols.ZipWithIndex())
                {
                    code.AddWithIdentifier(list_obj_name, ".", CodeWords.Item(sym_pair.Item2 + 1), ".", "Add", "(");
                    code.AddIdentifier(sym_pair.Item1.ObjName);
                    code.AddSnippet(");");
                }
            }

            code.AddWithIdentifier("return", " ", list_obj_name, ";}");

            return(AltRule.CreateInternally(position, new RhsGroup[] {
                RhsGroup.CreateSequence(position, RepetitionEnum.Once, new RhsSymbol(position, list_obj_name, lhsSymbolName)),
                RhsGroup.CreateSequence(position, RepetitionEnum.Once, symbols.Select(it => it.ShallowClone().SetSkip(false)).ToArray())
            },
                                            new CodeMix(CodeMix.AppendComment).AddBody(code)));
        }
        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);
        }
示例#5
0
        private AltRule createSeed(SymbolPosition position,
                                   List <Production> productions,
                                   bool doubled,  // should we double the seed right at the start
                                   string lhsSymbolName,
                                   IEnumerable <string> elementTypeNames,
                                   params RhsSymbol[] symbols)
        {
            RhsSymbol[] init_symbols = symbols.Where(it => !it.SkipInitially).ToArray();

            var main_code = new CodeBody().AddWithIdentifier(CodeWords.New, " ");

            main_code.Append(makeTupleListCode(position, elementTypeNames));
            main_code.AddSnippet("(");

            IEnumerable <CodeBody> code_lists
                = elementTypeNames.Select(it => new CodeBody().AddWithIdentifier(CodeWords.New, " ", CodeWords.List, "<", it, ">{")).ToList();

            // purpose: to handle names in doubled seed mode
            Dictionary <RhsSymbol, string[]> obj_name_substs = new Dictionary <RhsSymbol, string[]>();

            {
                IEnumerable <RhsSymbol> named_symbols = symbols.Where(it => it.ObjName != null);

                if (named_symbols.Any())
                {
                    foreach (Tuple <RhsSymbol, CodeBody> tuple in named_symbols.SyncZip(code_lists))
                    {
                        RhsSymbol nsymbol    = tuple.Item1;
                        CodeBody  lcode      = tuple.Item2;
                        bool      double_sym = doubled && !nsymbol.SkipInitially;

                        string[] name_subst = new string[double_sym ? 2 : 1];
                        obj_name_substs.Add(nsymbol, name_subst);

                        // if we double the element, we have to come up with new names
                        if (double_sym)
                        {
                            name_subst[0] = AutoNames.Double1 + nsymbol.ObjName + "__";
                            name_subst[1] = AutoNames.Double2 + nsymbol.ObjName + "__";
                        }
                        else
                        {
                            name_subst[0] = nsymbol.ObjName;
                        }

                        for (int i = 0; i < (double_sym ? 2 : 1); ++i)
                        {
                            if (i == 1)
                            {
                                lcode.AddSnippet(",");
                            }

                            if (double_sym)
                            {
                                lcode.AddIdentifier(name_subst[i]);
                            }
                            else
                            {
                                lcode.AddIdentifier(nsymbol.ObjName);
                            }
                        }
                    }
                }
            }

            foreach (Tuple <CodeBody, int> code_pair in code_lists.ZipWithIndex())
            {
                code_pair.Item1.AddSnippet("}");

                if (code_pair.Item2 > 0)
                {
                    main_code.AddSnippet(",");
                }
                main_code.Append(code_pair.Item1);
            }

            main_code.AddSnippet(")");

            // in case of doubled seed we have to rename the symbols
            // otherwise just make shallow copies without renaming
            // but since we already set proxy name correctly, we can use shared code for both cases
            var seed_symbols = new LinkedList <RhsSymbol>();

            for (int i = 0; i < (doubled ? 2 : 1); ++i)
            {
                foreach (RhsSymbol sym in (i == 0 ? init_symbols : symbols))
                {
                    if (sym.ObjName == null)
                    {
                        seed_symbols.AddLast(sym.ShallowClone());
                    }
                    else
                    {
                        int s_idx = (i == 1 && sym.SkipInitially) ? 0 : i;
                        seed_symbols.AddLast(sym.Renamed(obj_name_substs[sym][s_idx]));
                    }
                }
            }


            return(AltRule.CreateInternally(position,
                                            // are there any symbols for production
                                            seed_symbols.Any()
                ? new RhsGroup[] { RhsGroup.CreateSequence(position, RepetitionEnum.Once, seed_symbols.Select(it => it.SetSkip(false)).ToArray()) }
                : new RhsGroup[] { },
                                            new CodeMix(CodeMix.SeedComment).AddBody(main_code)));
        }