Package libxyz :: Package parser :: Module multi
[hide private]
[frames] | no frames]

Source Code for Module libxyz.parser.multi

  1  #-*- coding: utf8 -* 
  2  # 
  3  # Max E. Kuznecov ~syhpoon <syhpoon@syhpoon.name> 2008 
  4  # 
  5  # This file is part of XYZCommander. 
  6  # XYZCommander is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU Lesser Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # XYZCommander is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 13  # GNU Lesser Public License for more details. 
 14  # You should have received a copy of the GNU Lesser Public License 
 15  # along with XYZCommander. If not, see <http://www.gnu.org/licenses/>. 
 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   
26 -class MultiParser(BaseParser):
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
40 - def __init__(self, parsers, opt=None):
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 # First string 89 if isinstance(_key, basestring) and _key == val: 90 _p = self.parsers[_key] 91 break 92 # Next sequence 93 elif hasattr(_key, "__contains__") and val in _key: 94 _p = self.parsers[_key] 95 break 96 # Otherwise regexp 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 # Push read token back 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
135 - def register(self, keyword, parser):
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
156 - def unregister(self, keyword):
157 """ 158 Unregister parser. Ignore if was not registered. 159 """ 160 161 try: 162 del(self.parsers[keyword]) 163 except KeyError: 164 pass
165