diff --git a/lsp/src/analysis/visitor.rs b/lsp/src/analysis/visitor.rs index 821c5ac..9ebbf76 100644 --- a/lsp/src/analysis/visitor.rs +++ b/lsp/src/analysis/visitor.rs @@ -218,7 +218,9 @@ pub trait ASTVisitor { ExpressionKind::TokenList(toks) => self.visit_token_list(toks, expression.span), ExpressionKind::Call(callee, arguments) => { self.visit_call(callee, arguments, expression.span) - } + }, + ExpressionKind::Ident(expr) => self.visit_ident(expr, expression.span), + ExpressionKind::Sprintf(str, args) => self.visit_sprintf(str, args, expression.span), } } @@ -303,6 +305,12 @@ pub trait ASTVisitor { self.visit_expression(expr); } fn visit_match(&mut self, _expr1: &Expression, _expr2: &Expression, _span: Span) {} + fn visit_ident(&mut self, _ident: &Expression, _span: Span) {} + fn visit_sprintf(&mut self, _str: &Expression, args: &[Expression], _span: Span) { + for arg in args.iter() { + self.visit_expression(arg); + } + } fn visit_def(&mut self, _tok: &Token, _span: Span) {} fn visit_identifier(&mut self, _ident: &str, _span: Span) {} fn visit_unnamed_label_reference(&mut self, _reference: &i8, _span: Span) {} diff --git a/parser/src/data/token_type.rs b/parser/src/data/token_type.rs index 417097c..58be879 100644 --- a/parser/src/data/token_type.rs +++ b/parser/src/data/token_type.rs @@ -45,6 +45,8 @@ pub enum TokenType { Bank, SizeOf, Match, + Ident, + Sprintf, Def, UnnamedLabelReference, Extract, diff --git a/parser/src/parser.rs b/parser/src/parser.rs index a98aa37..b4ff6d9 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -131,6 +131,8 @@ pub enum ExpressionKind { TokenList(Vec), Call(String, Vec), WordOp(Token, Box), + Ident(Box), + Sprintf(Box, Vec), } #[derive(Debug, Clone, PartialEq)] @@ -1098,6 +1100,32 @@ impl<'a> Parser<'a> { span: Span::new(start, end), }); } + if match_token!(self.tokens, TokenType::Ident) { + self.consume_token(TokenType::LeftParen)?; + let expr = self.parse_expression()?; + self.consume_token(TokenType::RightParen)?; + let end = self.mark_end(); + + return Ok(Expression { + kind: ExpressionKind::Ident(Box::from(expr)), + span: Span::new(start, end), + }); + } + if match_token!(self.tokens, TokenType::Sprintf) { + self.consume_token(TokenType::LeftParen)?; + let expr = self.parse_expression()?; + let mut args = vec![]; + while match_token!(self.tokens, TokenType::Comma) { + args.push(self.parse_expression()?); + } + self.consume_token(TokenType::RightParen)?; + let end = self.mark_end(); + + return Ok(Expression { + kind: ExpressionKind::Sprintf(Box::from(expr), args), + span: Span::new(start, end), + }); + } if match_token!(self.tokens, TokenType::Extract) { return self.parse_extract(); } diff --git a/parser/src/tokenizer.rs b/parser/src/tokenizer.rs index 2cb75d2..c2cbcae 100644 --- a/parser/src/tokenizer.rs +++ b/parser/src/tokenizer.rs @@ -83,6 +83,8 @@ impl<'a> Tokenizer<'a> { self.make_token(TokenType::WordOp) } ".match" | ".xmatch" => self.make_token(TokenType::Match), + ".ident" => self.make_token(TokenType::Ident), + ".sprintf" => self.make_token(TokenType::Sprintf), ".def" | ".defined" => self.make_token(TokenType::Def), ".left" | ".mid" | ".right" => self.make_token(TokenType::Extract), _ => self.make_token(TokenType::Macro),