summaryrefslogtreecommitdiff
path: root/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java
blob: d60c6d49338c7a00e368af4031a1e06053213cdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package bjc.rgens.newparser;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.util.Scanner;

/**
 * Reads {@link RGrammar} from a input stream.
 * 
 * @author student
 *
 */
public class RGrammarParser {
	/**
	 * The exception thrown when something goes wrong while parsing a grammar.
	 * 
	 * @author student
	 *
	 */
	public static class GrammarException extends Exception {
		/*
		 * Serialization ID.
		 */
		private static final long serialVersionUID = -7287427479316953668L;

		/**
		 * Create a new grammar exception with the specified message.
		 * 
		 * @param msg
		 *            The message for this exception.
		 */
		public GrammarException(String msg) {
			super(msg);
		}

		/**
		 * Create a new grammar exception with the specified message and cause.
		 * 
		 * @param msg
		 *            The message for this exception.
		 * 
		 * @param cause
		 *            The cause of this exception.
		 */
		public GrammarException(String msg, Exception cause) {
			super(msg, cause);
		}
	}

	/**
	 * Read a {@link RGrammar} from an input stream.
	 * 
	 * @param is
	 *            The input stream to read from.
	 * 
	 * @return The grammar represented by the stream.
	 * 
	 * @throws GrammarException
	 *             Thrown if the grammar has a syntax error.
	 */
	public RGrammar readGrammar(InputStream is) throws GrammarException {
		LineNumberReader lnReader = new LineNumberReader(new InputStreamReader(is));

		try (Scanner scn = new Scanner(lnReader)) {
			scn.useDelimiter("\\n\\.?\\n");

			RGrammarBuilder build = new RGrammarBuilder();

			while (scn.hasNext()) {
				String block = scn.next();

				if (block.startsWith("pragma")) {
					handlePragmaBlock(block, build);
				} else if (block.startsWith("[")) {
					handleRuleBlock(block, build);
				} else {
					throw new GrammarException(String.format("Unknown block: %s", lnReader.getLineNumber(), block));
				}
			}
		} catch (GrammarException gex) {
			throw new GrammarException(String.format("Error at line %d", lnReader.getLineNumber()), gex);
		}

		return null;
	}

	private void handlePragmaBlock(String block, RGrammarBuilder build) throws GrammarException {
		LineNumberReader lnReader = new LineNumberReader(new StringReader(block));

		try (Scanner deblocker = new Scanner(lnReader)) {
			deblocker.useDelimiter("\\n(?!\\t)");

			while (deblocker.hasNext()) {
				String pragma = deblocker.next();

				if (!pragma.startsWith("pragma")) {
					throw new GrammarException(String.format("Illegal line at line %d of pragma block: %s",
							lnReader.getLineNumber(), pragma));
				}
			}
		}
	}

	private void handleRuleBlock(String block, RGrammarBuilder build) {
		// TODO Auto-generated method stub

	}
}