#!/usr/bin/env python # -*- coding: utf-8 -*- # # p2_hints.py # -- updated 11 APR 2022 # # Copyright 2022 JonnyMac # # Contributors: # -- add your name to this list before re-posting # # Use: # -- python p2_hints_1v6.py INFILE # # Terms: MIT license # import sys p1p2_changes = { '**' : 'sca/scas', '^^' : 'sqrt', '||' : 'abs', '~>' : 'sar', ' ~~' : 'signx (!)', # leading ~~ ' ~' : 'signx (!)', # leading ~ ' ?' : '??', # leading ? '? ' : 'new code', # trailing ? '|<' : 'decod', '>|' : 'encod (!)', '<-' : 'rol', '->' : 'ror', '><' : 'rev (!)', '=>' : '>=', '=<' : '<=', 'ctra' : 'Smart pin or code', 'frqa' : 'Smart pin or code', 'phsa' : 'Smart pin or code', 'ctrb' : 'Smart pin or code', 'frqb' : 'Smart pin or code', 'phsb' : 'Smart pin or code', 'waitcnt' : 'waitct', 'cnt' : 'getct()', 'cognew' : 'coginit/cogspin', 'reboot' : 'hubset($1000_0000)', 'waitpeq' : 'pinread + code', 'waitpne' : 'pinread + code', 'waitvid' : 'new code', 'chipver' : 'N/A', 'constant' : 'N/A', 'string(' : '@ (optional)', 'spr[' : 'new code', 'ina[' : 'pinread', 'outa[' : 'pinwrite/pinread', 'dira[' : 'set by pinxxx functions', # JM common objects/calls '"jm_time' : 'use waitxxx functions', '"jm_prng' : 'use jm_random object/methods', '"jm_io' : 'use pinxxx functions or smart pin', 'time.pause' : 'waitms', 'io.high' : 'pinhigh', 'io.low' : 'pinlow', 'io.toggle' : 'pintoggle', } def char_count(c, s): """ Count and return occurances of char c in string s """ count = 0 for char in s: if (char == c): count += 1 return count def is_odd(n): return True if (n % 2 == 1) else False def in_quotes(i, s): """ Returns True if position i of string s is in quotes """ qs = s.rfind('"', 0, i) # find " after qe = s.find('"', i) # find " before qc = char_count('"', s[0:i]) if (qs >= 0) and (qe >= 0): # has quotes if (i > qs) and (i < qe) and is_odd(qc): # and inside them return True return False def in_block(i, s): """ Returns True if position i of string s is in single-line block comment {} """ bs = s.rfind('{', 0, i-1) # find } after be = s.find('}', i+1) # find { before if (bs >= 0) and (be >= 0): # has block comment if (i > bs) and (i < be): # in block if not in_quotes(i, s): # and not in quotes return True return False def in_comment(i, s): """ Returns True if postion i of string s is in an end-of-line comment -- does not work for single-line block comments """ cs = s.rfind("'") if (cs >= 0) and (i > cs): # after ' if not in_quotes(i, s): # and not in "" return True return False def is_clear(i, s): """ Returns True if position i of string s is not in quotes or comment """ if in_quotes(i, s): return False elif in_block(i, s): return False elif in_comment(i, s): return False else: return True def find_p1_tokens(s): """ Returns list of column/p1 token pairs in string s -- p1 token is key for p1p2 dictionary """ tokenslist = list() s = s.lower() scancol = 0 while scancol < len(s): for tkn in p1p2_changes: chk = s[scancol:scancol+len(tkn)] if (chk == tkn) and is_clear(scancol, s): # bump found columm if token starts with space or " adj = 0 if (tkn[0] not in ' "') else 1 tokenslist.append([scancol+adj, tkn]) # col & p1 token scancol += len(tkn) # move past token break else: # no token found scancol += 1 # search at next column return tokenslist def make_showme(tokens): """ Returns string of ^ symbols to point to tokens in source line """ s = "---- " pos = 0 for ts in tokens: loc = ts[0] if (loc > pos): s = s + " " * (loc-pos) s = s + "^" pos = loc+1 return s def process_file(infile): fixedlines = 0 fixes = 0 linenum = 0 print(f'Processing {infile}\n') try: fin = open(infile, 'r') except: print('-- Error opening input file') return -2 for line in fin: # line-by-line line = line.rstrip() # remove traling \n linenum += 1 tokens = find_p1_tokens(line) found = len(tokens) if found: fixedlines += 1 fixes += found s = make_showme(tokens) print(f'{linenum:04d} {line} \n{s}') for x in range(0, found): pos, p1t = tokens[x] pos += 1 p2h = p1p2_changes[p1t] if (p1t[0] == '"'): # strip leading " p1t = p1t[1:] if (p1t[-1] in "([(."): # strip trailing [(. p1t = p1t[:-1] print(f' * Col {pos:03d} (p1) {p1t:<10} (p2) {p2h}') print() fin.close() s1 = 'change' + 's' if (fixes != 1) else '' s2 = 'line' + 's' if (fixedlines != 1) else '' print(f'Done. {fixes} {s1} in {fixedlines} {s2}.') return 0 def main(args): if len(args) != 2: print(f"Use: python {args[0]} INFILE") return -1 return process_file(args[1]) if __name__ == '__main__': sys.exit(main(sys.argv))