summaryrefslogtreecommitdiff
path: root/cad/src/tools/AMBER/ParseINI.py
blob: 08df1f09c7efd7ae974cc0d0da4c39f3a0c069bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env python

"""
ParseINI.py

Implements a rudimentary parser for config files used by GROMACS to
define force fields, such as the AMBER force field.

Comments start with ; and can appear anywhere.

These files are designed to be processed through cpp, so they may
include #define statements.  For the intended use of this module, we
will treat these as comments.

Blank lines are ignored.

Sections are introduced with '[ section_name ]'.  Indendation of this
indicates nesting of sections in .rtp files.

Data lines within a section consist of a set of whitespace delimited
fields, the interpretation of which varies depending on the section.

This module parses a single file, and returns a data structure
representing the top level of the file.  Each Section is a list of
Elements, each of which could be either another Section, or an Entry.

"""

class INIElement(object):
    pass

class Section(INIElement):
    def __init__(self, name):
        self.name = name
        self.elements = []

    def addElement(self, element):
        self.elements.append(element)

    def getElements(self):
        return self.elements

    def get(self, index):
        return self.elements[index]

    def write(self, indent):
        print "%s[ %s ]" % (indent, self.name)
        for element in self.elements:
            element.write(indent + " ")

class Entry(INIElement):
    def __init__(self, columns):
        self.columns = columns

    def getColumn(self, col):
        return self.columns[col]

    def getColumnCount(self):
        return len(self.columns)

    def write(self, indent):
        print "%s%s" % (indent, " ".join(self.columns))

class ParseINI(object):
    def __init__(self, filename):
        f = open(filename)
        self._lines = f.readlines()
        f.close()
        self._lineNumber = -1
        self._sectionIndent = -1
        self._sectionName = "default"
        self._nextLine()

    def _nextLine(self):
        self._lineNumber = self._lineNumber + 1
        while (self._lineNumber < len(self._lines)):
            line = self._lines[self._lineNumber]
            semi = line.find(";")
            if (semi >= 0):
                line = line[:semi]
            oct = line.find("#")
            if (oct >= 0):
                line = line[:oct]
            line = line.strip()
            if (len(line) == 0):
                self._lineNumber = self._lineNumber + 1
                continue
            self._columns = line.split()
            return
        self._columns = None

    def _parseSectionHeader(self):
        cols = self._columns
        if (cols != None and cols[0] == "[" and cols[-1] == "]"):
            sectionName = " ".join(cols[1:-1])
        else:
            sectionName = "default"
        line = self._lines[self._lineNumber]
        spaces = 0
        while (line[0] == " "):
            line = line[1:]
            spaces = spaces + 1
        self._sectionIndent = spaces
        self._sectionName = sectionName
        

    def parse(self):
        sectionName = self._sectionName
        indent = self._sectionIndent
        contents = Section(sectionName)
        while (self._columns != None):
            cols = self._columns
            if (cols[0] == "["):
                self._parseSectionHeader()
                while (self._columns != None and self._sectionIndent > indent):
                    self._nextLine()
                    nestedSection = self.parse()
                    contents.addElement(nestedSection)
                return contents
            else:
                thisRecord = Entry(cols)
                contents.addElement(thisRecord)
            self._nextLine()
        return contents

if (__name__ == '__main__'):
    import sys
    parser = ParseINI(sys.argv[1])
    tree = parser.parse()
    tree.write("")