summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs2
-rw-r--r--src/parser.rs77
2 files changed, 64 insertions, 15 deletions
diff --git a/src/main.rs b/src/main.rs
index 6c45741..726ed1c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,7 @@
use java2flowchart::parser::parse;
fn main() {
- let test = "int a";
+ let test = "if (a) {f}";
println!("{:#?}", parse(test));
}
diff --git a/src/parser.rs b/src/parser.rs
index 69c4856..544c296 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -1,5 +1,7 @@
use crate::tokenizer::{self, If, Keyword::*, Loop};
+pub type SplitWithMetadata<'a> = Vec<(&'a str, Option<Metadata>)>;
+
pub const EXPRESSION_DELIMITERS: &[char] = &[
';', '{', '}',
];
@@ -11,40 +13,87 @@ pub enum Scope {
}
#[derive(Debug)]
-pub enum Expr<'a> {
+pub enum Metadata {
+ StartScope,
+ EndScope,
+}
+
+#[derive(Debug)]
+pub enum ExprT<'a> {
StartOrStop(bool),
Decision((&'a str, Scope)),
IO(&'a str),
Process(&'a str),
}
-pub fn delimit(str: &str) -> Vec<&str> {
- str.split(|c| EXPRESSION_DELIMITERS.contains(&c))
- .filter(|c| !c.is_empty())
- .collect()
+#[derive(Debug)]
+pub struct Expr<'a> {
+ pub expr: ExprT<'a>,
+ pub meta: Option<Metadata>,
+}
+
+pub fn delimit(s: &str) -> SplitWithMetadata<'_> {
+ s.split_inclusive([
+ ';', '{', '}',
+ ])
+ .fold(Vec::new(), |mut acc, part| {
+ if let Some((i, ch)) = part
+ .char_indices()
+ .next_back()
+ {
+ let body = if ch == ';' || ch == '{' || ch == '}' {
+ part[..i].trim()
+ } else {
+ part.trim()
+ };
+ if !body.is_empty() {
+ acc.push((body, None));
+ }
+ match ch {
+ '{' => {
+ if let Some(last) = acc.last_mut() {
+ last.1 = Some(Metadata::StartScope);
+ }
+ }
+ '}' => {
+ if let Some(last) = acc.last_mut() {
+ last.1 = Some(Metadata::EndScope);
+ }
+ }
+ _ => {}
+ }
+ }
+ acc
+ })
}
-pub fn process(strs: Vec<&str>) -> Vec<Expr<'_>> {
+pub fn process(strs: SplitWithMetadata<'_>) -> Vec<Expr<'_>> {
let mut exprs = Vec::new();
- for str in strs {
- let mut exp: Option<Expr> = None;
+ for (str, meta) in strs {
+ let mut exp: Option<ExprT> = None;
// TODO: fix one line if else as not delimited by {}
for s in str.split_whitespace() {
if let Some(token) = tokenizer::parse(s) {
exp = match token {
- If(t) => Some(Expr::Decision((str, Scope::If(t.to_owned())))),
- Loop(t) => Some(Expr::Decision((str, Scope::Loop(t.to_owned())))),
- Throw => Some(Expr::IO(str)),
- IO => Some(Expr::IO(str)),
+ If(t) => Some(ExprT::Decision((str, Scope::If(t.to_owned())))),
+ Loop(t) => Some(ExprT::Decision((str, Scope::Loop(t.to_owned())))),
+ Throw => Some(ExprT::IO(str)),
+ IO => Some(ExprT::IO(str)),
}
}
}
match exp {
- Some(exp) => exprs.push(exp),
- None => exprs.push(Expr::Process(str)),
+ Some(expr) => exprs.push(Expr {
+ expr,
+ meta,
+ }),
+ None => exprs.push(Expr {
+ expr: ExprT::Process(str),
+ meta: None,
+ }),
}
}