Reputation: 277
I have a text file that should initialize my objects, which are built around a component based model, it is my first time trying to use a data driven approach and i'm not sure if i am heading in the right direction here.
The file i have currently in mind looks like this
EliteGoblin.txt
@Goblin.txt
[general]
hp += 20
strength = 12
description = "A big menacing goblin"
tacticModifier += 1.3
[skills]
fireball
Where the @ symbol says which other files to parse at at that point The names in [] correspond with component classes in the code And below them is how to configure them
For example the hp += 20
would increase the value taken from goblin.txt and increase it by 20 etc.
My question is how i should go about parsing this file, is there some sort of parser built in C#?
Could i change the format of my document to match already defined format that already has support in .net?
How do i go about understanding what type is each value? int/float/string
Does this seem a viable solution at all?
Thanks in advance, Xtapodi.
Upvotes: 4
Views: 976
Reputation: 10046
You might want to check out Sprache, a .net library that can create DSL' s by Autofac creator Nicholas Blumhardt. From the google site:
Sprache is a small library for constructing parsers directly in C# code.
It isn't an "industrial strength" framework - it fits somewhere in between regular expressions and a full-blown toolset like ANTLR.
Usage Unlike most parser-building frameworks, you use Sprache directly from your program code, and don't need to set up any build-time code generation tasks. Sprache itself is a single tiny assembly.
A simple parser might parse a sequence of characters:
// Parse any number of capital 'A's in a row var parseA = Parse.Char('A').AtLeastOnce(); Sprache provides a number of built-in functions that can make bigger parsers from smaller ones, often callable via Linq query comprehensions:
Parser identifier = from leading in Parse.Whitespace.Many() from first in Parse.Letter.Once() from rest in Parse.LetterOrDigit.Many() from trailing in Parse.Whitespace.Many() select new string(first.Concat(rest).ToArray());
var id = identifier.Parse(" abc123 ");
Assert.AreEqual("abc123", id);
The link to the article builds a questionaire that is driven by a simple text file with the following format:
identification "Personal Details"
[
name "Full Name"
department "Department"
]
employment "Current Employer"
[
name "Your Employer"
contact "Contact Number"
#months "Total Months Employed"
]
Upvotes: 2
Reputation: 9136
There is no builtin function to do exactly what you want to do, but you can easily write it.
void ParseLine(string charClass, string line) {
// your code to parse line here...
Console.WriteLine("{0} : {1}", charClass, line);
}
void ParseFile(string fileName) {
string currentClass = "";
using (StringReader sr = new StringReader(fileName)) {
string line = sr.ReadLine();
if (line[0] == '@') {
string embeddedFile = line.Substring(1);
ParseFile(embeddedFile);
}
else if (line[0] == '[') {
currentClass = line.Substring(2, line.Length - 2);
}
else ParseLine(currentClass, line);
}
}
Upvotes: 1
Reputation: 32258
Drop the flat file and pick up XML. Definately look into XML Serialization. You can simply create all of your objects in C# as classes, serialize them into XML, and reload them into your application without having to worry about parsing a flat file out. Because your objects will act as the schema for your XML, you won't have to worry about casting objects and writing a huge parsing routine, .NET will handle it for you. You will save many moons of headache.
For instance, you could rewrite your class to look like this:
public class Monster
{
public GeneralInfo General {get; set;}
public SkillsInfo Skills {get; set;}
}
public class GeneralInfo
{
public int Hp {get; set;}
public string Description {get; set;}
public double TacticModifier {get; set;}
}
public class SkillsInfo
{
public string[] SkillTypes {get; set;}
}
...and your XML would get deserialized to something like...
<Monster>
<General>
<Hp>20</Hp>
<Description>A big menacing goblin</Description>
<TacticModifier>1.3</TacticModifier>
</General>
<SkillTypes>
<SkillType>Fireball</SkillType>
<SkillType>Water</SkillType>
</SkillTypes>
</Monster>
..Some of my class names, hierarchy, etc. may be wrong, as I punched this in real quick, but you get the general gist of how serialization will work.
Upvotes: 12
Reputation: 2863
What you want to do isn't going to be easy. The statistic inheritance in particular.
So, unless you can find some existing code to leverage, I suggest you start with simpler requirements with a view to adding the more involved functionality later and build up the functionality incrementally.
Upvotes: 0