graph_generation_language 0.0.4

Core library for the Graph Generation Language (GGL)
Documentation
// --- Whitespace and Comments (implicitly skipped) ---
WHITESPACE = _{ " " | "\t" | NEWLINE }
COMMENT = _{
    "//" ~ (!NEWLINE ~ ANY)* |
    "/*" ~ (!"*/" ~ ANY)* ~ "*/"
}

// --- Top Level ---
file = { SOI ~ "graph" ~ identifier? ~ "{" ~ statement* ~ "}" ~ EOI }

// --- Statements ---
statement = _{ let_declaration | for_loop | node_declaration | edge_declaration | generate_statement | rule_definition | apply_statement }

// Variable Declaration
let_declaration = { "let" ~ identifier ~ "=" ~ expression ~ ";" }

// For Loop
for_loop = { "for" ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "{" ~ statement* ~ "}" }

// Node and Edge Declarations
node_declaration = { "node" ~ expression ~ (":" ~ expression)? ~ attributes? ~ ";" }
edge_declaration = { "edge" ~ edge_id? ~ expression ~ edge_operator ~ expression ~ attributes? ~ ";" }
edge_id = { expression ~ ":" | ":" }
edge_operator = { "->" | "--" }

// Generators and Rules
generate_statement = { "generate" ~ identifier ~ "{" ~ generator_param* ~ "}" }
generator_param = { identifier ~ ":" ~ expression ~ ";" }

rule_definition = { "rule" ~ identifier ~ "{" ~ lhs ~ rhs ~ "}" }
lhs = { "lhs" ~ "{" ~ pattern_statement* ~ "}" }
rhs = { "rhs" ~ "{" ~ pattern_statement* ~ "}" }
pattern_statement = { node_declaration | edge_declaration }

apply_statement = { "apply" ~ identifier ~ expression ~ "times" ~ ";" }

// --- Components ---
attributes = { "[" ~ (attribute_pair ~ ("," ~ attribute_pair)*)? ~ "]" }
attribute_pair = { identifier ~ "=" ~ expression }

// --- Expressions and Primitives ---
expression = { literal | formatted_string | identifier }

literal = _{ string | float | integer | boolean }
identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
string = { "\"" ~ (ASCII_ALPHANUMERIC | " " | "_" | "-")* ~ "\"" }
integer = @{ "-"? ~ ASCII_DIGIT+ }
float = @{ "-"? ~ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ }
boolean = @{ "true" | "false" }

// Formatted String for dynamic identifiers: "node_{i}"
formatted_string = { "\"" ~ (string_part | var_in_string)* ~ "\"" }
string_part = @{ ( (!("{") ~ !("\"") ~ ANY )+ ) }
var_in_string = { "{" ~ identifier ~ "}" }