2012-07-09 42 views
2

對於個人項目,我需要編寫一個簡單的詞法分析器來處理用戶輸入命令。它們可以包含四種模式和支架:如何在Python中爲用戶輸入命令編寫簡單的詞法分析器/解析器?

  • 運營商:.+-%
  • 名([A-ZA-Z0-9]):例如foobarfooZbar2
  • 過濾器([AZ] {1} 「[一些文本]」):例如a"hello world"p"escaped \"string\""
  • 其他過濾器([AZ] {1}〜 「[一些文本]」):例如a~"hello world"p~"escaped \"string\""

我想爲了有一個分級列表(根據括號)拆分命令包含每個運營商的條目,每個名稱的條目(單個字符串),併爲每個過濾器的項(字典,例如{'a': 'hello world'}{'p~': 'escaped "string"'})。

所以這裏是什麼,我想用這個輸入一個例子(各地運營空間是可選):

foo . bar - (a"hello \"world\"" % (b~"foo" + bar) . (fooZ.(bar2+(c"foo bar".d"bar foo"))))

[ 
    'foo', 
    '.', 
    'bar', 
    '-', 
    [ 
    {'a': 'hello "world"'}, 
    '%', 
    [ 
     {'b~': 'foo'}, 
     '+', 
     'bar' 
    ] 
    '.', 
    [ 
     'fooZ', 
     '.', 
     [ 
     'bar2', 
     '+', 
     [ 
      {'c': 'foo bar'}, 
      '.', 
      {'d': 'bar foo'} 
     ] 
     ] 
    ] 
    ] 
] 

我看了一下pyparsing,厚度,pyPEG,Yapps,等等,但他們都似乎很難使用,我不知道我是否需要這種工具,因爲我需要的語法不是很複雜。在此先感謝您的建議!

+2

這是更好地使用的工具,用於分析一個,無論多麼簡單的語法如下:)這方式,如果需要,您可以輕鬆擴展到未來的需求。我會推薦Python PLY :) – 2012-07-09 12:03:54

+0

這是一個個人項目更多沿着學習如何解析?或者,它只是解析輸入然後用它做什麼?取決於哪一個會根據您想要使用的內容而有所不同。第一個說實話更有趣,雖然是的,你正在重塑一匹非常彪悍的馬匹,但有助於個人的理解。 – sean 2012-07-09 13:00:35

+0

感謝Mihai,我會嘗試深入PLY。 – Nicolas 2012-07-09 13:13:11

回答

3

看到這個pyparsing解決方案如何滿足您所陳述的語法:

from pyparsing import * 
ParserElement.enablePackrat() 
import string 

name = Word(alphanums) 

filter = (Combine(oneOf(list(string.ascii_lowercase)) + Optional('~')) + 
      dblQuotedString.setParseAction(removeQuotes)) 
# convert parsed filter to dict 
filter.setParseAction(lambda t:{t[0]:t[1]}) 

expr = operatorPrecedence(filter | name, 
      [ 
      (oneOf('. % -'), 2, opAssoc.LEFT), 
      ('+', 2, opAssoc.LEFT), 
      ]) 

test = r'foo . bar - (a"hello \"world\"" % (b~"foo" + bar) . (fooZ.(bar2+(c"foo bar".d"bar foo"))))' 

print expr.parseString(test, parseAll=True).asList() 

打印:

[['foo', 
    '.', 
    'bar', 
    '-', 
    [{'a': 'hello \\"world\\"'}, 
    '%', 
    [{'b~': 'foo'}, '+', 'bar'], 
    '.', 
    ['fooZ', '.', ['bar2', '+', [{'c': 'foo bar'}, '.', {'d': 'bar foo'}]]]]]] 
+0

非常有趣,非常感謝! – Nicolas 2012-07-09 13:59:41

+0

現在我不太確定一個操作符的優先級高於另一個操作符的優先級,因此示例中的分組可能只是歸因於括號嵌套。如果是這種情況,您可以將'operatorPrecedence'中的兩個級別合併到'(oneOf('。%+ - '),2,opAssoc.LEFT)'。 – PaulMcG 2012-07-09 14:18:47

相關問題