Skip to main content

surql_parser/upstream/syn/lexer/compound/
js.rs

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