2016-06-20 23 views
2

ich pyparsing == 2.1.5 mit Python 3.4 bin mit, und ich bekommen, was eine ungerade Ergebnis zu sein scheint:pyparsing delimitedList (..., kombinieren = True) inkonsistent Ergebnis geben

word = Word(alphanums) 
word_list_no_combine = delimitedList(word, combine=False) 
word_list_combine = delimitedList(word, combine=True) 
print(word_list_no_combine.parseString('one, two')) # ['one', 'two'] 
print(word_list_no_combine.parseString('one,two')) # ['one', 'two'] 
print(word_list_combine.parseString('one, two')) # ['one']: ODD ONE OUT 
print(word_list_combine.parseString('one,two')) # ['one,two'] 

Es ist nicht offensichtlich für mich, warum die "kombinieren" -Option bewirkt, dass einer der Teile der Liste verschluckt wird, wenn ein Raum vorhanden ist, aber nicht, wenn er nicht vorhanden ist. Ist das ein pyparsing Bug oder fehlt mir etwas offensichtlich?

+1

Die Einstellung 'combine = True' umschließt den Ausdruck in einem' Combine', das erwartet, dass alle übereinstimmenden Wörter benachbart sind (kein Leerzeichen dazwischen). – PaulMcG

Antwort

2

Anstatt pyparsing zu ändern, empfehle ich Sie, diese Arbeit zu tun mit dem normalen ungebundener getrennter Liste mit einer benutzerdefinierten Parse-Aktion:

word_list_combine_using_parse_action = word_list_no_combine.copy().setParseAction(','.join) 
print(word_list_combine_using_parse_action.parseString('one, two')) 

one,two

+0

Sehr schön - vielen Dank in der Tat! –

1

Sieht aus wie es von Combine() auf das Verhalten aufgrund ist, insbesondere seine default "benachbart = True" Option, die dann von delimitedList() verwendet wird:

class Combine(TokenConverter): 
    """Converter to concatenate all matching tokens to a single string. 
     By default, the matching patterns must also be contiguous in the input string; 
     this can be disabled by specifying C{'adjacent=False'} in the constructor. 
    """ 
    def __init__(self, expr, joinString="", adjacent=True): 
    # ... 

def delimitedList(expr, delim=",", combine=False): 
    # ... 
    dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." 
    if combine: 
     return Combine(expr + ZeroOrMore(delim + expr)).setName(dlName) 
    else: 
     return (expr + ZeroOrMore(Suppress(delim) + expr)).setName(dlName) 

So kann es mit einem Ersatz gelöst werden :

def delimitedListPlus(expr, delim=",", combine=False, combine_adjacent=False): 
    dlName = str(expr) + " [" + str(delim) + " " + str(expr) + "]..." 
    if combine: 
     return Combine(expr + ZeroOrMore(delim + expr), 
         adjacent=combine_adjacent).setName(dlName) 
    else: 
     return (expr + ZeroOrMore(Suppress(delim) + expr)).setName(dlName)