mesecode/mesecode.py
2014-10-12 19:23:20 +01:00

176 lines
4.7 KiB
Python

import re, sys
# How many spaces in a tab.
# -1 disables support for spaces as tabs (recommended)
# There are usually 4 spaces in a tab
SPACES_PER_TAB = -1
class Node():
def __init__(self, desc):
self.desc = desc
self.name = desc.lower().replace(" ", "_")
self.groups = []
self.last_prop = None
self.type = "node"
self.eaten = None
self.drops = []
def build(self, project):
name = self.name
if name.find(":") == -1:
name = project.modname + ":" + name
retval = "minetest.register_node(\"" + name + "\", {\n"
retval += "\tdescription = \"" + self.desc + "\",\n"
if self.eaten is not None:
retval += "\ton_use = minetest.item_eat(" + self.eaten + "),\n"
is_ground_content = False
if len(self.groups) > 0:
retval += "\tgroups = {"
for group in self.groups:
if group == "ground":
is_ground_content = True
continue
if group.find("=") == -1:
group += " = 1"
retval += group + ", "
retval += "}\n"
if len(self.drops) == 1:
retval += "\tdrop = \"" + project.getItemName(self.drops[0]) + "\",\n"
elif len(self.drops) > 1:
retval += "\tdrop = {\n"
for dropped in self.drops:
retval += "\t\t\"" + project.getItemName(dropped) + "\",\n"
retval += "\t},"
if is_ground_content:
retval += "\tis_ground_content = true,\n"
retval += "})\n"
return retval
class Script:
def __init__(self, filename):
self.filename = filename
self.type = "script"
def build(self, project):
return "dofile(minetest.get_modpath(\"" + project.modname + "\") .. \"" + self.filename + "\")\n"
class ParseError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
def throwParseError(msg):
print("\033[91mParse Error: " + msg + "\033[0m")
sys.exit(-1)
def parse_list(the_list, line):
if line == "":
return
arr = line.split(",")
for item in arr:
item = item.strip()
if item != "":
the_list.append(item)
class Project:
def getItemName(self, desc):
for item in self.objects:
if item.type == "node" and item.desc.lower() == desc.lower():
if item.name.find(":") == -1:
return self.modname + ":" + item.name
else:
return item.name.strip(":")
return ""
def __init__(self, filename):
file = open(filename, "r")
self.modname = None
self.objects = []
lineno = 0
for line in file.readlines():
lineno += 1
# Remove comments
if line.find("--") != -1:
line = line[:line.find("--")]
if line.strip() == "":
continue
# Find indentation level
if SPACES_PER_TAB != -1:
line = line.replace(SPACES_PER_TAB * " ", "\t")
indented = 0
m = re.search('([\\t]+)', line)
if m:
indented = len(m.group(1))
# Strip redundant symbols
line = line.strip()
self.processLine(line, indented, lineno)
def processLine(self, line, indented, lineno):
if indented > 2 or indented < 0:
throwParseError("Too many levels of indentation at " + str(lineno))
elif indented == 0:
#
# Top Level Statements
#
if line.startswith("mod "):
if self.modname is not None:
throwParseError("Mod name redefined on line " + str(lineno))
self.modname = line[4:].strip()
elif line.startswith("node "):
self.objects.append(Node(line[5:].strip()))
elif line.startswith("script "):
self.objects.append(Script(line[7:].strip()))
else:
throwParseError("Unknown definition on line " + str(lineno))
else:
if len(self.objects) == 0:
throwParseError("Too many levels of indentation at " + str(lineno))
curobj = self.objects[len(self.objects) - 1]
#
# Properties
#
if indented == 1:
curobj.last_prop = None
if line.startswith("is"):
parse_list(curobj.groups, line[2:].strip())
curobj.last_prop = curobj.groups
elif line.startswith("name "):
curobj.name = line[5:].strip()
elif line.startswith("eaten "):
curobj.eaten = line[6:].strip()
elif curobj.type == "node":
if line.startswith("drops "):
parse_list(curobj.drops, line[6:].strip())
curobj.last_prop = curobj.drops
else:
throwParseError("Unknown property in '" + curobj.type + "/" + curobj.name + "' on line " + str(lineno))
else:
throwParseError("Unknown property in '" + curobj.type + "/" + curobj.name + "' on line " + str(lineno))
#
# Lists
#
elif indented == 2:
curprop = curobj.last_prop
if curprop is None:
throwParseError("Too many levels of indentation at " + str(lineno))
curprop.append(line)
def write(self, directory):
print("-- Mod namespace: " + self.modname)
print("-- Generated using the Minetest Readable Modding Format\n")
for item in self.objects:
print(item.build(self))
Project("test.mese").write("test")