The initial commit of jq is a Haskell implementation, before it was converted to C a month later. This reviews the language in those two commits.
|
Pipe,
Stream.
No-op.ident
, x.ident
Named property lookup[]
Array spreading[…]
Array and object lookup… as $ident
Variable bindings (C-only)$ident
Variable references (C-only)ident
, ident(…)
Arity 0 or 1 filter call (Haskell-only)
select/1
Select values other than false
and null
find/1
set/1
Updatesort/0
Sort arraygroup/1
Group array or return null
ident
Arity 0 filter call (C-only)
true
Boolean truefalse
Boolean false+
Integer addition, string concatenation, and array concatenation==
Equality (Haskell-only)LOADK
(constant; a – b)DUP
(a – b c) Duplicate top of stackSWAP
(x y – y x) Swap top two on stackPOP
(x – ) Pop from stackLOADV
(variable; a – b)STOREV
(variable; a – )INDEX
(a b – c) Array and object lookupAPPEND
(a b – c) Array appendINSERT
(a b c d – e f) Object assignmentYIELD
(a – )EACH
(a – b) Streaming ([]
)FORK
(branch; – )JUMP
(branch; – ) Unconditional jumpBACKTRACK
( – )CALL_BUILTIN_1_1
(function; a – b) Call a builtinNotably, it only supported integers, not floating point, and the syntax of filter calls was different. It was not Turing-complete.
Stack annotations with a
, b
, c
, d
, e
, and f
have not been analyzed
to be named. I am not sure of the precise operation of the unlabeled operations
(find
, LOADK
, LOADV
, and STOREV
) and most control-flow operations
(YIELD
, EACH
, FORK
, JUMP
, and BACKTRACK
).
Lexer:
IDENT ::= [a-z A-Z _] [a-z A-Z 0-9 _]*
STRING ::= "\"" CHAR* "\""
CHAR ::=
| PRINTABLE -- [\"\\]
| "\\" ["\\/]
| "\\" [nrt]
| "\\u" [0-9 a-f A-F]{4}
INT ::= [0-9]+
WHITESPACE ::= …
RESERVED ::=
| "." | "[" | "]" | "," | ":" | "(" | ")" | "{" | "}" | "|" | "==" | "+"
Parser:
Exp ::=
| Exp "|" Exp # left associativity
| Exp "," Exp # left associativity
| Exp "==" Exp # no associativity
| Exp "+" Exp # left associativity
| Term
ExpD ::=
| ExpD "|" ExpD
| ExpD "==" ExpD
| Term
Term ::=
| "."
| Term "." IDENT
| "." IDENT
| STRING
| Term "[" Exp "]"
| Term "[" "]"
| "(" Exp ")"
| "[" Exp "]"
| INT
| "{" MkDict "}"
| IDENT "(" Exp ")"
| IDENT
MkDict ::=
| MkDictPair
| MkDictPair "," MkDict # left associativity
MkDictPair ::=
| IDENT ":" ExpD
| IDENT
| STRING ":" ExpD
| "(" Exp ")" ":" ExpD
Lexer:
Number ::= [0-9]+
IDENT ::= [a-z A-Z 0-9]+
WHITESPACE ::= [ \n\t]+
RESERVED ::=
| "." | "=" | ";" | "[" | "]" | "," | ":" | "(" | ")" | "{" | "}"
| "|" | "+" | "$" | "==" | "as"
Parser:
Exp ::=
| Term "as" "$" IDENT "|" Exp ; "|" is left associative
| Exp "|" Exp ; left associativity
| Exp "," Exp ; left associativity
| Term
ExpD ::=
| ExpD "|" ExpD
| Term
Term ::=
| "."
| Term "." IDENT
| "." IDENT
| Term "[" Exp "]"
| Term "[" "]"
| NUMBER
| "(" Exp ")"
| "[" Exp "]"
| "[" "]"
| "{" MkDict "}"
| IDENT
| "$" IDENT
MkDict ::=
|
| MkDictPair
| MkDictPair ',' MkDict
MkDictPair ::=
| IDENT ':' ExpD
| IDENT
| '(' Exp ')' ':' ExpD