surrealdb_core/syn/lexer/compound/
js.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use crate::syn::{
	error::{MessageKind, SyntaxError},
	lexer::unicode::chars::JS_LINE_TERIMATORS,
	token::{t, Token},
};

use super::Lexer;

pub fn javascript(lexer: &mut Lexer, start: Token) -> Result<(), SyntaxError> {
	assert_eq!(start.kind, t!("{"), "Invalid start of JavaScript compound token");
	lex_js_function_body_inner(lexer)?;
	Ok(())
}

/// Lex the body of a js function.
fn lex_js_function_body_inner(lexer: &mut Lexer) -> Result<(), SyntaxError> {
	let mut block_depth = 1;
	loop {
		let Some(byte) = lexer.reader.next() else {
			let span = lexer.advance_span();
			return Err(SyntaxError::new(format_args!(
				"Invalid JavaScript function, encountered unexpected eof"
			))
			.with_span(span, MessageKind::Error)
			.with_data_pending());
		};
		match byte {
			b'`' => lex_js_string(lexer, b'`')?,
			b'\'' => lex_js_string(lexer, b'\'')?,
			b'\"' => lex_js_string(lexer, b'\"')?,
			b'/' => match lexer.reader.peek() {
				Some(b'/') => {
					lexer.reader.next();
					lex_js_single_comment(lexer)?;
				}
				Some(b'*') => {
					lexer.reader.next();
					lex_js_multi_comment(lexer)?
				}
				_ => {}
			},
			b'{' => {
				block_depth += 1;
			}
			b'}' => {
				block_depth -= 1;
				if block_depth == 0 {
					break;
				}
			}
			x if !x.is_ascii() => {
				lexer.reader.complete_char(x)?;
			}
			_ => {}
		}
	}

	Ok(())
}

/// lex a js string with the given delimiter.
fn lex_js_string(lexer: &mut Lexer, enclosing_byte: u8) -> Result<(), SyntaxError> {
	loop {
		let Some(byte) = lexer.reader.next() else {
			let span = lexer.advance_span();
			return Err(SyntaxError::new(format_args!(
				"Invalid JavaScript function, encountered unexpected eof"
			))
			.with_span(span, MessageKind::Error)
			.with_data_pending());
		};
		if byte == enclosing_byte {
			return Ok(());
		}
		if byte == b'\\' {
			lexer.reader.next();
		}
		// check for invalid characters.
		lexer.reader.convert_to_char(byte)?;
	}
}

/// lex a single line js comment.
fn lex_js_single_comment(lexer: &mut Lexer) -> Result<(), SyntaxError> {
	loop {
		let Some(byte) = lexer.reader.next() else {
			return Ok(());
		};
		let char = lexer.reader.convert_to_char(byte)?;
		if JS_LINE_TERIMATORS.contains(&char) {
			return Ok(());
		}
	}
}

/// lex a multi line js comment.
fn lex_js_multi_comment(lexer: &mut Lexer) -> Result<(), SyntaxError> {
	loop {
		let Some(byte) = lexer.reader.next() else {
			let span = lexer.advance_span();
			return Err(SyntaxError::new(format_args!(
				"Invalid JavaScript function, encountered unexpected eof"
			))
			.with_span(span, MessageKind::Error)
			.with_data_pending());
		};
		if byte == b'*' && lexer.reader.peek() == Some(b'/') {
			lexer.reader.next();
			return Ok(());
		}
		// check for invalid characters.
		lexer.reader.convert_to_char(byte)?;
	}
}