schala/schala-lang/language/src/parsing/new.rs

194 lines
6.8 KiB
Rust
Raw Normal View History

2021-11-03 16:27:42 -07:00
use crate::ast::*;
use std::rc::Rc;
2021-11-03 16:27:42 -07:00
peg::parser! {
pub grammar schala_parser() for str {
2021-11-03 18:01:23 -07:00
pub rule program() -> AST =
n:(statement() ** delimiter() ) { AST { id: Default::default(), statements: n.into() } }
rule delimiter() = ";" / "\n"
rule statement() -> Statement =
expr:expression() { Statement {
id: Default::default(), location: Default::default(), kind: StatementKind::Expression(expr) }
}
pub rule expression() -> Expression =
kind:expression_kind() { Expression { id: Default::default(), type_anno: None, kind: kind } }
rule expression_kind() -> ExpressionKind =
primary()
rule primary() -> ExpressionKind =
2021-11-03 20:31:46 -07:00
float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() /
list_expr()
rule list_expr() -> ExpressionKind =
"[" exprs:(expression() ** ",") "]" {
let mut exprs = exprs;
ExpressionKind::ListLiteral(exprs)
}
rule paren_expr() -> ExpressionKind =
"(" exprs:(expression() ** ",") ")" {
let mut exprs = exprs;
match exprs.len() {
1 => exprs.pop().unwrap().kind,
_ => ExpressionKind::TupleLiteral(exprs),
}
}
//TODO string escapes, prefixes
rule string_literal() -> ExpressionKind =
"\"" items:$([^ '"' ]*) "\"" { ExpressionKind::StringLiteral(Rc::new(items.to_string())) }
rule bool_literal() -> ExpressionKind =
"true" { ExpressionKind::BoolLiteral(true) } / "false" { ExpressionKind::BoolLiteral(false) }
2021-11-03 18:01:23 -07:00
rule nat_literal() -> ExpressionKind =
bin_literal() / hex_literal() / unmarked_literal()
rule unmarked_literal() -> ExpressionKind =
digits:digits() { ExpressionKind::NatLiteral(digits.parse().unwrap()) }
rule bin_literal() -> ExpressionKind =
"0b" digits:bin_digits() { ExpressionKind::NatLiteral(parse_binary(digits)) }
rule hex_literal() -> ExpressionKind =
"0x" digits:hex_digits() { ExpressionKind::NatLiteral(parse_hex(digits)) }
2021-11-03 18:01:23 -07:00
rule float_literal() -> ExpressionKind =
ds:$( digits() "." digits()? / "." digits() ) { ExpressionKind::FloatLiteral(ds.parse().unwrap()) }
rule digits() -> &'input str = $((digit_group() "_"*)+)
rule bin_digits() -> &'input str = $((bin_digit_group() "_"*)+)
rule hex_digits() -> &'input str = $((hex_digit_group() "_"*)+)
2021-11-03 18:01:23 -07:00
rule digit_group() -> &'input str = $(['0'..='9']+)
rule bin_digit_group() -> &'input str = $(['0' | '1']+)
rule hex_digit_group() -> &'input str = $(['0'..='9' | 'a'..='f' | 'A'..='F']+)
2021-11-03 16:27:42 -07:00
}
}
2021-11-03 18:01:23 -07:00
fn parse_binary(digits: &str/*, tok: Token*/) -> /*ParseResult<u64>*/ u64 {
let mut result: u64 = 0;
let mut multiplier = 1;
for d in digits.chars().rev() {
match d {
'1' => result += multiplier,
'0' => (),
'_' => continue,
_ => unreachable!()
}
multiplier = match multiplier.checked_mul(2) {
Some(m) => m,
None => /*return ParseError::new_with_token("This binary expression will overflow", tok),*/ panic!(),
}
}
//Ok(result)
result
}
//TODO fix these two functions
fn parse_hex(digits: &str) -> u64 {
let mut result: u64 = 0;
let mut multiplier: u64 = 1;
for d in digits.chars().rev() {
if d == '_' {
continue;
}
match d.to_digit(16) {
Some(n) => result += n as u64 * multiplier,
None => panic!(),
}
multiplier = match multiplier.checked_mul(16) {
Some(m) => m,
None => panic!()
}
}
result
}
2021-11-03 18:01:23 -07:00
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
2021-11-03 18:01:23 -07:00
#[test]
fn new_parser() {
let parsed = schala_parser::expression("4");
assert_eq!(parsed.unwrap(), Expression { id: Default::default(), type_anno: None, kind: ExpressionKind::NatLiteral(4) });
let parsed = schala_parser::program("56.1");
if let Err(ref err) = parsed {
println!("{}", err);
}
assert_eq!(parsed.unwrap(), AST {
id: Default::default(), statements: vec![
Statement {
id: Default::default(),
location: Default::default(),
kind: StatementKind::Expression(Expression { id: Default::default(), type_anno: None, kind:
ExpressionKind::FloatLiteral(56.1) })
}
].into() });
let parsed = schala_parser::program("1;2\n5\n(1.1,false)");
if let Err(ref err) = parsed {
println!("{}", err);
}
assert_eq!(parsed.unwrap(), AST {
id: Default::default(), statements: vec![
Statement {
id: Default::default(),
location: Default::default(),
kind: StatementKind::Expression(Expression { id: Default::default(), type_anno: None, kind:
ExpressionKind::NatLiteral(1) })
},
Statement {
id: Default::default(),
location: Default::default(),
kind: StatementKind::Expression(Expression { id: Default::default(), type_anno: None, kind:
ExpressionKind::NatLiteral(2) })
},
Statement {
id: Default::default(),
location: Default::default(),
kind: StatementKind::Expression(Expression { id: Default::default(), type_anno: None, kind:
ExpressionKind::NatLiteral(5) })
},
Statement {
id: Default::default(),
location: Default::default(),
kind: StatementKind::Expression(Expression { id: Default::default(), type_anno: None, kind:
ExpressionKind::TupleLiteral(vec![Expression{
id: Default::default(),
type_anno: None,
kind: ExpressionKind::FloatLiteral(1.1),
},
Expression {
id: Default::default(),
type_anno: None,
kind: ExpressionKind::BoolLiteral(false),
}]
) })
}
].into() });
2021-11-03 18:01:23 -07:00
/*
let parsed = schala_parser::expression("quincy");
println!("{:?}", parsed.unwrap_err());
assert_eq!(1, 2);
*/
}
}