RPGDXThe center of Indie-RPG gaming
Not logged in. [log in] [register]
 
 
Post new topic Reply to topic  
View previous topic - View next topic  
Author Message
DeveloperX
202192397


Joined: 04 May 2003
Posts: 1626
Location: Decatur, IL, USA

PostPosted: 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

PostPosted: 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

PostPosted: 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

PostPosted: Fri May 09, 2003 8:12 pm    Post subject: [quote]

I do not understand.

please don't be so brief.
_________________
Principal Software Architect
Rambling Indie Games, LLC

See my professional portfolio
Back to top  
Barret7sc
Lowly Slime


Joined: 22 Apr 2003
Posts: 1

PostPosted: 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

PostPosted: 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





PostPosted: 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

PostPosted: 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

PostPosted: 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

PostPosted: 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

PostPosted: 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

PostPosted: 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  
Post new topic Reply to topic Page 1 of 1 All times are GMT
 



Display posts from previous:   
Jump to:  
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