public static ConsoleColor indicateCol(NamedNode NN_in) { // side channel the color result indicatorRS indicator = noHit; // init is meaningless - just make the compiler shut up ( it can't know that PathUpTo can't yield empty sequences ) var res_NamedNode = NN_in.PathUpTo(NN => { indicator = indicate(NN); return(indicator.hit); }); if (res_NamedNode == null) { return(defaultConsoleColor); } return(indicator.col); }
/* * * GetAst * * functor to decouple the intricacies of translation and scoping ( particularly scoping and choice of grammar start production ) * to be moved elswhere later * * passing in an already generated AST does not make sense because this only this part is supposed to know how to react to errors ( how pass them on to the interactive shell and so forth ) */ public static ShellCommon.AC_Resp AC(ShellCommon.AC_Req shell_ac_request, Func <IEnumerable <PTokBase>, NamedNode> GetAst // Shell needs to do its own tokenization ) { var RESPONDER = new Responder(shell_ac_request); string str_in = shell_ac_request.arg; int cursor_pos = shell_ac_request.offs; /* * atm error tokens are normal PTok's with E == PTokE.ErrT * no special treatment in stripping needed - there are simply no productions that recognize token sequences with ErrT's among them */ var l_toks = Lexer.Tokenize(str_in, relaxed: true); var TokL = new TokLinePlanB <PTok>(); foreach (PTokBase tb in l_toks) { if (tb is PTok) { TokL.AddTok((PTok)tb); } else { TokL.AddWS((tb as PTokWhitespace).len); } } var CPos = TokL.CPosFromStringpos(cursor_pos); PTok AC_Tok = CPos.conflated_clusterF_AC_tok(); if (AC_Tok == null) { return(RESPONDER.NoAC(" no acable tok ").ac_response); } NamedNode AST; try { AST = GetAst(l_toks); } catch (Exception e) { return(RESPONDER.NoAC(e.ToString()).ac_response); // <-- this uses includes variable resolution and all kinds of other shenanigans, that are only needed for membAC, typeAC is a lot simpler - could do with only parsing } if (AST == null) { return(RESPONDER.NoAC(" GetAst() == null ").ac_response); } // with epsilon consuming productions ( ex: DeclStar ) "all Leafs are TermNodes" can not be relied on anymore var TermLeafs = AST.Leafs().Where(nn => nn is MG.TermNode).Select(n => (MG.TermNode)n).ToArray().NLSendRec("term leafs"); NamedNode AC_Node = null; int i = 0; for (; i < TermLeafs.Length; i++) { if (TermLeafs[i].tok == AC_Tok) { AC_Node = TermLeafs[i]; break; } } if (AC_Node == null) { return(RESPONDER.NoAC("ac beyond parsable").ac_response); // TODO : D.Assert() that this is actually true with something like : PToks.Skip(i).Where( term.tok == AC_Tok).Single } NamedNode descrNode = AC_Node.PathUpTo((n) => (n is MG.ACable)); if (descrNode == null) { return(RESPONDER.NoAC(" descrNode == null ").ac_response); } if (descrNode is MG.ACableMemb) { return(MembAcc_AC(TokL, CPos, (MGRX.MemANodeRX)descrNode, RESPONDER).ac_response); // <- todo cast not typesafe } else if (descrNode is MG.ACableTypeName) { return(Type_AC(TokL, CPos, descrNode, RESPONDER).ac_response); } else if (descrNode is MG.ACableFuncName) { return(FuncName_AC(TokL, CPos, (MGRX.FuncNameNodeRX)descrNode, RESPONDER).ac_response); } else { throw new NotImplementedException(); } }