summaryrefslogtreecommitdiff
path: root/src/stages/semantic.rs
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-10-14 20:40:39 +1300
committerBen Bridle <ben@derelict.engineering>2025-10-14 21:05:05 +1300
commit981bb70e5077bd30ef85a0092117a875dcc614fc (patch)
tree45e614de74d17071ca1e68098df4d32266df85a3 /src/stages/semantic.rs
parentace5677f87c2bc042d8d5e807ccea9ddcd828c9e (diff)
downloadtorque-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.rs72
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 }
}