How to use ErrorRule in SearchGrammar so even invalid query would generate a searchable CONTAINS query?

Oct 26, 2010 at 4:43 PM

Hi, I'm using the SearchGrammar and wondering if its possible to allow invalid user query to generate correct CONTAINS query.

 

Following query gave me a Syntax Error when parsing, but I'm not sure how to set the ErrorRule so that it will ignore the error and still generate a usable CONTAINS query.

" space " ; astronaut

 

The error happens right before paring ; where the space before is recognized as ImpliedAnd but ; fails to be parsed. Th error indicates:

Syntax error, expected: Term ~ + ( Phrase <

I've tried adding Root.ErrorRule = SyntaxError + Eos; but it doesn't seem to be able to generate a usable AST root.

Any help is appreciated!

 

Coordinator
Oct 26, 2010 at 5:24 PM

You can try the following. Create a custom terminal that represents any erroneous string. In its TryMatch method, consume all until next whitespace. Set its priority to (LowestPriority) so it is called to produce token only when all other terminals fail to produce token. Then in query conversion recognize this terminal and handle it in proper way (ignore or assume it TRUE in "AND" expressions). You may need to play with priority, as ImpliedSymbol terminal also has lowest priority and they may interfere.

Roman

Coordinator
Oct 26, 2010 at 5:38 PM

In fact you can probably use FreeTextLiteral for this error terminal, with space as a terminator.

Oct 26, 2010 at 6:25 PM

Thanks for the suggestion, I actually tried something like this and its giving me okay results (I'm not sure if it's the correct way of doing things since I'm pretty new to Irony)

  1. var Junk = new RegexBasedTerminal("Junk", "\\W*"); // this catches any no chars junks that's prob not what user wants to search for
  2. Modify Expression.Rule so it includes the Junk.
    Expression.Rule = PrimaryExpression | BinaryExpression | Junk;
    
  3. Add following so Junk is returning an empty string and modify BinaryExpression so that when constructing the result, we check if either side is empty string.

            case "Junk":
                result = string.Empty;
                  break;
            case "BinaryExpression":
              string opSym = string.Empty;
              string op = node.ChildNodes[1].FindTokenAndGetText().ToLower(); 
              string sqlOp = "";
              switch(op) {
                case "":  case "&":  case "and":
                  sqlOp = " AND ";
                  type = TermType.Inflectional;
                  break;
                case "-":
                  sqlOp = " AND NOT ";
                  break;
                case "|":   case "or":
                  sqlOp = " OR ";
                  break;
              }//switch

                  var left = ConvertQuery(node.ChildNodes[0], type);
                  var right = ConvertQuery(node.ChildNodes[2], type);
                  if (string.IsNullOrEmpty(left))
                  {
                      result = right;
                  } else if (string.IsNullOrEmpty(right))
                  {
                      result = left;
                  } else
                  {
                      result = "(" + left + sqlOp + right + ")";
                  }
              break;

 

Coordinator
Oct 26, 2010 at 7:37 PM

Looks good.. I'm just wondering - why treat stand-alone ";" as an error? what if user wants to search for this symbol as well?

Would it be more reasonable to expand allowed first/all symbols in Term definition, so that special chars like this (and strings of these chars) are treated as legit terms?

 

Oct 26, 2010 at 8:00 PM

That's a very good point, I'll experiment and try out some different scenarios.