% Autogenerated with DRAKON Editor 1.27

-module(lexer).
-export([create/1]).
-export([send_event/2]).
-export([get_state/1]).
-export([get_data/1]).
-export([lex/1]).
%  stipan.mitkin@gmail.com
%  http://drakon-editor.sourceforge.net/

%  Copyright 2015 Stepan Mitkin
%  This code is PUBLIC DOMAIN.

add_char(State, Char) ->
    % item 262
    {Buffer, Tokens} = State,
    % item 326
    {[Char | Buffer], Tokens}
.

classify(Operators, Char) ->
    % item 351
    case Char =:= $_ of true -> 
        % item 359
        letter
    ; false ->
        % item 354
        case (Char >= $0) andalso (Char =< $9) of true -> 
            % item 369
            digit
        ; false ->
            % item 370
            case is_whitespace(Char) of true -> 
                % item 365
                whitespace
            ; false ->
                % item 361
                case sets:is_element(Char, Operators) of true -> 
                    % item 364
                    operator
                ; false ->
                    % item 386
                    letter
                end
            end
        end
    end
.

create_identifier(State) ->
    % item 268
    create_token(State, identifier)
.

create_number(State) ->
    % item 329
    create_token(State, number)
.

create_operator(State) ->
    % item 330
    create_token(State, operator)
.

create_operator_list() ->
    % item 391
    OperatorList = [
    $!, 
    $=, 
    $<, 
    $>, 
    $-, 
    $+, 
    $/, 
    $\\, 
    $*, 
    $%, 
    $(, 
    $), 
    $[, 
    $], 
    ${, 
    $}, 
    $:, 
    $., 
    $;, 
    $,, 
    $^, 
    $|, 
    $&, 
    $", 
    $'],
    % item 392
    sets:from_list(OperatorList)
.

create_token(State, TokenType) ->
    % item 327
    {Buffer, Tokens} = State,
    % item 274
    case Buffer =:= [] of true -> 
        % item 328
        State
    ; false ->
        % item 277
        Text = lists:reverse(Buffer),
        Token = {TokenType, Text},
        % item 278
        {[], [Token | Tokens]}
    end
.

is_long_operator(Text) ->
    % item 338
    case (((Text =:= "==") orelse (Text =:= "!=")) orelse (Text =:= "<=")) orelse (Text =:= ">=") of true -> 
        % item 345
        true
    ; false ->
        % item 344
        false
    end
.

is_whitespace(Char) ->
    % item 378
    case (((Char =:= 9) orelse (Char =:= 32)) orelse (Char =:= 13)) orelse (Char =:= 10) of true -> 
        % item 385
        true
    ; false ->
        % item 384
        false
    end
.

lex(Text) ->
    % item 253
    State = {[], []},
    % item 398
    Lexer = create(State),
    % item 313
    Operators = create_operator_list(),
    % item 256
    FinalLexer = scan(Operators, Lexer, Text),
    % item 255
    {_, TokensInv} = get_data(FinalLexer),
    % item 393
    lists:reverse(TokensInv)
.

scan(Operators, Lexer, Text) ->
    % item 319
    case Text =:= [] of true -> 
        % item 387
        % item 367
        Message = {whitespace, 32},
        % item 366
        send_event(Lexer, Message)
    ; false ->
        % item 322
        [Char | Rest] = Text,
        % item 323
        Type = classify(Operators, Char),
        Message = {Type, Char},
        % item 325
        Lexer2 = send_event(Lexer, Message),
        % item 324
        scan(Operators, Lexer2, Rest)
    end
.

try_make_long_operator(State, Char) ->
    % item 332
    {[Old], Tokens} = State,
    Text = [Old, Char],
    % item 297
    case is_long_operator(Text) of true -> 
        % item 300
        Token = {operator, Text},
        % item 397
        NewState = {[], [Token | Tokens]},
        % item 301
        {true, NewState}
    ; false ->
        % item 302
        {false, []}
    end
.
identifier(Message_, State) ->
    case Message_ of
    {whitespace, _} ->
        % item 65
        {next_state, idle, create_identifier(State)}
    ;
    {letter, Char} ->
        % item 242
        {next_state, identifier, add_char(State, Char)}
    ;
    {digit, Char} ->
        % item 243
        {next_state, identifier, add_char(State, Char)}
    ;
    {operator, Char} ->
        % item 219
        StateWithId = 
         create_identifier(State),
        % item 61
        {next_state, operator, add_char(StateWithId, Char)}
    ;
    _ ->
        throw({invalid_state, "Message not supported by state 'identifier'."})
    end
.
idle(Message_, State) ->
    case Message_ of
    {whitespace, _} ->
        % item 211
        {next_state, idle, State}
    ;
    {dummy, _} ->
        % item 211
        {next_state, idle, State}
    ;
    {letter, Char} ->
        % item 44
        {next_state, identifier, add_char(State, Char)}
    ;
    {digit, Char} ->
        % item 240
        {next_state, number, add_char(State, Char)}
    ;
    {operator, Char} ->
        % item 241
        {next_state, operator, add_char(State, Char)}
    ;
    _ ->
        throw({invalid_state, "Message not supported by state 'idle'."})
    end
.
number(Message_, State) ->
    case Message_ of
    {whitespace, _} ->
        % item 82
        {next_state, idle, create_number(State)}
    ;
    {letter, Char} ->
        % item 244
        {next_state, number, add_char(State, Char)}
    ;
    {digit, Char} ->
        % item 245
        {next_state, number, add_char(State, Char)}
    ;
    {operator, Char} ->
        % item 226
        StateWithNum =
         create_number(State),
        % item 227
        {next_state, operator, add_char(StateWithNum, Char)}
    ;
    _ ->
        throw({invalid_state, "Message not supported by state 'number'."})
    end
.
operator(Message_, State) ->
    case Message_ of
    {whitespace, _} ->
        % item 229
        {next_state, idle, create_operator(State)}
    ;
    {letter, Char} ->
        % item 230
        StateWithOp =
         create_operator(State),
        % item 93
        {next_state, identifier, add_char(StateWithOp, Char)}
    ;
    {digit, Char} ->
        % item 231
        StateWithOp =
         create_operator(State),
        % item 246
        {next_state, number, add_char(StateWithOp, Char)}
    ;
    {operator, Char} ->
        % item 233
        {IsLong, StateWithLong} =
         try_make_long_operator(State, Char),
        % item 103
        case IsLong of true -> 
            % item 234
            {next_state, idle, StateWithLong}
        ; false ->
            % item 235
            StateWithOp =
             create_operator(State),
            % item 247
            {next_state, operator, add_char(StateWithOp, Char)}
        end
    ;
    _ ->
        throw({invalid_state, "Message not supported by state 'operator'."})
    end
.

create(State) ->
    {state_machine, idle, State}.

get_state(Machine) ->
    {state_machine, StateName, _} = Machine,
    StateName.

get_data(Machine) ->
    {state_machine, _, State } = Machine,
    State.

send_event(Machine, Event) ->
    {state_machine, StateName, State} = Machine,
    NewState = 
    case StateName of
    identifier ->
        identifier(Event, State);
    idle ->
        idle(Event, State);
    number ->
        number(Event, State);
    operator ->
        operator(Event, State);
    _ ->
        throw({invalid_state, "Unsupported state"})
    end,
    {next_state, NextStateName, NextState} = NewState,
    {state_machine, NextStateName, NextState}.


