aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/ast
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/ast')
-rw-r--r--compiler/src/ast/error.rs2
-rw-r--r--compiler/src/ast/parser.rs10
2 files changed, 12 insertions, 0 deletions
diff --git a/compiler/src/ast/error.rs b/compiler/src/ast/error.rs
index ced2231..21102ea 100644
--- a/compiler/src/ast/error.rs
+++ b/compiler/src/ast/error.rs
@@ -19,6 +19,8 @@ pub enum Error {
19 UnclosedLeftPar, 19 UnclosedLeftPar,
20 20
21 UnexpectedEof, 21 UnexpectedEof,
22
23 RecursionLimit,
22} 24}
23 25
24impl From<ParseFloatError> for Error { 26impl From<ParseFloatError> for Error {
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
9const MAX_DEPTH: usize = 256; // TODO: make it a compile flag
10
9fn parse_number(number: &str) -> Result<Atom, Error> { 11fn 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
71impl<'a, I> Parser<'a, I> 74impl<'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 }