public LexToken nextToken() throws LexException
	{
		while (Character.isWhitespace(ch))
		{
			rdCh();
		}

		int tokline = linecount;
		int tokpos = charpos;
		int tokOffset = offset;
		VDMToken type = null;
		last = null;
		boolean rdch = true;

		switch (ch)
		{
			case EOF:
				type = VDMToken.EOF;
				break;

			case '-':
				if (rdCh() == '-')
				{
					while (ch != '\n' && ch != EOF)
					{
						rdCh();
					}

					return nextToken();
				} else if (ch == '>')
				{
					type = VDMToken.ARROW;
				} else
				{
					rdch = false;
					type = VDMToken.MINUS;
				}
				break;

			case '+':
				if (rdCh() == '>')
				{
					type = VDMToken.TOTAL_FUNCTION;
				} else if (ch == '+')
				{
					type = VDMToken.PLUSPLUS;
				} else
				{
					rdch = false;
					type = VDMToken.PLUS;
				}
				break;

			case ':':
				if (rdCh() == '-')
				{
					if (rdCh() == '>')
					{
						type = VDMToken.RANGERESBY;
					} else
					{
						rdch = false;
						type = VDMToken.EQABST;
					}
				} else if (ch == '>')
				{
					type = VDMToken.RANGERESTO;
				} else if (ch == '=')
				{
					type = VDMToken.ASSIGN;
				} else if (ch == ':')
				{
					type = VDMToken.COLONCOLON;
				} else
				{
					rdch = false;
					type = VDMToken.COLON;
				}
				break;

			case '|':
				if (rdCh() == '-')
				{
					if (rdCh() == '>')
					{
						type = VDMToken.MAPLET;
					} else
					{
						throwMessage(1002, "Expecting '|->'");
					}
				} else if (ch == '|')
				{
					type = VDMToken.PIPEPIPE;
				} else
				{
					rdch = false;
					type = VDMToken.PIPE;
				}
				break;

			case '.':
				if (rdCh() == '.')
				{
					if (rdCh() == '.')
					{
						type = VDMToken.RANGE;
						break;
					}

					throwMessage(1003, "Expecting '...'");
				} else
				{
					rdch = false;
					type = VDMToken.POINT;
				}
				break;

			case '=':
				if (rdCh() == '=')
				{
					if (rdCh() == '>')
					{
						type = VDMToken.OPDEF;
					} else
					{
						rdch = false;
						type = VDMToken.EQUALSEQUALS;
					}
				} else if (ch == '>')
				{
					type = VDMToken.IMPLIES;
				} else
				{
					rdch = false;
					type = VDMToken.EQUALS;
				}
				break;

			case '*':
				if (rdCh() == '*')
				{
					type = VDMToken.STARSTAR;
				} else
				{
					rdch = false;
					type = VDMToken.TIMES;
				}
				break;

			case '<':
				push();
				if (rdCh() == '=')
				{
					unpush();
					if (rdCh() == '>')
					{
						type = VDMToken.EQUIVALENT;
					} else
					{
						rdch = false;
						type = VDMToken.LE;
					}
				} else if (ch == ':')
				{
					unpush();
					type = VDMToken.DOMRESTO;
				} else if (ch == '-')
				{
					unpush();
					if (rdCh() == ':')
					{
						type = VDMToken.DOMRESBY;
					} else
					{
						throwMessage(1004, "Expecting '<-:'");
					}
				} else if (ch == '>')
				{
					unpush();
					type = VDMToken.NE;
				} else if (startOfName(ch))
				{
					// <QuoteLiteral> or <x
					String name = rdIdentifier();

					if (ch == '>')
					{
						unpush();
						last = new LexQuoteToken(name, new LexLocation(file, currentModule, tokline, tokpos, linecount, charpos + 1, tokOffset, offset + 1));
						// location(tokline, tokpos, tokOffset, offset));
						type = VDMToken.QUOTE;
					} else
					{
						pop();
						type = VDMToken.LT;
					}
				} else
				{
					unpush();
					rdch = false;
					type = VDMToken.LT;
				}
				break;

			case '>':
				if (rdCh() == '=')
				{
					type = VDMToken.GE;
				} else
				{
					rdch = false;
					type = VDMToken.GT;
				}
				break;

			case '"':
				rdQuotedCh();
				StringBuffer msg = new StringBuffer();

				while ((ch != '"' || quotedQuote == true) && ch != EOF)
				{
					msg.append(ch);
					rdQuotedCh();
				}

				checkFor('\"', 1005, "Expecting close double quote");
				last = new LexStringToken(msg.toString(), location(tokline, tokpos, tokOffset, offset));
				rdch = false;
				break;

			case '\'':
				last = new LexCharacterToken(rdQuotedCh(), location(tokline, tokpos, tokOffset, offset));
				rdCh();
				checkFor('\'', 1006, "Expecting close quote after character");
				rdch = false;
				break;

			case '#':
				if (Character.isLetter(rdCh()))
				{
					StringBuilder tag = new StringBuilder();
					tag.append('#');

					do
					{
						tag.append(ch);
						rdCh();
					} while (Character.isLetter(ch));

					type = VDMToken.lookup(tag.toString(), dialect);

					if (type == null)
					{
						throwMessage(1007, "Unexpected tag after '#'");
					}

					rdch = false;
				} else
				{
					type = VDMToken.HASH;
					rdch = false;
				}
				break;

			case '/':
				if (rdCh() == '*') // Block comments
				{
					while (ch != '/' && ch != EOF)
					{
						while (ch != '*' && ch != EOF)
						{
							rdCh();
						}

						if (ch == EOF)
						{
							throwMessage(1011, tokline, tokpos, "Unterminated block comment");
						}

						rdCh();
					}

					rdCh();
					return nextToken();
				} else
				{
					type = VDMToken.DIVIDE;
					rdch = false;
				}
				break;

			case ',':
				type = VDMToken.COMMA;
				break;
			case ';':
				type = VDMToken.SEMICOLON;
				break;
			case '?':
				type = VDMToken.QMARK;
				break;
			case '@':
				type = VDMToken.AT;
				break;
			case '&':
				type = VDMToken.AMPERSAND;
				break;
			case '^':
				type = VDMToken.CONCATENATE;
				break;
			case '(':
				type = VDMToken.BRA;
				break;
			case ')':
				type = VDMToken.KET;
				break;
			case '{':
				type = VDMToken.SET_OPEN;
				break;
			case '}':
				type = VDMToken.SET_CLOSE;
				break;
			case '[':
				type = VDMToken.SEQ_OPEN;
				break;
			case ']':
				type = VDMToken.SEQ_CLOSE;
				break;
			case '\\':
				type = VDMToken.SETDIFF;
				break;

			case '0':
				push();
				rdCh();

				if (ch == 'x' || ch == 'X')
				{
					unpush();
					rdCh();
					String decimal = String.valueOf(Long.parseLong(rdNumber(16), 16));
					last = new LexIntegerToken(decimal, location(tokline, tokpos, tokOffset, offset));
				}
				else
				{
					pop();
					last = rdReal(tokline, tokpos, tokOffset);
				}

				rdch = false;
				break;

			default:
				if (ch >= '0' && ch <= '9')
				{
					last = rdReal(tokline, tokpos, tokOffset);
					rdch = false;
				} else if (startOfName(ch))
				{
					List<String> name = rdName(); // module`name parts
					rdch = false;

					switch (name.size())
					{
						case 1:
							type = VDMToken.lookup(name.get(0), dialect);

							if (type == null)
							{
								last = new LexIdentifierToken(name.get(0), ch == '~', location(tokline, tokpos, tokOffset, offset));
								rdch = ch == '~';
							} else
							{
								switch (type)
								{
									case TRUE:
									case FALSE:
										last = new LexBooleanToken(type, location(tokline, tokpos, tokOffset, offset));
										break;

									default:
										last = new LexKeywordToken(type, location(tokline, tokpos, tokOffset, offset));
										break;
								}
							}
							break;

						case 2:
							last = new LexNameToken(name.get(0), name.get(1), location(tokline, tokpos, tokOffset, offset), false, true);
							break;

						default:
							throwMessage(1008, "Malformed module`name");
					}
				} else
				{
					char badch = ch;
					rdCh();
					throwMessage(1009, "Unexpected character '" + badch
							+ "' (code 0x" + Integer.toHexString(badch) + ")");
				}
				break;
		}

		if (rdch)
		{
			rdCh();
		}

		if (last == null)
		{
			last = new LexKeywordToken(type, location(tokline, tokpos, tokOffset, offset));
		}

		tokensread++;
		return last;
	}
public LexToken nextToken ( ) throws LexException { while ( Character . isWhitespace ( ch ) ) { rdCh ( ) ; } int tokline = linecount ; int tokpos = charpos ; int tokOffset = offset ; VDMToken type = null ; last = null ; boolean rdch = true ; switch ( ch ) { case EOF : type = VDMToken . EOF ; break ; case '-' : if ( rdCh ( ) == '-' ) { while ( ch != '\n' && ch != EOF ) { rdCh ( ) ; } return nextToken ( ) ; } else if ( ch == '>' ) { type = VDMToken . ARROW ; } else { rdch = false ; type = VDMToken . MINUS ; } break ; case '+' : if ( rdCh ( ) == '>' ) { type = VDMToken . TOTAL_FUNCTION ; } else if ( ch == '+' ) { type = VDMToken . PLUSPLUS ; } else { rdch = false ; type = VDMToken . PLUS ; } break ; case ':' : if ( rdCh ( ) == '-' ) { if ( rdCh ( ) == '>' ) { type = VDMToken . RANGERESBY ; } else { rdch = false ; type = VDMToken . EQABST ; } } else if ( ch == '>' ) { type = VDMToken . RANGERESTO ; } else if ( ch == '=' ) { type = VDMToken . ASSIGN ; } else if ( ch == ':' ) { type = VDMToken . COLONCOLON ; } else { rdch = false ; type = VDMToken . COLON ; } break ; case '|' : if ( rdCh ( ) == '-' ) { if ( rdCh ( ) == '>' ) { type = VDMToken . MAPLET ; } else { throwMessage ( 1002 , "Expecting '|->'" ) ; } } else if ( ch == '|' ) { type = VDMToken . PIPEPIPE ; } else { rdch = false ; type = VDMToken . PIPE ; } break ; case '.' : if ( rdCh ( ) == '.' ) { if ( rdCh ( ) == '.' ) { type = VDMToken . RANGE ; break ; } throwMessage ( 1003 , "Expecting '...'" ) ; } else { rdch = false ; type = VDMToken . POINT ; } break ; case '=' : if ( rdCh ( ) == '=' ) { if ( rdCh ( ) == '>' ) { type = VDMToken . OPDEF ; } else { rdch = false ; type = VDMToken . EQUALSEQUALS ; } } else if ( ch == '>' ) { type = VDMToken . IMPLIES ; } else { rdch = false ; type = VDMToken . EQUALS ; } break ; case '*' : if ( rdCh ( ) == '*' ) { type = VDMToken . STARSTAR ; } else { rdch = false ; type = VDMToken . TIMES ; } break ; case '<' : push ( ) ; if ( rdCh ( ) == '=' ) { unpush ( ) ; if ( rdCh ( ) == '>' ) { type = VDMToken . EQUIVALENT ; } else { rdch = false ; type = VDMToken . LE ; } } else if ( ch == ':' ) { unpush ( ) ; type = VDMToken . DOMRESTO ; } else if ( ch == '-' ) { unpush ( ) ; if ( rdCh ( ) == ':' ) { type = VDMToken . DOMRESBY ; } else { throwMessage ( 1004 , "Expecting '<-:'" ) ; } } else if ( ch == '>' ) { unpush ( ) ; type = VDMToken . NE ; } else if ( startOfName ( ch ) ) { String name = rdIdentifier ( ) ; if ( ch == '>' ) { unpush ( ) ; last = new LexQuoteToken ( name , new LexLocation ( file , currentModule , tokline , tokpos , linecount , charpos + 1 , tokOffset , offset + 1 ) ) ; type = VDMToken . QUOTE ; } else { pop ( ) ; type = VDMToken . LT ; } } else { unpush ( ) ; rdch = false ; type = VDMToken . LT ; } break ; case '>' : if ( rdCh ( ) == '=' ) { type = VDMToken . GE ; } else { rdch = false ; type = VDMToken . GT ; } break ; case '"' : rdQuotedCh ( ) ; StringBuffer msg = new StringBuffer ( ) ; while ( ( ch != '"' || quotedQuote == true ) && ch != EOF ) { msg . append ( ch ) ; rdQuotedCh ( ) ; } checkFor ( '\"' , 1005 , "Expecting close double quote" ) ; last = new LexStringToken ( msg . toString ( ) , location ( tokline , tokpos , tokOffset , offset ) ) ; rdch = false ; break ; case '\'' : last = new LexCharacterToken ( rdQuotedCh ( ) , location ( tokline , tokpos , tokOffset , offset ) ) ; rdCh ( ) ; checkFor ( '\'' , 1006 , "Expecting close quote after character" ) ; rdch = false ; break ; case '#' : if ( Character . isLetter ( rdCh ( ) ) ) { StringBuilder tag = new StringBuilder ( ) ; tag . append ( '#' ) ; do { tag . append ( ch ) ; rdCh ( ) ; } while ( Character . isLetter ( ch ) ) ; type = VDMToken . lookup ( tag . toString ( ) , dialect ) ; if ( type == null ) { throwMessage ( 1007 , "Unexpected tag after '#'" ) ; } rdch = false ; } else { type = VDMToken . HASH ; rdch = false ; } break ; case '/' : if ( rdCh ( ) == '*' ) { while ( ch != '/' && ch != EOF ) { while ( ch != '*' && ch != EOF ) { rdCh ( ) ; } if ( ch == EOF ) { throwMessage ( 1011 , tokline , tokpos , "Unterminated block comment" ) ; } rdCh ( ) ; } rdCh ( ) ; return nextToken ( ) ; } else { type = VDMToken . DIVIDE ; rdch = false ; } break ; case ',' : type = VDMToken . COMMA ; break ; case ';' : type = VDMToken . SEMICOLON ; break ; case '?' : type = VDMToken . QMARK ; break ; case '@' : type = VDMToken . AT ; break ; case '&' : type = VDMToken . AMPERSAND ; break ; case '^' : type = VDMToken . CONCATENATE ; break ; case '(' : type = VDMToken . BRA ; break ; case ')' : type = VDMToken . KET ; break ; case '{' : type = VDMToken . SET_OPEN ; break ; case '}' : type = VDMToken . SET_CLOSE ; break ; case '[' : type = VDMToken . SEQ_OPEN ; break ; case ']' : type = VDMToken . SEQ_CLOSE ; break ; case '\\' : type = VDMToken . SETDIFF ; break ; case '0' : push ( ) ; rdCh ( ) ; if ( ch == 'x' || ch == 'X' ) { unpush ( ) ; rdCh ( ) ; String decimal = String . valueOf ( Long . parseLong ( rdNumber ( 16 ) , 16 ) ) ; last = new LexIntegerToken ( decimal , location ( tokline , tokpos , tokOffset , offset ) ) ; } else { pop ( ) ; last = rdReal ( tokline , tokpos , tokOffset ) ; } rdch = false ; break ; default : if ( ch >= '0' && ch <= '9' ) { last = rdReal ( tokline , tokpos , tokOffset ) ; rdch = false ; } else if ( startOfName ( ch ) ) { List < String > name = rdName ( ) ; rdch = false ; switch ( name . size ( ) ) { case 1 : type = VDMToken . lookup ( name . get ( 0 ) , dialect ) ; if ( type == null ) { last = new LexIdentifierToken ( name . get ( 0 ) , ch == '~' , location ( tokline , tokpos , tokOffset , offset ) ) ; rdch = ch == '~' ; } else { switch ( type ) { case TRUE : case FALSE : last = new LexBooleanToken ( type , location ( tokline , tokpos , tokOffset , offset ) ) ; break ; default : last = new LexKeywordToken ( type , location ( tokline , tokpos , tokOffset , offset ) ) ; break ; } } break ; case 2 : last = new LexNameToken ( name . get ( 0 ) , name . get ( 1 ) , location ( tokline , tokpos , tokOffset , offset ) , false , true ) ; break ; default : throwMessage ( 1008 , "Malformed module`name" ) ; } } else { char badch = ch ; rdCh ( ) ; throwMessage ( 1009 , "Unexpected character '" + badch + "' (code 0x" + Integer . toHexString ( badch ) + ")" ) ; } break ; } if ( rdch ) { rdCh ( ) ; } if ( last == null ) { last = new LexKeywordToken ( type , location ( tokline , tokpos , tokOffset , offset ) ) ; } tokensread ++ ; return last ; }
Read the next complete token from the input stream. Whitespace is skipped, and the start line and position of the
token are noted from the current stream position. Then the next character to process is used to drive a large
switch statement to produce the right {@link VDMToken}. The lastToken field is updated and the result returned.

@return The next token, or a LexToken of type EOF.
@throws LexException