Skip to content

Instantly share code, notes, and snippets.

@jchris
Created July 30, 2008 01:46
Show Gist options
  • Save jchris/3212 to your computer and use it in GitHub Desktop.
Save jchris/3212 to your computer and use it in GitHub Desktop.
Nonterminals array element elements object members member.
Terminals '{' '}' '[' ']' string ',' ':' integer float true false null.
Rootsymbol element.
object -> '{' members '}' : {obj, '$2'}.
object -> '{' '}' : {obj, []}.
% object -> '{' member '}' : {'$2'}. % results in a shift/reduce conflict...
members -> member ',' members : ['$1' | '$3'].
members -> member : ['$1'].
member -> string ':' element : {element(3, '$1'),'$3'}.
array -> '[' elements ']' : list_to_tuple('$2').
elements -> element ',' elements : ['$1' | '$3'].
elements -> element : ['$1'].
elements -> '$empty' : [].
element -> string : element(3, '$1').
element -> array : '$1'.
element -> object : '$1'.
element -> integer : element(3, '$1').
element -> float : element(3, '$1').
element -> true : element(1, '$1').
element -> false : element(1, '$1').
element -> null : element(1, '$1').
Definitions.
ST = [^"]
L = [A-Za-z]
WS = ([\000-\s]|%.*)
D = [0-9]
H = [0-9a-fA-F]
Rules.
{ : {token, {'{', TokenLine}}.
} : {token, {'}', TokenLine}}.
\[ : {token, {'[', TokenLine}}.
\] : {token, {']', TokenLine}}.
\-?{D}+\.{D}+((E|e)(\+|\-)?{D}+)? : {token,{float,TokenLine,list_to_float(TokenChars)}}.
\-?{D}+(E|e)(\+|\-)?{D}+ : {token,{float,TokenLine,whole_float(TokenChars)}}.
\-?{D}+ : {token,{integer,TokenLine,list_to_integer(TokenChars)}}.
% "[^"\\]*(\\[^u][^"\\]*)*" : {token,{string,TokenLine,strip(unicode_string(TokenChars),TokenLen)}}.
"[^"\\]*(\\.[^"\\]*)*" : {token,{string,TokenLine,parse_string(strip(TokenChars,TokenLen))}}.
% \\u{H}{H}{H}{H} : {token, {unicode, TokenLine,TokenChars}}.
true : {token,{'true', TokenLine}}.
false : {token,{'false', TokenLine}}.
null : {token,{'null', TokenLine}}.
: : {token, {':', TokenLine}}.
, : {token, {',', TokenLine}}.
{WS}+ : skip_token.
Erlang code.
% "
-define(LOG(Name, Value),
io:format("{~p:~p}: ~p -> ~s~n", [?MODULE, ?LINE, Name, Value])).
-define(PLOG(Name, Value),
io:format("{~p:~p}: ~p -> ~p~n", [?MODULE, ?LINE, Name, Value])).
strip(TokenChars,TokenLen) -> lists:sublist(TokenChars, 2, TokenLen - 2).
whole_float(TokenChars) ->
{ok, NowFloat, 1 } = regexp:sub(TokenChars,"e",".0e"),
list_to_float(NowFloat).
unescape([$\\,$\"|Cs]) -> [$\"|unescape(Cs)];
unescape([$\\,$\\|Cs]) -> [$\\|unescape(Cs)];
unescape([$\\,$/|Cs]) -> [$/|unescape(Cs)];
unescape([$\\,$b|Cs]) -> [$\b|unescape(Cs)];
unescape([$\\,$f|Cs]) -> [$\f|unescape(Cs)];
unescape([$\\,$n|Cs]) -> [$\n|unescape(Cs)];
unescape([$\\,$r|Cs]) -> [$\r|unescape(Cs)];
unescape([$\\,$t|Cs]) -> [$\t|unescape(Cs)];
unescape([$\\,$u,C0,C1,C2,C3|Cs]) ->
C = dehex(C0) bor
(dehex(C1) bsl 4) bor
(dehex(C2) bsl 8) bor
(dehex(C3) bsl 12),
[C|unescape(Cs)];
unescape([C|Cs]) -> [C|unescape(Cs)];
unescape([]) -> [].
dehex(C) when C >= $0, C =< $9 -> C - $0;
dehex(C) when C >= $a, C =< $f -> C - $a + 10;
dehex(C) when C >= $A, C =< $F -> C - $A + 10.
parse_string(StringChars) ->
unescape(StringChars).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment