Easiest way to parse a Lua datastructure in C# / .

2019-02-04 18:10发布

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.

标签: c# parsing lua
5条回答
【Aperson】
2楼-- · 2019-02-04 18:43

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.

查看更多
孤傲高冷的网名
3楼-- · 2019-02-04 18:44

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);
        }
    }
}
查看更多
乱世女痞
4楼-- · 2019-02-04 18:48

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.

查看更多
贪生不怕死
5楼-- · 2019-02-04 18:53

LsonLib can parse Lua data structures, manipulate them and serialize the result back to Lua text. Full disclosure: I am the author. It's pure C# and has no dependencies.

Given:

MY_VAR = { "Foo", ["Bar"] = "Baz" }
ANOTHER = { 235, nil }

Basic usage:

var d = LsonVars.Parse(File.ReadAllText(somefile));

d["MY_VAR"][1].GetString()     // returns "Foo"
d["MY_VAR"]["Bar"].GetString() // returns "Baz"
d["MY_VAR"][2]                 // throws

d["ANOTHER"][1].GetString()    // throws because it's an int
d["ANOTHER"][1].GetInt()       // returns 235
d["ANOTHER"][2]                // returns null
d["ANOTHER"][1].GetStringLenient() // returns "235"

d["ANOTHER"][1] = "blah";      // now { "blah", nil }
d["ANOTHER"].Remove(2);        // now { "blah" }

File.WriteAllText(somefile, LsonVars.ToString(d)); // save changes

(it's actually a fairly straightforward port of a JSON library we use internally, hence it has quite a few features and might have some JSON traces left over)

查看更多
Lonely孤独者°
6楼-- · 2019-02-04 18:54

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.

查看更多
登录 后发表回答