net/httpd/conf
The reader of the web server config: blocks, settings and values in Salam block syntax, with positions for errors.
import net.httpd.conf
This package reads text written in the block style that net/httpd uses for its config, and gives back a tree. It knows nothing about web servers: it only recognises the shapes, and net/httpd decides which names are valid. You can use it for settings files of your own that look like Salam.
There are two shapes. A setting is a name, an equals sign and one or more values on the same line: max connections = 100. A block is a name, optional strings, a colon, its contents and end: location "/api/": cache = 1h end. A name may be several words (error page), values are strings in double quotes (with \n, \t, \" and \\), strings in backticks (taken as written, so a regular expression needs no doubling of backslashes), numbers with an optional unit such as 64mb or 30d, and plain words such as tls. Comments are // to the end of the line, or /* ... */.
Everything lives in a Doc, a list of nodes that point at each other by number: node 0 is the root, Find and ChildAt move down, and the fields of a node hold its words, labels, values and children. Free the document with Free when you are done with it.
The things people get wrong:
- A value list ends at the end of the line, at
end, or where the next setting starts on the same line, soa = 1 b = 2is two settings. A bare word at the end of a list is read as a value, which is whylisten = 443 tlsworks. - A parse stops at the first error, and
okis then false. The error has the line and the column, andErrorTextputs them in front of the message the way compilers do. - Addresses and anything with a colon in it need quotes:
listen = "127.0.0.1:8080". Without them the colon would read as the start of a block. - A node's
wordshold its name, soNamejoins them with single spaces. Block labels, such as the path of a location, are inlabels, not in the name.
Types
Value
struct Value| Name | Type | Description |
|---|---|---|
kind | int = 0 | VAL_WORD, VAL_STR or VAL_NUM. |
text | str = "" | The value as text; strings without their quotes and with escapes resolved. |
line | int = 0 | The line, counting from 1. |
col | int = 0 | The column, counting from 1. |
import net.httpd.conf
func main:
text := `
server:
site:
listen = 80 tls
names = "a.test www.a.test"
location "/api/": cache = 1h end
end
end
`
d := conf.Parse(text)
println d.ok, d.nodes.len(), conf.Count(d, conf.Root())
server := conf.Find(d, conf.Root(), "server")
site := conf.Find(d, server, "site")
println conf.Name(d, site), conf.Count(d, site), d.nodes.get(site).block
listen := conf.Find(d, site, "listen")
v := d.nodes.get(listen).values.get(0)
println v.text, v.kind == conf.VAL_NUM, v.line, v.col
w := d.nodes.get(listen).values.get(1)
println w.text, w.kind == conf.VAL_WORD, conf.ValueText(d, conf.Find(d, site, "names"), 0)
names := d.nodes.get(conf.Find(d, site, "names")).values.get(0)
println names.kind == conf.VAL_STR
loc := conf.ChildAt(d, site, 2)
n := d.nodes.get(loc)
println conf.Name(d, loc), n.labels.get(0), n.block, n.words.len(), n.children.len(), n.line, n.col
conf.Free(d)
endNode
struct Node| Name | Type | Description |
|---|---|---|
block | bool = false | True for a block, false for a setting. |
words | Vector | The words of the name, such as error and page. |
labels | Vector | The strings written between the name and the colon of a block. |
values | Vector | The values of a setting. |
children | Vector | The numbers of the nodes inside a block. |
line | int = 0 | The line where it starts. |
col | int = 0 | The column where it starts. |
The example for this item is shown with the ones above: net-httpd-conf-Parse.salam
Doc
struct Doc| Name | Type | Description |
|---|---|---|
nodes | Vector | Every node; node 0 is the root. |
ok | bool = true | True when the text parsed without an error. |
error | str = "" | The message of the first error, empty when there is none. |
line | int = 0 | The line of the error. |
col | int = 0 | The column of the error. |
The example for this item is shown with the ones above: net-httpd-conf-Parse.salam
Constants and variables
VAL_WORD
const VAL_WORD: i32 = 0tls or auto.The example for this item is shown with the ones above: net-httpd-conf-Parse.salam
VAL_STR
const VAL_STR: i32 = 1The example for this item is shown with the ones above: net-httpd-conf-Parse.salam
VAL_NUM
const VAL_NUM: i32 = 28080 or 30d; the text keeps the unit.The example for this item is shown with the ones above: net-httpd-conf-Parse.salam
Functions
Parse
func Parse(text: str): Docok before using it.The example for this item is shown with the ones above: net-httpd-conf-Parse.salam
Free
func Free(d &: Doc)The example for this item is shown with the ones above: net-httpd-conf-Parse.salam
ErrorText
func ErrorText(d: Doc, file: str): strfile:line:column: message, or an empty string when the document is valid. The first argument is the name to show for the file.import net.httpd.conf
func show(text: str):
d := conf.Parse(text)
println d.ok, conf.ErrorText(d, "web.salam"), d.error, d.line, d.col
conf.Free(d)
end
func main:
show("server:\n site:\n")
show("server:\nend\nend\n")
show("listen = \n")
show("names = \"open\n")
show("listen 80\n")
show("a = 1 # no\n")
show("ok = 1\n")
endName
func Name(d: Doc, node: int): strThe example for this item is shown with the ones above: net-httpd-conf-Parse.salam
Root
func Root(): intThe example for this item is shown with the ones above: net-httpd-conf-Parse.salam
Count
func Count(d: Doc, node: int): intThe example for this item is shown with the ones above: net-httpd-conf-Parse.salam
ChildAt
func ChildAt(d: Doc, node: int, i: int): intThe example for this item is shown with the ones above: net-httpd-conf-Parse.salam
Find
func Find(d: Doc, node: int, name: str): intThe example for this item is shown with the ones above: net-httpd-conf-Parse.salam
ValueText
func ValueText(d: Doc, node: int, i: int): strThe example for this item is shown with the ones above: net-httpd-conf-Parse.salam