【问题标题】:Creating a List Lexer/Parser创建列表词法分析器/解析器
【发布时间】:2012-01-15 00:07:58
【问题描述】:

我需要创建一个词法分析器/解析器来处理可变长度和结构的输入数据。

假设我有一个保留关键字列表:

keyWordList = ['command1', 'command2', 'command3']

和一个用户输入字符串:

userInput = 'The quick brown command1 fox jumped over command2 the lazy dog command 3'
userInputList = userInput.split()

我将如何编写这个函数:

INPUT:

tokenize(userInputList, keyWordList)

OUTPUT:
[['The', 'quick', 'brown'], 'command1', ['fox', 'jumped', 'over'], 'command 2', ['the', 'lazy', 'dog'], 'command3']

我编写了一个可以识别关键字的分词器,但一直无法找到一种将非关键字组嵌入到更深层次的列表中的有效方法。

欢迎使用 RE 解决方案,但我真的很想看看底层算法,因为我可能会将应用程序扩展到其他对象的列表,而不仅仅是字符串。

【问题讨论】:

    标签: python algorithm parsing lexer tokenize


    【解决方案1】:

    类似这样的:

    def tokenize(lst, keywords):
        cur = []
        for x in lst:
            if x in keywords:
                yield cur
                yield x
                cur = []
            else:
                cur.append(x)
    

    这会返回一个生成器,因此请将您的调用打包到list

    【讨论】:

      【解决方案2】:

      使用一些正则表达式很容易做到:

      >>> reg = r'(.+?)\s(%s)(?:\s|$)' % '|'.join(keyWordList)
      >>> userInput = 'The quick brown command1 fox jumped over command2 the lazy dog command3'
      >>> re.findall(reg, userInput)
      [('The quick brown', 'command1'), ('fox jumped over', 'command2'), ('the lazy dog', 'command3')]
      

      现在您只需拆分每个元组的第一个元素。

      对于不止一个层次的深度,正则表达式可能不是一个好的答案。

      在此页面上有一些不错的解析器供您选择:http://wiki.python.org/moin/LanguageParsing

      我觉得Lepl 不错。

      【讨论】:

      • 只要 command1 是其他术语之一的子字符串(例如“length”和“len”),就会出现问题。
      • 确实如此。可以在关键字列表周围添加\s 来解决这个问题。我编辑了我的答案
      【解决方案3】:

      试试这个:

      keyWordList = ['command1', 'command2', 'command3']
      userInput = 'The quick brown command1 fox jumped over command2 the lazy dog command3'
      inputList = userInput.split()
      
      def tokenize(userInputList, keyWordList):
          keywords = set(keyWordList)
          tokens, acc = [], []
          for e in userInputList:
              if e in keywords:
                  tokens.append(acc)
                  tokens.append(e)
                  acc = []
              else:
                  acc.append(e)
          if acc:
              tokens.append(acc)
          return tokens
      
      tokenize(inputList, keyWordList)
      > [['The', 'quick', 'brown'], 'command1', ['fox', 'jumped', 'over'], 'command2', ['the', 'lazy', 'dog'], 'command3']
      

      【讨论】:

      • 我实际上想出了类似的东西,但你的更优雅一点。
      【解决方案4】:

      或者看看 PyParsing。相当不错的小 lex 解析器组合

      【讨论】:

        猜你喜欢
        • 2013-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-07
        • 2013-04-29
        • 2020-01-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多