	private SVDBExpr assignment_pattern_expr() throws SVParseException {
		SVDBExpr ret_top;
		fLexer.readOperator("'");
		fLexer.readOperator("{");
		if (fDebugEn) {debug("    assignmentPattern");}
		if (fLexer.peekOperator("}")) {
			fLexer.eatToken();
			ret_top = new SVDBConcatenationExpr();
		} else {
			try {
				fEnableNameMappedPrimary = true;
				SVDBExpr expr1 = expression();
				if (fLexer.peekOperator("{")) {
					SVDBAssignmentPatternRepeatExpr ret = new SVDBAssignmentPatternRepeatExpr(expr1);
					fLexer.eatToken(); 
					while (true) {
						SVDBExpr expr = expression();
						ret.getPatternList().add(expr);
						if (fLexer.peekOperator(",")) {
							fLexer.eatToken();
						} else {
							break;
						}
					}
					fLexer.readOperator("}");
					ret_top = ret;
				} else  {
					SVDBAssignmentPatternExpr ret = new SVDBAssignmentPatternExpr();
					ret.getPatternList().add(expr1);
					while (fLexer.peekOperator(",")) {
						fLexer.eatToken();
						SVDBExpr expr = expression();
						ret.getPatternList().add(expr);
					}
					ret_top = ret;
				}
				fLexer.readOperator("}");
			} finally {
				fEnableNameMappedPrimary = false;
			}
		}
		return ret_top;
	}
	public SVDBExpr primary() throws SVParseException {
		if (fDebugEn) {debug("--> primary() - " + fLexer.peek());}
		SVDBExpr ret = null;
		if (peekOperator("(")) {
			if (fDebugEn) {debug("  Found paren in primary");}
			fLexer.eatToken();
			SVDBExpr a = expression();
			if (fLexer.peekOperator(":")) {
				fLexer.eatToken();
				SVDBExpr expr = fParsers.exprParser().expression();
				if (fLexer.peekOperator(":")) {
					fLexer.eatToken();
					expr = fParsers.exprParser().expression();
				}
			}
			readOperator(")");
			peek();
			if (fLexer.isNumber() || fLexer.isIdentifier() ||
					peekOperator("(", "~", "!") ||
					peekKeyword("this", "super", "new")) {
				ret = new SVDBCastExpr(a, unaryExpression());
			} else {
				ret = new SVDBParenExpr(a);
			}
		} else {
			fLexer.peek();
			if (fLexer.isNumber()) {
				if (fDebugEn) {debug("-- primary is a number");}
				SVToken tmp = fLexer.consumeToken();
				if (fEnableNameMappedPrimary && fLexer.peekOperator(":")) {
					fLexer.eatToken();
					ret = new SVDBNameMappedExpr(tmp.getImage(), expression());
				} else {
					ret = new SVDBLiteralExpr(tmp.getImage());
				}
			} else if (fLexer.peekOperator("$")) {
				fLexer.eatToken();
				ret = new SVDBRangeDollarBoundExpr();
			} else if (fLexer.peekString()) {
				if (fDebugEn) {debug("-- primary is a string");}
				SVToken tmp = fLexer.consumeToken();
				if (fEnableNameMappedPrimary && fLexer.peekOperator(":")) {
					fLexer.eatToken();
					ret = new SVDBNameMappedExpr(tmp.getImage(), expression());
				} else {
					ret = new SVDBStringExpr(tmp.getImage());
				}
			} else if (fLexer.peekKeyword("null")) {
				if (fDebugEn) {debug("-- primary is 'null'");}
				fLexer.eatToken();
				ret = new SVDBNullExpr();
			} else if (fLexer.isIdentifier() || 
					SVKeywords.isBuiltInType(fLexer.peek()) ||
					fLexer.peekKeyword("new","default","local")) {
				if (fDebugEn) {
					debug("  primary \"" + fLexer.getImage() + "\" is identifier or built-in type");
				}
				String id = fLexer.eatToken();
				if (fLexer.peekOperator("(*")) {
					fParsers.attrParser().parse(null);
				}
				if (peekOperator("#")) {
					ret = new SVDBParamIdExpr(id);
					fLexer.eatToken(); 
					fLexer.readOperator("(");
					while (fLexer.peek() != null) {
						((SVDBParamIdExpr)ret).addParamExpr(datatype_or_expression());
						if (fLexer.peekOperator(",")) {
							fLexer.eatToken();
						} else {
							break;
						}
					}
					fLexer.readOperator(")");
				} else if (fLexer.peekOperator("(") || fLexer.peekKeyword("with")) {
					if (id.equals("randomize")) {
						ret = randomize_call(null);
					} else if (fLexer.peekOperator("(")) {
						ret = tf_args_call(null, id);
					} else {
						ret = tf_noargs_with_call(null, id);
					}
				} else if (id.equals("new")) {
					ret = ctor_call();
				} else if (fLexer.peekKeyword(SVKeywords.fBuiltinDeclTypes)) {
					fLexer.startCapture();
					fLexer.eatToken();
					if (fLexer.peekKeyword("signed","unsigned")) {
						fLexer.eatToken();
					}
					ret = new SVDBIdentifierExpr(fLexer.endCapture());
				} else {
					if (fEnableNameMappedPrimary && fLexer.peekOperator(":")) {
						fLexer.eatToken();
						if (fDebugEn) {debug("    nameMappedExpr");}
						ret = new SVDBNameMappedExpr(id, expression());
					} else {
						ret = new SVDBIdentifierExpr(id);
					}
					if (fDebugEn) {debug("  after id-read: " + peek());}
				}
			} else if (fLexer.peekOperator("{")) {
				ret = concatenation_or_repetition();
			} else if (peekKeyword("this")) {
				fLexer.eatToken();
				ret = new SVDBIdentifierExpr("this");
			} else if (peekKeyword("super")) {
				fLexer.eatToken();
				ret = new SVDBIdentifierExpr("super");
			} else if (peekKeyword("void")) {
				fLexer.eatToken();
				ret = new SVDBIdentifierExpr("void");
			} else if (fEventExpr.peek() && fLexer.peekOperator("@")) {
				ret = clocking_event();
			} else if (fEventExpr.peek() && fLexer.peekOperator("##")) {
				ret = cycle_delay();
			} else {
				error("Unexpected token in primary: \"" + fLexer.getImage() + "\"");
			}
		}
		if (fDebugEn) {debug("<-- primary() ");}
		return ret;
	}
	private SVDBExpr concatenation_or_repetition() throws SVParseException {
		SVDBExpr expr = null;
		if (fDebugEn) {debug("--> concatenation_or_repetition()");}
		readOperator("{");
		if (peekOperator("}")) {
			fLexer.eatToken();
			expr = new SVDBConcatenationExpr();
		} else if (peekOperator("<<", ">>")) {
			if (fDebugEn) {debug("streaming operator");}
			fLexer.eatToken();
			if (fLexer.peekKeyword(SVKeywords.fBuiltinTypes)) {
				expr = new SVDBTypeExpr(fParsers.dataTypeParser().data_type(0));
			} else if (!fLexer.peekOperator("{")) {
				expr = new SVDBLiteralExpr(fLexer.eatToken());
			}
			if (fDebugEn) {debug("post-datatype: " + fLexer.peek());}
			fLexer.readOperator("{");
			while (fLexer.peek() != null) {
				expression();
				if (fDebugEn) {debug("pre-with: " + fLexer.peek());}
				if (fLexer.peekKeyword("with")) {
					fLexer.eatToken();
					fLexer.readOperator("[");
					expression();
					if (fLexer.peekOperator(":", "+:", "-:")) {
						fLexer.eatToken();
						expression();
					}
					fLexer.readOperator("]");
				}
				if (fLexer.peekOperator(",")) {
					fLexer.eatToken();
				} else {
					break;
				}
			}
			fLexer.readOperator("}");
			fLexer.readOperator("}");
			expr = new SVDBConcatenationExpr();
		} else {
			try {
				SVDBExpr expr0 = expression();
				if (fLexer.peekOperator("{")) {
					if (fDebugEn) {debug("repetition");}
					fLexer.eatToken();
					SVDBAssignmentPatternRepeatExpr ret = new SVDBAssignmentPatternRepeatExpr(expr);
					ret.setRepeatExpr(expr0);
					while (fLexer.peek() != null) {
						ret.getPatternList().add(expression());
						if (fLexer.peekOperator(",")) {
							fLexer.eatToken();
						} else {
							break;
						}
					}
					fLexer.readOperator("}"); 
					fLexer.readOperator("}");
					expr = ret;
				} else {
					if (fDebugEn) {debug("concatenation");}
					SVDBConcatenationExpr ret = new SVDBConcatenationExpr();
					ret.getElements().add(expr0);
					while (fLexer.peekOperator(",")) {
						fLexer.eatToken();
						ret.getElements().add(expression());
					}
					fLexer.readOperator("}");
					expr = ret;
				}
			} finally {
			}
		}
		if (fDebugEn) {debug("<-- concatenation_or_repetition()");}
		return expr;
	}
	public List<SVDBExpr> arguments() throws SVParseException {
		if (fDebugEn) {debug("--> arguments()");}
		readOperator("(");
		if (peekOperator(")")) {
			fLexer.eatToken();
			return new ArrayList<SVDBExpr>();
		}
		List<SVDBExpr> arguments = argumentList();
		readOperator(")");
		if (fDebugEn) {debug("<-- arguments()");}
		return arguments;
	}
	private List<SVDBExpr>  argumentList() throws SVParseException {
		List<SVDBExpr> arguments = new ArrayList<SVDBExpr>();
		if (fDebugEn) {debug("--> argumentList()");}
		for (;;) {
			if (peekOperator(".")) {
				fLexer.eatToken();
				SVDBNamedArgExpr arg_expr = new SVDBNamedArgExpr();
				String name = readIdentifier();
				arg_expr.setArgName(name);
				readOperator("(");
				if (fLexer.peekOperator(")")) {
					arg_expr.setExpr(new SVDBLiteralExpr(""));
				} else {
					arg_expr.setExpr(expression());
				}
				readOperator(")");
				arguments.add(arg_expr);
			} else if (peekOperator(",", ")")) {
				arguments.add(new SVDBLiteralExpr(""));
			} else {
				arguments.add(expression());
			}
			if (peekOperator(",")) {
				fLexer.eatToken();
			} else {
				break;
			}
		}
		if (fDebugEn) {debug("<-- argumentList()");}
		return arguments;
	}
	public SVDBExpr selector(SVDBExpr expr) throws SVParseException {
		if (fDebugEn) {debug("--> selector()");}
		if (peekOperator(".", "::")) {
			String q = fLexer.eatToken();
			fLexer.peek();
			if (fLexer.isIdentifier() || peekKeyword("new", "super", "this")) {
				String id = fLexer.eatToken();
				if (fLexer.peekOperator("(*")) {
					fParsers.attrParser().parse(null);
				}
				if (fLexer.peekOperator("(") || fLexer.peekKeyword("with")) {
					if (id.equals("randomize")) {
						return randomize_call(expr);
					} else if (fLexer.peekOperator("(")){
						return tf_args_call(expr, id);
					} else {
						return tf_noargs_with_call(expr, id);
					}
				}
				if (fDebugEn) {debug("<-- selector()");}
				return new SVDBFieldAccessExpr(expr, (q.equals("::")), 
						new SVDBIdentifierExpr(id));
			}
		}
		if (peekOperator("[")) {
			if (fDebugEn) {debug("primary() -- operator " + fLexer.peek());}
			fLexer.eatToken();
			SVDBExpr low = expression();
			SVDBExpr high = null;
			if (peekOperator(":", "+:", "-:")) {
				fLexer.eatToken();
				high = expression();
			}
			readOperator("]");
			if (expr == null) {
				error("array expr == null");
			}
			if (fDebugEn) {debug("<-- selector()");}
			return new SVDBArrayAccessExpr(expr, low, high);
		}
		error("Unexpected token \"" + fLexer.getImage() + "\"");
		return null; 
	}
	private SVDBRandomizeCallExpr randomize_call(SVDBExpr target) throws SVParseException {
		List<SVDBExpr> arguments = null;
		SVDBRandomizeCallExpr rand_call = null;
		fAssertionExpr.push(false);
		fEventExpr.push(false);
		try {
			if (fLexer.peekOperator("(")) {
				arguments = arguments();
			}
			rand_call = new SVDBRandomizeCallExpr(target, "randomize", arguments);
			if (fLexer.peekKeyword("with")) {
				fLexer.eatToken();
				rand_call.setWithBlock(fParsers.constraintParser().constraint_set(true));
			}
		} finally {
			fAssertionExpr.pop();
			fEventExpr.pop();
		}
		return rand_call;
	}
	private SVDBTFCallExpr tf_args_call(SVDBExpr target, String id) throws SVParseException {
		SVDBTFCallExpr tf = new SVDBTFCallExpr(target, id, arguments());
		if (fLexer.peekKeyword("with")) {
			fLexer.eatToken();
			fLexer.readOperator("(");
			tf.setWithExpr(expression());
			fLexer.readOperator(")");
		}
		return tf;
	}
	private SVDBTFCallExpr tf_noargs_with_call(SVDBExpr target, String id) throws SVParseException {
		SVDBTFCallExpr tf = new SVDBTFCallExpr(target, id, null);
		if (fLexer.peekKeyword("with")) {
			fLexer.eatToken();
			if (fLexer.peekOperator("[")) {
				fLexer.readOperator("[");
				tf.setWithExpr(expression());
				if (fLexer.peekOperator(":", "+:","-:")) {
					fLexer.eatToken();
					expression();
				}
				fLexer.readOperator("]");
			} else {
				fLexer.readOperator("(");
				tf.setWithExpr(expression());
				fLexer.readOperator(")");
			}
		}
		return tf; 
	}
	private SVDBCtorExpr ctor_call() throws SVParseException {
		if (fDebugEn) {
			debug("--> ctor_call()");
		}
		SVDBCtorExpr ctor = new SVDBCtorExpr();
		if (fLexer.peekOperator("[")) {
			fLexer.readOperator("[");
			ctor.setCtorType(CtorType.CtorType_Dim);
			ctor.setArg(expression());
			fLexer.readOperator("]");
		}
		if (fLexer.peekOperator("(")) {
			ctor.setCtorType(CtorType.CtorType_Args);
			ctor.setArgs(arguments());
		} else if (fLexer.peekKeyword() || fLexer.peekId()) {
			ctor.setCtorType(CtorType.CtorType_Expr);
			ctor.setArg(expression());
		}
		if (fDebugEn) {
			debug("--> ctor_call()");
		}
		return ctor;
	}
	private String peek() throws SVParseException {
		return fLexer.peek();
	}
	private boolean peekOperator(String ... ops) throws SVParseException {
		return fLexer.peekOperator(ops);
	}
	private String readOperator(String ... ops) throws SVParseException {
		return fLexer.readOperator(ops);
	}
	private boolean peekKeyword(String ... kw) throws SVParseException {
		return fLexer.peekKeyword(kw);
	}
	private String readKeyword(String ... kw) throws SVParseException {
		return fLexer.readKeyword(kw);
	}
	private String readIdentifier() throws SVParseException {
		return fLexer.readId();
	}
	public SVDBIdentifierExpr idExpr() throws SVParseException {
		SVDBLocation start = fLexer.getStartLocation();
		SVDBIdentifierExpr ret = new SVDBIdentifierExpr(fLexer.readId());
		ret.setLocation(start);
		return ret;
	}
	public SVDBLiteralExpr literalExpr() throws SVParseException {
		SVDBLocation start = fLexer.getStartLocation();
		SVDBLiteralExpr ret = new SVDBLiteralExpr(fLexer.readNumber());
		ret.setLocation(start);
		return ret;
	}
}

	private SVDBExpr assignment_pattern_expr() throws SVParseException {
		SVDBExpr ret_top;
		fLexer.readOperator("'");
		fLexer.readOperator("{");
		if (fDebugEn) {debug("    assignmentPattern");}
		if (fLexer.peekOperator("}")) {
			fLexer.eatToken();
			ret_top = new SVDBConcatenationExpr();
		} else {
			try {
				fEnableNameMappedPrimary = true;
				SVDBExpr expr1 = expression();
				if (fLexer.peekOperator("{")) {
					SVDBAssignmentPatternRepeatExpr ret = new SVDBAssignmentPatternRepeatExpr(expr1);
					fLexer.eatToken(); 
					while (true) {
						SVDBExpr expr = expression();
						ret.getPatternList().add(expr);
						if (fLexer.peekOperator(",")) {
							fLexer.eatToken();
						} else {
							break;
						}
					}
					fLexer.readOperator("}");
					ret_top = ret;
				} else  {
					SVDBAssignmentPatternExpr ret = new SVDBAssignmentPatternExpr();
					ret.getPatternList().add(expr1);
					while (fLexer.peekOperator(",")) {
						fLexer.eatToken();
						SVDBExpr expr = expression();
						ret.getPatternList().add(expr);
					}
					ret_top = ret;
				}
				fLexer.readOperator("}");
			} finally {
				fEnableNameMappedPrimary = false;
			}
		}
		return ret_top;
	}
	public SVDBExpr primary() throws SVParseException {
		if (fDebugEn) {debug("--> primary() - " + fLexer.peek());}
		SVDBExpr ret = null;
		if (peekOperator("(")) {
			if (fDebugEn) {debug("  Found paren in primary");}
			fLexer.eatToken();
			SVDBExpr a = expression();
			if (fLexer.peekOperator(":")) {
				fLexer.eatToken();
				SVDBExpr expr = fParsers.exprParser().expression();
				if (fLexer.peekOperator(":")) {
					fLexer.eatToken();
					expr = fParsers.exprParser().expression();
				}
			}
			readOperator(")");
			peek();
			if (fLexer.isNumber() || fLexer.isIdentifier() ||
					peekOperator("(", "~", "!") ||
					peekKeyword("this", "super", "new")) {
				ret = new SVDBCastExpr(a, unaryExpression());
			} else {
				ret = new SVDBParenExpr(a);
			}
		} else {
			fLexer.peek();
			if (fLexer.isNumber()) {
				if (fDebugEn) {debug("-- primary is a number");}
				SVToken tmp = fLexer.consumeToken();
				if (fEnableNameMappedPrimary && fLexer.peekOperator(":")) {
					fLexer.eatToken();
					ret = new SVDBNameMappedExpr(tmp.getImage(), expression());
				} else {
					ret = new SVDBLiteralExpr(tmp.getImage());
				}
			} else if (fLexer.peekOperator("$")) {
				fLexer.eatToken();
				ret = new SVDBRangeDollarBoundExpr();
			} else if (fLexer.peekString()) {
				if (fDebugEn) {debug("-- primary is a string");}
				SVToken tmp = fLexer.consumeToken();
				if (fEnableNameMappedPrimary && fLexer.peekOperator(":")) {
					fLexer.eatToken();
					ret = new SVDBNameMappedExpr(tmp.getImage(), expression());
				} else {
					ret = new SVDBStringExpr(tmp.getImage());
				}
			} else if (fLexer.peekKeyword("null")) {
				if (fDebugEn) {debug("-- primary is 'null'");}
				fLexer.eatToken();
				ret = new SVDBNullExpr();
			} else if (fLexer.isIdentifier() || 
					SVKeywords.isBuiltInType(fLexer.peek()) ||
					fLexer.peekKeyword("new","default","local")) {
				if (fDebugEn) {
					debug("  primary \"" + fLexer.getImage() + "\" is identifier or built-in type");
				}
				String id = fLexer.eatToken();
				if (fLexer.peekOperator("(*")) {
					fParsers.attrParser().parse(null);
				}
				if (peekOperator("#")) {
					if (fDebugEn) {
						debug("Parameterized identifier");
					}
					ret = new SVDBParamIdExpr(id);
					fLexer.eatToken(); 
					fLexer.readOperator("(");
					while (fLexer.peek() != null && !fLexer.peekOperator(")")) {
						((SVDBParamIdExpr)ret).addParamExpr(datatype_or_expression());
						if (fLexer.peekOperator(",")) {
							fLexer.eatToken();
						} else {
							break;
						}
					}
					fLexer.readOperator(")");
				} else if (fLexer.peekOperator("(") || fLexer.peekKeyword("with")) {
					if (id.equals("randomize")) {
						ret = randomize_call(null);
					} else if (fLexer.peekOperator("(")) {
						ret = tf_args_call(null, id);
					} else {
						ret = tf_noargs_with_call(null, id);
					}
				} else if (id.equals("new")) {
					ret = ctor_call();
				} else if (fLexer.peekKeyword(SVKeywords.fBuiltinDeclTypes)) {
					fLexer.startCapture();
					fLexer.eatToken();
					if (fLexer.peekKeyword("signed","unsigned")) {
						fLexer.eatToken();
					}
					ret = new SVDBIdentifierExpr(fLexer.endCapture());
				} else {
					if (fEnableNameMappedPrimary && fLexer.peekOperator(":")) {
						fLexer.eatToken();
						if (fDebugEn) {debug("    nameMappedExpr");}
						ret = new SVDBNameMappedExpr(id, expression());
					} else {
						ret = new SVDBIdentifierExpr(id);
					}
					if (fDebugEn) {debug("  after id-read: " + peek());}
				}
			} else if (fLexer.peekOperator("{")) {
				ret = concatenation_or_repetition();
			} else if (peekKeyword("this")) {
				fLexer.eatToken();
				ret = new SVDBIdentifierExpr("this");
			} else if (peekKeyword("super")) {
				fLexer.eatToken();
				ret = new SVDBIdentifierExpr("super");
			} else if (peekKeyword("void")) {
				fLexer.eatToken();
				ret = new SVDBIdentifierExpr("void");
			} else if (fEventExpr.peek() && fLexer.peekOperator("@")) {
				ret = clocking_event();
			} else if (fEventExpr.peek() && fLexer.peekOperator("##")) {
				ret = cycle_delay();
			} else {
				error("Unexpected token in primary: \"" + fLexer.getImage() + "\"");
			}
		}
		if (fDebugEn) {debug("<-- primary() ");}
		return ret;
	}
	private SVDBExpr concatenation_or_repetition() throws SVParseException {
		SVDBExpr expr = null;
		if (fDebugEn) {debug("--> concatenation_or_repetition()");}
		readOperator("{");
		if (peekOperator("}")) {
			fLexer.eatToken();
			expr = new SVDBConcatenationExpr();
		} else if (peekOperator("<<", ">>")) {
			if (fDebugEn) {debug("streaming operator");}
			fLexer.eatToken();
			if (fLexer.peekKeyword(SVKeywords.fBuiltinTypes)) {
				expr = new SVDBTypeExpr(fParsers.dataTypeParser().data_type(0));
			} else if (!fLexer.peekOperator("{")) {
				expr = new SVDBLiteralExpr(fLexer.eatToken());
			}
			if (fDebugEn) {debug("post-datatype: " + fLexer.peek());}
			fLexer.readOperator("{");
			while (fLexer.peek() != null) {
				expression();
				if (fDebugEn) {debug("pre-with: " + fLexer.peek());}
				if (fLexer.peekKeyword("with")) {
					fLexer.eatToken();
					fLexer.readOperator("[");
					expression();
					if (fLexer.peekOperator(":", "+:", "-:")) {
						fLexer.eatToken();
						expression();
					}
					fLexer.readOperator("]");
				}
				if (fLexer.peekOperator(",")) {
					fLexer.eatToken();
				} else {
					break;
				}
			}
			fLexer.readOperator("}");
			fLexer.readOperator("}");
			expr = new SVDBConcatenationExpr();
		} else {
			try {
				SVDBExpr expr0 = expression();
				if (fLexer.peekOperator("{")) {
					if (fDebugEn) {debug("repetition");}
					fLexer.eatToken();
					SVDBAssignmentPatternRepeatExpr ret = new SVDBAssignmentPatternRepeatExpr(expr);
					ret.setRepeatExpr(expr0);
					while (fLexer.peek() != null) {
						ret.getPatternList().add(expression());
						if (fLexer.peekOperator(",")) {
							fLexer.eatToken();
						} else {
							break;
						}
					}
					fLexer.readOperator("}"); 
					fLexer.readOperator("}");
					expr = ret;
				} else {
					if (fDebugEn) {debug("concatenation");}
					SVDBConcatenationExpr ret = new SVDBConcatenationExpr();
					ret.getElements().add(expr0);
					while (fLexer.peekOperator(",")) {
						fLexer.eatToken();
						ret.getElements().add(expression());
					}
					fLexer.readOperator("}");
					expr = ret;
				}
			} finally {
			}
		}
		if (fDebugEn) {debug("<-- concatenation_or_repetition()");}
		return expr;
	}
	public List<SVDBExpr> arguments() throws SVParseException {
		if (fDebugEn) {debug("--> arguments()");}
		readOperator("(");
		if (peekOperator(")")) {
			fLexer.eatToken();
			return new ArrayList<SVDBExpr>();
		}
		List<SVDBExpr> arguments = argumentList();
		readOperator(")");
		if (fDebugEn) {debug("<-- arguments()");}
		return arguments;
	}
	private List<SVDBExpr>  argumentList() throws SVParseException {
		List<SVDBExpr> arguments = new ArrayList<SVDBExpr>();
		if (fDebugEn) {debug("--> argumentList()");}
		for (;;) {
			if (peekOperator(".")) {
				fLexer.eatToken();
				SVDBNamedArgExpr arg_expr = new SVDBNamedArgExpr();
				String name = readIdentifier();
				arg_expr.setArgName(name);
				readOperator("(");
				if (fLexer.peekOperator(")")) {
					arg_expr.setExpr(new SVDBLiteralExpr(""));
				} else {
					arg_expr.setExpr(expression());
				}
				readOperator(")");
				arguments.add(arg_expr);
			} else if (peekOperator(",", ")")) {
				arguments.add(new SVDBLiteralExpr(""));
			} else {
				arguments.add(expression());
			}
			if (peekOperator(",")) {
				fLexer.eatToken();
			} else {
				break;
			}
		}
		if (fDebugEn) {debug("<-- argumentList()");}
		return arguments;
	}
	public SVDBExpr selector(SVDBExpr expr) throws SVParseException {
		if (fDebugEn) {debug("--> selector()");}
		if (peekOperator(".", "::")) {
			String q = fLexer.eatToken();
			fLexer.peek();
			if (fLexer.isIdentifier() || peekKeyword("new", "super", "this")) {
				String id = fLexer.eatToken();
				if (fLexer.peekOperator("(*")) {
					fParsers.attrParser().parse(null);
				}
				if (fLexer.peekOperator("(") || fLexer.peekKeyword("with")) {
					if (id.equals("randomize")) {
						return randomize_call(expr);
					} else if (fLexer.peekOperator("(")){
						return tf_args_call(expr, id);
					} else {
						return tf_noargs_with_call(expr, id);
					}
				}
				if (fDebugEn) {debug("<-- selector()");}
				return new SVDBFieldAccessExpr(expr, (q.equals("::")), 
						new SVDBIdentifierExpr(id));
			}
		}
		if (peekOperator("[")) {
			if (fDebugEn) {debug("primary() -- operator " + fLexer.peek());}
			fLexer.eatToken();
			SVDBExpr low = expression();
			SVDBExpr high = null;
			if (peekOperator(":", "+:", "-:")) {
				fLexer.eatToken();
				high = expression();
			}
			readOperator("]");
			if (expr == null) {
				error("array expr == null");
			}
			if (fDebugEn) {debug("<-- selector()");}
			return new SVDBArrayAccessExpr(expr, low, high);
		}
		error("Unexpected token \"" + fLexer.getImage() + "\"");
		return null; 
	}
	private SVDBRandomizeCallExpr randomize_call(SVDBExpr target) throws SVParseException {
		List<SVDBExpr> arguments = null;
		SVDBRandomizeCallExpr rand_call = null;
		fAssertionExpr.push(false);
		fEventExpr.push(false);
		try {
			if (fLexer.peekOperator("(")) {
				arguments = arguments();
			}
			rand_call = new SVDBRandomizeCallExpr(target, "randomize", arguments);
			if (fLexer.peekKeyword("with")) {
				fLexer.eatToken();
				rand_call.setWithBlock(fParsers.constraintParser().constraint_set(true));
			}
		} finally {
			fAssertionExpr.pop();
			fEventExpr.pop();
		}
		return rand_call;
	}
	private SVDBTFCallExpr tf_args_call(SVDBExpr target, String id) throws SVParseException {
		SVDBTFCallExpr tf = new SVDBTFCallExpr(target, id, arguments());
		if (fLexer.peekKeyword("with")) {
			fLexer.eatToken();
			fLexer.readOperator("(");
			tf.setWithExpr(expression());
			fLexer.readOperator(")");
		}
		return tf;
	}
	private SVDBTFCallExpr tf_noargs_with_call(SVDBExpr target, String id) throws SVParseException {
		SVDBTFCallExpr tf = new SVDBTFCallExpr(target, id, null);
		if (fLexer.peekKeyword("with")) {
			fLexer.eatToken();
			if (fLexer.peekOperator("[")) {
				fLexer.readOperator("[");
				tf.setWithExpr(expression());
				if (fLexer.peekOperator(":", "+:","-:")) {
					fLexer.eatToken();
					expression();
				}
				fLexer.readOperator("]");
			} else {
				fLexer.readOperator("(");
				tf.setWithExpr(expression());
				fLexer.readOperator(")");
			}
		}
		return tf; 
	}
	private SVDBCtorExpr ctor_call() throws SVParseException {
		if (fDebugEn) {
			debug("--> ctor_call()");
		}
		SVDBCtorExpr ctor = new SVDBCtorExpr();
		if (fLexer.peekOperator("[")) {
			fLexer.readOperator("[");
			ctor.setCtorType(CtorType.CtorType_Dim);
			ctor.setArg(expression());
			fLexer.readOperator("]");
		}
		if (fLexer.peekOperator("(")) {
			ctor.setCtorType(CtorType.CtorType_Args);
			ctor.setArgs(arguments());
		} else if (fLexer.peekKeyword() || fLexer.peekId()) {
			ctor.setCtorType(CtorType.CtorType_Expr);
			ctor.setArg(expression());
		}
		if (fDebugEn) {
			debug("--> ctor_call()");
		}
		return ctor;
	}
	private String peek() throws SVParseException {
		return fLexer.peek();
	}
	private boolean peekOperator(String ... ops) throws SVParseException {
		return fLexer.peekOperator(ops);
	}
	private String readOperator(String ... ops) throws SVParseException {
		return fLexer.readOperator(ops);
	}
	private boolean peekKeyword(String ... kw) throws SVParseException {
		return fLexer.peekKeyword(kw);
	}
	private String readKeyword(String ... kw) throws SVParseException {
		return fLexer.readKeyword(kw);
	}
	private String readIdentifier() throws SVParseException {
		return fLexer.readId();
	}
	public SVDBIdentifierExpr idExpr() throws SVParseException {
		SVDBLocation start = fLexer.getStartLocation();
		SVDBIdentifierExpr ret = new SVDBIdentifierExpr(fLexer.readId());
		ret.setLocation(start);
		return ret;
	}
	public SVDBLiteralExpr literalExpr() throws SVParseException {
		SVDBLocation start = fLexer.getStartLocation();
		SVDBLiteralExpr ret = new SVDBLiteralExpr(fLexer.readNumber());
		ret.setLocation(start);
		return ret;
	}
}
