feat: DSL parser, eval system, and project structure

- Hand-written lexer + recursive-descent parser for .kap package definitions
- Package constructs: const, license, provides, outputs, patches, depends
  (version-constrained, feature-gated, output-targeted), features (enabled/
  forced/flag), config files (default/replace/merge with cfg interpolation),
  env (?= soft-set), prepare/build/check/install phases
- Evaluator: recursive  resolver for prefix, jobopts, destdir, userargs,
  cfg.*, feature.*, package vars
- Comments: // single-line, /* */ multi-line
- /kappa/{bin,temp,db,system,system/builds} path layout
- Clang 22, C++23, CMake + vcpkg (tomlplusplus)
- .clangd + .clang-tidy configured
This commit is contained in:
2026-07-29 22:16:16 -04:00
parent 6fd31b694b
commit a8b53681fc
20 changed files with 1282 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
#pragma once
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace kappa::dsl {
using Command = std::string;
struct Phase {
std::vector<Command> commands;
};
struct Dependency {
std::string name;
std::string version;
std::string output;
std::string feature; // empty = unconditional
};
struct ConfigFile {
std::string path;
std::string mode;
std::unordered_map<std::string, std::string> entries;
};
struct FeatureDef {
bool enabled = false;
bool force = false;
std::string flag;
};
struct Patch {
std::string url;
std::string sha256;
int level = 1;
};
struct EnvEntry {
std::string key;
std::string value;
bool soft = false;
};
struct PackageDef {
std::string name;
std::string version;
std::string source;
std::string license;
std::vector<Dependency> depends;
std::vector<std::string> provides;
std::vector<std::string> outputs;
std::unordered_map<std::string, FeatureDef> features;
std::vector<ConfigFile> config_files;
std::vector<Patch> patches;
std::vector<EnvEntry> env_entries;
std::unordered_set<std::string> const_keys;
Phase prepare;
Phase build;
Phase check;
Phase install;
};
} // namespace kappa::dsl
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include "kappa/dsl/token.hpp"
#include <string_view>
namespace kappa::dsl {
class Lexer {
public:
explicit Lexer(std::string_view source);
Token next();
private:
Token scan_ident();
Token scan_string();
Token scan_symbol();
void skip_whitespace();
bool skip_comment();
char peek() const;
char advance();
bool match(char c);
std::string_view source_;
std::size_t pos_ = 0;
int line_ = 1;
int col_ = 1;
int token_start_line_ = 0;
int token_start_col_ = 0;
};
} // namespace kappa::dsl
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include "kappa/dsl/ast.hpp"
#include <string>
#include <string_view>
namespace kappa::dsl {
PackageDef parse(std::string_view source);
} // namespace kappa::dsl
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#include <string>
#include <string_view>
namespace kappa::dsl {
enum class TokenType {
Eof,
Newline,
// Symbols
Lbrace, // {
Rbrace, // }
Equals, // =
Lbracket, // [
Rbracket, // ]
Comma, // ,
// Literals
String, // "..."
Ident, // bare word (keyword, command, variable ref)
// Keywords (tokenised as Ident, then classified)
KwPackage,
KwVersion,
KwSource,
KwDepends,
KwProvides,
KwOutputs,
KwFeatures,
KwConfig,
KwConst,
KwLicense,
KwPatches,
KwEnv,
KwPrepare,
KwBuild,
KwCheck,
KwInstall,
KwTrue,
KwFalse,
};
struct Token {
TokenType type = TokenType::Eof;
std::string lexeme;
int line = 0;
int col = 0;
};
std::string_view token_name(TokenType type);
} // namespace kappa::dsl
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "kappa/dsl/ast.hpp"
#include <string>
#include <string_view>
#include <unordered_map>
namespace kappa::eval {
enum class VarKind {
Unknown,
Builtin, // ${prefix}, ${jobs}, ${jobopts}, ${userargs}
Package, // ${version}, ${name}, ${source}
Config, // ${cfg.key}
Feature, // ${feature.key} → expanded flag or ""
};
struct ResolvedVar {
std::string value;
VarKind kind = VarKind::Unknown;
};
struct Scope {
std::unordered_map<std::string, std::string> builtins;
std::unordered_map<std::string, std::string> config;
std::unordered_map<std::string, dsl::FeatureDef> features;
std::unordered_map<std::string, std::string> package;
};
Scope make_default_scope();
ResolvedVar resolve(std::string_view name, const Scope& scope);
std::string interpolate(std::string_view input, const Scope& scope);
} // namespace kappa::eval
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <iosfwd>
#include <string>
#include <vector>
namespace kappa {
struct PackageConfig {
std::string name;
std::string version;
std::string description;
std::string source_url;
std::string source_extension;
std::string source_hash;
std::vector<std::string> dependencies;
std::string build_system;
};
PackageConfig parse_package(const std::string& toml_path);
void print_package(std::ostream& os, const PackageConfig& pkg);
} // namespace kappa
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <filesystem>
namespace kappa::paths {
inline const std::filesystem::path root{"/kappa"};
inline const auto bin_dir = root / "bin";
inline const auto temp_dir = root / "temp";
inline const auto db_dir = root / "db";
inline const auto system_dir = root / "system";
inline const auto builds_dir = system_dir / "builds";
void ensure_directories();
} // namespace kappa::paths