Home | Reviews | GUIpedia | Forum | Fun500
pharoah | Ideas about scripting language syntaxI have been looking for a way to create a minimalist, easy-to-parse scripting language, in the spirit of QML. I ran across a language I'd heard about called FORTH, which uses a stack to organize everything, allowing the interpreter/compiler to parse individual, self-contained words as commands rather than dealing with syntax.
It sounds amazingly easy to implement, but I have a hard time explaining how it works so take a look here:
http://www.softsynth.com/pforth/pf_tut.html
Basically it means that, say, adding 2 and 2 would look like this
2 | 2008-12-25 | 1:51 PM |
rCX | Re:Ideas about scripting language syntaxI heard of this language. It's so simple that interpreters for it have been written in ASM. | 2008-12-25 | 2:26 PM |
Todd | Re:Ideas about scripting language syntaxSounds pretty neat. I intend on developing a programming language and parser which fits around an interpreter to do these types of things. | 2008-12-25 | 2:36 PM |
pharoah | Re:Ideas about scripting language syntaxYes it's extremely simple, yet unlike basic ASM I can easily understand how FORTH works. I am thinking of creating a soft of FORTH/BASIC/PHP hybrid where the stack is a bunch of untyped string variables. | 2008-12-25 | 2:56 PM |
Todd | Re:Ideas about scripting language syntaxCool. Let us know how it goes. BTW, I created a small forum for PHP and other programs and projects: http://devboards.xetaspace.net/ . I've got a few people I know on it but we're just trying to get some fresh members. If you know anyone else, please let them know. | 2008-12-25 | 3:56 PM |
SonicBrit | Re:Ideas about scripting language syntaxWow that was an interesting read, I knew forth used the stack, but didn't realise to what extent. I could see how it would be easy to translate into asm. | 2008-12-25 | 6:35 PM |
pharoah | Re:Ideas about scripting language syntaxHere's something quick I whipped up in Freebasic today, it interprets a few forthlike commands. It isn't actually forth, there are a few differences:
[hide][code]
declare function nextword as string
dim shared code as string
redim shared stack(0) as string
type calltype
all as string
code as string
end type
redim shared callstack(1) as calltype
dim word as string
dim as integer x, y, z, i, c
dim as string dummy, s
screen 12
'code = "' First number? ' print drop input ' Second number? ' print drop input * rot print ' * ' print drop rot swap print swap ' = ' print drop print"
'code = "' Enter password: ' print drop input ' gui ' = rot drop drop if ' Password correct ' print drop then not if ' Password incorrect ' print drop then"
callstack(ubound(callstack)-1).code = "1 do dup 1 plot drop drop ++ 100 = if exit then drop drop loop"
do
word = nextword
select case word
case "do"
dummy = ""
do
s = nextword
dummy = dummy + s + " "
if s = "loop" then
exit do
end if
loop
dummy = left(dummy, len(dummy)-1)
callstack(ubound(callstack)).all = dummy
callstack(ubound(callstack)).code = dummy
redim preserve callstack(ubound(callstack)+1)
case "loop"
callstack(ubound(callstack)-1).code = callstack(ubound(callstack)-1).all
case "exit"
redim preserve callstack(ubound(callstack)-1)
callstack(ubound(callstack)).code = ""
callstack(ubound(callstack)).code = ""
case "++"
x = val(stack(ubound(stack)-1))
stack(ubound(stack)) = str(x+1)
redim preserve stack(ubound(stack)+1)
case "--"
x = val(stack(ubound(stack)-1))
stack(ubound(stack)) = str(x-1)
redim preserve stack(ubound(stack)+1)
case "plot"
x = val(stack(ubound(stack)-3))
y = val(stack(ubound(stack)-2))
c = val(stack(ubound(stack)-1))
pset (x, y), c
case "and"
dummy = stack(ubound(stack)-2)
s = stack(ubound(stack)-1)
if dummy "0" and s "0" then
stack(ubound(stack)) = "1"
redim preserve stack(ubound(stack)+1)
else
stack(ubound(stack)) = "0"
redim preserve stack(ubound(stack)+1)
end if
case "or"
dummy = stack(ubound(stack)-2)
s = stack(ubound(stack)-1)
if dummy "0" or s "0" then
stack(ubound(stack)) = "1"
redim preserve stack(ubound(stack)+1)
else
stack(ubound(stack)) = "0"
redim preserve stack(ubound(stack)+1)
end if
case "not"
s = stack(ubound(stack)-1)
if s = "0" then
stack(ubound(stack)) = "1"
redim preserve stack(ubound(stack)+1)
else
stack(ubound(stack)) = "0"
redim preserve stack(ubound(stack)+1)
end if
case "if"
if stack(ubound(stack)-1) = "0" then
do
loop until nextword = "then"
end if
case "then"
case "="
dummy = stack(ubound(stack)-2)
s = stack(ubound(stack)-1)
if dummy = s then
stack(ubound(stack)) = "1"
redim preserve stack(ubound(stack)+1)
else
stack(ubound(stack)) = "0"
redim preserve stack(ubound(stack)+1)
end if
case "!="
dummy = stack(ubound(stack)-2)
s = stack(ubound(stack)-1)
if dummy s then
stack(ubound(stack)) = "1"
redim preserve stack(ubound(stack)+1)
else
stack(ubound(stack)) = "0"
redim preserve stack(ubound(stack)+1)
end if
case ">"
x = val(stack(ubound(stack)-2))
y = val(stack(ubound(stack)-1))
if x > y then
stack(ubound(stack)) = "1"
redim preserve stack(ubound(stack)+1)
else
stack(ubound(stack)) = "0"
redim preserve stack(ubound(stack)+1)
end if
case " "; stack(i)
next
sleep
function nextword as string
dim code as string
code = callstack(ubound(callstack)-1).code
if instr(code," ") = 0 and len(code) > 0 then
nextword = code
code = ""
elseif len(code) = 0 then
nextword = ""
code = ""
else
nextword = left(code, instr(code, " ")-1)
code = mid(code, instr(code, " ")+1)
end if
callstack(ubound(callstack)-1).code = code
end function
[/code][/hide]
You can see it also lacks capabilities like loops and defining new words, but it's just to give people an idea of what I am talking about. Less than 200 lines, can do a fair number of very simple tasks, and completely unoptimized. Might be a good approach for a UniScript langauge.
EDIT: I added loops and a basic PSET function | 2008-12-26 | 12:42 AM |
pharoah | Re:Ideas about scripting language syntaxOkay, I've written a basic FORTHlike interpreter in less than 100 lines. More complicated statements can be constructed from the basic ones, as you can see in the comments.
[code]declare sub push(topush as string)
declare function pop as string
dim shared vars(256) as string
type calltype
all as string
code as string
end type
redim shared calls(1) as calltype, words(0) as string, stack(0) as string
dim char as string, dummy as string, one as string, x as integer
open "code.txt" for input as #1
line input #1, calls(0).all
calls(0).code = calls(0).all
close 1
do
if calls(ubound(calls)-1).code = "" and ubound(calls) = 1 then exit do
if calls(ubound(calls)-1).code = "" then redim preserve calls(ubound(calls)-1)
char = left(calls(ubound(calls)-1).code, 1)
calls(ubound(calls)-1).code = mid(calls(ubound(calls)-1).code,2)
select case char
case "'"
dummy = ""
x = 1
do
one = left(calls(ubound(calls)-1).code, 1)
calls(ubound(calls)-1).code = mid(calls(ubound(calls)-1).code,2)
if one = "'" then x = x + 1
if one = chr$(34) then x = x - 1
if x = 0 then exit do else dummy = dummy + one
loop
push dummy
case "&"
dummy = pop
push pop+dummy
case "-"
dummy = pop
push str(val(pop)-val(dummy))
case "*"
dummy = pop
push str(val(pop)*val(dummy))
case "/"
dummy = pop
push str(val(pop)/val(dummy))
case ">"
dummy = pop
if val(pop) > val(dummy) then push "1" else push "0"
case "="
if pop = pop then push "1" else push "0"
case "n"
if pop = "0" then push "1" else push "0"
case "p"
push stack(ubound(stack)-1-val(pop))
case "c"
push chr$(val(pop))
case "a"
push str(asc(pop))
case "b"
x = val(pop)
dummy = pop
push mid$(dummy, x, 1)
case "l"
if pop "0" then calls(ubound(calls)-1).code = calls(ubound(calls)-1).all
case "i"
if pop "0" then
calls(ubound(calls)).all = pop
calls(ubound(calls)).code = calls(ubound(calls)).all
redim preserve calls(ubound(calls)+1)
end if
case ":"
dummy = pop
words(ubound(words)) = left(pop, 1) + dummy
redim preserve words(ubound(words)+1)
case "s"
x=val(pop)
vars(x) = pop
case "f"
push vars(val(pop))
case "$"
print pop;
case "?"
push input(1)
case else
for x = 0 to ubound(words)-1
if char = left(words(x),1) then
calls(ubound(calls)).all = mid(words(x),2)
calls(ubound(calls)).code = calls(ubound(calls)).all
redim preserve calls(ubound(calls)+1)
end if
next
end select
loop
sleep
sub push(topush as string)
stack(ubound(stack)) = topush
redim preserve stack(ubound(stack)+1)
end sub
function pop as string
pop = stack(ubound(stack)-1)
redim preserve stack(ubound(stack)-1)
end function
' ' " '"
'& &
'- -
'* *
'/ /
'> >
'= =
'not n
'pick p
'char c
'asc a
'byte b
'loop l
'if i
'define :
'store s
'fetch f
'print $
'inkey ?
'Constructed Words
'=================
'First Level
'-----------
'+ (PLUS) '+"''-1"*-":
' a, b -> a+b
'D (DROP) 'D'1"s'"'1"s":
' x ->
'C (COPY) 'C"''1"p":
' x -> x, x
'S (SWAP) 'S"''1"s'2"s'1"f'2"f":
' a, b -> b, a
'R (ROT) 'R"''1"s'2"s'3"s'1"f'2"f'3"f":
' a, b, c -> c, b, a
'Second Level
'------------
'I (INPUT) 'I"''"'?CC'1"s$&'1"f'13"c=nl"'1"i'10"c$":
' -> String
' Requires: C
'Sample Programs
'===============
'Greet the user: 'C"''1"p":'I"''"'?CC'1"s$&'1"f'13"c=nl"'1"i'10"c$":'What is your name? "$I'Hello, "$$
[/code] | 2009-01-03 | 1:33 PM |
| Re:Ideas about scripting language syntaxHere's a language that's kinda like FORTH:
http://nerds-central.blogspot.com/2008/07/vspl-very-simple-programming-language.html | 2009-01-04 | 4:06 AM |
Other
2021 Brandon Cornell