mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
174 lines
3.8 KiB
Plaintext
174 lines
3.8 KiB
Plaintext
%{
|
|
#include "jv_alloc.h"
|
|
#include "compile.h"
|
|
|
|
struct lexer_param;
|
|
|
|
#include "parser.h" /* Generated by bison. */
|
|
|
|
#define YY_USER_ACTION \
|
|
do { \
|
|
yylloc->start = yyget_extra(yyscanner); \
|
|
yylloc->end = yylloc->start + yyleng; \
|
|
yyset_extra(yylloc->end, yyscanner); \
|
|
} while (0);
|
|
|
|
%}
|
|
|
|
%s IN_PAREN
|
|
%s IN_BRACKET
|
|
%s IN_BRACE
|
|
%s IN_QQINTERP
|
|
%x IN_QQSTRING
|
|
%{
|
|
static int enter(int opening, int state, yyscan_t yyscanner);
|
|
static int try_exit(int closing, int state, yyscan_t yyscanner);
|
|
%}
|
|
|
|
%option noyywrap nounput noinput nodefault
|
|
%option noyyalloc noyyrealloc noyyfree
|
|
%option reentrant
|
|
%option extra-type="int"
|
|
%option bison-bridge bison-locations
|
|
%option prefix="jq_yy"
|
|
%option stack
|
|
|
|
|
|
%%
|
|
|
|
"#"[^\r\n]* { /* comments */ }
|
|
|
|
"!=" { return NEQ; }
|
|
"==" { return EQ; }
|
|
"as" { return AS; }
|
|
"def" { return DEF; }
|
|
"if" { return IF; }
|
|
"then" { return THEN; }
|
|
"else" { return ELSE; }
|
|
"elif" { return ELSE_IF; }
|
|
"and" { return AND; }
|
|
"or" { return OR; }
|
|
"end" { return END; }
|
|
"reduce" { return REDUCE; }
|
|
"//" { return DEFINEDOR; }
|
|
"|=" { return SETPIPE; }
|
|
"+=" { return SETPLUS; }
|
|
"-=" { return SETMINUS; }
|
|
"*=" { return SETMULT; }
|
|
"/=" { return SETDIV; }
|
|
"%=" { return SETMOD; }
|
|
"//=" { return SETDEFINEDOR; }
|
|
"<=" { return LESSEQ; }
|
|
">=" { return GREATEREQ; }
|
|
"."|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"%"|"\$"|"<"|">" { return yytext[0];}
|
|
|
|
"["|"{"|"(" {
|
|
return enter(yytext[0], YY_START, yyscanner);
|
|
}
|
|
|
|
"]"|"}"|")" {
|
|
return try_exit(yytext[0], YY_START, yyscanner);
|
|
}
|
|
|
|
"@"[a-zA-Z0-9_]+ {
|
|
yylval->literal = jv_string_sized(yytext + 1, yyleng - 1); return FORMAT;
|
|
}
|
|
|
|
[0-9.]+([eE][+-]?[0-9]+)? {
|
|
yylval->literal = jv_parse_sized(yytext, yyleng); return LITERAL;
|
|
}
|
|
|
|
"\"" {
|
|
yy_push_state(IN_QQSTRING, yyscanner);
|
|
return QQSTRING_START;
|
|
}
|
|
|
|
<IN_QQSTRING>{
|
|
"\\(" {
|
|
return enter(QQSTRING_INTERP_START, YY_START, yyscanner);
|
|
}
|
|
"\"" {
|
|
yy_pop_state(yyscanner);
|
|
return QQSTRING_END;
|
|
}
|
|
(\\[^u(]|\\u[a-zA-Z0-9]{0,4})+ {
|
|
/* pass escapes to the json parser */
|
|
jv escapes = jv_string_fmt("\"%.*s\"", yyleng, yytext);
|
|
yylval->literal = jv_parse_sized(jv_string_value(escapes), jv_string_length_bytes(jv_copy(escapes)));
|
|
jv_free(escapes);
|
|
return QQSTRING_TEXT;
|
|
}
|
|
[^\\\"]+ {
|
|
yylval->literal = jv_string_sized(yytext, yyleng);
|
|
return QQSTRING_TEXT;
|
|
}
|
|
. {
|
|
return INVALID_CHARACTER;
|
|
}
|
|
}
|
|
|
|
|
|
[a-zA-Z_][a-zA-Z_0-9]* { yylval->literal = jv_string(yytext); return IDENT;}
|
|
\.[a-zA-Z_][a-zA-Z_0-9]* { yylval->literal = jv_string(yytext+1); return FIELD;}
|
|
|
|
[ \n\t]+ {}
|
|
|
|
. { return INVALID_CHARACTER; }
|
|
|
|
%%
|
|
/* perhaps these should be calls... */
|
|
/*
|
|
"true" { return TRUE; }
|
|
"false" { return FALSE; }
|
|
"null" { return NULL; }
|
|
*/
|
|
static int try_exit(int c, int state, yyscan_t yyscanner) {
|
|
char match = 0;
|
|
int ret;
|
|
switch (state) {
|
|
case IN_PAREN: match = ret = ')'; break;
|
|
case IN_BRACKET: match = ret = ']'; break;
|
|
case IN_BRACE: match = ret = '}'; break;
|
|
|
|
case IN_QQINTERP:
|
|
match = ')';
|
|
ret = QQSTRING_INTERP_END;
|
|
break;
|
|
|
|
default:
|
|
// may not be the best error to give
|
|
return INVALID_CHARACTER;
|
|
}
|
|
assert(match);
|
|
if (match == c) {
|
|
yy_pop_state(yyscanner);
|
|
return ret;
|
|
} else {
|
|
// FIXME: should we pop? Give a better error at least
|
|
return INVALID_CHARACTER;
|
|
}
|
|
}
|
|
|
|
static int enter(int c, int currstate, yyscan_t yyscanner) {
|
|
int state = 0;
|
|
switch (c) {
|
|
case '(': state = IN_PAREN; break;
|
|
case '[': state = IN_BRACKET; break;
|
|
case '{': state = IN_BRACE; break;
|
|
case QQSTRING_INTERP_START: state = IN_QQINTERP; break;
|
|
}
|
|
assert(state);
|
|
yy_push_state(state, yyscanner);
|
|
return c;
|
|
}
|
|
|
|
void* yyalloc(size_t sz, void* extra) {
|
|
return jv_mem_alloc(sz);
|
|
}
|
|
void* yyrealloc(void* p, size_t sz, void* extra) {
|
|
return jv_mem_realloc(p, sz);
|
|
}
|
|
void yyfree(void* p, void* extra) {
|
|
jv_mem_free(p);
|
|
}
|