public AltRule(SymbolPosition pos, string markWith, IEnumerable <RhsGroup> groups, CodeMix gen) { this.Position = pos; this.MarkWith = markWith; // [@PARSER_USER_ACTION] // here we swap the notion of user action // if in grammar user didn't pass ANY code -- it means identity function // if the grammar user pass empty code -- it means passing null value, so as shorcut set null as entire user action if (gen == null) // if there was no code at all, we infer the end object { CodeMix mix = null; if (inferEndObject(groups, ref mix)) { this.Code = mix; } else { throw ParseControlException.NewAndRun("Couldn't infer which object to pass at " + pos.XYString()); } } // if there was an empty code, such code does not produce anything (i.e. null) // thus we set entire action as null -- it is a shortcut else if (gen.IsEmpty) { this.Code = null; } else { this.Code = gen; } SetGroups(groups); }
private static bool inferEndObject(IEnumerable <RhsGroup> groups, ref CodeMix code) { IEnumerable <RhsSymbol> symbols = groups.Select(it => it.GetSymbols()).Flatten(); if (symbols.Any(it => it.IsError)) { return(true); } if (symbols.Count() != 1) { symbols = symbols.Where(it => it.ObjName != null); } if (symbols.Count() != 1) { return(false); } RhsSymbol symbol = symbols.Single(); // underscore is not magic -- it is a nice shortcut in grammar file, but awful when reading the output code // thus we change it to something more readable, and since it is automatic, we can do the change (because why not) // this replacement is rather useful only for NLT developer(s) if (symbol.ObjName == null || symbol.ObjName == "_") { symbol.ResetUserObjName(); code = new CodeMix(CodeMix.ObjectInferComment).AddBody(new CodeBody().AddPlaceholder(symbol.SymbolName)); } else { code = new CodeMix(CodeMix.ObjectInferComment).AddBody(new CodeBody().AddIdentifier(symbol.ObjName)); } return(true); }
internal static AltRule CreateInternally(SymbolPosition pos, IEnumerable <RhsGroup> groups, CodeMix code) { return(new AltRule(pos, null, groups, code)); }