Skip to content

Commit bfc9697

Browse files
committed
(keywords) add: attribute keywords for variables
1 parent b3adb15 commit bfc9697

File tree

10 files changed

+254
-118
lines changed

10 files changed

+254
-118
lines changed

src/errors/result.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ pub struct Res<T> {
1414
impl<T> Res<T> {
1515
#[inline]
1616
pub fn unwrap_or_display(self, files: &[(String, &str)], err_type: &str) -> T {
17-
if self.errors.is_empty() {
18-
self.result
19-
} else {
17+
if self.errors.iter().any(CompileError::is_error) {
2018
display_errors(self.errors, files, err_type);
2119
panic!(/* Fail when displaying errors */)
20+
} else {
21+
self.result
2222
}
2323
}
2424
}

src/lexer/end_state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn end_ident(literal: &mut Ident, lex_data: &mut LexingData, location: &Location
3131
let possible_number = literal_to_number(lex_data, literal, location);
3232
match possible_number {
3333
None => {
34-
let token = Token::from_identifier(literal, location);
34+
let token = Token::from_identifier(lex_data, literal, location);
3535
lex_data.push_token(token);
3636
}
3737
Some(nb) => {

src/lexer/types/keywords.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,19 @@ macro_rules! impl_keywords {
88
}
99

1010
impl Keyword {
11+
pub fn from_value_or_res(value: &str) -> TryKeywordType {
12+
match value {
13+
$($str => TryKeywordType::from_keyword($str, Keyword::$pascal),)*
14+
_ => TryKeywordType::Failure,
15+
}
16+
}
17+
1118
pub const fn keyword_type(&self) -> KeywordType {
1219
match self {
1320
$(Self::$pascal => KeywordType::$ktype,)*
1421
}
1522
}
16-
}
1723

18-
impl TryFrom<&str> for Keyword {
19-
type Error = ();
20-
fn try_from(value: &str) -> Result<Self, Self::Error> {
21-
match value {
22-
$($str => Ok(Self::$pascal),)*
23-
_ => return Err(()),
24-
}
25-
}
2624
}
2725

2826
#[expect(clippy::min_ident_chars)]
@@ -106,3 +104,19 @@ pub enum KeywordType {
106104
Storage,
107105
Type,
108106
}
107+
108+
pub enum TryKeywordType {
109+
Deprecated(Keyword),
110+
Failure,
111+
Success(Keyword),
112+
}
113+
114+
impl TryKeywordType {
115+
fn from_keyword(value: &str, keyword: Keyword) -> Self {
116+
if value.starts_with('_') {
117+
Self::Deprecated(keyword)
118+
} else {
119+
Self::Success(keyword)
120+
}
121+
}
122+
}

src/lexer/types/tokens_types.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use core::fmt;
22

33
use super::super::numbers::api::Number;
4-
use super::keywords::Keyword;
4+
use super::keywords::{Keyword, TryKeywordType};
5+
use super::lexing_data::LexingData;
56
use super::lexing_state::Ident;
67
use crate::errors::api::Location;
78

@@ -72,13 +73,35 @@ impl Token {
7273
}
7374
}
7475

75-
pub(crate) fn from_identifier(identifier: &mut Ident, location: &Location) -> Self {
76-
let value = identifier.take_value();
77-
let token_value = Keyword::try_from(value.as_str())
78-
.map_err(|()| value)
79-
.map_or_else(TokenValue::Identifier, TokenValue::Keyword);
76+
pub(crate) fn from_identifier(
77+
lex_data: &mut LexingData,
78+
literal: &mut Ident,
79+
location: &Location,
80+
) -> Self {
81+
let len = literal.len();
82+
let value = literal.take_value();
83+
let token_value = match Keyword::from_value_or_res(&value) {
84+
TryKeywordType::Success(keyword) => TokenValue::Keyword(keyword),
85+
TryKeywordType::Deprecated(keyword) => {
86+
let new_keyword = value
87+
.char_indices()
88+
.filter_map(|(idx, ch)| {
89+
if idx == 0 {
90+
None
91+
} else if idx == 1 {
92+
Some(ch.to_ascii_lowercase())
93+
} else {
94+
Some(ch)
95+
}
96+
})
97+
.collect::<String>();
98+
lex_data.push_err(location.to_owned().into_past(len).to_warning(format!("Underscore operators are deprecated since C23. Consider using the new keyword: {new_keyword}")));
99+
TokenValue::Keyword(keyword)
100+
}
101+
TryKeywordType::Failure => TokenValue::Identifier(value),
102+
};
80103
Self {
81-
location: location.to_owned().into_past(identifier.len()),
104+
location: location.to_owned().into_past(len),
82105
value: token_value,
83106
}
84107
}

src/parser/keyword/types/attributes.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ use core::fmt;
55
use super::super::Ast;
66
use super::PushInNode;
77
use crate::lexer::api::Keyword;
8+
use crate::parser::tree::binary::Binary;
9+
use crate::parser::tree::blocks::Block;
10+
use crate::parser::tree::unary::Unary;
11+
use crate::parser::tree::{FunctionCall, ListInitialiser, Literal, Ternary, Variable};
812

913
macro_rules! define_attribute_keywords {
1014
($($name:ident: $($variant:ident)*,)*) => {
@@ -22,11 +26,13 @@ macro_rules! define_attribute_keywords {
2226
}
2327
}
2428

25-
impl PushInNode for AttributeKeyword {
26-
fn push_in_node(self, node: &mut Ast) -> Result<(), String> {
27-
todo!()
28-
}
29-
}
29+
// impl PushInNode for AttributeKeyword {
30+
// fn push_in_node(self, node: &mut Ast) -> Result<(), String> {
31+
// match self {
32+
// $(Self::$name(val) => val.push_in_node(node),)*
33+
// }
34+
// }
35+
// }
3036

3137
pub enum UnsortedAttributeKeyword {
3238
$($($variant,)*)*
@@ -59,3 +65,27 @@ define_attribute_keywords!(
5965
UserDefinedTypes: Typedef Struct Union Enum,
6066
SpecialAttributes: UAtomic Alignas Inline Restrict UGeneric UNoreturn,
6167
);
68+
69+
impl AttributeKeyword {
70+
fn into_node(self) -> Ast {
71+
Ast::Leaf(Literal::Variable(Variable::from(self)))
72+
}
73+
}
74+
75+
impl PushInNode for AttributeKeyword {
76+
fn push_in_node(self, node: &mut Ast) -> Result<(), String> {
77+
match node {
78+
Ast::Empty => *node = self.into_node(),
79+
Ast::Leaf(Literal::Variable(var)) => var.push_attr(self),
80+
Ast::ParensBlock(_) | Ast::Leaf(_) => return Err(format!("invalid attribute. Attribute keywords can only be applied to variables, but found {node}")),
81+
Ast::Unary(Unary{arg: Some(arg), ..}) | Ast::Binary(Binary {arg_r: Some(arg), ..}) | Ast::Ternary(Ternary { failure: Some(arg), ..} | Ternary { success: arg, .. }) => return self.push_in_node(arg),
82+
Ast::Unary(Unary{arg: None, ..}) | Ast::Binary(Binary {arg_r: None, ..}) => return node.push_block_as_leaf(self.into_node()),
83+
Ast::ListInitialiser(ListInitialiser{ full: true, ..}) | Ast::FunctionCall(FunctionCall{full: true, .. }) => return Err("Attributes can only be placed before variables.".to_owned())
84+
,Ast::ListInitialiser(ListInitialiser{elts , ..}) | Ast::FunctionCall(FunctionCall{args: elts, ..}) | Ast::Block(Block{elts, ..}) => match elts.last_mut() {
85+
Some(last) => return self.push_in_node(last),
86+
None => elts.push(self.into_node()),
87+
}
88+
}
89+
Ok(())
90+
}
91+
}

src/parser/tree/binary.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ macro_rules! define_binary_operator {
4343

4444
#[derive(Debug, PartialEq)]
4545
pub struct Binary {
46-
pub(super) op: BinaryOperator,
47-
pub(super) arg_l: Box<Ast>,
48-
pub(super) arg_r: Option<Box<Ast>>,
46+
pub op: BinaryOperator,
47+
pub arg_l: Box<Ast>,
48+
pub arg_r: Option<Box<Ast>>,
4949
}
5050

5151
#[expect(clippy::min_ident_chars)]

src/parser/tree/mod.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,10 @@ impl Operator for CompoundLiteralOperator {
4545

4646
#[derive(Debug, PartialEq)]
4747
pub struct FunctionCall {
48-
args: Vec<Ast>,
49-
full: bool,
50-
name: VariableName,
51-
op: FunctionOperator,
52-
return_attrs: Vec<AttributeKeyword>,
48+
pub args: Vec<Ast>,
49+
pub full: bool,
50+
pub op: FunctionOperator,
51+
pub variable: Variable,
5352
}
5453

5554
#[expect(clippy::min_ident_chars)]
@@ -58,7 +57,7 @@ impl fmt::Display for FunctionCall {
5857
write!(
5958
f,
6059
"({}\u{b0}({}{}))",
61-
self.name,
60+
self.variable,
6261
repr_vec_node(&self.args),
6362
if self.full { "" } else { ".." },
6463
)
@@ -80,8 +79,8 @@ impl Operator for FunctionOperator {
8079

8180
#[derive(Debug, PartialEq, Default)]
8281
pub struct ListInitialiser {
83-
elts: Vec<Ast>,
84-
full: bool,
82+
pub elts: Vec<Ast>,
83+
pub full: bool,
8584
}
8685

8786
#[expect(clippy::min_ident_chars)]
@@ -127,10 +126,10 @@ impl fmt::Display for Literal {
127126

128127
#[derive(Debug, PartialEq, Default)]
129128
pub struct Ternary {
130-
pub(super) condition: Box<Ast>,
131-
pub(super) failure: Option<Box<Ast>>,
132-
pub(super) op: TernaryOperator,
133-
pub(super) success: Box<Ast>,
129+
pub condition: Box<Ast>,
130+
pub failure: Option<Box<Ast>>,
131+
pub op: TernaryOperator,
132+
pub success: Box<Ast>,
134133
}
135134

136135
#[expect(clippy::min_ident_chars)]
@@ -166,7 +165,7 @@ impl fmt::Display for TernaryOperator {
166165
}
167166
}
168167

169-
#[derive(Debug, PartialEq, Eq)]
168+
#[derive(Debug, PartialEq, Default, Eq)]
170169
pub struct Variable {
171170
attrs: Vec<AttributeKeyword>,
172171
name: VariableName,
@@ -179,6 +178,10 @@ impl Variable {
179178
attrs: vec![],
180179
}
181180
}
181+
182+
pub fn push_attr(&mut self, attr: AttributeKeyword) {
183+
self.attrs.push(attr);
184+
}
182185
}
183186

184187
impl From<String> for Variable {
@@ -190,6 +193,15 @@ impl From<String> for Variable {
190193
}
191194
}
192195

196+
impl From<AttributeKeyword> for Variable {
197+
fn from(attr: AttributeKeyword) -> Self {
198+
Self {
199+
name: VariableName::Empty,
200+
attrs: vec![attr],
201+
}
202+
}
203+
}
204+
193205
#[expect(clippy::min_ident_chars)]
194206
impl fmt::Display for Variable {
195207
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -211,7 +223,7 @@ impl fmt::Display for Variable {
211223
}
212224

213225
#[derive(Debug, PartialEq, Eq, Default)]
214-
enum VariableName {
226+
pub enum VariableName {
215227
#[default]
216228
Empty,
217229
Keyword(FunctionKeyword),

0 commit comments

Comments
 (0)