#!/usr/bin/env python3 # Face.py - module for reading and parsing Scintilla.iface file # Implemented 2000 by Neil Hodgson neilh@scintilla.org # Released to the public domain. # Requires Python 2.7 or later def sanitiseLine(line): if line[-1:] == '\n': line = line[:-1] if line.find("##") != -1: line = line[:line.find("##")] line = line.strip() return line def decodeFunction(featureVal): retType, rest = featureVal.split(" ", 1) nameIdent, params = rest.split("(") name, value = nameIdent.split("=") params, rest = params.split(")") param1, param2 = params.split(",") return retType, name, value, param1, param2 def decodeEvent(featureVal): retType, rest = featureVal.split(" ", 1) nameIdent, params = rest.split("(") name, value = nameIdent.split("=") return retType, name, value def decodeParam(p): param = p.strip() type = "" name = "" value = "" if " " in param: type, nv = param.split(" ") if "=" in nv: name, value = nv.split("=") else: name = nv return type, name, value def IsEnumeration(t): return t[:1].isupper() def PascalCase(s): capitalized = s.title() # Remove '_' except between digits pascalCase = "" characterPrevious = " " # Loop until penultimate character for i in range(len(capitalized)-1): character = capitalized[i] characterNext = capitalized[i+1] if character != "_" or ( characterPrevious.isnumeric() and characterNext.isnumeric()): pascalCase += character characterPrevious = character # Add last character - not between digits so no special treatment pascalCase += capitalized[-1] return pascalCase class Face: def __init__(self): self.order = [] self.features = {} self.values = {} self.events = {} self.aliases = {} def ReadFromFile(self, name): currentCategory = "" currentComment = [] currentCommentFinished = 0 file = open(name) for line in file.readlines(): line = sanitiseLine(line) if line: if line[0] == "#": if line[1] == " ": if currentCommentFinished: currentComment = [] currentCommentFinished = 0 currentComment.append(line[2:]) else: currentCommentFinished = 1 featureType, featureVal = line.split(" ", 1) if featureType in ["fun", "get", "set"]: try: retType, name, value, param1, param2 = decodeFunction(featureVal) except ValueError: print("Failed to decode %s" % line) raise p1 = decodeParam(param1) p2 = decodeParam(param2) self.features[name] = { "FeatureType": featureType, "ReturnType": retType, "Value": value, "Param1Type": p1[0], "Param1Name": p1[1], "Param1Value": p1[2], "Param2Type": p2[0], "Param2Name": p2[1], "Param2Value": p2[2], "Category": currentCategory, "Comment": currentComment } if value in self.values: raise Exception("Duplicate value " + value + " " + name) self.values[value] = 1 self.order.append(name) currentComment = [] elif featureType == "evt": retType, name, value = decodeEvent(featureVal) self.features[name] = { "FeatureType": featureType, "ReturnType": retType, "Value": value, "Category": currentCategory, "Comment": currentComment } if value in self.events: raise Exception("Duplicate event " + value + " " + name) self.events[value] = 1 self.order.append(name) elif featureType == "cat": currentCategory = featureVal elif featureType == "val": try: name, value = featureVal.split("=", 1) except ValueError: print("Failure %s" % featureVal) raise Exception() self.features[name] = { "FeatureType": featureType, "Category": currentCategory, "Value": value } self.order.append(name) elif featureType == "enu" or featureType == "lex": name, value = featureVal.split("=", 1) self.features[name] = { "FeatureType": featureType, "Category": currentCategory, "Value": value, "Comment": currentComment } self.order.append(name) currentComment = [] elif featureType == "ali": # Enumeration alias name, value = featureVal.split("=", 1) self.aliases[name] = value currentComment = [] file.close()