Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2ea90b8

Browse files
committed
Support foo_cast family
1 parent 29ad382 commit 2ea90b8

File tree

4 files changed

+237
-0
lines changed

4 files changed

+237
-0
lines changed

src/parser/errors.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::lexer::Token;
88

99
#[derive(Clone, Debug)]
1010
pub enum ParserError {
11+
// TODO: rewrite that stuff
1112
InvalidVarInDecl { sp: Span, name: String },
1213
InvalidTokenInOp { sp: Span, tok: Token },
1314
InvalidTokenInDtor { sp: Span, tok: Token },
@@ -36,6 +37,7 @@ pub enum ParserError {
3637
InvalidTokenInFor { sp: Span, tok: Token },
3738
InvalidTokenInWhile { sp: Span, tok: Token },
3839
InvalidTokenInUnit { sp: Span, tok: Token },
40+
InvalidTokenInExpr { sp: Span, tok: Token },
3941
InvalidExprInFor { sp: Span },
4042
InvalidTypeInOp { sp: Span, name: String },
4143
InvalidTypeInExpr { sp: Span, name: String },
@@ -140,6 +142,9 @@ impl ParserError {
140142
(*sp, format!("Invalid token {:?} in while statement", tok))
141143
}
142144
InvalidTokenInUnit { sp, tok } => (*sp, format!("Invalid token {:?} in CU", tok)),
145+
InvalidTokenInExpr { sp, tok } => {
146+
(*sp, format!("Invalid token {:?} in expression", tok))
147+
}
143148
InvalidExprInFor { sp } => (*sp, format!("Invalid expression in for statement")),
144149
InvalidTypeInOp { sp, name } => {
145150
(*sp, format!("Invalid type {} in conversion operator", name))

src/parser/expressions/casts.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
2+
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
3+
// http://opensource.org/licenses/MIT>, at your option. This file may not be
4+
// copied, modified, or distributed except according to those terms.
5+
6+
use std::rc::Rc;
7+
use termcolor::StandardStreamLock;
8+
9+
use crate::lexer::{TLexer, Token};
10+
use crate::parser::declarations::TypeDeclaratorParser;
11+
use crate::parser::dump::Dump;
12+
use crate::parser::errors::ParserError;
13+
use crate::parser::expressions::{ExprNode, ExpressionParser};
14+
use crate::parser::types::Type;
15+
use crate::parser::Context;
16+
17+
#[derive(Clone, Debug, PartialEq)]
18+
pub struct StaticCast {
19+
pub typ: Type,
20+
pub arg: ExprNode,
21+
}
22+
23+
#[derive(Clone, Debug, PartialEq)]
24+
pub struct DynamicCast {
25+
pub typ: Type,
26+
pub arg: ExprNode,
27+
}
28+
29+
#[derive(Clone, Debug, PartialEq)]
30+
pub struct ConstCast {
31+
pub typ: Type,
32+
pub arg: ExprNode,
33+
}
34+
35+
#[derive(Clone, Debug, PartialEq)]
36+
pub struct ReinterpretCast {
37+
pub typ: Type,
38+
pub arg: ExprNode,
39+
}
40+
41+
impl Dump for StaticCast {
42+
fn dump(&self, name: &str, prefix: &str, last: bool, stdout: &mut StandardStreamLock) {
43+
dump_obj!(self, name, "static_cast", prefix, last, stdout, typ, arg);
44+
}
45+
}
46+
47+
impl Dump for DynamicCast {
48+
fn dump(&self, name: &str, prefix: &str, last: bool, stdout: &mut StandardStreamLock) {
49+
dump_obj!(self, name, "dynamic_cast", prefix, last, stdout, typ, arg);
50+
}
51+
}
52+
53+
impl Dump for ConstCast {
54+
fn dump(&self, name: &str, prefix: &str, last: bool, stdout: &mut StandardStreamLock) {
55+
dump_obj!(self, name, "const_cast", prefix, last, stdout, typ, arg);
56+
}
57+
}
58+
59+
impl Dump for ReinterpretCast {
60+
fn dump(&self, name: &str, prefix: &str, last: bool, stdout: &mut StandardStreamLock) {
61+
dump_obj!(
62+
self,
63+
name,
64+
"reinterpret_cast",
65+
prefix,
66+
last,
67+
stdout,
68+
typ,
69+
arg
70+
);
71+
}
72+
}
73+
74+
pub(crate) struct FooCastParser<'a, L: TLexer> {
75+
lexer: &'a mut L,
76+
}
77+
78+
impl<'a, L: TLexer> FooCastParser<'a, L> {
79+
pub(crate) fn new(lexer: &'a mut L) -> Self {
80+
Self { lexer }
81+
}
82+
83+
pub(crate) fn parse(
84+
self,
85+
base_tok: Token,
86+
context: &mut Context,
87+
) -> Result<(Option<Token>, Option<ExprNode>), ParserError> {
88+
let tok = self.lexer.next_useful();
89+
if tok != Token::Lower {
90+
return Err(ParserError::InvalidTokenInExpr {
91+
sp: self.lexer.span(),
92+
tok,
93+
});
94+
}
95+
96+
let tdp = TypeDeclaratorParser::new(self.lexer);
97+
let (tok, typ) = tdp.parse(None, None, false, context)?;
98+
99+
let tok = tok.unwrap_or_else(|| self.lexer.next_useful());
100+
if tok != Token::Greater {
101+
return Err(ParserError::InvalidTokenInExpr {
102+
sp: self.lexer.span(),
103+
tok,
104+
});
105+
}
106+
107+
let typ = Rc::try_unwrap(typ.unwrap()).unwrap().typ;
108+
109+
let tok = self.lexer.next_useful();
110+
if tok != Token::LeftParen {
111+
return Err(ParserError::InvalidTokenInExpr {
112+
sp: self.lexer.span(),
113+
tok,
114+
});
115+
}
116+
117+
let mut ep = ExpressionParser::new(self.lexer, Token::RightParen);
118+
let (_, expr) = ep.parse(None, context)?;
119+
120+
let arg = expr.unwrap();
121+
122+
let node = match base_tok {
123+
Token::StaticCast => Some(ExprNode::StaticCast(Box::new(StaticCast { typ, arg }))),
124+
Token::DynamicCast => Some(ExprNode::DynamicCast(Box::new(DynamicCast { typ, arg }))),
125+
Token::ConstCast => Some(ExprNode::ConstCast(Box::new(ConstCast { typ, arg }))),
126+
Token::ReinterpretCast => Some(ExprNode::ReinterpretCast(Box::new(ReinterpretCast {
127+
typ,
128+
arg,
129+
}))),
130+
_ => None,
131+
};
132+
133+
Ok((None, node))
134+
}
135+
}

src/parser/expressions/expr.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use std::rc::Rc;
77
use termcolor::StandardStreamLock;
88

9+
use super::casts::{ConstCast, DynamicCast, FooCastParser, ReinterpretCast, StaticCast};
910
use super::list::{ListInitialization, ListInitializationParser};
1011
use super::operator::{BinaryOp, Conditional, Operator, UnaryOp};
1112
use super::params::{Parameters, ParametersParser};
@@ -108,6 +109,10 @@ pub enum ExprNode {
108109
Nullptr(Box<Nullptr>),
109110
This(Box<This>),
110111
Type(Box<Type>),
112+
StaticCast(Box<StaticCast>),
113+
DynamicCast(Box<DynamicCast>),
114+
ConstCast(Box<ConstCast>),
115+
ReinterpretCast(Box<ReinterpretCast>),
111116
}
112117

113118
impl Dump for ExprNode {
@@ -134,6 +139,10 @@ impl Dump for ExprNode {
134139
Self::Nullptr(x) => dump!(x),
135140
Self::This(x) => dump!(x),
136141
Self::Type(x) => dump!(x),
142+
Self::StaticCast(x) => dump!(x),
143+
Self::DynamicCast(x) => dump!(x),
144+
Self::ConstCast(x) => dump!(x),
145+
Self::ReinterpretCast(x) => dump!(x),
137146
}
138147
}
139148
}
@@ -995,6 +1004,15 @@ impl<'a, L: TLexer> ExpressionParser<'a, L> {
9951004
.push(ExprNode::Bool(Box::new(Bool { value: false })));
9961005
self.last = LastKind::Operand;
9971006
}
1007+
Token::StaticCast
1008+
| Token::DynamicCast
1009+
| Token::ConstCast
1010+
| Token::ReinterpretCast => {
1011+
let fcp = FooCastParser::new(self.lexer);
1012+
let (_, node) = fcp.parse(tok, context)?;
1013+
1014+
self.push_operand(node.unwrap());
1015+
}
9981016
_ => {
9991017
let dsp = DeclSpecifierParser::new(self.lexer);
10001018
let (tk, (_, typ, _, _)) = dsp.parse(Some(tok), None, context)?;
@@ -1458,4 +1476,80 @@ mod tests {
14581476

14591477
assert_eq!(node, expected);
14601478
}
1479+
1480+
#[test]
1481+
fn test_static_cast() {
1482+
let mut lexer = Lexer::<DefaultContext>::new(b"static_cast<const int>(x)");
1483+
let mut parser = ExpressionParser::new(&mut lexer, Token::Eof);
1484+
let mut context = Context::default();
1485+
let node = parser.parse(None, &mut context).unwrap().1.unwrap();
1486+
1487+
let expected = node!(StaticCast {
1488+
typ: Type {
1489+
base: BaseType::Primitive(Primitive::Int),
1490+
cv: CVQualifier::CONST,
1491+
pointers: None,
1492+
},
1493+
arg: ExprNode::Variable(Box::new(mk_var!("x"))),
1494+
});
1495+
1496+
assert_eq!(node, expected);
1497+
}
1498+
1499+
#[test]
1500+
fn test_dynamic_cast() {
1501+
let mut lexer = Lexer::<DefaultContext>::new(b"dynamic_cast<const int>(x)");
1502+
let mut parser = ExpressionParser::new(&mut lexer, Token::Eof);
1503+
let mut context = Context::default();
1504+
let node = parser.parse(None, &mut context).unwrap().1.unwrap();
1505+
1506+
let expected = node!(DynamicCast {
1507+
typ: Type {
1508+
base: BaseType::Primitive(Primitive::Int),
1509+
cv: CVQualifier::CONST,
1510+
pointers: None,
1511+
},
1512+
arg: ExprNode::Variable(Box::new(mk_var!("x"))),
1513+
});
1514+
1515+
assert_eq!(node, expected);
1516+
}
1517+
1518+
#[test]
1519+
fn test_const_cast() {
1520+
let mut lexer = Lexer::<DefaultContext>::new(b"const_cast<const int>(x)");
1521+
let mut parser = ExpressionParser::new(&mut lexer, Token::Eof);
1522+
let mut context = Context::default();
1523+
let node = parser.parse(None, &mut context).unwrap().1.unwrap();
1524+
1525+
let expected = node!(ConstCast {
1526+
typ: Type {
1527+
base: BaseType::Primitive(Primitive::Int),
1528+
cv: CVQualifier::CONST,
1529+
pointers: None,
1530+
},
1531+
arg: ExprNode::Variable(Box::new(mk_var!("x"))),
1532+
});
1533+
1534+
assert_eq!(node, expected);
1535+
}
1536+
1537+
#[test]
1538+
fn test_reinterpret_cast() {
1539+
let mut lexer = Lexer::<DefaultContext>::new(b"reinterpret_cast<const int>(x)");
1540+
let mut parser = ExpressionParser::new(&mut lexer, Token::Eof);
1541+
let mut context = Context::default();
1542+
let node = parser.parse(None, &mut context).unwrap().1.unwrap();
1543+
1544+
let expected = node!(ReinterpretCast {
1545+
typ: Type {
1546+
base: BaseType::Primitive(Primitive::Int),
1547+
cv: CVQualifier::CONST,
1548+
pointers: None,
1549+
},
1550+
arg: ExprNode::Variable(Box::new(mk_var!("x"))),
1551+
});
1552+
1553+
assert_eq!(node, expected);
1554+
}
14611555
}

src/parser/expressions/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ pub use self::list::*;
1818

1919
pub mod left_paren;
2020
pub use self::left_paren::*;
21+
22+
pub mod casts;
23+
pub use self::casts::*;

0 commit comments

Comments
 (0)