<commit_before>package org.gertje.abacus;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.gertje.abacus.nodes.AbstractNode;
import org.gertje.abacus.nodes.NodeFactoryInterface;
import org.gertje.abacus.nodes.StatementListNode;

class Parser {

	// Constanten voor mogelijke waarden van booleans.
	private static final String BOOLEAN_TRUE = "true";
	private static final String BOOLEAN_FALSE = "false";
	private static final String NULL = "null";

	/**
	 * De lexer.
	 */
	private LexerInterface lex;
	
	/**
	 * De fabriek voor nodes.
	 */
	private NodeFactoryInterface nodeFactory;

	public Parser(LexerInterface lex, NodeFactoryInterface nodeFactory) {
		this.lex = lex;
		this.nodeFactory = nodeFactory;
	}

	private Token determineNextToken() throws LexerException {
		Token nextToken = lex.getNextToken();

		// Haal net zo lang een nieuw token op totdat het geen whitespace of een nieuwe regel is.
		while (nextToken.getType() == TokenType.WHITE_SPACE || nextToken.getType() == TokenType.NEW_LINE) {
			nextToken = lex.getNextToken();
		}
		
		return nextToken;
	}
	
	private Token peekNextToken() throws LexerException {
		Token nextToken = lex.peekToken();

		// Haal net zo lang een nieuw token op totdat het geen whitespace of een nieuwe regel is.
		while (nextToken.getType() == TokenType.WHITE_SPACE || nextToken.getType() == TokenType.NEW_LINE) {
			lex.getNextToken();
			nextToken = lex.peekToken();
		}

		return nextToken;
	}
	
	/**
	 * Bouwt een AST op van de expressie.
	 * @throws CompilerException
	 */
	public StatementListNode parse() throws CompilerException {
		return statementList(determineNextToken());
	}

	private StatementListNode statementList(Token nextToken) throws CompilerException {
		StatementListNode list = nodeFactory.createStatementListNode(nextToken);
		// Zolang het token niet het einde van de input aangeeft maken we expressies aan.
		while (nextToken.getType() != TokenType.END_OF_INPUT) {
			list.add(statement(nextToken));
			nextToken = determineNextToken();
		}

		return list;
	}

	private AbstractNode statement(Token nextToken) throws CompilerException {
		// Een statement is een assignment gevolgd door een 'end of expression' of het 'end of input' token.
		AbstractNode statement = assignment(nextToken);

		// We verwachten het 'end of expression' of het 'end of input' token.
		nextToken = peekNextToken();
		if (nextToken.getType() != TokenType.END_OF_EXPRESSION 
				&& nextToken.getType() != TokenType.END_OF_INPUT) {
			throw new ParserException("Unexpected token '" + nextToken.getType().toString() + "'.", nextToken);
		}

		// Wanneer het token niet het 'end of input' token was, halen we het token van de stack.
		if (nextToken.getType() != TokenType.END_OF_INPUT) {
			determineNextToken();
		}

		return statement;
	}

	private AbstractNode assignment(Token nextToken) throws CompilerException {
		AbstractNode lhs = expression(nextToken);

		// Spiek wat het volgende token is.
		nextToken = peekNextToken();

		// Zolang het volgende token een sommatie is voeren we die operatie uit.
		if (nextToken.getType() == TokenType.ASSIGNMENT) {
			// Haal het gespiekte token van de stack.
			Token assignmentToken = determineNextToken();
			// Bepaal de rechter AST van de operatie.
			AbstractNode rhs = assignment(determineNextToken());

			// Maak afhankelijk van de operatie de juiste soort ASTNode aan.
			lhs = nodeFactory.createAssignmentNode(lhs, rhs, assignmentToken);
		}

		return lhs;
	}

	private AbstractNode expression(Token nextToken) throws CompilerException {
		return conditional(nextToken);
	}<commit_msg>Class Parser is now public. Made some methods protected instead of private. Changed return type of method parse() from StatementListNode to AbstractNode.<commit_after>package org.gertje.abacus;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.gertje.abacus.nodes.AbstractNode;
import org.gertje.abacus.nodes.NodeFactoryInterface;
import org.gertje.abacus.nodes.StatementListNode;

public class Parser {

	// Constanten voor mogelijke waarden van een boolean.
	private static final String BOOLEAN_TRUE = "true";
	private static final String BOOLEAN_FALSE = "false";
	// Constante voor de NULL waarde.
	private static final String NULL = "null";

	/**
	 * De lexer.
	 */
	private LexerInterface lex;
	
	/**
	 * De fabriek voor nodes.
	 */
	protected NodeFactoryInterface nodeFactory;

	public Parser(LexerInterface lex, NodeFactoryInterface nodeFactory) {
		this.lex = lex;
		this.nodeFactory = nodeFactory;
	}

	protected Token determineNextToken() throws LexerException {
		Token nextToken = lex.getNextToken();

		// Haal net zo lang een nieuw token op totdat het geen whitespace of een nieuwe regel is.
		while (nextToken.getType() == TokenType.WHITE_SPACE || nextToken.getType() == TokenType.NEW_LINE) {
			nextToken = lex.getNextToken();
		}
		
		return nextToken;
	}
	
	protected Token peekNextToken() throws LexerException {
		Token nextToken = lex.peekToken();

		// Haal net zo lang een nieuw token op totdat het geen whitespace of een nieuwe regel is.
		while (nextToken.getType() == TokenType.WHITE_SPACE || nextToken.getType() == TokenType.NEW_LINE) {
			lex.getNextToken();
			nextToken = lex.peekToken();
		}

		return nextToken;
	}
	
	/**
	 * Bouwt een AST op van de expressie.
	 * @throws CompilerException
	 */
	public AbstractNode parse() throws CompilerException {
		return statementList(determineNextToken());
	}

	private StatementListNode statementList(Token nextToken) throws CompilerException {
		StatementListNode list = nodeFactory.createStatementListNode(nextToken);
		// Zolang het token niet het einde van de input aangeeft maken we expressies aan.
		while (nextToken.getType() != TokenType.END_OF_INPUT) {
			list.add(statement(nextToken));
			nextToken = determineNextToken();
		}

		return list;
	}

	private AbstractNode statement(Token nextToken) throws CompilerException {
		// Een statement is een assignment gevolgd door een 'end of expression' of het 'end of input' token.
		AbstractNode statement = assignment(nextToken);

		// We verwachten het 'end of expression' of het 'end of input' token.
		nextToken = peekNextToken();
		if (nextToken.getType() != TokenType.END_OF_EXPRESSION 
				&& nextToken.getType() != TokenType.END_OF_INPUT) {
			throw new ParserException("Unexpected token '" + nextToken.getType().toString() + "'.", nextToken);
		}

		// Wanneer het token niet het 'end of input' token was, halen we het token van de stack.
		if (nextToken.getType() != TokenType.END_OF_INPUT) {
			determineNextToken();
		}

		return statement;
	}

	private AbstractNode assignment(Token nextToken) throws CompilerException {
		AbstractNode lhs = expression(nextToken);

		// Spiek wat het volgende token is.
		nextToken = peekNextToken();

		// Zolang het volgende token een sommatie is voeren we die operatie uit.
		if (nextToken.getType() == TokenType.ASSIGNMENT) {
			// Haal het gespiekte token van de stack.
			Token assignmentToken = determineNextToken();
			// Bepaal de rechter AST van de operatie.
			AbstractNode rhs = assignment(determineNextToken());

			// Maak afhankelijk van de operatie de juiste soort ASTNode aan.
			lhs = nodeFactory.createAssignmentNode(lhs, rhs, assignmentToken);
		}

		return lhs;
	}

	protected AbstractNode expression(Token nextToken) throws CompilerException {
		return conditional(nextToken);
	}
{'fraction_non_alphanumeric': 0.09371671991480299, 'fraction_numerical': 0.0, 'mean_word_length': 4.250174703004892, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3943840', 'n_tokens_mistral': 2438, 'n_tokens_neox': 2238, 'n_words': 686}