public ConfigFile read() {
		List<Declaration> declarations = new ArrayList<>();
		skipWhiteSpace();
		while (index < tokens.size()) {
			Token lookahead = tokens.get(index);
			if (lookahead.kind == LeftSquare) {
				declarations.add(parseSection());
			} else {
				declarations.add(parseKeyValuePair());
			}
			skipWhiteSpace();
		}
		// FIXME: why do we need this?
		file.setDeclarations(new Tuple<>(declarations));
		return file;
	}
public ConfigFile read() {
		List<Declaration> declarations = new ArrayList<>();
		skipWhiteSpace();
		while (index < tokens.size()) {
			Token lookahead = tokens.get(index);
			if (lookahead.kind == LeftSquare) {
				declarations.add(parseSection());
			} else {
				declarations.add(parseKeyValuePair());
			}
			skipWhiteSpace();
		}
		
		file.setDeclarations(new Tuple<>(declarations));
		return file;
	}
public ConfigFile read ( ) { List < Declaration > declarations = new ArrayList <> ( ) ; skipWhiteSpace ( ) ; while ( index < tokens . size ( ) ) { Token lookahead = tokens . get ( index ) ; if ( lookahead . kind == LeftSquare ) { declarations . add ( parseSection ( ) ) ; } else { declarations . add ( parseKeyValuePair ( ) ) ; } skipWhiteSpace ( ) ; } // FIXME: why do we need this? file . setDeclarations ( new Tuple <> ( declarations ) ) ; return file ; }
Read a <code>ConfigFile</code> from the token stream. If the stream is
invalid in some way (e.g. contains a syntax error, etc) then a
<code>SyntaxError</code> is thrown.

@return
Read a <code > ConfigFile< / code > from the token stream . If the stream is invalid in some way ( e . g . contains a syntax error etc ) then a <code > SyntaxError< / code > is thrown .