/// <summary> /// Check that tokens match /// </summary> /// <param name="pTok"></param> /// <param name="matchToken"></param> /// <returns></returns> static bool MatchToken( PositionedToken pTok, string matchToken, RichTextBox complexCriteriaCtl) { if (Lex.Eq(pTok.Text, matchToken)) { return(true); } ConvertLabeledCriteriaError("Expected keyword \"" + matchToken + "\"", pTok, complexCriteriaCtl); return(false); }
/// <summary> /// Show error message & select token with error /// </summary> /// <param name="message"></param> /// <param name="pTok"></param> static void ConvertLabeledCriteriaError( string message, PositionedToken pTok, RichTextBox complexCriteriaCtl) { Progress.Hide(); if (complexCriteriaCtl != null) { complexCriteriaCtl.SelectionStart = pTok.Position; complexCriteriaCtl.SelectionLength = pTok.Text.Length; } MessageBoxMx.ShowError(message); if (complexCriteriaCtl != null) { complexCriteriaCtl.Focus(); } return; }
/// <summary> /// Color criteria to highlight keywords, column names, constants, etc. /// </summary> /// <param name="criteria"></param> /// <param name="q"></param> /// <returns></returns> public static RichTextBox ColorCodeCriteria( string criteria, Query q) { bool inEditStructure = false; int i1; RichTextBox rtb = new RichTextBox(); rtb.Text = criteria; rtb.SelectionStart = 0; rtb.SelectionLength = rtb.Text.Length; rtb.SelectionFont = new Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); PositionedToken lastTok = null; Lex lex = new Lex(); lex.SetDelimiters(" , ; ( ) < = > <= >= <> != !> !< [ ]"); lex.OpenString(criteria); while (true) { PositionedToken tok = lex.GetPositionedToken(); if (tok == null) { break; } if (MqlUtil.IsKeyWord(tok.Text)) { rtb.SelectionStart = tok.Position; rtb.SelectionLength = tok.Text.Length; rtb.SelectionColor = Color.Blue; continue; } QueryColumn qc = MqlUtil.GetQueryColumn(tok.Text, q); if (qc != null) { // labeled field name rtb.SelectionStart = tok.Position; rtb.SelectionLength = tok.Text.Length; rtb.SelectionColor = Color.Cyan; continue; } if (tok.Text.StartsWith("/*")) { // comment rtb.SelectionStart = tok.Position; rtb.SelectionLength = tok.Text.Length; rtb.SelectionColor = Color.Green; continue; } if (tok.Text.StartsWith("'") || Lex.IsDouble(tok.Text)) { // constant rtb.SelectionStart = tok.Position; rtb.SelectionLength = tok.Text.Length; rtb.SelectionColor = Color.Red; continue; } if (tok.Text == "[") { inEditStructure = true; // color structure placeholder tokens } if (inEditStructure) // color the tokens in edit structure { rtb.SelectionStart = tok.Position; rtb.SelectionLength = tok.Text.Length; rtb.SelectionColor = Color.Red; if (tok.Text == "]") { inEditStructure = false; } continue; } } return(rtb); }
/// <summary> /// Translate a labeled column reference to a normal named reference /// </summary> /// <param name="pTok"></param> /// <returns></returns> static string TranslateLabeledColumnName( PositionedToken pTok, Query q, RichTextBox complexCriteriaCtl) { QueryColumn qc = null; int qti, qci; string tok = pTok.Text; tok = Lex.RemoveDoubleQuotes(tok); string tName, cName; MqlUtil.ParseColumnIdentifier(tok, out tName, out cName); QueryTable qt = q.Tables[0]; // default to first table if (tName != "") { for (qti = 0; qti < q.Tables.Count; qti++) { qt = q.Tables[qti]; if (Lex.Eq(qt.Alias, tName)) { break; } } if (qti >= q.Tables.Count) { ConvertLabeledCriteriaError("Invalid table name or alias", pTok, complexCriteriaCtl); } } for (qci = 0; qci < qt.QueryColumns.Count; qci++) { qc = qt.QueryColumns[qci]; if (qc.MetaColumn == null) { continue; } if (!qc.MetaColumn.IsSearchable) { continue; } string label = GetUniqueColumnLabel(qc); if (Lex.Eq(label, cName)) { break; } } if (qci >= qt.QueryColumns.Count) { qc = MqlUtil.GetQueryColumn(tok, q); // see if metacolumn name if (qc == null) { ConvertLabeledCriteriaError("Unrecognized query element: \"" + pTok.Text + "\"", pTok, complexCriteriaCtl); return(null); } } string colName = qc.MetaColumn.Name; if (tName != "") { colName = tName + "." + colName; // include table name or alias if exists } return(colName); }
/// <summary> /// Convert labeled criteria to complex checking for errors /// </summary> /// <param name="criteria"></param> /// <param name="q"></param> /// <param name="complexCriteriaCtl"></param> public static bool ConvertEditableCriteriaToComplex( LabeledCriteria labeledCriteria, Query q, RichTextBox complexCriteriaCtl) { QueryTable qt; QueryColumn qc; Lex lex = new Lex(); lex.SetDelimiters(" , ; ( ) < = > <= >= <> != !> !< [ ]"); lex.OpenString(labeledCriteria.Text); StringBuilder sb = new StringBuilder(); PositionedToken lastTok = null; List <PositionedToken> tokens = new List <PositionedToken>(); // list of tokens seen int parenDepth = 0; while (true) { PositionedToken pTok = lex.GetPositionedToken(); if (pTok == null) { break; } tokens.Add(pTok); if (lastTok != null) { // include same white space between tokens int wsBeg = lastTok.Position + lastTok.Text.Length; sb.Append(labeledCriteria.Text.Substring(wsBeg, pTok.Position - wsBeg)); } string tok = pTok.Text; if (MqlUtil.IsKeyWord(pTok.Text)) // ok if keyword, operator, etc { if (pTok.Text == "(") { parenDepth++; } else if (pTok.Text == ")") { parenDepth--; } } else if (pTok.Text.StartsWith("'")) // string constant { if (tokens.Count >= 3 && Lex.Eq(tokens[tokens.Count - 2].Text, "In") && Lex.Eq(tokens[tokens.Count - 1].Text, "List")) { // saved list reference UserObject uo = QueryEngine.ResolveCnListReference(tok); if (uo != null) { tok = "CNLIST_" + uo.Id.ToString(); } else { tok = "Nonexistant list"; } tok = Lex.AddSingleQuotes(tok); } } else if (Lex.IsDouble(pTok.Text)) { } // numeric constant else if (tok == "[") { // translate editable structure reference pTok = lex.GetPositionedToken(); if (!MatchToken(pTok, "Edit", complexCriteriaCtl)) { return(false); } pTok = lex.GetPositionedToken(); if (!MatchToken(pTok, "Structure", complexCriteriaCtl)) { return(false); } pTok = lex.GetPositionedToken(); tok = Lex.RemoveSingleQuotes(pTok.Text.ToUpper()); if (!labeledCriteria.Structures.ContainsKey(tok)) { ConvertLabeledCriteriaError("Structure \"" + pTok.Text + "\" not defined", pTok, complexCriteriaCtl); return(false); } tok = Lex.AddSingleQuotes(labeledCriteria.Structures[tok]); // replace with chime pTok = lex.GetPositionedToken(); if (!MatchToken(pTok, "]", complexCriteriaCtl)) { return(false); } } else if (Lex.Eq(pTok.Text, "structure_field")) { // check for user failing to define structure_field in structure search criteria ConvertLabeledCriteriaError("\"Structure_field\" must be replaced with a real field name", pTok, complexCriteriaCtl); return(false); } else // must be a column reference or invalid token { // translate labeled column name tok = TranslateLabeledColumnName(pTok, q, complexCriteriaCtl); if (tok == null) { return(false); } } sb.Append(tok); lastTok = pTok; } tokens = tokens; // debug if (parenDepth != 0) // parens balance? { if (parenDepth > 0) { MessageBoxMx.ShowError("Unbalanced parentheses: left parentheses exceed right by " + parenDepth.ToString()); } else { MessageBoxMx.ShowError("Unbalanced parentheses: right parentheses exceed left by " + (-parenDepth).ToString()); } if (complexCriteriaCtl != null) { complexCriteriaCtl.Focus(); } return(false); } q.ComplexCriteria = sb.ToString(); // store back in query return(true); }
/// <summary> /// Convert complex criteria to labeled form suitable for editing in complex criteria editor /// </summary> /// <param name="q"></param> /// <param name="structures">Dictionary of structure names & connection tables</param> public static LabeledCriteria ConvertComplexCriteriaToEditable( Query q, bool includeEditButtons) { bool insertBreaks = false; if (q.ComplexCriteria.IndexOf("\n") < 0) { insertBreaks = true; } Dictionary <string, string> tAliasMap = GetAliasMap(q); if (tAliasMap != null && !includeEditButtons) { // fixup aliases properly first using editable criteria ConvertComplexCriteriaToEditable(q, true); tAliasMap = null; } Lex lex = new Lex(); lex.SetDelimiters(" , ; ( ) < = > <= >= <> != !> !<"); string criteria = q.ComplexCriteria; lex.OpenString(criteria); StringBuilder sb = new StringBuilder(); PositionedToken lastTok = null; List <PositionedToken> tokens = new List <PositionedToken>(); // list of tokens seen LabeledCriteria lc = new LabeledCriteria(); lc.Structures = new Dictionary <string, string>(); while (true) { PositionedToken tok = lex.GetPositionedToken(); if (tok == null) { break; } tokens.Add(tok); if (lastTok != null) { // include same white space between tokens int wsBeg = lastTok.Position + lastTok.Text.Length; sb.Append(criteria.Substring(wsBeg, tok.Position - wsBeg)); } QueryColumn qc = MqlUtil.GetQueryColumn(tok.Text, q); // see if token is column ref if (qc != null) { //query column, map to labeled columns string label = GetUniqueColumnLabel(qc); QueryTable qt = qc.QueryTable; string tName, cName; MqlUtil.ParseColumnIdentifier(tok.Text, out tName, out cName); if (tName != null && tName != "") // any table name supplied? { if (tAliasMap != null && tAliasMap.ContainsKey(tName.ToUpper())) { tName = tAliasMap[tName.ToUpper()]; } label = tName + "." + label; } sb.Append(Lex.Dq(label)); } else { // not a query column reference string tokText = tok.Text; string txt = Lex.RemoveSingleQuotes(tokText).ToUpper(); if (UserObject.IsCompoundIdListName(txt)) { string listName = null; int objectId = int.Parse(txt.Substring(7)); UserObject uo = UserObjectDao.ReadHeader(objectId); if (uo != null) { listName = uo.InternalName; } else { listName = "Unknown"; } tokText = Lex.AddSingleQuotes(listName); } if (tokens.Count >= 5) { // see if this is a chime string string sFuncCand = tokens[tokens.Count - 5].Text.ToLower(); if ((Lex.Eq(sFuncCand, "SSS") || Lex.Eq(sFuncCand, "FSS") || Lex.Eq(sFuncCand, "MolSim")) && tokText.StartsWith("'") && tokText.EndsWith("'")) // single-quoted chime? { string sAlias = "S" + (lc.Structures.Count + 1).ToString(); lc.Structures[sAlias] = Lex.RemoveSingleQuotes(tokText); // save structure in dictionary if (includeEditButtons) { tokText = "[Edit Structure " + sAlias + "]"; // use alias in labeled query } else { tokText = Lex.AddSingleQuotes(sAlias); } } } if ((Lex.Eq(tokText, "And") || Lex.Eq(tokText, "Or")) && tokens.Count >= 3 && !Lex.Eq(tokens[tokens.Count - 3].Text, "Between") && insertBreaks) { sb.Append("\n"); // start new line for each and/or } sb.Append(tokText); // not query column identifier } lastTok = tok; } sb.Append(" "); // include final space so additional text is black, also to get correct font lc.Text = sb.ToString(); // If a table alias changes then update aliases & complex criteria but only if going // to editable text since ConvertEditableCriteriaToComplex fails otherwise. if (tAliasMap != null) { for (int qti = 0; qti < q.Tables.Count; qti++) { // set new table aliases QueryTable qt = q.Tables[qti]; string alias = "T" + (qti + 1).ToString(); qt.Alias = alias; } ConvertEditableCriteriaToComplex(lc, q, null); // update q.ComplexCriteria also } return(lc); }
/// <summary> /// Split an axis expression into a list of column expressions /// </summary> /// <param name="axisExpr"></param> /// <returns></returns> public static List <string> Split(string axisExpr) { List <string> colExprs = new List <string>(); Lex lex = new Lex(); lex.SetDelimiters(" , ( ) "); lex.OpenString(axisExpr); StringBuilder sb = new StringBuilder(); PositionedToken lastTok = null; List <PositionedToken> tokens = new List <PositionedToken>(); // list of tokens seen int parenDepth = 0; while (true) { PositionedToken pTok = lex.GetPositionedToken(); if (pTok == null) { break; } tokens.Add(pTok); if (lastTok != null) { // include same white space between tokens int wsBeg = lastTok.Position + lastTok.Text.Length; sb.Append(axisExpr.Substring(wsBeg, pTok.Position - wsBeg)); } string tok = pTok.Text; if (pTok.Text == "(") { parenDepth++; } else if (pTok.Text == ")") { parenDepth--; } if (Lex.Eq(pTok.Text, ",") && parenDepth == 0 && sb.Length > 0) { colExprs.Add(sb.ToString()); sb.Clear(); } else { sb.Append(tok); } lastTok = pTok; } if (sb.Length > 0) // final col expr { colExprs.Add(sb.ToString()); } return(colExprs); }
public static ColumnExpressionMsx Parse(string expr) { Lex lex = new Lex(); lex.SetDelimiters(" , ; ( ) [ ]"); lex.OpenString(expr); StringBuilder sb = new StringBuilder(); PositionedToken lastTok = null, leftBracket = null; ColumnExpressionMsx colExpr = new ColumnExpressionMsx(); List <PositionedToken> tokens = new List <PositionedToken>(); // list of tokens seen int parenDepth = 0; while (true) { PositionedToken pTok = lex.GetPositionedToken(); if (pTok == null) { break; } tokens.Add(pTok); if (lastTok != null) { // include same white space between tokens int wsBeg = lastTok.Position + lastTok.Text.Length; sb.Append(expr.Substring(wsBeg, pTok.Position - wsBeg)); } string tok = pTok.Text; if (pTok.Text == "(") { parenDepth++; } else if (pTok.Text == ")") { parenDepth--; } else if (tok == "[") { leftBracket = pTok; } else if (tok == "]") { if (leftBracket != null) { int p = leftBracket.Position + 1; int l = pTok.Position - p; string colName = expr.Substring(p, l); colExpr.ColumnNames.Add(colName); leftBracket = null; } } } return(colExpr); }