User:Eriksiers/BBC BASIC detokenizer/Generator

From Rosetta Code

This code uses data contained in an Excel spreadsheet to generate the QBasic code on the main detokenizer page. (I'm not including the actual data, but it can be easily reconstructed from the QBasic code.)

Licensing

All source code on this page is Copyright ©2012 Erik Siers. (This specifically includes everything generated by this VBA/Excel code!) The sources are dual-licensed under the terms of the following licenses:

The two licenses are not 100% compatible; which license you use, I leave up to you.

Exception

Any source code that is generated by the generated QBasic program (only) is specifically excluded from the above licensing terms, and is instead covered by whatever license(s) cover the original, tokenized sources.

create_detoken.bas

<lang vb>Sub buildBas()

   Open ActiveWorkbook.Path & "\detoken.bas" For Output As 1
       For L0 = 2 To Cells.SpecialCells(xlCellTypeLastCell).Row
           If Len(Cells(L0, 2).Value) Then
               tmp = tmp + 1
               If (tmp Mod 10) = 1 Then Print #1, "DATA ";
               Print #1, LTrim$(Val("&h" & Cells(L0, 1).Value)); ","; Cells(L0, 2).Value; "";
               If (tmp Mod 10) = 0 Then
                   Print #1,
               Else
                   Print #1, ",";
               End If
           End If
       Next
       Print #1, "0": Print #1,
       Print #1, "DIM lineNum AS LONG, encoded AS STRING * 1"
       Print #1, "DIM tmp AS LONG, lineNumDec AS LONG"
       Print #1, "DIM keywords(255) AS STRING"
       Print #1, "DO"
       Print #1, "    READ t%"
       Print #1, "    IF 0 = t% THEN EXIT DO"
       Print #1, "    READ keywords(t%)"
       Print #1, "LOOP"
       Print #1, "nm$ = ENVIRON$(""DETOKEN"")"
       Print #1, "OPEN nm$ + "".bbc"" FOR BINARY AS 2"
       Print #1, "OPEN nm$ + "".bas"" FOR OUTPUT AS 3"
       Print #1, "'skip first char"
       Print #1, "GET #2, , encoded"
       Print #1, "GET #2, , lineNum"
       Print #1, "SEEK #2, SEEK(2) - 2"
       Print #1, "lineNum = (lineNum AND &HFFFF&)"
       Print #1, "IF (CHR$(0) = encoded) AND (&HFFFF& = lineNum) THEN"
       Print #1, "    CLOSE : SYSTEM"
       Print #1, "ELSEIF lineNum <> 0 THEN"
       Print #1, "    PRINT #3, LTRIM$(STR$(lineNum)); "" "";"
       Print #1, "END IF"
       'still haven't figured out the first char...
       'Print #1, "PRINT #3, ASC(encoded); CHR$(9);"
       Print #1, "DO UNTIL EOF(2)"
       Print #1, "    GET #2, , encoded"
       Print #1, "    i% = ASC(encoded)"
       Print #1, "    SELECT CASE i%"
       Print #1, "        CASE 0"
       Print #1, "            'do nothing"
       Print #1, "        CASE 13"
       Print #1, "            PRINT #3,"
       Print #1, "            'skip first char of next line"
       Print #1, "            IF NOT EOF(2) THEN"
       Print #1, "                GET #2, , encoded"
       Print #1, "                GET #2, , lineNum"
       Print #1, "                SEEK #2, SEEK(2) - 2"
       Print #1, "                lineNum = (lineNum AND &HFFFF&)"
       Print #1, "                IF (CHR$(0) = encoded) AND (&HFFFF& = lineNum) THEN"
       Print #1, "                    CLOSE : SYSTEM"
       Print #1, "                ELSEIF lineNum <> 0 THEN"
       Print #1, "                    PRINT #3, LTRIM$(STR$(lineNum)); "" "";"
       Print #1, "                END IF"
       Print #1, "            END IF"
       Print #1, "        CASE &H8D"
       Print #1, "            'deal with encoded line numbers (GOTO targets)"
       Print #1, "            IF NOT EOF(2) THEN"
       Print #1, "                GET #2, , encoded"
       Print #1, "                IF NOT EOF(2) THEN"
       Print #1, "                    GET #2, , lineNum"
       Print #1, "                    SEEK #2, SEEK(2) - 2"
       Print #1, "                    lineNum = (lineNum AND &HFFFF&)"
       Print #1, "                ELSE"
       Print #1, "                    'should NEVER get here"
       Print #1, "                    lineNum = 0"
       Print #1, "                END IF"
       Print #1, "                lo& = ((ASC(encoded) * 4&) AND &HC0) XOR (lineNum AND 255&)           'LEFT SHIFT ASC(encoded), 2"
       Print #1, "                hi& = ((ASC(encoded) * 16&) AND &HC0) XOR ((lineNum \ 256&) AND 255&) 'LEFT SHIFT ASC(encoded), 4"
       Print #1, "                tmp = lo& + (hi& * 256&)"
       Print #1, "                PRINT #3, LTRIM$(RTRIM$(STR$(tmp)));"
       Print #1, "            END IF"
       Print #1, "        CASE ELSE"
       Print #1, "            IF keywords(i%) <> """" THEN"
       Print #1, "                PRINT #3, keywords(i%);"
       Print #1, "            ELSE"
       Print #1, "                PRINT #3, encoded;"
       Print #1, "            END IF"
       Print #1, "    END SELECT"
       Print #1, "LOOP"
       Print #1, "CLOSE"
       Print #1, "SYSTEM"
   Close

End Sub</lang>