basic muddle parser
This commit is contained in:
parent
0a4762f758
commit
8aa2726b4b
103
mudparse.js
Normal file
103
mudparse.js
Normal file
|
@ -0,0 +1,103 @@
|
|||
// parse beta.mud
|
||||
export const removeComments = (text) => {
|
||||
let newText = []
|
||||
let i = 0
|
||||
while (i < text.length) {
|
||||
let iLim = text.indexOf("/*", i)
|
||||
let iNext
|
||||
if (iLim < 0) {
|
||||
iLim = text.length
|
||||
iNext = iLim
|
||||
} else {
|
||||
const iCommentEnd = text.indexOf("*/", iLim + 2)
|
||||
if (iCommentEnd > 0) {
|
||||
iNext = iCommentEnd + 2
|
||||
} else {
|
||||
throw new Error(`Comment started at ${iLim} has no end`)
|
||||
}
|
||||
}
|
||||
newText.push(text.slice(i, iLim))
|
||||
i = iNext
|
||||
}
|
||||
return newText.join("")
|
||||
}
|
||||
|
||||
const splitLine = (line) => {
|
||||
const tokens = line.trim().split(/\s+/)
|
||||
return (tokens.length == 1 && tokens[0] == '') ? [] : tokens
|
||||
}
|
||||
|
||||
const reString = /^"(.*)"$/
|
||||
const parseResourceLine = (line, dict) => {
|
||||
const tokens = splitLine(line)
|
||||
if (tokens.length == 1 && tokens[0] == "}") {
|
||||
return false
|
||||
} else if (tokens.length == 0) {
|
||||
return true
|
||||
} else if (tokens.length == 1 || !tokens[0].endsWith(":") || !tokens[1].match(reString)) {
|
||||
throw new Error(`Expected 'key: "value"' but got '${line}'`)
|
||||
} else {
|
||||
const key = tokens[0].slice(0, -1)
|
||||
const value = { filename: tokens[1].match(reString)[1] }
|
||||
if (tokens.length > 2) {
|
||||
value.arguments = tokens.slice(2).map((v) => parseInt(v)) // would be nice to know what these mean
|
||||
}
|
||||
dict[key] = value
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
const parseClassLine = (line, cls) => {
|
||||
const tokens = splitLine(line)
|
||||
if (tokens.length == 1 && tokens[0] == "}") {
|
||||
return false
|
||||
} else if (tokens.length == 0) {
|
||||
return true
|
||||
} else if (tokens.length == 1) {
|
||||
throw new Error(`Expected "resourcetype reference" but got ${line}`)
|
||||
} else {
|
||||
const resourceType = tokens[0]
|
||||
if (!cls[resourceType]) {
|
||||
cls[resourceType] = []
|
||||
}
|
||||
const array = cls[resourceType]
|
||||
if (resourceType == "byte" && tokens.length == 2) {
|
||||
array.push(parseInt(tokens[1]))
|
||||
} else if (tokens.length == 2) {
|
||||
array.push({ id: tokens[1] })
|
||||
} else {
|
||||
array.push({ id: tokens[1], arguments: tokens.slice(2).map((v) => parseInt(v)) })
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
const parseStructure = (lines, iline, struct, parser) => {
|
||||
while (parser(lines[iline], struct)) {
|
||||
iline ++
|
||||
}
|
||||
return iline
|
||||
}
|
||||
|
||||
const parseMud = (lines) => {
|
||||
const mud = {"class": {}}
|
||||
for (let iline = 0; iline < lines.length; iline ++) {
|
||||
const tokens = splitLine(lines[iline])
|
||||
if (tokens.length == 2 && tokens[1] == "{") {
|
||||
const mapping = {}
|
||||
iline = parseStructure(lines, iline + 1, mapping, parseResourceLine)
|
||||
mud[tokens[0]] = mapping
|
||||
} else if (tokens.length == 4 && tokens[0] == "class" && tokens[3] == "{") {
|
||||
const cls = { id: parseInt(tokens[2]) }
|
||||
iline = parseStructure(lines, iline + 1, cls, parseClassLine)
|
||||
mud.class[tokens[1]] = cls
|
||||
} else if (tokens.length != 0) {
|
||||
throw new Error(`Expected "resourcetype {" but got ${lines[iline]}`)
|
||||
}
|
||||
}
|
||||
return mud
|
||||
}
|
||||
|
||||
export const parse = (text) => {
|
||||
return parseMud(removeComments(text).split("\n"))
|
||||
}
|
44
objects.html
Normal file
44
objects.html
Normal file
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Inhabitor - The Habitat Inspector</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin:40px auto;
|
||||
line-height:1.6;
|
||||
font-size:18px;
|
||||
color:#444;
|
||||
padding:0 10px
|
||||
}
|
||||
h1,h2,h3 {
|
||||
line-height:1.2
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Inhabitor - The Habitat Inspector</h1>
|
||||
<div id="muddle">
|
||||
<h3>Muddle database</h3>
|
||||
</div>
|
||||
<a href="javascript:showErrors();">Show errors</a>
|
||||
<div id="errors" style="display: none"></div>
|
||||
|
||||
<script type="module">
|
||||
import { parse, removeComments } from "./mudparse.js"
|
||||
import { textNode } from "./show.js"
|
||||
|
||||
window.showErrors = () => {
|
||||
document.getElementById('errors').style.display = 'block'
|
||||
}
|
||||
const onload = async () => {
|
||||
const response = await fetch("beta.mud", { cache: "no-cache" })
|
||||
const text = await response.text()
|
||||
const container = document.getElementById("muddle")
|
||||
const mud = parse(text)
|
||||
container.appendChild(textNode(JSON.stringify(mud, null, 2), "pre"))
|
||||
}
|
||||
onload()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue