@@ 34,9 34,13 @@ term = factor { , ( "+" | "-" ) , factor } ;
factor = unary { , ( "*" | "/" ) , unary } ;
-unary = ( ( "!" | "-" ) , unary ) | primary ;
+unary = ( ( "!" | "-" ) , unary ) | subscript ;
-primary = identifier | member | call | number | string | group ;
+subscript = primary , { "[" , expression , "]" , }
+
+primary = identifier | array | member | call | number | string | group ;
+
+array = "[" , { expression , "," ? } , "]" ;
member = identifier , "." , { ( identifier | call ) , "." ? } ;
@@ 74,6 74,14 @@ impl Lexer {
self.output.push(token!(self, TokenType::RightBrace));
self.start = self.current;
}
+ b'[' => {
+ self.output.push(token!(self, TokenType::LeftSquare));
+ self.start = self.current;
+ }
+ b']' => {
+ self.output.push(token!(self, TokenType::RightSquare));
+ self.start = self.current;
+ }
b'.' => {
self.output.push(token!(self, TokenType::Period));
self.start = self.current;
@@ 184,6 192,7 @@ impl Lexer {
self.read_char();
}
self.output.push(token!(self, TokenType::Ident(content)));
+ self.start = self.current;
} else if c.is_ascii_digit() {
let mut number = (c as char).to_string();
while self.peek().is_ascii_digit() {
@@ 256,6 265,8 @@ pub enum TokenType {
RightParen,
LeftBrace,
RightBrace,
+ LeftSquare,
+ RightSquare,
Period,
Comma,
Semicolon,
@@ 126,11 126,7 @@ impl Parser {
column: return_ident.column,
})
} else {
- return Err(unexpected_token!(
- self,
- "Expected ; found {}",
- semicolon
- ));
+ return Err(unexpected_token!(self, "Expected ; found {}", semicolon));
}
}
@@ 177,7 173,7 @@ impl Parser {
ast_type: ASTType::Break,
start: break_ident.start,
end: semicolon.end,
- line: break_ident.line,
+ line: break_ident.line,
column: break_ident.column,
})
} else {
@@ 193,7 189,7 @@ impl Parser {
ast_type: ASTType::Continue,
start: continue_ident.start,
end: semicolon.end,
- line: continue_ident.line,
+ line: continue_ident.line,
column: continue_ident.column,
})
} else {
@@ 625,7 621,30 @@ impl Parser {
}
}
- Ok(self.primary()?)
+ self.subscript()
+ }
+ pub fn subscript(&mut self) -> Result<AST, KabelError> {
+ let mut primary = self.primary()?;
+
+ while self.current < self.input.len() &&
+ self.peek()?.token_type == TokenType::LeftSquare {
+ self.read_token()?;
+ let expr = self.expression()?;
+ let right_brace = self.read_token()?;
+ if let TokenType::RightSquare = right_brace.token_type {
+ primary = AST {
+ ast_type: ASTType::Subscript(Box::new(primary.clone()), Box::new(expr)),
+ start: primary.start,
+ end: right_brace.end,
+ line: primary.line,
+ column: primary.column,
+ };
+ } else {
+ return Err(unexpected_token!(self, "Expected ] found {}", right_brace));
+ }
+ }
+
+ Ok(primary)
}
pub fn primary(&mut self) -> Result<AST, KabelError> {
let token = self.read_token()?;
@@ 667,7 686,10 @@ impl Parser {
});
}
TokenType::LeftParen => {
- return Ok(self.group(token)?);
+ return self.group(token);
+ }
+ TokenType::LeftSquare => {
+ return self.array(token);
}
_ => {
return Err(unexpected_token!(self, "Unexpected token {}", token));
@@ 675,6 697,24 @@ impl Parser {
}
}
+ pub fn array(&mut self, left_square: Token) -> Result<AST, KabelError> {
+ let mut expressions = Vec::new();
+ while self.peek()?.token_type != TokenType::RightSquare {
+ expressions.push(self.expression()?);
+ if let TokenType::Comma = self.peek()?.token_type {
+ self.read_token()?;
+ }
+ }
+ let right_square = self.read_token()?;
+ Ok(AST {
+ ast_type: ASTType::Lit(Lit::Array(expressions)),
+ start: left_square.start,
+ end: right_square.end,
+ line: left_square.line,
+ column: left_square.column,
+ })
+ }
+
pub fn member(&mut self, ident: Token) -> Result<AST, KabelError> {
if let TokenType::Ident(first) = ident.token_type {
let mut expr: AST = lit!(Ident, first, ident);
@@ 823,17 863,18 @@ pub enum ASTType {
Program(Vec<AST>),
// statements
- Function(Box<AST>, Vec<AST>, Box<AST>), // name, args, block
- Return(Option<Box<AST>>), // expression
- Loop(Box<AST>), // block
- While(Box<AST>, Box<AST>), // condition, block
+ Function(Box<AST>, Vec<AST>, Box<AST>), // name, args, block
+ Return(Option<Box<AST>>), // expression
+ Loop(Box<AST>), // block
+ While(Box<AST>, Box<AST>), // condition, block
Break,
Continue,
- If(Box<AST>, Box<AST>, Option<Box<AST>>), // condition, block, else/else if
- Block(Vec<AST>), // statements
+ If(Box<AST>, Box<AST>, Option<Box<AST>>), // condition, block, else/else if
+ Block(Vec<AST>), // statements
// expressions
- Decl(Box<AST>, Box<AST>), // identifier, expression
+ Decl(Box<AST>, Box<AST>), // identifier, expression
+ Subscript(Box<AST>, Box<AST>),
Binary(Box<AST>, BinOp, Box<AST>),
Unary(UnOp, Box<AST>),
@@ 849,6 890,7 @@ pub enum Lit {
Ident(String),
Num(f32),
Str(String),
+ Array(Vec<AST>),
}
#[derive(Debug, Clone, Copy)]