Skip to content
Snippets Groups Projects
Commit 4e98b897 authored by Martin Bauer's avatar Martin Bauer
Browse files

Python prm file parsing: added "_" as valid key identifier

parent b373b0e3
Branches
Tags
No related merge requests found
from __future__ import print_function, absolute_import, division, unicode_literals from __future__ import print_function, absolute_import, division, unicode_literals
import numpy as np import numpy as np
def _comment_replacer(match): def _comment_replacer(match):
start,mid,end = match.group(1,2,3) start, mid, end = match.group(1, 2, 3)
if mid is None: if mid is None:
# single line comment # single line comment
return '' return ''
...@@ -16,68 +17,71 @@ def _comment_replacer(match): ...@@ -16,68 +17,71 @@ def _comment_replacer(match):
# multi line comment without line break # multi line comment without line break
return ' ' return ' '
def _remove_comments(text): def _remove_comments(text):
import re import re
comment_re = re.compile( comment_re = re.compile(
r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?', r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
re.DOTALL | re.MULTILINE re.DOTALL | re.MULTILINE
) )
return comment_re.sub( _comment_replacer, text) return comment_re.sub(_comment_replacer, text)
def __parseNestedList( value, dtype = float): def __parse_nested_list(value, dtype=float):
from pyparsing import Word, Group, Forward, OneOrMore, Optional, alphanums, Suppress from pyparsing import Word, Group, Forward, OneOrMore, Optional, alphanums, Suppress
number = Word( alphanums + ".e-" ).setParseAction( lambda s,l,t: dtype(t[0]) ) number = Word(alphanums + ".e-").setParseAction(lambda s, l, t: dtype(t[0]))
arr = Forward() arr = Forward()
element = number | arr element = number | arr
arr << Group(Suppress('[') + ( OneOrMore(element + Optional(Suppress(",")) ) ) + Suppress(']') ) arr << Group(Suppress('[') + (OneOrMore(element + Optional(Suppress(",")))) + Suppress(']'))
return arr.parseString(value, parseAll = True).asList()[0] return arr.parseString(value, parseAll=True).asList()[0]
def __convertValue(value):
def tryType( thetype, value ): def __convert_value(value):
def try_type(thetype, value):
try: try:
return thetype(value) return thetype(value)
except ValueError: except ValueError:
return None return None
val = tryType(int, value)
val = try_type(int, value)
if val: return val if val: return val
val = tryType(float, value) val = try_type(float, value)
if val: return val if val: return val
if value == "True": return True if value == "True": return True
if value == "False" : return False if value == "False": return False
value = value.strip() value = value.strip()
if value[0] == '[' and value[-1] == "]": if value[0] == '[' and value[-1] == "]":
return np.array( __parseNestedList(value) ) return np.array(__parse_nested_list(value))
if value[0] == '<' and value[-1] == ">": if value[0] == '<' and value[-1] == ">":
return tuple( [__convertValue(s) for s in value[1:-1].split(",") ] ) return tuple([__convert_value(s) for s in value[1:-1].split(",")])
return value return value
def fromPrm( fileAsString ):
def fromPrm(fileAsString):
"""Parses a prm file to a nested python dict """ """Parses a prm file to a nested python dict """
from pyparsing import Word, Group, Forward, Dict, ZeroOrMore, Optional, alphanums, Suppress from pyparsing import Word, Group, Forward, Dict, ZeroOrMore, Optional, alphanums, Suppress
# Grammar # Grammar
identifier = Word( alphanums +"_-" ) identifier = Word(alphanums + "_-")
value = Word( alphanums + ".e-,<>[] \n" ).setParseAction( lambda s,l,t: __convertValue(t[0]) ) value = Word(alphanums + ".e-,<>_[] \n").setParseAction(lambda s, l, t: __convert_value(t[0]))
key_value_pair = Group ( identifier + Optional(value, default="") + Suppress(";") ) key_value_pair = Group(identifier + Optional(value, default="") + Suppress(";"))
block = Forward() block = Forward()
block_content = Dict( ZeroOrMore( key_value_pair | block ) ) block_content = Dict(ZeroOrMore(key_value_pair | block))
block << Group( identifier + Suppress("{") + block_content + Suppress("}") ) block << Group(identifier + Suppress("{") + block_content + Suppress("}"))
return block_content.parseString( _remove_comments(fileAsString) , parseAll = True ).asDict()
return block_content.parseString(_remove_comments(fileAsString), parseAll=True).asDict()
def __format(value, level, key=""): def __format(value, level, key=""):
if type(value) is float: if type(value) is float:
return "%.10g" % value return "%.10g" % value
else: else:
return str(value).replace("\n", "\n" + "\t"*level + " " * len(key) + " " ) return str(value).replace("\n", "\n" + "\t" * level + " " * len(key) + " ")
def toPrm( configDict, level = 0 ): def toPrm(configDict, level=0):
"""Returns a prm string from a nested python dict - Inverse of parse""" """Returns a prm string from a nested python dict - Inverse of parse"""
result = "" result = ""
for key, value in sorted(configDict.items()): for key, value in sorted(configDict.items()):
...@@ -87,28 +91,26 @@ def toPrm( configDict, level = 0 ): ...@@ -87,28 +91,26 @@ def toPrm( configDict, level = 0 ):
else: else:
result += "\t" * level + str(key) + "\n" result += "\t" * level + str(key) + "\n"
result += "\t" * level + "{\n" result += "\t" * level + "{\n"
result += toPrm(value, level + 1) result += toPrm(value, level + 1)
result += "\t" * level + "}\n" result += "\t" * level + "}\n"
elif ( type(value) is list ) and len( value ) > 0 and type(value[0]) is dict: elif (type(value) is list) and len(value) > 0 and type(value[0]) is dict:
for e in value: for e in value:
result += "\t" * level + str(key) + "\n" result += "\t" * level + str(key) + "\n"
result += "\t" * level + "{\n" result += "\t" * level + "{\n"
result += toPrm( e, level + 1) result += toPrm(e, level + 1)
result += "\t" * level + "}\n" result += "\t" * level + "}\n"
elif ( type(value) is tuple ) : elif type(value) is tuple:
result += "\t" * level + str(key) + " " result += "\t" * level + str(key) + " "
result += "< " + ",".join ( [ __format(v,level) for v in value ] ) + " >;\n" result += "< " + ",".join([__format(v, level) for v in value]) + " >;\n"
elif ( type(value) is float ): elif type(value) is float:
result += "\t" * level + str(key) + " " + __format(value,level) + ";\n" result += "\t" * level + str(key) + " " + __format(value, level) + ";\n"
else: else:
result += "\t" * level + str(key) + " " + __format(value,level,key) + ";\n" result += "\t" * level + str(key) + " " + __format(value, level, key) + ";\n"
return result return result
if __name__ == "__main__": if __name__ == "__main__":
test = """ test = """
blockId1 { blockId1 {
firstKey 5; // first key firstKey 5; // first key
...@@ -130,8 +132,8 @@ if __name__ == "__main__": ...@@ -130,8 +132,8 @@ if __name__ == "__main__":
outerKey hallo; outerKey hallo;
""" """
res = fromPrm( test ) res = fromPrm(test)
assert res['blockId1']['firstKey'] == 5 assert res['blockId1']['firstKey'] == 5
assert res['blockId1']['myVector3'] == ( 1.0, 2, 3) assert res['blockId1']['myVector3'] == (1.0, 2, 3)
assert res['blockId1']['keyWithoutValue'] == '' assert res['blockId1']['keyWithoutValue'] == ''
assert (res['blockId1']['myArray'] == np.array( [ [1,2], [3,4] ] )).all() assert (res['blockId1']['myArray'] == np.array([[1, 2], [3, 4]])).all()
\ No newline at end of file
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment