class SDKConfig: """ Encapsulates an sdkconfig file. Defines grammar of a configuration entry, and enables evaluation of logical expressions involving those entries. """ # A configuration entry is in the form CONFIG=VALUE. Definitions of components of that grammar IDENTIFIER = Word(alphanums.upper() + "_") HEX = Combine("0x" + Word(hexnums)).setParseAction(lambda t:int(t[0], 16)) DECIMAL = Combine(Optional(Literal("+") | Literal("-")) + Word(nums)).setParseAction(lambda t:int(t[0])) LITERAL = Word(printables.replace(":", "")) QUOTED_LITERAL = quotedString.setParseAction(removeQuotes) VALUE = HEX | DECIMAL | LITERAL | QUOTED_LITERAL # Operators supported by the expression evaluation OPERATOR = oneOf(["=", "!=", ">", "<", "<=", ">="]) def __init__(self, kconfig_file, sdkconfig_file, env=[]): env = [(name, value) for (name,value) in (e.split("=",1) for e in env)] for name, value in env: value = " ".join(value.split()) os.environ[name] = value self.config = kconfiglib.Kconfig(kconfig_file) self.config.load_config(sdkconfig_file) def evaluate_expression(self, expression): result = self.config.eval_string(expression) if result == 0: # n return False elif result == 2: # y return True else: # m raise Exception("unsupported config expression result") @staticmethod def get_expression_grammar(): identifier = SDKConfig.IDENTIFIER.setResultsName("identifier") operator = SDKConfig.OPERATOR.setResultsName("operator") value = SDKConfig.VALUE.setResultsName("value") test_binary = identifier + operator + value test_single = identifier test = test_binary | test_single condition = Group(Optional("(").suppress() + test + Optional(")").suppress()) grammar = infixNotation(condition, [ ("!", 1, opAssoc.RIGHT), ("&&", 2, opAssoc.LEFT), ("||", 2, opAssoc.LEFT)]) return grammar
class SDKConfig: """ Evaluates conditional expressions based on the build's sdkconfig and Kconfig files. This also defines the grammar of conditional expressions. """ # A configuration entry is in the form CONFIG=VALUE. Definitions of components of that grammar IDENTIFIER = Word(alphanums.upper() + '_') HEX = Combine('0x' + Word(hexnums)).setParseAction(lambda t: int(t[0], 16)) DECIMAL = Combine(Optional(Literal('+') | Literal('-')) + Word(nums)).setParseAction(lambda t: int(t[0])) LITERAL = Word(printables.replace(':', '')) QUOTED_LITERAL = quotedString.setParseAction(removeQuotes) VALUE = HEX | DECIMAL | LITERAL | QUOTED_LITERAL # Operators supported by the expression evaluation OPERATOR = oneOf(['=', '!=', '>', '<', '<=', '>=']) def __init__(self, kconfig_file, sdkconfig_file): self.config = kconfiglib.Kconfig(kconfig_file) self.config.load_config(sdkconfig_file) def evaluate_expression(self, expression): result = self.config.eval_string(expression) if result == 0: # n return False elif result == 2: # y return True else: # m raise Exception('unsupported config expression result') @staticmethod def get_expression_grammar(): identifier = SDKConfig.IDENTIFIER.setResultsName('identifier') operator = SDKConfig.OPERATOR.setResultsName('operator') value = SDKConfig.VALUE.setResultsName('value') test_binary = identifier + operator + value test_single = identifier test = test_binary | test_single condition = Group( Optional('(').suppress() + test + Optional(')').suppress()) grammar = infixNotation(condition, [('!', 1, opAssoc.RIGHT), ('&&', 2, opAssoc.LEFT), ('||', 2, opAssoc.LEFT)]) return grammar
def __init__(self): self.filename = "" self.basedir = "" ############# # Constants # ############# self.possibleKeywords = [ "AGGREGALLOWED", "AUTOPEN", "AXIS-VERSION", "BASEPERIOD", "CELLNOTE", "CELLNOTEX", "CFPRICES", "CHARSET", "CODEPAGE", "CODES", "CONFIDENTIAL", "CONTACT", "CONTENTS", "CONTVARIABLE", "COPYRIGHT", "CREATION-DATE", "DATA", "DATABASE", "DATANOTECELL", "DATANOTESUM", "DATASYMBOL1", "DATASYMBOL2", "DATASYMBOL3", "DATASYMBOL4", "DATASYMBOL5", "DATASYMBOL6", "DATASYMBOLNIL", "DATASYMBOLSUM", "DAYADJ", "DECIMAL", "DEFAULT-GRAPH", "DESCRIPTION", "DESCRIPTIONDEFAULT", "DIRECTORY-PATH", "DOMAIN", "DOUBLECOLUMN", "ELIMINATION", "HEADING", "HIERARCHIES", "HIERARCHYLEVELS", "HIERARCHYLEVELSOPEN", "HIERARCHYNAMES", "INFO", "INFOFILE", "KEYS", "LANGUAGE", "LANGUAGES", "LAST-UPDATED", "LINK", "MAP", "MATRIX", "NEXT-UPDATE", "NOTE", "NOTEX", "PARTITIONED", "PRECISION", "PRESTEXT", "PX-SERVER", "REFPERIOD", "ROUNDING", "SEASADJ", "SHOWDECIMALS", "SOURCE", "STOCKFA", "STUB", "SUBJECT-AREA", "SUBJECT-CODE", "SURVEY", "SYNONYMS", "TABLEID", "TIMEVAL", "TITLE", "UNITS", "UPDATE-FREQUENCY", "VALUENOTE", "VALUENOTEX", "VALUES", "VARIABLE-TYPE" ] self.mandatoryKeywords = [ "CONTENTS", "DATA", "DECIMAL", "HEADING", "MATRIX", "STUB", "SUBJECT-AREA", "SUBJECT-CODE", "TITLE", "UNITS", "VALUES" ] self.languageAllowedKeywords = [ "BASEPERIOD", "CELLNOTE", "CELLNOTEX", "CFPRICES", "CODES", "CONTACT", "CONTENTS", "CONTVARIABLE", "DATABASE", "DATANOTECELL", "DATANOTESUM", "DATASYMBOL1", "DATASYMBOL2", "DATASYMBOL3", "DATASYMBOL4", "DATASYMBOL5", "DATASYMBOL6", "DATASYMBOLNIL", "DATASYMBOLSUM", "DAYADJ", "DESCRIPTION", "DOMAIN", "DOUBLECOLUMN", "ELIMINATION", "HEADING", "HIERARCHIES", "HIERARCHYLEVELS", "HIERARCHYLEVELSOPEN", "HIERARCHYNAMES", "INFO", "INFOFILE", "KEYS", "LAST-UPDATED", "LINK", "MAP", "NOTE", "NOTEX", "PARTITIONED", "PRECISION", "PRESTEXT", "REFPERIOD", "SEASADJ", "SOURCE", "STOCKFA", "STUB", "SUBJECT-AREA", "SURVEY", "TIMEVAL", "TITLE", "UNITS", "VALUENOTE", "VALUENOTEX", "VALUES", "VARIABLE-TYPE" ] ########### # Buffers # ########### self.buffers = { "foundKeywords": [], "currentKeyword": "", "validLanguageCodes": [], "languageCode": "", "timeFormat": "", "rounding": "", "results": {}, } ########### # Grammar # ########### # Utilities self.grammar = {} self.grammar["EOL"] = LineEnd().suppress() self.grammar["quote"] = Suppress(Regex("\"|\'")) self.grammar["number"] = Word(nums).setParseAction( self.convertToNumber) self.grammar["quotedString"] = (QuotedString('"') | QuotedString("'"))\ .setParseAction(lambda tokens: tokens[0].replace("#", "\n")) self.grammar["quotedNumber"] = self.grammar["quote"] + self.grammar[ "number"] + self.grammar["quote"] self.grammar["lparen"], self.grammar["rparen"], self.grammar[ "lbracket"], self.grammar["rbracket"] = map(Suppress, "()[]") self.grammar["dots"] = Regex("\.{1,6}") self.grammar["quotedDots"] = self.grammar["quote"] + self.grammar[ "dots"] + self.grammar["quote"] self.grammar["dataNumber"] = Combine(Optional("-") + Word(nums) +\ Optional(Literal(".") + Word(nums))).setParseAction(self.convertToNumber) # Keywords self.grammar["baseKeyword"] = Word(alphanums.upper() + "-")\ .setParseAction(self.handleKeyword)("keyword") self.grammar["tableSpecificKeyword"] = self.grammar[ "baseKeyword"] + FollowedBy("=") self.grammar["variableSpecificKeyword"] = self.grammar["baseKeyword"] +\ self.grammar["lparen"] +\ self.grammar["quotedString"]("variable") +\ self.grammar["rparen"] + FollowedBy("=") self.grammar["valueSpecificKeyword"] = self.grammar["baseKeyword"] +\ self.grammar["lparen"] + Group(self.grammar["quotedString"]("variable") + Suppress(",") +\ self.grammar["quotedString"]("value")) + self.grammar["rparen"] + FollowedBy("=") self.grammar["languageSpecificKeyword"] = (self.grammar["baseKeyword"] +\ self.grammar["lbracket"] + Word(alphas).setParseAction(self.isValidLanguageCode)("language") +\ self.grammar["rbracket"] + FollowedBy("=")).setParseAction(self.isLanguageAllowedKeyword) self.grammar["keyword"] = self.grammar["tableSpecificKeyword"] |\ self.grammar["variableSpecificKeyword"] |\ self.grammar["valueSpecificKeyword"] |\ self.grammar["languageSpecificKeyword"] # Keyword values self.grammar["keywordValue"] = OneOrMore(self.grammar["quotedString"])\ .setParseAction(lambda tokens: " ".join(tokens)) self.grammar["keywordValues"] = Group(delimitedList((self.grammar["number"] |\ self.grammar["keywordValue"])\ .setParseAction(self.handleKeywordValue)("keywordValue")))("keywordValues") +\ FollowedBy(";") # Time list values self.grammar["timeFormat"] = Regex("[AHQMW]1").setParseAction( self.setTimeFormat)("timeFormat") self.grammar["timeValues"] = Group( delimitedList(self.grammar["quotedNumber"])("timeValue")) self.grammar["timeSpan"] = Group( delimitedList(self.grammar["quotedNumber"]("timeValue"), delim="-")) self.grammar["TLIST"] = Literal("TLIST") + self.grammar["lparen"] +\ (self.grammar["timeFormat"] + ((self.grammar["rparen"] + Suppress(",") +\ self.grammar["timeValues"])|(Suppress(",") + self.grammar["timeSpan"] +\ self.grammar["rparen"]))).setParseAction(self.convertTimeList) + FollowedBy(";") self.grammar["keywordLine"] = Group(self.grammar["keyword"] + Suppress("=") +\ (self.grammar["keywordValues"] | self.grammar["TLIST"]) +\ Suppress(";")) # Data values self.grammar["observation"] = (self.grammar["quotedDots"] | self.grammar["dataNumber"]) self.grammar["observationSeparator"] = White(" \t").suppress() self.grammar["observationLine"] = Group(delimitedList(self.grammar["observation"],\ delim=self.grammar["observationSeparator"]).leaveWhitespace()) self.grammar["observationLines"] = OneOrMore(self.grammar["observationLine"] +\ Optional(Suppress(";")))("keywordValues") self.grammar["data"] = Group(Literal("DATA")("keyword") + Suppress("=") +\ Optional(OneOrMore(self.grammar["EOL"])) + self.grammar["observationLines"]) # Whole file self.grammar["pcaxisFile"] = OneOrMore(self.grammar["keywordLine"]) +\ OneOrMore(self.grammar["EOL"]) + self.grammar["data"]
def get_parser(self): declaration = Forward() keyword = (Keyword("enum") | Keyword("case") | Keyword("struct") | Keyword("default") | Keyword("switch") | Keyword("union") | Keyword("const") | Keyword("unsigned") | Keyword("int") | Keyword("hyper") | Keyword("float") | Keyword("double") | Keyword("bool") | Keyword("typedef") | Keyword("opaque") | Keyword("string") | Keyword("void") | Keyword("program") | Keyword("version")) identifier = NotAny(keyword) + Word( alphas + alphas.upper(), alphanums + alphanums.upper() + "_", asKeyword=True) constant = Combine(Optional("-") + Word(nums)) constant.setParseAction(lambda s, l, t: [int(t[0])]) value = constant | identifier enum_body = Literal("{").suppress() + identifier + Literal( "=").suppress() + value + ZeroOrMore( Literal(",").suppress() + identifier + Literal("=").suppress() + value) + Literal("}").suppress() enum_type_spec = Literal("enum").suppress() + enum_body enum_body.setParseAction(self.parse_enum) struct_body = Literal("{").suppress() + OneOrMore( declaration + Literal(";").suppress()) + Literal("}").suppress() struct_type_spec = Literal("struct").suppress() + struct_body struct_body.setParseAction(self.parse_struct) case_stmt = Literal("case").suppress() + value + Literal( ":").suppress() + declaration + Literal(";").suppress() default_stmt = Literal("default") + Literal( ":").suppress() + declaration + Literal(";").suppress() union_body = Literal("switch").suppress() + Literal("(").suppress( ) + declaration + Literal(")").suppress() + Literal("{").suppress( ) + Group(OneOrMore(Group(case_stmt)) + Optional(Group(default_stmt))) + Literal("}").suppress() union_type_spec = Literal("union").suppress() + union_body union_body.setParseAction(self.parse_union) constant_def = Literal("const").suppress() + identifier + Literal( "=").suppress() + constant + Literal(";").suppress() constant_def.setParseAction(self.parse_const) type_spec = ((Optional(Literal("unsigned")) + Literal("int")).setParseAction(self.parse_builtin) | (Optional(Literal("unsigned")) + Literal("hyper")).setParseAction(self.parse_builtin) | Literal("float").setParseAction(self.parse_builtin) | Literal("double").setParseAction(self.parse_builtin) | Literal("bool").setParseAction(self.parse_builtin) | enum_type_spec | struct_type_spec | union_type_spec | identifier) proc_return = Literal("void") | type_spec procedure_def = proc_return + identifier + Literal("(").suppress() + ( Literal("void") | type_spec) + ZeroOrMore( Literal(",").suppress() + type_spec) + Literal(")").suppress() + Literal( "=").suppress() + constant + Literal(";").suppress() procedure_def.setParseAction(self.parse_procedure_def) version_def = Literal("version").suppress() + identifier + Literal( "{").suppress() + OneOrMore(procedure_def) + Literal("}").suppress( ) + Literal("=").suppress() + constant + Literal(";").suppress() version_def.setParseAction(self.parse_version_def) program_body = Literal("{").suppress() + Group( OneOrMore(version_def)) + Literal("}").suppress() type_def = ( (Literal("typedef") + declaration + Literal(";")) | (Literal("enum") + identifier + enum_body + Literal(";")) | (Literal("struct") + identifier + struct_body + Literal(";")) | (Literal("union") + identifier + union_body + Literal(";")) | (Literal("program") + identifier + program_body + Literal("=").suppress() + constant + Literal(";"))) type_def.setParseAction(self.parse_type_def) declaration << ( (type_spec + identifier + Literal("[") + value + Literal("]")) | (type_spec + identifier + Literal("<") + value + Literal(">")) | (type_spec + identifier) | (Literal("opaque") + identifier + Literal("[") + value + Literal("]")) | (Literal("opaque") + identifier + Literal("<") + value + Literal(">")) | (Literal("string") + identifier + Literal("<") + value + Literal(">")) | (type_spec + Literal("*") + identifier) | Literal("void")) declaration.setParseAction(self.parse_decl) definition = type_def | constant_def specification = ZeroOrMore(definition) comment = (Literal("#") + restOfLine).suppress() specification.ignore(comment) return specification
def __init__(self): self.filename = "" self.basedir = "" ############# # Constants # ############# self.possibleKeywords = [ "AGGREGALLOWED", "AUTOPEN", "AXIS-VERSION", "BASEPERIOD", "CELLNOTE", "CELLNOTEX", "CFPRICES", "CHARSET", "CODEPAGE", "CODES", "CONFIDENTIAL", "CONTACT", "CONTENTS", "CONTVARIABLE", "COPYRIGHT", "CREATION-DATE", "DATA", "DATABASE", "DATANOTECELL", "DATANOTESUM", "DATASYMBOL1", "DATASYMBOL2", "DATASYMBOL3", "DATASYMBOL4", "DATASYMBOL5", "DATASYMBOL6", "DATASYMBOLNIL", "DATASYMBOLSUM", "DAYADJ", "DECIMAL", "DEFAULT-GRAPH", "DESCRIPTION", "DESCRIPTIONDEFAULT", "DIRECTORY-PATH", "DOMAIN", "DOUBLECOLUMN", "ELIMINATION", "HEADING", "HIERARCHIES", "HIERARCHYLEVELS", "HIERARCHYLEVELSOPEN", "HIERARCHYNAMES", "INFO", "INFOFILE", "KEYS", "LANGUAGE", "LANGUAGES", "LAST-UPDATED", "LINK", "MAP", "MATRIX", "NEXT-UPDATE", "NOTE", "NOTEX", "PARTITIONED", "PRECISION", "PRESTEXT", "PX-SERVER", "REFPERIOD", "ROUNDING", "SEASADJ", "SHOWDECIMALS", "SOURCE", "STOCKFA", "STUB", "SUBJECT-AREA", "SUBJECT-CODE", "SURVEY", "SYNONYMS", "TABLEID", "TIMEVAL", "TITLE", "UNITS", "UPDATE-FREQUENCY", "VALUENOTE", "VALUENOTEX", "VALUES", "VARIABLE-TYPE" ] self.mandatoryKeywords = [ "CONTENTS", "DATA", "DECIMAL", "HEADING", "MATRIX", "STUB", "SUBJECT-AREA", "SUBJECT-CODE", "TITLE", "UNITS", "VALUES" ] self.languageAllowedKeywords = [ "BASEPERIOD", "CELLNOTE", "CELLNOTEX", "CFPRICES", "CODES", "CONTACT", "CONTENTS", "CONTVARIABLE", "DATABASE", "DATANOTECELL", "DATANOTESUM", "DATASYMBOL1", "DATASYMBOL2", "DATASYMBOL3", "DATASYMBOL4", "DATASYMBOL5", "DATASYMBOL6", "DATASYMBOLNIL", "DATASYMBOLSUM", "DAYADJ", "DESCRIPTION", "DOMAIN", "DOUBLECOLUMN", "ELIMINATION", "HEADING", "HIERARCHIES", "HIERARCHYLEVELS", "HIERARCHYLEVELSOPEN", "HIERARCHYNAMES", "INFO", "INFOFILE", "KEYS", "LAST-UPDATED", "LINK", "MAP", "NOTE", "NOTEX", "PARTITIONED", "PRECISION", "PRESTEXT", "REFPERIOD", "SEASADJ", "SOURCE", "STOCKFA", "STUB", "SUBJECT-AREA", "SURVEY", "TIMEVAL", "TITLE", "UNITS", "VALUENOTE", "VALUENOTEX", "VALUES", "VARIABLE-TYPE" ] ########### # Buffers # ########### self.buffers = { "foundKeywords" : [], "currentKeyword" : "", "validLanguageCodes" : [], "languageCode" : "", "timeFormat" : "", "rounding" : "", "results" : {}, } ########### # Grammar # ########### # Utilities self.grammar = {} self.grammar["EOL"] = LineEnd().suppress() self.grammar["quote"] = Suppress(Regex("\"|\'")) self.grammar["number"] = Word(nums).setParseAction(self.convertToNumber) self.grammar["quotedString"] = (QuotedString('"') | QuotedString("'"))\ .setParseAction(lambda tokens: tokens[0].replace("#", "\n")) self.grammar["quotedNumber"] = self.grammar["quote"] + self.grammar["number"] + self.grammar["quote"] self.grammar["lparen"], self.grammar["rparen"], self.grammar["lbracket"], self.grammar["rbracket"] = map(Suppress, "()[]") self.grammar["dots"] = Regex("\.{1,6}") self.grammar["quotedDots"] = self.grammar["quote"] + self.grammar["dots"] + self.grammar["quote"] self.grammar["dataNumber"] = Combine(Optional("-") + Word(nums) +\ Optional(Literal(".") + Word(nums))).setParseAction(self.convertToNumber) # Keywords self.grammar["baseKeyword"] = Word(alphanums.upper() + "-")\ .setParseAction(self.handleKeyword)("keyword") self.grammar["tableSpecificKeyword"] = self.grammar["baseKeyword"] + FollowedBy("=") self.grammar["variableSpecificKeyword"] = self.grammar["baseKeyword"] +\ self.grammar["lparen"] +\ self.grammar["quotedString"]("variable") +\ self.grammar["rparen"] + FollowedBy("=") self.grammar["valueSpecificKeyword"] = self.grammar["baseKeyword"] +\ self.grammar["lparen"] + Group(self.grammar["quotedString"]("variable") + Suppress(",") +\ self.grammar["quotedString"]("value")) + self.grammar["rparen"] + FollowedBy("=") self.grammar["languageSpecificKeyword"] = (self.grammar["baseKeyword"] +\ self.grammar["lbracket"] + Word(alphas).setParseAction(self.isValidLanguageCode)("language") +\ self.grammar["rbracket"] + FollowedBy("=")).setParseAction(self.isLanguageAllowedKeyword) self.grammar["keyword"] = self.grammar["tableSpecificKeyword"] |\ self.grammar["variableSpecificKeyword"] |\ self.grammar["valueSpecificKeyword"] |\ self.grammar["languageSpecificKeyword"] # Keyword values self.grammar["keywordValue"] = OneOrMore(self.grammar["quotedString"])\ .setParseAction(lambda tokens: " ".join(tokens)) self.grammar["keywordValues"] = Group(delimitedList((self.grammar["number"] |\ self.grammar["keywordValue"])\ .setParseAction(self.handleKeywordValue)("keywordValue")))("keywordValues") +\ FollowedBy(";") # Time list values self.grammar["timeFormat"] = Regex("[AHQMW]1").setParseAction(self.setTimeFormat)("timeFormat") self.grammar["timeValues"] = Group(delimitedList(self.grammar["quotedNumber"])("timeValue")) self.grammar["timeSpan"] = Group(delimitedList(self.grammar["quotedNumber"]("timeValue"), delim="-")) self.grammar["TLIST"] = Literal("TLIST") + self.grammar["lparen"] +\ (self.grammar["timeFormat"] + ((self.grammar["rparen"] + Suppress(",") +\ self.grammar["timeValues"])|(Suppress(",") + self.grammar["timeSpan"] +\ self.grammar["rparen"]))).setParseAction(self.convertTimeList) + FollowedBy(";") self.grammar["keywordLine"] = Group(self.grammar["keyword"] + Suppress("=") +\ (self.grammar["keywordValues"] | self.grammar["TLIST"]) +\ Suppress(";")) # Data values self.grammar["observation"] = (self.grammar["quotedDots"] | self.grammar["dataNumber"]) self.grammar["observationSeparator"] = White(" \t").suppress() self.grammar["observationLine"] = Group(delimitedList(self.grammar["observation"],\ delim=self.grammar["observationSeparator"]).leaveWhitespace()) self.grammar["observationLines"] = OneOrMore(self.grammar["observationLine"] +\ Optional(Suppress(";")))("keywordValues") self.grammar["data"] = Group(Literal("DATA")("keyword") + Suppress("=") +\ Optional(OneOrMore(self.grammar["EOL"])) + self.grammar["observationLines"]) # Whole file self.grammar["pcaxisFile"] = OneOrMore(self.grammar["keywordLine"]) +\ OneOrMore(self.grammar["EOL"]) + self.grammar["data"]
from pyparsing import Word, alphanums, delimitedList, Group, Optional, cStyleComment, ZeroOrMore, Forward, nestedExpr from first_order import Var, Relation, Exists from primitives import Literal as Lit, FreeClause, Implies, And, HornClause from visitor import FreeVarVisitor upper = alphanums.upper() + "_" lower = alphanums.lower() + "_" identifier = Word(lower).setResultsName("name", listAllMatches=True) variable = Word(upper).setResultsName("var_name", listAllMatches=True) relation_par = Forward() list_par = Forward().setResultsName("list") parameter = variable ^ identifier ^ relation_par ^ list_par comma_list = delimitedList(parameter) head_tail_list = parameter.setResultsName( "head") + "|" + variable.setResultsName("tail") # list = "[" + (comma_list ^ head_tail_list) + "]" list_parser = nestedExpr(opener="[", closer="]", content=comma_list) list_par << list_parser relation = Group( identifier.setResultsName("relation_name") + "(" + Optional(Group(delimitedList(parameter)).setResultsName("parameters")) + ")").setResultsName("relation") relation_par << relation literal_relation = identifier.setResultsName("relation_name") + "(" + Group(delimitedList(identifier)) \ .setResultsName("literals") + ")"
def get_parser(self): declaration = Forward() keyword = ( Keyword("enum") | Keyword("case") | Keyword("struct") | Keyword("default") | Keyword("switch") | Keyword("union") | Keyword("const") | Keyword("unsigned") | Keyword("int") | Keyword("hyper") | Keyword("float") | Keyword("double") | Keyword("bool") | Keyword("typedef") | Keyword("opaque") | Keyword("string") | Keyword("void") | Keyword("program") | Keyword("version") ) identifier = NotAny(keyword) + Word(alphas + alphas.upper(), alphanums + alphanums.upper() + "_", asKeyword=True) constant = Combine(Optional("-") + Word(nums)) constant.setParseAction(lambda s,l,t: [int(t[0])]) value = constant | identifier enum_body = Literal("{").suppress() + identifier + Literal("=").suppress() + value + ZeroOrMore(Literal(",").suppress() + identifier + Literal("=").suppress() + value) + Literal("}").suppress() enum_type_spec = Literal("enum").suppress() + enum_body enum_body.setParseAction(self.parse_enum) struct_body = Literal("{").suppress() + OneOrMore(declaration + Literal(";").suppress()) + Literal("}").suppress() struct_type_spec = Literal("struct").suppress() + struct_body struct_body.setParseAction(self.parse_struct) case_stmt = Literal("case").suppress() + value + Literal(":").suppress() + declaration + Literal(";").suppress() default_stmt = Literal("default") + Literal(":").suppress() + declaration + Literal(";").suppress() union_body = Literal("switch").suppress() + Literal("(").suppress() + declaration + Literal(")").suppress() + Literal("{").suppress() + Group(OneOrMore(Group(case_stmt)) + Optional(Group(default_stmt))) + Literal("}").suppress() union_type_spec = Literal("union").suppress() + union_body union_body.setParseAction(self.parse_union) constant_def = Literal("const").suppress() + identifier + Literal("=").suppress() + constant + Literal(";").suppress() constant_def.setParseAction(self.parse_const) type_spec = ( (Optional(Literal("unsigned")) + Literal("int")).setParseAction(self.parse_builtin) | (Optional(Literal("unsigned")) + Literal("hyper")).setParseAction(self.parse_builtin) | Literal("float").setParseAction(self.parse_builtin) | Literal("double").setParseAction(self.parse_builtin) | Literal("bool").setParseAction(self.parse_builtin) | enum_type_spec | struct_type_spec | union_type_spec | identifier ) proc_return = Literal("void") | type_spec procedure_def = proc_return + identifier + Literal("(").suppress() + (Literal("void") | type_spec) + ZeroOrMore(Literal(",").suppress() + type_spec) + Literal(")").suppress() + Literal("=").suppress() + constant + Literal(";").suppress() procedure_def.setParseAction(self.parse_procedure_def) version_def = Literal("version").suppress() + identifier + Literal("{").suppress() + OneOrMore(procedure_def) + Literal("}").suppress() + Literal("=").suppress() + constant + Literal(";").suppress() version_def.setParseAction(self.parse_version_def) program_body = Literal("{").suppress() + Group(OneOrMore(version_def)) + Literal("}").suppress() type_def = ( (Literal("typedef") + declaration + Literal(";")) | (Literal("enum") + identifier + enum_body + Literal(";")) | (Literal("struct") + identifier + struct_body + Literal(";")) | (Literal("union") + identifier + union_body + Literal(";")) | (Literal("program") + identifier + program_body + Literal("=").suppress() + constant + Literal(";")) ) type_def.setParseAction(self.parse_type_def) declaration << ( (type_spec + identifier + Literal("[") + value + Literal("]")) | (type_spec + identifier + Literal("<") + value + Literal(">")) | (type_spec + identifier) | (Literal("opaque") + identifier + Literal("[") + value + Literal("]")) | (Literal("opaque") + identifier + Literal("<") + value + Literal(">")) | (Literal("string") + identifier + Literal("<") + value + Literal(">")) | (type_spec + Literal("*") + identifier) | Literal("void") ) declaration.setParseAction(self.parse_decl) definition = type_def | constant_def specification = ZeroOrMore(definition) comment = (Literal("#") + restOfLine).suppress() specification.ignore(comment) return specification