mirror of
https://github.com/HigherOrderCO/Kind1.git
synced 2024-09-19 04:37:28 +03:00
chore: fmt
This commit is contained in:
parent
e2a4df9577
commit
912b9fccde
@ -1,37 +1,94 @@
|
||||
use proc_macro::{self, TokenStream};
|
||||
use proc_macro2::Span;
|
||||
use proc_macro2::TokenStream as TknStream;
|
||||
use quote::quote;
|
||||
use syn::parse_quote;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::Error;
|
||||
use syn::Ident;
|
||||
use syn::ItemTrait;
|
||||
use syn::{parse_macro_input, PatIdent, Receiver};
|
||||
use syn::{Error};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Method {
|
||||
name: syn::Ident,
|
||||
args: Vec<syn::FnArg>,
|
||||
memoizable: bool,
|
||||
meta_info: bool,
|
||||
ret: syn::ReturnType,
|
||||
meta_ret: syn::ReturnType,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TraitPat {
|
||||
methods: Vec<(syn::Ident, Vec<syn::FnArg>, syn::ReturnType)>,
|
||||
methods: Vec<Method>,
|
||||
}
|
||||
|
||||
fn methods_to_pat(trait_item: &ItemTrait) -> syn::Result<TraitPat> {
|
||||
fn method_args(method: &syn::TraitItemMethod) -> syn::Result<Vec<syn::FnArg>> {
|
||||
if method.sig.inputs.is_empty() {
|
||||
return Err(Error::new(method.sig.ident.span(), "expected `&self`"));
|
||||
}
|
||||
|
||||
match &method.sig.inputs[0] {
|
||||
syn::FnArg::Receiver(Receiver {
|
||||
mutability: None,
|
||||
self_token: _,
|
||||
reference: Some(_),
|
||||
..
|
||||
}) => {}
|
||||
id => return Err(Error::new(id.span(), "expected `&self`")),
|
||||
}
|
||||
|
||||
let mut iter = method.sig.inputs.iter();
|
||||
iter.next();
|
||||
|
||||
Ok(iter.cloned().collect())
|
||||
}
|
||||
|
||||
fn methods_to_pat(trait_item: &mut ItemTrait) -> syn::Result<TraitPat> {
|
||||
let mut pat = TraitPat { methods: Vec::new() };
|
||||
for item in &trait_item.items {
|
||||
for item in &mut trait_item.items {
|
||||
match item {
|
||||
syn::TraitItem::Method(method) => {
|
||||
if method.sig.inputs.is_empty() {
|
||||
return Err(Error::new(method.sig.ident.span(), "expected `&self`"));
|
||||
}
|
||||
match method.sig.inputs[0] {
|
||||
syn::FnArg::Receiver(Receiver {
|
||||
mutability: None,
|
||||
self_token: _,
|
||||
reference: Some(_),
|
||||
..
|
||||
}) => {}
|
||||
_ => return Err(Error::new(method.sig.ident.span(), "expected `&self`")),
|
||||
}
|
||||
let mut method_args = Vec::new();
|
||||
for i in 1..method.sig.inputs.len() {
|
||||
method_args.push(method.sig.inputs[i].clone())
|
||||
let mut memoizable = false;
|
||||
let mut meta_info = false;
|
||||
for attr in &method.attrs {
|
||||
let span = attr.path.span();
|
||||
match attr.path.get_ident() {
|
||||
Some(path) => {
|
||||
if path == &Ident::new("memoize", Span::call_site()) {
|
||||
memoizable = true;
|
||||
} else if path == &Ident::new("memoize_info", Span::call_site()) {
|
||||
meta_info = true;
|
||||
memoizable = true;
|
||||
} else {
|
||||
return Err(Error::new(span, "unrecognized query attribute"));
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::new(span, "invalid query attribute")),
|
||||
}
|
||||
}
|
||||
method.attrs = Vec::new();
|
||||
let args = method_args(method)?;
|
||||
let name = method.sig.ident.clone();
|
||||
pat.methods.push((name, method_args, method.sig.output.clone()))
|
||||
|
||||
let old = method.sig.output.clone();
|
||||
|
||||
if meta_info {
|
||||
match &mut method.sig.output {
|
||||
syn::ReturnType::Default => method.sig.output = parse_quote!(quote! { -> ((), bool) }),
|
||||
syn::ReturnType::Type(_, ty) => *ty = Box::new(parse_quote!((#ty, bool))),
|
||||
}
|
||||
}
|
||||
|
||||
pat.methods.push(Method {
|
||||
name,
|
||||
args,
|
||||
memoizable,
|
||||
ret: old,
|
||||
meta_info,
|
||||
meta_ret: method.sig.output.clone(),
|
||||
})
|
||||
}
|
||||
_ => return Err(Error::new(trait_item.ident.span(), "can only process methods")),
|
||||
}
|
||||
@ -39,119 +96,103 @@ fn methods_to_pat(trait_item: &ItemTrait) -> syn::Result<TraitPat> {
|
||||
Ok(pat)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn make_provider(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let mut ast: ItemTrait = parse_macro_input!(input);
|
||||
fn append_ident(ident: &syn::Ident, str: &str) -> syn::Ident {
|
||||
syn::Ident::new(&format!("{}{}", ident, str), ident.span())
|
||||
}
|
||||
|
||||
let cache = syn::Ident::new(&format!("{}Cache", ast.ident), ast.ident.span());
|
||||
let provider = syn::Ident::new(&format!("{}Provider", ast.ident), ast.ident.span());
|
||||
let store = syn::Ident::new(&format!("{}Database", ast.ident), ast.ident.span());
|
||||
let ident = ast.ident.clone();
|
||||
|
||||
let pat = match methods_to_pat(&ast) {
|
||||
Ok(res) => res,
|
||||
Err(err) => return err.to_compile_error().into(),
|
||||
};
|
||||
fn mk_ident(ident: &str) -> syn::Ident {
|
||||
syn::Ident::new(ident, Span::call_site())
|
||||
}
|
||||
|
||||
fn make_cache_struct(pat: &TraitPat, ident_cache: &syn::Ident) -> syn::Result<TknStream> {
|
||||
let mut defs = Vec::new();
|
||||
|
||||
for (ident, _, ret) in &pat.methods {
|
||||
match ret {
|
||||
syn::ReturnType::Type(_, ty) => {
|
||||
defs.push(quote! {
|
||||
pub #ident: std::sync::Arc<dashmap::DashMap<u64, #ty>>,
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
let mut fields = Vec::new();
|
||||
|
||||
for (ident, args, ret) in &pat.methods {
|
||||
fields.push(quote! {
|
||||
pub #ident: fn(&#store, #(#args),*) #ret,
|
||||
});
|
||||
}
|
||||
|
||||
let mut impls = Vec::new();
|
||||
|
||||
for i in 0..pat.methods.len() {
|
||||
let mut new_args: Vec<PatIdent> = Vec::new();
|
||||
let (ident, args, ret) = &pat.methods[i];
|
||||
|
||||
for arg in args {
|
||||
match arg {
|
||||
syn::FnArg::Typed(syn::PatType { pat, .. }) => match *pat.clone() {
|
||||
syn::Pat::Ident(id) => new_args.push(id),
|
||||
_ => return quote! {compile_error!("pattern type not supported yet"); }.into(),
|
||||
},
|
||||
_ => return quote! {compile_error!("cannot use &self in the middle of parameters yet"); }.into(),
|
||||
for Method { ret, memoizable, name, .. } in &pat.methods {
|
||||
if let syn::ReturnType::Type(_, ty) = ret {
|
||||
if *memoizable {
|
||||
defs.push(quote! {
|
||||
pub #name: std::sync::Arc<dashmap::DashMap<u64, #ty>>,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impls.push(quote! {
|
||||
fn #ident(&self, #(#args),*) #ret {
|
||||
self.run_query((#(#new_args)* as u64), self.cache.#ident.clone(), #i as u8, |db| {
|
||||
(db.provider.#ident)(db, #(#new_args),*)
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for entry in &mut ast.items {
|
||||
match entry {
|
||||
syn::TraitItem::Method(met) => {
|
||||
met.attrs = Vec::new();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
let mut match_fields = Vec::new();
|
||||
|
||||
for i in 0..pat.methods.len() {
|
||||
let (ident, _, _) = &pat.methods[i];
|
||||
let u = i as u8;
|
||||
match_fields.push(quote! {
|
||||
#u => {self.cache.#ident.remove(&hash);},
|
||||
});
|
||||
}
|
||||
|
||||
quote! {
|
||||
#ast
|
||||
|
||||
let struct_quoted = quote! {
|
||||
#[derive(Default)]
|
||||
pub struct #cache {
|
||||
pub struct #ident_cache {
|
||||
#(#defs)*
|
||||
}
|
||||
};
|
||||
|
||||
pub struct #provider {
|
||||
Ok(struct_quoted)
|
||||
}
|
||||
|
||||
fn make_provider_struct(pat: &TraitPat, ident_provider: &syn::Ident, ident_store: &syn::Ident) -> syn::Result<TknStream> {
|
||||
let mut fields = Vec::new();
|
||||
|
||||
for Method { name, args, ret, .. } in &pat.methods {
|
||||
fields.push(quote! {
|
||||
pub #name: fn(&#ident_store, #(#args),*) #ret,
|
||||
});
|
||||
}
|
||||
|
||||
let quoted = quote! {
|
||||
pub struct #ident_provider {
|
||||
#(#fields)*
|
||||
}
|
||||
};
|
||||
|
||||
Ok(quoted)
|
||||
}
|
||||
|
||||
fn make_storage_struct(pat: &TraitPat, ident_provider: &syn::Ident, ident_cache: &syn::Ident, ident_storage: &syn::Ident, conf: Option<syn::Path>) -> syn::Result<TknStream> {
|
||||
let mut match_fields = Vec::new();
|
||||
|
||||
for i in 0..pat.methods.iter().filter(|e| e.memoizable).count() {
|
||||
let Method { name, .. } = &pat.methods[i];
|
||||
let u = i as u8;
|
||||
match_fields.push(quote! {
|
||||
#u => {self.cache.#name.remove(&hash);},
|
||||
});
|
||||
}
|
||||
|
||||
let config = match &conf {
|
||||
Some(res) => quote! { config: #res },
|
||||
None => quote! {},
|
||||
};
|
||||
|
||||
let conf_def = match conf {
|
||||
Some(_) => quote! { config },
|
||||
None => quote! {},
|
||||
};
|
||||
|
||||
let res = quote! {
|
||||
#[derive(Clone)]
|
||||
pub struct #store {
|
||||
provider: std::sync::Arc<#provider>,
|
||||
cache: std::sync::Arc<#cache>,
|
||||
dep_graph: crate::graph::DepGraph,
|
||||
pub struct #ident_storage {
|
||||
provider: std::sync::Arc<#ident_provider>,
|
||||
cache: std::sync::Arc<#ident_cache>,
|
||||
dep_graph: crate::core::graph::DepGraph,
|
||||
input_hash: u64,
|
||||
parent: Option<u64>
|
||||
parent: Option<u64>,
|
||||
#config
|
||||
}
|
||||
|
||||
impl #store {
|
||||
pub fn new(provider: std::sync::Arc<#provider>) -> #store {
|
||||
#store {
|
||||
impl #ident_storage {
|
||||
pub fn new(provider: std::sync::Arc<#ident_provider>, #config) -> #ident_storage {
|
||||
#ident_storage {
|
||||
provider,
|
||||
cache: Default::default(),
|
||||
dep_graph: Default::default(),
|
||||
input_hash: Default::default(),
|
||||
parent: None,
|
||||
#conf_def
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::store::Session for #store {
|
||||
use crate::core::store::Session;
|
||||
|
||||
impl crate::core::store::Session for #ident_storage {
|
||||
fn delete_from_cache(&self, hash: u64, db_idx: u8) {
|
||||
match db_idx {
|
||||
#(#match_fields)*
|
||||
@ -167,14 +208,128 @@ pub fn make_provider(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
self.parent = Some(hash);
|
||||
}
|
||||
|
||||
fn dependency_graph(&self) -> crate::graph::DepGraph {
|
||||
fn dependency_graph(&self) -> crate::core::graph::DepGraph {
|
||||
self.dep_graph.clone()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
impl #ident for #store {
|
||||
#(#impls)*
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn make_impl(pat: &TraitPat, ident: &syn::Ident, ident_storage: &syn::Ident) -> syn::Result<TknStream> {
|
||||
let mut impls = Vec::new();
|
||||
|
||||
let mut counter = 0;
|
||||
for i in 0..pat.methods.len() {
|
||||
let mut new_args: Vec<PatIdent> = Vec::new();
|
||||
let Method {
|
||||
name,
|
||||
args,
|
||||
memoizable,
|
||||
ret,
|
||||
meta_info,
|
||||
meta_ret,
|
||||
..
|
||||
} = &pat.methods[i];
|
||||
|
||||
for arg in args {
|
||||
match arg {
|
||||
syn::FnArg::Typed(syn::PatType { pat, .. }) => match *pat.clone() {
|
||||
syn::Pat::Ident(id) => new_args.push(id),
|
||||
pat => return Err(Error::new(pat.span(), "pattern matching not supported yet")),
|
||||
},
|
||||
pat => return Err(Error::new(pat.span(), "cannot use self in this position")),
|
||||
}
|
||||
}
|
||||
|
||||
let run_memoized = mk_ident("run_query_memoized");
|
||||
let run_flat = mk_ident("run_query_flat");
|
||||
|
||||
let meta = if *meta_info {
|
||||
quote! {}
|
||||
} else {
|
||||
quote! { .0 }
|
||||
};
|
||||
|
||||
if *memoizable {
|
||||
impls.push(quote! {
|
||||
fn #name(&self, #(#args),*) #meta_ret {
|
||||
self.#run_memoized(fxhash::hash64(&(#i+1, #(&#new_args),*)), self.cache.#name.clone(), #counter as u8, |db| {
|
||||
(db.provider.#name)(db, #(#new_args),*)
|
||||
})#meta
|
||||
}
|
||||
});
|
||||
counter += 1;
|
||||
} else {
|
||||
impls.push(quote! {
|
||||
fn #name(&self, #(#args),*) #ret {
|
||||
self.#run_flat(fxhash::hash64(&(#i+1, #(&#new_args),*)), |db| {
|
||||
(db.provider.#name)(db, #(#new_args),*)
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
.into()
|
||||
|
||||
Ok(quote! {
|
||||
impl #ident for #ident_storage {
|
||||
#(#impls)*
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn make_provider_strutures(ast: &mut ItemTrait, ident: &syn::Ident, attr_vec: Vec<syn::NestedMeta>) -> syn::Result<TknStream> {
|
||||
let cache = append_ident(ident, "Cache");
|
||||
let provider = append_ident(ident, "Provider");
|
||||
let storage = append_ident(ident, "Database");
|
||||
let trait_pat = methods_to_pat(ast)?;
|
||||
let attr = parse_config(attr_vec)?;
|
||||
|
||||
let cache_struct = make_cache_struct(&trait_pat, &cache)?;
|
||||
let provider_struct = make_provider_struct(&trait_pat, &provider, &storage)?;
|
||||
let storage_struct = make_storage_struct(&trait_pat, &provider, &cache, &storage, attr)?;
|
||||
|
||||
let impl_for_struct = make_impl(&trait_pat, ident, &storage)?;
|
||||
|
||||
let res = quote! {
|
||||
#ast
|
||||
#cache_struct
|
||||
#provider_struct
|
||||
#storage_struct
|
||||
#impl_for_struct
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn parse_config(ast: Vec<syn::NestedMeta>) -> syn::Result<Option<syn::Path>> {
|
||||
if ast.len() == 1 {
|
||||
let ast = &ast[0];
|
||||
match ast {
|
||||
syn::NestedMeta::Meta(meta) => match meta {
|
||||
syn::Meta::Path(path) => Ok(Some(path.clone())),
|
||||
_ => Err(Error::new(ast.span(), "cannot use type")),
|
||||
},
|
||||
syn::NestedMeta::Lit(_) => Err(Error::new(ast.span(), "cannot parse type")),
|
||||
}
|
||||
} else if ast.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Err(Error::new(Span::call_site(), "too many arguments for the attribute"))
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn make_provider(attr_inp: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let mut ast: ItemTrait = parse_macro_input!(input);
|
||||
|
||||
for attr in &ast.attrs {
|
||||
println!("{:?}", attr);
|
||||
}
|
||||
|
||||
let ident = ast.ident.clone();
|
||||
make_provider_strutures(&mut ast, &ident, parse_macro_input!(attr_inp))
|
||||
.map_or_else(|x| x.into_compile_error(), |x| x)
|
||||
.into()
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use kind_report::data::{DiagnosticFrame, Marking, Severity, Color};
|
||||
use kind_report::data::{Color, DiagnosticFrame, Marking, Severity};
|
||||
use kind_span::Range;
|
||||
|
||||
use crate::lexer::tokens::Token;
|
||||
@ -49,12 +49,12 @@ impl From<Box<SyntaxError>> for DiagnosticFrame {
|
||||
SyntaxError::LowerCasedDefinition(name, range) => DiagnosticFrame {
|
||||
code: 0,
|
||||
severity: Severity::Error,
|
||||
title: "The definition name should be upper cased.".to_string(),
|
||||
title: "The definition name must be capitalized.".to_string(),
|
||||
subtitles: vec![],
|
||||
hints: vec![{
|
||||
let mut c = name.chars();
|
||||
let fst = c.next().unwrap().to_uppercase();
|
||||
format!("Change it to '{}{}'", fst, c.as_str()).to_string()
|
||||
format!("Change it to '{}{}'", fst, c.as_str())
|
||||
}],
|
||||
positions: vec![Marking {
|
||||
position: range,
|
||||
@ -74,20 +74,18 @@ impl From<Box<SyntaxError>> for DiagnosticFrame {
|
||||
text: "The comment starts in this position!".to_string(),
|
||||
}],
|
||||
},
|
||||
SyntaxError::InvalidEscapeSequence(kind, range) => {
|
||||
DiagnosticFrame {
|
||||
code: 0,
|
||||
severity: Severity::Error,
|
||||
title: format!("The {} character sequence is invalid!", encode_name(kind)),
|
||||
subtitles: vec![],
|
||||
hints: vec![],
|
||||
positions: vec![Marking {
|
||||
position: range,
|
||||
color: Color::Fst,
|
||||
text: "Here!".to_string(),
|
||||
}],
|
||||
}
|
||||
}
|
||||
SyntaxError::InvalidEscapeSequence(kind, range) => DiagnosticFrame {
|
||||
code: 0,
|
||||
severity: Severity::Error,
|
||||
title: format!("The {} character sequence is invalid!", encode_name(kind)),
|
||||
subtitles: vec![],
|
||||
hints: vec![],
|
||||
positions: vec![Marking {
|
||||
position: range,
|
||||
color: Color::Fst,
|
||||
text: "Here!".to_string(),
|
||||
}],
|
||||
},
|
||||
SyntaxError::InvalidNumberRepresentation(repr, range) => DiagnosticFrame {
|
||||
code: 0,
|
||||
severity: Severity::Error,
|
||||
@ -132,4 +130,4 @@ impl From<&Box<SyntaxError>> for DiagnosticFrame {
|
||||
fn from(err: &Box<SyntaxError>) -> Self {
|
||||
(err.clone()).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,6 @@ impl<'a> Parser<'a> {
|
||||
Ok(ident)
|
||||
}
|
||||
|
||||
|
||||
fn parse_lambda(&mut self) -> Result<Box<Expr>, SyntaxError> {
|
||||
let name_span = self.range();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use kind_span::{Range};
|
||||
use kind_span::Range;
|
||||
|
||||
use crate::errors::{EncodeSequence, SyntaxError};
|
||||
use crate::lexer::tokens::Token;
|
||||
|
@ -45,12 +45,12 @@ impl<'a> Lexer<'a> {
|
||||
"open" => Token::Open,
|
||||
"return" => Token::Return,
|
||||
_ => {
|
||||
if data.bytes().next().map(|x| x.is_ascii_uppercase()).unwrap_or(false) {
|
||||
Token::UpperId(data.to_string())
|
||||
}else {
|
||||
Token::LowerId(data.to_string())
|
||||
}
|
||||
},
|
||||
if data.bytes().next().map(|x| x.is_ascii_uppercase()).unwrap_or(false) {
|
||||
Token::UpperId(data.to_string())
|
||||
} else {
|
||||
Token::LowerId(data.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ use std::{iter::Peekable, str::Chars};
|
||||
|
||||
use kind_span::{Pos, Range, SyntaxCtxIndex};
|
||||
|
||||
use crate::{lexer::tokens::Token};
|
||||
use crate::lexer::tokens::Token;
|
||||
|
||||
/// The lexer state.
|
||||
pub struct Lexer<'a> {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use kind_tree::concrete::pat::{Pat, PatKind};
|
||||
use kind_tree::concrete::pat::{Pat, PatKind, PatIdent};
|
||||
|
||||
use crate::errors::SyntaxError;
|
||||
use crate::lexer::tokens::Token;
|
||||
@ -56,7 +56,7 @@ impl<'a> Parser<'a> {
|
||||
let id = self.parse_id()?;
|
||||
Ok(Box::new(Pat {
|
||||
range: id.range,
|
||||
data: PatKind::Var(id),
|
||||
data: PatKind::Var(PatIdent(id)),
|
||||
}))
|
||||
}
|
||||
|
||||
@ -68,7 +68,6 @@ impl<'a> Parser<'a> {
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
fn parse_pat_list(&mut self) -> Result<Box<Pat>, SyntaxError> {
|
||||
let range = self.range();
|
||||
self.bump(); // '['
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use kind_span::{Range};
|
||||
use kind_span::Range;
|
||||
|
||||
use crate::{errors::SyntaxError, lexer::tokens::Token, Lexer};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/// Parses all of the top level structures
|
||||
/// like Book, Entry, Rule and Argument.
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap};
|
||||
|
||||
use kind_tree::concrete::{Argument, Book, Entry, Rule};
|
||||
|
||||
@ -13,16 +13,17 @@ fn is_hidden_arg(token: &Token) -> bool {
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn is_top_level_entry(&self) -> bool {
|
||||
self.get().is_upper_id() && (
|
||||
self.peek(1).same_variant(Token::Colon) // ':'
|
||||
pub fn is_top_level_entry_continuation(&self) -> bool {
|
||||
self.peek(1).same_variant(Token::Colon) // ':'
|
||||
| self.peek(1).same_variant(Token::LPar) // '('
|
||||
| self.peek(1).same_variant(Token::Less) // '<'
|
||||
| self.peek(1).same_variant(Token::Minus) // '-'
|
||||
| self.peek(1).same_variant(Token::Plus) // '+'
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_top_level_entry(&self) -> bool {
|
||||
self.get().is_upper_id() && self.is_top_level_entry_continuation()
|
||||
}
|
||||
|
||||
pub fn complement_binding_op(&self) -> Option<Token> {
|
||||
match self.get() {
|
||||
@ -88,17 +89,16 @@ impl<'a> Parser<'a> {
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_entry(&mut self) -> Result<Box<Entry>, SyntaxError> {
|
||||
pub fn parse_entry(&mut self) -> Result<Entry, SyntaxError> {
|
||||
let start = self.range();
|
||||
|
||||
if self.get().is_lower_id() {
|
||||
if self.get().is_lower_id() && self.is_top_level_entry_continuation() {
|
||||
let ident = self.parse_id()?;
|
||||
return Err(SyntaxError::LowerCasedDefinition(ident.data.0, ident.range));
|
||||
}
|
||||
|
||||
// Just to make errors more localized
|
||||
if !self.is_top_level_entry() {
|
||||
println!("{:?} {:?}", self.get(), self.peek(1));
|
||||
self.fail(vec![])?
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
let end = rules.last().as_ref().map(|x| x.range).unwrap_or(tipo.range);
|
||||
Ok(Box::new(Entry {
|
||||
Ok(Entry {
|
||||
name: ident,
|
||||
docs,
|
||||
args,
|
||||
@ -130,18 +130,18 @@ impl<'a> Parser<'a> {
|
||||
rules,
|
||||
attrs: Vec::new(),
|
||||
range: start.mix(end),
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_book(&mut self) -> Book {
|
||||
let mut entrs = HashMap::new();
|
||||
let mut entries = HashMap::new();
|
||||
let mut names = Vec::new();
|
||||
while !self.get().same_variant(Token::Eof) {
|
||||
match self.parse_entry() {
|
||||
Ok(entry) => {
|
||||
if entrs.get(&entry.name.data.0).is_none() {
|
||||
if entries.get(&entry.name.data.0).is_none() {
|
||||
names.push(entry.name.clone());
|
||||
entrs.insert(entry.name.data.0.clone(), entry);
|
||||
entries.insert(entry.name.data.0.clone(), entry);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
@ -156,9 +156,9 @@ impl<'a> Parser<'a> {
|
||||
|
||||
match res {
|
||||
Ok(_) => (),
|
||||
Err(err) => self.errs.push(Box::new(err))
|
||||
Err(err) => self.errs.push(Box::new(err)),
|
||||
}
|
||||
|
||||
Book { names, entrs }
|
||||
Book { entries, names }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user