surrealdb_core/syn/lexer/compound/
js.rs

1use crate::syn::{
2	error::{MessageKind, SyntaxError},
3	lexer::unicode::chars::JS_LINE_TERIMATORS,
4	token::{t, Token},
5};
6
7use super::Lexer;
8
9pub fn javascript(lexer: &mut Lexer, start: Token) -> Result<(), SyntaxError> {
10	assert_eq!(start.kind, t!("{"), "Invalid start of JavaScript compound token");
11	lex_js_function_body_inner(lexer)?;
12	Ok(())
13}
14
15/// Lex the body of a js function.
16fn lex_js_function_body_inner(lexer: &mut Lexer) -> Result<(), SyntaxError> {
17	let mut block_depth = 1;
18	loop {
19		let Some(byte) = lexer.reader.next() else {
20			let span = lexer.advance_span();
21			return Err(SyntaxError::new(format_args!(
22				"Invalid JavaScript function, encountered unexpected eof"
23			))
24			.with_span(span, MessageKind::Error)
25			.with_data_pending());
26		};
27		match byte {
28			b'`' => lex_js_string(lexer, b'`')?,
29			b'\'' => lex_js_string(lexer, b'\'')?,
30			b'\"' => lex_js_string(lexer, b'\"')?,
31			b'/' => match lexer.reader.peek() {
32				Some(b'/') => {
33					lexer.reader.next();
34					lex_js_single_comment(lexer)?;
35				}
36				Some(b'*') => {
37					lexer.reader.next();
38					lex_js_multi_comment(lexer)?
39				}
40				_ => {}
41			},
42			b'{' => {
43				block_depth += 1;
44			}
45			b'}' => {
46				block_depth -= 1;
47				if block_depth == 0 {
48					break;
49				}
50			}
51			x if !x.is_ascii() => {
52				lexer.reader.complete_char(x)?;
53			}
54			_ => {}
55		}
56	}
57
58	Ok(())
59}
60
61/// lex a js string with the given delimiter.
62fn lex_js_string(lexer: &mut Lexer, enclosing_byte: u8) -> Result<(), SyntaxError> {
63	loop {
64		let Some(byte) = lexer.reader.next() else {
65			let span = lexer.advance_span();
66			return Err(SyntaxError::new(format_args!(
67				"Invalid JavaScript function, encountered unexpected eof"
68			))
69			.with_span(span, MessageKind::Error)
70			.with_data_pending());
71		};
72		if byte == enclosing_byte {
73			return Ok(());
74		}
75		if byte == b'\\' {
76			lexer.reader.next();
77		}
78		// check for invalid characters.
79		lexer.reader.convert_to_char(byte)?;
80	}
81}
82
83/// lex a single line js comment.
84fn lex_js_single_comment(lexer: &mut Lexer) -> Result<(), SyntaxError> {
85	loop {
86		let Some(byte) = lexer.reader.next() else {
87			return Ok(());
88		};
89		let char = lexer.reader.convert_to_char(byte)?;
90		if JS_LINE_TERIMATORS.contains(&char) {
91			return Ok(());
92		}
93	}
94}
95
96/// lex a multi line js comment.
97fn lex_js_multi_comment(lexer: &mut Lexer) -> Result<(), SyntaxError> {
98	loop {
99		let Some(byte) = lexer.reader.next() else {
100			let span = lexer.advance_span();
101			return Err(SyntaxError::new(format_args!(
102				"Invalid JavaScript function, encountered unexpected eof"
103			))
104			.with_span(span, MessageKind::Error)
105			.with_data_pending());
106		};
107		if byte == b'*' && lexer.reader.peek() == Some(b'/') {
108			lexer.reader.next();
109			return Ok(());
110		}
111		// check for invalid characters.
112		lexer.reader.convert_to_char(byte)?;
113	}
114}