Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

parser for eep

  • Loading branch information...
commit 5e1c93732051bbdc16117293ecbf8a989b7494c6 1 parent 5211af8
Chris Anderson authored
View
BIN  cjson.beam
Binary file not shown
View
586 cjson.erl
@@ -0,0 +1,586 @@
+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2006 Mochi Media, Inc.
+%% @author Chris Anderson <jchris@grabb.it>
+%% @copyright 2008 Chris Anderson.
+%%
+%% 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.
+
+%% @doc Yet another JSON (RFC 4627) library for Erlang.
+
+-module(cjson).
+-author('bob@mochimedia.com').
+-author('jchris@grabb.it').
+-export([encoder/1, encode/1]).
+-export([decoder/1, decode/1]).
+-export([test/0, profile/0]).
+
+
+% This is a macro to placate syntax highlighters..
+-define(Q, $\").
+-define(ADV_COL(S, N), S#decoder{column=N+S#decoder.column}).
+-define(INC_COL(S), S#decoder{column=1+S#decoder.column}).
+-define(INC_LINE(S), S#decoder{column=1, line=1+S#decoder.line}).
+
+-define(LOG(Name, Value),
+ io:format("{~p:~p}: ~p -> ~p~n", [?MODULE, ?LINE, Name, Value])).
+
+%% @type iolist() = [char() | binary() | iolist()]
+%% @type iodata() = iolist() | binary()
+%% @type json_string() = atom | string() | binary()
+%% @type json_number() = integer() | float()
+%% @type json_array() = {json_term()}
+%% @type json_object() = {struct, [{json_string(), json_term()}]}
+%% @type json_term() = json_string() | json_number() | json_array() |
+%% json_object()
+%% @type encoding() = utf8 | unicode
+%% @type encoder_option() = {input_encoding, encoding()} |
+%% {handler, function()}
+%% @type decoder_option() = {input_encoding, encoding()} |
+%% {object_hook, function()}
+
+-record(encoder, {input_encoding=utf8,
+ handler=null}).
+
+-record(decoder, {input_encoding=utf8,
+ object_hook=null,
+ line=1,
+ column=1,
+ state=null}).
+
+%% @spec encoder([encoder_option()]) -> function()
+%% @doc Create an encoder/1 with the given options.
+encoder(Options) ->
+ State = parse_encoder_options(Options, #encoder{}),
+ fun (O) -> json_encode(O, State) end.
+
+%% @spec encode(json_term()) -> iolist()
+%% @doc Encode the given as JSON to an iolist.
+encode(Any) ->
+ json_encode(Any, #encoder{}).
+
+%% @spec decoder([decoder_option()]) -> function()
+%% @doc Create a decoder/1 with the given options.
+decoder(Options) ->
+ State = parse_decoder_options(Options, #decoder{}),
+ fun (O) -> json_decode(O, State) end.
+
+%% @spec decode(iolist()) -> json_term()
+%% @doc Decode the given iolist to Erlang terms.
+% decode(S) ->
+% json_decode(S, #decoder{}).
+
+decode(S) ->
+ {ok, Tokens, _} = jsonl:string(S),
+ % ?LOG("Tokens",Tokens),
+ {ok, Result} = jsong:parse(Tokens),
+ % ?LOG("Result",Result),
+ Result.
+
+test() ->
+ test_all().
+
+profile() ->
+ profile_test().
+
+%% Internal API
+
+parse_encoder_options([], State) ->
+ State;
+parse_encoder_options([{input_encoding, Encoding} | Rest], State) ->
+ parse_encoder_options(Rest, State#encoder{input_encoding=Encoding});
+parse_encoder_options([{handler, Handler} | Rest], State) ->
+ parse_encoder_options(Rest, State#encoder{handler=Handler}).
+
+parse_decoder_options([], State) ->
+ State;
+parse_decoder_options([{input_encoding, Encoding} | Rest], State) ->
+ parse_decoder_options(Rest, State#decoder{input_encoding=Encoding});
+parse_decoder_options([{object_hook, Hook} | Rest], State) ->
+ parse_decoder_options(Rest, State#decoder{object_hook=Hook}).
+
+
+format_float(F) ->
+ format_float1(lists:reverse(float_to_list(F)), []).
+
+format_float1([$0, $0, _, $e | Rest], []) ->
+ strip_zeros(Rest, []);
+format_float1([Sign, $e | Rest], Acc) ->
+ strip_zeros(Rest, [$e, Sign | Acc]);
+format_float1([C | Rest], Acc) ->
+ format_float1(Rest, [C | Acc]).
+
+strip_zeros(L=[$0, $. | _], Acc) ->
+ lists:reverse(L, Acc);
+strip_zeros([$0 | Rest], Acc) ->
+ strip_zeros(Rest, Acc);
+strip_zeros(L, Acc) ->
+ lists:reverse(L, Acc).
+
+json_encode(true, _State) ->
+ "true";
+json_encode(false, _State) ->
+ "false";
+json_encode(null, _State) ->
+ "null";
+json_encode(I, _State) when is_integer(I) ->
+ integer_to_list(I);
+json_encode(F, _State) when is_float(F) ->
+ format_float(F);
+json_encode(L, State) when is_list(L); is_binary(L); is_atom(L) ->
+ json_encode_string(L, State);
+json_encode({obj, Props}, State) when is_list(Props) ->
+ json_encode_proplist(Props, State);
+json_encode(Array, State) when is_tuple(Array) ->
+ json_encode_array(Array, State);
+json_encode(Bad, #encoder{handler=null}) ->
+ exit({json_encode, {bad_term, Bad}});
+json_encode(Bad, State=#encoder{handler=Handler}) ->
+ json_encode(Handler(Bad), State).
+
+json_encode_array({}, _State) ->
+ "[]";
+json_encode_array(Tuple, State) ->
+ F = fun (O, Acc) ->
+ [$,, json_encode(O, State) | Acc]
+ end,
+ [$, | Acc1] = lists:foldl(F, "[", tuple_to_list(Tuple)),
+ lists:reverse([$\] | Acc1]).
+
+json_encode_proplist([], _State) ->
+ "{}";
+json_encode_proplist(Props, State) ->
+ F = fun ({K, V}, Acc) ->
+ KS = case K of
+ K when is_atom(K) ->
+ json_encode_string_utf8(atom_to_list(K), [?Q]);
+ K when is_integer(K) ->
+ json_encode_string(integer_to_list(K), State);
+ K when is_list(K); is_binary(K) ->
+ json_encode_string(K, State)
+ end,
+ VS = json_encode(V, State),
+ [$,, VS, $:, KS | Acc]
+ end,
+ [$, | Acc1] = lists:foldl(F, "{", Props),
+ lists:reverse([$\} | Acc1]).
+
+json_encode_string(A, _State) when is_atom(A) ->
+ json_encode_string_unicode(xmerl_ucs:from_utf8(atom_to_list(A)), [?Q]);
+json_encode_string(B, _State) when is_binary(B) ->
+ json_encode_string_unicode(xmerl_ucs:from_utf8(B), [?Q]);
+json_encode_string(S, #encoder{input_encoding=utf8}) ->
+ json_encode_string_utf8(S, [?Q]);
+json_encode_string(S, #encoder{input_encoding=unicode}) ->
+ json_encode_string_unicode(S, [?Q]).
+
+json_encode_string_utf8([], Acc) ->
+ lists:reverse([$\" | Acc]);
+json_encode_string_utf8(All=[C | Cs], Acc) ->
+ case C of
+ C when C >= 16#7f ->
+ json_encode_string_unicode(xmerl_ucs:from_utf8(All), Acc);
+ _ ->
+ Acc1 = case C of
+ ?Q ->
+ [?Q, $\\ | Acc];
+ $/ ->
+ [$/, $\\ | Acc];
+ $\\ ->
+ [$\\, $\\ | Acc];
+ $\b ->
+ [$b, $\\ | Acc];
+ $\f ->
+ [$f, $\\ | Acc];
+ $\n ->
+ [$n, $\\ | Acc];
+ $\r ->
+ [$r, $\\ | Acc];
+ $\t ->
+ [$t, $\\ | Acc];
+ C when C >= 0, C < $\s ->
+ [unihex(C) | Acc];
+ C when C >= $\s ->
+ [C | Acc];
+ _ ->
+ exit({json_encode, {bad_char, C}})
+ end,
+ json_encode_string_utf8(Cs, Acc1)
+ end.
+
+json_encode_string_unicode([], Acc) ->
+ lists:reverse([$\" | Acc]);
+json_encode_string_unicode([C | Cs], Acc) ->
+ Acc1 = case C of
+ ?Q ->
+ [?Q, $\\ | Acc];
+ $/ ->
+ [$/, $\\ | Acc];
+ $\\ ->
+ [$\\, $\\ | Acc];
+ $\b ->
+ [$b, $\\ | Acc];
+ $\f ->
+ [$f, $\\ | Acc];
+ $\n ->
+ [$n, $\\ | Acc];
+ $\r ->
+ [$r, $\\ | Acc];
+ $\t ->
+ [$t, $\\ | Acc];
+ C when C >= 0, C < $\s; C >= 16#7f, C =< 16#10FFFF ->
+ [unihex(C) | Acc];
+ C when C < 16#7f ->
+ [C | Acc];
+ _ ->
+ exit({json_encode, {bad_char, C}})
+ end,
+ json_encode_string_unicode(Cs, Acc1).
+
+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.
+
+hexdigit(C) when C >= 0, C =< 9 ->
+ C + $0;
+hexdigit(C) when C =< 15 ->
+ C + $a - 10.
+
+unihex(C) when C < 16#10000 ->
+ <<D3:4, D2:4, D1:4, D0:4>> = <<C:16>>,
+ Digits = [hexdigit(D) || D <- [D3, D2, D1, D0]],
+ [$\\, $u | Digits];
+unihex(C) when C =< 16#10FFFF ->
+ N = C - 16#10000,
+ S1 = 16#d800 bor ((N bsr 10) band 16#3ff),
+ S2 = 16#dc00 bor (N band 16#3ff),
+ [unihex(S1), unihex(S2)].
+
+json_decode(B, S) when is_binary(B) ->
+ json_decode([B], S);
+json_decode(L, S) ->
+ {Res, L1, S1} = decode1(L, S),
+ {eof, [], _} = tokenize(L1, S1#decoder{state=trim}),
+ Res.
+
+decode1(L, S=#decoder{state=null}) ->
+ case tokenize(L, S#decoder{state=any}) of
+ {{const, C}, L1, S1} ->
+ {C, L1, S1};
+ {start_array, L1, S1} ->
+ decode_array(L1, S1#decoder{state=any}, []);
+ {start_object, L1, S1} ->
+ decode_object(L1, S1#decoder{state=key}, [])
+ end.
+
+make_object(V, #decoder{object_hook=null}) ->
+ V;
+make_object(V, #decoder{object_hook=Hook}) ->
+ Hook(V).
+
+decode_object(L, S=#decoder{state=key}, Acc) ->
+ case tokenize(L, S) of
+ {end_object, Rest, S1} ->
+ V = make_object({obj, lists:reverse(Acc)}, S1),
+ {V, Rest, S1#decoder{state=null}};
+ {{const, K}, Rest, S1} when is_list(K) ->
+ {colon, L2, S2} = tokenize(Rest, S1),
+ {V, L3, S3} = decode1(L2, S2#decoder{state=null}),
+ decode_object(L3, S3#decoder{state=comma}, [{K, V} | Acc])
+ end;
+decode_object(L, S=#decoder{state=comma}, Acc) ->
+ case tokenize(L, S) of
+ {end_object, Rest, S1} ->
+ V = make_object({obj, lists:reverse(Acc)}, S1),
+ {V, Rest, S1#decoder{state=null}};
+ {comma, Rest, S1} ->
+ decode_object(Rest, S1#decoder{state=key}, Acc)
+ end.
+
+decode_array(L, S=#decoder{state=any}, Acc) ->
+ case tokenize(L, S) of
+ {end_array, Rest, S1} ->
+ {list_to_tuple(lists:reverse(Acc)), Rest, S1#decoder{state=null}};
+ {start_array, Rest, S1} ->
+ {Array, Rest1, S2} = decode_array(Rest, S1#decoder{state=any}, []),
+ decode_array(Rest1, S2#decoder{state=comma}, [Array | Acc]);
+ {start_object, Rest, S1} ->
+ {Array, Rest1, S2} = decode_object(Rest, S1#decoder{state=key}, []),
+ decode_array(Rest1, S2#decoder{state=comma}, [Array | Acc]);
+ {{const, Const}, Rest, S1} ->
+ decode_array(Rest, S1#decoder{state=comma}, [Const | Acc])
+ end;
+decode_array(L, S=#decoder{state=comma}, Acc) ->
+ case tokenize(L, S) of
+ {end_array, Rest, S1} ->
+ {list_to_tuple(lists:reverse(Acc)), Rest, S1#decoder{state=null}};
+ {comma, Rest, S1} ->
+ decode_array(Rest, S1#decoder{state=any}, Acc)
+ end.
+
+tokenize_string(IoList=[C | _], S=#decoder{input_encoding=utf8}, Acc)
+ when is_list(C); is_binary(C); C >= 16#7f ->
+ List = xmerl_ucs:from_utf8(list_to_binary(lists:flatten(IoList))),
+ tokenize_string(List, S#decoder{input_encoding=unicode}, Acc);
+tokenize_string("\"" ++ Rest, S, Acc) ->
+ {lists:reverse(Acc), Rest, ?INC_COL(S)};
+tokenize_string("\\\"" ++ Rest, S, Acc) ->
+ tokenize_string(Rest, ?ADV_COL(S, 2), [$\" | Acc]);
+tokenize_string("\\\\" ++ Rest, S, Acc) ->
+ tokenize_string(Rest, ?ADV_COL(S, 2), [$\\ | Acc]);
+tokenize_string("\\/" ++ Rest, S, Acc) ->
+ tokenize_string(Rest, ?ADV_COL(S, 2), [$/ | Acc]);
+tokenize_string("\\b" ++ Rest, S, Acc) ->
+ tokenize_string(Rest, ?ADV_COL(S, 2), [$\b | Acc]);
+tokenize_string("\\f" ++ Rest, S, Acc) ->
+ tokenize_string(Rest, ?ADV_COL(S, 2), [$\\ | Acc]);
+tokenize_string("\\n" ++ Rest, S, Acc) ->
+ tokenize_string(Rest, ?ADV_COL(S, 2), [$\n | Acc]);
+tokenize_string("\\r" ++ Rest, S, Acc) ->
+ tokenize_string(Rest, ?ADV_COL(S, 2), [$\r | Acc]);
+tokenize_string("\\t" ++ Rest, S, Acc) ->
+ tokenize_string(Rest, ?ADV_COL(S, 2), [$\t | Acc]);
+tokenize_string([$\\, $u, C3, C2, C1, C0 | Rest], S, Acc) ->
+ % coalesce UTF-16 surrogate pair?
+ C = dehex(C0) bor
+ (dehex(C1) bsl 4) bor
+ (dehex(C2) bsl 8) bor
+ (dehex(C3) bsl 12),
+ tokenize_string(Rest, ?ADV_COL(S, 6), [C | Acc]);
+tokenize_string([C | Rest], S, Acc) when C >= $\s; C < 16#10FFFF ->
+ tokenize_string(Rest, ?ADV_COL(S, 1), [C | Acc]).
+
+tokenize_number(IoList=[C | _], Mode, S=#decoder{input_encoding=utf8}, Acc)
+ when is_list(C); is_binary(C); C >= 16#7f ->
+ List = xmerl_ucs:from_utf8(list_to_binary(lists:flatten(IoList))),
+ tokenize_number(List, Mode, S#decoder{input_encoding=unicode}, Acc);
+tokenize_number([$- | Rest], sign, S, []) ->
+ tokenize_number(Rest, int, ?INC_COL(S), [$-]);
+tokenize_number(Rest, sign, S, []) ->
+ tokenize_number(Rest, int, S, []);
+tokenize_number([$0 | Rest], int, S, Acc) ->
+ tokenize_number(Rest, frac, ?INC_COL(S), [$0 | Acc]);
+tokenize_number([C | Rest], int, S, Acc) when C >= $1, C =< $9 ->
+ tokenize_number(Rest, int1, ?INC_COL(S), [C | Acc]);
+tokenize_number([C | Rest], int1, S, Acc) when C >= $0, C =< $9 ->
+ tokenize_number(Rest, int1, ?INC_COL(S), [C | Acc]);
+tokenize_number(Rest, int1, S, Acc) ->
+ tokenize_number(Rest, frac, S, Acc);
+tokenize_number([$., C | Rest], frac, S, Acc) when C >= $0, C =< $9 ->
+ tokenize_number(Rest, frac1, ?ADV_COL(S, 2), [C, $. | Acc]);
+tokenize_number([E | Rest], frac, S, Acc) when E == $e; E == $E ->
+ tokenize_number(Rest, esign, ?INC_COL(S), [$e, $0, $. | Acc]);
+tokenize_number(Rest, frac, S, Acc) ->
+ {{int, lists:reverse(Acc)}, Rest, S};
+tokenize_number([C | Rest], frac1, S, Acc) when C >= $0, C =< $9 ->
+ tokenize_number(Rest, frac1, ?INC_COL(S), [C | Acc]);
+tokenize_number([E | Rest], frac1, S, Acc) when E == $e; E == $E ->
+ tokenize_number(Rest, esign, ?INC_COL(S), [$e | Acc]);
+tokenize_number(Rest, frac1, S, Acc) ->
+ {{float, lists:reverse(Acc)}, Rest, S};
+tokenize_number([C | Rest], esign, S, Acc) when C == $-; C == $+ ->
+ tokenize_number(Rest, eint, ?INC_COL(S), [C | Acc]);
+tokenize_number(Rest, esign, S, Acc) ->
+ tokenize_number(Rest, eint, S, Acc);
+tokenize_number([C | Rest], eint, S, Acc) when C >= $0, C =< $9 ->
+ tokenize_number(Rest, eint1, ?INC_COL(S), [C | Acc]);
+tokenize_number([C | Rest], eint1, S, Acc) when C >= $0, C =< $9 ->
+ tokenize_number(Rest, eint1, ?INC_COL(S), [C | Acc]);
+tokenize_number(Rest, eint1, S, Acc) ->
+ {{float, lists:reverse(Acc)}, Rest, S}.
+
+tokenize([], S=#decoder{state=trim}) ->
+ {eof, [], S};
+tokenize([L | Rest], S) when is_list(L) ->
+ tokenize(L ++ Rest, S);
+tokenize([B | Rest], S) when is_binary(B) ->
+ tokenize(xmerl_ucs:from_utf8(B) ++ Rest, S#decoder{input_encoding=unicode});
+tokenize("\r\n" ++ Rest, S) ->
+ tokenize(Rest, ?INC_LINE(S));
+tokenize("\n" ++ Rest, S) ->
+ tokenize(Rest, ?INC_LINE(S));
+tokenize([C | Rest], S) when C == $\s; C == $\t ->
+ tokenize(Rest, ?INC_COL(S));
+tokenize("{" ++ Rest, S) ->
+ {start_object, Rest, ?INC_COL(S)};
+tokenize("}" ++ Rest, S) ->
+ {end_object, Rest, ?INC_COL(S)};
+tokenize("[" ++ Rest, S) ->
+ {start_array, Rest, ?INC_COL(S)};
+tokenize("]" ++ Rest, S) ->
+ {end_array, Rest, ?INC_COL(S)};
+tokenize("," ++ Rest, S) ->
+ {comma, Rest, ?INC_COL(S)};
+tokenize(":" ++ Rest, S) ->
+ {colon, Rest, ?INC_COL(S)};
+tokenize("null" ++ Rest, S) ->
+ {{const, null}, Rest, ?ADV_COL(S, 4)};
+tokenize("true" ++ Rest, S) ->
+ {{const, true}, Rest, ?ADV_COL(S, 4)};
+tokenize("false" ++ Rest, S) ->
+ {{const, false}, Rest, ?ADV_COL(S, 5)};
+tokenize("\"" ++ Rest, S) ->
+ {String, Rest1, S1} = tokenize_string(Rest, ?INC_COL(S), []),
+ {{const, xmerl_ucs:to_utf8(String)}, Rest1, S1};
+tokenize(L=[C | _], S) when C >= $0, C =< $9; C == $- ->
+ case tokenize_number(L, sign, S, []) of
+ {{int, Int}, Rest, S1} ->
+ {{const, list_to_integer(Int)}, Rest, S1};
+ {{float, Float}, Rest, S1} ->
+ {{const, list_to_float(Float)}, Rest, S1}
+ end.
+
+%% testing constructs borrowed from the Yaws JSON implementation.
+
+%% Create an object from a list of Key/Value pairs.
+
+obj_new() ->
+ {obj, []}.
+
+is_obj({obj, Props}) ->
+ F = fun ({K, _}) when is_list(K) ->
+ true;
+ (_) ->
+ false
+ end,
+ lists:all(F, Props).
+
+obj_from_list(Props) ->
+ Obj = {obj, Props},
+ case is_obj(Obj) of
+ true -> Obj;
+ false -> exit(json_bad_object)
+ end.
+
+%% Test for equivalence of Erlang terms.
+%% Due to arbitrary order of construction, equivalent objects might
+%% compare unequal as erlang terms, so we need to carefully recurse
+%% through aggregates (tuples and objects).
+
+equiv({obj, Props1}, {obj, Props2}) ->
+ equiv_object(Props1, Props2);
+equiv(T1, T2) when is_tuple(T1), is_tuple(T2) ->
+ equiv_list(tuple_to_list(T1), tuple_to_list(T2));
+equiv(N1, N2) when is_number(N1), is_number(N2) -> N1 == N2;
+equiv(S1, S2) when is_list(S1), is_list(S2) -> S1 == S2;
+equiv(true, true) -> true;
+equiv(false, false) -> true;
+equiv(null, null) -> true.
+
+%% Object representation and traversal order is unknown.
+%% Use the sledgehammer and sort property lists.
+
+equiv_object(Props1, Props2) ->
+ L1 = lists:keysort(1, Props1),
+ L2 = lists:keysort(1, Props2),
+ Pairs = lists:zip(L1, L2),
+ true = lists:all(fun({{K1, V1}, {K2, V2}}) ->
+ equiv(K1, K2) and equiv(V1, V2)
+ end, Pairs).
+
+%% Recursively compare tuple elements for equivalence.
+
+equiv_list([], []) ->
+ true;
+equiv_list([V1 | L1], [V2 | L2]) ->
+ case equiv(V1, V2) of
+ true ->
+ equiv_list(L1, L2);
+ false ->
+ false
+ end.
+
+profile_test() ->
+ fprof:trace(start, "fprof.trace"),
+ profile_one(e2j_test_vec(utf8), 1),
+ fprof:trace(stop),
+ fprof:profile(),
+ fprof:analyse().
+
+profile_one([], _) -> ok;
+profile_one([{_, J} | Rest], N) ->
+ decode(J),
+ profile_one(Rest, 1+N).
+
+test_all() ->
+ test_one(e2j_test_vec(utf8), 1).
+
+test_one([], N) ->
+ io:format("~p tests passed~n", [N-1]),
+ ok;
+test_one([{E, J} | Rest], N) ->
+ io:format("[~p] ~p ~p~n", [N, E, J]),
+ true = equiv(E, decode(J)),
+ % ?LOG("encoded", encode(E)),
+ % true = equiv(E, decode(encode(E))),
+ % true = equiv(E, decode(encode(E))),
+ test_one(Rest, 1+N).
+
+e2j_test_vec(unicode) ->
+ [
+ {"foo" ++ [500] ++ "bar", [$", $f, $o, $o, 500, $b, $a, $r, $"]}
+ ];
+e2j_test_vec(utf8) ->
+ [
+ {1, "1"},
+ {3.1416, "3.14160"}, % text representation may truncate, trail zeroes
+ {-1, "-1"},
+ {-3.1416, "-3.14160"},
+ {12.0e10, "1.20000e+11"},
+ {1.234E+10, "1.23400e+10"},
+ {-1.234E-10, "-1.23400e-10"},
+ {10.0, "1.0e+01"},
+ {123.456, "1.23456E+2"},
+ {10.0, "1e1"},
+ {"foo", "\"foo\""},
+ {"", "\"\""},
+ {[], "\"\""},
+ % {"1/4", "\"1\/4\""},
+ {"name is \"Quentin\"", "\"name is \\\"Quentin\\\"\""},
+ {"\n\n\n", "\"\\n\\n\\n\""},
+ {"foo" ++ [5] ++ "bar", "\"foo\\u0005bar\""},
+ {obj_new(), "{}"},
+ {obj_from_list([{"foo", "bar"}]), "{\"foo\":\"bar\"}"},
+ {obj_from_list([{"foo", "bar"}, {"baz", 123}]),
+ "{\"foo\":\"bar\",\"baz\":123}"},
+ {{}, "[]"},
+ {{{}}, "[[]]"},
+ {{1, "foo"}, "[1,\"foo\"]"},
+
+ % json array in a json object
+ {obj_from_list([{"foo", {123}}]),
+ "{\"foo\":[123]}"},
+
+ % json object in a json object
+ {obj_from_list([{"foo", obj_from_list([{"bar", true}])}]),
+ "{\"foo\":{\"bar\":true}}"},
+
+ % fold evaluation order
+ {obj_from_list([{"foo", {}},
+ {"bar", obj_from_list([{"baz", true}])},
+ {"alice", "bob"}]),
+ "{\"foo\":[],\"bar\":{\"baz\":true},\"alice\":\"bob\"}"},
+
+ % json object in a json array
+ {{-123, "foo", obj_from_list([{"bar", {}}]), null},
+ "[-123,\"foo\",{\"bar\":[]},null]"}
+ ].
View
BIN  fprof.trace
Binary file not shown
View
BIN  json_eep.beam
Binary file not shown
View
134 json_eep.erl
@@ -0,0 +1,134 @@
+%% @author Chris Anderson <jchris@grabb.it>
+%% @copyright 2008 Chris Anderson.
+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2006 Mochi Media, Inc.
+%%
+%% 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.
+
+%% @doc Parser to illustrate EEP
+%% tests based on mochijson
+
+
+-module(json_eep).
+-author('bob@mochimedia.com').
+-author('jchris@grabb.it').
+-export([json_to_term/1]).
+-export([test/0]).
+
+json_to_term(S) ->
+ {ok, Tokens, _} = json_lex2:string(S),
+ % ?LOG("Tokens",Tokens),
+ {ok, Result} = json_grammar:parse(Tokens),
+ % ?LOG("Result",Result),
+ Result.
+
+%% Test for equivalence of Erlang terms.
+%% Due to arbitrary order of construction, equivalent objects might
+%% compare unequal as erlang terms, so we need to carefully recurse
+%% through aggregates (tuples and objects).
+
+equiv(T1, T2) when is_list(T1), is_list(T2) ->
+ equiv_list(T1, T2);
+equiv({T1}, {T2}) when is_list(T1), is_list(T2) ->
+ equiv_object(T1, T2);
+equiv(N1, N2) when is_number(N1), is_number(N2) -> N1 == N2;
+equiv(S1, S2) when is_binary(S1), is_binary(S2) -> S1 == S2;
+equiv(true, true) -> true;
+equiv(false, false) -> true;
+equiv(null, null) -> true.
+
+%% Object representation and traversal order is unknown.
+%% Use the sledgehammer and sort property lists.
+
+equiv_object(Props1, Props2) ->
+ L1 = lists:keysort(1, Props1),
+ L2 = lists:keysort(1, Props2),
+ Pairs = lists:zip(L1, L2),
+ true = lists:all(fun({{K1, V1}, {K2, V2}}) ->
+ equiv(K1, K2) and equiv(V1, V2)
+ end, Pairs).
+
+%% Recursively compare tuple elements for equivalence.
+
+equiv_list([], []) ->
+ true;
+equiv_list([V1 | L1], [V2 | L2]) ->
+ case equiv(V1, V2) of
+ true ->
+ equiv_list(L1, L2);
+ false ->
+ false
+ end.
+
+test() ->
+ test_next(tests(binary)).
+
+test_next([]) -> {ok, passed};
+
+test_next([{E,J}|Rest]) ->
+ io:format("~p ~p~n", [E, J]),
+ Decoded = json_to_term(J),
+ io:format("~p ~p~n", [E, Decoded]),
+ true = equiv(E, Decoded),
+ test_next(Rest).
+
+tests(binary) ->
+ [
+ {{[{<<"key">>,<<"value">>}]}, "{\"key\":\"value\"}"},
+ {{[]},"{}"},
+ {[], "[]"},
+ {[1], "[1]"},
+ {[3.1416], "[3.14160]"}, % text representation may truncate, trail zeroes
+ {[-1], "[-1]"},
+ {[-3.1416], "[-3.14160]"},
+ {{[{<<"number">>, 12.0e10}]}, "{\"number\":1.20000e+11}"},
+ {[1.234E+10], "[1.23400e+10]"},
+ {[-1.234E-10], "[-1.23400e-10]"},
+ {[10.0], "[1.0e+01]"},
+ {[123.456], "[1.23456E+2]"},
+ {[10.0], "[1e1]"},
+ {[<<"foo">>], "[\"foo\"]"},
+ {[<<>>], "[\"\"]"},
+ {[<<"1/4">>], "[\"1\/4\"]"},
+ {[<<"name is \"Quentin\"">>], "[\"name is \\\"Quentin\\\"\"]"},
+ {[<<"\n\n\n">>], "[\"\\n\\n\\n\"]"},
+ {[iolist_to_binary("foo" ++ [5] ++ "bar")], "[\"foo\\u0005bar\"]"},
+ {{[{<<"foo">>, <<"bar">>}]}, "{\"foo\":\"bar\"}"},
+ {{[{<<"foo">>, <<"bar">>}, {<<"baz">>, 123}]}, "{\"foo\":\"bar\",\"baz\":123}"},
+ {[[]], "[[]]"},
+ {[1, <<"foo">>], "[1,\"foo\"]"},
+
+ % json array in a json object
+ {{[{<<"foo">>, [123]}]}, "{\"foo\":[123]}"},
+
+ % json object in a json object
+ {{[{<<"foo">>, {[{<<"bar">>, true}]}}]},
+ "{\"foo\":{\"bar\":true}}"},
+
+ % fold evaluation order
+ {{[{<<"foo">>, []},
+ {<<"bar">>, {[{<<"baz">>, true}]}},
+ {<<"alice">>, <<"bob">>}]},
+ "{\"foo\":[],\"bar\":{\"baz\":true},\"alice\":\"bob\"}"},
+
+ % json object in a json array
+ {[-123, <<"foo">>, {[{<<"bar">>, []}]}, null],
+ "[-123,\"foo\",{\"bar\":[]},null]"}
+ ].
View
BIN  json_grammar.beam
Binary file not shown
View
329 jsong.erl → json_grammar.erl
@@ -1,4 +1,4 @@
--module(jsong).
+-module(json_grammar).
-export([parse/1, parse_and_scan/1, format_error/1]).
-file("/opt/local/lib/erlang/lib/parsetools-1.4.4/include/yeccpre.hrl", 0).
@@ -152,7 +152,7 @@ yecctoken2string(Other) ->
--file("jsong.erl", 155).
+-file("json_grammar.erl", 155).
yeccpars2(0=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr);
@@ -174,14 +174,14 @@ yeccpars2(8=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_8(S, Cat, Ss, Stack, T, Ts, Tzr);
yeccpars2(9=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(10=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(10=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr);
%% yeccpars2(11=S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_11(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(12=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(13=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_13(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(12=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(13=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_13(S, Cat, Ss, Stack, T, Ts, Tzr);
yeccpars2(14=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_14(S, Cat, Ss, Stack, T, Ts, Tzr);
yeccpars2(15=S, Cat, Ss, Stack, T, Ts, Tzr) ->
@@ -189,21 +189,29 @@ yeccpars2(15=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2(16=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_16(S, Cat, Ss, Stack, T, Ts, Tzr);
yeccpars2(17=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_5(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(18=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_18(S, Cat, Ss, Stack, T, Ts, Tzr);
+ yeccpars2_17(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(18=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_18(S, Cat, Ss, Stack, T, Ts, Tzr);
yeccpars2(19=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_19(S, Cat, Ss, Stack, T, Ts, Tzr);
-%% yeccpars2(20=S, Cat, Ss, Stack, T, Ts, Tzr) ->
-%% yeccpars2_20(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(20=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_20(S, Cat, Ss, Stack, T, Ts, Tzr);
%% yeccpars2(21=S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_21(S, Cat, Ss, Stack, T, Ts, Tzr);
yeccpars2(22=S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_22(S, Cat, Ss, Stack, T, Ts, Tzr);
%% yeccpars2(23=S, Cat, Ss, Stack, T, Ts, Tzr) ->
%% yeccpars2_23(S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccpars2(24=S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(24=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(25=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_25(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(26=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(27=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_27(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(28=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_28(S, Cat, Ss, Stack, T, Ts, Tzr);
yeccpars2(Other, _, _, _, _, _, _) ->
erlang:error({yecc_bug,"1.3",{missing_state_in_action_table, Other}}).
@@ -213,74 +221,75 @@ yeccpars2_0(S, '{', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 5, Ss, Stack, T, Ts, Tzr).
yeccpars2_1(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_arrobj(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
+ yeccgoto_arrayobj(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_2(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) ->
{ok, hd(Stack)}.
yeccpars2_3(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_arrobj(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
+ yeccgoto_arrayobj(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_4(S, '[', Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 4, Ss, Stack, T, Ts, Tzr);
-yeccpars2_4(S, false, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 12, Ss, Stack, T, Ts, Tzr);
-yeccpars2_4(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
-yeccpars2_4(S, null, Ss, Stack, T, Ts, Tzr) ->
+yeccpars2_4(S, ']', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 25, Ss, Stack, T, Ts, Tzr);
+yeccpars2_4(S, '{', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 5, Ss, Stack, T, Ts, Tzr);
+yeccpars2_4(S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_cont_4(S, Cat, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_cont_4(S, false, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 14, Ss, Stack, T, Ts, Tzr);
-yeccpars2_4(S, string, Ss, Stack, T, Ts, Tzr) ->
+yeccpars2_cont_4(S, float, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 15, Ss, Stack, T, Ts, Tzr);
-yeccpars2_4(S, true, Ss, Stack, T, Ts, Tzr) ->
+yeccpars2_cont_4(S, integer, Ss, Stack, T, Ts, Tzr) ->
yeccpars1(S, 16, Ss, Stack, T, Ts, Tzr);
-yeccpars2_4(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 5, Ss, Stack, T, Ts, Tzr);
-yeccpars2_4(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_4_(Stack),
- yeccpars2_20(20, Cat, [4 | Ss], NewStack, T, Ts, Tzr).
+yeccpars2_cont_4(S, null, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 17, Ss, Stack, T, Ts, Tzr);
+yeccpars2_cont_4(S, string, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 18, Ss, Stack, T, Ts, Tzr);
+yeccpars2_cont_4(S, true, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 19, Ss, Stack, T, Ts, Tzr).
yeccpars2_5(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 8, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 8, Ss, Stack, T, Ts, Tzr);
+yeccpars2_5(S, '}', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 9, Ss, Stack, T, Ts, Tzr).
yeccpars2_6(S, '}', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 19, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 22, Ss, Stack, T, Ts, Tzr).
yeccpars2_7(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 17, Ss, Stack, T, Ts, Tzr);
+ yeccpars1(S, 20, Ss, Stack, T, Ts, Tzr);
yeccpars2_7(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccgoto_members(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
+ NewStack = yeccpars2_7_(Stack),
+ yeccgoto_members(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_8(S, ':', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 9, Ss, Stack, T, Ts, Tzr).
+ yeccpars1(S, 10, Ss, Stack, T, Ts, Tzr).
-yeccpars2_9(S, false, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 12, Ss, Stack, T, Ts, Tzr);
-yeccpars2_9(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
-yeccpars2_9(S, null, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 14, Ss, Stack, T, Ts, Tzr);
-yeccpars2_9(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 15, Ss, Stack, T, Ts, Tzr);
-yeccpars2_9(S, true, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 16, Ss, Stack, T, Ts, Tzr);
-yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr).
+yeccpars2_9(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_|Nss] = Ss,
+ NewStack = yeccpars2_9_(Stack),
+ yeccgoto_object(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-yeccpars2_10(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
- NewStack = yeccpars2_10_(Stack),
- yeccgoto_member(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+yeccpars2_10(S, '[', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 4, Ss, Stack, T, Ts, Tzr);
+yeccpars2_10(S, '{', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 5, Ss, Stack, T, Ts, Tzr);
+yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_cont_4(S, Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_11(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccgoto_element(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_12(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_,_|Nss] = Ss,
NewStack = yeccpars2_12_(Stack),
- yeccgoto_element(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+ yeccgoto_member(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- NewStack = yeccpars2_13_(Stack),
- yeccgoto_element(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+ yeccgoto_element(hd(Ss), Cat, Ss, Stack, T, Ts, Tzr).
yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
NewStack = yeccpars2_14_(Stack),
@@ -294,137 +303,126 @@ yeccpars2_16(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
NewStack = yeccpars2_16_(Stack),
yeccgoto_element(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-%% yeccpars2_17: see yeccpars2_5
+yeccpars2_17(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ NewStack = yeccpars2_17_(Stack),
+ yeccgoto_element(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
NewStack = yeccpars2_18_(Stack),
- yeccgoto_members(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+ yeccgoto_element(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- [_,_|Nss] = Ss,
NewStack = yeccpars2_19_(Stack),
- yeccgoto_object(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+ yeccgoto_element(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
-yeccpars2_20(S, ']', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 24, Ss, Stack, T, Ts, Tzr).
+yeccpars2_20(S, string, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 8, Ss, Stack, T, Ts, Tzr).
-yeccpars2_21(S, ',', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 22, Ss, Stack, T, Ts, Tzr);
yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_,_|Nss] = Ss,
NewStack = yeccpars2_21_(Stack),
- yeccgoto_elements(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+ yeccgoto_members(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-yeccpars2_22(S, '[', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 4, Ss, Stack, T, Ts, Tzr);
-yeccpars2_22(S, false, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 12, Ss, Stack, T, Ts, Tzr);
-yeccpars2_22(S, integer, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr);
-yeccpars2_22(S, null, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 14, Ss, Stack, T, Ts, Tzr);
-yeccpars2_22(S, string, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 15, Ss, Stack, T, Ts, Tzr);
-yeccpars2_22(S, true, Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 16, Ss, Stack, T, Ts, Tzr);
-yeccpars2_22(S, '{', Ss, Stack, T, Ts, Tzr) ->
- yeccpars1(S, 5, Ss, Stack, T, Ts, Tzr);
yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_,_|Nss] = Ss,
NewStack = yeccpars2_22_(Stack),
- yeccpars2_23(_S, Cat, [22 | Ss], NewStack, T, Ts, Tzr).
+ yeccgoto_object(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+yeccpars2_23(S, ']', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 28, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_24(S, ',', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 26, Ss, Stack, T, Ts, Tzr);
+yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ NewStack = yeccpars2_24_(Stack),
+ yeccgoto_elements(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+
+yeccpars2_25(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_|Nss] = Ss,
+ NewStack = yeccpars2_25_(Stack),
+ yeccgoto_array(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+
+%% yeccpars2_26: see yeccpars2_10
+
+yeccpars2_27(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
- NewStack = yeccpars2_23_(Stack),
+ NewStack = yeccpars2_27_(Stack),
yeccgoto_elements(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
-yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
[_,_|Nss] = Ss,
- NewStack = yeccpars2_24_(Stack),
+ NewStack = yeccpars2_28_(Stack),
yeccgoto_array(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
yeccgoto_array(0=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_3(_S, Cat, Ss, Stack, T, Ts, Tzr);
yeccgoto_array(4=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_3(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_array(9=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_3(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_array(22=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_3(_S, Cat, Ss, Stack, T, Ts, Tzr).
+ yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_array(10=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_array(26=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr).
-yeccgoto_arrobj(0, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_2(2, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_arrobj(4=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_11(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_arrobj(9=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_11(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_arrobj(22=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_11(_S, Cat, Ss, Stack, T, Ts, Tzr).
+yeccgoto_arrayobj(0, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_2(2, Cat, Ss, Stack, T, Ts, Tzr).
yeccgoto_element(4, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(21, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_element(9=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_10(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_element(22, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_21(21, Cat, Ss, Stack, T, Ts, Tzr).
+ yeccpars2_24(24, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_element(10=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_12(_S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_element(26, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_24(24, Cat, Ss, Stack, T, Ts, Tzr).
yeccgoto_elements(4, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_20(20, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_elements(22=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr).
+ yeccpars2_23(23, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_elements(26=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_27(_S, Cat, Ss, Stack, T, Ts, Tzr).
yeccgoto_member(5, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_7(7, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_member(17, Cat, Ss, Stack, T, Ts, Tzr) ->
+yeccgoto_member(20, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_7(7, Cat, Ss, Stack, T, Ts, Tzr).
yeccgoto_members(5, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_6(6, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_members(17=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr).
+yeccgoto_members(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr).
yeccgoto_object(0=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
yeccpars2_1(_S, Cat, Ss, Stack, T, Ts, Tzr);
yeccgoto_object(4=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_1(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_object(9=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_1(_S, Cat, Ss, Stack, T, Ts, Tzr);
-yeccgoto_object(22=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
- yeccpars2_1(_S, Cat, Ss, Stack, T, Ts, Tzr).
+ yeccpars2_11(_S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_object(10=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_11(_S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_object(26=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_11(_S, Cat, Ss, Stack, T, Ts, Tzr).
--compile({inline,{yeccpars2_4_,1}}).
--file("jsong.yrl", 18).
-yeccpars2_4_(__Stack0) ->
+-compile({inline,{yeccpars2_7_,1}}).
+-file("json_grammar.yrl", 10).
+yeccpars2_7_(__Stack0) ->
+ [__1 | __Stack] = __Stack0,
[begin
- nil
- end | __Stack0].
+ [ __1 ]
+ end | __Stack].
--compile({inline,{yeccpars2_10_,1}}).
--file("jsong.yrl", 12).
-yeccpars2_10_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
+-compile({inline,{yeccpars2_9_,1}}).
+-file("json_grammar.yrl", 7).
+yeccpars2_9_(__Stack0) ->
+ [__2,__1 | __Stack] = __Stack0,
[begin
- { element ( 3 , __1 ) , __3 }
+ { [ ] }
end | __Stack].
-compile({inline,{yeccpars2_12_,1}}).
--file("jsong.yrl", 24).
+-file("json_grammar.yrl", 12).
yeccpars2_12_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
- [begin
- element ( 1 , __1 )
- end | __Stack].
-
--compile({inline,{yeccpars2_13_,1}}).
--file("jsong.yrl", 22).
-yeccpars2_13_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
+ [__3,__2,__1 | __Stack] = __Stack0,
[begin
- element ( 3 , __1 )
+ { list_to_binary ( element ( 3 , __1 ) ) , __3 }
end | __Stack].
-compile({inline,{yeccpars2_14_,1}}).
--file("jsong.yrl", 25).
+-file("json_grammar.yrl", 26).
yeccpars2_14_(__Stack0) ->
[__1 | __Stack] = __Stack0,
[begin
@@ -432,7 +430,7 @@ yeccpars2_14_(__Stack0) ->
end | __Stack].
-compile({inline,{yeccpars2_15_,1}}).
--file("jsong.yrl", 20).
+-file("json_grammar.yrl", 24).
yeccpars2_15_(__Stack0) ->
[__1 | __Stack] = __Stack0,
[begin
@@ -440,55 +438,80 @@ yeccpars2_15_(__Stack0) ->
end | __Stack].
-compile({inline,{yeccpars2_16_,1}}).
--file("jsong.yrl", 23).
+-file("json_grammar.yrl", 23).
yeccpars2_16_(__Stack0) ->
[__1 | __Stack] = __Stack0,
[begin
+ element ( 3 , __1 )
+ end | __Stack].
+
+-compile({inline,{yeccpars2_17_,1}}).
+-file("json_grammar.yrl", 27).
+yeccpars2_17_(__Stack0) ->
+ [__1 | __Stack] = __Stack0,
+ [begin
element ( 1 , __1 )
end | __Stack].
-compile({inline,{yeccpars2_18_,1}}).
--file("jsong.yrl", 9).
+-file("json_grammar.yrl", 20).
yeccpars2_18_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
+ [__1 | __Stack] = __Stack0,
[begin
- [ __1 | __3 ]
+ list_to_binary ( element ( 3 , __1 ) )
end | __Stack].
-compile({inline,{yeccpars2_19_,1}}).
--file("jsong.yrl", 6).
+-file("json_grammar.yrl", 25).
yeccpars2_19_(__Stack0) ->
- [__3,__2,__1 | __Stack] = __Stack0,
+ [__1 | __Stack] = __Stack0,
[begin
- { obj , __2 }
+ element ( 1 , __1 )
end | __Stack].
-compile({inline,{yeccpars2_21_,1}}).
--file("jsong.yrl", 17).
+-file("json_grammar.yrl", 9).
yeccpars2_21_(__Stack0) ->
- [__1 | __Stack] = __Stack0,
+ [__3,__2,__1 | __Stack] = __Stack0,
[begin
- [ __1 ]
+ [ __1 | __3 ]
end | __Stack].
-compile({inline,{yeccpars2_22_,1}}).
--file("jsong.yrl", 18).
+-file("json_grammar.yrl", 6).
yeccpars2_22_(__Stack0) ->
+ [__3,__2,__1 | __Stack] = __Stack0,
[begin
- nil
- end | __Stack0].
+ { __2 }
+ end | __Stack].
--compile({inline,{yeccpars2_23_,1}}).
--file("jsong.yrl", 16).
-yeccpars2_23_(__Stack0) ->
+-compile({inline,{yeccpars2_24_,1}}).
+-file("json_grammar.yrl", 18).
+yeccpars2_24_(__Stack0) ->
+ [__1 | __Stack] = __Stack0,
+ [begin
+ [ __1 ]
+ end | __Stack].
+
+-compile({inline,{yeccpars2_25_,1}}).
+-file("json_grammar.yrl", 15).
+yeccpars2_25_(__Stack0) ->
+ [__2,__1 | __Stack] = __Stack0,
+ [begin
+ [ ]
+ end | __Stack].
+
+-compile({inline,{yeccpars2_27_,1}}).
+-file("json_grammar.yrl", 17).
+yeccpars2_27_(__Stack0) ->
[__3,__2,__1 | __Stack] = __Stack0,
[begin
[ __1 | __3 ]
end | __Stack].
--compile({inline,{yeccpars2_24_,1}}).
--file("jsong.yrl", 14).
-yeccpars2_24_(__Stack0) ->
+-compile({inline,{yeccpars2_28_,1}}).
+-file("json_grammar.yrl", 14).
+yeccpars2_28_(__Stack0) ->
[__3,__2,__1 | __Stack] = __Stack0,
[begin
__2
View
31 json_grammar.yrl
@@ -0,0 +1,31 @@
+Nonterminals array element elements object members member arrayobj.
+
+Terminals '{' '}' '[' ']' string ',' ':' integer float true false null.
+
+Rootsymbol arrayobj.
+
+arrayobj -> array : '$1'.
+arrayobj -> object : '$1'.
+
+object -> '{' members '}' : {'$2'}.
+object -> '{' '}' : {[]}.
+
+members -> member ',' members : ['$1' | '$3'].
+members -> member : ['$1'].
+
+member -> string ':' element : {list_to_binary(element(3, '$1')),'$3'}.
+
+array -> '[' elements ']' : '$2'.
+array -> '[' ']' : [].
+
+elements -> element ',' elements : ['$1' | '$3'].
+elements -> element : ['$1'].
+
+element -> string : list_to_binary(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').
View
BIN  json_lex2.beam
Binary file not shown
View
406 jsonl.erl → json_lex2.erl
@@ -5,15 +5,48 @@
%% property of the creator of the scanner and is not covered by that
%% Copyright.
--module(jsonl).
+-module(json_lex2).
-export([string/1,string/2,token/2,token/3,tokens/2,tokens/3]).
-export([format_error/1]).
%% User code. This is placed here to allow extra attributes.
-
-strip(TokenChars,TokenLen) -> lists:sublist(TokenChars, 2, TokenLen - 2).
-
+% "
+
+-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(C3) bor
+ (dehex(C2) bsl 4) bor
+ (dehex(C1) bsl 8) bor
+ (dehex(C0) 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).
format_error({illegal,S}) -> ["illegal characters ",io_lib:write_string(S)];
format_error({user,S}) -> S.
@@ -207,228 +240,214 @@ yysuf(List, N) -> lists:nthtail(N, List).
%% return signal either an unrecognised character or end of current
%% input.
-yystate() -> 34.
+yystate() -> 32.
-yystate(37, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
- yystate(35, Ics, Line, Tlen+1, Action, Alen);
-yystate(37, [C|Ics], Line, Tlen, Action, Alen) when C >= $A, C =< $F ->
- yystate(35, Ics, Line, Tlen+1, Action, Alen);
-yystate(37, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $f ->
- yystate(35, Ics, Line, Tlen+1, Action, Alen);
-yystate(37, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,37};
-yystate(36, Ics, Line, Tlen, _, _) ->
+yystate(35, [C|Ics], Line, Tlen, _, _) when C >= $0, C =< $9 ->
+ yystate(35, Ics, Line, Tlen+1, 5, Tlen);
+yystate(35, Ics, Line, Tlen, _, _) ->
+ {5,Tlen,Ics,Line,35};
+yystate(34, Ics, Line, Tlen, _, _) ->
{1,Tlen,Ics,Line};
-yystate(35, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
- yystate(31, Ics, Line, Tlen+1, Action, Alen);
-yystate(35, [C|Ics], Line, Tlen, Action, Alen) when C >= $A, C =< $F ->
- yystate(31, Ics, Line, Tlen+1, Action, Alen);
-yystate(35, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $f ->
- yystate(31, Ics, Line, Tlen+1, Action, Alen);
-yystate(35, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,35};
-yystate(34, [$\n|Ics], Line, Tlen, Action, Alen) ->
- yystate(30, Ics, Line+1, Tlen+1, Action, Alen);
-yystate(34, [$"|Ics], Line, Tlen, Action, Alen) ->
- yystate(26, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$%|Ics], Line, Tlen, Action, Alen) ->
- yystate(10, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$,|Ics], Line, Tlen, Action, Alen) ->
- yystate(6, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$:|Ics], Line, Tlen, Action, Alen) ->
- yystate(21, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$[|Ics], Line, Tlen, Action, Alen) ->
- yystate(25, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$\\|Ics], Line, Tlen, Action, Alen) ->
- yystate(29, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$]|Ics], Line, Tlen, Action, Alen) ->
- yystate(23, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$f|Ics], Line, Tlen, Action, Alen) ->
- yystate(19, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$n|Ics], Line, Tlen, Action, Alen) ->
+yystate(33, Ics, Line, Tlen, _, _) ->
+ {11,Tlen,Ics,Line};
+yystate(32, [$\n|Ics], Line, Tlen, Action, Alen) ->
+ yystate(28, Ics, Line+1, Tlen+1, Action, Alen);
+yystate(32, [$"|Ics], Line, Tlen, Action, Alen) ->
+ yystate(24, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [$%|Ics], Line, Tlen, Action, Alen) ->
+ yystate(8, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [$,|Ics], Line, Tlen, Action, Alen) ->
+ yystate(4, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [$-|Ics], Line, Tlen, Action, Alen) ->
yystate(0, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$t|Ics], Line, Tlen, Action, Alen) ->
- yystate(16, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [${|Ics], Line, Tlen, Action, Alen) ->
- yystate(32, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [$}|Ics], Line, Tlen, Action, Alen) ->
- yystate(36, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t ->
- yystate(30, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $\s ->
+yystate(32, [$:|Ics], Line, Tlen, Action, Alen) ->
+ yystate(33, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [$[|Ics], Line, Tlen, Action, Alen) ->
+ yystate(29, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [$]|Ics], Line, Tlen, Action, Alen) ->
+ yystate(25, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [$f|Ics], Line, Tlen, Action, Alen) ->
+ yystate(21, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [$n|Ics], Line, Tlen, Action, Alen) ->
+ yystate(1, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [$t|Ics], Line, Tlen, Action, Alen) ->
+ yystate(14, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [${|Ics], Line, Tlen, Action, Alen) ->
yystate(30, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
- yystate(2, Ics, Line, Tlen+1, Action, Alen);
-yystate(34, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,34};
-yystate(33, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
- yystate(37, Ics, Line, Tlen+1, Action, Alen);
-yystate(33, [C|Ics], Line, Tlen, Action, Alen) when C >= $A, C =< $F ->
- yystate(37, Ics, Line, Tlen+1, Action, Alen);
-yystate(33, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $f ->
- yystate(37, Ics, Line, Tlen+1, Action, Alen);
-yystate(33, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,33};
-yystate(32, Ics, Line, Tlen, _, _) ->
- {0,Tlen,Ics,Line};
+yystate(32, [$}|Ics], Line, Tlen, Action, Alen) ->
+ yystate(34, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t ->
+ yystate(28, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $\s ->
+ yystate(28, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
+ yystate(3, Ics, Line, Tlen+1, Action, Alen);
+yystate(32, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,32};
yystate(31, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
- yystate(27, Ics, Line, Tlen+1, Action, Alen);
-yystate(31, [C|Ics], Line, Tlen, Action, Alen) when C >= $A, C =< $F ->
- yystate(27, Ics, Line, Tlen+1, Action, Alen);
-yystate(31, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $f ->
- yystate(27, Ics, Line, Tlen+1, Action, Alen);
+ yystate(35, Ics, Line, Tlen+1, Action, Alen);
yystate(31, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,31};
-yystate(30, [$\n|Ics], Line, Tlen, _, _) ->
- yystate(30, Ics, Line+1, Tlen+1, 13, Tlen);
-yystate(30, [$%|Ics], Line, Tlen, _, _) ->
- yystate(10, Ics, Line, Tlen+1, 13, Tlen);
-yystate(30, [C|Ics], Line, Tlen, _, _) when C >= $\000, C =< $\t ->
- yystate(30, Ics, Line, Tlen+1, 13, Tlen);
-yystate(30, [C|Ics], Line, Tlen, _, _) when C >= $\v, C =< $\s ->
- yystate(30, Ics, Line, Tlen+1, 13, Tlen);
yystate(30, Ics, Line, Tlen, _, _) ->
- {13,Tlen,Ics,Line,30};
-yystate(29, [$u|Ics], Line, Tlen, Action, Alen) ->
- yystate(33, Ics, Line, Tlen+1, Action, Alen);
-yystate(29, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,29};
+ {0,Tlen,Ics,Line};
+yystate(29, Ics, Line, Tlen, _, _) ->
+ {2,Tlen,Ics,Line};
+yystate(28, [$\n|Ics], Line, Tlen, _, _) ->
+ yystate(28, Ics, Line+1, Tlen+1, 13, Tlen);
+yystate(28, [$%|Ics], Line, Tlen, _, _) ->
+ yystate(8, Ics, Line, Tlen+1, 13, Tlen);
+yystate(28, [C|Ics], Line, Tlen, _, _) when C >= $\000, C =< $\t ->
+ yystate(28, Ics, Line, Tlen+1, 13, Tlen);
+yystate(28, [C|Ics], Line, Tlen, _, _) when C >= $\v, C =< $\s ->
+ yystate(28, Ics, Line, Tlen+1, 13, Tlen);
yystate(28, Ics, Line, Tlen, _, _) ->
+ {13,Tlen,Ics,Line,28};
+yystate(27, [$+|Ics], Line, Tlen, Action, Alen) ->
+ yystate(31, Ics, Line, Tlen+1, Action, Alen);
+yystate(27, [$-|Ics], Line, Tlen, Action, Alen) ->
+ yystate(31, Ics, Line, Tlen+1, Action, Alen);
+yystate(27, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
+ yystate(35, Ics, Line, Tlen+1, Action, Alen);
+yystate(27, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,27};
+yystate(26, Ics, Line, Tlen, _, _) ->
{8,Tlen,Ics,Line};
-yystate(27, Ics, Line, Tlen, _, _) ->
- {7,Tlen,Ics,Line};
-yystate(26, [$\n|Ics], Line, Tlen, Action, Alen) ->
- yystate(26, Ics, Line+1, Tlen+1, Action, Alen);
-yystate(26, [$"|Ics], Line, Tlen, Action, Alen) ->
- yystate(22, Ics, Line, Tlen+1, Action, Alen);
-yystate(26, [$\\|Ics], Line, Tlen, Action, Alen) ->
- yystate(18, Ics, Line, Tlen+1, Action, Alen);
-yystate(26, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t ->
- yystate(26, Ics, Line, Tlen+1, Action, Alen);
-yystate(26, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $! ->
- yystate(26, Ics, Line, Tlen+1, Action, Alen);
-yystate(26, [C|Ics], Line, Tlen, Action, Alen) when C >= $#, C =< $[ ->
- yystate(26, Ics, Line, Tlen+1, Action, Alen);
-yystate(26, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ ->
- yystate(26, Ics, Line, Tlen+1, Action, Alen);
-yystate(26, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,26};
yystate(25, Ics, Line, Tlen, _, _) ->
- {2,Tlen,Ics,Line};
-yystate(24, [$e|Ics], Line, Tlen, Action, Alen) ->
- yystate(28, Ics, Line, Tlen+1, Action, Alen);
+ {3,Tlen,Ics,Line};
+yystate(24, [$\n|Ics], Line, Tlen, Action, Alen) ->
+ yystate(24, Ics, Line+1, Tlen+1, Action, Alen);
+yystate(24, [$"|Ics], Line, Tlen, Action, Alen) ->
+ yystate(20, Ics, Line, Tlen+1, Action, Alen);
+yystate(24, [$\\|Ics], Line, Tlen, Action, Alen) ->
+ yystate(16, Ics, Line, Tlen+1, Action, Alen);
+yystate(24, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t ->
+ yystate(24, Ics, Line, Tlen+1, Action, Alen);
+yystate(24, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $! ->
+ yystate(24, Ics, Line, Tlen+1, Action, Alen);
+yystate(24, [C|Ics], Line, Tlen, Action, Alen) when C >= $#, C =< $[ ->
+ yystate(24, Ics, Line, Tlen+1, Action, Alen);
+yystate(24, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ ->
+ yystate(24, Ics, Line, Tlen+1, Action, Alen);
yystate(24, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,24};
+yystate(23, [C|Ics], Line, Tlen, _, _) when C >= $0, C =< $9 ->
+ yystate(23, Ics, Line, Tlen+1, 4, Tlen);
yystate(23, Ics, Line, Tlen, _, _) ->
- {3,Tlen,Ics,Line};
-yystate(22, Ics, Line, Tlen, _, _) ->
- {6,Tlen,Ics,Line};
-yystate(21, Ics, Line, Tlen, _, _) ->
- {11,Tlen,Ics,Line};
-yystate(20, [$u|Ics], Line, Tlen, Action, Alen) ->
- yystate(24, Ics, Line, Tlen+1, Action, Alen);
-yystate(20, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,20};
-yystate(19, [$a|Ics], Line, Tlen, Action, Alen) ->
- yystate(15, Ics, Line, Tlen+1, Action, Alen);
+ {4,Tlen,Ics,Line,23};
+yystate(22, [$e|Ics], Line, Tlen, Action, Alen) ->
+ yystate(26, Ics, Line, Tlen+1, Action, Alen);
+yystate(22, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,22};
+yystate(21, [$a|Ics], Line, Tlen, Action, Alen) ->
+ yystate(17, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,21};
+yystate(20, Ics, Line, Tlen, _, _) ->
+ {7,Tlen,Ics,Line};
+yystate(19, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
+ yystate(23, Ics, Line, Tlen+1, Action, Alen);
yystate(19, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,19};
-yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t ->
- yystate(14, Ics, Line, Tlen+1, Action, Alen);
-yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $ÿ ->
- yystate(14, Ics, Line, Tlen+1, Action, Alen);
+yystate(18, [$u|Ics], Line, Tlen, Action, Alen) ->
+ yystate(22, Ics, Line, Tlen+1, Action, Alen);
yystate(18, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,18};
-yystate(17, [C|Ics], Line, Tlen, _, _) when C >= $0, C =< $9 ->
- yystate(17, Ics, Line, Tlen+1, 4, Tlen);
-yystate(17, Ics, Line, Tlen, _, _) ->
- {4,Tlen,Ics,Line,17};
-yystate(16, [$r|Ics], Line, Tlen, Action, Alen) ->
- yystate(20, Ics, Line, Tlen+1, Action, Alen);
+yystate(17, [$l|Ics], Line, Tlen, Action, Alen) ->
+ yystate(13, Ics, Line, Tlen+1, Action, Alen);
+yystate(17, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,17};
+yystate(16, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t ->
+ yystate(12, Ics, Line, Tlen+1, Action, Alen);
+yystate(16, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $ÿ ->
+ yystate(12, Ics, Line, Tlen+1, Action, Alen);
yystate(16, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,16};
-yystate(15, [$l|Ics], Line, Tlen, Action, Alen) ->
- yystate(11, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [$+|Ics], Line, Tlen, Action, Alen) ->
+ yystate(19, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [$-|Ics], Line, Tlen, Action, Alen) ->
+ yystate(19, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
+ yystate(23, Ics, Line, Tlen+1, Action, Alen);
yystate(15, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,15};
-yystate(14, [$\n|Ics], Line, Tlen, Action, Alen) ->
- yystate(14, Ics, Line+1, Tlen+1, Action, Alen);
-yystate(14, [$"|Ics], Line, Tlen, Action, Alen) ->
- yystate(22, Ics, Line, Tlen+1, Action, Alen);
-yystate(14, [$\\|Ics], Line, Tlen, Action, Alen) ->
+yystate(14, [$r|Ics], Line, Tlen, Action, Alen) ->
yystate(18, Ics, Line, Tlen+1, Action, Alen);
-yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t ->
- yystate(14, Ics, Line, Tlen+1, Action, Alen);
-yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $! ->
- yystate(14, Ics, Line, Tlen+1, Action, Alen);
-yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $#, C =< $[ ->
- yystate(14, Ics, Line, Tlen+1, Action, Alen);
-yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ ->
- yystate(14, Ics, Line, Tlen+1, Action, Alen);
yystate(14, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,14};
-yystate(13, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
- yystate(17, Ics, Line, Tlen+1, Action, Alen);
+yystate(13, [$s|Ics], Line, Tlen, Action, Alen) ->
+ yystate(9, Ics, Line, Tlen+1, Action, Alen);
yystate(13, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,13};
-yystate(12, Ics, Line, Tlen, _, _) ->
- {10,Tlen,Ics,Line};
-yystate(11, [$s|Ics], Line, Tlen, Action, Alen) ->
- yystate(7, Ics, Line, Tlen+1, Action, Alen);
-yystate(11, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,11};
-yystate(10, [$\n|Ics], Line, Tlen, _, _) ->
- yystate(30, Ics, Line+1, Tlen+1, 13, Tlen);
-yystate(10, [C|Ics], Line, Tlen, _, _) when C >= $\000, C =< $\t ->
- yystate(10, Ics, Line, Tlen+1, 13, Tlen);
-yystate(10, [C|Ics], Line, Tlen, _, _) when C >= $\v, C =< $ÿ ->
- yystate(10, Ics, Line, Tlen+1, 13, Tlen);
+yystate(12, [$\n|Ics], Line, Tlen, Action, Alen) ->
+ yystate(12, Ics, Line+1, Tlen+1, Action, Alen);
+yystate(12, [$"|Ics], Line, Tlen, Action, Alen) ->
+ yystate(20, Ics, Line, Tlen+1, Action, Alen);
+yystate(12, [$\\|Ics], Line, Tlen, Action, Alen) ->
+ yystate(16, Ics, Line, Tlen+1, Action, Alen);
+yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t ->
+ yystate(12, Ics, Line, Tlen+1, Action, Alen);
+yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $! ->
+ yystate(12, Ics, Line, Tlen+1, Action, Alen);
+yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $#, C =< $[ ->
+ yystate(12, Ics, Line, Tlen+1, Action, Alen);
+yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ ->
+ yystate(12, Ics, Line, Tlen+1, Action, Alen);
+yystate(12, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,12};
+yystate(11, [$E|Ics], Line, Tlen, _, _) ->
+ yystate(15, Ics, Line, Tlen+1, 4, Tlen);
+yystate(11, [$e|Ics], Line, Tlen, _, _) ->
+ yystate(15, Ics, Line, Tlen+1, 4, Tlen);
+yystate(11, [C|Ics], Line, Tlen, _, _) when C >= $0, C =< $9 ->
+ yystate(11, Ics, Line, Tlen+1, 4, Tlen);
+yystate(11, Ics, Line, Tlen, _, _) ->
+ {4,Tlen,Ics,Line,11};
yystate(10, Ics, Line, Tlen, _, _) ->
- {13,Tlen,Ics,Line,10};
-yystate(9, [$+|Ics], Line, Tlen, Action, Alen) ->
- yystate(13, Ics, Line, Tlen+1, Action, Alen);
-yystate(9, [$-|Ics], Line, Tlen, Action, Alen) ->
- yystate(13, Ics, Line, Tlen+1, Action, Alen);
-yystate(9, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
- yystate(17, Ics, Line, Tlen+1, Action, Alen);
+ {10,Tlen,Ics,Line};
+yystate(9, [$e|Ics], Line, Tlen, Action, Alen) ->
+ yystate(5, Ics, Line, Tlen+1, Action, Alen);
yystate(9, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,9};
-yystate(8, [$l|Ics], Line, Tlen, Action, Alen) ->
- yystate(12, Ics, Line, Tlen+1, Action, Alen);
-yystate(8, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,8};
-yystate(7, [$e|Ics], Line, Tlen, Action, Alen) ->
- yystate(3, Ics, Line, Tlen+1, Action, Alen);
+yystate(8, [$\n|Ics], Line, Tlen, _, _) ->
+ yystate(28, Ics, Line+1, Tlen+1, 13, Tlen);
+yystate(8, [C|Ics], Line, Tlen, _, _) when C >= $\000, C =< $\t ->
+ yystate(8, Ics, Line, Tlen+1, 13, Tlen);
+yystate(8, [C|Ics], Line, Tlen, _, _) when C >= $\v, C =< $ÿ ->
+ yystate(8, Ics, Line, Tlen+1, 13, Tlen);
+yystate(8, Ics, Line, Tlen, _, _) ->
+ {13,Tlen,Ics,Line,8};
+yystate(7, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
+ yystate(11, Ics, Line, Tlen+1, Action, Alen);
yystate(7, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,7};
-yystate(6, Ics, Line, Tlen, _, _) ->
- {12,Tlen,Ics,Line};
-yystate(5, [$E|Ics], Line, Tlen, _, _) ->
- yystate(9, Ics, Line, Tlen+1, 4, Tlen);
-yystate(5, [$e|Ics], Line, Tlen, _, _) ->
- yystate(9, Ics, Line, Tlen+1, 4, Tlen);
-yystate(5, [C|Ics], Line, Tlen, _, _) when C >= $0, C =< $9 ->
- yystate(5, Ics, Line, Tlen+1, 4, Tlen);
+yystate(6, [$l|Ics], Line, Tlen, Action, Alen) ->
+ yystate(10, Ics, Line, Tlen+1, Action, Alen);
+yystate(6, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,6};
yystate(5, Ics, Line, Tlen, _, _) ->
- {4,Tlen,Ics,Line,5};
-yystate(4, [$l|Ics], Line, Tlen, Action, Alen) ->
- yystate(8, Ics, Line, Tlen+1, Action, Alen);
-yystate(4, Ics, Line, Tlen, Action, Alen) ->
- {Action,Alen,Tlen,Ics,Line,4};
-yystate(3, Ics, Line, Tlen, _, _) ->
{9,Tlen,Ics,Line};
-yystate(2, [$.|Ics], Line, Tlen, _, _) ->
- yystate(1, Ics, Line, Tlen+1, 5, Tlen);
-yystate(2, [C|Ics], Line, Tlen, _, _) when C >= $0, C =< $9 ->
- yystate(2, Ics, Line, Tlen+1, 5, Tlen);
-yystate(2, Ics, Line, Tlen, _, _) ->
- {5,Tlen,Ics,Line,2};
-yystate(1, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
- yystate(5, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, Ics, Line, Tlen, _, _) ->
+ {12,Tlen,Ics,Line};
+yystate(3, [$.|Ics], Line, Tlen, _, _) ->
+ yystate(7, Ics, Line, Tlen+1, 6, Tlen);
+yystate(3, [$E|Ics], Line, Tlen, _, _) ->
+ yystate(27, Ics, Line, Tlen+1, 6, Tlen);
+yystate(3, [$e|Ics], Line, Tlen, _, _) ->
+ yystate(27, Ics, Line, Tlen+1, 6, Tlen);
+yystate(3, [C|Ics], Line, Tlen, _, _) when C >= $0, C =< $9 ->
+ yystate(3, Ics, Line, Tlen+1, 6, Tlen);
+yystate(3, Ics, Line, Tlen, _, _) ->
+ {6,Tlen,Ics,Line,3};
+yystate(2, [$l|Ics], Line, Tlen, Action, Alen) ->
+ yystate(6, Ics, Line, Tlen+1, Action, Alen);
+yystate(2, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,2};
+yystate(1, [$u|Ics], Line, Tlen, Action, Alen) ->
+ yystate(2, Ics, Line, Tlen+1, Action, Alen);
yystate(1, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,1};
-yystate(0, [$u|Ics], Line, Tlen, Action, Alen) ->
- yystate(4, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 ->
+ yystate(3, Ics, Line, Tlen+1, Action, Alen);
yystate(0, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,0};
yystate(S, Ics, Line, Tlen, Action, Alen) ->
@@ -451,14 +470,13 @@ yyaction(4, TokenLen, YYtcs, TokenLine) ->
{token,{float,TokenLine,list_to_float(TokenChars)}};
yyaction(5, TokenLen, YYtcs, TokenLine) ->
TokenChars = yypre(YYtcs, TokenLen),
- {token,{integer,TokenLine,list_to_integer(TokenChars)}};
+ {token,{float,TokenLine,whole_float(TokenChars)}};
yyaction(6, TokenLen, YYtcs, TokenLine) ->
TokenChars = yypre(YYtcs, TokenLen),
- {token,
- {string,TokenLine,list_to_binary(strip(TokenChars, TokenLen))}};
+ {token,{integer,TokenLine,list_to_integer(TokenChars)}};
yyaction(7, TokenLen, YYtcs, TokenLine) ->
TokenChars = yypre(YYtcs, TokenLen),
- {token,{unicode,TokenLine,TokenChars}};
+ {token,{string,TokenLine,parse_string(strip(TokenChars, TokenLen))}};
yyaction(8, _, _, TokenLine) ->
{token,{true,TokenLine}};
yyaction(9, _, _, TokenLine) ->
View
72 json_lex2.xrl
@@ -0,0 +1,72 @@
+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(C3) bor
+ (dehex(C2) bsl 4) bor
+ (dehex(C1) bsl 8) bor
+ (dehex(C0) 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).
View
BIN  jsong.beam
Binary file not shown
View
12 jsong.yrl
@@ -1,29 +1,31 @@
Nonterminals array element elements arrobj object members member.
-Terminals '{' '}' '[' ']' string ',' ':' integer true false null.
+Terminals '{' '}' '[' ']' string ',' ':' integer float true false null.
-Rootsymbol arrobj.
+Rootsymbol element.
arrobj -> array : '$1'.
arrobj -> object : '$1'.
object -> '{' members '}' : {obj, '$2'}.
+object -> '{' '}' : {obj, []}.
% object -> '{' member '}' : {'$2'}. % results in a shift/reduce conflict...
members -> member ',' members : ['$1' | '$3'].
-members -> member : '$1'.
+members -> member : ['$1'].
member -> string ':' element : {element(3, '$1'),'$3'}.
-array -> '[' elements ']' : '$2'.
+array -> '[' elements ']' : list_to_tuple('$2').
elements -> element ',' elements : ['$1' | '$3'].
elements -> element : ['$1'].
-elements -> '$empty' : nil.
+elements -> '$empty' : [].
element -> string : element(3, '$1').
element -> arrobj : '$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').
View
BIN  jsonl.beam
Binary file not shown
View
78 jsonl.xrl
@@ -14,15 +14,15 @@ Rules.
\[ : {token, {'[', TokenLine}}.
\] : {token, {']', TokenLine}}.
-{D}+\.{D}+((E|e)(\+|\-)?{D}+)? :
- {token,{float,TokenLine,list_to_float(TokenChars)}}.
-{D}+ : {token,{integer,TokenLine,list_to_integer(TokenChars)}}.
+\-?{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(TokenChars,TokenLen)}}.
-"[^"\\]*(\\.[^"\\]*)*" : {token,{string,TokenLine,list_to_binary(strip(TokenChars,TokenLen))}}.
+% "[^"\\]*(\\[^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}}.
+% \\u{H}{H}{H}{H} : {token, {unicode, TokenLine,TokenChars}}.
true : {token,{'true', TokenLine}}.
false : {token,{'false', TokenLine}}.