serene-rust-implementation/src/grammer.lalrpop

59 lines
1.4 KiB
Plaintext

//! Serene's grammer based on LALRPOP which is a LR(1) parser.
use std::str::FromStr;
use crate::ast;
grammar;
// A collection of Expr objects is simply a sequence of parsed AST objects.
pub Exprs: Vec<ast::Expr> = {
<v:(<Expr>)*> => v,
};
// Parse an AST expression.
Expr: ast::Expr = {
// Matches a list
"(" <Exprs> ")" => ast::Expr::List(<>),
// Matches a vector
// "[" <Exprs> "]" => Ast::Vector(<>),
// Match the literal value "nil".
// "nil" => Ast::Nil,
// Match a Num term.
Float => ast::Expr::Num(ast::Number::Float(<>)),
Decimal => ast::Expr::Num(ast::Number::Integer(<>)),
// Matches a string.
r#""(?:[^"\\]|\\.)*""# => {
let val = <>;
ast::Expr::Str(val[1..val.len() - 1].to_owned())
},
// Matches a quoted expr
"'" <Expr> => ast::Expr::Quote(Box::new(<>)),
// Match any token and treat it as an atom.
Symbol => ast::Expr::Symbol(<>),
! => ast::Expr::Error(format!("{:?}", <>)),
};
// Match any sequence of token characters.
Symbol: String = {
r#"[A-Za-z_?+*/=<>-]+[0-9A-Za-z_?+*/=<>-]*"# => (<>).to_owned()
};
// Match any valid integer value and treat it as a 32-bit signed integer.
Decimal: i32 = {
r"[0-9]+" => i32::from_str(<>).unwrap()
};
Float: f32 = {
r"[0-9]*\.[0-9]+" => f32::from_str(<>).unwrap()
};
match {
r"\s*" => { },
r";[^\n\r]*[\n\r]*" => { },
_
}