e2348db082
Adds parse_sml(text) -> Item / try_parse_sml(text) -> optional<Item> in secs2/sml.hpp. Round-trips with the existing to_sml() emitter for every Item shape the codec produces: lists with nesting, ASCII / JIS8, Binary (decimal and 0xHH literals), Boolean (T/F or 1/0, scalar and multi-element), U1-U8 / I1-I8 / F4 / F8 vectors, and the optional `[n]` count syntax (accepted but not enforced). The parser is whitespace-insensitive outside quoted strings and uses a small Cursor type for read_word / read_quoted / skip_ws. Numeric literals go through strtoul/strtoll/strtod so SML can carry hex, octal, and decimal interchangeably (the emitter writes hex for Binary and decimal everywhere else). 11 test cases cover the full round-trip surface, the whitespace invariant, unknown-tag rejection, the try_parse error-swallowing variant, and the optional `[n]` count. secsgem-py has secs/sml.py for the same purpose; this brings the C++ port to parity on the tooling side. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
33 lines
1.1 KiB
C++
33 lines
1.1 KiB
C++
#pragma once
|
|
|
|
#include <optional>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
#include "secsgem/secs2/item.hpp"
|
|
|
|
// SML (SECS Message Language) parser — the inverse of `to_sml()` in
|
|
// codec.cpp. Accepts the same human-readable form emitted by
|
|
// Item::sml() / Message::sml(): each item is `<TAG [count]? values >`
|
|
// with nesting for lists. Strings are quoted; numeric literals are
|
|
// whitespace-separated; binary bytes use `0x` prefix or decimal.
|
|
//
|
|
// The grammar is loose but unambiguous. Whitespace (incl. newlines)
|
|
// is insignificant outside of quoted strings. The optional `[n]`
|
|
// count is accepted but not enforced — actual element counts come
|
|
// from the values that follow. Boolean accepts T/F as well as 1/0.
|
|
namespace secsgem::secs2 {
|
|
|
|
class SmlError : public std::runtime_error {
|
|
public:
|
|
using std::runtime_error::runtime_error;
|
|
};
|
|
|
|
// Parse a single Item. Throws SmlError on a malformed input.
|
|
Item parse_sml(const std::string& text);
|
|
|
|
// Try-style variant that returns nullopt instead of throwing.
|
|
std::optional<Item> try_parse_sml(const std::string& text);
|
|
|
|
} // namespace secsgem::secs2
|