Skip to content

Commit d713788

Browse files
authored
Add QuickBASIC (#7080)
* Fix FreeBASIC capitalization * Add QuickBASIC with samples * Make regexes case-insensitive + small tweak * Fix comment after CLS issue * Include statement and second pass * Add CONST + VBA second pass * Improve quickbasic and freebasic heuristics * del: Remove VBA fallback for now
1 parent 120e0e5 commit d713788

File tree

12 files changed

+374
-3
lines changed

12 files changed

+374
-3
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,9 @@
12651265
[submodule "vendor/grammars/vsc-language-1c-bsl"]
12661266
path = vendor/grammars/vsc-language-1c-bsl
12671267
url = https://github.com/1c-syntax/vsc-language-1c-bsl.git
1268+
[submodule "vendor/grammars/vscode"]
1269+
path = vendor/grammars/vscode
1270+
url = https://github.com/QB64Official/vscode.git
12681271
[submodule "vendor/grammars/vscode-TalonScript"]
12691272
path = vendor/grammars/vscode-TalonScript
12701273
url = https://github.com/mrob95/vscode-TalonScript.git

grammars.yml

+2
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,8 @@ vendor/grammars/vsc-fennel:
11321132
vendor/grammars/vsc-language-1c-bsl:
11331133
- source.bsl
11341134
- source.sdbl
1135+
vendor/grammars/vscode:
1136+
- source.QB64
11351137
vendor/grammars/vscode-TalonScript:
11361138
- markdown.talon.codeblock
11371139
- source.talon

lib/linguist/heuristics.yml

+34-2
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,15 @@ disambiguations:
9191
- language: B4X
9292
pattern: '\A\W{0,3}(?:.*(?:\r?\n|\r)){0,9}B4(?:J|A|R|i)=true'
9393
- language: FreeBASIC
94-
pattern: '^[ \t]*#(?i)(?:define|endif|endmacro|ifn?def|include|lang|macro)(?:$|\s)'
94+
named_pattern: freebasic
95+
- language: FreeBASIC
96+
and:
97+
- pattern: '(?i)^[ \t]*return '
98+
- negative_pattern: '(?i)[ \t]*gosub '
9599
- language: BASIC
96100
pattern: '\A\s*\d'
101+
- language: QuickBASIC
102+
named_pattern: quickbasic
97103
- language: VBA
98104
named_pattern: vba
99105
- language: Visual Basic 6.0
@@ -119,7 +125,11 @@ disambiguations:
119125
- extensions: ['.bi']
120126
rules:
121127
- language: FreeBASIC
122-
pattern: '^[ \t]*#(?i)(?:define|endif|endmacro|ifn?def|if|include|lang|macro)(?:$|\s)'
128+
named_pattern: freebasic
129+
- language: FreeBASIC
130+
and:
131+
- pattern: '(?i)^[ \t]*return '
132+
- negative_pattern: '(?i)[ \t]*gosub '
123133
- extensions: ['.bs']
124134
rules:
125135
- language: Bikeshed
@@ -922,6 +932,10 @@ named_patterns:
922932
- '^\s*(?:public\s+)?include\s'
923933
- '^\s*(?:(?:public|export|global)\s+)?(?:atom|constant|enum|function|integer|object|procedure|sequence|type)\s'
924934
fortran: '^(?i:[c*][^abd-z]| (subroutine|program|end|data)\s|\s*!)'
935+
freebasic:
936+
- '(?i)^[ \t]*#(?:define|endif|endmacro|ifn?def|include|lang|macro|pragma)(?:$|\s)'
937+
- '(?i)^[ \t]*dim( shared)? [a-z_][a-z0-9_]* as [a-z_][a-z0-9_]* ptr'
938+
- '(?i)^[ \t]*dim( shared)? as [a-z_][a-z0-9_]* [a-z_][a-z0-9_]*'
925939
gsc:
926940
- '^\s*#\s*(?:using|insert|include|define|namespace)[ \t]+\w'
927941
- '^\s*(?>(?:autoexec|private)\s+){0,2}function\s+(?>(?:autoexec|private)\s+){0,2}\w+\s*\('
@@ -949,6 +963,24 @@ named_patterns:
949963
- '^\s*(?:\*|(?:our\s*)?@)EXPORT\s*='
950964
- '^\s*package\s+[^\W\d]\w*(?:::\w+)*\s*(?:[;{]|\sv?\d)'
951965
- '[\s$][^\W\d]\w*(?::\w+)*->[a-zA-Z_\[({]'
966+
quickbasic:
967+
# Uppercase keywords are a good indicator of QuickBASIC (if no FreeBASIC syntax is detected)
968+
- '^[ ]*(CONST|DIM|REDIM|DEFINT|PRINT|DECLARE (SUB|FUNCTION)|FUNCTION|SUB) '
969+
# Preprocessor statement to set the compiler dialect in QuickBASIC ($lang) and FreeBASIC (#lang)
970+
- '(#|$)lang:?\s*"?qb"?'
971+
# Other QuickBASIC-specific patterns
972+
- '(?i)''\$INCLUDE:'
973+
- '(?i)^[ ]*CLS[ ]*(''|:|\r|\n)'
974+
- '(?i)^[ ]*OPTION _EXPLICIT'
975+
- '(?i)^[ ]*DIM SHARED '
976+
- '(?i)^[ ]*PRINT "'
977+
- '(?i) As _(Byte|Offset|MEM)'
978+
- '(?i)^[ ]*_(DISPLAY|DEST|CONSOLE|SOURCE|FREEIMAGE|PALETTECOLOR|PRINTSTRING|LOADFONT|PUTIMAGE)'
979+
- '(?i)^[ ]*_(TITLE|PLAYMOD) "'
980+
- '(?i)^[ ]*_(LIMIT|SCREEN|DELAY) \.?\d+'
981+
- '(?i)\b_(MOUSEBUTTON|NEWIMAGE|KEYDOWN|WIDTH|HEIGHT)\('
982+
- '(?i)^[ ]*\$(CONSOLE|CHECKING):'
983+
- '(?i)^[ ]*\$(FULLSCREEN|RESIZE|STATIC|DYNAMIC|NOPREFIX|SCREENSHOW|SCREENHIDE|EXEICON)\b'
952984
raku: '^\s*(?:use\s+v6\b|\bmodule\b|\b(?:my\s+)?class\b)'
953985
vb-class: '^[ ]*VERSION [0-9]\.[0-9] CLASS'
954986
vb-form: '^[ ]*VERSION [0-9]\.[0-9]{2}'

lib/linguist/languages.yml

+16
Original file line numberDiff line numberDiff line change
@@ -5857,6 +5857,22 @@ Quake:
58575857
ace_mode: text
58585858
tm_scope: source.quake
58595859
language_id: 375265331
5860+
QuickBASIC:
5861+
type: programming
5862+
color: "#008080"
5863+
extensions:
5864+
- ".bas"
5865+
tm_scope: source.QB64
5866+
aliases:
5867+
- qb
5868+
- qbasic
5869+
- qb64
5870+
- classic qbasic
5871+
- classic quickbasic
5872+
ace_mode: text
5873+
codemirror_mode: vb
5874+
codemirror_mime_type: text/x-vb
5875+
language_id: 593107205
58605876
R:
58615877
type: programming
58625878
color: "#198CE7"

samples/BASIC/P180.BAS

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
10 PRINT "PROGRAM FILE 180: EXCEPTION - EVALUATION OF NUMERIC"
2+
20 PRINT " EXPRESSIONS IN THE ON-GOTO STATEMENT."
3+
30 PRINT " ANSI STANDARD 7.5, 10.2, 10.5"
4+
40 PRINT
5+
50 PRINT "SECTION 180.1: EXCEPTION - EVALUATION OF NUMERIC"
6+
60 PRINT " EXPRESSIONS IN THE ON-GOTO STATEMENT."
7+
70 PRINT
8+
80 PRINT "THIS SECTION TESTS THE EFFECT OF USING EXPRESSIONS,"
9+
90 PRINT "WHICH CAUSE NON-FATAL EXCEPTIONS, TO CONTROL THE ON-GOG."
10+
100 PRINT
11+
130 PRINT "TO PASS THIS TEST:"
12+
140 PRINT
13+
150 PRINT " 1) TWO EXCEPTIONS MUST BE REPORTED: DIVISION "
14+
160 PRINT " BY ZERO AND ON-GOTO OUT OF RANGE, AND"
15+
170 PRINT
16+
180 PRINT " 2) EXECUTION MUST TERMINATE."
17+
190 PRINT
18+
193 PRINT " BEGIN TEST."
19+
196 PRINT
20+
200 PRINT "ABOUT TO EXECUTE:"
21+
210 PRINT " ON 1E-33 / 0 GOTO ..."
22+
220 LET A=0
23+
230 LET C=1E-33
24+
240 PRINT
25+
250 ON C/A GOTO 280,300,320
26+
260 LET I=0
27+
270 GOTO 340
28+
280 LET I=1
29+
290 GOTO 340
30+
300 LET I=2
31+
310 GOTO 340
32+
320 LET I=3
33+
330 GOTO 340
34+
340 PRINT
35+
350 PRINT " PATH TAKEN FOR CONTROL-EXPRESSION = ";I
36+
360 PRINT "*** TEST FAILED: EXECUTION DID NOT TERMINATE ***"
37+
370 PRINT
38+
380 PRINT " END TEST."
39+
390 PRINT
40+
400 PRINT "END PROGRAM 180"
41+
410 END

samples/QuickBASIC/FGETRT.BAS

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
'*********** FGetRT.Bas - demonstrates FGetRT and FPutRT in context
2+
3+
'Copyright (c) 1989 Ethan Winer
4+
5+
6+
DEFINT A-Z
7+
DECLARE SUB FClose (Handle)
8+
DECLARE SUB FCreate (FileName$)
9+
DECLARE SUB FGetRT (Handle, Destination AS ANY, RecNumber&, RecLength)
10+
DECLARE SUB FOpen (FileName$, Handle)
11+
DECLARE SUB FPutRT (Handle, Source AS ANY, RecNumber&, RecLength)
12+
DECLARE SUB KillFile (FileName$)
13+
14+
DECLARE FUNCTION DOSError% ()
15+
DECLARE FUNCTION WhichError% ()
16+
DECLARE FUNCTION ErrorMsg$ (ErrNumber)
17+
18+
TYPE FTest 'this is the sample type for the file test
19+
FirstName AS STRING * 15
20+
LastName AS STRING * 15
21+
Company AS STRING * 25
22+
AccountNum AS LONG
23+
WhatNot AS DOUBLE
24+
WhyNot AS SINGLE
25+
END TYPE
26+
DIM TestRec AS FTest 'TestRec will hold the data to/from the file
27+
28+
CLS
29+
F$ = "Random.Tst" 'this will be our test file
30+
RecLength = LEN(TestRec) 'this sets the record length for gets and puts
31+
32+
FCreate F$ 'create the file
33+
IF DOSError% THEN 'see if an error occurred creating the file
34+
PRINT ErrorMsg$(WhichError%)
35+
END
36+
END IF
37+
38+
FOpen F$, Handle 'open the file for QuickPak Pro Binary
39+
40+
FOR Record& = 1 TO 100 'create one hundred records
41+
TestRec.FirstName = "Testing" + STR$(Record&)
42+
TestRec.WhatNot = Record&
43+
FPutRT Handle, TestRec, Record&, RecLength
44+
IF DOSError% THEN 'check for possible full disk
45+
PRINT ErrorMsg$(WhichError%)
46+
END
47+
END IF
48+
NEXT
49+
50+
FOR Record& = 99 TO 1 STEP -10 'read records backwards to prove it all works
51+
FGetRT Handle, TestRec, Record&, RecLength
52+
PRINT "Record"; Record&, TestRec.FirstName; TestRec.WhatNot
53+
NEXT
54+
55+
FClose Handle 'close the file
56+
KillFile F$ 'why clutter up the disk with this nonsense?
57+

samples/QuickBASIC/VLONG.BAS

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
'********** VLong.Bas demos three math functions and eight byte packing
2+
3+
'Copyright (c) 1988 Paul Passarelli
4+
'Copyright (c) 1988 Crescent Software
5+
6+
7+
DEFINT A-Z
8+
DECLARE SUB VLAdd (Addend1#, Addend2#, Sum#, ErrFlag%)
9+
DECLARE SUB VLSub (Minuend#, Subtrahend#, Difference#, ErrFlag%)
10+
DECLARE SUB VLMul (Multiplicand#, Multiplier#, Product#, ErrFlagg%)
11+
DECLARE SUB VLPack (Number$, Value#, ErrFlag%)
12+
DECLARE SUB VLUnpack (Value#, Number$, ErrFlag%)
13+
DECLARE FUNCTION StripZ$ (X$) 'strips leading zeros for the demo
14+
15+
16+
CLS
17+
LINE INPUT "Enter a big number (up to 19 digits): ", Num1$
18+
LINE INPUT " Enter another big number: ", Num2$
19+
PRINT
20+
21+
VLPack Num1$, Num1#, ErrFlag
22+
IF ErrFlag% GOTO ErrHandler
23+
24+
VLPack Num2$, Num2#, ErrFlag
25+
IF ErrFlag% GOTO ErrHandler
26+
27+
VLAdd Num1#, Num2#, Sum#, ErrFlag
28+
UPSum$ = SPACE$(20)
29+
VLUnpack Sum#, UPSum$, ErrFlag%
30+
IF ErrFlag% GOTO ErrHandler
31+
32+
PRINT Num1$; " + "; Num2$; " = "; StripZ$(UPSum$)
33+
34+
VLSub Num1#, Num2#, Sum#, ErrFlag
35+
UPSum$ = SPACE$(20)
36+
VLUnpack Sum#, UPSum$, ErrFlag%
37+
IF ErrFlag% GOTO ErrHandler
38+
39+
PRINT Num1$; " - "; Num2$; " = "; StripZ$(UPSum$)
40+
41+
PRINT
42+
VLPack "2", Num3#, ErrFlag
43+
VLMul Num1#, Num3#, Prod#, ErrFlag
44+
IF ErrFlag% GOTO ErrHandler
45+
VLUnpack Prod#, UPSum$, ErrFlag%
46+
PRINT Num1$; " * 2 = "; StripZ$(UPSum$)
47+
48+
VLPack "3", Num3#, ErrFlag
49+
VLMul Num1#, Num3#, Prod#, ErrFlag
50+
IF ErrFlag% GOTO ErrHandler
51+
VLUnpack Prod#, UPSum$, ErrFlag%
52+
PRINT Num1$; " * 3 = "; StripZ$(UPSum$)
53+
54+
END
55+
56+
ErrHandler:
57+
PRINT "Error - press any key ";
58+
59+
FUNCTION StripZ$ (X$)
60+
FOR X = 2 TO LEN(X$)
61+
IF MID$(X$, X, 1) <> "0" THEN
62+
StripZ$ = LEFT$(X$, 1) + MID$(X$, X)
63+
EXIT FUNCTION
64+
END IF
65+
NEXT
66+
END FUNCTION
67+

samples/QuickBASIC/sponge4.bas

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
' Sponge4: a sponge construction based on RC4
2+
' Ref: https://nullprogram.com/blog/2020/11/17/
3+
' This is free and unencumbered software released into the public domain.
4+
5+
TYPE sponge4
6+
i AS INTEGER
7+
j AS INTEGER
8+
k AS INTEGER
9+
s(0 TO 255) AS INTEGER
10+
END TYPE
11+
12+
DECLARE SUB init (r AS sponge4)
13+
DECLARE SUB absorb (r AS sponge4, b AS INTEGER)
14+
DECLARE SUB absorbstop (r AS sponge4)
15+
DECLARE SUB absorbstr (r AS sponge4, x AS STRING)
16+
17+
DECLARE FUNCTION squeeze% (r AS sponge4)
18+
DECLARE FUNCTION squeeze24& (r AS sponge4)
19+
DECLARE FUNCTION squeezen% (r AS sponge4, n AS INTEGER)
20+
21+
CONST ntickets = 208
22+
CONST nresults = 12
23+
24+
DIM tickets(0 TO ntickets - 1) AS INTEGER
25+
FOR i = 0 TO ntickets - 1
26+
tickets(i) = i
27+
NEXT
28+
29+
DIM sponge AS sponge4
30+
init sponge
31+
absorbstr sponge, DATE$
32+
absorbstr sponge, MKS$(TIMER)
33+
absorbstr sponge, MKI$(ntickets)
34+
35+
CLS
36+
PRINT "Press Esc to finish, any other key for entropy..."
37+
t = TIMER
38+
DO
39+
c& = c& + 1
40+
LOCATE 2, 1
41+
PRINT "cycles ="; c&; "; keys ="; k%
42+
43+
FOR i% = ntickets - 1 TO 1 STEP -1
44+
j% = squeezen%(sponge, i% + 1)
45+
SWAP tickets(i%), tickets(j%)
46+
NEXT
47+
48+
k$ = INKEY$
49+
IF k$ = CHR$(27) THEN
50+
EXIT DO
51+
ELSEIF k$ <> "" THEN
52+
k% = k% + 1
53+
absorbstr sponge, k$
54+
END IF
55+
absorbstr sponge, MKS$(TIMER)
56+
LOOP
57+
58+
FOR i% = 1 TO nresults
59+
PRINT tickets(i%)
60+
NEXT
61+
62+
SUB absorb (r AS sponge4, b AS INTEGER)
63+
r.j = (r.j + r.s(r.i) + b) MOD 256
64+
SWAP r.s(r.i), r.s(r.j)
65+
r.i = (r.i + 1) MOD 256
66+
r.k = (r.k + 1) MOD 256
67+
END SUB
68+
69+
SUB absorbstop (r AS sponge4)
70+
r.j = (r.j + 1) MOD 256
71+
END SUB
72+
73+
SUB absorbstr (r AS sponge4, x AS STRING)
74+
FOR i% = 1 TO LEN(x)
75+
absorb r, ASC(MID$(x, i%))
76+
NEXT
77+
END SUB
78+
79+
SUB init (r AS sponge4)
80+
r.i = 0
81+
r.j = 0
82+
r.k = 0
83+
FOR i% = 0 TO 255
84+
r.s(i%) = i%
85+
NEXT
86+
END SUB
87+
88+
FUNCTION squeeze% (r AS sponge4)
89+
IF r.k > 0 THEN
90+
absorbstop r
91+
DO WHILE r.k > 0
92+
absorb r, r.k
93+
LOOP
94+
END IF
95+
96+
r.j = (r.j + r.i) MOD 256
97+
r.i = (r.i + 1) MOD 256
98+
SWAP r.s(r.i), r.s(r.j)
99+
squeeze% = r.s((r.s(r.i) + r.s(r.j)) MOD 256)
100+
END FUNCTION
101+
102+
FUNCTION squeeze24& (r AS sponge4)
103+
b0& = squeeze%(r)
104+
b1& = squeeze%(r)
105+
b2& = squeeze%(r)
106+
squeeze24& = b2& * &H10000 + b1& * &H100 + b0&
107+
END FUNCTION
108+
109+
FUNCTION squeezen% (r AS sponge4, n AS INTEGER)
110+
DO
111+
x& = squeeze24&(r) - &H1000000 MOD n
112+
LOOP WHILE x& < 0
113+
squeezen% = x& MOD n
114+
END FUNCTION
115+

0 commit comments

Comments
 (0)