Skip to content

Commit

Permalink
修改ValueBind, 使用报错保证左值句柄不为字符串, 修改语法保证右值不为字符串
Browse files Browse the repository at this point in the history
  • Loading branch information
A4-Tacks committed Aug 13, 2023
1 parent 06b7974 commit 82eb0cc
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 25 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.10.0"
version = "0.10.1"
edition = "2021"

authors = ["A4-Tacks <[email protected]>"]
Expand Down
2 changes: 2 additions & 0 deletions examples/dexp.mdtlbl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* `x = (y: y = (z: $ = 2;););`,
* 此处的句柄替换符会被替换为`z`
*
* 需要注意的是, 对于Var这些, 它们的句柄即为它们自己本身
*
* 语法方面的困惑可以查看源码中的`syntax_def.lalrpop`文件
* `...: ... = ... => ...;`这种就是一个类型定义, 而`=>`前面的就是语法定义, 后方的不用管那是逻辑处理
* 例如`pub Foo: FooStruct = "!" <r"\d+"> => { ... };`
Expand Down
3 changes: 2 additions & 1 deletion examples/value_bind.mdtlbl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* 这是在0.10.0版本加入的语法
* 可以有效的把数据组织起来
* 作用是将一个Var按照特定格式绑定到一个Value的句柄
* 语法为 `Value "." Var`, 例如`$.data` `foo.bar`
* 语法为 `Value "." NoStringVar`, 例如`$.data` `foo.bar`
* 这里需要注意的是, 其左值的句柄不能为字符串, 否则会报错
*#

const Human_new = (
Expand Down
78 changes: 60 additions & 18 deletions src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub enum Errors {
/// 带有错误前缀, 并且文本为红色的eprintln
macro_rules! err {
( $fmtter:expr $(, $args:expr)* $(,)? ) => {
eprintln!(concat!("\x1b[1;31m", "ParseError: ", $fmtter, "\x1b[0m"), $($args),*);
eprintln!(concat!("\x1b[1;31m", "CompileError:\n", $fmtter, "\x1b[0m"), $($args),*);
};
}

Expand Down Expand Up @@ -203,14 +203,18 @@ impl Value {
}
}

/// 判断是否不应该由原始标识符包裹
/// 注意是原始标识符(原始字面量), 不要与原始值混淆
pub fn no_use_repr_var(s: &str) -> bool {
pub fn is_string(s: &str) -> bool {
s.len() >= 2
&& s.starts_with('"')
&& s.ends_with('"')
}

/// 判断是否不应该由原始标识符包裹
/// 注意是原始标识符(原始字面量), 不要与原始值混淆
pub fn no_use_repr_var(s: &str) -> bool {
Self::is_string(s)
}

/// 返回被规范化的标识符
pub fn replace_ident(s: &str) -> String {
if Self::no_use_repr_var(s) {
Expand Down Expand Up @@ -283,11 +287,12 @@ impl TakeHandle for DExp {
if let Some(dexp) = value.as_dexp() {
err!(
concat!(
"尝试在`DExp`的返回句柄处使用值为`DExp`的const, ",
"{}\n尝试在`DExp`的返回句柄处使用值为`DExp`的const, ",
"此处仅允许使用`Var`\n",
"DExp: {:?}\n",
"名称: {:?}",
),
meta.err_info().join("\n"),
dexp,
result
);
Expand Down Expand Up @@ -338,6 +343,16 @@ impl TakeHandle for ValueBind {
fn take_handle(self, meta: &mut CompileMeta) -> Var {
// 以`__{}__bind__{}`的形式组合
let handle = self.0.take_handle(meta);
assert!(! Value::is_string(&self.1));
if Value::is_string(&handle) {
err!(
"{}\nValueBind过程中, 左值句柄为字符串, ({}.{})",
meta.err_info().join("\n"),
Value::replace_ident(&handle),
Value::replace_ident(&self.1),
);
exit(6)
}
format!("__{}__bind__{}", handle, self.1)
}
}
Expand Down Expand Up @@ -1728,9 +1743,14 @@ impl CompileMeta {
}

pub fn debug_tags_map(&self) -> Vec<String> {
self.tags_map()
let mut tags_map: Vec<_> = self
.tags_map()
.iter()
.map(|(tag, id)| format!("{} \t-> {}", tag, id))
.collect();
tags_map.sort_unstable_by_key(|(_, &k)| k);
tags_map
.into_iter()
.map(|(tag, id)| format!("{} \t-> {}", id, tag))
.collect()
}

Expand All @@ -1754,19 +1774,10 @@ impl CompileMeta {

/// 对在外部使用`DExpHandle`进行报错
fn do_out_of_dexp_err(&self, value: &str) -> ! {
let mut tags_map = self.debug_tags_map();
let mut tag_lines = self.debug_tag_codes();
line_first_add(&mut tags_map, "\t");
line_first_add(&mut tag_lines, "\t");
err!(
concat!(
"尝试在`DExp`的外部使用{}\n",
"tag映射id:\n{}\n",
"已经生成的代码:\n{}\n",
),
"{}\n尝试在`DExp`的外部使用{}",
self.err_info().join("\n"),
value,
tags_map.join("\n"),
tag_lines.join("\n"),
);
exit(6)
}
Expand Down Expand Up @@ -1808,6 +1819,21 @@ impl CompileMeta {
pub fn const_expand_exit(&mut self) -> HashMap<Var, Var> {
self.const_expand_tag_name_map.pop().unwrap()
}

pub fn err_info(&self) -> Vec<String> {
let mut res = Vec::new();

let mut tags_map = self.debug_tags_map();
let mut tag_lines = self.debug_tag_codes();
line_first_add(&mut tags_map, "\t");
line_first_add(&mut tag_lines, "\t");

res.push("Id映射Tag:".into());
res.extend(tags_map);
res.push("已生成代码:".into());
res.extend(tag_lines);
res
}
}

pub fn line_first_add(lines: &mut Vec<String>, insert: &str) {
Expand Down Expand Up @@ -3822,4 +3848,20 @@ mod tests {
]);

}

#[test]
fn no_string_var_test() {
let parser = NoStringVarParser::new();

assert!(parse!(parser, r#"1"#).is_ok());
assert!(parse!(parser, r#"1.5"#).is_ok());
assert!(parse!(parser, r#"sbosb"#).is_ok());
assert!(parse!(parser, r#"0x1b"#).is_ok());
assert!(parse!(parser, r#"@abc"#).is_ok());
assert!(parse!(parser, r#"'My_name"s'"#).is_ok());
assert!(parse!(parser, r#"'"no_str"'"#).is_ok());

assert!(parse!(parser, r#""abc""#).is_err());
assert!(parse!(parser, r#""""#).is_err());
}
}
13 changes: 9 additions & 4 deletions src/syntax_def.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,19 @@ pub OtherValue: Var = r"'[^'\s]+'" => {
};

// 逻辑里面一个单元
// 例如`0x50` `'@alpha'` `add` `'a-b-c'`
pub Var: Var = {
String,
// 但不包含字符串
pub NoStringVar: Var = {
Ident,
OIdent,
Number,
OtherValue,
}
// 逻辑里面一个单元
// 例如`0x50` `'@alpha'` `add` `'a-b-c'`
pub Var: Var = {
String,
NoStringVar,
}

pub Value: Value = {
Var => <>.into(),
Expand All @@ -89,7 +94,7 @@ pub Value: Value = {
expand.push(LogicLine::SetResultHandle(name.into()));
DExp::new("__".into(), expand.into()).into()
},
<value:Value> "." <attr:Var> => ValueBind(value.into(), attr).into(),
<value:Value> "." <attr:NoStringVar> => ValueBind(value.into(), attr).into(),
}

pub LiteralUInt: usize = <l:@L> <num:Number> <r:@R> =>? {
Expand Down

0 comments on commit 82eb0cc

Please sign in to comment.