summaryrefslogtreecommitdiff
path: root/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java
blob: e31bb033745d3933b46cf046bf9539e17b606c65 (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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));

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

			RGrammarBuilder build = new RGrammarBuilder();

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

				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 in block %d at line %d of stream", blockNo, lnReader.getLineNumber()), gex);
		}

		return null;
	}

	/*
	 * Handle reading a block of pragmas
	 */
	private void handlePragmaBlock(String block, RGrammarBuilder build) throws GrammarException {
		LineNumberReader lnReader = new LineNumberReader(new StringReader(block));

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

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

				if (!pragma.startsWith("pragma")) {
					throw new GrammarException(String.format("Illegal line: %s",
							lnReader.getLineNumber(), pragma));
				} else {
					handlePragma(pragma.substring(7), build);
				}
			}
		} catch (GrammarException gex) {
			throw new GrammarException(String.format("Error in pragma %d at line %d", pragmaNo, lnReader.getLineNumber()), gex);
		}
	}

	private void handlePragma(String pragma, RGrammarBuilder build) {
		
	}

	/*
	 * Handle a block of rules.
	 */
	private void handleRuleBlock(String block, RGrammarBuilder build) {
		LineNumberReader lnReader = new LineNumberReader(new StringReader(block));

		try(Scanner scn = new Scanner(lnReader)) {
			
		}
	}
}