如何解析搜索引擎输入的关键词

问题描述 投票:0回答:1

我正在实现一个工具,可以让用户搜索文本中的术语。我目前专注于处理来自搜索的更复杂的输入。

我希望支持的运营商是:

  • | = 或
  • & = 和
  • ^ = 不是
  • " " = 引号以转义序列中的所有内容
  • ( ) = 括号,优先考虑封装的内容

此代码应该进入构建对数据库引擎的查询的Python后端,因此我需要一种方法来解析查询以转换适当的部分。是否有模块可以让我做到这一点?

我尝试查看 NLTK 的逻辑包,但它似乎做了太多的事情,而且我不清楚如何将其简化为这些功能。我想我需要像 NLTK 的语法树这样的东西,但我发现的只是添加语法标签的包,因此与语言模型相关联。

python parsing operators nltk
1个回答
0
投票

我会使用 PLY (Python Lex-Yacc) 或 SLY 来解析它。

PLY
SLY
具有相同的作者,但
PLY
使用函数而
SLY
使用类)

我从

calc.py
中获取了示例
SLY
并创建了将查询转换为

的代码
^(abc & def) | xyz

到嵌套列表

['OR', ['NOT', ['AND', 'abc', 'def']], 'xyz']

应该很容易用来生成 SQL 查询

但是没有获取

" "
的功能。

我还没有尝试添加它。它可能需要更多更改,因为它可能以特殊方式使用空间。

其他例子:

(A&B)|(^C&D)
==>
['OR', ['AND', 'A', 'B'], ['AND', ['NOT', 'C'], 'D']]

from sly import Lexer, Parser

class QueryLexer(Lexer):
    tokens = { TEXT }
    ignore = ' \t'
    literals = { '&', '|', '^', '(', ')', }

    # Tokens
    TEXT = r'[a-zA-Z_][a-zA-Z0-9_]*'

    @_(r'\n+')
    def newline(self, t):
        self.lineno += t.value.count('\n')

    def error(self, t):
        print("Illegal character '%s'" % t.value[0])
        self.index += 1

class QueryParser(Parser):
    tokens = QueryLexer.tokens

    precedence = (
        ('left', '&', '|'),
        ('right', '^'),
        )

    def __init__(self):
        self.names = { }

    @_('expr')
    def statement(self, p):
        print(p.expr)

    @_('expr "&" expr')
    def expr(self, p):
        return ['AND', p.expr0, p.expr1]

    @_('expr "|" expr')
    def expr(self, p):
        return ['OR', p.expr0, p.expr1]

    @_('"^" expr')
    def expr(self, p):
        return ['NOT', p.expr]

    @_('"(" expr ")"')
    def expr(self, p):
        return p.expr

    @_('TEXT')
    def expr(self, p):
        return p.TEXT

if __name__ == '__main__':
    lexer = QueryLexer()
    parser = QueryParser()
    while True:
        try:
            text = input('query > ')
        except EOFError:
            break
        if text:
            parser.parse(lexer.tokenize(text))
© www.soinside.com 2019 - 2024. All rights reserved.