Skip to content

Parser spec

jD91mZM2 edited this page Nov 24, 2017 · 3 revisions

This is the command parser. Its task is to break a string into an array of "parts", where the first part is the command and the rest is the arguments. All empty parts are discarded.

The parser is handled on the client-side. It's used for commands (prefixed with /) and bot commands (/msg ...). When used on bots the parts are sent to the server using the command_send packet. The server later translates command_send to command_receive, and sends it to the recipient (unless it's not a bot account.)

The parser is simple. Pseudo code:

parts  = []
buffer = ""
escape = false
quote  = false

for c in string
    if escape
        escape = false
        if c == '\\' || c == '"'
            buffer += c
        else
            buffer += '\\' + c // Don't do anything special
    else if c == '\\'
        escape = true
    else if c == '"'
        if buffer == "" || quote
            quote = !quote
        else
            buffer += c // Don't do anything special
    else if c == ' '
        if quote
            buffer += c
        else if buffer != ""
            parts += buffer
            buffer = ""
    else
        buffer += c

if escape
    buffer += '\\' // Don't do anything special
if buffer != ""
    parts += buffer

Here's a few examples on how it should act:

hello world -> ["hello", "world"]
"hello world" -> ["hello world"]
hel"lo wor"ld -> ["hel\"lo", "wor\"ld"]
"hello wor"ld -> ["hello world"]
hello\ world -> ["hello\\", "world"]
hello "" world -> ["hello", "world"]
\h\e\l\l\o world -> ["\\h\\e\\l\\l\\o", "world"]
\"hello world\" -> ["\"hello", "world\""]
\\\"hello world\\\" -> ["\\\"hello", "world\\\""]

Rust implementation of the parser can be seen in client/src/parser.rs

Clone this wiki locally