basic muddle parser

main
Jeremy Penner 2024-01-03 16:27:34 -05:00
parent 0a4762f758
commit 8aa2726b4b
3 changed files with 3261 additions and 0 deletions

3114
beta.mud Normal file

File diff suppressed because it is too large Load Diff

103
mudparse.js Normal file
View 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
View 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>