1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
//! Defines Carlo language tokens.
use std::fmt;
#[derive(Clone, Debug)]
/// A Carlo language token.
pub struct Token {
pub class: TokenClass,
pub value: String,
}
impl Token {
/// Constructs a new token.
pub fn new(class: TokenClass, value: String) -> Self {
Self {
class,
value,
}
}
/// Checks if this token is of a given class.
pub fn check(&self, class: TokenClass) -> bool {
self.class == class
}
/// Gets the precedence of this token.
pub fn precedence(&self) -> u8 {
self.class.into()
}
}
impl fmt::Display for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, \"{}\")", self.class, self.value)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
/// Enumerates the classes of Carlo langauge tokens.
pub enum TokenClass {
/// Let
Let,
/// Identifier
Identifier,
/// Assignment operator
Assignment,
/// Addition
Plus,
/// Subtraction
Minus,
/// Multiplication
Times,
/// Division
Divide,
/// Number
Number,
/// Unknown
Unknown,
}
impl From<TokenClass> for u8 {
fn from(class: TokenClass) -> Self {
use TokenClass::*;
match class {
Let => 1,
Identifier => 0,
Assignment => 1,
Number => 0,
Unknown => 0,
Plus => 2,
Minus => 2,
Times => 3,
Divide => 3,
}
}
}
/// Maps characters to classes of tokens that may
/// begin with this character.
impl From<char> for TokenClass {
fn from(c: char) -> Self {
use TokenClass::*;
match c {
'a'..='z' | 'A'..='Z' | '_' => Identifier,
'=' => Assignment,
'+' => Plus,
'-' => Minus,
'*' => Times,
'/' => Divide,
'0'..='9' => Number,
_ => Unknown,
}
}
}
impl fmt::Display for TokenClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use TokenClass::*;
let string = match self {
Let => "Let",
Identifier => "Identifier",
Assignment => "Assignment",
Number => "Number",
Unknown => "Unknown",
Plus => "Plus",
Minus => "Minus",
Times => "Times",
Divide => "Divide",
};
write!(f, "{}", string)
}
}