From 2cc8651e7eb0904c946a31d3f0e79fc7f9ad1f88 Mon Sep 17 00:00:00 2001 From: Masato Imai Date: Thu, 14 Jul 2022 11:29:34 +0900 Subject: [PATCH] add mode grammar --- gpsl/src/grammar/GpslLexer.g4 | 3 +- gpsl/src/grammar/GpslParser.g4 | 1 + gpsl/src/node.rs | 12 +- gpsl/src/parser.rs | 72 ++++++-- gpsl/src/tokenizer.rs | 15 +- gpsl/src/vm/gpsl.rs | 298 ++++++++++++++------------------- test.gpsl | 3 + 7 files changed, 205 insertions(+), 199 deletions(-) create mode 100644 test.gpsl diff --git a/gpsl/src/grammar/GpslLexer.g4 b/gpsl/src/grammar/GpslLexer.g4 index b33dbe4..3af6968 100644 --- a/gpsl/src/grammar/GpslLexer.g4 +++ b/gpsl/src/grammar/GpslLexer.g4 @@ -5,6 +5,7 @@ WS -> skip ; +SHARP: '#' ; DOLLER: '$' ; ADD: '+' ; SUB: '-' ; @@ -47,4 +48,4 @@ RETURN: 'return' ; NUM: [1-9] [0-9]* ; TEXT: QUOTE [a-zA-Z0-9_-]* QUOTE ; -IDENT: [a-zA-Z_]+ ; \ No newline at end of file +IDENT: [a-zA-Z_]+ ; diff --git a/gpsl/src/grammar/GpslParser.g4 b/gpsl/src/grammar/GpslParser.g4 index bf18158..1c460c0 100644 --- a/gpsl/src/grammar/GpslParser.g4 +++ b/gpsl/src/grammar/GpslParser.g4 @@ -23,6 +23,7 @@ if: IF LPAREN expr RPAREN stmt (ELSE stmt)? ; while: WHILE LPAREN expr RPAREN stmt ; for: FOR LPAREN expr? SEMICOLON expr? SEMICOLON expr? RPAREN stmt ; +mode: SHARP IDENT ; permission: DOLLER LPAREN ( IDENT LBRACKET ( IDENT COMMA? )* RBRACKET COMMA? )* RPAREN ; expr: assign ; diff --git a/gpsl/src/node.rs b/gpsl/src/node.rs index d6dcc92..e8594f6 100644 --- a/gpsl/src/node.rs +++ b/gpsl/src/node.rs @@ -18,11 +18,14 @@ pub enum Node { Function { name: String, args: HashMap, - body: Vec> + body: Vec>, + }, + Mode { + mode: String, }, Permission { accept: Vec, - reject: Vec + reject: Vec, }, Operator { kind: NodeKind, @@ -58,7 +61,8 @@ pub enum Node { }, Block { stmts: Vec>, - permission: Option> + permission: Option>, + mode: Option>, }, Define { name: String, @@ -68,7 +72,7 @@ pub enum Node { name: String, args: Vec>, }, - None + None, } impl Node { diff --git a/gpsl/src/parser.rs b/gpsl/src/parser.rs index 34d055a..58c1f4b 100644 --- a/gpsl/src/parser.rs +++ b/gpsl/src/parser.rs @@ -15,7 +15,7 @@ impl Parser { loop { if self.tokenizer.current_token().kind != TokenKind::EOF { let function = self.function()?; - if let Node::Function{name, .. } = *function.clone() { + if let Node::Function { name, .. } = *function.clone() { nodes.insert(name, function); } } else { @@ -28,19 +28,27 @@ impl Parser { function: FN IDENT LPAREN (IDENT COLON IDENT COMMA?)* RPAREN (ARROW IDENT)? block ; */ pub fn function(&mut self) -> Result, String> { - if self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from("fn")) { + if self + .tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from("fn")) + { debug!("parsing function"); let func_name = self.tokenizer.current_token().clone(); self.tokenizer.expect_kind(TokenKind::IDENT)?; let mut args = HashMap::new(); self.tokenizer.expect(String::from("("))?; debug!("parsing args"); - while !self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(")")) { + while !self + .tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(")")) + { debug!("consume argument"); let name = self.tokenizer.expect_ident()?; - self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(":")); + self.tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(":")); let type_str = self.tokenizer.expect_ident()?; - self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(",")); + self.tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(",")); args.insert(name, type_str); } @@ -53,7 +61,7 @@ impl Parser { return Ok(Box::new(Node::Function { name: func_name.str, args, - body: nodes + body: nodes, })); } } else { @@ -110,9 +118,17 @@ impl Parser { None }; + debug!("parsing mode"); + let mode = if self.tokenizer.current_token().str == "#" { + Some(self.mode()?) + } else { + None + }; + if self .tokenizer - .consume_kind_str(TokenKind::RESERVED, String::from("{")) || permission != None + .consume_kind_str(TokenKind::RESERVED, String::from("{")) + || permission != None { let mut stmts: Vec> = vec![]; loop { @@ -120,7 +136,11 @@ impl Parser { .tokenizer .consume_kind_str(TokenKind::RESERVED, String::from("}")) { - return Ok(Box::new(Node::Block { stmts, permission: permission })); + return Ok(Box::new(Node::Block { + stmts, + permission: permission, + mode: mode, + })); } else { stmts.push(self.stmt()?); } @@ -207,6 +227,17 @@ impl Parser { return node; } + /* + mode: SHARP IDENT ; + */ + pub fn mode(&mut self) -> Result, String> { + self.tokenizer.expect(String::from("#"))?; + let mode = self.tokenizer.current_token().clone(); + self.tokenizer.expect_kind(TokenKind::IDENT)?; + self.tokenizer.expect(String::from(";"))?; + return Ok(Box::new(Node::Mode { mode: mode.str })); + } + /* permission: DOLLER LPAREN ( IDENT LBRACKET ( IDENT COMMA? )* RBRACKET COMMA? )* RPAREN ; */ @@ -217,15 +248,23 @@ impl Parser { let mut accept: Vec = vec![]; let mut reject: Vec = vec![]; - while !self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(")")) { + while !self + .tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(")")) + { let name = self.tokenizer.expect_ident()?; if name != "accept" && name != "reject" { return Err(String::from(format!("Unexpected: {}", name))); } - self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from("[")); - while !self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from("]")) { + self.tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from("[")); + while !self + .tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from("]")) + { let permission = self.tokenizer.expect_ident()?; - self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(",")); + self.tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(",")); if name == "accept" { accept.push(permission); @@ -234,7 +273,8 @@ impl Parser { } } - self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(",")); + self.tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(",")); } Ok(Box::new(Node::Permission { accept, reject })) @@ -378,7 +418,7 @@ impl Parser { return Ok(Box::new(Node::Call { name: node.clone(), args: args, - })) + })); } return Ok(Node::new_lvar_node(node.clone())); } @@ -386,9 +426,7 @@ impl Parser { if self.tokenizer.current_token().kind == TokenKind::TEXT { let text = self.tokenizer.current_token().str.clone(); self.tokenizer.consume_kind(TokenKind::TEXT); - return Ok(Box::new(Node::Text { - value: text, - })); + return Ok(Box::new(Node::Text { value: text })); } return Ok(Node::new_num_node(self.tokenizer.expect_number()?)); diff --git a/gpsl/src/tokenizer.rs b/gpsl/src/tokenizer.rs index a17ae8c..4890912 100644 --- a/gpsl/src/tokenizer.rs +++ b/gpsl/src/tokenizer.rs @@ -33,7 +33,12 @@ impl Tokenizer { } pub fn consume_kind_str(&mut self, kind: TokenKind, string: String) -> bool { - debug!("consume kind str {:?} {:?} {:?}", kind ,string, self.current_token()); + debug!( + "consume kind str {:?} {:?} {:?}", + kind, + string, + self.current_token() + ); return if self.current_token().kind == kind && self.current_token().str == string { self.cursor += 1; true @@ -63,10 +68,7 @@ impl Tokenizer { pub fn expect_ident(&mut self) -> Result { debug!("Expect IDENT {:?}", self.current_token()); if self.current_token().kind != TokenKind::IDENT { - return Err(format!( - "Unexpected type : {:?}", - self.current_token().kind - )); + return Err(format!("Unexpected type : {:?}", self.current_token().kind)); } let val = self.current_token().str.clone(); self.cursor += 1; @@ -113,6 +115,7 @@ impl Tokenizer { String::from("-="), String::from("*="), String::from("/="), + String::from("#"), String::from("$"), String::from("+"), String::from("-"), @@ -159,7 +162,7 @@ impl Tokenizer { self.tokens.push(Token { kind: TokenKind::TEXT, str: text, - num: 0 + num: 0, }); continue; } diff --git a/gpsl/src/vm/gpsl.rs b/gpsl/src/vm/gpsl.rs index d523ff7..1570c5e 100644 --- a/gpsl/src/vm/gpsl.rs +++ b/gpsl/src/vm/gpsl.rs @@ -11,7 +11,7 @@ pub struct Block { pub accept: Vec, pub reject: Vec, pub variables: HashMap, - pub is_split: bool + pub is_split: bool, } pub struct GPSL { @@ -19,7 +19,8 @@ pub struct GPSL { pub global_variables: Vec, pub source: Source, pub blocks: VecDeque, - pub external_func: Vec, Vec, Vec) -> ExternalFuncReturn> + pub external_func: + Vec, Vec, Vec) -> ExternalFuncReturn>, } #[derive(Clone, Debug)] @@ -41,13 +42,19 @@ impl VariableStatus { } impl GPSL { - pub fn new(source: Source, functions: Option>>, external_func: Vec, Vec, Vec) -> ExternalFuncReturn>) -> GPSL { + pub fn new( + source: Source, + functions: Option>>, + external_func: Vec< + fn(String, Vec, Vec, Vec) -> ExternalFuncReturn, + >, + ) -> GPSL { GPSL { source, functions, global_variables: vec![], blocks: VecDeque::new(), - external_func + external_func, } } @@ -58,7 +65,7 @@ impl GPSL { } if self.blocks[x].is_split { - break + break; } } None @@ -75,7 +82,7 @@ impl GPSL { } if self.blocks[x].is_split { - break + break; } } None @@ -83,12 +90,8 @@ impl GPSL { pub fn extract_number(node: Variable) -> Result { match node { - Variable::Number { value } => { - Ok(value) - }, - _ => { - Err(String::from("Not a number")) - } + Variable::Number { value } => Ok(value), + _ => Err(String::from("Not a number")), } } @@ -105,8 +108,18 @@ impl GPSL { } if let Some(functions) = self.functions.clone() { - debug!("functions: {:?}", functions.iter().map(|f| format!("{},", f.0)).collect::()); - debug!("{}: {}", &function_name, functions.contains_key(&function_name)); + debug!( + "functions: {:?}", + functions + .iter() + .map(|f| format!("{},", f.0)) + .collect::() + ); + debug!( + "{}: {}", + &function_name, + functions.contains_key(&function_name) + ); if functions.contains_key(&function_name) { if let Node::Function { body, .. } = &*(functions[&function_name]) { for program in body { @@ -119,7 +132,7 @@ impl GPSL { accept: block.accept.clone(), reject: block.reject.clone(), variables: HashMap::new(), - is_split: true + is_split: true, }); let res = self.evaluate(Box::new(*program.clone())); @@ -146,7 +159,12 @@ impl GPSL { for func in f { let block = self.blocks.front().unwrap(); - let res = func(function_name.clone(), args_value.clone(), block.accept.clone(), block.reject.clone()); + let res = func( + function_name.clone(), + args_value.clone(), + block.accept.clone(), + block.reject.clone(), + ); if res.status == ExternalFuncStatus::SUCCESS { return Ok(res.value); } @@ -157,16 +175,8 @@ impl GPSL { Err(format!("Function not found: {}", function_name)) } - Node::Text { value } => { - Ok(Some(Variable::Text { - value - })) - } - Node::Number { value } => { - Ok(Some(Variable::Number { - value - })) - } + Node::Text { value } => Ok(Some(Variable::Text { value })), + Node::Number { value } => Ok(Some(Variable::Number { value })), Node::Operator { kind, lhs, rhs } => { if kind == NodeKind::ASSIGN { debug!("Assign: {:?}", self.blocks.front()); @@ -191,132 +201,76 @@ impl GPSL { if let Some(lhs) = lhs { if let Some(rhs) = rhs { match kind { - NodeKind::ADD => { - match GPSL::extract_number(lhs) { - Ok(lhs) => { - match GPSL::extract_number(rhs) { - Ok(rhs) => { - Ok(Some(Variable::Number { - value: lhs + rhs - })) - } - Err(err) => { Err(err) } - } - } - Err(err) => { Err(err) } - } + NodeKind::ADD => match GPSL::extract_number(lhs) { + Ok(lhs) => match GPSL::extract_number(rhs) { + Ok(rhs) => Ok(Some(Variable::Number { value: lhs + rhs })), + Err(err) => Err(err), + }, + Err(err) => Err(err), }, - NodeKind::DIV => { - match GPSL::extract_number(lhs) { - Ok(lhs) => { - match GPSL::extract_number(rhs) { - Ok(rhs) => { - Ok(Some(Variable::Number { - value: lhs / rhs - })) - } - Err(err) => { Err(err) } - } - } - Err(err) => { Err(err) } - } + NodeKind::DIV => match GPSL::extract_number(lhs) { + Ok(lhs) => match GPSL::extract_number(rhs) { + Ok(rhs) => Ok(Some(Variable::Number { value: lhs / rhs })), + Err(err) => Err(err), + }, + Err(err) => Err(err), }, - NodeKind::MUL => { - match GPSL::extract_number(lhs) { - Ok(lhs) => { - match GPSL::extract_number(rhs) { - Ok(rhs) => { - Ok(Some(Variable::Number { - value: lhs * rhs - })) - } - Err(err) => { Err(err) } - } - } - Err(err) => { Err(err) } - } + NodeKind::MUL => match GPSL::extract_number(lhs) { + Ok(lhs) => match GPSL::extract_number(rhs) { + Ok(rhs) => Ok(Some(Variable::Number { value: lhs * rhs })), + Err(err) => Err(err), + }, + Err(err) => Err(err), }, - NodeKind::SUB => { - match GPSL::extract_number(lhs) { - Ok(lhs) => { - match GPSL::extract_number(rhs) { - Ok(rhs) => { - Ok(Some(Variable::Number { - value: lhs - rhs - })) - } - Err(err) => { Err(err) } - } - } - Err(err) => { Err(err) } - } + NodeKind::SUB => match GPSL::extract_number(lhs) { + Ok(lhs) => match GPSL::extract_number(rhs) { + Ok(rhs) => Ok(Some(Variable::Number { value: lhs - rhs })), + Err(err) => Err(err), + }, + Err(err) => Err(err), }, NodeKind::EQ => { if lhs == rhs { - Ok(Some(Variable::Number { - value: 1 - })) + Ok(Some(Variable::Number { value: 1 })) } else { - Ok(Some(Variable::Number { - value: 0 - })) + Ok(Some(Variable::Number { value: 0 })) } - }, + } NodeKind::NE => { if lhs != rhs { - Ok(Some(Variable::Number { - value: 1 - })) + Ok(Some(Variable::Number { value: 1 })) } else { - Ok(Some(Variable::Number { - value: 0 - })) + Ok(Some(Variable::Number { value: 0 })) } - }, - NodeKind::LT => { - match GPSL::extract_number(lhs) { - Ok(lhs) => { - match GPSL::extract_number(rhs) { - Ok(rhs) => { - if lhs < rhs { - Ok(Some(Variable::Number { - value: 1 - })) - } else { - Ok(Some(Variable::Number { - value: 0 - })) - } - } - Err(err) => { Err(err) } + } + NodeKind::LT => match GPSL::extract_number(lhs) { + Ok(lhs) => match GPSL::extract_number(rhs) { + Ok(rhs) => { + if lhs < rhs { + Ok(Some(Variable::Number { value: 1 })) + } else { + Ok(Some(Variable::Number { value: 0 })) } } - Err(err) => { Err(err) } - } + Err(err) => Err(err), + }, + Err(err) => Err(err), }, - NodeKind::LE => { - match GPSL::extract_number(lhs) { - Ok(lhs) => { - match GPSL::extract_number(rhs) { - Ok(rhs) => { - if lhs <= rhs { - Ok(Some(Variable::Number { - value: 1 - })) - } else { - Ok(Some(Variable::Number { - value: 0 - })) - } - } - Err(err) => { Err(err) } + NodeKind::LE => match GPSL::extract_number(lhs) { + Ok(lhs) => match GPSL::extract_number(rhs) { + Ok(rhs) => { + if lhs <= rhs { + Ok(Some(Variable::Number { value: 1 })) + } else { + Ok(Some(Variable::Number { value: 0 })) } } - Err(err) => { Err(err) } - } + Err(err) => Err(err), + }, + Err(err) => Err(err), }, - _ => Ok(None) + _ => Ok(None), } } else { Err(String::from("RHS Variable is null.")) @@ -331,7 +285,7 @@ impl GPSL { Node::Return { lhs } => { if let Ok(Some(lhs)) = self.evaluate(lhs) { return Ok(Some(Variable::Return { - value: Box::new(lhs) + value: Box::new(lhs), })); } else { return Err(String::from("Cannot evaluate LHS.")); @@ -345,7 +299,7 @@ impl GPSL { if let Ok(Some(condition)) = self.evaluate(condition) { if match condition { Variable::Number { value } => value == 1, - _ => false + _ => false, } { if let Ok(Some(res)) = self.evaluate(stmt) { match res.clone() { @@ -378,22 +332,18 @@ impl GPSL { let mut cond = if let Some(condition) = self.evaluate(condition.clone())? { condition } else { - Variable::Number { - value: 0 - } + Variable::Number { value: 0 } }; while match cond { Variable::Number { value } => value == 1, - _ => false + _ => false, } { self.evaluate(stmt.clone())?; cond = if let Some(condition) = self.evaluate(condition.clone())? { condition } else { - Variable::Number { - value: 0 - } + Variable::Number { value: 0 } }; } @@ -406,7 +356,9 @@ impl GPSL { stmt, } => { match init { - Some(init) => {self.evaluate(init)?;}, + Some(init) => { + self.evaluate(init)?; + } None => {} } @@ -415,26 +367,22 @@ impl GPSL { if let Some(condition) = self.evaluate(condition)? { condition } else { - Variable::Number { - value: 0 - } - } - }, - None => { - Variable::Number { - value: 1 + Variable::Number { value: 0 } } } + None => Variable::Number { value: 1 }, }; while match cond { Variable::Number { value } => value == 1, - _ => false + _ => false, } { self.evaluate(stmt.clone())?; match update.clone() { - Some(update) => {self.evaluate(update)?;}, + Some(update) => { + self.evaluate(update)?; + } None => {} } @@ -443,35 +391,45 @@ impl GPSL { if let Some(condition) = self.evaluate(condition)? { condition } else { - Variable::Number { - value: 0 - } - } - }, - None => { - Variable::Number { - value: 1 + Variable::Number { value: 0 } } } + None => Variable::Number { value: 1 }, }; } return Ok(None); } - Node::Block { stmts, permission } => { + Node::Block { + stmts, + permission, + mode, + } => { let accept = self.blocks.front().unwrap().accept.clone(); let reject = self.blocks.front().unwrap().reject.clone(); - let (accept, reject) = if let Node::Permission { accept, reject } = *permission.unwrap_or(Box::new(Node::None)) { - (accept.iter().map(|p| Permission::from_string(p)).collect(), reject.iter().map(|p| Permission::from_string(p)).collect()) + let (accept, reject) = if let Node::Permission { accept, reject } = + *permission.unwrap_or(Box::new(Node::None)) + { + ( + accept.iter().map(|p| Permission::from_string(p)).collect(), + reject.iter().map(|p| Permission::from_string(p)).collect(), + ) } else { (accept, reject) }; + let mode = if let Node::Mode { mode } = *mode.unwrap_or(Box::new(Node::None)) { + mode + } else { + "".to_string() + }; + println!("Mode: {}", mode); + self.blocks.push_front(Block { accept: accept, reject: reject, variables: HashMap::new(), - is_split: false + is_split: false, }); for stmt in stmts { @@ -492,12 +450,10 @@ impl GPSL { } Node::Define { name, var_type } => { let value = if var_type == "num" { - Variable::Number { - value: 0 - } + Variable::Number { value: 0 } } else if var_type == "String" { Variable::Text { - value: String::default() + value: String::default(), } } else { return Err(format!("{}: 未知の型です。", var_type)); @@ -515,7 +471,7 @@ impl GPSL { return Ok(None); } - _ => { Ok(None) }, + _ => Ok(None), } } @@ -526,7 +482,7 @@ impl GPSL { accept: vec![Permission::Administrator, Permission::StdIo], reject: vec![], variables: HashMap::new(), - is_split: true + is_split: true, }); if let Some(functions) = self.functions.clone() { if let Node::Function { body, .. } = &*(functions[&function_name]) { diff --git a/test.gpsl b/test.gpsl new file mode 100644 index 0000000..760d8d7 --- /dev/null +++ b/test.gpsl @@ -0,0 +1,3 @@ +fn main() { + println("test"); +}