tags:

views:

1441

answers:

4

Anyone know of an easy way to parse a Lua datastructure in C# or with any .Net library? This would be similar to JSON decoding, except for Lua instead of javascript.

At this point it looks like I'll need to write my own, but hoping there's something already out there.

+1  A: 

You may (or may not) find what you need among Lablua projects.

In any case, do not hesitate to ask your question on Lua mailing list.

Alexander Gladysh
+3  A: 

What Alexander said. The lab is the home of Lua, after all.

Specifically, LuaInterface can allow a Lua interpreter to be embedded in your application so that you can use Lua's own parser to read the data. This is analogous to embedding Lua in a C/C++ application for use as a config/datafile language. The LuaCLR project might be fruitful at some point as well, but it may not be quite as mature.

RBerteig
see my answer for sample code on how I used LuaInterface
Frank Schwieterman
ahh LuaInterface seems to be x86 only. :(
Frank Schwieterman
+4  A: 

Thanks to both of you, I found what I was looking for using LuaInterface

Here's a datastructure in Lua I wanted to read ("c:\sample.lua"):

TestValues = {
    NumbericOneMillionth = 1e-006,
    NumbericOnehalf = 0.5,
    NumbericOne = 1,
    AString = "a string"
}

Here's some sample code reading that Lua datastructure using LuaInterface:

Lua lua = new Lua();

var result = lua.DoFile("C:\\sample.lua");

foreach (DictionaryEntry member in lua.GetTable("TestValues")) {
    Console.WriteLine("({0}) {1} = {2}", 
        member.Value.GetType().ToString(), 
        member.Key, 
        member.Value);
}

And here's what that sample code writes to the console:

(System.String) AString = a string
(System.Double) NumbericOneMillionth = 1E-06
(System.Double) NumbericOnehalf = 0.5
(System.Double) NumbericOne = 1

To figure out how to use the library I opened up the LuaInterface.dll in Reflector and google'd the member functions.

Frank Schwieterman
+1  A: 

I haven't looked at this one yet, saving a link for now: http://www.youpvp.com/blog/post/LuaParse-C-parser-for-World-of-Warcraft-saved-variable-files.aspx

LuaInterface is unfortunately only packaged to run on x86, so I was looking at alternatives. Here's the source:

/*
 * Denis Bekman 2009
 * www.youpvp.com/blog
 --
 * This code is licensed under a Creative Commons Attribution 3.0 United States License.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using System.Net;

namespace YouPVP
{
    public class LuaParse
    {
        List<string> toks = new List<string>();

        public string Id { get; set; }
        public LuaObject Val { get; set; }
        public void Parse(string s)
        {
            string qs = string.Format("({0}[^{0}]*{0})", "\"");
            string[] z = Regex.Split(s, qs + @"|(=)|(,)|(\[)|(\])|(\{)|(\})|(--[^\n\r]*)");

            foreach (string tok in z)
            {
                if (tok.Trim().Length != 0 && !tok.StartsWith("--"))
                {
                    toks.Add(tok.Trim());
                }
            }

            Assign();
        }
        protected void Assign()
        {
            if (!IsLiteral)
                throw new Exception("expect identifier");
            Id = GetToken();
            if (!IsToken("="))
                throw new Exception("expect '='");
            NextToken();
            Val = RVal();
        }
        protected LuaObject RVal()
        {
            if (IsToken("{"))
                return LuaObject();
            else if (IsString)
                return GetString();
            else if (IsNumber)
                return GetNumber();
            else if (IsFloat)
                return GetFloat();
            else
                throw new Exception("expecting '{', a string or a number");
        }
        protected LuaObject LuaObject()
        {
            Dictionary<string, LuaObject> table = new Dictionary<string, LuaObject>();
            NextToken();
            while (!IsToken("}"))
            {
                if (IsToken("["))
                {
                    NextToken();
                    string name = GetString();
                    if (!IsToken("]"))
                        throw new Exception("expecting ']'");
                    NextToken();
                    if (!IsToken("="))
                        throw new Exception("expecting '='");
                    NextToken();
                    table.Add(name, RVal());
                }
                else
                {
                    table.Add(table.Count.ToString(), RVal());//array
                }
                if (!IsToken(","))
                    throw new Exception("expecting ','");
                NextToken();
            }
            NextToken();
            return table;
        }

        protected bool IsLiteral
        {
            get
            {
                return Regex.IsMatch(toks[0], "^[a-zA-Z]+[0-9a-zA-Z_]*");
            }
        }
        protected bool IsString
        {
            get
            {
                return Regex.IsMatch(toks[0], "^\"([^\"]*)\"");
            }
        }
        protected bool IsNumber
        {
            get
            {
                return Regex.IsMatch(toks[0], @"^\d+");
            }
        }
        protected bool IsFloat
        {
            get
            {
                return Regex.IsMatch(toks[0], @"^\d*\.\d+");
            }
        }
        protected string GetToken()
        {
            string v = toks[0];
            toks.RemoveAt(0);
            return v;
        }
        protected LuaObject GetString()
        {
            Match m = Regex.Match(toks[0], "^\"([^\"]*)\"");
            string v = m.Groups[1].Captures[0].Value;
            toks.RemoveAt(0);
            return v;
        }
        protected LuaObject GetNumber()
        {
            int v = Convert.ToInt32(toks[0]);
            toks.RemoveAt(0);
            return v;
        }
        protected LuaObject GetFloat()
        {
            double v = Convert.ToDouble(toks[0]);
            toks.RemoveAt(0);
            return v;
        }
        protected void NextToken()
        {
            toks.RemoveAt(0);
        }
        protected bool IsToken(string s)
        {
            return toks[0] == s;
        }
    }



    public class LuaObject : System.Collections.IEnumerable
    {
        private object luaobj;

        public LuaObject(object o)
        {
            luaobj = o;
        }
        public System.Collections.IEnumerator GetEnumerator()
        {
            Dictionary<string, LuaObject> dic = luaobj as Dictionary<string, LuaObject>;
            return dic.GetEnumerator();
        }
        public LuaObject this[int ix]
        {
            get
            {
                Dictionary<string, LuaObject> dic = luaobj as Dictionary<string, LuaObject>;
                try
                {
                    return dic[ix.ToString()];
                }
                catch (KeyNotFoundException)
                {
                    return null;
                }
            }
        }
        public LuaObject this[string index]
        {
            get
            {
                Dictionary<string, LuaObject> dic = luaobj as Dictionary<string, LuaObject>;
                try
                {
                    return dic[index];
                }
                catch (KeyNotFoundException)
                {
                    return null;
                }
            }
        }
        public static implicit operator string(LuaObject m)
        {
            return m.luaobj as string;
        }
        public static implicit operator int(LuaObject m)
        {
            return (m.luaobj as int? ?? 0);
        }
        public static implicit operator LuaObject(string s)
        {
            return new LuaObject(s);
        }
        public static implicit operator LuaObject(int i)
        {
            return new LuaObject(i);
        }
        public static implicit operator LuaObject(double d)
        {
            return new LuaObject(d);
        }
        public static implicit operator LuaObject(Dictionary<string, LuaObject> dic)
        {
            return new LuaObject(dic);
        }
    }
}
Frank Schwieterman