From 37c36ab873476ce9649c5063316de873ea692d0d Mon Sep 17 00:00:00 2001 From: Vincent Pelletier <vincent@nexedi.com> Date: Tue, 5 May 2009 12:22:24 +0000 Subject: [PATCH] Make AdvancedSearchTextParser behaviour relative to unknown column names coherent with AdvancedSearchtextDetector's behaviour. Update embeded test. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@26803 20353a03-c40f-0410-a6d1-a30d3c3de9de --- .../SearchText/AdvancedSearchTextParser.py | 57 ++++++++++++++++++- .../SearchText/SearchTextParser.py | 9 ++- product/ZSQLCatalog/SearchText/lexer.py | 4 +- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/product/ZSQLCatalog/SearchText/AdvancedSearchTextParser.py b/product/ZSQLCatalog/SearchText/AdvancedSearchTextParser.py index da4f27e99f..18ab4f6bd7 100644 --- a/product/ZSQLCatalog/SearchText/AdvancedSearchTextParser.py +++ b/product/ZSQLCatalog/SearchText/AdvancedSearchTextParser.py @@ -148,6 +148,48 @@ verifyClass(IColumnNode, ColumnNode) class AdvancedSearchTextParser(lexer): + # IMPORTANT: + # In short: Don't remove any token definition below even if they look + # useless. + # In detail: The lex methods below are redefined here because of ply nice + # feature of prioritizing tokens using the *line* *number* at which they + # are defined. As we inherit those methods from another class from another + # file (which doesn't match this file's content, of course) we must redefine + # wrapper methods to enforce token priority. Kudos to ply for so much + # customisable behaviour. Not. + + def t_LEFT_PARENTHESE(self, t): + return lexer.t_LEFT_PARENTHESE(self, t) + + def t_RIGHT_PARENTHESE(self, t): + return lexer.t_RIGHT_PARENTHESE(self, t) + + def t_OPERATOR(self, t): + return lexer.t_OPERATOR(self, t) + + def t_STRING(self, t): + return lexer.t_STRING(self, t) + + def t_COLUMN(self, t): + if self.isColumn(t.value[:-1]): + t = lexer.t_COLUMN(self, t) + else: + # t is a non-existing column, so it should be taken as a string prefix. + t.type = 'STRING_PREFIX' + return t + + def t_OR(self, t): + return lexer.t_OR(self, t) + + def t_AND(self, t): + return lexer.t_AND(self, t) + + def t_NOT(self, t): + return lexer.t_NOT(self, t) + + def t_WORD(self, t): + return lexer.t_WORD(self, t) + def p_seach_text(self, p): '''search_text : and_expression | and_expression OR search_text''' @@ -225,8 +267,19 @@ class AdvancedSearchTextParser(lexer): def p_string(self, p): '''string : WORD - | STRING''' - p[0] = p[1] + | STRING + | STRING_PREFIX string''' + if len(p) == 3: + p[0] = p[1] + p[2] + else: + p[0] = p[1] + + def __call__(self, input, is_column, *args, **kw): + self.isColumn = is_column + try: + return self.parse(input, *args, **kw) + finally: + self.isColumn = None update_docstrings(AdvancedSearchTextParser) diff --git a/product/ZSQLCatalog/SearchText/SearchTextParser.py b/product/ZSQLCatalog/SearchText/SearchTextParser.py index 335f81c7a5..37fc0b1bc4 100755 --- a/product/ZSQLCatalog/SearchText/SearchTextParser.py +++ b/product/ZSQLCatalog/SearchText/SearchTextParser.py @@ -72,7 +72,7 @@ def isAdvancedSearchText(input, is_column): @profiler_decorator def _parse(input, is_column, *args, **kw): if isAdvancedSearchText(input, is_column): - result = getAdvancedSearchTextParser()(input, *args, **kw) + result = getAdvancedSearchTextParser()(input, is_column, *args, **kw) else: result = None return result @@ -222,7 +222,7 @@ if __name__ == '__main__': ('(a AND b) OR (c AND (d OR e))', ComplexQuery([ComplexQuery([Query(None, 'a'), Query(None, 'b')], operator='and'), ComplexQuery([Query(None, 'c'), ComplexQuery([Query(None, 'd'), Query(None, 'e')], operator='or')], operator='and')], operator='or')), ('(foo:"") (bar:baz)', ComplexQuery([Query('foo', ''), Query('bar', 'baz')], operator='and')), - ('(foo:"") (OR:bar)', ComplexQuery([Query('foo', ''), Query('OR', 'bar')], operator='and')), + ('(foo:"") (OR:bar)', ComplexQuery([Query('foo', ''), Query(None, 'OR:bar')], operator='and')), # ('foo: OR', ['foo', 'or']), # ('foo: OR ', ['foo', 'or']), # ('(foo:)', ['foo', '']), @@ -328,12 +328,15 @@ if __name__ == '__main__': print ' Detector: %r' % (detector_result, ) if detector_result: print ' LEX:' - lexer = getAdvancedSearchTextParser().lexer + advanced_parser = getAdvancedSearchTextParser() + lexer = advanced_parser.lexer + advanced_parser.isColumn = isColumn lexer.input(input) while 1: tok = lexer.token() if not tok: break # No more input print ' %s' % (tok, ) + advanced_parser.isColumn = None print ' YACC:' print ' %r' % (parse(input, debug=2), ) else: diff --git a/product/ZSQLCatalog/SearchText/lexer.py b/product/ZSQLCatalog/SearchText/lexer.py index 2da29fa7fa..b558a34d30 100644 --- a/product/ZSQLCatalog/SearchText/lexer.py +++ b/product/ZSQLCatalog/SearchText/lexer.py @@ -82,6 +82,7 @@ class lexer(object): 'NOT', 'COLUMN', 'STRING', + 'STRING_PREFIX', 'WORD', 'OPERATOR', 'LEFT_PARENTHESE', @@ -146,7 +147,8 @@ class lexer(object): kw['lexer'] = self return self.parser.parse(*args, **kw) - __call__ = parse + def __call__(self, input, is_column, *args, **kw): + raise NotImplementedError def update_docstrings(klass): for property in dir(klass): -- 2.30.9