#!/usr/bin/env python """ cdecl.py - parse c declarations (c) 2002, 2003, 2004, 2005 Simon Burton Released under GNU LGPL license. version 0.xx """ import sys import string import types import copy #from cparse import BasicType, Qualifier, StorageClass, Typedef, Ellipses, GCCBuiltin #from cparse import * import cparse as host class LexError(Exception): pass class Lexer(object): def __init__(self,s="",verbose=0,**kw): self.verbose = verbose self.lookup = {} # a map for keywords and typedefs for t in \ "float double void char int".split(): self.lookup[t] = host.BasicType( t ) for t in \ "register signed unsigned short long const volatile inline".split(): # inline here ??? self.lookup[t] = host.Qualifier( t ) for t in "extern static auto".split(): self.lookup[t] = host.StorageClass( t ) self.lookup['typedef'] = host.Typedef() #self.lookup['__inline__'] = host.GCCBuiltin('__inline__') #self.lookup['__extension__'] = host.Qualifier('__extension__') self.lookup['...'] = host.Ellipses() if s: self.lex(s) for key in kw.keys(): self.__dict__[key] = kw[key] def lex(self,s): self.stack = None self.lines = s.splitlines() self.set_state("","",0,0) self.so_file = "" self._newline() self.get_token() # start def mktypedef(self,tok,node): if self.verbose: print "%s.mktypedef(%s,%s)"%(self,tok,node) self.lookup[ tok ] = node def rmtypedef(self,tok): " used in round trip testing " # print "# rmtypedef(%s)"%tok assert isinstance( self.lookup[ tok ], host.Node ) # existance del self.lookup[ tok ] def _get_kind(self,tok): #print '_get_kind(%s)'%tok,self.lookup try: return self.lookup[tok] #return self.lookup[tok].clone() except KeyError: if tok.startswith("__builtin"): node = host.GCCBuiltin(tok) self.lookup[tok] = node return node #elif tok in ( "__extension__", ): #node = GCCBuiltin(tok) #self.lookup[tok] = node #return node return None def _newline(self): while self.lno < len(self.lines): line = self.lines[self.lno] if not line or line[0] != "#": break l = line.split('"') assert len(l)>=2 self.so_file = l[1] #self.so_lno = int( l[0].split()[1] ) #sys.stderr.write("# %s %s: %s\n"%(so_lno,so_file,l)) self.lno+=1 def get_brace_token( self ): self.push_state() ident_chars0 = string.letters+"_" ident_chars1 = string.letters+string.digits+"_" tok, kind = "", "" while self.lno < len(self.lines): s = self.lines[self.lno] i=self.col while i < len(s): if s[i] not in '{}': i=i+1 continue else: tok = s[i] kind = tok self.col = i+1 break # keep moving #sys.stderr.write( "lexer ignoring '%s'\n"%s[i] ) i=i+1 if i==len(s): # nothing found assert tok == "" self.col=0 self.lno+=1 self._newline() else: assert tok break self.set_state(tok,kind,self.lno,self.col) def get_token(self): self.push_state() ident_chars0 = string.letters+"_" ident_chars1 = string.letters+string.digits+"_" tok, kind = "", "" while self.lno < len(self.lines): s = self.lines[self.lno] i=self.col while i < len(s): if s[i].isspace(): i=i+1 continue #if s[i] in ident_chars0: if s[i].isalpha() or s[i]=='_': # identifier j=i+1 while j|&': tok = s[i] kind = tok self.col = i+1 break if s[i] == "'": j = i+2 while j