#![allow(dead_code, unused_variables)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![recursion_limit = "1024"]
use std::fmt;
#[macro_use]
extern crate error_chain;
pub mod error;
mod index_str;
use error::{ErrorKind, Result};
use index_str::IndexStr;
#[macro_use]
mod testing;
pub type OwnedSymbol = Symbol<Vec<u8>>;
pub type BorrowedSymbol<'a> = Symbol<&'a [u8]>;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Symbol<T> {
raw: T,
parsed: MangledName,
}
impl<T> Symbol<T>
where T: AsRef<[u8]>
{
pub fn new(raw: T) -> Result<Symbol<T>> {
let input = IndexStr::new(raw.as_ref());
let _ = input;
unimplemented!()
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct MangledName(usize, Encoding);
impl MangledName {
fn parse(input: IndexStr) -> Result<(MangledName, IndexStr)> {
unimplemented!()
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum Encoding {
Function(Name, BareFunctionType),
Data(Name),
Special(SpecialName),
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum Name {
Nested(NestedName),
Unscoped(UnscopedName),
UnscopedTemplate(UnscopedTemplateName, TemplateArgs),
Local(LocalName),
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum UnscopedName {
Unqualified(UnqualifiedName),
Std(UnqualifiedName),
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum UnscopedTemplateName {
Unscoped(UnscopedName),
Substitution(Substitution),
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum NestedName {
Unqualified(CvQualifiers, RefQualifier, Prefix, UnqualifiedName),
Template(CvQualifiers, RefQualifier, TemplatePrefix, TemplateArgs),
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum Prefix {
Unqualified(UnqualifiedName, Option<PrefixTail>),
Template(TemplatePrefix, TemplateArgs, Option<PrefixTail>),
TemplateParam(TemplateParam, Option<PrefixTail>),
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Substitution(Option<SeqId>);
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct BareFunctionType(Type);
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct SeqId(usize);
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Type;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct SpecialName;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct TemplateArgs;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct LocalName;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct UnqualifiedName;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct CvQualifiers;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RefQualifier;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct TemplatePrefix;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct PrefixTail;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct TemplateParam;
macro_rules! define_vocabulary {
( $typename:ident { $($variant:ident ( $mangled:pat, $printable:expr )),* } ) => {
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
enum $typename {
$(
#[doc=$printable]
$variant
),*
}
impl $typename {
fn parse(input: IndexStr) -> Result<($typename, IndexStr)> {
let (head, tail) = match input.try_split_at(2) {
Some((head, tail)) => (head, tail),
None => {
return Err(ErrorKind::UnexpectedEnd.into());
}
};
let name = match head.as_ref() {
$(
$mangled => $typename::$variant,
)*
_ => {
return Err(ErrorKind::UnexpectedText.into());
}
};
Ok((name, tail))
}
}
impl fmt::Display for $typename {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match *self {
$(
$typename::$variant => $printable
),*
})
}
}
}
}
define_vocabulary! {
OperatorName {
New (b"nw", "`new`"),
NewArray (b"na", "`new[]`"),
Delete (b"dl", "`delete`"),
DeleteArray (b"da", "`delete[]`"),
UnaryPlus (b"ps", "`+` (unary)"),
Neg (b"ng", "`-` (unary)"),
AddressOf (b"ad", "`&` (unary)"),
Deref (b"de", "`*` (unary)"),
BitNot (b"co", "`~`"),
Add (b"pl", "`+`"),
Sub (b"mi", "`-`"),
Mul (b"ml", "`*`"),
Div (b"dv", "`/`"),
Rem (b"rm", "`%`"),
BitAnd (b"an", "`&`"),
BitOr (b"or", "`|`"),
BitXor (b"eo", "`^`"),
Assign (b"aS", "`=`"),
AddAssign (b"pL", "`+=`"),
SubAssign (b"mI", "`-=`"),
MulAssign (b"mL", "`*=`"),
DivAssign (b"dV", "`/=`"),
RemAssign (b"rM", "`%=`"),
BitAndAssign (b"aN", "`&=`"),
BitOrAssign (b"oR", "`|=`"),
BitXorAssign (b"eO", "`^=`"),
Shl (b"ls", "`<<`"),
Shr (b"rs", "`>>`"),
ShlAssign (b"lS", "`<<=`"),
ShrAssign (b"rS", "`>>=`"),
Eq (b"eq", "`==`"),
Ne (b"ne", "`!=`"),
Less (b"lt", "`<`"),
Greater (b"gt", "`>`"),
LessEq (b"le", "`<=`"),
GreaterEq (b"ge", "`>=`"),
Not (b"nt", "`!`"),
LogicalAnd (b"aa", "`&&`"),
LogicalOr (b"oo", "`||`"),
PostInc (b"pp", "`++` (postfix in <expression> context)"),
PostDec (b"mm", "`--` (postfix in <expression> context)"),
Comma (b"cm", "`,`"),
DerefMemberPtr (b"pm", "`->*`"),
DerefMember (b"pt", "`->`"),
Call (b"cl", "`()`"),
Index (b"ix", "`[]`"),
Question (b"qu", "`?:`")
}
}
define_vocabulary! {
CtorDtorName {
CompleteConstructor (b"C1", "complete object constructor"),
BaseConstructor (b"C2", "base object constructor"),
CompleteAllocatingConstructor (b"C3", "complete object allocating constructor"),
DeletingDestructor (b"D0", "deleting destructor"),
CompleteDestructor (b"D1", "complete object destructor"),
BaseDestructor (b"D2", "base object destructor")
}
}
#[cfg(test)]
mod tests {
use super::{CtorDtorName, OperatorName};
use error::ErrorKind;
#[test]
fn parse_ctor_dtor_name() {
assert_parse!(CtorDtorName: b"D0" => Ok(CtorDtorName::DeletingDestructor, b""));
assert_parse!(CtorDtorName: b"C101" => Ok(CtorDtorName::CompleteConstructor, b"01"));
assert_parse!(CtorDtorName: b"gayagaya" => Err(ErrorKind::UnexpectedText));
assert_parse!(CtorDtorName: b"C" => Err(ErrorKind::UnexpectedEnd));
assert_parse!(CtorDtorName: b"" => Err(ErrorKind::UnexpectedEnd));
}
#[test]
fn parse_operator_name() {
assert_parse!(OperatorName: b"qu" => Ok(OperatorName::Question, b""));
assert_parse!(OperatorName: b"quokka" => Ok(OperatorName::Question, b"okka"));
assert_parse!(OperatorName: b"bu-buuu" => Err(ErrorKind::UnexpectedText));
assert_parse!(OperatorName: b"b" => Err(ErrorKind::UnexpectedEnd));
assert_parse!(OperatorName: b"" => Err(ErrorKind::UnexpectedEnd));
}
}