Current section

Files

Jump to
gpb src gpb_scan.xrl
Raw

src/gpb_scan.xrl

%% This line tells emacs to use -*- erlang -*- mode for this file
%%% Copyright (C) 2010-2011 Tomas Abrahamsson
%%%
%%% Author: Tomas Abrahamsson <tab@lysator.liu.se>
%%%
%%% This library is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU Lesser General Public
%%% License as published by the Free Software Foundation; either
%%% version 2.1 of the License, or (at your option) any later version.
%%%
%%% This library is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% Lesser General Public License for more details.
%%%
%%% You should have received a copy of the GNU Lesser General Public
%%% License along with this library; if not, write to the Free Software
%%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
%%% MA 02110-1301 USA
Definitions.
D = [0-9]
H = [0-9a-fA-F]
WS = [\000-\s]+
Rules.
required : {token, {required,TokenLine}}.
optional : {token, {optional,TokenLine}}.
repeated : {token, {repeated,TokenLine}}.
oneof : {token, {oneof,TokenLine}}.
double : {token, {double,TokenLine}}.
float : {token, {float,TokenLine}}.
int32 : {token, {int32,TokenLine}}.
int64 : {token, {int64,TokenLine}}.
uint32 : {token, {uint32,TokenLine}}.
uint64 : {token, {uint64,TokenLine}}.
sint32 : {token, {sint32,TokenLine}}.
sint64 : {token, {sint64,TokenLine}}.
fixed32 : {token, {fixed32,TokenLine}}.
fixed64 : {token, {fixed64,TokenLine}}.
sfixed32 : {token, {sfixed32,TokenLine}}.
sfixed64 : {token, {sfixed64,TokenLine}}.
bool : {token, {bool,TokenLine}}.
string : {token, {string,TokenLine}}.
bytes : {token, {bytes,TokenLine}}.
map : {token, {map,TokenLine}}.
package : {token, {package,TokenLine}}.
message : {token, {message,TokenLine}}.
enum : {token, {enum,TokenLine}}.
option : {token, {option,TokenLine}}.
import : {token, {import,TokenLine}}.
default : {token, {default,TokenLine}}.
packed : {token, {packed,TokenLine}}.
deprecated : {token, {deprecated,TokenLine}}.
extensions : {token, {extensions,TokenLine}}.
extend : {token, {extend,TokenLine}}.
to : {token, {to,TokenLine}}.
max : {token, {max,TokenLine}}.
reserved : {token, {reserved,TokenLine}}.
service : {token, {service,TokenLine}}.
rpc : {token, {rpc,TokenLine}}.
returns : {token, {returns,TokenLine}}.
stream : {token, {stream,TokenLine}}.
true : {token, {bool_lit,TokenLine,true}}.
false : {token, {bool_lit,TokenLine,false}}.
syntax : {token, {syntax,TokenLine}}.
"(\\x[0-9a-fA-F]|\\[0-7]|\\[abfnrtv?"'\\]|[^"\n])*" :
{token,{str_lit,TokenLine,string_value(TokenChars)}}.
'(\\x[0-9a-fA-F]|\\[0-7]|\\[abfnrtv?"'\\]|[^'\n])*' :
{token,{str_lit,TokenLine,string_value(TokenChars)}}.
(\+|-)?{D}+\.{D}+((E|e)(\+|\-)?{D}+)? :
{token,{float_lit,TokenLine,str_to_float_1(TokenChars)}}.
(\+|-)?\.{D}+((E|e)(\+|\-)?{D}+)? :
{token,{float_lit,TokenLine,str_to_float_2(TokenChars)}}.
(\+|-)?{D}+\.((E|e)(\+|\-)?{D}+)? :
{token,{float_lit,TokenLine,str_to_float_3(TokenChars)}}.
(\+|-)?{D}+(E|e)(\+|\-)?{D}+ :
{token,{float_lit,TokenLine,str_to_float_4(TokenChars)}}.
% Cannot create neither +-inf or nan in erlang...
% (\+|-)?inf : {token,{float_lit,TokenLine,create_inf(TokenChars)}}.
% nan : {token,{float_lit,TokenLine,create_nan()}}.
(\+|-)?0[xX]{H}+ : {token,{hex_lit,TokenLine,hexstr_to_integer(TokenChars)}}.
(\+|-)?0{D}+ : {token,{oct_lit,TokenLine,octstr_to_integer(TokenChars)}}.
(\+|-)?{D}+ : {token,{dec_lit,TokenLine,list_to_integer(TokenChars)}}.
[a-zA-Z_][A-Za-z0-9_]* : {token,{identifier,TokenLine,TokenChars}}.
\. : {token, {'.', TokenLine}}.
; : {token, {';', TokenLine}}.
\{ : {token, {'{', TokenLine}}.
\} : {token, {'}', TokenLine}}.
\[ : {token, {'[', TokenLine}}.
\] : {token, {']', TokenLine}}.
\( : {token, {'(', TokenLine}}.
\) : {token, {')', TokenLine}}.
= : {token, {'=', TokenLine}}.
, : {token, {',', TokenLine}}.
< : {token, {'<', TokenLine}}.
> : {token, {'>', TokenLine}}.
//.*\n : skip_token. %% C++-style comment
//.* : skip_token. %% C++-style comment
(/\*([^*]|(\*+[^*/]))*\*+/)|(//.*) : skip_token. %% C-style comment
{WS} : skip_token.
Erlang code.
-include_lib("eunit/include/eunit.hrl").
%% Eliminate a dialyzer warning like below:
%% /usr/lib/erlang/lib/parsetools-2.1.1/include/leexinc.hrl:268:
%% Function yyrev/2 will never be called
-dialyzer({nowarn_function, yyrev/2}).
string_value(S) -> % S is with start+end quote
%% Strip quotes.
string_val_2(lists:sublist(S, 2, length(S) - 2)).
string_val_2([$\\|Cs]) -> string_escape(Cs);
string_val_2([C|Cs]) -> [C|string_val_2(Cs)];
string_val_2([]) -> [].
-define(is_octal_char(C), $0 =< C, C =< $7).
string_escape("x"++Rest) ->
{HexChars, Rest2} = collect(fun is_hex_char/1, Rest),
[hex_to_integer(HexChars) | string_val_2(Rest2)];
string_escape([Oct|Rest]) when ?is_octal_char(Oct) ->
{OctChars, Rest2} = collect(fun is_oct_char/1, [Oct|Rest]),
[oct_to_integer(OctChars) | string_val_2(Rest2)];
string_escape([C|Rest]) ->
[escape_char(C) | string_val_2(Rest)].
escape_char($a) -> 7; %\a = BEL
escape_char($b) -> $\b; %\b = BS
escape_char($f) -> $\f; %\f = FF
escape_char($n) -> $\n; %\n = LF
escape_char($r) -> $\r; %\r = CR
escape_char($t) -> $\t; %\t = TAB
escape_char($v) -> $\v; %\v = VT
escape_char(C) -> C.
collect(Pred, Str) -> lists:splitwith(Pred, Str).
is_oct_char(C) -> $0 =< C andalso C =< $7.
is_hex_char(C) -> ($0 =< C andalso C =< $9)
orelse ($a =< C andalso C =< $f)
orelse ($A =< C andalso C =< $F).
oct_to_integer(Str) -> erlang:list_to_integer(Str, 8).
hex_to_integer(Str) -> erlang:list_to_integer(Str, 16).
octstr_to_integer(Str) -> oct_to_integer(Str).
hexstr_to_integer("0x"++H) -> hex_to_integer(H);
hexstr_to_integer("0X"++H) -> hex_to_integer(H);
hexstr_to_integer("+0x"++H) -> hex_to_integer(H);
hexstr_to_integer("+0X"++H) -> hex_to_integer(H);
hexstr_to_integer("-0x"++H) -> -hex_to_integer(H);
hexstr_to_integer("-0X"++H) -> -hex_to_integer(H).
str_to_float_1(S) -> list_to_float(S).
str_to_float_2("."++_=S) -> str_to_float_1("0"++S);
str_to_float_2("+."++T) -> str_to_float_1("0."++T);
str_to_float_2("-."++T) -> str_to_float_1("-0."++T).
str_to_float_3(S) -> %% No decimals after `.' Possibly e+-<n> following `.'
{UpToDot, "."++Rest} = collect(fun isnt_dot/1, S),
str_to_float_1(UpToDot++"."++"0"++Rest).
str_to_float_4(S) -> %% Integer preceding e+-<n>
{UpToDot, Rest} = collect(fun isnt_exp_e/1, S),
str_to_float_1(UpToDot++"."++"0"++Rest).
isnt_dot(C) -> C /= $. .
isnt_exp_e($e) -> false;
isnt_exp_e($E) -> false;
isnt_exp_e(_) -> true.