add mode grammar

This commit is contained in:
Masato Imai
2022-07-14 11:29:34 +09:00
parent 0e0952d40a
commit 2cc8651e7e
7 changed files with 205 additions and 199 deletions

View File

@ -5,6 +5,7 @@ WS
-> skip
;
SHARP: '#' ;
DOLLER: '$' ;
ADD: '+' ;
SUB: '-' ;

View File

@ -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 ;

View File

@ -18,11 +18,14 @@ pub enum Node {
Function {
name: String,
args: HashMap<String, String>,
body: Vec<Box<Node>>
body: Vec<Box<Node>>,
},
Mode {
mode: String,
},
Permission {
accept: Vec<String>,
reject: Vec<String>
reject: Vec<String>,
},
Operator {
kind: NodeKind,
@ -58,7 +61,8 @@ pub enum Node {
},
Block {
stmts: Vec<Box<Node>>,
permission: Option<Box<Node>>
permission: Option<Box<Node>>,
mode: Option<Box<Node>>,
},
Define {
name: String,
@ -68,7 +72,7 @@ pub enum Node {
name: String,
args: Vec<Box<Node>>,
},
None
None,
}
impl Node {

View File

@ -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<Box<Node>, 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<Box<Node>> = 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<Box<Node>, 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<String> = vec![];
let mut reject: Vec<String> = 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()?));

View File

@ -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<String, String> {
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;
}

View File

@ -11,7 +11,7 @@ pub struct Block {
pub accept: Vec<Permission>,
pub reject: Vec<Permission>,
pub variables: HashMap<String, LocalVariable>,
pub is_split: bool
pub is_split: bool,
}
pub struct GPSL {
@ -19,7 +19,8 @@ pub struct GPSL {
pub global_variables: Vec<Variable>,
pub source: Source,
pub blocks: VecDeque<Block>,
pub external_func: Vec<fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> ExternalFuncReturn>
pub external_func:
Vec<fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> ExternalFuncReturn>,
}
#[derive(Clone, Debug)]
@ -41,13 +42,19 @@ impl VariableStatus {
}
impl GPSL {
pub fn new(source: Source, functions: Option<HashMap<String, Box<Node>>>, external_func: Vec<fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> ExternalFuncReturn>) -> GPSL {
pub fn new(
source: Source,
functions: Option<HashMap<String, Box<Node>>>,
external_func: Vec<
fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> 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<usize, String> {
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::<String>());
debug!("{}: {}", &function_name, functions.contains_key(&function_name));
debug!(
"functions: {:?}",
functions
.iter()
.map(|f| format!("{},", f.0))
.collect::<String>()
);
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]) {

3
test.gpsl Normal file
View File

@ -0,0 +1,3 @@
fn main() {
println("test");
}