use std::fmt::{Display, Formatter, Error};
use std::str::FromStr;
use base::code::Span;
macro_rules! gen_helper {
(
$name:ident; ;
$($variant:ident = $val:expr),+
) => { };
(
$name:ident;
$helper:ident $(, $tail:ident)*;
$($variant:ident = $val:expr),+
) => {
$helper!($name; $($variant = $val),+ );
gen_helper!($name; $($tail),*; $($variant = $val),+);
};
}
macro_rules! gen_enum {
(
$(#[$attr:meta])*
pub enum $name:ident;
with $($helper:ident),* for:
$($variant:ident = $val:expr),+
) => {
$(
#[$attr]
)*
pub enum $name {
$($variant,)*
}
gen_helper!($name; $($helper),*; $( $variant = $val ),+);
}
}
macro_rules! to_java_string {
($name:ident; $($variant:ident = $val:expr),+) => {
impl $name {
pub fn as_java_string(&self) -> &str {
match self {
$( &$name::$variant => $val ,)*
}
}
}
}
}
macro_rules! into_str {
($name:ident; $($variant:ident = $val:expr),+) => {
impl Into<String> for $name {
fn into(self) -> String {
self.as_java_string().into()
}
}
}
}
macro_rules! display {
($name:ident; $($variant:ident = $val:expr),+) => {
impl Display for $name {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
self.as_java_string().fmt(f)
}
}
}
}
macro_rules! from_str {
($name:ident; $($variant:ident = $val:expr),+) => {
impl FromStr for $name {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
$($val => Ok($name::$variant), )*
_ => Err(()),
}
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TokenSpan {
pub tok: Token,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Token {
Whitespace,
Comment,
Ident(String),
KeyW(Keyword),
Literal(Lit),
ParenOp,
ParenCl,
BraceOp,
BraceCl,
BracketOp,
BracketCl,
Semi,
Comma,
Dot,
DotDotDot,
At,
ColonSep,
Eq,
Gt,
Lt,
Bang,
Tilde,
Question,
Colon,
Arrow,
EqEq,
Ge,
Le,
Ne,
AndAnd,
OrOr,
PlusPlus,
MinusMinus,
Plus,
Minus,
Star,
Slash,
And,
Or,
Caret,
Percent,
Shl,
Shr,
ShrUn,
PlusEq,
MinusEq,
StarEq,
SlashEq,
AndEq,
OrEq,
CaretEq,
PercentEq,
ShlEq,
ShrEq,
ShrUnEq,
}
impl Token {
pub fn is_real(&self) -> bool {
match *self {
Token::Whitespace | Token::Comment => false,
_ => true,
}
}
pub fn as_java_string(&self) -> &str {
use self::Token::*;
match *self {
Whitespace => "whitespace",
Comment => "comment",
Ident(_) => "identifier",
KeyW(ref keyword) => keyword.as_java_string(),
Literal(ref lit) => lit.as_java_string(),
ParenOp => "(",
ParenCl => ")",
BraceOp => "{",
BraceCl => "}",
BracketOp => "[",
BracketCl => "]",
Semi => ";",
Comma => ",",
Dot => ".",
DotDotDot => "...",
At => "@",
ColonSep => "::",
Eq => "=",
Gt => ">",
Lt => "<",
Bang => "!",
Tilde => "~",
Question => "?",
Colon => ":",
Arrow => "->",
EqEq => "==",
Ge => ">=",
Le => "<=",
Ne => "!=",
AndAnd => "&&",
OrOr => "||",
PlusPlus => "++",
MinusMinus => "--",
Plus => "+",
Minus => "-",
Star => "*",
Slash => "/",
And => "&",
Or => "|",
Caret => "^",
Percent => "%",
Shl => "<<",
Shr => ">>",
ShrUn => ">>>",
PlusEq => "+=",
MinusEq => "-=",
StarEq => "*=",
SlashEq => "/=",
AndEq => "&=",
OrEq => "|=",
CaretEq => "^=",
PercentEq => "%=",
ShlEq => "<<=",
ShrEq => ">>=",
ShrUnEq => ">>>=",
}
}
}
impl Display for Token {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}", self.as_java_string())
}
}
gen_enum! {
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Keyword;
with to_java_string, display, from_str, into_str for:
Abstract = "abstract",
Assert = "assert",
Boolean = "boolean",
Break = "break",
Byte = "byte",
Case = "case",
Catch = "catch",
Char = "char",
Class = "class",
Const = "const",
Continue = "continue",
Default = "default",
Do = "do",
Double = "double",
Else = "else",
Enum = "enum",
Extends = "extends",
Final = "final",
Finally = "finally",
Float = "float",
For = "for",
If = "if",
Goto = "goto",
Implements = "implements",
Import = "import",
Instanceof = "instanceof",
Int = "int",
Interface = "interface",
Long = "long",
Native = "native",
New = "new",
Package = "package",
Private = "private",
Protected = "protected",
Public = "public",
Return = "return",
Short = "short",
Static = "static",
Strictfp = "strictfp",
Super = "super",
Switch = "switch",
Synchronized = "synchronized",
This = "this",
Throw = "throw",
Throws = "throws",
Transient = "transient",
Try = "try",
Void = "void",
Volatile = "volatile",
While = "while"
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Lit {
Str(String),
Char(char),
Integer {
raw: String,
is_long: bool,
radix: u8
},
Float {
raw: String,
is_double: bool,
radix: u8,
exp: String
},
Null,
Bool(bool),
}
impl Lit {
pub fn as_java_string(&self) -> &str {
match *self {
Lit::Str(_) => "string literal",
Lit::Char(_) => "character literal",
Lit::Integer { .. } => "integer literal",
Lit::Float { .. } => "floating point literal",
Lit::Null => "null literal",
Lit::Bool(_) => "boolean literal",
}
}
}