diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2025-09-27 17:59:43 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2025-09-27 17:59:52 +0800 |
| commit | 76af2f9a4a06140d7e00706817b59678c4468d1a (patch) | |
| tree | 80d4f3d799fa465500d5c54ff609b4ccc28b670e /src | |
| parent | 282b9fad4db35d21618226dcd28dd041c9405930 (diff) | |
parser: preserve scope data as metadata
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 2 | ||||
| -rw-r--r-- | src/parser.rs | 77 |
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, + }), } } |
