from pyparsing import *
# Only the top level typedef element will be used to search for typedef stmts.
# But this is also used to parse declare stmts nested inside typedefs.
declare_list = Forward() # Will be defined later, after being referenced.
ident = Word(alphas+'_', alphanums+'_')
int_number = Word(nums+' ()+-*/')
# "|" = MatchFirst
simple_base = Group(
( Optional(Keyword('unsigned'))('unsigned') + oneOf('char int long short')('name') ) |
oneOf('unsigned double float void')('name') |
ident('name')
)('simple')
struct_base = Group( Keyword('struct') + Optional(ident('struct_name')) + '{' + declare_list + '}' )('struct')
union_base = Group( Keyword('union') + '{' + declare_list + '}' )('union') # "+" = And
enum_base = Group( Keyword('enum') + Optional(ident('enum_name')) + '{'
+ delimitedList(ident) + Optional(',') +
'}' )('enum')
any_base = (struct_base | union_base | enum_base | simple_base)('type')
array = Group( '[' + ( int_number | ident )('extent') + ']' )
bit_size = Group( ':' + int_number('extent') )
declare = Group(
any_base + ident('instance') +
Optional( OneOrMore(array)('array') | bit_size('bit') ) + ';'
)('declare')