view Implab/Formats/InputScanner.cs @ 228:6fa235c5a760 v2

Rewritten JsonScanner, JsonParser, fixed naming style
author cin
date Tue, 12 Sep 2017 01:19:12 +0300
parents
children 5f7a3e1d32b9
line wrap: on
line source

using Implab.Automaton;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Implab.Formats {
    public class InputScanner<TTag> {
        readonly TTag[] m_tags;
        readonly int m_initialState;
        readonly int[,] m_dfa;
        readonly CharMap m_alphabet;
        readonly bool[] m_final;

        int m_position;
        int m_state;

        public InputScanner(int[,] dfaTable, bool[] finalStates, TTag[] tags, int initialState, CharMap alphabet) {
            Safe.ArgumentNotNull(dfaTable, nameof(dfaTable));
            Safe.ArgumentNotNull(finalStates, nameof(finalStates));
            Safe.ArgumentNotNull(tags, nameof(tags));
            Safe.ArgumentNotNull(alphabet, nameof(alphabet));

            m_dfa = dfaTable;
            m_final = finalStates;
            m_tags = tags;
            m_initialState = initialState;
            m_alphabet = alphabet;
        }

        public TTag Tag {
            get {
                return m_tags[m_state];
            }
        }

        public int Position {
            get {
                return m_position;
            }
        }

        public bool IsFinal {
            get {
                return m_final[m_state];
            }
        }

        public void Reset() {
            m_state = m_initialState;
        }

        public InputScanner<TTag> Clone() {
            var clone = new InputScanner<TTag>(m_dfa, m_final, m_tags, m_initialState, m_alphabet);
            clone.m_state = m_state;
            clone.m_position = m_position;
            return clone;
        }

        public bool Scan(char[] data, int offset, int length) {
            if (length <= 0) {
                m_position = offset;
                return false; // EOF
            }

            var max = offset + length;
            var next = m_state;

            while(offset < max) {
                next = m_dfa[next, m_alphabet.Translate(data[offset])];
                if (next == AutomatonConst.UNREACHABLE_STATE) {
                    // scanner stops on the next position after last recognized symbol
                    m_position = offset;
                    return false;
                }
                m_state = next;
                offset++;
            }
            m_position = offset;
            return true;
        }
    }
}