duckyscript 0.1.0

parser for duckyscript
Documentation
WHITESPACE = _{ " " | "\t" }

script = { 
    SOI
    ~(statement*)
    ~ EOI
}


identifier_chars = _{ 
    'a'..'z' | 
    'A'..'Z' | 
    '0'..'9' |
    "_"
}

identifier = { identifier_chars+ }

button_variable = _{
    "$_BUTTON_ENABLED" |
    "$_BUTTON_USER_DEFINED" |
    "$_BUTTON_PUSH_RECEIVED" |
    "$_BUTTON_TIMEOUT"
}

led_variable = _{
    "$_SYSTEM_LEDS_ENABLED" |
    "$_STORAGE_LEDS_ENABLED" |
    "$_LED_CONTINUOUS_SHOW_STORAGE_ACTIVITY" |
    "$_INJECTING_LEDS_ENABLED" |
    "$_EXFIL_LEDS_ENABLED" |
    "$_LED_SHOW_CAPS" |
    "$_LED_SHOW_NUM" |
    "$_LED_SHOW_SCROLL"
}

internal_variable = {
    button_variable |
    led_variable
}

led_on = { "LED_ON" }
led_off = { "LED_OFF" }
led_r = { "LED_R" }
led_g = { "LED_G" }

wait_for_button_press = { "WAIT_FOR_BUTTON_PRESS" }
disable_button = { "DISABLE_BUTTON" }
enable_button = { "ENABLE_BUTTON" }

delay = { "DELAY"~(lit_int|variable) }
stop_payload = { "STOP_PAYLOAD" }

builtin_fn = {
    led_on | 
    led_off |
    led_r |
    led_g |
    wait_for_button_press |
    disable_button |
    enable_button |
    delay |
    stop_payload
}

function_def = {
    "FUNCTION" ~ identifier
    ~ statement* 
    ~ "END_FUNCTION"
}

button_def = { 
    ("BUTTON_DEF" ~ NEWLINE)
    ~ statement*
    ~ ("END_BUTTON")
}

script_variable = @{
    "$" ~ identifier
}

variable = _{ internal_variable | script_variable }

lit_bool = {
    "TRUE" |
    "FALSE"
}

lit_int = {
    ('0'..'9')+
}
lit = _{
    lit_bool |
    lit_int
}

conditional = {
    "+" |
    ">" |
    "<" |
    "==" 
}

value = _{ 
    lit |
    variable
}

expr_conditional = { value ~ conditional ~ value }

expr_value = { value }
expr = _{
    expr_value |
    expr_conditional
}

variable_def = { "VAR" ~ variable ~ "=" ~ expr }

else_if = {
    ("ELSE IF" ~ "(" ~ expr ~ ")" ~ "THEN" ~ NEWLINE)
    ~statement* 
    ~"END_IF"
}

while_block = { 
    ("WHILE" ~ expr ~ NEWLINE)
    ~(statement*)
    ~"END_WHILE"
}

function = _{
    builtin_fn
}

empty_line = _{ NEWLINE }

statement_body = _{
    empty_line |
    button_def |
    variable_def |
    function_def |
    while_block |
    function 
}

statement = _{ (NEWLINE*) ~ (statement_body ~ NEWLINE) }