///|
fn lex_conf(src : String) -> Result[Array[Tok], NgxError] {
let c = cursor_new(src)
let toks : Array[Tok] = []
let mut depth = 0
while !cursor_eof(c) {
skip_ws(c)
if cursor_eof(c) {
break
}
let line = c.line
let ch = cursor_peek(c)
if ch == 35 {
cursor_bump(c)
let start = c.i
while !cursor_eof(c) && !is_eol(cursor_peek(c)) {
cursor_bump(c)
}
toks.push(tok_comment(slice_text(src, start, c.i), line))
continue
}
if ch == 34 || ch == 39 {
match lex_quoted(c, ch) {
Ok(s) => toks.push(tok_quoted(s, line))
Err(e) => return Err(e)
}
continue
}
if ch == 123 {
depth += 1
cursor_bump(c)
toks.push(tok_lbrace(line))
continue
}
if ch == 125 {
depth -= 1
if depth < 0 {
return Err(Unexpected(line_msg(line, "unexpected }")))
}
cursor_bump(c)
toks.push(tok_rbrace(line))
continue
}
if ch == 59 {
cursor_bump(c)
toks.push(tok_semi(line))
continue
}
match lex_word(c) {
Ok(w) => {
if w == "" {
return Err(Syntax(line_msg(line, "empty token")))
}
toks.push(tok_word(w, line))
}
Err(e) => return Err(e)
}
}
if depth > 0 {
return Err(
Unterminated(line_msg(c.line, "unexpected end of file, expecting }")),
)
}
Ok(toks)
}
///|
fn lex_quoted(c : Cursor, quote : Int) -> Result[String, NgxError] {
let line = c.line
cursor_bump(c)
let mut s = ""
while !cursor_eof(c) {
let ch = cursor_peek(c)
if ch == 92 {
cursor_bump(c)
if cursor_eof(c) {
return Err(
Unterminated(line_msg(line, "escape at end of quoted string")),
)
}
let nxt = cursor_peek(c)
if nxt == quote {
s = s + slice_text(c.src, c.i, c.i + 1)
cursor_bump(c)
} else {
s = s + "\\" + slice_text(c.src, c.i, c.i + 1)
cursor_bump(c)
}
continue
}
if ch == quote {
cursor_bump(c)
return Ok(s)
}
s = s + slice_text(c.src, c.i, c.i + 1)
cursor_bump(c)
}
Err(Unterminated(line_msg(line, "quoted string")))
}
///|
fn lex_word(c : Cursor) -> Result[String, NgxError] {
let start_line = c.line
let mut s = ""
while !cursor_eof(c) {
let ch = cursor_peek(c)
if is_ws(ch) || is_special(ch) {
break
}
if ch == 35 && s == "" {
break
}
if ch == 34 || ch == 39 {
if s == "" {
break
}
s = s + slice_text(c.src, c.i, c.i + 1)
cursor_bump(c)
continue
}
if ch == 92 {
cursor_bump(c)
if cursor_eof(c) {
return Err(Unterminated(line_msg(start_line, "escape at end of word")))
}
s = s + "\\" + slice_text(c.src, c.i, c.i + 1)
cursor_bump(c)
continue
}
if ch == 36 {
s = s + "$"
cursor_bump(c)
if cursor_peek(c) == 123 {
s = s + "{"
cursor_bump(c)
while !cursor_eof(c) {
let inner = cursor_peek(c)
s = s + slice_text(c.src, c.i, c.i + 1)
cursor_bump(c)
if inner == 125 {
break
}
}
}
continue
}
s = s + slice_text(c.src, c.i, c.i + 1)
cursor_bump(c)
}
Ok(s)
}