I have a file that looks similar to:
background_color{ 104, 184, 104 }
tile_pattern{
id = "1",
ground = "empty",
default_layer = 2,
x = 0,
y = 0,
width = 8,
height = 16,
repeat_mode = "none",
}
tile_pattern{
id = "999",
ground = "traversable",
default_layer = 0,
x = 40,
y = 1000,
width = 8,
height = 8,
}
tile_pattern{
id = "abyss_bridge",
ground = "traversable",
default_layer = 0,
x = 280,
y = 448,
width = 16,
height = 16,
}
tile_pattern{
id = "acid",
ground = "prickles",
default_layer = 0,
x = { 712, 728, 744 },
y = { 384, 384, 384 },
width = 16,
height = 16,
}
tile_pattern{
id = "lava",
ground = "lava",
default_layer = 0,
x = { 696, 696, 696, 696 },
y = { 368, 384, 400, 384 },
width = 16,
height = 16,
}
tile_pattern{
id = "hole_parallax.1-1",
ground = "hole",
default_layer = 0,
x = 312,
y = 224,
width = 16,
height = 16,
scrolling = "self",
}
tile_pattern{
id = "air_duct.1",
ground = "wall",
default_layer = 0,
x = 880,
y = 48,
width = 32,
height = 24,
repeat_mode = "none",
}
border_set{
id = "wall_hole",
inner = true,
pattern_0 = "wall_hole.4-1",
pattern_1 = "wall_hole.1-1",
pattern_2 = "wall_hole.3-1",
pattern_3 = "wall_hole.2-1",
pattern_4 = "wall_hole.corner.2-1",
pattern_5 = "wall_hole.corner.1-1",
pattern_6 = "wall_hole.corner.3-1",
pattern_7 = "wall_hole.corner.4-1",
pattern_8 = "wall_hole.corner_reverse.2-1",
pattern_9 = "wall_hole.corner_reverse.1-1",
pattern_10 = "wall_hole.corner_reverse.3-1",
pattern_11 = "wall_hole.corner_reverse.4-1",
}
border_set{
id = "wall_low-1",
pattern_0 = "wall_low.4-1",
pattern_1 = "wall_low.1-1",
pattern_2 = "wall_low.3-1",
pattern_3 = "wall_low.2-1",
pattern_4 = "wall_low.corner.2-1",
pattern_5 = "wall_low.corner.1-1",
pattern_6 = "wall_low.corner.3-1",
pattern_7 = "wall_low.corner.4-1",
pattern_8 = "wall_low.corner_reverse.2-1b",
pattern_9 = "wall_low.corner_reverse.1-1b",
pattern_10 = "wall_low.corner_reverse.3-1b",
pattern_11 = "wall_low.corner_reverse.4-1b",
}
I have it loaded into a string called datString
. I am trying to match all of the tile_pattern
parts in a single regex expression.
This is what I have so far:
//tilePatterns = new List<TilePatternData>();
//tile_pattern{
//id = "10", (string)
//ground = "empty", (string)
//default_layer = 2, (number)
//(x = 72,) (x = { 712, 728, 744 },) (number or table)(only matching the number, have to add in the table)
//(y = 0,) (y = { 384, 384, 384 },) (number or table)(only matching the number, have to add in the table)
//width = 8,
//height = 16,
//frame_delay(number, optional)(None in test file)
//mirror_loop (boolean, optional)(None in test file)
//scrolling (string, optional)(The Ones in the test file do not have a repeat_mode
//repeat_mode = "none", (string, optional)
//}
parts = new Regex("tile_pattern\\s*{\\s*(id\\s*=\\s*\".+\",\\s*ground\\s*=\\s*\".+\",\\s*default_layer\\s*=\\s*-*\\d+,\\s*x\\s*=\\s*\\d+,\\s*y\\s*=\\s*\\d+,\\s*width\\s*=\\s*\\d+,\\s*height\\s*=\\s*\\d+,\\s*\\w*\\s*=*\\s*\"*\\w*\"*),*\\s*}");
match = parts.Match(datFileString);
Debug.Log("Match " + match.Success + " : " + match.Length);
while (match.Success)
{
// To easily see which ones are getting loaded in
Debug.Log(match.Groups[1]);
//TilePatternData tilePatternData = new TilePatternData();
//tilePatternData.LoadFromDatFile(match.Groups[1].ToString());
//tilePatterns.Add(tilePatternData);
match = match.NextMatch();
}
which returns a match length of 138 (should be 4830) at a glance through my debug log the only ones that seem to be missing are the 32 patterns that have x = { 712, 728, 744 }, I have not figured out how to add this into my capture group yet any help would be appreciated. Also how would I add the 3 optional fields to make sure if the are all there they would get matched?
Need to add to pattern
tile_pattern{
id = "acid",
ground = "prickles",
default_layer = 0,
x = { 712, 728, 744 },
y = { 384, 384, 384 },
width = 16,
height = 16,
}
It appears your file input is from a Solarus Quest Tileset data file. According to the specs :
This syntax of the tileset data file is actually valid Lua.
Rather than using Regex, consider using a Lua parser. NLua seems to be able to do a lot with Lua, although it may be a bit much for just parsing variable list notation.
See also: Easiest way to parse a Lua datastructure in C# /.Net
Your regex is really much more complex than it has to be... now only you and god know what it does - after a week only god will;-)
Try this regex: tile_pattern\{(?:[^{}]|(?R))+\}
Please also make sure to set the correct flags (because I don't know the C# syntax for that)
Also refer to this sample https://regex101.com/r/zqcOBY/1
This also takes care of filtering future new elements in your file without the explicit exclude rules you define in your regex.
I went with a different solution
string[] patternString = Regex.Split(datFileString, "tile_pattern{");
string[] borderString = Regex.Split(patternString[patternString.Length - 1], "border_set{");
patternString[patternString.Length - 1] =
patternString[patternString.Length - 1]
.Remove(patternString[patternString.Length - 1].IndexOf("border_set{", StringComparison.Ordinal));
tilePatterns = new List<TilePatternData>();
foreach (string s in patternString)
{
if (s.Contains("background_color")) continue;
TilePatternData tilePatternData = new TilePatternData();
tilePatternData.LoadFromDatFile(s);
tilePatterns.Add(tilePatternData);
}
Then in TilePatternData class
public void LoadFromDatFile(string datFileString)
{
//tile_pattern{
//id = "10", (string)
//ground = "empty", (string)
//default_layer = 2, (number)
//(x = 72,) (x = { 712, 728, 744 },) (number or table)(only matching the number, have to add in the table)
//(y = 0,) (y = { 384, 384, 384 },) (number or table)(only matching the number, have to add in the table)
//width = 8,
//height = 16,
//frame_delay = 250 (number, optional)
//mirror_loop = true (boolean, optional)
//scrolling (string, optional)(The Ones in the test file do not have a repeat_mode
//repeat_mode = "none", (string, optional)
//}
Regex parts = new Regex("\\s*(\\w+)\\s*=\\s*\"(\\w+)\"");
Match match = parts.Match(datFileString);
//Debug.Log(match.Success + " " + datFileString);
while (match.Success)
{
string pram = match.Groups[1].ToString();
string value = match.Groups[2].ToString();
// Debug.Log(pram + "=" + value);
switch (pram)
{
case "id":
id = value;
break;
case "ground":
Enum.TryParse(value, out ground);
break;
case "scrolling":
Debug.Log(pram + "=" + value);
Enum.TryParse(value, out scrollingEffect);
break;
case "repeat_mode":
Enum.TryParse(value, out repeatMode);
break;
}
match = match.NextMatch();
}
parts = new Regex("\\s*(\\w+)\\s*=\\s*(-*\\d+)");
match = parts.Match(datFileString);
// Debug.Log(match.Success + ": \\s*(\\w+)\\s*=\\s*(-*\\d+)");
while (match.Success)
{
string pram = match.Groups[1].ToString();
string value = match.Groups[2].ToString();
// Debug.Log(pram + "=" + value);
switch (pram)
{
case "x":
int.TryParse(value, out startX);
break;
case "y":
int.TryParse(value, out startY);
break;
case "width":
int.TryParse(value, out width);
break;
case "height":
int.TryParse(value, out height);
break;
case "default_layer":
int.TryParse(value, out defaultLayer);
break;
case "frame_delay":
int.TryParse(value, out height);
break;
}
match = match.NextMatch();
}
// x = { 712, 728, 744 },
parts = new Regex("\\s*([xy])\\s*=\\s*{(\\s*\\d+,*)*\\s*}");
match = parts.Match(datFileString);
Debug.Log(match.Success + ": \\s*([xy])\\s*=\\s*{(\\s*\\d+,*)*\\s*}");
while (match.Success)
{
Debug.Log(match.Groups[2].Captures.Count);
string pram = match.Groups[1].ToString();
string[] value = new string[match.Groups[2].Captures.Count];
// work in progress to extract the table values
}
parts = new Regex("\\s*mirror_loop\\s*=\\s*(\\w+)");
match = parts.Match(datFileString);
//Debug.Log(match.Success + ": \\s*mirror_loop\\s*=\\s*(\\w+)");
if (!match.Success) return;
bool.TryParse(match.Groups[1].ToString(), out mirrorLoop);
Debug.Log(mirrorLoop);
}
There may still be a way to simplify this even further.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.