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
}