mechylang/parser/expressions/
identifier.rs1use std::fmt;
2use std::fmt::{Display, Formatter};
3use std::rc::Rc;
4use serde::Serialize;
5use crate::parser::{Parser, Error, Result};
6use crate::{trace, TokenKind, Span};
7use crate::parser::error::Location;
8
9#[derive(Debug, Clone, PartialEq, Serialize)]
10pub struct Identifier {
11 pub span: Span,
12 pub value: Rc<str>,
13}
14
15impl Display for Identifier {
16 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
17 write!(f, "{}", self.value)
18 }
19}
20
21impl From<Identifier> for Rc<str> {
22 fn from(ident: Identifier) -> Self {
23 ident.value
24 }
25}
26impl Parser<'_> {
27
28 pub(super) fn parse_identifier(&mut self) -> Result<Identifier> {
29 let _trace = trace!("parse_identifier");
30
31 let literal = match self.cur_token.kind {
32 TokenKind::Identifier(ref literal) => literal.clone(),
33 _ => {
34 return Err(Error::UnexpectedToken {
35 span: self.cur_token.span.clone(),
36 expected: vec![TokenKind::Identifier(String::new())],
37 found: self.cur_token.kind.clone(),
38 location: Some(Location::Expression),
39 })
40 }
41 };
42
43 Ok(Identifier {
44 span: self.cur_token.span.clone(),
45 value: literal.into(),
46 })
47 }
48 }
49
50#[cfg(test)]
51mod tests {
52 use crate::parser::expressions::Expression;
53 use crate::parser::tests::parse;
54 use crate::parser::statements::Statement;
55
56 #[test]
57 fn test_identifier_expression() {
58 let input = "foobar;";
59
60 let statements = parse(input).unwrap();
61
62 let stmt = &statements[0];
63
64 match stmt {
65 Statement::Expression(ref expr) => {
66 match expr.expression {
67 Expression::Identifier(ref ident) => {
68 assert_eq!(ident.value, "foobar".into());
69 }
70 _ => panic!("expected identifier expression"),
71 };
72 }
73 _ => panic!("expected expression statement"),
74 };
75 }
76}