Parsing JSON with lex and yacc
%{ | |
#include<stdio.h> | |
#include "json.tab.h" | |
char *strclone(char *str); | |
/* | |
#define STRING "str" | |
#define NUMBER "number" | |
#define O_BEGIN "o_begin" | |
#define O_END "o_end" | |
#define A_BEGIN "a_begin" | |
#define A_END "a_end" | |
#define COMMA "comma" | |
*/ | |
%} | |
DIGIT1to9 [1-9] | |
DIGIT [0-9] | |
DIGITS {DIGIT}+ | |
INT {DIGIT}|{DIGIT1to9}{DIGITS}|-{DIGIT}|-{DIGIT1to9}{DIGITS} | |
FRAC [.]{DIGITS} | |
EXP {E}{DIGITS} | |
E [eE][+-]? | |
HEX_DIGIT [0-9a-f] | |
NUMBER {INT}|{INT}{FRAC}|{INT}{EXP}|{INT}{FRAC}{EXP} | |
UNESCAPEDCHAR [ -!#-\[\]-~] | |
ESCAPEDCHAR \\["\\bfnrt/] | |
UNICODECHAR \\u{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT} | |
CHAR {UNESCAPEDCHAR}|{ESCAPEDCHAR}|{UNICODECHAR} | |
CHARS {CHAR}+ | |
DBL_QUOTE ["] | |
%% | |
{DBL_QUOTE}{DBL_QUOTE} | | |
{DBL_QUOTE}{CHARS}{DBL_QUOTE} { | |
yylval=strclone(yytext); | |
return STRING; | |
}; | |
{NUMBER} { | |
yylval=strclone(yytext); | |
return NUMBER; | |
} | |
true { | |
return true; | |
}; | |
false { | |
return false; | |
}; | |
null { | |
return null; | |
}; | |
\{ { | |
return O_BEGIN; | |
}; | |
\} { | |
return O_END; | |
}; | |
\[ { | |
return A_BEGIN; | |
}; | |
\] { | |
return A_END; | |
}; | |
, { | |
return COMMA; | |
}; | |
: { | |
return COLON; | |
}; | |
[ \t\n]+ /* ignore whitespace */; | |
. { | |
printf("Unexpected: %c\nExiting...\n",*yytext); | |
exit(0); | |
} | |
%% | |
char *strclone(char *str) | |
{ | |
int len = strlen(str); | |
char *clone = (char *)malloc(sizeof(char)*(len+1)); | |
strcpy(clone,str); | |
return clone; | |
} |
%{ | |
#include<stdio.h> | |
#include<string.h> | |
#include<stdlib.h> | |
#define YYSTYPE char* | |
char *strconcat(char *str1, char *str2); | |
%} | |
%token NUMBER | |
%token STRING | |
%token true false null | |
%left O_BEGIN O_END A_BEGIN A_END | |
%left COMMA | |
%left COLON | |
%% | |
START: ARRAY { | |
printf("%s",$1); | |
} | |
| OBJECT { | |
printf("%s",$1); | |
} | |
; | |
OBJECT: O_BEGIN O_END { | |
$$ = "{}"; | |
} | |
| O_BEGIN MEMBERS O_END { | |
$$ = (char *)malloc(sizeof(char)*(1+strlen($2)+1+1)); | |
sprintf($$,"{%s}",$2); | |
} | |
; | |
MEMBERS: PAIR { | |
$$ = $1; | |
} | |
| PAIR COMMA MEMBERS { | |
$$ = (char *)malloc(sizeof(char)*(strlen($1)+1+strlen($3)+1)); | |
sprintf($$,"%s,%s",$1,$3); | |
} | |
; | |
PAIR: STRING COLON VALUE { | |
$$ = (char *)malloc(sizeof(char)*(strlen($1)+1+strlen($3)+1)); | |
sprintf($$,"%s:%s",$1,$3); | |
} | |
; | |
ARRAY: A_BEGIN A_END { | |
$$ = (char *)malloc(sizeof(char)*(2+1)); | |
sprintf($$,"[]"); | |
} | |
| A_BEGIN ELEMENTS A_END { | |
$$ = (char *)malloc(sizeof(char)*(1+strlen($2)+1+1)); | |
sprintf($$,"[%s]",$2); | |
} | |
; | |
ELEMENTS: VALUE { | |
$$ = $1; | |
} | |
| VALUE COMMA ELEMENTS { | |
$$ = (char *)malloc(sizeof(char)*(strlen($1)+1+strlen($3)+1)); | |
sprintf($$,"%s,%s",$1,$3); | |
} | |
; | |
VALUE: STRING {$$=yylval;} | |
| NUMBER {$$=yylval;} | |
| OBJECT {$$=$1;} | |
| ARRAY {$$=$1;} | |
| true {$$="true";} | |
| false {$$="false";} | |
| null {$$="null";} | |
; | |
%% | |
int main() | |
{ | |
printf("\n"); | |
yyparse(); | |
printf("\n"); | |
return 0; | |
} | |
int yywrap() | |
{ | |
return 1; | |
} | |
void yyerror (char const *s) { | |
fprintf (stderr, "%s\n", s); | |
} | |
char *strconcat(char *str1, char *str2) | |
{ | |
int len1 = strlen(str1); | |
int len2 = strlen(str2); | |
char *str3 = (char *)malloc(sizeof(char)*(len1+len2+1)); | |
strcpy(str3,str1); | |
strcpy(&(str3[len1]),str2); | |
return str3; | |
} |
The MIT License (MIT) | |
Copyright (c) 2015 J Kishore Kumar | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in | |
all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
THE SOFTWARE. |
This comment has been minimized.
This comment has been minimized.
You could replace |
This comment has been minimized.
This comment has been minimized.
Thank you for this. In order to compile on a Mac: In both json.l and json.y add just before the .h includes:
in json.y add "int yylex();" in the includes as well. Sorry I can't submit a pull request on a Gist. So comments it is. |
This comment has been minimized.
This comment has been minimized.
Thanks for sharing this. A couple of comments: I think whitespace should include carriage return i.e. [ \t\n\r]+ /* ignore whitespace */; in json.l Also, the root should accept VALUE not just OBJECT | ARRAY in json.y (see https://tools.ietf.org/html/rfc7159#section-2). |
This comment has been minimized.
This comment has been minimized.
How should I compile and run in Ubuntu? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Thanks a lot for this.