/*
 * Copyright 2009-2010 Yuichiro Moriguchi
 *
 * 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.
 */
package net.morilib.bc;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import junit.framework.TestCase;

/**
 *
 *
 * @author MORIGUCHI, Yuichiro 2013/07/06
 */
public class BcParserTest extends TestCase {

	void syn(String s) {
		try {
			BcNamespace ns = new BcRootNamespace();
			BcLexer lex = new BcLexer(s);
			StringWriter b = new StringWriter();
			PrintWriter  w = new PrintWriter(b);

			new BcParser(System.in, System.out).parse(lex, ns, w);
			if(!lex.isEof())  fail();
		} catch(BcQuitException e) {
			// do nothing
		} catch(IOException e) {
			throw new RuntimeException(e);
		}
	}

	void eqn(String s, String t) {
		try {
			BcNamespace ns = new BcRootNamespace();
			BcLexer lex = new BcLexer(s);
			StringWriter b = new StringWriter();
			PrintWriter  w = new PrintWriter(b);

			new BcParser(System.in, System.out).parse(lex, ns, w);
			if(!lex.isEof())  fail();
			assertEquals(t, b.toString());
		} catch(BcQuitException e) {
			// do nothing
		} catch(IOException e) {
			throw new RuntimeException(e);
		}
	}

	public void testSyntax001() {
		syn("1");
		syn("1+2");
		syn("if (a == 1) b = 1");
		syn("if (a == 1) b = 1 else c = 1");
		syn("if (a == 1) b = 1 else if(b == 1) c = 1 else d = 1");
		syn("{ a = 1; b = 1; }");
		syn("if (a == 1) { a = 1; b = 1; }");
		syn("if (a == 1) { a = 1; b = 1; } else d = 1");
//		syn("if (a == 1);");
		syn("while(a == 1) a = 1");
		syn("while(a == 1) { a = 1; }");
		syn("for(a = 1; a == 1; a++) a = 1");
		syn("for(a = 1; a == 1; a++) { a = 1; }");
		syn("for(; a == 1; a++) { a = 1; }");
		syn("for(a = 1;; a++) { a = 1; }");
		syn("for(a = 1; a == 1;) { a = 1; }");
		syn("for(;; a++) { a = 1; }");
		syn("for(a = 1;;) { a = 1; }");
		syn("for(;;) { a = 1; }");
//		syn("break;");
//		syn("continue;");
		syn("halt");
		syn("\"aaaa\"");
		syn("print \"aaaa\"");
		syn("print 1+2");
		syn("print \"aaaa\",1+2");
		syn("return");
		syn("return (1)");
		syn("return 1");
	}

	public void testSyntax002() {
		syn("define aaa () { a = 1; }");
		syn("define aaa (a) { a = 1; }");
		syn("define aaa (a, b) { a = 1; }");
	}

	public void testParse001() {
		eqn("1", "1 p捨");
		eqn("1+2", "1 2 +p捨");
	}

	public void testParse002() {
		eqn("if(1 == 2) 1+2", "1 2 ＝[1 2 +p捨][]？");
		eqn("if(1 == 2) 1+2 else 2+3", "1 2 ＝[1 2 +p捨][2 3 +p捨]？");
	}

	public void testParse003() {
		eqn("while(i < 10) i",
				"[l\u4e0010 ＜[[l\u4e00p捨]xl\ufe00x][]？]s\ufe00l\ufe00x");
	}

	public void testParse004() {
		eqn("for(i = 1; i < 10; i++) i",
				"1 ds\u4e00捨[l\u4e0010 ＜[[l\u4e00p捨]xl\u4e00d1+ds\u4e00捨捨l\ufe00x][]？]s\ufe00l\ufe00x");
		eqn("for(; i < 10; i++) i",
				"[l\u4e0010 ＜[[l\u4e00p捨]xl\u4e00d1+ds\u4e00捨捨l\ufe00x][]？]s\ufe00l\ufe00x");
		eqn("for(i = 1;; i++) i",
				"1 ds\u4e00捨[1[[l\u4e00p捨]xl\u4e00d1+ds\u4e00捨捨l\ufe00x][]？]s\ufe00l\ufe00x");
		eqn("for(i = 1; i < 10;) i",
				"1 ds\u4e00捨[l\u4e0010 ＜[[l\u4e00p捨]xl\ufe00x][]？]s\ufe00l\ufe00x");
		eqn("for(;; i++) i",
				"[1[[l\u4e00p捨]xl\u4e00d1+ds\u4e00捨捨l\ufe00x][]？]s\ufe00l\ufe00x");
		eqn("for(; i < 10;) i",
				"[l\u4e0010 ＜[[l\u4e00p捨]xl\ufe00x][]？]s\ufe00l\ufe00x");
		eqn("for(i = 1;;) i",
				"1 ds\u4e00捨[1[[l\u4e00p捨]xl\ufe00x][]？]s\ufe00l\ufe00x");
		eqn("for(;;) i",
				"[1[[l\u4e00p捨]xl\ufe00x][]？]s\ufe00l\ufe00x");
	}

	public void testParse005() {
		eqn("for(; i < 10;) break",
				"[l\u4e0010 ＜[[2Q]xl\ufe00x][]？]s\ufe00l\ufe00x");
		eqn("for(; i < 10;) continue",
				"[l\u4e0010 ＜[[1Q]xl\ufe00x][]？]s\ufe00l\ufe00x");
		eqn("for(; i < 10;) halt",
				"[l\u4e0010 ＜[[停]xl\ufe00x][]？]s\ufe00l\ufe00x");
//		eqn("for(; i < 10;) for(; i < 10;) break",
//				"[l\u4e0010 ＜[[[l\u4e0010 ＜[[4Q]xl\ufe00x][]？]s\ufe00l\ufe00x]xl\ufe00x][]？]s\ufe00l\ufe00x");
	}

	public void testParse006() {
		eqn("define aaa() { i = 1; }", "[[1 ds\u4e00捨]x]s\u4e00");
		eqn("define aaa(a) { a = 1; }", "[S\uf000[1 ds\uf000捨]xL\uf000捨]s\u4e00");
		eqn(    "define aaa(a, b) {\n" +
				"  a = 1;\n" +
				"  b = 2;\n" +
				"}", "[S\uf000S\uf001[1 ds\uf001捨2 ds\uf000捨]xL\uf001捨L\uf000捨]s\u4e00");
	}

	public void testParse007() {
		eqn("\"aaaa\"", "[aaaa]");
		eqn("print \"aaaa\"", "[aaaa]1刷");
		eqn("print \"aaaa\", 1 + 2", "[aaaa]1 2 +2刷");
	}

	public void testParse008() {
		eqn(    "define aaa(a, b) {\n" +
				"  return\n" +
				"}", "[S\uf000S\uf001[0 1Q]xL\uf001捨L\uf000捨]s\u4e00");
		eqn(    "define aaa(a, b) {\n" +
				"  if(1 == 1)  return\n" +
				"}", "[S\uf000S\uf001[1 1 ＝[0 2Q][]？]xL\uf001捨L\uf000捨]s\u4e00");
		eqn(    "define aaa(a, b) {\n" +
				"  return (1)\n" +
				"}", "[S\uf000S\uf001[1 1Q]xL\uf001捨L\uf000捨]s\u4e00");
	}

	public void testParse009() {
		eqn(    "define aaa() {\n" +
				"  auto a, b;\n" +
				"  return a + b;\n" +
				"}", "[0S\uf0000S\uf001[l\uf000l\uf001+1Q]xL\uf000捨L\uf001捨]s\u4e00");
	}

}
