"""
Create pyparsing grammar for problem configuration and options.
"""
from pyparsing import (Word, Group, Suppress, Combine, Optional,
                       Forward, Empty, quotedString, oneOf, removeQuotes,
                       delimitedList, nums, alphas, alphas8bit, alphanums)

def create_bnf():
    cvt_int = lambda toks: int(toks[0])
    cvt_real = lambda toks: float(toks[0])
    cvt_tuple = lambda toks : tuple(toks.asList())
    cvt_dict = lambda toks: dict(toks.asList())

    # define punctuation as suppressed literals
    (lparen, rparen, lbrack, rbrack,
     lbrace, rbrace, colon) = map(Suppress,"()[]{}:")

    integer = Combine(Optional(oneOf("+ -")) + Word(nums)).setName("integer")
    integer.setParseAction(cvt_int)

    real = Combine(Optional(oneOf("+ -"))+ Word(nums)
                   + "." + Optional(Word(nums))
                   + Optional("e" + Optional(oneOf("+ -"))
                              + Word(nums))).setName("real")
    real.setParseAction(cvt_real)

    tuple_str = Forward()
    list_str = Forward()
    dict_str = Forward()

    list_item = (real | integer | Group(list_str) | tuple_str | dict_str
                 | quotedString.setParseAction(removeQuotes)
                 | Word(alphas8bit + alphas, alphas8bit + alphanums + "_"))
    list_item2 = list_item | Empty().setParseAction(lambda: [None])

    tuple_str << (Suppress("(") + Optional(delimitedList(list_item)) +
                  Optional(Suppress(",")) + Suppress(")"))
    tuple_str.setParseAction(cvt_tuple)

    list_str << (lbrack + Optional(delimitedList(list_item) +
                                   Optional(Suppress(","))) + rbrack)

    dict_entry = Group(list_item + colon + list_item2)
    dict_inner = delimitedList(dict_entry) + Optional(Suppress(","))
    dict_inner.setParseAction(cvt_dict)

    dict_str << (lbrace + Optional(dict_inner) + rbrace)

    return dict_inner

@@ -281,26 +281,92 @@
 nums
-)%0A%0Adef create_bnf(
+,%0A                       Keyword)%0A%0Adef create_bnf(allow_tuple=False, free_word=False
 ):%0A 
@@ -439,32 +439,121 @@
  float(toks%5B0%5D)%0A
+    cvt_bool =  lambda toks: toks%5B0%5D.lower == 'true'%0A    cvt_none =  lambda toks: %5BNone%5D%0A
     cvt_tuple = 
@@ -636,16 +636,17 @@
 ist())%0A%0A
+%0A
     # de
@@ -888,24 +888,189 @@
 n(cvt_int)%0A%0A
+    boolean = Keyword(%22False%22, caseless = True)%0A    boolean.setParseAction(cvt_bool)%0A%0A    none = Keyword(%22None%22, caseless = True)%0A    none.setParseAction(cvt_none)%0A%0A
     real = C
@@ -1399,21 +1399,200 @@
     
-list_item = (
+if free_word:%0A        string = Word(alphas8bit + %22_-/.+**%22 + alphanums)%0A%0A    else:%0A        string = Word(alphas8bit + alphas, alphas8bit + alphanums + %22_%22 )%0A%0A    list_item = (none %7C boolean %7C 
 real
@@ -1608,22 +1608,16 @@
 r %7C 
-Group(
 list_str
 ) %7C 
@@ -1612,17 +1612,16 @@
 list_str
-)
  %7C tuple
@@ -1624,16 +1624,33 @@
 uple_str
+%0A                
  %7C dict_
@@ -1737,63 +1737,15 @@
   %7C 
-Word(alphas8bit + alphas, alphas8bit + alphanums + %22_%22)
+string 
 )%0A  
@@ -1825,31 +1825,15 @@
 ple_
-str %3C%3C (Suppress(%22(%22) +
+inner =
  Opt
@@ -1865,34 +1865,16 @@
 item)) +
-%0A                 
  Optiona
@@ -1893,25 +1893,8 @@
 ,%22))
- + Suppress(%22)%22))
 %0A   
@@ -1900,18 +1900,20 @@
   tuple_
-st
+inne
 r.setPar
@@ -1932,25 +1932,25 @@
 _tuple)%0A
-%0A
     
-list
+tuple
 _str %3C%3C 
@@ -1954,112 +1954,224 @@
 %3C%3C (
-lbrack + Optional(delimitedList(list_item) +%0A                                   Optional(Suppress(%22,%22)))
+Suppress(%22(%22) + tuple_inner  + Suppress(%22)%22))%0A%0A    list_inner = Optional(delimitedList(list_item) + Optional(Suppress(%22,%22)))%0A    list_inner.setParseAction(lambda toks: list(toks))%0A    list_str %3C%3C (lbrack + list_inner
  + r
@@ -2342,17 +2342,16 @@
 t_dict)%0A
-%0A
     dict
@@ -2396,24 +2396,135 @@
  + rbrace)%0A%0A
+    dict_or_tuple =  dict_inner %7C tuple_inner%0A%0A    if allow_tuple:%0A        return dict_or_tuple%0A%0A    else:%0A    
     return d

add allow_tuple, free_word arguments to create_bnf()