1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import re
18
19 from libxyz.parser import Lexer
20 from libxyz.parser import BaseParser
21 from libxyz.parser import SourceData
22 from libxyz.exceptions import XYZValueError
23 from libxyz.exceptions import LexerError
24 from libxyz.exceptions import ParseError
25
27 """
28 MultiParser is a simple container for any other parsers
29 Usually parsers, such as BlockParser designed to parse homogeneous blocks in
30 single source: file or string. But still it might be useful sometimes to
31 parse multiple blocks of different syntax in single source.
32 Thus, one can register some necessary parsers into MultiParser and go on.
33 """
34
35 DEFAULT_OPT = {
36 u"comment": u"#",
37 u"tokens": (),
38 }
39
41 """
42 @param parsers: dictionary containing string, list or
43 compiled regexp of keywords as key
44 and *Parser objects as values.
45 @type parsers: dictionary with string or sequence keys
46
47 @param opt: Options
48
49 Available options:
50 - comment: Comment character.
51 Everything else ignored until EOL.
52 Type: I{string (single char)}
53
54 - tokens: List of tokens.
55 Type: I{sequence}
56 """
57
58 super(MultiParser, self).__init__()
59
60 self._rx = re.compile("")
61
62 if parsers:
63 if not isinstance(parsers, dict):
64 raise XYZValueError(_(u"Invalid argument type %s. "\
65 u"Dictionary expected") % str(parsers))
66 else:
67 self.parsers = parsers
68 else:
69 self.parsers = {}
70
71 self.opt = opt or self.DEFAULT_OPT
72 self.set_opt(self.DEFAULT_OPT, self.opt)
73
74 self._lexer = None
75 self._result = {}
76
77
78
79 - def parse(self, source, default_data=None):
80 """
81 Begin parsing
82 """
83
84 def _get_parser(val):
85 _p = None
86
87 for _key in self.parsers:
88
89 if isinstance(_key, basestring) and _key == val:
90 _p = self.parsers[_key]
91 break
92
93 elif hasattr(_key, "__contains__") and val in _key:
94 _p = self.parsers[_key]
95 break
96
97 elif type(_key) is type(self._rx) and _key.match(val):
98 _p = self.parsers[_key]
99 break
100
101 return _p
102
103
104
105 self._result = {}
106 self._lexer = Lexer(source, self.tokens, self.comment)
107
108 _data = default_data or {}
109
110 try:
111 while True:
112 _res = self._lexer.lexer()
113
114 if _res is None:
115 break
116 else:
117 _lex, _val = _res
118
119 _parser = _get_parser(_val)
120
121 if _parser:
122
123 self._lexer.unget(_val)
124 _data = _parser.parse(self._lexer.sdata, _data)
125 self._result.update(_data)
126 else:
127 self.error(_(u"Unknown keyword: %s") % _val)
128 except LexerError, e:
129 self.error(str(e))
130
131 return self._result
132
133
134
136 """
137 Register new parser. If parser for keyword given already registered
138 replace it with new one.
139
140 @param keyword: Keyword that will trigger the parser.
141 @type keyword: string, sequence or compiled regular expression
142
143 @param param: Any *Parser instance. Must be subclassed
144 from L{BaseParser}.
145 """
146
147 if not isinstance(parser, BaseParser):
148 raise XYZValueError(_(u"Invalid argument type %s. "\
149 u"BaseParser or subclassed expected") % \
150 str(parsers))
151
152 self.parsers[keyword] = parser
153
154
155
157 """
158 Unregister parser. Ignore if was not registered.
159 """
160
161 try:
162 del(self.parsers[keyword])
163 except KeyError:
164 pass
165