| 131 | }; |
| 132 | |
| 133 | class Argparse { |
| 134 | public: |
| 135 | Argparse() = default; |
| 136 | |
| 137 | template<typename T> |
| 138 | static Argument<T>& add(const std::string& flags) { |
| 139 | auto& inst = instance(); |
| 140 | auto arg = std::make_unique<Argument<T>>(); |
| 141 | auto flag_list = splitFlags(flags); |
| 142 | for (const auto& f : flag_list) { arg->flag(f); } |
| 143 | if (flag_list.empty()) arg->positional(); |
| 144 | Argument<T>* ptr = arg.get(); |
| 145 | inst.args_.push_back(std::move(arg)); |
| 146 | return *ptr; |
| 147 | } |
| 148 | |
| 149 | static void parse(int argc, char* argv[]) { |
| 150 | auto& inst = instance(); |
| 151 | std::vector<std::string> args(argv + 1, argv + argc); |
| 152 | std::vector<std::string> positional_args; |
| 153 | |
| 154 | // First parse options |
| 155 | for (size_t i = 0; i < args.size(); ++i) { |
| 156 | const auto& arg = args[i]; |
| 157 | if (arg[0] == '-') { |
| 158 | bool found = false; |
| 159 | for (auto& param : inst.args_) { |
| 160 | const auto& flags = param->flags(); |
| 161 | if (std::find(flags.begin(), flags.end(), arg) != flags.end()) { |
| 162 | if (param->isBoolean()) { |
| 163 | param->handleFlag(); |
| 164 | } else { |
| 165 | if (i + 1 >= args.size()) { |
| 166 | printHelp(); |
| 167 | MLLM_ERROR_EXIT(ExitCode::kCoreError, "Missing value for {}", arg); |
| 168 | } |
| 169 | param->parse(args[++i]); |
| 170 | } |
| 171 | found = true; |
| 172 | break; |
| 173 | } |
| 174 | } |
| 175 | if (!found) { |
| 176 | printHelp(); |
| 177 | MLLM_ERROR_EXIT(ExitCode::kCoreError, "Unknown option: {}", arg); |
| 178 | } |
| 179 | } else { |
| 180 | positional_args.push_back(arg); |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | // Then parse positional arguments |
| 185 | size_t pos_idx = 0; |
| 186 | for (auto& param : inst.args_) { |
| 187 | if (param->isPositional()) { |
| 188 | if (pos_idx >= positional_args.size()) { |
| 189 | if (param->isRequired()) { |
| 190 | printHelp(); |