peg-parser.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. #pragma once
  2. #include <nlohmann/json_fwd.hpp>
  3. #include <memory>
  4. #include <unordered_map>
  5. #include <string>
  6. #include <string_view>
  7. #include <functional>
  8. #include <vector>
  9. #include <variant>
  10. struct common_grammar_builder;
  11. class common_peg_parser_builder;
  12. using common_peg_parser_id = size_t;
  13. constexpr common_peg_parser_id COMMON_PEG_INVALID_PARSER_ID = static_cast<common_peg_parser_id>(-1);
  14. using common_peg_ast_id = size_t;
  15. constexpr common_peg_ast_id COMMON_PEG_INVALID_AST_ID = static_cast<common_peg_ast_id>(-1);
  16. // Lightweight wrapper around common_peg_parser_id for convenience
  17. class common_peg_parser {
  18. common_peg_parser_id id_;
  19. common_peg_parser_builder & builder_;
  20. public:
  21. common_peg_parser(const common_peg_parser & other) : id_(other.id_), builder_(other.builder_) {}
  22. common_peg_parser(common_peg_parser_id id, common_peg_parser_builder & builder) : id_(id), builder_(builder) {}
  23. common_peg_parser & operator=(const common_peg_parser & other);
  24. common_peg_parser & operator+=(const common_peg_parser & other);
  25. common_peg_parser & operator|=(const common_peg_parser & other);
  26. operator common_peg_parser_id() const { return id_; }
  27. common_peg_parser_id id() const { return id_; }
  28. common_peg_parser_builder & builder() const { return builder_; }
  29. // Creates a sequence
  30. common_peg_parser operator+(const common_peg_parser & other) const;
  31. // Creates a sequence separated by spaces.
  32. common_peg_parser operator<<(const common_peg_parser & other) const;
  33. // Creates a choice
  34. common_peg_parser operator|(const common_peg_parser & other) const;
  35. common_peg_parser operator+(const char * str) const;
  36. common_peg_parser operator+(const std::string & str) const;
  37. common_peg_parser operator<<(const char * str) const;
  38. common_peg_parser operator<<(const std::string & str) const;
  39. common_peg_parser operator|(const char * str) const;
  40. common_peg_parser operator|(const std::string & str) const;
  41. };
  42. common_peg_parser operator+(const char * str, const common_peg_parser & p);
  43. common_peg_parser operator+(const std::string & str, const common_peg_parser & p);
  44. common_peg_parser operator<<(const char * str, const common_peg_parser & p);
  45. common_peg_parser operator<<(const std::string & str, const common_peg_parser & p);
  46. common_peg_parser operator|(const char * str, const common_peg_parser & p);
  47. common_peg_parser operator|(const std::string & str, const common_peg_parser & p);
  48. enum common_peg_parse_result_type {
  49. COMMON_PEG_PARSE_RESULT_FAIL = 0,
  50. COMMON_PEG_PARSE_RESULT_SUCCESS = 1,
  51. COMMON_PEG_PARSE_RESULT_NEED_MORE_INPUT = 2,
  52. };
  53. const char * common_peg_parse_result_type_name(common_peg_parse_result_type type);
  54. struct common_peg_ast_node {
  55. common_peg_ast_id id;
  56. std::string rule;
  57. std::string tag;
  58. size_t start;
  59. size_t end;
  60. std::string_view text;
  61. std::vector<common_peg_ast_id> children;
  62. bool is_partial = false;
  63. };
  64. struct common_peg_parse_result;
  65. using common_peg_ast_visitor = std::function<void(const common_peg_ast_node & node)>;
  66. class common_peg_ast_arena {
  67. std::vector<common_peg_ast_node> nodes_;
  68. public:
  69. common_peg_ast_id add_node(
  70. const std::string & rule,
  71. const std::string & tag,
  72. size_t start,
  73. size_t end,
  74. std::string_view text,
  75. std::vector<common_peg_ast_id> children,
  76. bool is_partial = false
  77. ) {
  78. common_peg_ast_id id = nodes_.size();
  79. nodes_.push_back({id, rule, tag, start, end, text, std::move(children), is_partial});
  80. return id;
  81. }
  82. const common_peg_ast_node & get(common_peg_ast_id id) const { return nodes_.at(id); }
  83. size_t size() const { return nodes_.size(); }
  84. void clear() { nodes_.clear(); }
  85. void visit(common_peg_ast_id id, const common_peg_ast_visitor & visitor) const;
  86. void visit(const common_peg_parse_result & result, const common_peg_ast_visitor & visitor) const;
  87. };
  88. struct common_peg_parse_result {
  89. common_peg_parse_result_type type = COMMON_PEG_PARSE_RESULT_FAIL;
  90. size_t start = 0;
  91. size_t end = 0;
  92. std::vector<common_peg_ast_id> nodes;
  93. common_peg_parse_result() = default;
  94. common_peg_parse_result(common_peg_parse_result_type type, size_t start)
  95. : type(type), start(start), end(start) {}
  96. common_peg_parse_result(common_peg_parse_result_type type, size_t start, size_t end)
  97. : type(type), start(start), end(end) {}
  98. common_peg_parse_result(common_peg_parse_result_type type, size_t start, size_t end, std::vector<common_peg_ast_id> nodes)
  99. : type(type), start(start), end(end), nodes(std::move(nodes)) {}
  100. bool fail() const { return type == COMMON_PEG_PARSE_RESULT_FAIL; }
  101. bool need_more_input() const { return type == COMMON_PEG_PARSE_RESULT_NEED_MORE_INPUT; }
  102. bool success() const { return type == COMMON_PEG_PARSE_RESULT_SUCCESS; }
  103. };
  104. struct common_peg_parse_context {
  105. std::string input;
  106. bool is_partial;
  107. common_peg_ast_arena ast;
  108. int parse_depth;
  109. common_peg_parse_context()
  110. : is_partial(false), parse_depth(0) {}
  111. common_peg_parse_context(const std::string & input)
  112. : input(input), is_partial(false), parse_depth(0) {}
  113. common_peg_parse_context(const std::string & input, bool is_partial)
  114. : input(input), is_partial(is_partial), parse_depth(0) {}
  115. };
  116. class common_peg_arena;
  117. // Parser variants
  118. struct common_peg_epsilon_parser {};
  119. struct common_peg_start_parser {};
  120. struct common_peg_end_parser {};
  121. struct common_peg_literal_parser {
  122. std::string literal;
  123. };
  124. struct common_peg_sequence_parser {
  125. std::vector<common_peg_parser_id> children;
  126. };
  127. struct common_peg_choice_parser {
  128. std::vector<common_peg_parser_id> children;
  129. };
  130. struct common_peg_repetition_parser {
  131. common_peg_parser_id child;
  132. int min_count;
  133. int max_count; // -1 for unbounded
  134. };
  135. struct common_peg_and_parser {
  136. common_peg_parser_id child;
  137. };
  138. struct common_peg_not_parser {
  139. common_peg_parser_id child;
  140. };
  141. struct common_peg_any_parser {};
  142. struct common_peg_space_parser {};
  143. struct common_peg_chars_parser {
  144. struct char_range {
  145. uint32_t start;
  146. uint32_t end;
  147. bool contains(uint32_t codepoint) const { return codepoint >= start && codepoint <= end; }
  148. };
  149. std::string pattern;
  150. std::vector<char_range> ranges;
  151. bool negated;
  152. int min_count;
  153. int max_count; // -1 for unbounded
  154. };
  155. struct common_peg_json_string_parser {};
  156. struct common_peg_until_parser {
  157. std::vector<std::string> delimiters;
  158. };
  159. struct common_peg_schema_parser {
  160. common_peg_parser_id child;
  161. std::string name;
  162. std::shared_ptr<nlohmann::ordered_json> schema;
  163. // Indicates if the GBNF should accept a raw string that matches the schema.
  164. bool raw;
  165. };
  166. struct common_peg_rule_parser {
  167. std::string name;
  168. common_peg_parser_id child;
  169. bool trigger;
  170. };
  171. struct common_peg_ref_parser {
  172. std::string name;
  173. };
  174. struct common_peg_atomic_parser {
  175. common_peg_parser_id child;
  176. };
  177. struct common_peg_tag_parser {
  178. common_peg_parser_id child;
  179. std::string tag;
  180. };
  181. // Variant holding all parser types
  182. using common_peg_parser_variant = std::variant<
  183. common_peg_epsilon_parser,
  184. common_peg_start_parser,
  185. common_peg_end_parser,
  186. common_peg_literal_parser,
  187. common_peg_sequence_parser,
  188. common_peg_choice_parser,
  189. common_peg_repetition_parser,
  190. common_peg_and_parser,
  191. common_peg_not_parser,
  192. common_peg_any_parser,
  193. common_peg_space_parser,
  194. common_peg_chars_parser,
  195. common_peg_json_string_parser,
  196. common_peg_until_parser,
  197. common_peg_schema_parser,
  198. common_peg_rule_parser,
  199. common_peg_ref_parser,
  200. common_peg_atomic_parser,
  201. common_peg_tag_parser
  202. >;
  203. class common_peg_arena {
  204. std::vector<common_peg_parser_variant> parsers_;
  205. std::unordered_map<std::string, common_peg_parser_id> rules_;
  206. common_peg_parser_id root_ = COMMON_PEG_INVALID_PARSER_ID;
  207. public:
  208. const common_peg_parser_variant & get(common_peg_parser_id id) const { return parsers_.at(id); }
  209. common_peg_parser_variant & get(common_peg_parser_id id) { return parsers_.at(id); }
  210. size_t size() const { return parsers_.size(); }
  211. bool empty() const { return parsers_.empty(); }
  212. common_peg_parser_id get_rule(const std::string & name) const;
  213. bool has_rule(const std::string & name) const { return rules_.find(name) != rules_.end(); }
  214. common_peg_parser_id root() const { return root_; }
  215. void set_root(common_peg_parser_id id) { root_ = id; }
  216. common_peg_parse_result parse(common_peg_parse_context & ctx, size_t start = 0) const;
  217. common_peg_parse_result parse(common_peg_parser_id id, common_peg_parse_context & ctx, size_t start) const;
  218. void resolve_refs();
  219. void build_grammar(const common_grammar_builder & builder, bool lazy = false) const;
  220. std::string dump(common_peg_parser_id id) const;
  221. nlohmann::json to_json() const;
  222. static common_peg_arena from_json(const nlohmann::json & j);
  223. std::string save() const;
  224. void load(const std::string & data);
  225. friend class common_peg_parser_builder;
  226. private:
  227. common_peg_parser_id add_parser(common_peg_parser_variant parser);
  228. void add_rule(const std::string & name, common_peg_parser_id id);
  229. common_peg_parser_id resolve_ref(common_peg_parser_id id);
  230. };
  231. class common_peg_parser_builder {
  232. common_peg_arena arena_;
  233. common_peg_parser wrap(common_peg_parser_id id) { return common_peg_parser(id, *this); }
  234. common_peg_parser add(const common_peg_parser_variant & p) { return wrap(arena_.add_parser(p)); }
  235. public:
  236. common_peg_parser_builder();
  237. // Match nothing, always succeed.
  238. // S -> ε
  239. common_peg_parser eps() { return add(common_peg_epsilon_parser{}); }
  240. // Matches the start of the input.
  241. // S -> ^
  242. common_peg_parser start() { return add(common_peg_start_parser{}); }
  243. // Matches the end of the input.
  244. // S -> $
  245. common_peg_parser end() { return add(common_peg_end_parser{}); }
  246. // Matches an exact literal string.
  247. // S -> "hello"
  248. common_peg_parser literal(const std::string & literal) { return add(common_peg_literal_parser{literal}); }
  249. // Matches a sequence of parsers in order, all must succeed.
  250. // S -> A B C
  251. common_peg_parser sequence() { return add(common_peg_sequence_parser{}); }
  252. common_peg_parser sequence(const std::vector<common_peg_parser_id> & parsers);
  253. common_peg_parser sequence(const std::vector<common_peg_parser> & parsers);
  254. common_peg_parser sequence(std::initializer_list<common_peg_parser> parsers);
  255. // Matches the first parser that succeeds from a list of alternatives.
  256. // S -> A | B | C
  257. common_peg_parser choice() { return add(common_peg_choice_parser{}); }
  258. common_peg_parser choice(const std::vector<common_peg_parser_id> & parsers);
  259. common_peg_parser choice(const std::vector<common_peg_parser> & parsers);
  260. common_peg_parser choice(std::initializer_list<common_peg_parser> parsers);
  261. // Matches one or more repetitions of a parser.
  262. // S -> A+
  263. common_peg_parser one_or_more(const common_peg_parser & p) { return repeat(p, 1, -1); }
  264. // Matches zero or more repetitions of a parser, always succeeds.
  265. // S -> A*
  266. common_peg_parser zero_or_more(const common_peg_parser & p) { return repeat(p, 0, -1); }
  267. // Matches zero or one occurrence of a parser, always succeeds.
  268. // S -> A?
  269. common_peg_parser optional(const common_peg_parser & p) { return repeat(p, 0, 1); }
  270. // Positive lookahead: succeeds if child parser succeeds, consumes no input.
  271. // S -> &A
  272. common_peg_parser peek(const common_peg_parser & p) { return add(common_peg_and_parser{p}); }
  273. // Negative lookahead: succeeds if child parser fails, consumes no input.
  274. // S -> !A
  275. common_peg_parser negate(const common_peg_parser & p) { return add(common_peg_not_parser{p}); }
  276. // Matches any single character.
  277. // S -> .
  278. common_peg_parser any() { return add(common_peg_any_parser{}); }
  279. // Matches between min and max repetitions of characters from a character class.
  280. // S -> [a-z]{m,n}
  281. //
  282. // Use -1 for max to represent unbounded repetition (equivalent to {m,})
  283. common_peg_parser chars(const std::string & classes, int min = 1, int max = -1);
  284. // Creates a lightweight reference to a named rule (resolved during build()).
  285. // Use this for forward references in recursive grammars.
  286. // expr_ref -> expr
  287. common_peg_parser ref(const std::string & name) { return add(common_peg_ref_parser{name}); }
  288. // Matches zero or more whitespace characters (space, tab, newline).
  289. // S -> [ \t\n]*
  290. common_peg_parser space() { return add(common_peg_space_parser{}); }
  291. // Matches all characters until a delimiter is found (delimiter not consumed).
  292. // S -> (!delim .)*
  293. common_peg_parser until(const std::string & delimiter) { return add(common_peg_until_parser{{delimiter}}); }
  294. // Matches all characters until one of the delimiters in the list is found (delimiter not consumed).
  295. // S -> (!delim .)*
  296. common_peg_parser until_one_of(const std::vector<std::string> & delimiters) { return add(common_peg_until_parser{delimiters}); }
  297. // Matches everything
  298. // S -> .*
  299. common_peg_parser rest() { return until_one_of({}); }
  300. // Matches between min and max repetitions of a parser (inclusive).
  301. // S -> A{m,n}
  302. // Use -1 for max to represent unbounded repetition (equivalent to {m,})
  303. common_peg_parser repeat(const common_peg_parser & p, int min, int max) { return add(common_peg_repetition_parser{p, min,max}); }
  304. // Matches exactly n repetitions of a parser.
  305. // S -> A{n}
  306. common_peg_parser repeat(const common_peg_parser & p, int n) { return repeat(p, n, n); }
  307. // Creates a complete JSON parser supporting objects, arrays, strings, numbers, booleans, and null.
  308. // value -> object | array | string | number | true | false | null
  309. common_peg_parser json();
  310. common_peg_parser json_object();
  311. common_peg_parser json_string();
  312. common_peg_parser json_array();
  313. common_peg_parser json_number();
  314. common_peg_parser json_bool();
  315. common_peg_parser json_null();
  316. // Matches JSON string content without the surrounding quotes.
  317. // Useful for extracting content within a JSON string.
  318. common_peg_parser json_string_content();
  319. // Matches a JSON object member with a key and associated parser as the
  320. // value.
  321. common_peg_parser json_member(const std::string & key, const common_peg_parser & p);
  322. // Wraps a parser with JSON schema metadata for grammar generation.
  323. // Used internally to convert JSON schemas to GBNF grammar rules.
  324. common_peg_parser schema(const common_peg_parser & p, const std::string & name, const nlohmann::ordered_json & schema, bool raw = false);
  325. // Creates a named rule, stores it in the grammar, and returns a ref.
  326. // If trigger=true, marks this rule as an entry point for lazy grammar generation.
  327. // auto json = p.rule("json", json_obj | json_arr | ...)
  328. common_peg_parser rule(const std::string & name, const common_peg_parser & p, bool trigger = false);
  329. // Creates a named rule using a builder function, and returns a ref.
  330. // If trigger=true, marks this rule as an entry point for lazy grammar generation.
  331. // auto json = p.rule("json", [&]() { return json_object() | json_array() | ... })
  332. common_peg_parser rule(const std::string & name, const std::function<common_peg_parser()> & builder, bool trigger = false);
  333. // Creates a trigger rule. When generating a lazy grammar from the parser,
  334. // only trigger rules and descendents are emitted.
  335. common_peg_parser trigger_rule(const std::string & name, const common_peg_parser & p) { return rule(name, p, true); }
  336. common_peg_parser trigger_rule(const std::string & name, const std::function<common_peg_parser()> & builder) { return rule(name, builder, true); }
  337. // Creates an atomic parser. Atomic parsers do not create an AST node if
  338. // the child results in a partial parse, i.e. NEEDS_MORE_INPUT. This is
  339. // intended for situations where partial output is undesirable.
  340. common_peg_parser atomic(const common_peg_parser & p) { return add(common_peg_atomic_parser{p}); }
  341. // Tags create nodes in the generated AST for semantic purposes.
  342. // Unlike rules, you can tag multiple nodes with the same tag.
  343. common_peg_parser tag(const std::string & tag, const common_peg_parser & p) { return add(common_peg_tag_parser{p.id(), tag}); }
  344. void set_root(const common_peg_parser & p);
  345. common_peg_arena build();
  346. };
  347. // Helper function for building parsers
  348. common_peg_arena build_peg_parser(const std::function<common_peg_parser(common_peg_parser_builder & builder)> & fn);