Scanner Skeleton |

    note

        description: "General lexical analyzers"
        library: "Gobo Eiffel Lexical Library"
        copyright: "Copyright (c) 2001, Eric Bezault and others"
        license: "MIT License"

    deferred class YY_SCANNER

    create

        make
                -- Create a new scanner with
                -- standard input as input file.

        make_with_file (a_file: FILE)
                -- Create a new scanner with
                -- a_file as input file.
            require
                a_file_not_void: a_file /= Void
                a_file_open_read: a_file.is_open_read

        make_with_buffer (a_buffer: like input_buffer)
                -- Create a new scanner with
                -- a_buffer as input buffer.
            require
                a_buffer_not_void: a_buffer /= Void
            ensure
                input_buffer_set: input_buffer = a_buffer

    feature -- Initialization

        reset
                -- Reset scanner before scanning next input source.
                -- (This routine can be called in wrap before scanning
                -- another input buffer.)

    feature -- Access

        last_token: INTEGER
                -- Code of last token read
                -- (0 means that the end-of-input has been reached,
                -- non-positive values mean that an error occurred
                -- (see header-comment of scanning_error.))

        text: STRING
                -- Text of last token read
                -- (Create a new string at each call.)
            ensure
                text_not_void: Result /= Void
                correct_count: Result.count = text_count

        text_item (i: INTEGER): CHARACTER
                -- i-th character of last token read
            require
                i_large_enough: i >= 1
                i_small_enough: i <= text_count
            ensure
                definition: Result = text.item (i)

        text_substring (s, e: INTEGER): STRING
                -- Substring of last token read
                -- (Create a new string at each call.)
                -- (For efficiency reason, this function can bypass the
                -- call to text and create the substring directly from
                -- the input buffer.)
            require
                meaningful_start: 1 <= s
                meaningful_interval: s <= e + 1
                meaningful_end: e <= text_count
            ensure
                text_substring_not_void: Result /= Void
                text_substring_empty: (s > e) implies Result.empty
                definition: s <= e implies Result.is_equal (text.substring (s, e))

        start_condition: INTEGER
                -- Start condition

    feature -- Measurement

        text_count: INTEGER
                -- Length of last token read
            ensure
                positive_count: Result >= 0

        line: INTEGER
                -- Line number of last token read when
                -- '%option line' has been specified
            ensure
                line_positive: Result >= 1

        column: INTEGER
                -- Column number of last token read when
                -- '%option line' has been specified
            ensure
                column_positive: Result >= 1

        position: INTEGER
                -- Position of last token read (i.e. number of
                -- characters from the start of the input source)
                -- when '%option position' has been specified
            ensure
                position_positive: Result >= 1

    feature -- Status report

        end_of_file: BOOLEAN
                -- Has the end of input buffer been reached?
                -- This means that last_token has been set
                -- to 0 indicating "all done".

        scanning_error: BOOLEAN
                -- Has an error occurred during scanning?
                -- This can occur when too many reject are called (and hence
                -- nothing can be matched anymore) or when the option "nodefault"
                -- (or option -s) has been specified but the default rule is
                -- matched nevertheless.

        valid_start_condition (sc: INTEGER): BOOLEAN
                -- Is sc a valid start condition?

    feature -- Setting

        set_last_token (a_token: INTEGER)
                -- Set last_token to a_token.
            ensure
                last_token_set: last_token = a_token

        set_start_condition (a_start_condition: INTEGER)
                -- Set start_condition to a_start_condition.
            require
                valid_start_condition: valid_start_condition (a_start_condition)
            ensure
                start_condition_set: start_condition = a_start_condition

    feature -- Scanning

        scan
                -- Scan input_buffer until end of file is found.
            ensure
                end_of_file: not scanning_error implies end_of_file

        read_token
                -- Read a token from input_buffer.
                -- Make result available in last_token.

    feature -- Element change

        append_text_to_string (a_string: STRING)
                -- Append text at end of a_string.
                -- (For efficiency reason, this feature can bypass the
                -- call to text and directly copy the characters from
                -- the input buffer.)
            require
                a_string_not_void: a_string /= Void

        append_text_substring_to_string (s, e: INTEGER; a_string: STRING)
                -- Append text_substring at end of a_string.
                -- (For efficiency reason, this feature can bypass
                -- the call to text_substring and directly copy
                -- the characters from the input buffer.)
            require
                a_string_not_void: a_string /= Void
                s_large_enough: 1 <= s
                valid_interval: s <= e + 1
                e_small_enough: e <= text_count

        terminate
                -- Terminate scanner and set last_token
                -- to 0 indicating "all done".

        wrap: BOOLEAN
                -- Should current scanner terminate when end of file is reached?
                -- This function can be redefined to switch to another input
                -- buffer (but don't forget to update start_condition).
                -- (Default: True.)

        more
                -- Tell scanner to append the next matched token
                -- to current value of text instead of
                -- replacing it.

        less (n: INTEGER)
                -- Return all but the first n matched
                -- characters back to input_buffer.
            require
                n_large_enough: n >= 0
                n_small_enough: n <= text_count
            ensure
                text_count_set: text_count = n

        unread_character (c: CHARACTER)
                -- Put c back to input_buffer. This will alter both
                -- text and the content of input_buffer.

        read_character
                -- Read a character from input_buffer.
                -- Make result available in last_character.

        last_character: CHARACTER
                -- Last character read by read_character

    feature -- Input

        input_buffer: YY_BUFFER
                -- Input buffer

        set_input_buffer (a_buffer: like input_buffer)
                -- Set input_buffer to a_buffer.
            require
                a_buffer_not_void: a_buffer /= Void
            ensure
                input_buffer_set: input_buffer = a_buffer

        flush_input_buffer
                -- Flush input_buffer. input_buffer will be automatically
                -- refilled unless end of file has been found.
            ensure
                flushed: input_buffer.count = 0

        new_file_buffer (a_file: FILE): YY_FILE_BUFFER
                -- New input buffer for a_file
            require
                a_file_not_void: a_file /= Void
                a_file_open_read: a_file.is_open_read
            ensure
                new_buffer_not_void: Result /= Void

        new_string_buffer (a_string: STRING): YY_BUFFER
                -- New input buffer for a_string
            require
                a_string_not_void: a_string /= Void
            ensure
                new_buffer_not_void: Result /= Void

        Empty_buffer: YY_BUFFER
                -- Empty input buffer
            ensure
                empty_buffer_not_void: Result /= Void

    feature -- Output

        output (a_text: like text)
                -- Output a_text.
                -- (Note: this routine can be redefined in descendant
                -- classes. Default: print a_text to standard output.)
            require
                a_text_not_void: a_text /= Void

        echo
                -- Output text using feature output.

    feature -- Action

        pre_action
                -- Action executed before every semantic action
                -- when '%option pre-action' has been specified.
                -- (Note: this routine can be redefined in descendant
                -- classes. Default: do nothing.)

        post_action
                -- Action executed after every semantic action
                -- when '%option post-action' has been specified.
                -- (Note: this routine can be redefined in descendant
                -- classes. Default: do nothing.)

        pre_eof_action
                -- Action executed before every end-of-file semantic action
                -- (i.e. <<EOF>>) when '%option pre-eof-action' has been specified.
                -- (Note: this routine can be redefined in descendant classes.
                -- Default: do nothing.)

        post_eof_action
                -- Action executed after every end-of-file semantic action
                -- (i.e. <<EOF>>) when '%option post-eof-action' has been specified.
                -- (Note: this routine can be redefined in descendant classes.
                -- Default: do nothing.)

        default_action
                -- Action executed when default rule is matched.
                -- (Note: this routine can be redefined in descendant classes.
                -- Default: print last character read to standard output.)

    feature -- Error handling

        fatal_error (a_message: STRING)
                -- A fatal error occurred.
                -- Print a_message.
            require
                a_message_not_void: a_message /= Void

    feature -- Debugging

        print_last_token
                -- Print to standard error debug information
                -- about the last token read. Can be redefined
                -- in descendant classes to print more information.
                -- (Called at the end of read_token when compiled
                -- with 'debug ("GELEX")' enabled).

    invariant

        input_buffer_not_void: input_buffer /= Void
        valid_start_condition: valid_start_condition (start_condition)

    end