|
|
View previous topic - View next topic |
Author |
Message |
DeveloperX 202192397
Joined: 04 May 2003 Posts: 1626 Location: Decatur, IL, USA
|
Posted: Thu May 08, 2003 11:41 pm Post subject: is there a better way to do this? |
[quote] |
|
I haven't been able to get any scripting done except like this.
I'm sure there is a better way.
But I don't know it.
Any suggestions?
Code: |
OPEN ScriptFile$ FOR INPUT AS #1
DO WHITE NOT LOF(1)
LINE INPUT #1, Cmd$
Parse Cmd$
LOOP
CLOSE #1
SUB Parse (TheString$)
DIM pError$
IF MID$(TheString,1,1) = ";" THEN ' comment
EXIT SUB
ELSEIF MID$(TheString,1,1) = "" THEN ' ignore whitespace
EXIT SUB
ELSEIF MID$(TheString,1,1) = " " THEN ' ignore whitespace
EXIT SUB
ELSEIF MID$(TheString,1,1) = "@" THEN ' command found
PRINT "found command"
EXIT SUB
ELSEIF MID$(TheString,1,1) = "%" THEN ' variable found
PRINT "found variable declaration"
EXIT SUB
ELSE
pError$ = "invalid command" : GOTO ParseError
END IF
ParseError:
COLOR 4 : PRINT pError$ : COLOR 7
END SUB
|
I left out the code for the actual commands..
but anyway, _________________ Principal Software Architect
Rambling Indie Games, LLC
See my professional portfolio
|
|
Back to top |
|
|
janus Mage
Joined: 29 Jun 2002 Posts: 464 Location: Issaquah, WA
|
Posted: Fri May 09, 2003 6:22 am Post subject: |
[quote] |
|
Yes, create a state machine that parses your code character by character and sends the data into subroutines based on type.
|
|
Back to top |
|
|
DrunkenCoder Demon Hunter
Joined: 29 May 2002 Posts: 559
|
Posted: Fri May 09, 2003 1:58 pm Post subject: |
[quote] |
|
write a recursive decent parser... just google it.. _________________ If there's life after death there is no death, if there's no death we never live. | ENTP
|
|
Back to top |
|
|
DeveloperX 202192397
Joined: 04 May 2003 Posts: 1626 Location: Decatur, IL, USA
|
|
Back to top |
|
|
Barret7sc Lowly Slime
Joined: 22 Apr 2003 Posts: 1
|
Posted: Sun May 11, 2003 12:40 am Post subject: hrm.. |
[quote] |
|
The easiest way to do it is through recursive subroutines. Basically, a sub can call itself it if needs to.
I first parse out my script into a string array, getting rid of comments and whitespace and tabs (trim$() is your friend), then I parse through it.
First I search for variable declarations, so I can find out what variables are used by the script. Afterwards, I loop through the string array and look for keywords, sending them off to the apropriate subs. (left$() and right$() are your friends as well, much faster than mid$())
Variables are a bit trickier. If the parser finds a word that is not a number or a built-in function, it sees if it is a variable, and then creates a new string that contains the value of the variable instead of the variable name.
Writing a robust scripting language is diffucult, and requires lots of recursion, perhaps you should brush up on recursion and other tricks before you worry about scripting.
|
|
Back to top |
|
|
akOOma Wandering Minstrel
Joined: 20 Jun 2002 Posts: 113 Location: Germany
|
Posted: Sun May 11, 2003 6:12 pm Post subject: |
[quote] |
|
Codin' a script engine is always a hard job...some months ago i coded one where you can do things like that:
Code: |
if xpos=3 and ypos=5 then
if hp>50 or mp>50 then
let x=5
end if
end if
|
at the moment I'm just planning to write a bytecode scripting thingy where you compile the script code to get the whole thing faster _________________ Keep on codin'
-----------------
-----------------
Just another post to increase my rank...
|
|
Back to top |
|
|
Matt2j Guest
|
Posted: Sun May 11, 2003 7:00 pm Post subject: The best script engines are the simplest... |
[quote] |
|
Most people spend ages planning and writting a really powerful script interpreter for their game, which is ultra efficiant and logical and powerful and like a real programming language. What they forget is that we use scripts because we need something at a higher level then a programming language. The best script engines should only have about 11 commands, and using these commands you should be able to controll the whole engine. simplify, throw something together in a couple of minuits then concentrate on the game, its the best way.
an excerpt from the twisted opinions of Mathew Lloyd Jones
|
|
Back to top |
|
|
Bjorn Demon Hunter
Joined: 29 May 2002 Posts: 1425 Location: Germany
|
Posted: Sun May 11, 2003 9:02 pm Post subject: |
[quote] |
|
That depends, of course, on what the goal of the engine writer is. The more flexible an engine should be the more responsibility is moved into the scripts. For Sauerkraut, a lot was happening in the engine (like character animation handling, converstions, fights, keeping track of progress). In our more recent game, using a modified and more flexible engine, all of the just mentioned examples are now totally handled by scripts. And I'm glad that I've modified the engine like this, as making changes is soo much easier now and I hardly have to recompile the engine anymore.
Of course, you are still right about not spending ages on your own powerfull parser. You should probably do that just shortly, for learning purposes. Next, grab one of the many exdendible extensions languages available from the net. Most of them will be both a lot faster and a lot easier to use than your own system.
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: Tue Jun 24, 2003 11:12 pm Post subject: Although not entirely useful to the language you are using.. |
[quote] |
|
(heh: Old thread, I guess, but this might prove useful.)
You should look up flex and bison at GNU. The documentation for both the lexer generator (flex) and the parser generator (bison) discusses some of the internal components of the programs -- you can even get the source code for each, although it isn't in BASIC.
Anyway, as Janus suggested, you might want to consider writing a state-machine and a parser. A state-machine -- as usually built on computers -- searches a given text for regular expression matches. (You can find out a little more about state-machines here, or you can google state-machine, DFA, NFA, regular expressions, etc.) The fundamental concept is that you search for the longest match on a set of characters against a set of patterns. Each pattern is based upon a regular expression representation of a match: e.g. let us assume you wanted a scripting language that had if statements analogous to C/C++ if statements. You would construct a pattern along the lines of "if" -- what we can all the if lexeme -- and return from the lexer function a token value associated with this lexeme.
So, the general structure for a lexer would be to read in each character of text, add the character to a word of characters (representing the current match), compare this word against a list of patterns (which can include wildcards and other fancy things), and if a match is found, return a lexeme token for it. Obviously, the mechanism is much more complicated than this (as you need to account for look-aheads, and what not), but you get the idea.
The parser function would then call the lexer to get the next lexeme token in the text you are parsing. As token's are guaranteed to have distinct values (with some limitations), you string together a set of token values that represent a rule in what is known as context-free grammar. (Fundamentally, CFGs are the basis of parsers, while REs are the basis of lexers.) A CFG is composed of a 4-tuple of values: a set of non-terminal symbols, a set of terminal symbols, a start symbol (which is from the set of non-terminals), and a set of production rules that take a given non-terminal to either another non-terminal or to a terminal.
Great! So, how does this help? Using a CFG, you can represent a finite (but relatively large) set of languages in a manner that a computer can interpret.
Lexers and parsers allow you to construct a syntatic tree representation of the file that was passed to them -- each node in this tree represents a chunk of code in the script file text. How is this useful? Well, the children of a given node are the set of valid lexemes of a language that compose a valid statement or expression of that language. The syntatic tree can then be decorated with semantic information (as appropriate); this allows you to look for variables, assign types to those variables, make sure that expressions used in statements have the appropriate type, etc.
Now, lexers and parsers are most usually used for compilers -- that is, you'll find some form of a lexer and parser at the core of any compiler. However, they could be used just as well for a scripting language. Assuming that you somehow store the syntactic/semantic tree that a parser can generate, you could then recursively traverse this tree to generate a series of function calls in your engine. (I.E. rather than write to an output file a list of byte-commands that approximate the code the engine was given, you make a series of calls inside your engine that do the exact same thing.) Or, you could "compile" your scripts to a lower-level language that would be easier for your engine to operate off of.
The problem, of course, is that BASIC (I assume you are using QB, from your source) is not an OO language; it would be difficult to create a syntactic tree in BASIC, as there is no concept of a class in BASIC. (Well, that's not entirely the problem -- it is more that BASIC lacks pointers and a sense of polymorphism.) However, a few years ago Tenshi was attempting to construct OO constructs in BASIC using a funky memory addressing system.
Of course, there exists the problem of writing relatively fast, efficient lexer and parser functions. Were you writing this in C++, I would point you directly to Flex and Bison (linked above), as they generate C/C++ code that can be directly linked into your own code. You might consider googling lexers and parsers in BASIC, and see what comes up.
Or, you could just use a short if...else if...else structure, as you are doing :P _________________ "...LeoDraco is a pompus git..." -- Mandrake
|
|
Back to top |
|
|
twinsen Stephen Hawking
Joined: 21 May 2003 Posts: 242 Location: Melbourne, Australia
|
Posted: Wed Jun 25, 2003 3:02 am Post subject: |
[quote] |
|
Bjorn, I'm surprised you didn't do a plug for LUA :) _________________ Lovely girls & great prices always available at CLUB 859, 859 Glenhunly Road, Caulfield, Open 10am till late 7 days. +61-3-9523-8555. (Sorry, it was in front of me in the newspaper, I just had to use it as a signature!)
|
|
Back to top |
|
|
Bjorn Demon Hunter
Joined: 29 May 2002 Posts: 1425 Location: Germany
|
Posted: Wed Jun 25, 2003 10:26 am Post subject: |
[quote] |
|
Heh, that's because I am in no way confident that Lua would be the 'best' choise as a scripting language. More specifically, I'm looking into ICI which seems to handle OO programming much nicer.
About flex and bison, I have used scangen and parsgen to construct a scanner-parser combination for a custom language once. It requires more work as a programmer but a nice thing is that you can design the language yourself. I guess it's a matter of taste.
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: Wed Jun 25, 2003 4:45 pm Post subject: |
[quote] |
|
The one caveat about scanner/parser generators like flex and bison that I forgot to mention (for the absolutely curious), is that they are intended to be as flexible as possible, so that they can work for as many languages as possible. Unfortunately, this can translate into a few thousand lines of code genereated by each utility; so, if code size is a retraint, it would probably be better to go with something a bit more specialized.
(For instance: this last quarter at my college, I was required to write the unix wc program in one of my classes. The c++ implementation was a little over 300 lines, while a python implementation I wrote later in the quarter was about half that. As an introduction to flex in a compilers course I was taking concurrently, we were asked to construct wc (a very basic version) using flex; while the script we fed into flex was only about 30 lines long, the generated c code was a little over 1300 lines long.)
~Leo _________________ "...LeoDraco is a pompus git..." -- Mandrake
|
|
Back to top |
|
|
|
Page 1 of 1 |
All times are GMT
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|