Skip to content

Commit a9a5b44

Browse files
committed
fix(semantic): additional fixes for function analysis
1 parent 0d853ba commit a9a5b44

File tree

9 files changed

+61
-12
lines changed

9 files changed

+61
-12
lines changed

src/lexer/token.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ pub enum KeywordType {
1414
True,
1515
False,
1616
Null,
17+
Print,
18+
Read,
19+
Flush,
1720
Alloc,
1821
AllocArray,
1922
Int,
@@ -38,6 +41,9 @@ impl KeywordType {
3841
Self::True => "true",
3942
Self::False => "false",
4043
Self::Null => "null",
44+
Self::Print => "print",
45+
Self::Read => "read",
46+
Self::Flush => "flush",
4147
Self::Alloc => "alloc",
4248
Self::AllocArray => "alloc_array",
4349
Self::Int => "int",
@@ -62,6 +68,9 @@ impl KeywordType {
6268
"true" => Some(Self::True),
6369
"false" => Some(Self::False),
6470
"null" => Some(Self::Null),
71+
"print" => Some(Self::Print),
72+
"read" => Some(Self::Read),
73+
"flush" => Some(Self::Flush),
6574
"alloc" => Some(Self::Alloc),
6675
"alloc_array" => Some(Self::AllocArray),
6776
"int" => Some(Self::Int),
@@ -83,6 +92,10 @@ impl KeywordType {
8392
pub fn is_type(&self) -> bool {
8493
matches!(self, Self::Bool | Self::Int)
8594
}
95+
96+
pub fn is_function(&self) -> bool {
97+
matches!(self, Self::Flush | Self::Read | Self::Print)
98+
}
8699
}
87100

88101
#[derive(Eq, Hash, Clone, Debug, PartialEq)]
@@ -296,6 +309,10 @@ impl Token {
296309
}
297310
}
298311

312+
pub fn is_function(&self) -> bool {
313+
matches!(self, Self::Keyword(_, keyword_type) if keyword_type.is_function())
314+
}
315+
299316
pub fn is_assignment_operator(&self) -> bool {
300317
matches!(self, Self::Operator(_, operator) if operator.is_assignment_operator())
301318
}

src/parser/ast/call_tree.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ use crate::{
44
lexer::{collection::ParserTokens, token::SeperatorType},
55
parser::{
66
ast::{
7-
call_parameter_tree::CallParameterTree, identifier_tree::IdentifierExpressionTree, Tree,
7+
call_parameter_tree::CallParameterTree, identifier_tree::IdentifierExpressionTree,
8+
name_tree::NameTree, Tree,
89
},
910
error::ParseError,
11+
symbols::Name,
1012
},
1113
util::span::Span,
1214
};
@@ -23,7 +25,15 @@ impl Tree for CallTree {
2325
self.identifier.span().merge(&self.closing_span)
2426
}
2527
fn from_tokens(tokens: &mut ParserTokens) -> Result<Self, ParseError> {
26-
let identifier = IdentifierExpressionTree::from_tokens(tokens)?;
28+
let identifier = if tokens.peek().ok_or(ParseError::ReachedEnd)?.is_function() {
29+
let token = tokens.consume()?;
30+
IdentifierExpressionTree::new(NameTree::new(
31+
Name::IdentifierName(token.as_string().to_string()),
32+
token.span(),
33+
))
34+
} else {
35+
IdentifierExpressionTree::from_tokens(tokens)?
36+
};
2737
tokens.expect_seperator(SeperatorType::ParenOpen)?;
2838
let mut call_parameter = Vec::new();
2939
if !tokens

src/parser/ast/expression_tree.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ impl ExpressionTree {
204204
))
205205
}
206206
}
207+
Token::Keyword(_, keyword_type) if keyword_type.is_function() => {
208+
Ok(ExpressionTree::CallTree(CallTree::from_tokens(tokens)?))
209+
}
207210
Token::NumberLiteral(_, _, _) => Ok(ExpressionTree::IntegerLiteralTree(
208211
IntegerLiteralTree::from_tokens(tokens)?,
209212
)),

src/parser/ast/identifier_tree.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ impl Tree for IdentifierExpressionTree {
3131
}
3232

3333
impl IdentifierExpressionTree {
34+
pub fn new(name: NameTree) -> IdentifierExpressionTree {
35+
IdentifierExpressionTree { name }
36+
}
37+
3438
pub fn name(&self) -> &NameTree {
3539
&self.name
3640
}

src/parser/ast/name_tree.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ impl Tree for NameTree {
3232
}
3333

3434
impl NameTree {
35+
pub fn new(name: Name, span: Span) -> NameTree {
36+
NameTree { name, span }
37+
}
38+
3539
pub fn name(&self) -> &Name {
3640
&self.name
3741
}

src/parser/ast/program_tree.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,7 @@ impl Tree for ProgramTree {
4747
if functions.is_empty() {
4848
return Err(ParseError::NoFunctions);
4949
}
50-
if functions
51-
.iter()
52-
.any(|v| v.name_tree().name().as_string() == "main")
53-
{
54-
Ok(ProgramTree { functions })
55-
} else {
56-
Err(ParseError::NoMainFunction)
57-
}
50+
Ok(ProgramTree { functions })
5851
}
5952
}
6053

src/parser/error.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pub enum ParseError {
1919
NotAStatement,
2020
NotAOperation,
2121
NoFunctions,
22-
NoMainFunction,
2322
ReachedEnd,
2423
WhitespaceError,
2524
InvalidCharacter,

src/semantic/ast/program_tree.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,18 @@ impl SemanticAnalysis for ProgramTree {
2828
for function in self.functions() {
2929
function.analyze(state)?;
3030
}
31-
Ok(())
31+
if let Some(main_function) = self
32+
.functions()
33+
.iter()
34+
.find(|v| v.name_tree().name().as_string() == "main")
35+
{
36+
if main_function.parameters().len() > 0 {
37+
return Err(SemanticError::InvalidMainFunction);
38+
}
39+
Ok(())
40+
} else {
41+
Err(SemanticError::NoMainFunction)
42+
}
3243
}
3344
fn r#type(&self, _: &mut AnalysisState) -> Result<Type, SemanticError> {
3445
Ok(Type::Unit)

src/semantic/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ pub enum SemanticError {
2525
ConditionMustBeBoolean(ExpressionTree),
2626
FunctionNotReturning(BlockTree),
2727
ForAdvancementDefinesVariable,
28+
NoMainFunction,
2829
MainMustReturnInt,
2930
IncompatibleReturnType(ExpressionTree),
3031
FunctionAlreadyDefined(Name),
3132
UndefinedFunction(Name),
3233
FunctionParameterMismatch,
34+
InvalidMainFunction,
3335
}
3436

3537
impl Display for SemanticError {
@@ -119,6 +121,12 @@ impl Display for SemanticError {
119121
SemanticError::FunctionParameterMismatch => {
120122
writeln!(f, "Mismatching function parameters!")
121123
}
124+
SemanticError::NoMainFunction => {
125+
writeln!(f, "No main function!")
126+
}
127+
SemanticError::InvalidMainFunction => {
128+
writeln!(f, "Invalid main function")
129+
}
122130
}
123131
}
124132
}

0 commit comments

Comments
 (0)