commit ac3e274cc0e76956d5035dd3b7f0d331cc9a3954
parent eefbd852f6a3f09f4116ccc0b18bc3e49abcd3b6
Author: Sebastian <sebastian@sebsite.pw>
Date: Sat, 28 Oct 2023 02:36:07 -0400
cmd/parsechk: initial commit
This uses hare::parse to parse all .ha files in the tree, and report if
any parsing errors occurred. This should hopefully ensure that in the
future we keep hare::parse up to date, and don't push changes that
compile but don't work with haredoc.
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
2 files changed, 62 insertions(+), 0 deletions(-)
diff --git a/.builds/alpine.yml b/.builds/alpine.yml
@@ -38,6 +38,9 @@ tasks:
- check_with_libc: |
cd hare
hare test -lc
+- parsechk: |
+ cd hare
+ hare run cmd/parsechk
- lint: |
cd hare
./scripts/lint.sh
diff --git a/cmd/parsechk/main.ha b/cmd/parsechk/main.ha
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// (c) Hare authors <https://harelang.org>
+
+use bufio;
+use fmt;
+use fs;
+use hare::ast;
+use hare::lex;
+use hare::parse;
+use io;
+use os;
+use path;
+use types;
+
+export fn main() void = {
+ let buf = path::init()!;
+ let status: int = os::status::SUCCESS;
+ iter(&buf, &status);
+ os::exit(status);
+};
+
+fn iter(buf: *path::buffer, status: *int) void = {
+ let it = os::iter(path::string(buf))!;
+ defer fs::finish(it);
+ for (true) match (fs::next(it)) {
+ case void =>
+ break;
+ case let ent: fs::dirent =>
+ path::push(buf, ent.name)!;
+ defer path::pop(buf);
+ const st = os::stat(path::string(buf))!;
+ if (fs::isfile(st.mode)) {
+ match (path::peek_ext(buf)) {
+ case let s: str =>
+ if (s == "ha") {
+ parse(path::string(buf), status);
+ };
+ case void => void;
+ };
+ } else if (fs::isdir(st.mode)) {
+ iter(buf, status);
+ };
+ };
+};
+
+fn parse(path: str, status: *int) void = {
+ const f = os::open(path)!;
+ defer io::close(f)!;
+ let sc = bufio::newscanner(f, types::SIZE_MAX);
+ defer bufio::finish(&sc);
+ let lexer = lex::init(&sc, path);
+ match (parse::subunit(&lexer)) {
+ case let su: ast::subunit =>
+ ast::subunit_finish(su);
+ case let err: parse::error =>
+ fmt::errorln(parse::strerror(err))!;
+ *status = os::status::FAILURE;
+ };
+};