Program Real Line Counter. Anyone want to jump in?
#31
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
Reply
#32
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.
b = b + ...
Reply
#33
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.
Ask me about Windows API and maybe some Linux stuff
Reply
#34
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
Reply
#35
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.
b = b + ...
Reply
#36
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.
Ask me about Windows API and maybe some Linux stuff
Reply




Users browsing this thread: 1 Guest(s)