PageRenderTime 12ms CodeModel.GetById 1ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/ooc/frontend/parser/ImportParser.java

http://github.com/nddrylliog/ooc
Java | 124 lines | 109 code | 15 blank | 0 comment | 52 complexity | 7bfcb281d0cc20973b2a927b7253dd1a MD5 | raw file
  1package org.ooc.frontend.parser;
  2
  3import org.ooc.frontend.model.Import;
  4import org.ooc.frontend.model.Module;
  5import org.ooc.frontend.model.NamespaceDecl;
  6import org.ooc.frontend.model.NodeList;
  7import org.ooc.frontend.model.tokens.Token;
  8import org.ooc.frontend.model.tokens.TokenReader;
  9import org.ooc.frontend.model.tokens.Token.TokenType;
 10import org.ubi.CompilationFailedError;
 11import org.ubi.SourceReader;
 12
 13public class ImportParser {
 14
 15	public static boolean fill(Module module, SourceReader sReader, TokenReader reader) {
 16
 17		Token startToken = reader.peek();
 18		if(startToken.type != TokenType.IMPORT_KW) {
 19			return false;
 20		}
 21		reader.skip();
 22		
 23		StringBuilder sb = new StringBuilder();
 24		NamespaceDecl namespace = null;
 25		NodeList<Import> imports = new NodeList<Import>(startToken);
 26
 27		Token token = null;
 28		
 29		while(true) {
 30		
 31			token = reader.read();
 32			if(token.type == TokenType.LINESEP || token.type == TokenType.INTO_KW) {
 33				Import imp = new Import(sb.toString(), startToken);
 34				imports.add(imp);
 35				break;
 36			} else if(token.type == TokenType.COMMA) {
 37				Import imp = new Import(sb.toString(), startToken);
 38				imports.add(imp);
 39				sb.setLength(0);
 40				reader.skipWhitespace();
 41				startToken = reader.peek();
 42			} else if(token.type == TokenType.SLASH) {
 43				sb.append('/');
 44				if(readMulti(sReader, reader, imports, sb, token)) break;
 45				if(reader.peek().type == TokenType.COMMA) {
 46					reader.skip();
 47				}
 48			} else if(token.type == TokenType.DOT) {
 49				throw new CompilationFailedError(sReader.getLocation(token),
 50						"import my.package.MyClass style deprecated, use import my/package/MyClass instead.");
 51			} else if(token.type == TokenType.DOUBLE_DOT) {
 52				sb.append("..");
 53			} else {
 54				sb.append(token.get(sReader));
 55			}
 56			
 57		}
 58		
 59		if(token.type == TokenType.INTO_KW || reader.peek().type == TokenType.INTO_KW) {
 60			if(reader.peek().type == TokenType.INTO_KW)
 61				reader.skip();
 62			Token nameToken = reader.read();
 63			if(nameToken.type != TokenType.NAME) {
 64				throw new CompilationFailedError(sReader.getLocation(token),
 65					"Expected NAME after `into` keyword.");
 66			}
 67			if(namespace != null) {
 68				throw new CompilationFailedError(sReader.getLocation(token),
 69					"Only one `into` declaration is allowed per import statement.");
 70			}
 71			String nsName = nameToken.get(sReader);
 72			namespace = module.getNamespace(nsName);
 73			if(namespace == null) {
 74			       namespace = new NamespaceDecl(nsName, nameToken, module);
 75			       module.addNamespace(namespace);
 76			}
 77		}
 78
 79		if(namespace != null) {
 80			namespace.getImports().addAll(imports);
 81		} else {
 82			module.getGlobalImports().addAll(imports);
 83		}
 84		
 85		return true;
 86		
 87	}
 88
 89	private static boolean readMulti(SourceReader sReader, TokenReader reader,
 90			NodeList<Import> imports, StringBuilder sb,
 91			Token token) throws CompilationFailedError {
 92		if(reader.peek().type == TokenType.OPEN_SQUAR) {
 93			reader.skip();
 94			StringBuilder innerSb = new StringBuilder();
 95			Token startToken = reader.peek();
 96			while(true) {
 97				reader.skipWhitespace();
 98				Token innerToken = reader.read();
 99				if(innerToken.type == TokenType.COMMA) {
100					Import imp = new Import(sb.toString() + innerSb.toString(), startToken);
101					imports.add(imp);
102					innerSb.setLength(0);
103					startToken = reader.peek();
104				} else if(innerToken.type == TokenType.CLOS_SQUAR) {
105					Import imp = new Import(sb.toString() + innerSb.toString(), startToken);
106					imports.add(imp);
107					break;
108				} else {
109					innerSb.append(innerToken.get(sReader));
110				}
111			}
112			sb.setLength(0);
113			Token next = reader.peek();
114			if(next.type == TokenType.LINESEP || next.type == TokenType.INTO_KW) {
115				return true;
116			} else if(next.type != TokenType.COMMA) {
117				throw new CompilationFailedError(sReader.getLocation(next),
118						"Unexpected token "+next+" while reading an import");
119			}
120		}
121		return false;
122	}
123	
124}