| #!/usr/bin/env python |
| """ cdecl.py - parse c declarations |
| |
| (c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com> |
| 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<len(s): |
| if s[j] in ident_chars1: |
| j=j+1 |
| else: |
| break |
| tok = s[i:j] |
| self.col = j |
| kind = self._get_kind(tok) |
| break |
| if s[i].isdigit() or \ |
| (i+1<len(s) and s[i] in '+-.' and s[i+1].isdigit()): |
| # number literal |
| is_float = s[i]=='.' |
| is_hex = s[i:i+2]=='0x' |
| if is_hex: |
| i=i+2 |
| assert s[i].isdigit() or s[i] in "abcdefABCDEF", self.err_string() |
| j=i+1 |
| while j<len(s): |
| #print "lex ",repr(s[i]),is_float |
| if s[j].isdigit() or (is_hex and s[j] in "abcdefABCDEF"): |
| j=j+1 |
| elif s[j]=='.' and not is_float: |
| assert not is_hex |
| j=j+1 |
| is_float=1 |
| else: |
| break |
| tok = s[i:j] |
| self.col = j |
| if is_float: |
| kind = float(tok) |
| elif is_hex: |
| kind = int(tok,16) |
| else: |
| kind = int(tok) |
| break |
| if s[i:i+3]=='...': |
| # ellipses |
| #sys.stderr.write( "ELLIPSES "+str(self.get_state()) ) |
| tok = s[i:i+3] |
| kind = self._get_kind(tok) |
| self.col = i+3 |
| break |
| if s[i] in '*/{}()[]:;,=+-~.<>|&': |
| tok = s[i] |
| kind = tok |
| self.col = i+1 |
| break |
| if s[i] == "'": |
| j = i+2 |
| while j<len(s) and s[j]!="'": |
| j+=1 |
| if j==len(s): |
| raise LexError( self.err_string() + "unterminated char constant" ) |
| tok = s[i:j+1] |
| self.col = j+1 |
| kind = s[i:j+1] |
| break |
| # keep moving |
| #sys.stderr.write( "lexer ignoring '%s'\n"%s[i] ) |
| sys.stderr.write( "lexer ignoring '%s' lno=%d\n"%(s[i],self.lno+1) ) |
| i=i+1 |
| # end while i < len(s) |
| if i==len(s): |
| # nothing found, go to next line |
| assert tok == "" |
| self.col=0 |
| self.lno+=1 |
| self._newline() |
| else: |
| # we got one |
| assert tok |
| break |
| # end while self.lno < len(self.lines): |
| self.set_state(tok,kind,self.lno,self.col) |
| |
| def err_string(self): |
| "Return helpful error string :)" |
| return self.lines[self.lno]+"\n"+" "*self.col+"^\n" |
| |
| def push_state(self): |
| self.stack = self.get_state() # a short stack :) |
| #self.stack.push( self.get_state() ) |
| |
| def unget_token(self): |
| assert self.stack is not None |
| self.set_state(*self.stack) |
| self.stack = None |
| |
| def set_state(self,tok,kind,lno,col): |
| if self.verbose: |
| print "tok,kind,lno,col = ",(tok,kind,lno,col) |
| self.tok = tok |
| self.kind = kind |
| self.lno = lno # line |
| self.col = col # column |
| |
| def get_state(self): |
| return self.tok,self.kind,self.lno,self.col |
| |
| def get_file(self): |
| return self.so_file |
| |
| ################################################################### |
| # |
| ################################################################### |
| # |
| |
| |