Package Pyblio :: Package Parsers :: Package Syntax :: Package BibTeX :: Module Environ'
[hide private]
[frames] | no frames]

Source Code for Module Pyblio.Parsers.Syntax.BibTeX.Environ'

  1  # -*- coding: utf-8 -*- 
  2  # This file is part of pybliographer 
  3  #  
  4  # Copyright (C) 1998-2006 Frederic GOBRY 
  5  # Email : gobry@pybliographer.org 
  6  #           
  7  # This program is free software; you can redistribute it and/or 
  8  # modify it under the terms of the GNU General Public License 
  9  # as published by the Free Software Foundation; either version 2  
 10  # of the License, or (at your option) any later version. 
 11  #    
 12  # This program is distributed in the hope that it will be useful, 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 15  # GNU General Public License for more details.  
 16  #  
 17  # You should have received a copy of the GNU General Public License 
 18  # along with this program; if not, write to the Free Software 
 19  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
 20  #  
 21  #  
 22   
 23  """ 
 24  Handles decoding of @string substitution and of LaTeX commands. 
 25   
 26  The @string substitution is a one-way operation, as it is probably not 
 27  possible to do something better, except in some restricted cases 
 28  (dates for instance). Commands, on the other side, can be reencoded 
 29  when they represent unicode characters for instance. 
 30  """ 
 31   
 32  from Pyblio.Parsers.Syntax.BibTeX import Parser, Coding 
 33   
34 -def _accent(stack, cmd, tt):
35 36 try: 37 m = Coding.basemap[cmd] 38 39 except KeyError: 40 return Parser.Text('?') 41 42 if isinstance(tt, Parser.Text): 43 44 if len(tt) > 1: 45 t = tt[0] 46 stack.insert(0, Parser.Text(tt[1:])) 47 else: 48 t = tt 49 50 elif isinstance(tt, Parser.Block): 51 t = tt._d [0] 52 53 if isinstance(t, Parser.Text): 54 pass 55 56 elif isinstance(t, Parser.Cmd): 57 # There are a few special cases where one wants to accent a command, like: 58 # \'{\i} 59 if t._cmd == 'i': 60 t = Parser.Text('i') 61 else: 62 raise Exceptions.ParserError('cannot evaluate expression %s' % repr((cmd, tt))) 63 64 else: 65 raise Exceptions.ParserError('cannot evaluate expression %s' % repr((cmd, tt))) 66 67 else: 68 raise Exceptions.ParserError('cannot evaluate expression %s' % repr((cmd, tt))) 69 70 try: 71 return Parser.Text(m[t]) 72 except KeyError: 73 raise KeyError ("cannot find %s in map %s" % (repr (t), repr (cmd)))
74 75
76 -class Environ(object):
77 78 commands = { 79 "'": (_accent, 1), 80 '`': (_accent, 1), 81 '^': (_accent, 1), 82 '"': (_accent, 1), 83 'c': (_accent, 1), 84 '~': (_accent, 1), 85 } 86 87 commands.update(Coding.staticmap) 88
89 - def run(self, cmd, stack):
90 try: 91 fn, count = self.commands[cmd] 92 93 except KeyError: 94 # The \char macro is special: \char125 -> character with ascii code 125 95 if cmd.startswith('char'): 96 try: return Parser.Text(unichr(int(cmd[4:]))) 97 except ValueError: pass 98 99 # Try with local extensions 100 fn = getattr(self, 'do_' + cmd, None) 101 102 if fn: 103 return fn(cmd, stack) 104 105 return Parser.Text(cmd) 106 107 # we have found a known command. as a convenience, we fetch 108 # the required number of arguments and pass it to the actual 109 # function handling the command. 110 args = [] 111 112 while count: 113 try: 114 args.append(stack.pop(0)) 115 except IndexError: 116 raise Exceptions.ParserError('command %s requires %d arguments, got %s' % ( 117 repr(cmd), count, len(args))) 118 119 count -= 1 120 121 if callable(fn): 122 return fn(stack, cmd, *args) 123 124 return Parser.Text(fn)
125