diff options
Diffstat (limited to 'compiler/src/ast/parser.rs')
| -rw-r--r-- | compiler/src/ast/parser.rs | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/compiler/src/ast/parser.rs b/compiler/src/ast/parser.rs index 6b11cc6..8e476ad 100644 --- a/compiler/src/ast/parser.rs +++ b/compiler/src/ast/parser.rs | |||
| @@ -6,6 +6,8 @@ use crate::{ | |||
| 6 | span::{Pos, Span, Spanned}, | 6 | span::{Pos, Span, Spanned}, |
| 7 | }; | 7 | }; |
| 8 | 8 | ||
| 9 | const MAX_DEPTH: usize = 256; // TODO: make it a compile flag | ||
| 10 | |||
| 9 | fn parse_number(number: &str) -> Result<Atom, Error> { | 11 | fn parse_number(number: &str) -> Result<Atom, Error> { |
| 10 | let is_float = number.bytes().any(|b| matches!(b, b'.' | b'e' | b'E')) | 12 | let is_float = number.bytes().any(|b| matches!(b, b'.' | b'e' | b'E')) |
| 11 | || matches!(number, "inf" | "+inf" | "-inf" | "nan"); | 13 | || matches!(number, "inf" | "+inf" | "-inf" | "nan"); |
| @@ -66,6 +68,7 @@ where | |||
| 66 | { | 68 | { |
| 67 | tokens: Peekable<I>, | 69 | tokens: Peekable<I>, |
| 68 | last_token_span: Span, | 70 | last_token_span: Span, |
| 71 | depth: usize, | ||
| 69 | } | 72 | } |
| 70 | 73 | ||
| 71 | impl<'a, I> Parser<'a, I> | 74 | impl<'a, I> Parser<'a, I> |
| @@ -76,6 +79,7 @@ where | |||
| 76 | Self { | 79 | Self { |
| 77 | tokens: tokens.peekable(), | 80 | tokens: tokens.peekable(), |
| 78 | last_token_span: Span::new(Pos::new(1, 0, 0), Pos::new(1, 0, 0)), | 81 | last_token_span: Span::new(Pos::new(1, 0, 0), Pos::new(1, 0, 0)), |
| 82 | depth: 0, | ||
| 79 | } | 83 | } |
| 80 | } | 84 | } |
| 81 | 85 | ||
| @@ -147,6 +151,11 @@ where | |||
| 147 | fn parse_list(&mut self, left_par_span: Span) -> Result<Vec<Spanned<Expr>>, Spanned<Error>> { | 151 | fn parse_list(&mut self, left_par_span: Span) -> Result<Vec<Spanned<Expr>>, Spanned<Error>> { |
| 148 | let mut list = Vec::new(); | 152 | let mut list = Vec::new(); |
| 149 | 153 | ||
| 154 | self.depth += 1; | ||
| 155 | if self.depth >= MAX_DEPTH { | ||
| 156 | return Err(Spanned::new(Error::RecursionLimit, self.last_token_span)); | ||
| 157 | } | ||
| 158 | |||
| 150 | while let Some(Spanned { inner: token, .. }) = self.peek() { | 159 | while let Some(Spanned { inner: token, .. }) = self.peek() { |
| 151 | match token { | 160 | match token { |
| 152 | Token::RightPar => { | 161 | Token::RightPar => { |
| @@ -156,6 +165,7 @@ where | |||
| 156 | _ => list.push(self.parse_expr()?), | 165 | _ => list.push(self.parse_expr()?), |
| 157 | } | 166 | } |
| 158 | } | 167 | } |
| 168 | self.depth -= 1; | ||
| 159 | 169 | ||
| 160 | Err(Spanned::new(Error::UnclosedLeftPar, left_par_span)) | 170 | Err(Spanned::new(Error::UnclosedLeftPar, left_par_span)) |
| 161 | } | 171 | } |
