# ==================================================================================================================== #
#            __     ___   _ ____  _     ____                                                                           #
#  _ __  _   \ \   / / | | |  _ \| |   |  _ \ __ _ _ __ ___  ___ _ __                                                  #
# | '_ \| | | \ \ / /| |_| | | | | |   | |_) / _` | '__/ __|/ _ \ '__|                                                 #
# | |_) | |_| |\ V / |  _  | |_| | |___|  __/ (_| | |  \__ \  __/ |                                                    #
# | .__/ \__, | \_/  |_| |_|____/|_____|_|   \__,_|_|  |___/\___|_|                                                    #
# |_|    |___/                                                                                                         #
# ==================================================================================================================== #
# Authors:                                                                                                             #
#   Patrick Lehmann                                                                                                    #
#                                                                                                                      #
# License:                                                                                                             #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany                                                            #
# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany                                                               #
#                                                                                                                      #
# Licensed under the Apache License, Version 2.0 (the "License");                                                      #
# you may not use this file except in compliance with the License.                                                     #
# You may obtain a copy of the License at                                                                              #
#                                                                                                                      #
#   http://www.apache.org/licenses/LICENSE-2.0                                                                         #
#                                                                                                                      #
# Unless required by applicable law or agreed to in writing, software                                                  #
# distributed under the License is distributed on an "AS IS" BASIS,                                                    #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                                             #
# See the License for the specific language governing permissions and                                                  #
# limitations under the License.                                                                                       #
# ==================================================================================================================== #
#
from pyTooling.Decorators             import export

from pyVHDLParser.Blocks.Type.ResolutionIndication import RecordResolutionIndicationBlock, \
	SimpleResolutionIndicationBlock
from pyVHDLParser.Token               import SpaceToken, LinebreakToken, CommentToken, WordToken, ExtendedIdentifier, MultiLineCommentToken
from pyVHDLParser.Token               import IndentationToken, SingleLineCommentToken, CharacterToken, FusedCharacterToken
from pyVHDLParser.Token.Keywords      import InKeyword, VariableAssignmentKeyword, OutKeyword, InoutKeyword, BufferKeyword, LinkageKeyword
from pyVHDLParser.Token.Keywords      import IdentifierToken, BoundaryToken, DelimiterToken
from pyVHDLParser.Blocks              import Block, TokenToBlockParser, CommentBlock, BlockParserException
from pyVHDLParser.Blocks.Common       import LinebreakBlock, WhitespaceBlock
from pyVHDLParser.Blocks.Expression   import ExpressionBlockEndedByCharORClosingRoundBracket


@export
class InterfaceObjectBlock(Block):
	OBJECT_KIND =     ""
	MODES =           {}
	EXPRESSION =      None
	DELIMITER_BLOCK = None

	@classmethod
	def stateWhitespace1(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, WordToken):
			parserState.NewToken =      IdentifierToken(fromExistingToken=token)
			parserState.NextState =     cls.stateObjectName
			return
		elif isinstance(token, ExtendedIdentifier):
			parserState.NextState =     cls.stateObjectName
			return
		elif isinstance(token, LinebreakToken):
			if not (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
				_ =                       LinebreakBlock(parserState.NewBlock, token)
			else:
				parserState.NewBlock =    LinebreakBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, CommentToken):
			parserState.NewBlock =      CommentBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, IndentationToken) and isinstance(token.PreviousToken, (LinebreakToken, SingleLineCommentToken)):
			return
		elif isinstance(token, SpaceToken) and (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
			parserState.NewToken =      BoundaryToken(fromExistingToken=token)
			parserState.NewBlock =      WhitespaceBlock(parserState.LastBlock, parserState.NewToken)
			parserState.TokenMarker =   None
			return

		raise BlockParserException("Expected interface {0} name (identifier).".format(cls.OBJECT_KIND), token)

	@classmethod
	def stateObjectName(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, SpaceToken):
			parserState.NewToken =    BoundaryToken(fromExistingToken=token)
			parserState.NextState =   cls.stateWhitespace2
			return
		elif isinstance(token, CharacterToken) and (token == ":"):
			parserState.NewToken =    DelimiterToken(fromExistingToken=token)
			parserState.NextState =   cls.stateColon1
			return
		elif isinstance(token, (LinebreakToken, CommentToken)):
			block =                   LinebreakBlock if isinstance(token, LinebreakToken) else CommentBlock
			parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                       block(parserState.NewBlock, token)
			parserState.TokenMarker = None
			parserState.NextState =   cls.stateWhitespace2
			return

		raise BlockParserException("Expected whitespace after interface {0} name.".format(cls.OBJECT_KIND), token)

	@classmethod
	def stateWhitespace2(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, CharacterToken) and (token == ":"):
			parserState.NewToken =      DelimiterToken(fromExistingToken=token)
			parserState.NextState =     cls.stateColon1
			return
		elif isinstance(token, LinebreakToken):
			if not (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
				_ =                       LinebreakBlock(parserState.NewBlock, token)
			else:
				parserState.NewBlock =    LinebreakBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, CommentToken):
			parserState.NewBlock =      CommentBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, IndentationToken) and isinstance(token.PreviousToken, (LinebreakToken, SingleLineCommentToken)):
			return
		elif isinstance(token, SpaceToken) and (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
			parserState.NewToken =      BoundaryToken(fromExistingToken=token)
			parserState.NewBlock =      WhitespaceBlock(parserState.LastBlock, parserState.NewToken)
			parserState.TokenMarker =   None
			return

		raise BlockParserException("Expected ':' after interface {0} name.".format(cls.OBJECT_KIND), token)

	@classmethod
	def stateColon1(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, WordToken):
			try:
				parserState.NewToken =    cls.MODES[token.Value.lower()](fromExistingToken=token)
				parserState.NextState =   cls.stateModeKeyword
				return
			except KeyError:
				parserState.NewToken =    IdentifierToken(fromExistingToken=token)
				parserState.NextState =   cls.stateSubtypeIndication
				return
		elif isinstance(token, SpaceToken):
			parserState.NewToken =    BoundaryToken(fromExistingToken=token)
			parserState.NextState =   cls.stateWhitespace3
			return
		elif isinstance(token, (LinebreakToken, CommentToken)):
			block =                   LinebreakBlock if isinstance(token, LinebreakToken) else CommentBlock
			parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                       block(parserState.NewBlock, token)
			parserState.TokenMarker = None
			parserState.NextState =   cls.stateWhitespace3
			return

		raise BlockParserException("Expected subtype indication or whitespace after colon.", token)

	@classmethod
	def stateWhitespace3(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, WordToken):
			tokenValue = token.Value.lower()
			try:
				parserState.NewToken =    cls.MODES[tokenValue](fromExistingToken=token)
				parserState.NextState =   cls.stateModeKeyword
				return
			except KeyError:
				parserState.NewToken =    IdentifierToken(fromExistingToken=token)
				parserState.NextState =   cls.stateSubtypeIndication
				return
		elif isinstance(token, ExtendedIdentifier):
			parserState.NextState =     cls.stateSubtypeIndication
			return
		elif isinstance(token, LinebreakToken):
			if not (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
				_ =                       LinebreakBlock(parserState.NewBlock, token)
			else:
				parserState.NewBlock =    LinebreakBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, CommentToken):
			parserState.NewBlock =      CommentBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, IndentationToken) and isinstance(token.PreviousToken, (LinebreakToken, SingleLineCommentToken)):
			return
		elif isinstance(token, SpaceToken) and (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
			parserState.NewToken =      BoundaryToken(fromExistingToken=token)
			parserState.NewBlock =      WhitespaceBlock(parserState.LastBlock, parserState.NewToken)
			parserState.TokenMarker =   None
			return

		raise BlockParserException("Expected subtype indication or keyword IN.", token)

	@classmethod
	def stateModeKeyword(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, SpaceToken):
			parserState.NextState =   cls.stateSubtypeIndication
			parserState.PushState =   SimpleResolutionIndicationBlock.stateResolutionFunction
			return
		elif isinstance(token, CharacterToken) and (token == "("):
			parserState.NextState =   cls.stateSubtypeIndication
			parserState.PushState =   RecordResolutionIndicationBlock.stateOpeningParentesis
			return
		elif isinstance(token, (LinebreakToken, CommentToken)):
			block =                   LinebreakBlock if isinstance(token, LinebreakToken) else CommentBlock
			parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                       block(parserState.NewBlock, token)
			parserState.TokenMarker = None
			parserState.NextState =   cls.stateWhitespace4
			return

		raise BlockParserException("Expected whitespace after keyword CONSTANT.", token)

	@classmethod
	def stateWhitespace4(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, WordToken):
			parserState.NewToken =      IdentifierToken(fromExistingToken=token)
			parserState.NextState =     cls.stateSubtypeIndication
			return
		elif isinstance(token, ExtendedIdentifier):
			parserState.NextState =     cls.stateSubtypeIndication
			return
		elif isinstance(token, LinebreakToken):
			if not (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
				_ =                       LinebreakBlock(parserState.NewBlock, token)
			else:
				parserState.NewBlock =    LinebreakBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, CommentToken):
			parserState.NewBlock =      CommentBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, IndentationToken) and isinstance(token.PreviousToken, (LinebreakToken, SingleLineCommentToken)):
			return
		elif isinstance(token, SpaceToken) and (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
			parserState.NewToken =      BoundaryToken(fromExistingToken=token)
			parserState.NewBlock =      WhitespaceBlock(parserState.LastBlock, parserState.NewToken)
			parserState.TokenMarker =   None
			return

		raise BlockParserException("Expected subtype indication (name).", token)

	@classmethod
	def stateSubtypeIndication(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, FusedCharacterToken) and (token == ":="):
			parserState.NewToken =      VariableAssignmentKeyword(fromExistingToken=token)
			parserState.NewBlock =      cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken)
			parserState.NextState =     cls.DELIMITER_BLOCK.stateItemDelimiter
			parserState.PushState =     cls.EXPRESSION.stateBeforeExpression
			parserState.TokenMarker =   None
			parserState.Counter =       0
			return
		elif isinstance(token, CharacterToken):
			if token == '(':
			# 	parserState.NewToken = BoundaryToken(fromExistingToken=token)
			# 	parserState.NewBlock = cls(parserState.LastBlock, parserState.TokenMarker,
			# 														 endToken=parserState.NewToken.PreviousToken)
			# 	parserState.TokenMarker = parserState.NewToken
			# 	parserState.NextState = LoopBlock.stateSequentialRegion
			# 	parserState.PushState = ExpressionBlockEndedByLoopORToORDownto.stateExpression
			# 	return
			# elif token == ';':
				parserState.NewToken =    DelimiterToken(fromExistingToken=token)
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken.PreviousToken)
				_ =                       cls.DELIMITER_BLOCK(parserState.NewBlock, parserState.NewToken)
				parserState.Pop()
				return
			elif token == ')':
				parserState.NewToken =    BoundaryToken(fromExistingToken=token)
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken.PreviousToken)
				parserState.Pop(2)
				parserState.TokenMarker = parserState.NewToken
				return
		elif isinstance(token, SpaceToken):
			parserState.NewToken =    BoundaryToken(fromExistingToken=token)
			parserState.NextState =   cls.stateWhitespace5
			return
		elif isinstance(token, (LinebreakToken, CommentToken)):
			block =                   LinebreakBlock if isinstance(token, LinebreakToken) else CommentBlock
			parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                       block(parserState.NewBlock, token)
			parserState.TokenMarker = None
			parserState.NextState =   cls.stateWhitespace5
			return

		raise BlockParserException("Expected ';', ':=' or whitespace after subtype indication.", token)

	@classmethod
	def stateWhitespace5(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, FusedCharacterToken) and (token == ":="):
			parserState.NewToken =      VariableAssignmentKeyword(fromExistingToken=token)
			parserState.NewBlock =      cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken)
			parserState.NextState =     cls.DELIMITER_BLOCK.stateItemDelimiter
			parserState.PushState =     cls.EXPRESSION.stateBeforeExpression
			parserState.Counter =       0
			return
		elif isinstance(token, CharacterToken):
			if token == ';':
				parserState.NewToken =    DelimiterToken(fromExistingToken=token)
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken.PreviousToken)
				_ =                       cls.DELIMITER_BLOCK(parserState.NewBlock, parserState.NewToken)
				parserState.Pop()
				return
			elif token == ')':
				parserState.NewToken =    BoundaryToken(fromExistingToken=token)
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken.PreviousToken)
				parserState.Pop(2)
				parserState.TokenMarker = parserState.NewToken
				return
		elif isinstance(token, LinebreakToken):
			if not (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
				_ =                       LinebreakBlock(parserState.NewBlock, token)
			else:
				parserState.NewBlock =    LinebreakBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, CommentToken):
			parserState.NewBlock =      cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                         CommentBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, IndentationToken) and isinstance(token.PreviousToken, (LinebreakToken, SingleLineCommentToken)):
			return
		elif isinstance(token, SpaceToken) and (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
			parserState.NewToken =      BoundaryToken(fromExistingToken=token)
			parserState.NewBlock =      WhitespaceBlock(parserState.LastBlock, parserState.NewToken)
			parserState.TokenMarker =   None
			return

		raise BlockParserException("Expected ';' or ':='.", token)


@export
class InterfaceConstantBlock(InterfaceObjectBlock):
	OBJECT_KIND = "constant"
	MODES =       {
		"in": InKeyword
	}

	@classmethod
	def stateConstantKeyword(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, SpaceToken):
			parserState.NextState =   cls.stateWhitespace1
			return
		elif isinstance(token, (LinebreakToken, CommentToken)):
			block =                   LinebreakBlock if isinstance(token, LinebreakToken) else CommentBlock
			parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                       block(parserState.NewBlock, token)
			parserState.TokenMarker = None
			parserState.NextState =   cls.stateWhitespace1
			return

		raise BlockParserException("Expected whitespace after keyword CONSTANT.", token)


@export
class InterfaceVariableBlock(InterfaceObjectBlock):
	OBJECT_KIND = "variable"
	MODES =       {
		"in":    InKeyword,
		"out":   OutKeyword,
		"inout": InoutKeyword
	}

	@classmethod
	def stateVariableKeyword(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, SpaceToken):
			parserState.NextState =   cls.stateWhitespace1
			return
		elif isinstance(token, (LinebreakToken, CommentToken)):
			block =                   LinebreakBlock if isinstance(token, LinebreakToken) else CommentBlock
			parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                       block(parserState.NewBlock, token)
			parserState.TokenMarker = None
			parserState.NextState =   cls.stateWhitespace1
			return

		raise BlockParserException("Expected whitespace after keyword VARIABLE.", token)


@export
class InterfaceSignalBlock(InterfaceObjectBlock):
	OBJECT_KIND = "signal"
	MODES =       {
		"in":       InKeyword,
		"out":      OutKeyword,
		"inout":    InoutKeyword,
		"buffer":   BufferKeyword,
		"linkage":  LinkageKeyword
	}

	@classmethod
	def stateSignalKeyword(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, SpaceToken):
			parserState.NextState =   cls.stateWhitespace1
			return
		elif isinstance(token, (LinebreakToken, CommentToken)):
			block =                   LinebreakBlock if isinstance(token, LinebreakToken) else CommentBlock
			parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                       block(parserState.NewBlock, token)
			parserState.TokenMarker = None
			parserState.NextState =   cls.stateWhitespace1
			return

		raise BlockParserException("Expected whitespace after keyword SIGNAL.", token)


@export
class InterfaceTypeBlock(Block):
	DELIMITER_BLOCK = None

	@classmethod
	def stateTypeKeyword(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, SpaceToken):
			parserState.NextState =   cls.stateWhitespace1
			return
		elif isinstance(token, (LinebreakToken, CommentToken)):
			block =                   LinebreakBlock if isinstance(token, LinebreakToken) else CommentBlock
			parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                       block(parserState.NewBlock, token)
			parserState.TokenMarker = None
			parserState.NextState =   cls.stateWhitespace1
			return

		raise BlockParserException("Expected whitespace after keyword CONSTANT.", token)

	@classmethod
	def stateWhitespace1(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, WordToken):
			parserState.NewToken =      IdentifierToken(fromExistingToken=token)
			parserState.NextState =     cls.stateTypeName
			return
		elif isinstance(token, ExtendedIdentifier):
			parserState.NextState =     cls.stateTypeName
			return
		elif isinstance(token, LinebreakToken):
			if not (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
				_ =                       LinebreakBlock(parserState.NewBlock, token)
			else:
				parserState.NewBlock =    LinebreakBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, CommentToken):
			parserState.NewBlock =      CommentBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, IndentationToken) and isinstance(token.PreviousToken, (LinebreakToken, SingleLineCommentToken)):
			return
		elif isinstance(token, SpaceToken) and (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
			parserState.NewToken =      BoundaryToken(fromExistingToken=token)
			parserState.NewBlock =      WhitespaceBlock(parserState.LastBlock, parserState.NewToken)
			parserState.TokenMarker =   None
			return

		raise BlockParserException("Expected interface type name (identifier).", token)

	@classmethod
	def stateTypeName(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, CharacterToken):
			if token == ';':
				parserState.NewToken =    DelimiterToken(fromExistingToken=token)
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken.PreviousToken)
				_ =                       cls.DELIMITER_BLOCK(parserState.NewBlock, parserState.NewToken)
				parserState.Pop()
				return
			elif token == ')':
				parserState.NewToken =    BoundaryToken(fromExistingToken=token)
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken.PreviousToken)
				parserState.Pop(2)
				parserState.TokenMarker = parserState.NewToken
				return
		elif isinstance(token, SpaceToken):
			parserState.NewToken =    BoundaryToken(fromExistingToken=token)
			parserState.NextState =   cls.stateWhitespace2
			return
		elif isinstance(token, (LinebreakToken, CommentToken)):
			block =                   LinebreakBlock if isinstance(token, LinebreakToken) else CommentBlock
			parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
			_ =                       block(parserState.NewBlock, token)
			parserState.TokenMarker = None
			parserState.NextState =   cls.stateWhitespace2
			return

		raise BlockParserException("Expected ';', ')' or whitespace after interface type name.", token)

	@classmethod
	def stateWhitespace2(cls, parserState: TokenToBlockParser):
		token = parserState.Token
		if isinstance(token, CharacterToken):
			if token == ';':
				parserState.NewToken =    DelimiterToken(fromExistingToken=token)
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken.PreviousToken)
				_ =                       cls.DELIMITER_BLOCK(parserState.NewBlock, parserState.NewToken)
				parserState.Pop()
				return
			elif token == ')':
				parserState.NewToken =    BoundaryToken(fromExistingToken=token)
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=parserState.NewToken.PreviousToken)
				parserState.Pop(2)
				parserState.TokenMarker = parserState.NewToken
				return
		elif isinstance(token, LinebreakToken):
			if not (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
				parserState.NewBlock =    cls(parserState.LastBlock, parserState.TokenMarker, endToken=token.PreviousToken, multiPart=True)
				_ =                       LinebreakBlock(parserState.NewBlock, token)
			else:
				parserState.NewBlock =    LinebreakBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, CommentToken):
			parserState.NewBlock =      CommentBlock(parserState.LastBlock, token)
			parserState.TokenMarker =   None
			return
		elif isinstance(token, IndentationToken) and isinstance(token.PreviousToken, (LinebreakToken, SingleLineCommentToken)):
			return
		elif isinstance(token, SpaceToken) and (isinstance(parserState.LastBlock, CommentBlock) and isinstance(parserState.LastBlock.StartToken, MultiLineCommentToken)):
			parserState.NewToken =      BoundaryToken(fromExistingToken=token)
			parserState.NewBlock =      WhitespaceBlock(parserState.LastBlock, parserState.NewToken)
			parserState.TokenMarker =   None
			return

		raise BlockParserException("Expected ';' or ')'.", token)
