Skip to content

Commit fe470b7

Browse files
authored
Merge pull request #23 from MisakaVan/dev
Fixes and improvements
2 parents c7941e5 + 4eecf7b commit fe470b7

File tree

6 files changed

+34
-11
lines changed

6 files changed

+34
-11
lines changed

batchtest.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/bin/bash
22

3+
inputext=".jtl.h"
4+
35
# Function to run test on a given input file
46
run_test() {
57
local input_file="$1"
@@ -15,7 +17,7 @@ run_test() {
1517
test_on_directory() {
1618
local dir="$1"
1719
for input_file in "$dir"/*; do
18-
if [ -f "$input_file" ] && [[ "$input_file" != *.out ]]; then
20+
if [ -f "$input_file" ] && [[ "$input_file" == *"$inputext" ]]; then
1921
run_test "$input_file"
2022
fi
2123
done

doc/parser.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,13 +204,15 @@ CFG的语法规则到此结束,需要更多信息可以查看`bison`的输出
204204
- enum元素(枚举常量)的定义:新的枚举常量。(规则22,23)
205205
- typedef的定义中的`NT_NAMED_RIGHT_TYPE_EXPR`:新的类型标识符。
206206
- 全局变量的声明中的`NT_NAMED_RIGHT_TYPE_EXPR`:变量名。
207-
- 在所有的`NT_LEFT_TYPE`中,引入新定义的struct/union/enum类型标识符。(规则24,27,30)
207+
- 在所有的`NT_LEFT_TYPE`中,引入带有定义的struct/union/enum类型标识符。(规则24,27,30)
208+
- 在所有的`NT_LEFT_TYPE`中,使用的struct/union/enum类型标识符。(规则26,29,32)
209+
注:一般来说,会写出这样的代码 `struct Foo; struct Foo foo;`或者`struct Foo{}; struct Foo foo;`,我们一般认为前一句声明/引入了`Foo`,后一句使用了`Foo`。实际上,后一句也可以声明/引入`Foo``struct Foo foo; struct Foo{};`也是合法的C语言代码。只不过同一个标识符的重复声明不会引发错误而已。
210+
208211

209212
参考C语言的行为,同一个标识符可以被用作不同的类型。
210213
一个标识符可以是struct/union/enum类型标识符(此三者内部互斥),同时也可以是typedef/全局变量/枚举常量的标识符(此三者内部互斥)。我们支持这种行为:向全局作用域添加新的标识符时,将检查是否已经存在同名的标识符,如果存在,将进一步检查前置定义的类型是否与当前希望定义的类型兼容。
211214

212215
2. (全局)使用标识符:仅检查全局作用域中是否存在该标识符,且标识符对应的类型是否正确。
213-
- 在所有的`NT_LEFT_TYPE`中,使用已定义的struct/union/enum类型标识符。(规则26,29,32)
214216
- 在所有的`NT_LEFT_TYPE`中,使用已定义的typedef类型标识符。(规则35)
215217

216218
与struct/union的定义作用域相关的CFG产生式:
@@ -221,6 +223,14 @@ CFG的语法规则到此结束,需要更多信息可以查看`bison`的输出
221223

222224
以上的检查函数都被定义在`lib.h/lib.c`中,并且在parser尝试将新的语法成分加入AST时被调用。
223225

226+
### 标识符管理:无法解决的问题
227+
228+
标识符的重复声明/定义检查。
229+
- 在C语言中,typedef的重复声明不会引发错误,只要它们所指的是同一个类型。这个问题没有在本项目中解决,因为设计AST的比较操作。
230+
- 在C语言中,struct/union的重复声明不会引发错误;重复定义会引发错误。这个问题没有在本项目中解决,因为没有追踪struct/union是否已经被定义。默认重复声明/定义同一个struct/union不会引发警告。
231+
- 在C语言中,全局变量的重复声明不会引发错误,但是涉及链接阶段可见性(如`extern int a; int a;`是合法的)。这个问题没有在本项目中解决,因为本项目不涉及`extern``static`等关键字。本项目默认重复声明同一个变量名是错误的,引发警告。
232+
233+
224234
### 错误处理
225235

226236
如果遇到了语法错误,parser会输出错误信息并停止解析,通过`yyerror`函数实现。因为使用了`%define parse.error detailed``yyerror`会输出更详细的错误信息。

resource/test/test-identifier-predeclared/testcase1.jtl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ enum Foo b; // Warning: Identifier Foo has been registered as struct, not enum
77
union Foo c; // Warning: Identifier Foo has been registered as struct, not union
88

99

10-
typedef Foo foo_t;
10+
typedef Foo foo_t; // warning: should use `struct Foo` instead of `Foo`
1111
foo_t d; // OK: foo_t has been registered as typedef
1212
bar_t e; // Warning: Identifier bar_t has never been registered
1313

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
struct foo {};
22
struct foo foo; // OK
33

4+
struct Bar bar;
5+
struct Bar {int a;};
6+
47
enum foo {a}; // Warning: Identifier foo has been registered as struct, not enum
58
int foo; // Warning : Identifier foo is already registered as variable at line 2

src/lang.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ struct left_type* TStructType(char* name) {
9090
res->t = T_STRUCT_TYPE;
9191
res->d.STRUCT_TYPE.name = name;
9292

93-
check_identifier_struct(name);
93+
register_identifier_struct(name);
9494

9595
return res;
9696
}
@@ -111,7 +111,7 @@ struct left_type* TUnionType(char* name) {
111111
res->t = T_UNION_TYPE;
112112
res->d.UNION_TYPE.name = name;
113113

114-
check_identifier_union(name);
114+
register_identifier_union(name);
115115

116116
return res;
117117
}
@@ -133,7 +133,7 @@ struct left_type* TEnumType(char* name) {
133133
res->t = T_ENUM_TYPE;
134134
res->d.ENUM_TYPE.name = name;
135135

136-
check_identifier_enum(name);
136+
register_identifier_enum(name);
137137

138138
return res;
139139
}

src/lib.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ struct, union, enum names should not overlap with each other.
158158
int conflict_identifier_register_lut[6][6] = {
159159
{1, 1, 0, 0, 0, 1}, // variable
160160
{1, 1, 0, 0, 0, 1}, // enumerator
161-
{0, 0, 1, 1, 1, 0}, // struct
162-
{0, 0, 1, 1, 1, 0}, // union
163-
{0, 0, 1, 1, 1, 0}, // enum
161+
{0, 0, 0, 1, 1, 0}, // struct
162+
{0, 0, 1, 0, 1, 0}, // union
163+
{0, 0, 1, 1, 0, 0}, // enum
164164
{1, 1, 0, 0, 0, 1}, // typedef
165165
};
166166

@@ -271,7 +271,15 @@ void check_identifier_in_table(char* name, enum IdentifierType using_type, struc
271271
printf("Warning: (Line %d) Identifier %s is not registered as %s\n", yylineno, name, description);
272272
for (int i = 0; i < IDENT_TYPE_COUNT; i++) {
273273
if (info->flags & (1 << i)) {
274-
pdebug(" - Identifier %s is registered as %s at line %d\n", name, identifier_type_str[i], info->lineno[i]);
274+
printf(" - Identifier %s is registered as %s at line %d\n", name, identifier_type_str[i], info->lineno[i]);
275+
if (using_type == IDENT_TYPE_TYPEDEF &&
276+
(i == IDENT_TYPE_STRUCT || i == IDENT_TYPE_UNION ||
277+
i == IDENT_TYPE_ENUM)) {
278+
// e.g. Got `Foo foo` but `Foo` is registered as struct.
279+
// Suggest to use `struct Foo foo` instead.
280+
printf(" - Maybe you want to use %s %s instead of %s\n",
281+
identifier_type_str[i], name, name);
282+
}
275283
}
276284
}
277285
}

0 commit comments

Comments
 (0)