import java.io.*;
import java.util.Scanner;

public class LinZParse
{
	/*
	 * write a recursive descent parser for Linear Z expressions
	 * using LinZScan to get tokens.
	 *
	 * written by mike slattery - sep 2010
	 */
	int lookahead;
	LinZScan scanner;

	public LinZParse(String expr)
	{
		scanner = new LinZScan(expr);
		try
		{
			lookahead = scanner.getToken();
		} catch(IOException e)
		{
			error("IO troubles");
		}
	}

	void parse()
	{
		expr(); match(LinZScan.EOF);
		System.out.println("Legal expression");
	}

	void expr()
	{
		term(); moreterms();
	}

	void moreterms()
	{
		if (lookahead == LinZScan.PLUS)
		{
			match(LinZScan.PLUS); term(); moreterms();
		}
		else if (lookahead == LinZScan.MINUS)
		{
			match(LinZScan.MINUS); term(); moreterms();
		}
		else
		{
			/* epsilon */
		}
	}

	void term()
	{
		factor(); morefactors();
	}

	void morefactors()
	{
		if (lookahead == LinZScan.TIMES)
		{
			match(LinZScan.TIMES); factor(); morefactors();
		}
		else
		{
			/* epsilon */
		}
	}

	void factor()
	{
		if (lookahead == LinZScan.NUM)
		{
			match(LinZScan.NUM);
		}
		else if (lookahead == LinZScan.LBRACE)
		{
			match(LinZScan.LBRACE); expr(); match(LinZScan.RBRACE);
		}
		else
		{
			error("missing operand");
		}
	}

	void match(int token)
	{
		if (lookahead == token)
		{
			try
			{
				lookahead = scanner.getToken();
			} catch(IOException e)
			{
				error("IO troubles");
			}
		}
		else
		{
			error("missing symbol");
		}
	}

	void error(String msg)
	{
		System.err.println("Syntax error: "+msg);
		System.exit(1);
	}

	public static void main(String[] args)
	{
		Scanner kb = new Scanner(System.in);
		while(true)
		{
			System.out.print("Enter LinearZ expression: ");
			String expr = kb.nextLine();
			if (expr.equals("quit"))
				break;
			LinZParse parser = new LinZParse(expr);
			parser.parse();
			System.out.println();
		}
	}
}

