Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Gramática

La definición de la gramática actual de minipas.

// Minipas grammar.pest 1.8.0
//
WHITESPACE = _{ (" " | "\t" | NEWLINE | comment)+ }
NEWLINE    = _{ "\n" | "\r\n" }

comment_single = { "//" ~ (!NEWLINE ~ ANY)* }
comment_braces = { "{" ~ (!"}" ~ ANY)* ~ "}" }

comment        =  { comment_single | comment_braces }
string_literal = @{
    ("\"" ~ ("\\\"" | "\\\\" | (!"\"" ~ ANY))* ~ "\"")
  | ("'" ~ ("\\'" | "\\\\" | (!"'" ~ ANY))* ~ "'")
}

boolean_literal = { "True" | "False" | "TRUE" | "FALSE" }

// Tokens
keyword_var       = { "var" }
keyword_program   = { "program" }
keyword_integer   = { "integer" }
keyword_real      = { "real" }
keyword_string    = { "string" }
keyword_boolean   = { "boolean" }
keyword_byte      = { "byte" }
keyword_writeln   = { "writeln" }
keyword_if        = { "if" }
keyword_then      = { "then" }
keyword_else      = { "else" }
keyword_const     = { "const" }
keyword_and       = { "and" }
keyword_array     = { "array" }
keyword_for       = { "for" }
keyword_while     = { "while" }
keyword_repeat     = { "repeat" }
keyword_until     = { "until" }
keyword_function  = { "function" }
keyword_procedure = { "procedure" }
keyword_nil       = { "nil" }
// for loop
keyword_to     = { "to" }
keyword_do     = { "do" }
keyword_downto = { "downto" }
// break/continue in loops
keyword_break    = { "break" }
keyword_continue = { "continue" }
break_stmt    = { keyword_break ~ semicolon }
continue_stmt = { keyword_continue ~ semicolon }
// abbreviated operations
assign_add = { "+=" }
assign_sub = { "-=" }
assign_mul = { "*=" }
assign_div = { "/=" }
assign_mod = { "%=" }

ident = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }

number = @{ "-"? ~ ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT+)? }
real   = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ }

assign_op = { ":=" }
add_op    = { "+" }
sub_op    = { "-" }
mul_op    = { "*" }
div_op    = { "/" }
idiv_op   = { "div" }
mod_op    = { "%" | "mod" }
cmp_op    = { ">=" | "<=" | "<>" | ">" | "<" | "=" }

semicolon = { ";" }
comma     = { "," }
colon     = { ":" }
lparen    = { "(" }
rparen    = { ")" }

expr    = { sum ~ (cmp_op ~ sum)? }
sum     = { product ~ ((add_op | sub_op) ~ product)* }

method_chain = { factor ~ ("." ~ ident ~ lparen ~ (expr_list)? ~ rparen)* }
product = { method_chain ~ ((mul_op | div_op | idiv_op |mod_op) ~ method_chain)* }
//product = { factor ~ ((mul_op | div_op | idiv_op |mod_op) ~ factor)* }

//
// llamadas a función/ procedimiento
func_call = { ident ~ lparen ~ (expr_list)? ~ rparen }
factor = { number | string_literal | boolean_literal | func_call | ident | keyword_nil | "(" ~ expr ~ ")" }
// Aquí el `-` delante del número se reconoce como operador unario.
// Esto permite -1 y también expresiones como -(2+3).
//
// factor = { ("-"? ~ number) | string_literal | boolean_literal | func_call | ident | "(" ~ expr ~ ")" }

string    = @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }
expr_item =  { expr | string_literal }

expr_list = { expr_item ~ (comma ~ expr_item)* }
expr_stmt = { expr ~ semicolon }

// Sentencias
block = { "begin" ~ stmt* ~ "end" }
//stmt  = { comment* ~ (if_stmt | for_stmt | while_stmt | repeat_stmt | block | assignment | expr_stmt | return_stmt) }
stmt  = { comment* ~ (if_stmt | for_stmt | while_stmt | repeat_stmt | break_stmt | continue_stmt | block | assignment | expr_stmt | return_stmt) }

if_stmt = { keyword_if ~ expr ~ keyword_then ~ stmt ~ (keyword_else ~ stmt)? }

var_decl = { ident ~ ("," ~ ident)* ~ ":" ~ (keyword_integer | keyword_real | keyword_string | keyword_boolean | keyword_byte) ~ ";" }

//assignment = { ident ~ assign_op ~ expr ~ semicolon }
assignment = {ident ~ (assign_op | assign_add | assign_sub | assign_mul | assign_div|assign_mod) ~ expr ~ semicolon}

var_section = { ("var" ~ var_decl+)+ }

// procedures
proc_decl = {
    keyword_procedure ~ ident ~ lparen ~ (param_list)? ~ rparen ~ semicolon ~ var_section? ~ block ~ semicolon?
}

// functions
func_decl = {
    keyword_function ~ ident ~ lparen ~ (param_list)? ~ rparen ~ colon ~ (keyword_integer | keyword_real | keyword_string | keyword_boolean | keyword_byte) ~ semicolon ~ (var_section)? ~ block ~ semicolon?
}

// return
return_stmt = { "return" ~ expr ~ semicolon }

// FOR LOOP
for_stmt = {
    keyword_for ~ ident ~ assign_op ~ expr // ~ ("to" | "downto") ~ expr
  ~ (keyword_to | keyword_downto) ~ expr ~ keyword_do ~ stmt
}

// WHILE LOOP
while_stmt   =  {
    keyword_while ~ expr_boolean ~ keyword_do ~ stmt
}
expr_boolean = _{ expr }

// REPEAT LOOP
repeat_stmt = {
    keyword_repeat ~ stmt+ ~ keyword_until ~ expr ~ semicolon
}

param_list   = { param ~ (semicolon ~ param)* }
param        = { ident ~ colon ~ type_keyword }
type_keyword = { keyword_integer | keyword_real | keyword_string | keyword_boolean | keyword_byte }

//
program = {
    SOI ~ comment* ~ "program" ~ ident ~ semicolon ~ var_section? ~ (proc_decl | func_decl)* ~ block ~ "." ~ EOI
}