PageRenderTime 585ms CodeModel.GetById 141ms app.highlight 212ms RepoModel.GetById 223ms app.codeStats 0ms

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

http://github.com/nddrylliog/ooc
Java | 158 lines | 132 code | 26 blank | 0 comment | 34 complexity | aa739ff00b006f4c5fcd59515c53960f MD5 | raw file
  1package org.ooc.frontend.parser;
  2
  3import java.util.ArrayList;
  4import java.util.List;
  5
  6import org.ooc.frontend.model.Argument;
  7import org.ooc.frontend.model.MemberArgument;
  8import org.ooc.frontend.model.MemberAssignArgument;
  9import org.ooc.frontend.model.Module;
 10import org.ooc.frontend.model.NodeList;
 11import org.ooc.frontend.model.RegularArgument;
 12import org.ooc.frontend.model.Type;
 13import org.ooc.frontend.model.VarArg;
 14import org.ooc.frontend.model.tokens.Token;
 15import org.ooc.frontend.model.tokens.TokenReader;
 16import org.ooc.frontend.model.tokens.Token.TokenType;
 17import org.ubi.CompilationFailedError;
 18import org.ubi.SourceReader;
 19
 20public class ArgumentParser {
 21
 22	public static boolean fill(Module module, SourceReader sReader, TokenReader reader, boolean acceptTypeArgs, NodeList<Argument> args) {
 23		
 24		if(reader.peek().type == TokenType.OPEN_PAREN) {
 25			reader.skip();
 26			boolean comma = false;
 27			while(true) {
 28				
 29				if(reader.peekWhiteless().type == TokenType.CLOS_PAREN) {
 30					reader.skipWhitespace();
 31					reader.skip(); // skip the ')'
 32					break;
 33				}
 34				if(comma) {
 35					if(reader.read().type != TokenType.COMMA) {
 36						throw new CompilationFailedError(sReader.getLocation(reader.prev(2)),
 37								"Did you forget to close the parenthesis here?");
 38					}
 39				} else {
 40					if(!parseInto(module, sReader, reader, acceptTypeArgs, args)) {
 41						throw new CompilationFailedError(sReader.getLocation(reader.peek()),
 42								"Expected argument specification of a function definition");
 43					}
 44				}
 45				comma = !comma;
 46				
 47			}
 48			return true;
 49		}
 50		return false;
 51		
 52	}
 53	
 54	public static boolean parseInto(Module module, SourceReader sReader, TokenReader reader,
 55			boolean acceptTypeArgs, NodeList<Argument> args) {
 56		
 57		int mark = reader.mark();
 58		
 59		Token startToken = reader.peek();
 60		if(startToken.type == TokenType.TRIPLE_DOT) {
 61			reader.skip();
 62			VarArg varArg = new VarArg(startToken);
 63			args.add(varArg);
 64			return true;
 65		}
 66		
 67		Token token = reader.readWhiteless();
 68		if(tryRegular(module, sReader, reader, args, mark, token)) return true;
 69		if(tryAssign(sReader, reader, args, token)) return true;
 70		if(tryMember(sReader, reader, args, token)) return true;
 71		reader.reset(mark);
 72		
 73		if(acceptTypeArgs) {
 74			Type type = TypeParser.parse(module, sReader, reader);
 75			if(type == null) {
 76				throw new CompilationFailedError(sReader.getLocation(reader.peek()),
 77					"Expected argument type in extern func definition ':'");
 78			}
 79			TypeArgument typeArg = new TypeArgument(type, type.startToken);
 80			args.add(typeArg);
 81			return true;
 82		}
 83				
 84		reader.reset();
 85		return false;
 86		
 87	}
 88
 89	protected static boolean tryMember(SourceReader sReader, TokenReader reader,
 90			NodeList<Argument> args, Token token)
 91			throws CompilationFailedError {
 92		
 93		if(token.type != TokenType.DOT) return false;
 94		
 95		Token t2 = reader.read();
 96		if(t2.type != TokenType.NAME) {
 97			throw new CompilationFailedError(sReader.getLocation(t2),
 98					"Expecting member variable name in member-assign-argument");
 99		}
100		MemberArgument arg = new MemberArgument(t2.get(sReader), token);
101		args.add(arg);
102		return true;
103	}
104
105	protected static boolean tryAssign(SourceReader sReader, TokenReader reader,
106			NodeList<Argument> args, Token token)
107			throws CompilationFailedError {
108		
109		if(token.type != TokenType.ASSIGN) return false;
110		Token t2 = reader.read();
111		if(t2.type != TokenType.NAME) {
112			throw new CompilationFailedError(sReader.getLocation(t2),
113					"Expecting member variable name in member-assign-argument");
114		}
115		MemberAssignArgument arg = new MemberAssignArgument(t2.get(sReader), token);
116		args.add(arg);
117		return true;
118	}
119
120	protected static boolean tryRegular(Module module, SourceReader sReader, TokenReader reader,
121			NodeList<Argument> args, int mark, Token token) {
122		
123		if(!token.isNameToken()) return false;
124		
125		List<String> names = new ArrayList<String>();
126		List<Token> tokens = new ArrayList<Token>();
127		names.add(token.get(sReader));
128		tokens.add(token);
129		while(reader.peek().type == TokenType.COMMA) {
130			reader.skip();
131			if(reader.peek().type != TokenType.NAME) {
132				reader.reset(mark);
133				return false;
134			}
135			Token subToken = reader.read();
136			names.add(subToken.get(sReader));
137			tokens.add(subToken);
138		}
139
140		if(reader.peek().type == TokenType.COLON) {
141			reader.skip();
142			Type type = TypeParser.parse(module, sReader, reader, false);
143			if(type == null) {
144				throw new CompilationFailedError(sReader.getLocation(reader.peek()),
145						"Expected argument type after its name and ':'");
146			}
147			for(int i = 0; i < names.size(); i++) {
148				RegularArgument regArg = new RegularArgument(type, names.get(i), tokens.get(i));
149				args.add(regArg);
150			}
151			return true;
152		}
153		reader.reset(mark);
154		return false;
155		
156	}
157	
158}