Compare commits
3 Commits
73580c4ff0
...
dfae432055
Author | SHA1 | Date |
---|---|---|
NotAFile | dfae432055 | |
NotAFile | 01fa26742e | |
NotAFile | e1f64548b4 |
|
@ -20,12 +20,6 @@ dependencies = [
|
||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arrayvec"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -43,24 +37,12 @@ version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bytecount"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytecount"
|
name = "bytecount"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"
|
checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.34.0"
|
version = "2.34.0"
|
||||||
|
@ -81,9 +63,8 @@ name = "futilehdl"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ariadne",
|
"ariadne",
|
||||||
"nom 7.1.0",
|
"nom",
|
||||||
"nom-greedyerror",
|
"nom_locate",
|
||||||
"nom_locate 4.0.0",
|
|
||||||
"smol_str",
|
"smol_str",
|
||||||
"structopt",
|
"structopt",
|
||||||
]
|
]
|
||||||
|
@ -112,19 +93,6 @@ version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lexical-core"
|
|
||||||
version = "0.7.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
|
||||||
dependencies = [
|
|
||||||
"arrayvec",
|
|
||||||
"bitflags",
|
|
||||||
"cfg-if",
|
|
||||||
"ryu",
|
|
||||||
"static_assertions",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.115"
|
version = "0.2.115"
|
||||||
|
@ -143,17 +111,6 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nom"
|
|
||||||
version = "5.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
|
||||||
dependencies = [
|
|
||||||
"lexical-core",
|
|
||||||
"memchr",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.0"
|
version = "7.1.0"
|
||||||
|
@ -165,50 +122,15 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nom-greedyerror"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fcd01dcb46ac4b8133a093685c5133b044d45c35f10ac9b6606e4db780d94ac7"
|
|
||||||
dependencies = [
|
|
||||||
"nom 5.1.2",
|
|
||||||
"nom 7.1.0",
|
|
||||||
"nom_locate 1.0.0",
|
|
||||||
"nom_locate 2.1.0",
|
|
||||||
"nom_locate 4.0.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nom_locate"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f932834fd8e391fc7710e2ba17e8f9f8645d846b55aa63207e17e110a1e1ce35"
|
|
||||||
dependencies = [
|
|
||||||
"bytecount 0.3.2",
|
|
||||||
"memchr",
|
|
||||||
"nom 5.1.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nom_locate"
|
|
||||||
version = "2.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a67484adf5711f94f2f28b653bf231bff8e438be33bf5b0f35935a0db4f618a2"
|
|
||||||
dependencies = [
|
|
||||||
"bytecount 0.6.2",
|
|
||||||
"memchr",
|
|
||||||
"nom 5.1.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom_locate"
|
name = "nom_locate"
|
||||||
version = "4.0.0"
|
version = "4.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37794436ca3029a3089e0b95d42da1f0b565ad271e4d3bb4bad0c7bb70b10605"
|
checksum = "37794436ca3029a3089e0b95d42da1f0b565ad271e4d3bb4bad0c7bb70b10605"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytecount 0.6.2",
|
"bytecount",
|
||||||
"memchr",
|
"memchr",
|
||||||
"nom 7.1.0",
|
"nom",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -253,12 +175,6 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.136"
|
version = "1.0.136"
|
||||||
|
@ -274,12 +190,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "static_assertions"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|
|
@ -8,7 +8,8 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ariadne = "0.1.3"
|
ariadne = "0.1.3"
|
||||||
nom = "7.1.0"
|
nom = "7.1.0"
|
||||||
nom-greedyerror = "0.4.0"
|
|
||||||
nom_locate = "4.0.0"
|
nom_locate = "4.0.0"
|
||||||
smol_str = "0.1.21"
|
smol_str = "0.1.21"
|
||||||
structopt = "0.3.26"
|
structopt = "0.3.26"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
|
|
@ -4,6 +4,7 @@ mod package;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod rtlil;
|
mod rtlil;
|
||||||
|
|
||||||
|
use ariadne::Source;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -48,11 +49,9 @@ fn main() {
|
||||||
if opt.debug {
|
if opt.debug {
|
||||||
println!("{err:#?}");
|
println!("{err:#?}");
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
parser::error::convert_error(input, err)
|
parser::error::convert_error(input, err)
|
||||||
.eprint(Source::from(input.fragment()))
|
.eprint(Source::from(input.fragment()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
Err(_) => (unreachable!()),
|
Err(_) => (unreachable!()),
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
|
|
|
@ -1,23 +1,124 @@
|
||||||
|
use super::tokens::{TokenKind, TokenSpan};
|
||||||
use super::{IErr, Span};
|
use super::{IErr, Span};
|
||||||
use ariadne::{Label, Report, ReportKind};
|
use ariadne::{Label, Report, ReportKind};
|
||||||
use nom_greedyerror::{GreedyErrorKind, Position};
|
use nom::error::{ContextError, ParseError};
|
||||||
|
use nom::InputTake;
|
||||||
|
|
||||||
fn span_to_range(input: Span) -> std::ops::Range<usize> {
|
#[derive(Debug)]
|
||||||
input.position()..(input.position() + input.len())
|
pub struct Error<I> {
|
||||||
|
pub errors: Vec<(I, ErrorKind)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_error(_input: Span, e: IErr<Span>) -> Report {
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum ErrorKind {
|
||||||
|
/// A static context string
|
||||||
|
Context(&'static str),
|
||||||
|
/// An expected character
|
||||||
|
Char(char),
|
||||||
|
/// An expected token
|
||||||
|
Token(TokenKind),
|
||||||
|
/// A list of valid tokens
|
||||||
|
Tokens(Vec<TokenKind>),
|
||||||
|
/// A nom error
|
||||||
|
Nom(nom::error::ErrorKind),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> ParseError<I> for Error<I>
|
||||||
|
where
|
||||||
|
I: InputPos + std::fmt::Debug + Clone,
|
||||||
|
{
|
||||||
|
fn from_error_kind(input: I, kind: nom::error::ErrorKind) -> Self {
|
||||||
|
Self {
|
||||||
|
errors: vec![(input, ErrorKind::Nom(kind))],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append(input: I, kind: nom::error::ErrorKind, mut other: Self) -> Self {
|
||||||
|
other.errors.push((input, ErrorKind::Nom(kind)));
|
||||||
|
other
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_char(input: I, c: char) -> Self {
|
||||||
|
Self {
|
||||||
|
errors: vec![(input, ErrorKind::Char(c))],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn or(self, mut other: Self) -> Self {
|
||||||
|
let self_first = self.errors.first();
|
||||||
|
let other_first = other.errors.first();
|
||||||
|
match (self_first, other_first) {
|
||||||
|
(Some((_is, ErrorKind::Token(s))), Some((io, ErrorKind::Token(o)))) => {
|
||||||
|
let combined_kind = ErrorKind::Tokens(vec![*s, *o]);
|
||||||
|
other.errors[0] = (io.clone(), combined_kind);
|
||||||
|
other
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
other.errors.extend_from_slice(&self.errors[..]);
|
||||||
|
other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> ContextError<I> for Error<I> {
|
||||||
|
fn add_context(input: I, ctx: &'static str, mut other: Self) -> Self {
|
||||||
|
other.errors.push((input, ErrorKind::Context(ctx)));
|
||||||
|
other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> Error<I> {
|
||||||
|
pub fn from_tokenkind(input: I, kind: TokenKind) -> Self {
|
||||||
|
Self {
|
||||||
|
errors: vec![(input, ErrorKind::Token(kind))],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait InputPos {
|
||||||
|
fn position(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputPos for Span<'_> {
|
||||||
|
fn position(&self) -> usize {
|
||||||
|
self.location_offset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tokspan_to_range(input: TokenSpan) -> std::ops::Range<usize> {
|
||||||
|
let first = input.first().unwrap().span().position();
|
||||||
|
let last_span = input.last().unwrap().span();
|
||||||
|
let last = last_span.position() + last_span.len();
|
||||||
|
first..last
|
||||||
|
}
|
||||||
|
|
||||||
|
fn label_tokspan(input: TokenSpan) -> Label {
|
||||||
|
Label::new(tokspan_to_range(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert_error(_input: Span, e: IErr<TokenSpan>) -> Report {
|
||||||
let mut labels = Vec::new();
|
let mut labels = Vec::new();
|
||||||
for err in e.errors {
|
let mut colors = ariadne::ColorGenerator::new();
|
||||||
let label = match err.1 {
|
for (input, err) in e.errors {
|
||||||
GreedyErrorKind::Context(ctx) => {
|
let label = match err {
|
||||||
Label::new(span_to_range(err.0)).with_message(format!("in {ctx}"))
|
ErrorKind::Context(ctx) => label_tokspan(input).with_message(format!("in {ctx}")),
|
||||||
|
ErrorKind::Char(c) => label_tokspan(input).with_message(format!("expected {c:?}")),
|
||||||
|
ErrorKind::Nom(kind) => {
|
||||||
|
label_tokspan(input).with_message(format!("nom error {kind:?}"))
|
||||||
|
}
|
||||||
|
ErrorKind::Token(t) => {
|
||||||
|
let next = input.first().unwrap().kind();
|
||||||
|
let msg = format!("expected {t:?} found {next:?}");
|
||||||
|
label_tokspan(input.take(1)).with_message(msg)
|
||||||
|
}
|
||||||
|
ErrorKind::Tokens(ts) => {
|
||||||
|
let next = input.first().unwrap().kind();
|
||||||
|
let msg = format!("expected one of {ts:?} found {next:?}");
|
||||||
|
label_tokspan(input.take(1)).with_message(msg)
|
||||||
}
|
}
|
||||||
GreedyErrorKind::Char(c) => Label::new(err.0.position()..err.0.position())
|
|
||||||
.with_message(format!("expected {c:?}")),
|
|
||||||
GreedyErrorKind::Nom(kind) => Label::new(err.0.position()..err.0.position())
|
|
||||||
.with_message(format!("nom error {kind:?}")),
|
|
||||||
};
|
};
|
||||||
|
let label = label.with_color(colors.next());
|
||||||
labels.push(label);
|
labels.push(label);
|
||||||
}
|
}
|
||||||
let mut rep = Report::build(ReportKind::Error, (), 0).with_message("Parse Error");
|
let mut rep = Report::build(ReportKind::Error, (), 0).with_message("Parse Error");
|
||||||
|
|
|
@ -6,22 +6,12 @@ pub mod module;
|
||||||
pub mod proc;
|
pub mod proc;
|
||||||
pub mod tokens;
|
pub mod tokens;
|
||||||
|
|
||||||
use nom::{
|
|
||||||
branch::alt,
|
|
||||||
bytes::complete::tag,
|
|
||||||
character::complete::{alpha1, alphanumeric1, multispace0},
|
|
||||||
combinator::{map, opt, recognize},
|
|
||||||
error::{ErrorKind, ParseError},
|
|
||||||
multi::{many0, separated_list0},
|
|
||||||
sequence::{delimited, pair, preceded, separated_pair, tuple},
|
|
||||||
};
|
|
||||||
use nom_greedyerror::GreedyError;
|
|
||||||
use nom_locate::LocatedSpan;
|
use nom_locate::LocatedSpan;
|
||||||
|
|
||||||
// custom span type for nom_locate
|
// custom span type for nom_locate
|
||||||
pub type Span<'a> = LocatedSpan<&'a str>;
|
pub type Span<'a> = LocatedSpan<&'a str>;
|
||||||
|
|
||||||
pub type IErr<I> = GreedyError<I, ErrorKind>;
|
pub type IErr<I> = error::Error<I>;
|
||||||
// custom IResult type for VerboseError
|
// custom IResult type for VerboseError
|
||||||
pub type IResult<I, O, E = IErr<I>> = nom::IResult<I, O, E>;
|
pub type IResult<I, O, E = IErr<I>> = nom::IResult<I, O, E>;
|
||||||
|
|
||||||
|
@ -30,7 +20,7 @@ pub use crate::parser::declaration::{
|
||||||
};
|
};
|
||||||
pub use crate::parser::expression::{expression, Call, Expression, Operation};
|
pub use crate::parser::expression::{expression, Call, Expression, Operation};
|
||||||
pub use crate::parser::module::{module, Module, ModuleItem, PortDirection};
|
pub use crate::parser::module::{module, Module, ModuleItem, PortDirection};
|
||||||
use crate::parser::tokens::{token, TokenKind as tk, TokenSpan};
|
use crate::parser::tokens::TokenSpan;
|
||||||
|
|
||||||
pub fn parse(input: TokenSpan) -> IResult<TokenSpan, Module> {
|
pub fn parse(input: TokenSpan) -> IResult<TokenSpan, Module> {
|
||||||
module(input)
|
module(input)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
combinator::map,
|
combinator::{cut, map},
|
||||||
error::context,
|
error::context,
|
||||||
multi::{many0, separated_list0},
|
multi::{many0, separated_list0},
|
||||||
sequence::{delimited, preceded, tuple},
|
sequence::{delimited, preceded, tuple},
|
||||||
|
@ -52,7 +52,11 @@ fn inputs_list(input: TokenSpan) -> IResult<TokenSpan, Vec<PortDecl>> {
|
||||||
fn assign_item(input: TokenSpan) -> IResult<TokenSpan, Assign> {
|
fn assign_item(input: TokenSpan) -> IResult<TokenSpan, Assign> {
|
||||||
context(
|
context(
|
||||||
"assignment",
|
"assignment",
|
||||||
delimited(token(tk::Assign), assign_statement, token(tk::Semicolon)),
|
delimited(
|
||||||
|
token(tk::Assign),
|
||||||
|
cut(assign_statement),
|
||||||
|
cut(token(tk::Semicolon)),
|
||||||
|
),
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,23 +68,22 @@ fn module_item(input: TokenSpan) -> IResult<TokenSpan, ModuleItem> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn module(input: TokenSpan) -> IResult<TokenSpan, Module> {
|
pub fn module(input: TokenSpan) -> IResult<TokenSpan, Module> {
|
||||||
context(
|
|
||||||
"module",
|
|
||||||
map(
|
map(
|
||||||
tuple((
|
preceded(
|
||||||
token(tk::Module),
|
token(tk::Module),
|
||||||
|
cut(tuple((
|
||||||
token(tk::Ident),
|
token(tk::Ident),
|
||||||
delimited(token(tk::LParen), inputs_list, token(tk::RParen)),
|
delimited(token(tk::LParen), inputs_list, token(tk::RParen)),
|
||||||
preceded(token(tk::RArrow), typename),
|
preceded(token(tk::RArrow), typename),
|
||||||
delimited(token(tk::LBrace), many0(module_item), token(tk::RBrace)),
|
delimited(token(tk::LBrace), many0(module_item), token(tk::RBrace)),
|
||||||
)),
|
))),
|
||||||
|(_, name, inputs, _ret, items)| Module {
|
),
|
||||||
|
|(name, inputs, _ret, items)| Module {
|
||||||
// TODO: bring back returns
|
// TODO: bring back returns
|
||||||
name: name.span(),
|
name: name.span(),
|
||||||
ports: inputs,
|
ports: inputs,
|
||||||
items,
|
items,
|
||||||
},
|
},
|
||||||
),
|
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! convert text into a token stream
|
//! convert text into a token stream
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
error::{Error, InputPos},
|
||||||
literals::{identifier, ws0},
|
literals::{identifier, ws0},
|
||||||
IResult, Span,
|
IResult, Span,
|
||||||
};
|
};
|
||||||
|
@ -9,7 +10,6 @@ use nom::{
|
||||||
bytes::complete::tag,
|
bytes::complete::tag,
|
||||||
character::complete::{anychar, digit1},
|
character::complete::{anychar, digit1},
|
||||||
combinator::{consumed, map, recognize},
|
combinator::{consumed, map, recognize},
|
||||||
error::ParseError,
|
|
||||||
multi::many0,
|
multi::many0,
|
||||||
};
|
};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -40,9 +40,12 @@ impl<'a> Token<'a> {
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
self.span
|
self.span
|
||||||
}
|
}
|
||||||
|
pub fn kind(&self) -> TokenKind {
|
||||||
|
self.kind
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
pub enum TokenKind {
|
pub enum TokenKind {
|
||||||
// no whitespace, for now
|
// no whitespace, for now
|
||||||
// no token trees either, for now
|
// no token trees either, for now
|
||||||
|
@ -92,6 +95,12 @@ impl<'a> TokenSpan<'a> {
|
||||||
pub fn with_pos(rest: &'a [Token<'a>], pos: usize) -> Self {
|
pub fn with_pos(rest: &'a [Token<'a>], pos: usize) -> Self {
|
||||||
Self { rest, pos }
|
Self { rest, pos }
|
||||||
}
|
}
|
||||||
|
pub fn first(&self) -> Option<&Token> {
|
||||||
|
self.rest.first()
|
||||||
|
}
|
||||||
|
pub fn last(&self) -> Option<&Token> {
|
||||||
|
self.rest.last()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl nom::InputTake for TokenSpan<'_> {
|
impl nom::InputTake for TokenSpan<'_> {
|
||||||
|
@ -114,30 +123,22 @@ impl nom::InputLength for TokenSpan<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl nom_greedyerror::Position for TokenSpan<'_> {
|
impl InputPos for TokenSpan<'_> {
|
||||||
fn position(&self) -> usize {
|
fn position(&self) -> usize {
|
||||||
self.pos
|
self.pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// combinator that matches a token kind
|
/// combinator that matches a token kind
|
||||||
pub fn token<'a, E>(
|
pub fn token<'a>(kind: TokenKind) -> impl FnMut(TokenSpan<'a>) -> IResult<TokenSpan, &Token> {
|
||||||
kind: TokenKind,
|
|
||||||
) -> impl FnMut(TokenSpan<'a>) -> nom::IResult<TokenSpan, &Token, E>
|
|
||||||
where
|
|
||||||
E: ParseError<TokenSpan<'a>>,
|
|
||||||
{
|
|
||||||
move |input: TokenSpan| {
|
move |input: TokenSpan| {
|
||||||
let next = &input.rest[0];
|
let next = &input.rest[0];
|
||||||
if next.kind == kind.clone() {
|
let kind = kind;
|
||||||
|
if next.kind == kind {
|
||||||
let rest = TokenSpan::with_pos(&input.rest[1..], input.pos + 1);
|
let rest = TokenSpan::with_pos(&input.rest[1..], input.pos + 1);
|
||||||
Ok((rest, next))
|
Ok((rest, next))
|
||||||
} else {
|
} else {
|
||||||
Err(nom::Err::Error(E::from_error_kind(
|
Err(nom::Err::Error(Error::from_tokenkind(input, kind)))
|
||||||
input,
|
|
||||||
// TODO: Proper errors here
|
|
||||||
nom::error::ErrorKind::Tag,
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue