never sseen such clean error handling
This commit is contained in:
parent
a06927e356
commit
76ca07b4dd
8 changed files with 204 additions and 98 deletions
57
Cargo.lock
generated
57
Cargo.lock
generated
|
@ -11,12 +11,6 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "anyhow"
|
|
||||||
version = "1.0.40"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
|
@ -280,12 +274,12 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||||
name = "nomwut"
|
name = "nomwut"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"itertools",
|
"itertools",
|
||||||
"lalrpop",
|
"lalrpop",
|
||||||
"lalrpop-util",
|
"lalrpop-util",
|
||||||
"maplit",
|
"maplit",
|
||||||
"regex",
|
"regex",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -319,6 +313,24 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.1.57"
|
version = "0.1.57"
|
||||||
|
@ -383,6 +395,17 @@ dependencies = [
|
||||||
"precomputed-hash",
|
"precomputed-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "term"
|
name = "term"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
@ -394,6 +417,26 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-keccak"
|
name = "tiny-keccak"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
|
|
|
@ -12,8 +12,8 @@ build = "build.rs"
|
||||||
lalrpop-util = "0.19.5"
|
lalrpop-util = "0.19.5"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
itertools = "0.10"
|
itertools = "0.10"
|
||||||
anyhow = "1.0"
|
thiserror = "1.0"
|
||||||
maplit = "*"
|
maplit = "1.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
lalrpop = "0.19.5"
|
lalrpop = "0.19.5"
|
||||||
|
|
1
rust-toolchain
Normal file
1
rust-toolchain
Normal file
|
@ -0,0 +1 @@
|
||||||
|
nightly
|
14
rustfmt.toml
Normal file
14
rustfmt.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
unstable_features = true
|
||||||
|
fn_single_line = false
|
||||||
|
max_width = 130
|
||||||
|
reorder_impl_items = true
|
||||||
|
merge_imports = true
|
||||||
|
normalize_comments = true
|
||||||
|
use_field_init_shorthand = true
|
||||||
|
#wrap_comments = true
|
||||||
|
combine_control_expr = false
|
||||||
|
condense_wildcard_suffixes = true
|
||||||
|
format_code_in_doc_comments = true
|
||||||
|
format_macro_matchers = true
|
||||||
|
format_strings = true
|
||||||
|
use_small_heuristics = "Max"
|
|
@ -2,7 +2,6 @@ use std::{collections::HashMap, iter::FromIterator};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use anyhow::*;
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::collections::LinkedList;
|
use std::collections::LinkedList;
|
||||||
|
|
||||||
|
@ -11,11 +10,11 @@ type AttrValue = String;
|
||||||
type AttrName = String;
|
type AttrName = String;
|
||||||
|
|
||||||
pub trait FromExpr: Sized {
|
pub trait FromExpr: Sized {
|
||||||
fn from_expr(e: Expr) -> Result<Self, AstError>;
|
fn from_expr(e: Expr) -> AstResult<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromExpr for Expr {
|
impl FromExpr for Expr {
|
||||||
fn from_expr(e: Expr) -> Result<Self, AstError> {
|
fn from_expr(e: Expr) -> AstResult<Self> {
|
||||||
Ok(e)
|
Ok(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,14 +24,14 @@ pub enum DefType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromExpr for DefType {
|
impl FromExpr for DefType {
|
||||||
fn from_expr(e: Expr) -> Result<Self, AstError> {
|
fn from_expr(e: Expr) -> AstResult<Self> {
|
||||||
if let Expr::Symbol(_, sym) = e {
|
if let Expr::Symbol(span, sym) = e {
|
||||||
match sym.as_str() {
|
match sym.as_str() {
|
||||||
"defwidget" => Ok(DefType::Widget),
|
"defwidget" => Ok(DefType::Widget),
|
||||||
_ => Err(AstError::InvalidDefinition),
|
_ => Err(AstError::InvalidDefinition(Some(span))),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(AstError::UnexpectedNode)
|
Err(AstError::WrongExprType(Some(e.span()), ExprType::Symbol, e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,26 +44,18 @@ pub struct Definitional<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromExpr> FromExpr for Definitional<T> {
|
impl<T: FromExpr> FromExpr for Definitional<T> {
|
||||||
fn from_expr(e: Expr) -> Result<Self, AstError> {
|
fn from_expr(e: Expr) -> AstResult<Self> {
|
||||||
if let Expr::List(span, list) = e {
|
spanned!(e.span(), {
|
||||||
|
let list = e.as_list()?;
|
||||||
let mut iter = itertools::put_back(list.into_iter());
|
let mut iter = itertools::put_back(list.into_iter());
|
||||||
|
|
||||||
let def_type = DefType::from_expr(iter.next().or_missing()?)?;
|
let def_type = DefType::from_expr(iter.next().or_missing(ExprType::Symbol)?)?;
|
||||||
let name = iter.next().or_missing()?.as_str()?;
|
let name = iter.next().or_missing(ExprType::Str)?.as_str()?;
|
||||||
let attrs = parse_key_values(&mut iter);
|
let attrs = parse_key_values(&mut iter);
|
||||||
|
|
||||||
let children = iter
|
let children = iter.map(|x| T::from_expr(x)).collect::<AstResult<Vec<_>>>()?;
|
||||||
.map(T::from_expr)
|
Definitional { def_type, name, attrs, children }
|
||||||
.collect::<Result<Vec<_>, AstError>>()?;
|
})
|
||||||
Ok(Definitional {
|
|
||||||
def_type,
|
|
||||||
name,
|
|
||||||
attrs,
|
|
||||||
children,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(AstError::UnexpectedNode)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
@ -75,27 +66,20 @@ pub struct Element<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromExpr for Element<Expr> {
|
impl FromExpr for Element<Expr> {
|
||||||
fn from_expr(e: Expr) -> Result<Self, AstError> {
|
fn from_expr(e: Expr) -> AstResult<Self> {
|
||||||
if let Expr::List(span, list) = e {
|
spanned!(e.span(), {
|
||||||
|
let list = e.as_list()?;
|
||||||
let mut iter = itertools::put_back(list.into_iter());
|
let mut iter = itertools::put_back(list.into_iter());
|
||||||
|
|
||||||
let name = iter.next().or_missing()?.as_symbol()?;
|
let name = iter.next().or_missing(ExprType::Str)?.as_symbol()?;
|
||||||
let attrs = parse_key_values(&mut iter);
|
let attrs = parse_key_values(&mut iter);
|
||||||
|
|
||||||
Ok(Element {
|
Element { name, attrs, children: iter.collect_vec() }
|
||||||
name,
|
})
|
||||||
attrs,
|
|
||||||
children: iter.collect_vec(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(AstError::UnexpectedNode)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_key_values<I: Iterator<Item = Expr>>(
|
fn parse_key_values<I: Iterator<Item = Expr>>(iter: &mut itertools::PutBack<I>) -> HashMap<String, Expr> {
|
||||||
iter: &mut itertools::PutBack<I>,
|
|
||||||
) -> HashMap<String, Expr> {
|
|
||||||
let mut data = HashMap::new();
|
let mut data = HashMap::new();
|
||||||
loop {
|
loop {
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
|
@ -126,10 +110,7 @@ mod test {
|
||||||
fn test() {
|
fn test() {
|
||||||
let parser = parser::ExprParser::new();
|
let parser = parser::ExprParser::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Element::<Expr>::from_expr(
|
Element::<Expr>::from_expr(parser.parse("(box :bar 12 :baz \"hi\" foo (bar))").unwrap()).unwrap(),
|
||||||
parser.parse("(box :bar 12 :baz \"hi\" foo (bar))").unwrap()
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
Element {
|
Element {
|
||||||
name: "box".to_string(),
|
name: "box".to_string(),
|
||||||
attrs: maplit::hashmap! {
|
attrs: maplit::hashmap! {
|
||||||
|
@ -139,10 +120,7 @@ mod test {
|
||||||
},
|
},
|
||||||
children: vec![
|
children: vec![
|
||||||
Expr::Symbol(Span(23, 26), "foo".to_string()),
|
Expr::Symbol(Span(23, 26), "foo".to_string()),
|
||||||
Expr::List(
|
Expr::List(Span(27, 32), vec![Expr::Symbol(Span(28, 31), "bar".to_string())]),
|
||||||
Span(27, 32),
|
|
||||||
vec![Expr::Symbol(Span(28, 31), "bar".to_string())]
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
52
src/error.rs
52
src/error.rs
|
@ -1,18 +1,52 @@
|
||||||
use crate::Expr;
|
use crate::{Expr, ExprType, Span};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
pub type AstResult<T> = Result<T, AstError>;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Error)]
|
||||||
pub enum AstError {
|
pub enum AstError {
|
||||||
UnexpectedNode,
|
#[error("Definition invalid")]
|
||||||
InvalidDefinition,
|
InvalidDefinition(Option<Span>),
|
||||||
WrongExprType(Expr),
|
#[error("Expected a {1}, but got nothing")]
|
||||||
MissingNode,
|
MissingNode(Option<Span>, ExprType),
|
||||||
|
#[error("Wrong type of expression: Expected {1} but got {2}")]
|
||||||
|
WrongExprType(Option<Span>, ExprType, Expr),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spanned(span: Span, err: impl Into<AstError>) -> AstError {
|
||||||
|
use AstError::*;
|
||||||
|
match err.into() {
|
||||||
|
AstError::InvalidDefinition(None) => AstError::InvalidDefinition(Some(span)),
|
||||||
|
AstError::MissingNode(None, x) => AstError::MissingNode(Some(span), x),
|
||||||
|
AstError::WrongExprType(None, x, y) => AstError::WrongExprType(Some(span), x, y),
|
||||||
|
x => x,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait OptionAstErrorExt<T> {
|
pub trait OptionAstErrorExt<T> {
|
||||||
fn or_missing(self) -> Result<T, AstError>;
|
fn or_missing(self, t: ExprType) -> Result<T, AstError>;
|
||||||
}
|
}
|
||||||
impl<T> OptionAstErrorExt<T> for Option<T> {
|
impl<T> OptionAstErrorExt<T> for Option<T> {
|
||||||
fn or_missing(self) -> Result<T, AstError> {
|
fn or_missing(self, t: ExprType) -> Result<T, AstError> {
|
||||||
self.ok_or(AstError::MissingNode)
|
self.ok_or(AstError::MissingNode(None, t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait AstResultExt<T> {
|
||||||
|
fn at(self, span: Span) -> Result<T, AstError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, E: Into<AstError>> AstResultExt<T> for Result<T, E> {
|
||||||
|
fn at(self, span: Span) -> Result<T, AstError> {
|
||||||
|
self.map_err(|err| spanned(span, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! spanned {
|
||||||
|
($span:expr, $block:expr) => {{
|
||||||
|
let span = $span;
|
||||||
|
let result: Result<_, AstError> = try { $block };
|
||||||
|
result.at(span)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
104
src/main.rs
104
src/main.rs
|
@ -1,17 +1,18 @@
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
#![feature(try_blocks)]
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
use error::AstError;
|
use error::AstError;
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::{fmt::Display, ops::Deref};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use lalrpop_util::lalrpop_mod;
|
use lalrpop_util::lalrpop_mod;
|
||||||
|
|
||||||
//mod lexer;
|
// mod lexer;
|
||||||
|
|
||||||
lalrpop_mod!(pub parser);
|
lalrpop_mod!(pub parser);
|
||||||
|
|
||||||
|
@ -24,6 +25,23 @@ impl std::fmt::Display for Span {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub enum ExprType {
|
||||||
|
List,
|
||||||
|
Table,
|
||||||
|
Keyword,
|
||||||
|
Symbol,
|
||||||
|
Str,
|
||||||
|
Number,
|
||||||
|
Comment,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ExprType {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
List(Span, Vec<Expr>),
|
List(Span, Vec<Expr>),
|
||||||
|
@ -32,28 +50,50 @@ pub enum Expr {
|
||||||
Symbol(Span, String),
|
Symbol(Span, String),
|
||||||
Str(Span, String),
|
Str(Span, String),
|
||||||
Number(Span, i32),
|
Number(Span, i32),
|
||||||
Comment,
|
Comment(Span),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Expr> for ExprType {
|
||||||
|
fn from(x: Expr) -> Self {
|
||||||
|
match x {
|
||||||
|
Expr::List(..) => ExprType::List,
|
||||||
|
Expr::Table(..) => ExprType::Table,
|
||||||
|
Expr::Keyword(..) => ExprType::Keyword,
|
||||||
|
Expr::Symbol(..) => ExprType::Symbol,
|
||||||
|
Expr::Str(..) => ExprType::Str,
|
||||||
|
Expr::Number(..) => ExprType::Number,
|
||||||
|
Expr::Comment(_) => ExprType::Number,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! as_func {
|
macro_rules! as_func {
|
||||||
($name:ident<$t:ty> = $p:pat => $value:expr) => {
|
($exprtype:expr, $name:ident < $t:ty > = $p:pat => $value:expr) => {
|
||||||
fn $name(self) -> Result<$t, AstError> {
|
fn $name(self) -> Result<$t, AstError> {
|
||||||
match self {
|
match self {
|
||||||
$p => Ok($value),
|
$p => Ok($value),
|
||||||
x => Err(AstError::WrongExprType(x)),
|
x => Err(AstError::WrongExprType(Some(x.span()), $exprtype, x)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
as_func!(as_str<String> = Expr::Str(_, x) => x);
|
as_func!(ExprType::Str, as_str<String> = Expr::Str(_, x) => x);
|
||||||
as_func!(as_symbol<String> = Expr::Symbol(_, x) => x);
|
|
||||||
|
|
||||||
fn is_keyword(&self) -> bool {
|
as_func!(ExprType::Symbol, as_symbol<String> = Expr::Symbol(_, x) => x);
|
||||||
|
|
||||||
|
as_func!(ExprType::List, as_list<Vec<Expr>> = Expr::List(_, x) => x);
|
||||||
|
|
||||||
|
pub fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Expr::Keyword(_, _) => true,
|
Expr::List(span, _) => *span,
|
||||||
_ => false,
|
Expr::Table(span, _) => *span,
|
||||||
|
Expr::Keyword(span, _) => *span,
|
||||||
|
Expr::Symbol(span, _) => *span,
|
||||||
|
Expr::Str(span, _) => *span,
|
||||||
|
Expr::Number(span, _) => *span,
|
||||||
|
Expr::Comment(span) => *span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,15 +104,11 @@ impl std::fmt::Display for Expr {
|
||||||
match self {
|
match self {
|
||||||
Number(_, x) => write!(f, "{}", x),
|
Number(_, x) => write!(f, "{}", x),
|
||||||
List(_, x) => write!(f, "({})", x.iter().map(|e| format!("{}", e)).join(" ")),
|
List(_, x) => write!(f, "({})", x.iter().map(|e| format!("{}", e)).join(" ")),
|
||||||
Table(_, x) => write!(
|
Table(_, x) => write!(f, "{{{}}}", x.iter().map(|(k, v)| format!("{} {}", k, v)).join(" ")),
|
||||||
f,
|
|
||||||
"{{{}}}",
|
|
||||||
x.iter().map(|(k, v)| format!("{} {}", k, v)).join(" ")
|
|
||||||
),
|
|
||||||
Keyword(_, x) => write!(f, "{}", x),
|
Keyword(_, x) => write!(f, "{}", x),
|
||||||
Symbol(_, x) => write!(f, "{}", x),
|
Symbol(_, x) => write!(f, "{}", x),
|
||||||
Str(_, x) => write!(f, "{}", x),
|
Str(_, x) => write!(f, "{}", x),
|
||||||
Comment => write!(f, ""),
|
Comment(_) => write!(f, ""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,28 +129,28 @@ macro_rules! test_p {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
//test_p!("1");
|
// test_p!("1");
|
||||||
//test_p!("(12)");
|
// test_p!("(12)");
|
||||||
//test_p!("(1 2)");
|
// test_p!("(1 2)");
|
||||||
//test_p!("(1 :foo 1)");
|
// test_p!("(1 :foo 1)");
|
||||||
//test_p!("(:foo 1)");
|
// test_p!("(:foo 1)");
|
||||||
//test_p!("(:foo->: 1)");
|
// test_p!("(:foo->: 1)");
|
||||||
//test_p!("(foo 1)");
|
// test_p!("(foo 1)");
|
||||||
//test_p!("(lol😄 1)");
|
// test_p!("(lol😄 1)");
|
||||||
|
|
||||||
//test_p!(r#"(test "hi")"#);
|
// test_p!(r#"(test "hi")"#);
|
||||||
//test_p!(r#"(test "h\"i")"#);
|
// test_p!(r#"(test "h\"i")"#);
|
||||||
//test_p!(r#"(test " hi ")"#);
|
// test_p!(r#"(test " hi ")"#);
|
||||||
|
|
||||||
//test_p!("(+ (1 2 (* 2 5)))");
|
// test_p!("(+ (1 2 (* 2 5)))");
|
||||||
|
|
||||||
//test_p!(r#"{:key value 12 "hi" (test) (1 2 3)}"#);
|
// test_p!(r#"{:key value 12 "hi" (test) (1 2 3)}"#);
|
||||||
|
|
||||||
//test_p!(r#"; test"#);
|
// test_p!(r#"; test"#);
|
||||||
//test_p!(
|
// test_p!(
|
||||||
//r#"(f arg ; test
|
// r#"(f arg ; test
|
||||||
//arg2)"#
|
// arg2)"#
|
||||||
//);
|
//);
|
||||||
|
|
||||||
//println!("\n\n\n\n\n\n");
|
// println!("\n\n\n\n\n\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub Expr: Expr = {
|
||||||
<x:Symbol> => x,
|
<x:Symbol> => x,
|
||||||
<l:@L> <x:StrLit> <r:@R> => Expr::Str(Span(l, r), x),
|
<l:@L> <x:StrLit> <r:@R> => Expr::Str(Span(l, r), x),
|
||||||
<l:@L> <x:Num> <r:@R> => Expr::Number(Span(l, r), x),
|
<l:@L> <x:Num> <r:@R> => Expr::Number(Span(l, r), x),
|
||||||
Comment => Expr::Comment,
|
<l:@L> Comment <r:@R> => Expr::Comment(Span(l, r)),
|
||||||
};
|
};
|
||||||
|
|
||||||
Keyword: Expr = <l:@L> <x:r":[^\s]+"> <r:@R> => Expr::Keyword(Span(l, r), x.to_string());
|
Keyword: Expr = <l:@L> <x:r":[^\s]+"> <r:@R> => Expr::Keyword(Span(l, r), x.to_string());
|
||||||
|
|
Loading…
Add table
Reference in a new issue