[.net] Parsing a scripting language in C#..

Started by
14 comments, last by BradSnobar 14 years, 3 months ago
I'm working on my own custom 2D Game engine, and I implemented Lua. Although LUA is very easy to work with in .NET, my problem is I can't really port it very well to other systems (Xbox, Windows Mobile), that I know of.. Not sure that's even possible with the .NET version? So I was thinking, how hard would it be to develop my own SIMPLE scripting language for my engine? It doesn't have to do ANYTHING special whats so ever. All it has to do is maybe perform loops and if statements. I don't need to declare variables, since it's for NPCs. Most COMPLEX scripts would be already implemented (like AI). Eventually, of course, it'd grow to be more complex but for now it needs to be simple. I'm thinking a simple script would be:

if (player.name == "hello") {
   player.setName = "hello!";
}

if (player.Flags["flagname"].value == "key1253") {
    someNpcName.OpenDoor = true;
    ShowMessage("You unlocked the door.");
}



That is literally all it would need, is the ability to set/get variables, if statements, loop statements (something like do until blah == blah), etc. Truthfully, I'm not 100% crazy over lua syntax. I like my example. My problem is, I'm not 100% sure HOW to approach this (haven't tried). It would also need to support nested if statements, But I'm sure it would work as long as I designed it right. I don't need code, just perhaps good articles that would get me going. I was thinking of using Regular Expressions, and parsing it like that which would work easily, but I'm not 100% sure it'll be fast enough (especially on slower single core systems). [Edited by - tmack on December 26, 2009 9:11:55 PM]
Advertisement
I'm no language expert. I don't know the proper way to "write a language" as I've never read a book on the topic, though I ran into a similar situation while writing my engine. Here are the basic steps I came up with while writing my language.
(You'll have to google these for more info, its such a huge topic)

Not needing to deal with variables makes your job much easier... writing a stack is not that bad, but garbage collection... that gave me some headaches.

1) Tokenize the code

Basically you need to go through the code and convert it into tokens. Tokens consist of identifiers, operators, constants, ect... Once it is tokenizer however, it will be much easier to work with.

2) Build an abstract syntax tree (AST)

This is a tree of operators and operands, hard to explain, just look at this picture for an example of PHP in an AST: http://www.phpcompiler.org/doc/latest/_images/ifx5.jpg

3) Two options:
a) Iterate through the AST and execute as you go
b) Iterate through the AST and output byte code instead of executing it

At first I did (a) but found that in game it ran a bit slow, so I wrote a very simple set of bytecode instructions. Bytecode is very cool because after outputing it, you can go through and look for patterns, and do things like remove dead code, replace complex code, ect... (this is called optimization)
There's a C# compiler in .NET; I forget where it is (they like to move it) and it might not be available for the mobile versions, and you need elevated privileges to use it, but that's an option.

There's also IronPython and IronRuby (amongst others) which are interpretable into MSIL.

And I'd also be a little surprised if there wasn't some project somewhere to provide LUA access on the systems you want.

... all that said, you'd probably want to use Expression Trees to do your code generation and if you use a pre-made parsing library or are familiar with a good parser generator that talks C# it shouldn't take that long at all.
C# compiles to CIL bytecode... You can just use C# as your scripting language, and either embed Mono into your application, or write a CIL bytecode interpreter, or if your game is already C#, then you're already good to go.

This way you don't need to mess with parsing, compiling, optimizing, etc etc etc... If you aren't wanting to dedicate a lot of time to it, I would avoid trying to design a language.
I can use any .Net langage (C#, VB.Net, Python.Net...) as script in my framework really easily (thanks to System.CodeDom.Compiler namespace). Using Reflection too is pure happines !

You can have a look at my source here.
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]
Creating a (scripting) language is always exciting when you start. If you don't have a deadline and you absolutely want to roll your own scripting language, do so; along the way you'll be almost forced to improve your coding habits using patterns in order to avoid repetitions and smelly code. It's not a bad thing.

However, I've been bitten many times by the allure of compilers etc and I strongly suggest you to think about the problem in a different way: you say you won't be able to port LuaInterface (I assume it's LuaInterface), and you're right. But how high is this in your priority list?

The bottom line is: abstract the "scripting" part of your game engine and use Lua for the moment. It'll be much easier to swap out implementations later on.

public interface IScripting {  void Bind(Action action, string name);  void RunString(string chunk);  object this[string path] { get; set; }  }IScripting script = new LuaInterface();script.RunString("a = 10");var value = script["myobject.myvalue"];


I know this does not answer your original question; but it can help you save some time now, and focus on less time-consuming features of your engine :)

Have fun all the same, coderchris already outlined a realistic workflow.
Rainweaver Framework (working title)

IronLua (looking for a DLR expert)



OK, I have seen this posted many times. Yeah, LUA is great but it isn't your code. Here is my opinion on this....

Write your own code.

Common example
yadayada = param 1, param 2, param 3

Write a routine called SplitParams.
Your routine passes back
yadayada as the command
param 1 as parameter 1
param 2, param 3 etc...

Section off your data such as...
[sectionname]
Include a bool that says this is a section name, act accordingly.

Once you do that porting it to any language will be a breeze. I've done this for almost 10 years now and it has saved me from ever having to use any external library to read my scripts plus I can update it any time I want (try doing that to the LUA library).

Just my 2 cents worth

******************************************************************************************
Youtube Channel

Quote:Original post by LancerSolurus
Yeah, LUA is great but it isn't your code.


That is... the entire point?

The instinct to not use something because you can't 'control' it or 'know what's going on' is something pretty much all programmers face, and need to overcome. Writing your own ini-like config just provides a lot of code to write and debug for no real gain. If you want some arbitrary formatted text to use with many languages, XML or even the ini format itself has parsers prebuilt in many languages.

Libraries are your friend. Writing code you don't need to write is just a waste of time and distracts you from actually getting the game done.
I'm thinking LUA and any other scripting languages would be "too" much for me. Most of the AI would be hard coded, in C#, in the engine. All I need to do is to "call" the functions. There would be 100's of functions that you could call to do different things (move camera, move characters, etc) (movecam newx newy, movechar charRef newx newy, etc)

I'm worried, I go and implement LUA. I decide I want to port it to XBOX 360 - all I need to do is convert my SlimDX code to XNA, and I'm basically there. If my code has LUA, I'm pretty much screwed. I have to rewrite all my AI scripts...

And no, I have no deadline. And it would be really cool to have my own scripting language, and heck, it could turn into something 2-3 years from now.

Where can I read more about using C# as my scripting language? Couldn't I compile my scripts then? That would be the ideal way, but then again if it doesn't support it in XBOX/WM platforms then I'm beat. But wouldn't that open up a whole new world of exploits?

Thanks for all the great information =)
This may be stupid or not even work, but what about using &#106avascript and adding the functions I need? &#106avascript is light weight, and fairly fast..

This topic is closed to new replies.

Advertisement