Skip to content

Commit

Permalink
feat: basic support for range for
Browse files Browse the repository at this point in the history
  • Loading branch information
Enter-tainer committed Nov 7, 2022
1 parent 3de468b commit 79a19b3
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cxx2flow"
version = "0.5.9"
version = "0.5.10"
edition = "2018"
authors = ["mgt <[email protected]>"]
description = "Convert your C/C++ code to control flow chart"
Expand Down
1 change: 1 addition & 0 deletions README-en.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,4 @@ https://github.com/Enter-tainer/cxx2flow

- The support of preprocessor is based on `cpp`, and is disabled by default. `--cpp` flag is needed to enable it. It will fail if `cpp` does not exist in `PATH`.
- Supported control flow keyword: while,for,if,break,continue,break,return,switch, goto, do-while。
- Very basic support for range based loop in C++ 11.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,4 @@ https://github.com/Enter-tainer/cxx2flow

- 对于预处理器的支持基于 `cpp` ,默认关闭,需要使用 `--cpp` 参数手动启用。如果 `PATH` 中不存在 `cpp` 则会失败。
- 支持的控制流语句有:while,for,if,break,continue,break,return,switch, goto, do-while。
- 对 range for 有基本支持。部分情况下,受到 tree-sitter-cpp 能力限制,会出现一些问题
29 changes: 29 additions & 0 deletions assets/rangefor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
void basic() {
for (auto i : vec) {
i = i + 1;
}
}

void auto_ref() {
for (auto & i : map) {
a;
}
}

void const_auto_rvref() {
for (const auto &&i : vec) {
i - 1;
}
}

void auto_destruct() {
for (auto [x, y] : vec) {
x + y;
}
}

void int_init() {
for (int i : vec) {
i;
}
}
29 changes: 29 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ fn parse_single_stat(stat: Node, content: &[u8]) -> Result<Rc<RefCell<Ast>>> {
"while_statement" => parse_while_stat(stat, content),
"do_statement" => parse_do_while_stat(stat, content),
"for_statement" => parse_for_stat(stat, content),
"for_range_loop" => parse_range_for_stat(stat, content),
"switch_statement" => parse_switch_stat(stat, content),
"goto_statement" => parse_goto_stat(stat, content),
"expression_statement" | "declaration" => {
Expand Down Expand Up @@ -422,3 +423,31 @@ fn parse_for_stat(for_stat: Node, content: &[u8]) -> Result<Rc<RefCell<Ast>>> {
)));
Ok(res)
}

fn parse_range_for_stat(range_for_stat: Node, content: &[u8]) -> Result<Rc<RefCell<Ast>>> {
let ty = range_for_stat.child_by_field_name("type").ok_or(Error::ChildNotFound)?;
let declarator = range_for_stat.child_by_field_name("declarator").ok_or(Error::ChildNotFound)?;
let range = range_for_stat.child_by_field_name("right").ok_or(Error::ChildNotFound)?;
let body = range_for_stat.child_by_field_name("body").ok_or(Error::ChildNotFound)?;
let body = parse_stat(body, content)?;
let type_text = ty.utf8_text(content)?;
let init_text = declarator.utf8_text(content)?;
let range_text = range.utf8_text(content)?;
let real_init_text = format!("{init_text}_iter = {range_text}.begin()");
let real_cond_text = format!("{init_text}_iter != {range_text}.end()");
let real_update_text = format!("++{init_text}_iter");
let res = Rc::new(RefCell::new(Ast::new(
AstNode::For {
init: real_init_text,
cond: real_cond_text,
upd: real_update_text,
body: Rc::new(RefCell::new(Ast::new(AstNode::Compound(vec![
Rc::new(RefCell::new(Ast::new(AstNode::Stat(format!("{type_text} {init_text} = *{init_text}_iter")), range_for_stat.byte_range(), None))),
body
]), range_for_stat.byte_range(), None))),
},
range_for_stat.byte_range(),
None,
)));
Ok(res)
}

0 comments on commit 79a19b3

Please sign in to comment.