Skip to content

Commit

Permalink
添加sets, 对于多个set, 可以写为一个sets, 以求简洁
Browse files Browse the repository at this point in the history
  • Loading branch information
A4-Tacks committed Jul 29, 2023
1 parent 7c8df8e commit 71fc477
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mindustry_logic_bang_lang"
version = "0.5.1"
version = "0.5.2"
edition = "2021"

authors = ["A4-Tacks <[email protected]>"]
Expand Down
13 changes: 13 additions & 0 deletions examples/sets.mdtlbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#* sets是0.5.2新出的一个小语法
避免编写多行简单的set显得有些空.
当然, 你不要刻意的把应该用op take等地方的语句换成sets来增加开销!
你只应该在多个set使用时使用它
也不要刻意的把一大堆set塞进一个sets, 这是不明智的, 适量即可
*#

a b c = 1 2 3;
#* 以上代码会被编译为
set a 1
set b 2
set c 3
*#
39 changes: 29 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,19 +253,38 @@ fn unwrap_parse_err<'a>(result: ParseResult<'a>, src: &str) -> Expand {
error: Error {
start,
end,
err: Errors::NotALiteralUInteger(str, err)
err
}
} => {
let [start, end] = get_locations(src, [start, end]);
err!(
"在 {:?} 至 {:?} 处的错误: {:?} 不是一个有效的无符号整数, 错误: {}",
start, end,
str, err,
let [start, end]
= get_locations(src, [start, end]);
let head = format!(
"在 {:?} 至 {:?} 处的错误: ",
start,
end
);
},
#[allow(unreachable_patterns)]
e => {
err!("未被枚举的错误: {:?}", e);
match err {
Errors::NotALiteralUInteger(str, err) => {
err!(
"{}{:?} 不是一个有效的无符号整数, 错误: {}",
head,
str,
err,
);
},
Errors::SetVarNoPatternValue(var_count, val_count) => {
err!(
"{}sets两侧值数量不匹配, {} != {}",
head,
var_count,
val_count,
);
},
#[allow(unreachable_patterns)]
e => {
err!("未被枚举的错误: {:?}", e);
},
}
},
}
exit(4)
Expand Down
70 changes: 70 additions & 0 deletions src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ impl From<((Location, Location), Errors)> for Error {
#[derive(Debug, PartialEq, Clone)]
pub enum Errors {
NotALiteralUInteger(String, ParseIntError),
SetVarNoPatternValue(usize, usize),
}

pub type Var = String;
Expand Down Expand Up @@ -288,8 +289,47 @@ impl Meta {
f(Const(name, value, Vec::with_capacity(0)))
}
}

/// 构建一个`sets`, 例如`a b c = 1 2 3;`
/// 如果只有一个值与被赋值则与之前行为一致
/// 如果值与被赋值数量不匹配则返回错误
/// 如果值与被赋值数量匹配且大于一对就返回Expand中多个set
pub fn build_sets(&self, loc: [Location; 2], mut vars: Vec<Value>, mut values: Vec<Value>)
-> Result<LogicLine, Error> {
fn build_set(var: Value, value: Value) -> LogicLine {
LogicLine::Other(vec![
"set".into(),
var,
value,
])
}
if vars.len() != values.len() {
// 接受与值数量不匹配
return Err((
loc,
Errors::SetVarNoPatternValue(vars.len(), values.len())
).into());
}

assert_ne!(vars.len(), 0);
let len = vars.len();

if len == 1 {
// normal
Ok(build_set(vars.pop().unwrap(), values.pop().unwrap()))
} else {
// sets
let mut expand = Vec::with_capacity(len);
expand.extend(zip(vars, values)
.map(|(var, value)| build_set(var, value))
);
debug_assert_eq!(expand.len(), len);
Ok(Expand(expand).into())
}
}
}


/// `jump`可用判断条件枚举
#[derive(Debug, PartialEq, Clone)]
pub enum JumpCmp {
Expand Down Expand Up @@ -1990,4 +2030,34 @@ mod tests {
r#"printflush message1"#,
]);
}

#[test]
fn sets_test() {
let parser = ExpandParser::new();

let ast = parse!(parser, r#"
a b c = 1 2 (op $ 2 + 1;);
"#).unwrap();
let meta = CompileMeta::new();
let mut tag_codes = meta.compile(ast);
let logic_lines = tag_codes.compile().unwrap();
assert_eq!(logic_lines, vec![
"set a 1",
"set b 2",
"op add __0 2 1",
"set c __0",
]);

assert!(parse!(parser, r#"
a b c = 1 2;
"#).is_err());

assert!(parse!(parser, r#"
a = 1 2;
"#).is_err());

assert!(parse!(parser, r#"
= 1 2;
"#).is_err());
}
}
43 changes: 24 additions & 19 deletions src/syntax_def.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,23 @@ match {
_
}

Or<A, B> = { A, B }; // A或者B
Or3<A, B, C> = { A, B, C }; // A或者B或者C
OrSwap<A, B> = { A B, B A }; // 匹配 `A B`或者`B A`
OrRev<A, M, B> = { A M B, B, M, A }; // 匹配`A M B`或者`B M A`
OrShl<A, B, C> = { A B C, B C A }; // 匹配`A B C`或者`B C A`, 后者是值进行左移循环得到
Wrap<Open, T, Close> = Open <T> Close; // 用于定义包裹
MTuple<T> = Wrap<"(", T, ")">;
MList<T> = Wrap<"[", T, "]">;
MBlock<T> = Wrap<"{", T, "}">;
OpenArgs<T, S> = (<T> S)*; // 零至多个有分隔后缀值
CloseArgs<T, S> = (<T> S)* T => { // 一至多个有分隔无后缀值
let (mut args, tail) = <>;
args.push(tail);
args
};
Span<T> = @L T @R;

pub String: Var = r#""[^"]*""# => <>.replace('\n', "\\n");
pub Ident: Var = r"[_\p{XID_Start}]\p{XID_Continue}*" => <>.into();
pub OIdent: Var = r"@[_\p{XID_Start}][\p{XID_Continue}\-]*" => <>.into(); // `@abc-def`这种
Expand Down Expand Up @@ -80,23 +97,6 @@ pub LiteralUInt: usize = <l:@L> <num:Number> <r:@R> =>? {
};


Or<A, B> = { A, B }; // A或者B
Or3<A, B, C> = { A, B, C }; // A或者B或者C
OrSwap<A, B> = { A B, B A }; // 匹配 `A B`或者`B A`
OrRev<A, M, B> = { A M B, B, M, A }; // 匹配`A M B`或者`B M A`
OrShl<A, B, C> = { A B C, B C A }; // 匹配`A B C`或者`B C A`, 后者是值进行左移循环得到
Wrap<Open, T, Close> = Open <T> Close; // 用于定义包裹
MTuple<T> = Wrap<"(", T, ")">;
MList<T> = Wrap<"[", T, "]">;
MBlock<T> = Wrap<"{", T, "}">;
OpenArgs<T, S> = (<T> S)*; // 零至多个有分隔后缀值
CloseArgs<T, S> = (<T> S)* T => { // 一至多个有分隔无后缀值
let (mut args, tail) = <>;
args.push(tail);
args
};
Span<T> = @L T @R;

LEnd: () = ";" => ();

JumpCmpBody: JumpCmp = {
Expand Down Expand Up @@ -177,7 +177,9 @@ pub LogicLine: LogicLine = {
"op" <Op> LEnd => <>.into(),
"noop" LEnd => LogicLine::NoOp,
"set" <var:Value> <value:Value> LEnd => LogicLine::Other(vec!["set".into(), var.into(), value]),
<var:Value> "=" <value:Value> LEnd => LogicLine::Other(vec!["set".into(), var.into(), value]),
<l:@L> <vars:PArgs> "=" <values:PArgs> LEnd <r:@R>
=>? meta.build_sets([l, r], vars, values)
.map_err(|e| e.into()),
"read" <var:Value> <from:Value> <index:Value> LEnd
=> LogicLine::Other(vec!["read".into(), var.into(), from, index]),
"print" <Args> LEnd => {
Expand All @@ -201,8 +203,11 @@ pub LogicLine: LogicLine = {
},
}

#[inline] Args: Vec<Value> = {
Args: Vec<Value> = {
() => vec![],
PArgs,
}
PArgs: Vec<Value> = {
Value => vec![<>],
Value Value => vec![<>],
Value Value Value => vec![<>],
Expand Down

0 comments on commit 71fc477

Please sign in to comment.