diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-10-14 20:40:39 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-10-14 21:05:05 +1300 |
commit | 981bb70e5077bd30ef85a0092117a875dcc614fc (patch) | |
tree | 45e614de74d17071ca1e68098df4d32266df85a3 /src/stages/semantic.rs | |
parent | ace5677f87c2bc042d8d5e807ccea9ddcd828c9e (diff) | |
download | torque-asm-981bb70e5077bd30ef85a0092117a875dcc614fc.zip |
Implement new intermediate stage
Massive improvement. Label references can be used anywhere in the
program, with the program being assembled repeatedly until all labels
have stabilised. The bytecode stage will just be a tiny stage tacked
onto the end, rather than the old bytecode stage that would resolve
labels and expressions.
Diffstat (limited to 'src/stages/semantic.rs')
-rw-r--r-- | src/stages/semantic.rs | 72 |
1 files changed, 34 insertions, 38 deletions
diff --git a/src/stages/semantic.rs b/src/stages/semantic.rs index fdd1766..96cf7af 100644 --- a/src/stages/semantic.rs +++ b/src/stages/semantic.rs @@ -306,22 +306,44 @@ impl SemanticParser { } } - /// Parse the remaining syntactic tokens as the contents of a block. - fn parse_block(&mut self) -> Vec<Tracked<BlockToken>> { - let mut tokens = Vec::new(); - while !self.syntactic.is_empty() { - if let Some(token) = self.pull_block_token(SemanticLocation::BlockLiteral) { - tokens.push(token); + /// Attempt to pull a token that can be used in an expression. + fn pull_expression_token(&mut self) -> Option<Tracked<ExpressionToken>> { + match self.pull_macro_definition_body_token()? { + MacroDefinitionBody::Block(mut tokens) => { + assert_eq!(tokens.len(), 1); + let token = tokens.pop().unwrap(); + let error = SemanticError::InvalidBlockInExpression; + self.errors.push(Tracked::from(error, token.source)); + None + } + MacroDefinitionBody::Invocation(invocation) => { + // Attempt to parse the invocation as an operator. + if invocation.arguments.is_empty() { + if let Some(operator) = Operator::from_str(&invocation.name) { + let expr = ExpressionToken::Operator(operator); + return Some(Tracked::from(expr, invocation.source)) + } + } + // Parse invocation as an invocation. + let expr = ExpressionToken::Invocation(invocation.value); + Some(Tracked::from(expr, invocation.source)) + } + MacroDefinitionBody::Integer(integer) => { + let expr = ExpressionToken::IntegerToken(Box::new(integer.value)); + Some(Tracked::from(expr, integer.source)) + } + MacroDefinitionBody::List(list) => { + let expr = ExpressionToken::ListToken(list.value); + Some(Tracked::from(expr, list.source)) } } - tokens } - /// Parse the remaining syntactic tokens as a list of integer tokens. - fn parse_integer_list(&mut self, location: SemanticLocation) -> Vec<Tracked<IntegerToken>> { + /// Parse the remaining syntactic tokens as the contents of a block. + fn parse_block(&mut self) -> Vec<Tracked<BlockToken>> { let mut tokens = Vec::new(); while !self.syntactic.is_empty() { - if let Some(token) = self.pull_integer_token(location) { + if let Some(token) = self.pull_block_token(SemanticLocation::BlockLiteral) { tokens.push(token); } } @@ -331,34 +353,8 @@ impl SemanticParser { /// Parse the remaining syntactic tokens as the contents of an expression. fn parse_expression(&mut self) -> Expression { let mut tokens = Vec::new(); - for token in self.parse_integer_list(SemanticLocation::Expression) { - let source = token.source; - match token.value { - IntegerToken::IntegerLiteral(value) => { - let integer = Box::new(IntegerToken::IntegerLiteral(value)); - let token = ExpressionToken::IntegerToken(integer); - tokens.push(Tracked::from(token, source)); - } - IntegerToken::Expression(expression) => { - let integer = Box::new(IntegerToken::Expression(expression)); - let token = ExpressionToken::IntegerToken(integer); - tokens.push(Tracked::from(token, source)); - } - IntegerToken::Invocation(invocation) => { - // Parse the invocation as an operator instead. - if invocation.arguments.is_empty() { - if let Some(operator) = Operator::from_str(&invocation.name) { - let token = ExpressionToken::Operator(operator); - tokens.push(Tracked::from(token, source)); - continue; - } - } - // Parse the invocation as an invocation. - let integer = Box::new(IntegerToken::Invocation(invocation)); - let token = ExpressionToken::IntegerToken(integer); - tokens.push(Tracked::from(token, source)); - } - } + while let Some(token) = self.pull_expression_token() { + tokens.push(token); } Expression { tokens } } |