kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

json_frontend.ebnf (2185B)


      1 // JSON front end: the realistic JSON grammar (RFC 8259) with the two sub-lexers
      2 // a real frontend uses to turn leaf lexemes into values. The parser yields whole
      3 // NUMBER / STRING tokens; the value-channel actions then point a sub-lexer at the
      4 // token's own bytes to decode it — NUMBER via the `number` sub-lexer (classify
      5 // int vs float, read the integer value), STRING via the `strescape` sub-lexer
      6 // (unescape into raw UTF-8). Driven by test/realistic/test_json_frontend.c, which
      7 // reaches the sub-lexers through gramgen_lexer_grammar_at / gramgen_find_lexer.
      8 //
      9 // The main lexer + parser are the ordinary JSON grammar, written with inline
     10 // string literals ("[", "true", ...) exactly like test/realistic/json.ebnf — the
     11 // `strescape` sub-lexer's catch-all SCHARS = [^"\\]+ does NOT shadow them, because
     12 // parser literals are scoped to the parser-feeding (main) lexer and never
     13 // injected into a sub-lexer.
     14 %lex {
     15   %skip WS = [ \t\r\n] [ \t\r\n]*;
     16 
     17   // string = quote ( unescaped | '\' escape )* quote
     18   STRING = "\"" ( [^"\\] | "\\" ( ["\\/bfnrt] | "u" [0-9A-Fa-f] [0-9A-Fa-f] [0-9A-Fa-f] [0-9A-Fa-f] ) )* "\"";
     19 
     20   // number = -? int frac? exp?    (no leading zeros, per the spec)
     21   NUMBER = "-"? ( "0" | [1-9] [0-9]* ) ( "." [0-9]+ )? ( [eE] [+\-]? [0-9]+ )?;
     22 }
     23 
     24 // NUMBER payload -> sign / integer / fraction / exponent parts.
     25 %lex number {
     26   %def digit = [0-9];
     27   NSIGN = "-";
     28   NINT  = digit+;
     29   NFRAC = "." digit+;
     30   NEXP  = [eE] [+\-]? digit+;
     31 }
     32 
     33 // STRING payload -> quotes, literal runs, and one escape atom per escape. The
     34 // catch-all SCHARS would have collided with the parser's "[" / "true" / ... if
     35 // parser literals were shared across lexers — they are not.
     36 %lex strescape {
     37   SQUOTE = "\"";
     38   SESC   = "\\" ( ["\\/bfnrt] | "u" [0-9A-Fa-f] [0-9A-Fa-f] [0-9A-Fa-f] [0-9A-Fa-f] );
     39   SCHARS = [^"\\]+;
     40 }
     41 
     42 %token TRUE  = "true";
     43 %token FALSE = "false";
     44 %token NULL  = "null";
     45 
     46 value   = object | array | STRING | NUMBER | "true" | "false" | "null";
     47 
     48 object  = "{" members? "}";
     49 members = member member_tail*;
     50 member_tail = "," member;
     51 member  = STRING ":" value;
     52 
     53 array   = "[" elements? "]";
     54 elements = value element_tail*;
     55 element_tail = "," value;