2009-05-19 15 views
11

¿Alguien sabe de una manera fácil de analizar una estructura de datos Lua en C# o con cualquier biblioteca .Net? Esto sería similar a la decodificación JSON, a excepción de Lua en lugar de javascript.La forma más fácil de analizar una estructura de datos Lua en C#/.Net

En este punto, parece que tendré que escribir el mío, pero esperando que haya algo por ahí.

+7

Por favor, nunca escriba LUA como todos los capitales: http://www.lua.org/about.html#name –

Respuesta

5

Lo que dijo Alexander. El laboratorio es el hogar de Lua, después de todo.

Específicamente, LuaInterface puede permitir que un intérprete de Lua se integre en su aplicación para que pueda usar el propio analizador de Lua para leer los datos. Esto es análogo a incrustar Lua en una aplicación C/C++ para utilizarlo como un archivo de configuración/archivo de datos. El proyecto LuaCLR también puede ser fructífero en algún momento, pero puede que no sea tan maduro.

+0

vea mi respuesta para ver el código de ejemplo de cómo usé LuaInterface –

+0

ahh LuaInterface parece ser solo x86. :( –

9

Gracias a los dos, he encontrado lo que estaba buscando para el uso de LuaInterface

Aquí está una estructura de datos en Lua quería leer ("c: \ sample.lua"):

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

He aquí algunos ejemplos de código de lectura que Lua estructura de datos utilizando 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); 
} 

y esto es lo que escribe código de ejemplo en la consola:

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

Para descubrir cómo usar la biblioteca abrí el LuaInterface.dll en Reflector y google'd las funciones miembro.

1

No he mirado en éste, sin embargo, el ahorro de un enlace por ahora: http://www.youpvp.com/blog/post/LuaParse-C-parser-for-World-of-Warcraft-saved-variable-files.aspx

LuaInterface, lamentablemente, sólo se envasan para funcionar en sistemas x86, así que fue a buscar alternativas. Aquí está la fuente:

/* 
* 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

LsonLib puede analizar las estructuras de datos de Lua, manipularlos y serializar el resultado de nuevo al texto Lua. Divulgación completa: soy el autor. Es C# puro y no tiene dependencias.

Dado:

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

Uso básico:

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 

(en realidad es un puerto bastante sencillo de una biblioteca JSON utilizamos internamente, por lo tanto tiene un buen número de características y podría tener algún JSON rastros sobrantes)

Cuestiones relacionadas