diff --git a/src/grammar/GpslLexer.g4 b/src/grammar/GpslLexer.g4 index b33dbe4..cab0041 100644 --- a/src/grammar/GpslLexer.g4 +++ b/src/grammar/GpslLexer.g4 @@ -5,6 +5,7 @@ WS -> skip ; +SHARP: '#' ; DOLLER: '$' ; ADD: '+' ; SUB: '-' ; diff --git a/src/grammar/GpslParser.g4 b/src/grammar/GpslParser.g4 index bf18158..9a73d1a 100644 --- a/src/grammar/GpslParser.g4 +++ b/src/grammar/GpslParser.g4 @@ -17,12 +17,13 @@ stmt: let ; let: LET IDENT COLON IDENT SEMICOLON ; -block: permission? LCURL stmt* RCURL ; +block: permission? mode? LCURL stmt* RCURL ; return: RETURN expr? SEMICOLON ; 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/src/node.rs b/src/node.rs index d6dcc92..3ec8bca 100644 --- a/src/node.rs +++ b/src/node.rs @@ -20,6 +20,9 @@ pub enum Node { args: HashMap, body: Vec> }, + Mode { + mode: String + }, Permission { accept: Vec, reject: Vec @@ -58,7 +61,8 @@ pub enum Node { }, Block { stmts: Vec>, - permission: Option> + permission: Option>, + mode: Option>, }, Define { name: String, diff --git a/src/parser.rs b/src/parser.rs index 34d055a..5ef4cf8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -110,6 +110,13 @@ 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 @@ -120,7 +127,7 @@ 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 +214,16 @@ 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)?; + return Ok(Box::new(Node::Mode { mode: mode.str })); + } + /* permission: DOLLER LPAREN ( IDENT LBRACKET ( IDENT COMMA? )* RBRACKET COMMA? )* RPAREN ; */ diff --git a/src/tokenizer.rs b/src/tokenizer.rs index a17ae8c..d51e6e5 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -113,6 +113,7 @@ impl Tokenizer { String::from("-="), String::from("*="), String::from("/="), + String::from("#"), String::from("$"), String::from("+"), String::from("-"), diff --git a/src/vm/gpsl.rs b/src/vm/gpsl.rs index d523ff7..576aac3 100644 --- a/src/vm/gpsl.rs +++ b/src/vm/gpsl.rs @@ -458,7 +458,7 @@ impl GPSL { 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)) { @@ -467,6 +467,8 @@ impl GPSL { (accept, reject) }; + if let Node::Mode { mode } = *mode.unwrap_or(Box::new(Node::None)) {} + self.blocks.push_front(Block { accept: accept, reject: reject,