Add WIP Pest grammar

This commit is contained in:
mars 2022-03-25 00:35:36 -06:00
parent 1eed7487ca
commit b47137d27d
3 changed files with 98 additions and 0 deletions

View File

@ -8,4 +8,6 @@ license = "GPL-3.0-or-later"
[dependencies]
console = "0.15.0"
logos = "0.12.0"
pest = "2"
pest_derive = "2"
strum = { version="0.24", features=["derive"] }

View File

@ -1,6 +1,9 @@
// Copyright (c) 2022 Marceline Cramer
// SPDX-License-Identifier: GPL-3.0-or-later
#[macro_use]
extern crate pest_derive;
use console::Style;
pub mod lexer;
@ -41,6 +44,12 @@ impl ColorTheme {
}
}
mod pest_parser {
#[derive(Parser)]
#[grammar = "sprite.pest"]
pub struct SpriteParser;
}
#[cfg(test)]
mod tests {
use super::*;
@ -58,6 +67,18 @@ mod tests {
}
}
#[test]
fn parse_pest() {
use pest::Parser;
use pest_parser::{Rule, SpriteParser};
let source = include_str!("test/clock.fae");
let parsed = SpriteParser::parse(Rule::module, source);
match parsed {
Ok(ok) => println!("{:#?}", ok),
Err(err) => panic!("{}", err),
}
}
// TODO use spans to color-code instead of raw tokens, to show original whitespace
/*#[test]
fn color_file() {

75
src/sprite.pest Normal file
View File

@ -0,0 +1,75 @@
// Copyright (c) 2022 Marceline Cramer
// SPDX-License-Identifier: GPL-3.0-or-later
module = { SOI ~ top_level* ~ EOI }
top_level = _{ iface_def | struct_def | impl_block | impl_fn }
struct_def = { "struct" ~ identifier ~ member_defs }
iface_def = { "interface" ~ identifier ~ iface_defs }
impl_block = { "impl" ~ identifier ~ identifier? ~ "{" ~ impl_fn* ~ "}" }
impl_fn = { fn_def ~ branch }
member_defs = _{ "{" ~ "}" | "{" ~ member_def ~ ("," ~ member_def)* ~ ","? ~ "}" }
iface_defs = _{ "{" ~ (fn_def ~ ";")* ~ "}" }
fn_args = _{ "(" ~ ")" | "(" ~ fn_arg ~ ("," ~ fn_arg)* ~ ")" }
member_def = { identifier ~ identifier }
fn_def = { "mut"? ~ "fn" ~ identifier ~ fn_args ~ identifier? }
fn_arg = { identifier ~ identifier? }
branch = _{ "{" ~ stmt* ~ expr? ~ "}" }
stmt = _{ let_stmt | if_stmt | while_stmt | expr ~ ";" }
let_stmt = { "let" ~ "mut"? ~ identifier ~ "=" ~ expr ~ ";" }
if_stmt = { "if" ~ expr ~ branch ~ ("else" ~ branch)? }
while_stmt = { "while" ~ expr ~ branch }
expr = { term ~ (binary_op ~ term)* }
term = { unary_op? ~ val ~ call_args? ~ field* }
call_args = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" }
field = { "." ~ identifier ~ call_args? }
val = _{ field | if_expr | identifier | literal | "(" ~ expr ~ ")" }
literal = _{ string | float | int }
if_expr = { "if" ~ expr ~ branch ~ "else" ~ branch }
unary_op = _{ op_bool_not | op_bit_not }
binary_op = _{
op_eq | // match early to prevent shadowing
op_add | op_sub | op_mul | op_div | op_assign |
op_bool_or | op_bool_and |
op_bit_or | op_bit_and | op_bit_xor |
op_less_eq | op_less | op_greater_eq | op_greater | op_neq
}
// arithmetic operators
op_add = { "+" }
op_sub = { "-" }
op_mul = { "*" }
op_div = { "/" }
op_assign = { "=" }
// boolean operators
op_bool_or = { "or" }
op_bool_and = { "and" }
op_bool_not = { "not" }
// bitwise operators
op_bit_or = { "|" }
op_bit_and = { "&" }
op_bit_xor = { "^" }
op_bit_not = { "~" }
// comparison operators
op_less = { "<" }
op_less_eq = { "<=" }
op_greater = { ">" }
op_greater_eq = { ">=" }
op_eq = { "==" }
op_neq = { "!=" }
string = @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }
bool = { "true" | "false" }
int = @{ ("+" | "-")? ~ ASCII_DIGIT+ }
float = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT* | "." ~ ASCII_DIGIT+ }
identifier = @{ ("_" | ASCII_ALPHA) ~ ("_" | ASCII_ALPHANUMERIC)* }
WHITESPACE = _{ " " | "\t" | NEWLINE }
COMMENT = _{ "//" ~ (!NEWLINE ~ ANY)* }