Source code for sfepy.base.parse_conf

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

word_free = Word(alphas + '][@_-/.+**' + alphanums)
word_strict = Word(alphas, alphas + alphanums + '_' )

(lparen, rparen, lbrack, rbrack,
 lbrace, rbrace, colon, equal_sign) = map(Suppress, '()[]{}:=')

integer = Combine(Optional(oneOf('+ -')) + Word(nums)).setName('integer')
cvt_int = lambda toks: int(toks[0])
integer.setParseAction(cvt_int)

boolean_true = Keyword('True', caseless=True)
boolean_true.setParseAction(lambda x: True)
boolean_false = Keyword('False', caseless=True)
boolean_false.setParseAction(lambda x: False)

boolean = boolean_true | boolean_false

none = Keyword('None', caseless=True)

cvt_none = lambda toks: [None]
none.setParseAction(cvt_none)

real = Combine(Optional(oneOf('+ -')) + Word(nums)
               + '.' + Optional(Word(nums))
               + Optional('e' + Optional(oneOf('+ -'))
                          + Word(nums))).setName('real')
cvt_real = lambda toks: float(toks[0])
real.setParseAction(cvt_real)

array_index = integer + Optional(colon + integer
                                 + Optional(colon + integer))
cvt_array_index = lambda toks: int(toks[0]) if len(toks) == 1 \
                  else slice(*toks)
array_index.setParseAction(cvt_array_index)
array_braces = lbrack + array_index + rbrack

[docs]def create_bnf(allow_tuple=False, free_word=False): word = word_free if free_word else word_strict defs = get_standard_type_defs(word) if allow_tuple: return defs['dict'].inner | defs['tuple'].inner else: return defs['dict'].inner
[docs]def list_of(element, *elements): """ Return lexical element that parses a list of items. The items can be a one or several lexical elements. For example, result of ``list_of(real, integer)`` parses list of real or integer numbers. """ for e in elements: element |= e lst = delimitedList(element) return lst + Optional(Suppress(','))
[docs]def get_standard_type_defs(word=word_free): """ Return dict of the pyparsing base lexical elements. The compound types (tuple, list, dict) can contain compound types or simple types such as integers, floats and words. Parameters ---------- word : lexical element A custom lexical element for word. Returns ------- defs : dict The dictionary with the following items: - tuple: (..., ..., ...) - list: [..., ...., ...] - dict: {...:..., ...:..., ....} or {...=..., ...=..., ....} - list_item: any of preceding compound types or simple types """ tuple_str = Forward() list_str = Forward() dict_str = Forward() cvt_tuple = lambda toks : tuple(toks.asList()) cvt_dict = lambda toks: dict(toks.asList()) list_item = (none | boolean | real | integer | list_str | tuple_str | dict_str | quotedString.setParseAction(removeQuotes) | word) list_item2 = list_item | Empty().setParseAction(lambda: [None]) tuple_str.inner = list_of(list_item) tuple_str.inner.setParseAction(cvt_tuple) tuple_str << (lparen + tuple_str.inner + rparen) list_str.inner = tuple_str.inner.copy() list_str.inner.setParseAction(lambda toks: list(toks)) list_str << (lbrack + list_str.inner + rbrack) dict_entry = Group(list_item + (colon | equal_sign) + list_item2) dict_str.inner = list_of(dict_entry) dict_str.inner.setParseAction(cvt_dict) dict_str << (lbrace + Optional(dict_str.inner) + rbrace) defs = {'tuple' : tuple_str, 'list' : list_str, 'dict' : dict_str, 'list_item' : list_item} return defs
[docs]def list_dict(word=word_free): """ Return the pyparsing lexical element, that parses a string either as a list or as a dictionary. Parameters ---------- word : lexical element A custom lexical element for word. Returns ------- ld : lexical element The returned lexical element parses a string in the form ``..., ..., ...`` or ``key1:..., key2=..., key3: ...`` where ``...`` is a ``list_item`` from :func:`get_standard_type_defs()` and interprets it as a list or a dictionary. """ defs = get_standard_type_defs(word) i = defs['list_item'] arg = i.copy() arg.setParseAction(lambda t: (t[0],)) narg = word_strict + (colon | equal_sign) + i narg.setParseAction(lambda t: (t[0], t[1])) ld = Group(list_of(narg | arg)) ld.setParseAction(lambda t: ([x[0] for x in t[0] if len(x) == 1], dict([x for x in t[0] if len(x) > 1])) ) return ld