001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.util.sexp;
038:
039: import edu.rice.cs.drjava.DrJavaTestCase;
040:
041: import java.io.*;
042: import java.util.List;
043:
044: /** A JUnit test case class. Every method starting with the word "test" will be called when running
045: * the test with JUnit.
046: */
047: public class SExpParserTest extends DrJavaTestCase {
048:
049: /**
050: * Creates a temporary file and writes the given string to that file
051: * @param fname the name of the file to create
052: * @param text the text to write to the file
053: * @return the File that was created
054: */
055: private File _fillTempFile(String fname, String text) {
056: File f = null;
057: try {
058: f = File.createTempFile(fname, null).getCanonicalFile();
059: FileWriter fw = new FileWriter(f);
060: fw.write(text, 0, text.length());
061: fw.close();
062: } catch (IOException e) {
063: throw new RuntimeException(
064: "IOException thrown while writing to temp file");
065: }
066: return f;
067: }
068:
069: /**
070: * There are three ways to input the data to a parse.
071: * this tests to make sure they all three return the same
072: * thing.
073: */
074: public void testDifferentInputs() throws SExpParseException,
075: IOException {
076: String text = "()";
077: File f = _fillTempFile("temp1", text);
078: char[] ca = new char[text.length()];
079: text.getChars(0, text.length(), ca, 0);
080: Reader r = new CharArrayReader(ca);
081:
082: SExp sa1 = SExpParser.parse(text).get(0);
083: SExp sa2 = SExpParser.parse(f).get(0);
084: SExp sa3 = SExpParser.parse(r).get(0);
085:
086: SExp ans = Empty.ONLY;
087:
088: assertEquals("the 1st parse wasn't right", ans, sa1);
089: assertEquals("the 2nd parse wasn't right", ans, sa2);
090: assertEquals("the 3rd parse wasn't right", ans, sa3);
091: }
092:
093: /**
094: * Tests to make sure that multiple top-level s-exps
095: * are parsed separately and in tact
096: */
097: public void testParseMultiple() throws SExpParseException {
098: String text = "(abcdefg)(hijklmnop)";
099: List<? extends SExp> exps = SExpParser.parse(text);
100: SExp exp1 = exps.get(0);
101: SExp exp2 = exps.get(1);
102:
103: // use a few visitors to test the instances
104: final SExpVisitor<String> innerVisitor = new SExpVisitor<String>() {
105: private String _failMe(String who) {
106: fail("The inside was " + who
107: + " but should have been text");
108: return "";
109: }
110:
111: public String forEmpty(Empty e) {
112: return _failMe("an empty list");
113: }
114:
115: public String forCons(Cons c) {
116: return _failMe("an empty list");
117: }
118:
119: public String forBoolAtom(BoolAtom b) {
120: return _failMe("a boolean");
121: }
122:
123: public String forNumberAtom(NumberAtom n) {
124: return _failMe("a number");
125: }
126:
127: public String forTextAtom(TextAtom t) {
128: return t.getText();
129: }
130: };
131:
132: final SExpVisitor<String> outerVisitor = new SExpVisitor<String>() {
133: private String _failMe(String who) {
134: fail("The top-level was " + who
135: + " but should have been a cons");
136: return "";
137: }
138:
139: public String forEmpty(Empty e) {
140: return _failMe("an empty list");
141: }
142:
143: public String forCons(Cons c) {
144: return c.getFirst().accept(innerVisitor);
145: }
146:
147: public String forBoolAtom(BoolAtom b) {
148: return _failMe("a boolean");
149: }
150:
151: public String forNumberAtom(NumberAtom n) {
152: return _failMe("a number");
153: }
154:
155: public String forTextAtom(TextAtom t) {
156: return _failMe("text");
157: }
158: };
159:
160: assertEquals("wrong text in 1st s-expression", "abcdefg", exp1
161: .accept(outerVisitor));
162: assertEquals("wrong text in 2nd s-expression", "hijklmnop",
163: exp2.accept(outerVisitor));
164: }
165:
166: public void testTopLevel() throws SExpParseException {
167: // Test an illegal top-level s-exp
168: String text = "true";
169: try {
170: SExp exp = SExpParser.parse(text).get(0);
171: fail("Didn't throw a parse exception");
172: } catch (SExpParseException e) {
173: assertEquals("Incorrect exception message",
174: "A top-level s-expression must be a list. "
175: + "Invalid start of list: true", e
176: .getMessage());
177: }
178: text = "123 ((help) me)";
179: try {
180: SExp exp = SExpParser.parse(text).get(0);
181: fail("Didn't throw a parse exception");
182: } catch (SExpParseException e) {
183: assertEquals("Incorrect exception message",
184: "A top-level s-expression must be a list. "
185: + "Invalid start of list: 123", e
186: .getMessage());
187: }
188: text = "[help me]"; // right now, I haven't allowed other brace types
189: try {
190: SExp exp = SExpParser.parse(text).get(0);
191: fail("Didn't throw a parse exception");
192: } catch (SExpParseException e) {
193: assertEquals("Incorrect exception message",
194: "A top-level s-expression must be a list. "
195: + "Invalid start of list: [help", e
196: .getMessage());
197: }
198: }
199:
200: public void testInvalidLowerLevel() {
201:
202: String text = "(abcdefg";
203: try {
204: SExp exp = SExpParser.parse(text).get(0);
205: fail("Didn't throw a parse exception");
206: } catch (SExpParseException e) {
207: assertEquals("Incorrect exception message",
208: "Unexpected <EOF> at line 1", e.getMessage());
209: }
210:
211: text = "(ab\ncdefg";
212: try {
213: SExp exp = SExpParser.parse(text).get(0);
214: fail("Didn't throw a parse exception");
215: } catch (SExpParseException e) {
216: assertEquals("Incorrect exception message",
217: "Unexpected <EOF> at line 2", e.getMessage());
218: }
219:
220: text = "(ab\ncdefg))";
221: try {
222: SExp exp = SExpParser.parse(text).get(0);
223: fail("Didn't throw a parse exception");
224: } catch (SExpParseException e) {
225: assertEquals("Incorrect exception message",
226: "A top-level s-expression must be a list. "
227: + "Invalid start of list: )", e
228: .getMessage());
229: }
230:
231: text = "(\")"; // (") <-- unclosed string
232: try {
233: SExp exp = SExpParser.parse(text).get(0);
234: fail("Didn't throw a parse exception");
235: } catch (SExpParseException e) {
236: assertEquals("Incorrect exception message",
237: "Unexpected <EOF> at line 1", e.getMessage());
238: }
239:
240: text = "(;)"; // <-- last ) is commented out
241: try {
242: SExp exp = SExpParser.parse(text).get(0);
243: fail("Didn't throw a parse exception");
244: } catch (SExpParseException e) {
245: assertEquals("Incorrect exception message",
246: "Unexpected <EOF> at line 1", e.getMessage());
247: }
248: }
249:
250: public void testCorrectParse() throws SExpParseException {
251: String n = "\n";
252: String text = "; this is a comment line "
253: + n + "; this is another comment line "
254: + n + "(Source "
255: + n + " (/sexp/Atom.java) "
256: + n + " (/sexp/Cons.java) "
257: + n + " (/sexp/Empty.java) "
258: + n + " (/sexp/Lexer.java) "
259: + n + " (/sexp/SExp.java) "
260: + n + " (/sexp/SExpParser.java) "
261: + n + " (/sexp/SExpVisitor.java) "
262: + n + " (/sexp/Tokens.java) "
263: + n + ") "
264: + n + "; This is the build directory. Absolute path "
265: + n + "(BuildDir \"/home/javaplt/drjava/built\") "
266: + n + "(MainFile \"/sexp/SExpParser.java\") "
267: + n + "(Included "
268: + n + ")";
269:
270: List<SEList> res = SExpParser.parse(text);
271: assertEquals("Should have four trees in forest", 4, res.size());
272: }
273: }
|