def skip_nest(self, pos): """Skips anything between two brackets, parentheses or braces starting at 'pos', if the brackets, parentheses or braces are not closed or are closed in the wrong order an error shall be raised """ lbrackets = ["LBRACKET", "LBRACE", "LPARENTHESIS"] rbrackets = ["RBRACKET", "RBRACE", "RPARENTHESIS"] try: c = self.peek_token(pos).type except: raise CParsingError(f"Unexpected EOF line {pos}") if c not in lbrackets: return pos c = rbrackets[lbrackets.index(c)] i = pos + 1 while self.peek_token(i) is not None: if self.check_token(i, lbrackets) is True: i = self.skip_nest(i) if i == -1: return -1 elif self.check_token(i, rbrackets) is True: if c == self.peek_token(i).type: return i i += 1 raise CParsingError("Nested parentheses, braces or brackets\ are not correctly closed") return -1
def check_reserved_keywords(self, context, pos): if context.check_token(pos, keywords) is False: return False, pos if context.check_token(pos, "RETURN"): i = pos + 1 while context.check_token(i, "SEMI_COLON") is False: i += 1 i += 1 return True, i elif context.check_token(pos, "GOTO"): i = pos + 1 i = context.skip_ws(i) while context.check_token( i, ["MULT", "BWISE_AND" ]) is True and context.is_operator(i) is False: i += 1 if context.check_token(i, "IDENTIFIER") is False: if context.check_token(i, "LPARENTHESIS") is True: #parse label value here i = context.skip_nest(i) elif context.debug == 0: raise CParsingError( "Goto statement should be followed by a label") i += 1 i = context.skip_ws(i) i += 1 return True, i else: i = pos + 1 i = context.skip_ws(i) i += 1 return True, i
def run(self, context, source): """ Main function for each file. Primary rules are determined by the prefix "Is" and are run by order of priority as defined in each class Each secondary rule is then run in arbitrary order based on their dependencies """ unrecognized_tkns = [] while context.tokens != []: context.tkn_scope = len(context.tokens) for rule in self.primary_rules: if type(context.scope) not in rule.scope and rule.scope != []: continue ret, jump = self.run_rules(context, rule) if ret is True: if unrecognized_tkns != []: if context.debug == 0: raise CParsingError( f"Unrecognized line {unrecognized_tkns[0].pos} while parsing line {unrecognized_tkns}" ) print('uncaught -> ', context.filename) print('uncaught -> ', unrecognized_tkns) unrecognized_tkns = [] context.dprint(rule.name, jump) context.update() context.pop_tokens(jump) break # ############################################################# else: # Remove these one ALL primary rules are done # print("#, ", context.tokens[0]) unrecognized_tkns.append(context.tokens[0]) context.pop_tokens(1) # ################################## # ############################################################# if unrecognized_tkns != []: print(context.debug) if context.debug > 0: print("uncaught ->", unrecognized_tkns) if context.errors == []: print(context.filename + ": OK!") else: print(context.filename + ": KO!") context.errors = sorted(context.errors, key=cmp_to_key(sort_errs)) for err in context.errors: print(err)
def run(self, context): """ User defined types must respect the following rules: - Struct names start with s_ - Enum names start with e_ - Union names start with u_ - Typedef names start with t_ """ i = 0 i = context.skip_ws(i) tkns = context.tokens is_td = False on_newline = False utype = None contain_full_def = False ids = [] while context.check_token(i, ['SEMI_COLON']) is False and i < len(context.tokens): if context.check_token(i, ['SPACE', 'TAB']): pass if context.check_token(i, ["LPARENTHESIS"]) is True: val, tmp = context.parenthesis_contain(i) if val == None: i = tmp if context.check_token(i, utypes) is True: utype = context.peek_token(i) if context.check_token(i, "TYPEDEF") is True: is_td = True if context.check_token(i, "LBRACKET") is True: i = context.skip_nest(i) if context.check_token(i, "IDENTIFIER") is True: if context.peek_token(i).value == "__attribute__": i += 1 i = context.skip_ws(i) i = context.skip_nest(i) continue if context.check_token(i - 1, ["MULT", "BWISE_AND"]) is True: tmp = i - 1 while context.check_token(tmp, ["MULT", "BWISE_AND"]) is True and context.is_operator(tmp) == False: tmp -= 1 ids.append((context.peek_token(i), tmp)) else: ids.append((context.peek_token(i), i)) if context.check_token(i, 'LBRACE') is True: contain_full_def = True i = context.skip_nest(i) i += 1 check = -1 if is_td == True and len(ids) < 2 and utype != None: context.new_error("MISSING_TYPEDEF_ID", context.peek_token(0)) return False, 0 if contain_full_def == False and is_td == False and len(ids) > 1: check = -2 else: check = -1 if len(ids) == 0: return False, 0 name = ids[0][0] loc = ids[check][1] if is_td == True: if ids[check][0].value.startswith('t_') is False: context.new_error("USER_DEFINED_TYPEDEF", context.peek_token(loc)) if utype is not None: if len(ids) > 1: name = ids[0][0] else: if context.debug >= 1: pass elif context.debug == 0: raise CParsingError(f"{context.filename}: Could not parse structure line {context.peek_token(0).pos[0]}") loc = ids[0][1] else: loc = ids[0][1] if utype is not None and utype.type == "STRUCT" and name.value.startswith('s_') is False: context.new_error("STRUCT_TYPE_NAMING", context.peek_token(loc)) if utype is not None and utype.type == "UNION" and name.value.startswith('u_') is False: context.new_error("UNION_TYPE_NAMING", context.peek_token(loc)) if utype is not None and utype.type == "ENUM" and name.value.startswith('e_') is False: context.new_error("ENUM_TYPE_NAMING", context.peek_token(loc)) if is_td or (is_td == False and contain_full_def == False): tmp = ids[-1][1] - 1 while (context.check_token(tmp, "TAB")) is True and tmp > 0: tmp -= 1 if context.check_token(tmp, "SPACE") is True: context.new_error("SPACE_REPLACE_TAB", context.peek_token(tmp)) while tmp > 0: if context.check_token(tmp, "RBRACE") is True: tmp = context.skip_nest_reverse(tmp) if context.check_token(tmp, "TAB") is True and on_newline == False: context.new_error("TAB_REPLACE_SPACE", context.peek_token(tmp)) tmp -= 1 if contain_full_def == False: i = 0 identifier = ids[-1][0] i = ids[-1][1] if context.check_token(i - 1, ["MULT", "BWISE_AND", "LPARENTHESIS"]) is True: i -= 1 while context.check_token(i, ["MULT", "BWISE_AND", "LPARENTHESIS"]) is True \ and context.is_operator(i) is False: i -= 1 current_indent = context.peek_token(i).pos[1] if context.scope.vars_alignment == 0: context.scope.vars_alignment = current_indent elif context.scope.vars_alignment != current_indent: context.new_error("MISALIGNED_VAR_DECL", context.peek_token(0)) return True, i return False, 0