RE: Program Real Line Counter. Anyone want to jump in? - Pete - 10-24-2022
That took some re-tooling to fix. I needed to address instances of compound IF THEN statements with colons so this wouldn't happen...
IF a = b THEN IF c = d THEN x = 1: y = 2
didn't turn into...
IF a = b THEN IF c = d THEN
x = 1: y = 2
END IF
So now it recognizes compound IF/THEN statements and blocks them as...
IF a = b THEN
IF c = d THEN
x = 1: y = 2
END IF
END IF
What I haven't addressed yet, and may pass on is the ELSE statement in an IF/THEN being converted to a block if.
IF a = b THEN IF c = d THEN x = 1: y = 2 ELSE x = 0: y = 0
becomes...
IF a = b THEN
IF c = d THEN
x = 1
y = 2
ELSE x = 0
y = 0
END IF
END IF
That's fine and acceptable and if you are in a contest, it's one line less than I would write it as...
IF a = b THEN
IF c = d THEN
x = 1
y = 2
ELSE
x = 0
y = 0
END IF
END IF
Anyway... Here's the slightly retooled version. Note that bug was only present when choice "2" was made to block single line IF/THEN statements containing colons.
Code: (Select All) WIDTH 100, 25
_SCREENMOVE _MIDDLE
DIM AS _INTEGER64 i
REDIM then_marker(0)
z$ = _CLIPBOARD$
x$ = UCASE$(_CLIPBOARD$)
IF RIGHT$(x$, 2) <> CHR$(13) + CHR$(10) THEN x$ = x$ + CHR$(13) + CHR$(10) ' Compensates for 1-line no return Notepad copy.
PRINT "Line count analysis and reformat app...": PRINT
DO
LINE INPUT "Remove blank program lines from re-formatted code? [Y] / [N]: "; tmp$: PRINT
tmp$ = UCASE$(tmp$)
IF tmp$ = "Y" THEN no_blanks = -1
IF INSTR("YN", rem_ans$) THEN EXIT DO
LOOP
DO
LINE INPUT "Count statements beginning with REM or ' as a line? [Y] / [N]: "; rem_ans$: PRINT
rem_ans$ = UCASE$(rem_ans$)
IF INSTR("YN", rem_ans$) THEN EXIT DO
LOOP
PRINT "Press [1] to parse all colons. [2] to exclude colons in one-line IF/THEN statements.": PRINT
DO
_LIMIT 30
b$ = INKEY$
IF LEN(b$) THEN
SELECT CASE b$
CASE CHR$(27): SYSTEM
CASE "1": PRINT "Parsing all significant colons...": EXIT DO
CASE "2": myopt = -1: PRINT "Parsing all significant colons not used in IF/THEN one line statements.": EXIT DO
END SELECT
END IF
LOOP
PRINT
_KEYCLEAR
FOR i = 1 TO LEN(x$)
a$ = MID$(x$, i, 1)
SELECT CASE a$
CASE CHR$(10) ' Check for labels and blank lines here.
IF label_check THEN
tmp$ = _TRIM$(MID$(s$, INSTR(s$, ":") + 1))
IF MID$(tmp$, 1, 3) = "REM" OR LEFT$(tmp$, 1) = "'" OR tmp$ = CHR$(10) + CHR$(13) OR tmp$ = "" THEN ELSE MID$(z$, label_check, 1) = CHR$(0): c_cnt = c_cnt + 1
END IF
IF LEN(s$) = 0 THEN blank_line_cnt = blank_line_cnt + 1
IF parse4$ = "off" THEN rem_lines = rem_lines + 1
IF if_block$ = "on" THEN
' Special to compound IF/THEN statements.
FOR j = 1 TO it_cnt
MID$(z$, then_marker(j), 1) = CHR$(0)
c_cnt = c_cnt + 1 ' Add one line for the END IF
MID$(z$, i - 1, 1) = CHR$(255): MID$(z$, i, 1) = CHR$(126 + it_cnt) ' tag to add "end ifs" to end of block.
NEXT
END IF
' Clear variables for next line. (Except for parse4$)
if_block$ = "": ERASE then_marker: it_cnt = 0
s$ = "": c$ = "": parse1$ = "": parse2$ = "": parse3$ = "": label_check = 0: ide_line_cnt = ide_line_cnt + 1
CASE CHR$(13)
' Do nothing.
CASE ELSE
s$ = s$ + a$
c$ = c$ + a$
IF c$ = "THEN " THEN
SELECT CASE myopt
CASE -1
IF parse1$ = "" AND parse2$ = "" AND parse4$ = "" THEN parse3$ = "off"
CASE 0
IF parse1$ = "" AND parse2$ = "" AND parse4$ = "" THEN
it_cnt = it_cnt + 1: REDIM _PRESERVE then_marker(it_cnt): then_marker(it_cnt) = i
END IF
END SELECT
END IF
IF s$ = "$IF THEN" THEN parse4$ = "off": parse1$ = "": parse2$ = "": parse3$ = ""
IF a$ = "'" OR c$ = "REM " THEN
IF parse1$ = "" AND parse2$ = "" AND parse3$ = "" AND parse4$ = "" THEN parse1$ = "off"
IF _TRIM$(s$) = _TRIM$(c$) THEN rem_lines = rem_lines + 1
END IF
IF parse4$ = "off" THEN IF s$ = "$END IF " THEN parse4$ = ""
IF a$ = " " THEN c$ = ""
IF parse1$ <> "off" THEN ' Remark statements.
IF a$ = CHR$(34) THEN IF parse1$ = "" AND parse3$ = "" THEN IF parse2$ = "off" THEN parse2$ = "" ELSE parse2$ = "off"
IF parse2$ <> "off" THEN ' Quoted text like PRINT statements or string assignments.
IF parse3$ <> "off" THEN 'IF/THEN.
IF parse4$ <> "off" THEN ' $IF/THEN block.
IF myopt = 0 AND it_cnt THEN IF a$ = ":" THEN IF if_block$ = "" THEN if_block$ = "on"
IF col$ = "on" THEN IF a$ <> " " AND a$ <> ":" THEN col$ = ""
IF a$ = ":" THEN ' Test for label.
IF INSTR(MID$(LTRIM$(s$), 1, INSTR(LTRIM$(s$), ":")), " ") = 0 THEN
label_check = i + 1
ELSE
IF col$ = "" THEN col$ = "on": c_cnt = c_cnt + 1: MID$(z$, i, 1) = CHR$(0)
END IF
END IF
END IF
END IF
END IF
END IF
END SELECT
IF a$ = "_" THEN IF MID$(x$, i + 1, 1) = CHR$(13) THEN IF parse1$ = "" AND parse2$ = "" AND parse3$ = "" THEN cont_lines = cont_lines + 1
NEXT
IF rem_ans$ = "Y" THEN
PRINT "IDE Lines ="; ide_line_cnt; " Statement Lines ="; ide_line_cnt - blank_line_cnt - cont_lines; " Real Lines ="; ide_line_cnt - blank_line_cnt - cont_lines + c_cnt
ELSE
PRINT "IDE Lines ="; ide_line_cnt; " Statement Lines Without Remark Lines ="; ide_line_cnt - blank_line_cnt - cont_lines - rem_lines; " Real Lines ="; ide_line_cnt - blank_line_cnt - cont_lines - rem_lines + c_cnt
END IF
_CLIPBOARD$ = ""
FOR i = 1 TO LEN(z$)
a$ = MID$(z$, i, 1)
IF a$ = CHR$(0) THEN
concat$ = concat$ + CHR$(13) + CHR$(10)
ELSEIF a$ = CHR$(255) THEN
k = ASC(MID$(z$, i + 1, 1)) - 126
FOR j = 1 TO k
concat$ = concat$ + CHR$(13) + "END IF"
NEXT
MID$(z$, i + 1, 1) = CHR$(10) ' Replace expected control character for next loop.
ELSE
IF no_blanks = 0 THEN
concat$ = concat$ + a$
ELSE
j = -1
IF RIGHT$(concat$, 1) = CHR$(10) THEN IF a$ = CHR$(10) OR a$ = CHR$(13) THEN j = 0 ' skip printing a blank line.
IF j THEN concat$ = concat$ + a$
END IF
END IF
NEXT
_CLIPBOARD$ = concat$
PRINT: PRINT "Program line rewrite was added to your clipboard."
Pete
RE: Program Real Line Counter. Anyone want to jump in? - bplus - 10-24-2022
Yeah I was thinking the 2 forms of IF THEN would throw a monkey wrench into the works, just showed up later...
My brain is still on freak'n ball reflections, I just reworked... well never mind.
Glad you are still on the case to get this Lines-Of-Code (LOC) thing right!
I like the rewrite with the comments and blank lines preserved (and counted) so I know what to deduct from the IDE last line number.
RE: Program Real Line Counter. Anyone want to jump in? - SpriggsySpriggs - 10-25-2022
I think if you were to use my tokenize function then this should be pretty easy. You pass it a list of delimiters and then it splits a string based on those delimiters. You could give it the colon, carriage-return + line feed, and whatever else, and the resulting array count should be pretty accurate. Then you'd need to handle the line continuation stuff (underscore). If you don't want to count lines that start with a comma or a REM then you can simply omit those from the tokenized array.
RE: Program Real Line Counter. Anyone want to jump in? - Pete - 10-25-2022
Tokenizers are pretty cool. The question would be does yours parse out REM lines and text enclosed in quotes, as colons appearing in those must be ignored, as well as a colon used for a label name. The latter is easy because there is no leading space. Anyway, mostly building this for fun and did a little extra because Mark has a use for it. If you'd like to post or link yous, as an alternative, in this thread that would be great. It's cool when folks come to sites to dig around and find a few examples in a thread.
Pete
RE: Program Real Line Counter. Anyone want to jump in? - bplus - 10-25-2022
I was thinking of using Split as well but as Pete points out their is the enclosed : in double quotes to contend with and it's not going to help with the 2 forms of IF THEN namely single line and block. I skipped single line with my interpreter just to avoid the extra hassle of distinguishing between the two.
RE: Program Real Line Counter. Anyone want to jump in? - SpriggsySpriggs - 10-25-2022
It would probably require running them through the tokenize stuff a few times. First for blank lines, then for comments, then for colons, etc. It's all from C so it's very fast.
|