From 8687b21821551f06a405b45d0c85ee73d9be60b5 Mon Sep 17 00:00:00 2001 From: Hare Date: Mon, 9 Dec 2024 04:22:02 +0900 Subject: [PATCH] add label behaviour; update main.rs for improved output formatting --- src/main.rs | 3 +- src/om/behavior.rs | 74 ++++++++----- src/om/tokenizer.rs | 252 ++++++++++++++++++++------------------------ 3 files changed, 166 insertions(+), 163 deletions(-) diff --git a/src/main.rs b/src/main.rs index c36a6b4..e4c6f39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ fn main() { let mut input = String::new(); io::stdin().read_to_string(&mut input).expect("Failed to read from stdin"); om::tokenizer::Tokenizer::new(input).for_each(|token| { - println!("{:?}", token); + println!("\n{:?}", token); }); + println!(); } diff --git a/src/om/behavior.rs b/src/om/behavior.rs index 906c00b..86e6846 100644 --- a/src/om/behavior.rs +++ b/src/om/behavior.rs @@ -1,36 +1,56 @@ +use std::str; #[derive(Debug, Clone, PartialEq, Eq)] -pub struct BehaviorItem { - pub prefix: Option, - pub key: String, - pub value: String, +pub enum BehaviorItem { + KeyValue { + prefix: Option, + key: String, + value: String, + }, + Label { + prefix: Option, + label: String, + }, } impl BehaviorItem { - pub fn new() -> Self { - Self { - prefix: Option::None, - key: String::new(), - value: String::new(), + pub fn from(input: &str) -> Self { + let (prefix, part) = input.split_once(':').unwrap_or(("", input)); + let (key, value) = part.split_once('=').unwrap_or((part, "")); + if value.is_empty() { + Self::Label { + prefix: if prefix.is_empty() { + None + } else { + Some(prefix.to_string()) + }, + label: key.to_string(), + } + } else { + Self::KeyValue { + prefix: if prefix.is_empty() { + None + } else { + Some(prefix.to_string()) + }, + key: key.to_string(), + value: value.to_string(), + } + } } - } +} - pub fn set_prefix(&mut self, prefix: String) { - self.prefix = Some(prefix); - } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Behavior { + pub items: Vec, +} - pub fn set_value(&mut self, value: String) { - self.value = value; - } - - pub fn set_key(&mut self, key: String) { - self.key = key; - } - - pub fn name(&self) -> String { - match &self.prefix { - Some(prefix) => format!("{}:{}", prefix, self.key), - None => self.key.clone(), +impl Behavior { + pub fn new() -> Self { + Self { items: Vec::new() } } - } -} \ No newline at end of file + + pub fn add_item(&mut self, item: BehaviorItem) { + self.items.push(item); + } +} diff --git a/src/om/tokenizer.rs b/src/om/tokenizer.rs index 794c466..f7988dd 100644 --- a/src/om/tokenizer.rs +++ b/src/om/tokenizer.rs @@ -1,3 +1,5 @@ +use crate::om::behavior::*; + pub struct Tokenizer { state: State, pos: usize, @@ -34,15 +36,20 @@ impl Iterator for Tokenizer { type Item = Token; fn next(&mut self) -> Option { - if self.is_eof() { - return None; - } loop { if self.reconsume { self.pos -= 1; self.reconsume = false; } + if self.pos >= self.input.len() { + if self.pos > self.input.len() { + return None; + } + self.pos += 1; + return Some(Token::EOF); + } let c = self.consume_input(); + print!("{}", c); match self.state { State::Data => match c { '(' => { @@ -53,15 +60,12 @@ impl Iterator for Tokenizer { self.state = State::Data; return Some(Token::NodeEnd); } - _ if self.is_eof() => { - return Some(Token::EOF); - } _ => { return Some(Token::Character(c)); } }, State::NodeOpen => match c { - ' ' | '\n' => {} + ' ' | '\n' | '\t' => {} x if x.is_ascii_alphanumeric() => { self.state = State::Define; self.reconsume = true; @@ -73,126 +77,104 @@ impl Iterator for Tokenizer { _ => panic!("Unexpected character: {}", c), }, State::Define => match c { - x if x.is_ascii_alphanumeric() => { - self.buffer.push(c); - } - ' ' | '\n' => { + ' ' | '\n' | '\t' => { self.state = State::AfterDefine; self.latest = Some(Token::Define { name: self.buffer.clone(), - behavior: Vec::new(), + behavior: Behavior::new(), }); self.buffer.clear(); } - _ if self.is_eof() => { - return Some(Token::EOF); + x => { + if !x.is_ascii_alphanumeric() { + panic!("Unexpected character: {}", c); + } + self.buffer.push(c); + if self.is_eof() { + return Some(Token::Define { + name: self.buffer.clone(), + behavior: Behavior::new(), + }); + } } - _ => panic!("Unexpected character: {}", c), }, - State::AfterDefine => match c { - ' ' | '\n' => {} - '[' => { + State::AfterDefine => { + if self.is_eof() { + return self.latest.take(); + } + match c { + ' ' | '\n' | '\t' => {} + '[' => { + self.state = State::Behavior; + } + _ => { + self.state = State::Data; + self.reconsume = true; + return self.latest.take(); + } + } + } + State::Behavior => match c { + ' ' | '\n' | '\t' => { + self.state = State::BehaviorSeparator; + } + ']' => { + if let Some(t) = self.latest.as_mut() { + if let Token::Define { behavior, .. } = t { + behavior.add_item(BehaviorItem::from(&self.buffer)); + } + } + self.buffer.clear(); + self.state = State::Data; + return self.latest.take(); + } + x => { + if !x.is_ascii_alphanumeric() && x != '=' && x != ':' { + panic!("Unexpected character: {}", x); + } + self.buffer.push(x); + if self.is_eof() { + if let Some(t) = self.latest.as_mut() { + if let Token::Define { behavior, .. } = t { + behavior.add_item(BehaviorItem::from(&self.buffer)); + } + } + self.buffer.clear(); + self.state = State::Data; + return self.latest.take(); + } + } + }, + State::BehaviorSeparator => match c { + ' ' | '\n' | '\t' => {} + '=' => { + self.state = State::Behavior; + self.buffer.push('='); + } + ']' => { + self.reconsume = true; self.state = State::Behavior; } - _ if self.is_eof() => { - return Some(Token::EOF); - } - _ => { - self.state = State::Data; - self.reconsume = true; - return self.latest.take(); - } - }, - State::Behavior => match c { - x if x.is_ascii_alphanumeric() => { - self.reconsume = true; - if let Some(t) = self.latest.as_mut() { - match t { - Token::Define { - name: _, - ref mut behavior, - } => { - behavior.push(BehaviorItem::new()); - } - _ => {} - } + x => { + if !x.is_ascii_alphanumeric() { + panic!("Unexpected character: {}", x); } - self.state = State::BehaviorKey; - } - ' ' | '\n' => {} - ']' => { - self.state = State::Data; - return self.latest.take(); - } - _ if self.is_eof() => { - return Some(Token::EOF); - } - _ => panic!("Unexpected character: {}", c), - }, - State::BehaviorKey => match c { - x if x.is_ascii_alphanumeric() => { - self.buffer.push(c); - } - ':' => { - if let Some(t) = self.latest.as_mut() { - match t { - Token::Define { - name: _, - ref mut behavior, - } => { - behavior.last_mut().unwrap().set_prefix(self.buffer.clone()); - self.buffer.clear(); - self.state = State::BehaviorKey; + if self.buffer.ends_with('=') { + self.reconsume = true; + self.state = State::Behavior; + } else { + if let Some(t) = self.latest.as_mut() { + if let Token::Define { behavior, .. } = t { + behavior.add_item(BehaviorItem::from(&self.buffer)); } - _ => {} } - } - } - '=' => { - if let Some(t) = self.latest.as_mut() { - match t { - Token::Define { - name: _, - ref mut behavior, - } => { - behavior.last_mut().unwrap().set_key(self.buffer.clone()); - self.buffer.clear(); - self.state = State::BehaviorValue; - } - _ => {} - } - } - } - _ if self.is_eof() => { - return Some(Token::EOF); - } - _ => panic!("Unexpected character: {}", c), - }, - State::BehaviorValue => match c { - x if x.is_ascii_alphanumeric() => { - self.buffer.push(c); - } - ' ' | '\n' | '\t' | ']' => { - if let Some(t) = self.latest.as_mut() { - match t { - Token::Define { - name: _, - ref mut behavior, - } => { - behavior.last_mut().unwrap().set_value(self.buffer.clone()); - self.buffer.clear(); - self.state = State::Behavior; - self.reconsume = true; - } - _ => {} - } - } - } + self.buffer.clear(); - _ if self.is_eof() => { - return Some(Token::EOF); + self.reconsume = true; + self.state = State::Behavior; + println!("BehaviorItem: {:?}", BehaviorItem::from(&self.buffer)); + } } - _ => panic!("Unexpected character: {}", c), }, } } @@ -206,18 +188,12 @@ enum State { Define, AfterDefine, Behavior, - BehaviorKey, - BehaviorValue, + BehaviorSeparator, } -use crate::om::behavior::BehaviorItem; - #[derive(Debug, Clone, PartialEq, Eq)] pub enum Token { - Define { - name: String, - behavior: Vec, - }, + Define { name: String, behavior: Behavior }, Character(char), NodeEnd, EOF, @@ -241,11 +217,13 @@ mod tests { let expected = [ Token::Define { name: "foo".to_string(), - behavior: vec![BehaviorItem { - prefix: Some("prefix".to_string()), - key: "key".to_string(), - value: "value".to_string(), - }], + behavior: Behavior { + items: vec![BehaviorItem::KeyValue { + prefix: Some("prefix".to_string()), + key: "key".to_string(), + value: "value".to_string(), + }], + }, }, Token::EOF, ]; @@ -261,19 +239,23 @@ mod tests { let expected = [ Token::Define { name: "foo".to_string(), - behavior: vec![BehaviorItem { - prefix: Some("prefix".to_string()), - key: "key".to_string(), - value: "value".to_string(), - }], + behavior: Behavior { + items: vec![BehaviorItem::KeyValue { + prefix: Some("prefix".to_string()), + key: "key".to_string(), + value: "value".to_string(), + }], + }, }, Token::Define { name: "bar".to_string(), - behavior: vec![BehaviorItem { - prefix: Some("prefix".to_string()), - key: "key".to_string(), - value: "value".to_string(), - }], + behavior: Behavior { + items: vec![BehaviorItem::KeyValue { + prefix: Some("prefix".to_string()), + key: "key".to_string(), + value: "value".to_string(), + }], + }, }, Token::EOF, ];