package def parsing

This commit is contained in:
2026-02-14 10:51:28 +01:00
parent db06671f56
commit 6eb984c3b8
4 changed files with 165 additions and 2 deletions

View File

@@ -1 +1 @@
Checks: '*,clang-analyzer-*,-llvmlibc-*,-fuchsia-*,-altera-*,-abseil-*,-android-*,-modernize-use-trailing-return-type,-readability-identifier-length,-*-readability-todo,-*-magic-numbers,-readability-function-cognitive-complexity,-*-easily-swappable-parameters'
Checks: '*,clang-analyzer-*,-llvmlibc-*,-fuchsia-*,-altera-*,-abseil-*,-android-*,-modernize-use-trailing-return-type,-readability-identifier-length,-*-readability-todo,-*-magic-numbers,-readability-function-cognitive-complexity,-*-easily-swappable-parameters,-*-non-private-member-variables-in-classes,-*-no-recursion'

View File

@@ -1,3 +1,18 @@
#include "parser.h"
#include <fstream>
#include <iostream>
#include <sstream>
int main() { std::cout << "Hello, World!\n"; }
int main() {
std::ifstream file("zlib.shrap");
if (!file) {
std::cerr << "Error opening file\n";
return 1;
}
std::stringstream buffer;
buffer << file.rdbuf();
Expr pkg = Expr::parse(buffer.str());
std::cout << pkg.get("name").value << std::endl;
}

141
src/parser.h Normal file
View File

@@ -0,0 +1,141 @@
#pragma once
#include <sstream>
#include <string>
#include <vector>
struct Expr {
public:
enum class Type { Atom, String, List };
Type type = Type::Atom;
std::string value;
std::vector<Expr> children;
[[nodiscard]] Expr get(const std::string &key) const {
if (type != Type::List) {
throw std::runtime_error("get() called on non-list");
}
for (const auto &child : children) {
if (child.type == Type::List && child.children.size() >= 2 &&
child.children[0].type == Type::Atom &&
child.children[0].value == key) {
return child.children[1];
}
}
throw std::runtime_error("key not found: " + key);
}
static Expr parse(const std::string &input) {
std::istringstream in(input);
return parse_expr(in);
}
private:
static std::string read_atom(std::istringstream &in) {
std::string atom;
while (true) {
int next = in.peek();
if (next == -1 || is_space(static_cast<char>(next)) || next == '(' ||
next == ')') {
break;
}
atom += static_cast<char>(in.get());
}
if (atom.empty()) {
throw std::runtime_error("empty atom");
}
return atom;
}
static Expr parse_list(std::istringstream &in) {
Expr result = {.type = Expr::Type::List};
in.get(); // consume bracket
while (true) {
while (is_space(static_cast<char>(in.peek()))) {
in.get();
}
if (!in) {
throw std::runtime_error("unexpected EOF");
}
if (in.peek() == ')') {
in.get();
break;
}
result.children.push_back(parse_expr(in));
}
return result;
}
static std::string read_string(std::istringstream &in) {
std::string result;
in.get(); // consume the quote
while (true) {
if (!in) {
throw std::runtime_error("unexpected EOF in string");
}
auto c = static_cast<char>(in.get());
if (c == '"') {
break;
}
result += c;
}
return result;
}
static Expr parse_expr(std::istringstream &in) {
while (is_space(static_cast<char>(in.peek()))) {
in.get();
}
if (!in) {
throw std::runtime_error("unexpected EOF");
}
if (in.peek() == '(') {
return parse_list(in);
}
if (in.peek() == ')') {
throw std::runtime_error("unexpected ')'");
}
if (in.peek() == '"') {
return {.type = Type::String, .value = read_string(in)};
}
return {.type = Type::Atom, .value = read_atom(in)};
}
static bool is_space(char c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\r';
}
};
inline std::ostream &operator<<(std::ostream &out, const Expr &e) {
switch (e.type) {
case Expr::Type::Atom:
out << e.value;
break;
case Expr::Type::String:
out << '"' << e.value << '"';
break;
case Expr::Type::List:
out << '(';
for (size_t i = 0; i < e.children.size(); ++i) {
if (i > 0) {
out << ' ';
}
out << e.children[i];
}
out << ')';
break;
}
return out;
}

7
zlib.shrap Normal file
View File

@@ -0,0 +1,7 @@
(package
(name "zlib")
(version "1.3.1")
(homepage "https://zlib.net/")
(src (tar "https://zlib.net/zlib-1.3.1.tar.gz" "207c3b0862cb4e3686f8405f76a98c38dbad9c94bcf4be4b9efca0716aba51ec"))
(build
(configure_make)))