Parse simple number literal

This commit is contained in:
Joscha 2022-11-17 10:56:59 +01:00
parent 4aecce8107
commit c593e4c872
4 changed files with 133 additions and 3 deletions

View file

@ -1,9 +1,11 @@
use std::fs;
use std::path::PathBuf;
use chumsky::Parser as _;
use clap::Parser;
mod builtin;
mod parser;
mod table;
mod value;
@ -25,9 +27,14 @@ fn main() -> anyhow::Result<()> {
match args.command {
Command::Parse { file } => {
let content = fs::read_to_string(&file)?;
print!("{content}");
if !content.ends_with('\n') {
println!();
match parser::parser().parse(&content as &str) {
Ok(lit) => println!("Successful parse: {lit:#?}"),
Err(errs) => {
println!("Parsing failed");
for err in errs {
println!("{err:?}");
}
}
}
}
}

37
src/parser.rs Normal file
View file

@ -0,0 +1,37 @@
use chumsky::prelude::*;
#[derive(Debug)]
pub enum Lit {
Num(i64),
}
fn lit_num() -> impl Parser<char, i64, Error = Simple<char>> {
let sign = just('+')
.or(just('-'))
.or_not()
.map(|s| if s == Some('-') { -1_i128 } else { 1_i128 });
let digits = text::int(10);
sign.then(digits).try_map(|(sign, digits), span| {
// u64::MIN and u32::MAX have 19 digits in base 10
if digits.len() > 19 {
return Err(Simple::custom(span, "number out of range"));
}
let number = sign * digits.parse::<i128>().unwrap();
if number < i64::MIN.into() || number > u64::MAX.into() {
return Err(Simple::custom(span, "number out of range"));
}
Ok(number as i64)
})
}
fn lit() -> impl Parser<char, Lit, Error = Simple<char>> {
lit_num().map(Lit::Num)
}
pub fn parser() -> impl Parser<char, Lit, Error = Simple<char>> {
lit().padded().then_ignore(end())
}