Fix comments parsing.
This commit is contained in:
parent
fc54fdc907
commit
719f0babbf
@ -16,6 +16,7 @@ Bug fixes
|
|||||||
* Constants are no longer propagated by the optimizer if shadowed by a non-constant variable.
|
* Constants are no longer propagated by the optimizer if shadowed by a non-constant variable.
|
||||||
* Constants passed as the `this` parameter to Rhai functions now throws an error if assigned to.
|
* Constants passed as the `this` parameter to Rhai functions now throws an error if assigned to.
|
||||||
* Generic type parameter of `Engine::register_iterator` is `IntoIterator` instead of `Iterator`.
|
* Generic type parameter of `Engine::register_iterator` is `IntoIterator` instead of `Iterator`.
|
||||||
|
* Fixes parsing of block comments ending with `**/` or inner blocks starting with `//*`.
|
||||||
|
|
||||||
Breaking changes
|
Breaking changes
|
||||||
----------------
|
----------------
|
||||||
|
69
src/token.rs
69
src/token.rs
@ -918,41 +918,41 @@ fn eat_next(stream: &mut impl InputStream, pos: &mut Position) -> Option<char> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Scan for a block comment until the end.
|
/// Scan for a block comment until the end.
|
||||||
fn scan_comment(
|
fn scan_block_comment(
|
||||||
stream: &mut impl InputStream,
|
stream: &mut impl InputStream,
|
||||||
mut level: usize,
|
mut level: usize,
|
||||||
pos: &mut Position,
|
pos: &mut Position,
|
||||||
comment: &mut String,
|
comment: &mut Option<String>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
while let Some(c) = stream.get_next() {
|
while let Some(c) = stream.get_next() {
|
||||||
pos.advance();
|
pos.advance();
|
||||||
|
|
||||||
if !comment.is_empty() {
|
if let Some(ref mut comment) = comment {
|
||||||
comment.push(c);
|
comment.push(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
match c {
|
match c {
|
||||||
'/' => {
|
'/' => {
|
||||||
if let Some(c2) = stream.get_next() {
|
if let Some(c2) = stream.peek_next() {
|
||||||
if !comment.is_empty() {
|
if c2 == '*' {
|
||||||
|
eat_next(stream, pos);
|
||||||
|
if let Some(ref mut comment) = comment {
|
||||||
comment.push(c2);
|
comment.push(c2);
|
||||||
}
|
}
|
||||||
if c2 == '*' {
|
|
||||||
level += 1;
|
level += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos.advance();
|
|
||||||
}
|
}
|
||||||
'*' => {
|
'*' => {
|
||||||
if let Some(c2) = stream.get_next() {
|
if let Some(c2) = stream.peek_next() {
|
||||||
if !comment.is_empty() {
|
if c2 == '/' {
|
||||||
|
eat_next(stream, pos);
|
||||||
|
if let Some(ref mut comment) = comment {
|
||||||
comment.push(c2);
|
comment.push(c2);
|
||||||
}
|
}
|
||||||
if c2 == '/' {
|
|
||||||
level -= 1;
|
level -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos.advance();
|
|
||||||
}
|
}
|
||||||
'\n' => pos.new_line(),
|
'\n' => pos.new_line(),
|
||||||
_ => (),
|
_ => (),
|
||||||
@ -1032,11 +1032,16 @@ fn get_next_token_inner(
|
|||||||
// Still inside a comment?
|
// Still inside a comment?
|
||||||
if state.comment_level > 0 {
|
if state.comment_level > 0 {
|
||||||
let start_pos = *pos;
|
let start_pos = *pos;
|
||||||
let mut comment = String::new();
|
let mut comment = if state.include_comments {
|
||||||
state.comment_level = scan_comment(stream, state.comment_level, pos, &mut comment);
|
Some(String::new())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if state.include_comments || is_doc_comment(&comment) {
|
state.comment_level = scan_block_comment(stream, state.comment_level, pos, &mut comment);
|
||||||
return Some((Token::Comment(comment), start_pos));
|
|
||||||
|
if state.include_comments || is_doc_comment(comment.as_ref().unwrap()) {
|
||||||
|
return Some((Token::Comment(comment.unwrap()), start_pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1282,10 +1287,13 @@ fn get_next_token_inner(
|
|||||||
('/', '/') => {
|
('/', '/') => {
|
||||||
eat_next(stream, pos);
|
eat_next(stream, pos);
|
||||||
|
|
||||||
let mut comment = match stream.peek_next().unwrap() {
|
let mut comment = match stream.peek_next() {
|
||||||
'/' => "///".to_string(),
|
Some('/') => {
|
||||||
_ if state.include_comments => "//".to_string(),
|
eat_next(stream, pos);
|
||||||
_ => String::new(),
|
Some("///".to_string())
|
||||||
|
}
|
||||||
|
_ if state.include_comments => Some("//".to_string()),
|
||||||
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
while let Some(c) = stream.get_next() {
|
while let Some(c) = stream.get_next() {
|
||||||
@ -1293,30 +1301,33 @@ fn get_next_token_inner(
|
|||||||
pos.new_line();
|
pos.new_line();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if let Some(ref mut comment) = comment {
|
||||||
if !comment.is_empty() {
|
|
||||||
comment.push(c);
|
comment.push(c);
|
||||||
}
|
}
|
||||||
pos.advance();
|
pos.advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.include_comments || is_doc_comment(&comment) {
|
if let Some(comment) = comment {
|
||||||
return Some((Token::Comment(comment), start_pos));
|
return Some((Token::Comment(comment), start_pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
('/', '*') => {
|
('/', '*') => {
|
||||||
state.comment_level = 1;
|
state.comment_level = 1;
|
||||||
|
|
||||||
eat_next(stream, pos);
|
eat_next(stream, pos);
|
||||||
|
|
||||||
let mut comment = match stream.peek_next().unwrap() {
|
let mut comment = match stream.peek_next() {
|
||||||
'*' => "/**".to_string(),
|
Some('*') => {
|
||||||
_ if state.include_comments => "/*".to_string(),
|
eat_next(stream, pos);
|
||||||
_ => String::new(),
|
Some("/**".to_string())
|
||||||
|
}
|
||||||
|
_ if state.include_comments => Some("/*".to_string()),
|
||||||
|
_ => None,
|
||||||
};
|
};
|
||||||
state.comment_level = scan_comment(stream, state.comment_level, pos, &mut comment);
|
|
||||||
|
|
||||||
if state.include_comments || is_doc_comment(&comment) {
|
state.comment_level =
|
||||||
|
scan_block_comment(stream, state.comment_level, pos, &mut comment);
|
||||||
|
|
||||||
|
if let Some(comment) = comment {
|
||||||
return Some((Token::Comment(comment), start_pos));
|
return Some((Token::Comment(comment), start_pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,62 @@ fn test_comments() -> Result<(), Box<EvalAltResult>> {
|
|||||||
42
|
42
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_eq!(engine.eval::<()>("/* Hello world */")?, ());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
#[test]
|
||||||
|
fn test_comments_doc() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
let engine = Engine::new();
|
||||||
|
|
||||||
|
let ast = engine.compile(
|
||||||
|
r"
|
||||||
|
/// Hello world
|
||||||
|
|
||||||
|
|
||||||
|
fn foo() {}
|
||||||
|
",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
ast.iter_functions().next().unwrap().comments[0],
|
||||||
|
"/// Hello world"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(engine
|
||||||
|
.compile(
|
||||||
|
r"
|
||||||
|
/// Hello world
|
||||||
|
let x = 42;
|
||||||
|
"
|
||||||
|
)
|
||||||
|
.is_err());
|
||||||
|
|
||||||
|
let ast = engine.compile(
|
||||||
|
r"
|
||||||
|
/** Hello world
|
||||||
|
** how are you?
|
||||||
|
**/
|
||||||
|
|
||||||
|
fn foo() {}
|
||||||
|
",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
ast.iter_functions().next().unwrap().comments[0],
|
||||||
|
"/** Hello world\n ** how are you?\n **/"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(engine
|
||||||
|
.compile(
|
||||||
|
r"
|
||||||
|
/** Hello world */
|
||||||
|
let x = 42;
|
||||||
|
"
|
||||||
|
)
|
||||||
|
.is_err());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user